import { describe, expect, it } from 'vitest'; import { cva } from './cva'; const button = cva('base', { variants: { variant: { primary: 'bg-primary', ghost: 'bg-transparent' }, size: { sm: 'h-8', md: 'h-9' }, }, defaultVariants: { variant: 'primary', size: 'md' }, }); describe('cva', () => { it('applies the defaults when nothing is passed', () => { expect(button()).toBe('base bg-primary h-9'); }); it('lets a passed variant win over the default', () => { expect(button({ variant: 'ghost' })).toBe('base bg-transparent h-9'); }); it('falls back to the default for an undefined prop', () => { expect(button({ variant: undefined })).toBe('base bg-primary h-9'); }); it('drops the variant entirely when it is explicitly null', () => { /* `null` is the documented escape hatch for rendering the bare base — the default must not be substituted back in. */ expect(button({ variant: null })).toBe('base h-9'); }); it('appends class and className last, so a caller always overrides', () => { expect(button({ class: 'mt-2' })).toBe('base bg-primary h-9 mt-2'); expect(button({ className: 'mt-2' })).toBe('base bg-primary h-9 mt-2'); }); it('works with no config at all', () => { expect(cva('base')({ className: 'extra' })).toBe('base extra'); }); it('accepts an array base, like a cn() composition', () => { expect(cva(['a', 'b'])()).toBe('a b'); }); describe('boolean and numeric variant keys', () => { const flagged = cva('base', { variants: { loading: { true: 'opacity-50', false: 'opacity-100' }, level: { 0: 'z-0', 1: 'z-10' }, }, defaultVariants: { loading: false }, }); it('indexes a boolean variant by its stringified value', () => { expect(flagged({ loading: true })).toBe('base opacity-50'); expect(flagged({ loading: false })).toBe('base opacity-100'); }); it('applies a false default rather than treating it as absent', () => { expect(flagged()).toBe('base opacity-100'); }); it('indexes 0 as a real key rather than a missing one', () => { expect(flagged({ level: 0 })).toBe('base opacity-100 z-0'); }); }); describe('compound variants', () => { const compound = cva('base', { variants: { variant: { primary: 'bg-primary', ghost: 'bg-transparent' }, size: { sm: 'h-8', lg: 'h-10' }, }, defaultVariants: { variant: 'primary', size: 'sm' }, compoundVariants: [ { variant: 'ghost', size: 'lg', class: 'border-2' }, { variant: ['primary', 'ghost'], size: 'sm', className: 'tracking-tight' }, ], }); it('adds the compound class when every condition matches', () => { expect(compound({ variant: 'ghost', size: 'lg' })).toBe('base bg-transparent h-10 border-2'); }); it('omits it when one condition does not match', () => { expect(compound({ variant: 'primary', size: 'lg' })).toBe('base bg-primary h-10'); }); it('matches an array condition against any of its values', () => { expect(compound({ variant: 'ghost', size: 'sm' })).toBe( 'base bg-transparent h-8 tracking-tight' ); }); it('matches against defaults for variants that were not passed', () => { expect(compound()).toBe('base bg-primary h-8 tracking-tight'); }); }); });