Some checks failed
Dev CI / Notify Failure (push) Blocked by required conditions
Dev CI / Frontend — Lint & Type-check (push) Failing after 6m16s
Dev CI / Frontend — Unit Tests (push) Has been skipped
Dev CI / Backend — Lint (push) Successful in 10m24s
Dev CI / Backend — Unit Tests (push) Has been cancelled
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
import { cn } from '@/lib/utils';
|
|
|
|
describe('cn — class name merger', () => {
|
|
describe('basic merging', () => {
|
|
it('returns an empty string when called with no arguments', () => {
|
|
expect(cn()).toBe('');
|
|
});
|
|
|
|
it('returns the class when given a single string', () => {
|
|
expect(cn('foo')).toBe('foo');
|
|
});
|
|
|
|
it('joins multiple class strings with a space', () => {
|
|
expect(cn('foo', 'bar', 'baz')).toBe('foo bar baz');
|
|
});
|
|
|
|
it('ignores falsy values', () => {
|
|
expect(cn('foo', undefined, null, false, 'bar')).toBe('foo bar');
|
|
});
|
|
|
|
it('handles an empty string argument', () => {
|
|
expect(cn('', 'foo')).toBe('foo');
|
|
});
|
|
});
|
|
|
|
describe('conditional classes', () => {
|
|
it('includes a class when its condition is true', () => {
|
|
expect(cn('base', true && 'active')).toBe('base active');
|
|
});
|
|
|
|
it('excludes a class when its condition is false', () => {
|
|
expect(cn('base', false && 'active')).toBe('base');
|
|
});
|
|
|
|
it('supports object syntax — includes keys whose value is truthy', () => {
|
|
expect(cn({ foo: true, bar: false, baz: true })).toBe('foo baz');
|
|
});
|
|
|
|
it('supports array syntax', () => {
|
|
expect(cn(['foo', 'bar'])).toBe('foo bar');
|
|
});
|
|
|
|
it('supports mixed input types', () => {
|
|
expect(cn('base', { active: true, disabled: false }, ['extra'])).toBe('base active extra');
|
|
});
|
|
});
|
|
|
|
describe('Tailwind conflict resolution', () => {
|
|
it('resolves padding conflicts — last padding wins', () => {
|
|
expect(cn('p-4', 'p-8')).toBe('p-8');
|
|
});
|
|
|
|
it('resolves text-size conflicts — last size wins', () => {
|
|
expect(cn('text-sm', 'text-lg')).toBe('text-lg');
|
|
});
|
|
|
|
it('resolves background-color conflicts', () => {
|
|
expect(cn('bg-red-500', 'bg-blue-500')).toBe('bg-blue-500');
|
|
});
|
|
|
|
it('keeps non-conflicting utility classes', () => {
|
|
const result = cn('p-4', 'text-sm', 'font-bold');
|
|
expect(result).toContain('p-4');
|
|
expect(result).toContain('text-sm');
|
|
expect(result).toContain('font-bold');
|
|
});
|
|
|
|
it('resolves margin conflicts', () => {
|
|
expect(cn('mt-2', 'mt-4')).toBe('mt-4');
|
|
});
|
|
|
|
it('does not remove classes that do not conflict', () => {
|
|
expect(cn('flex', 'items-center', 'justify-between')).toBe(
|
|
'flex items-center justify-between'
|
|
);
|
|
});
|
|
});
|
|
});
|