Appearance
classNames 工具函数常用于合并和控制样式名
测试用例如下
import { test, expect, describe } from 'vitest'
import { cn } from '@slsanyi/utils'
test('(compat) keeps object keys with truthy values', () => {
const out = cn({ a: true, b: false, c: 0, d: null, e: undefined, f: 1 })
expect(out).toBe('a f')
})
test('(compat) joins arrays of class names and ignore falsy values', () => {
const out = cn('a', 0, null, undefined, true, 1, 'b')
expect(out).toBe('a 1 b')
})
test('(compat) supports heterogenous arguments', () => {
expect(cn({ a: true }, 'b', 0)).toBe('a b')
})
test('(compat) should be trimmed', () => {
expect(cn('', 'b', {}, '')).toBe('b')
})
test('(compat) returns an empty string for an empty configuration', () => {
expect(cn({})).toBe('')
})
test('(compat) supports an array of class names', () => {
expect(cn(['a', 'b'])).toBe('a b')
})
test('(compat) joins array arguments with string arguments', () => {
expect(cn(['a', 'b'], 'c')).toBe('a b c')
expect(cn('c', ['a', 'b'])).toBe('c a b')
})
test('(compat) handles multiple array arguments', () => {
expect(cn(['a', 'b'], ['c', 'd'])).toBe('a b c d')
})
test('(compat) handles arrays that include falsy and true values', () => {
expect(cn(['a', 0, null, undefined, false, true, 'b'])).toBe('a b')
})
test('(compat) handles arrays that include arrays', () => {
expect(cn(['a', ['b', 'c']])).toBe('a b c')
})
test('(compat) handles arrays that include objects', () => {
expect(cn(['a', { b: true, c: false }])).toBe('a b')
})
test('(compat) handles deep array recursion', () => {
expect(cn(['a', ['b', ['c', { d: true }]]])).toBe('a b c d')
})
test('(compat) handles arrays that are empty', () => {
expect(cn('a', [])).toBe('a')
})
test('(compat) handles nested arrays that have empty nested arrays', () => {
expect(cn('a', [[]])).toBe('a')
})
test('(compat) handles all types of truthy and falsy property values as expected', () => {
const out = cn({
// falsy:
null: null,
emptyString: '',
noNumber: NaN,
zero: 0,
negativeZero: -0,
false: false,
undefined: undefined,
// truthy (literally anything else):
nonEmptyString: 'foobar',
whitespace: ' ',
function: Object.prototype.toString,
emptyObject: {},
nonEmptyObject: { a: 1, b: 2 },
emptyList: [],
nonEmptyList: [1, 2, 3],
greaterZero: 1
})
expect(out).toBe(
'nonEmptyString whitespace function emptyObject nonEmptyObject emptyList nonEmptyList greaterZero'
)
})
describe('cx', () => {
describe.each([
[null, ''],
[undefined, ''],
[false && 'foo', ''],
[true && 'foo', 'foo'],
[['foo', null, 'bar', undefined, 'baz'], 'foo bar baz'],
[
[
'foo',
[
null,
['bar'],
[
undefined,
[
'baz',
'qux',
'quux',
'quuz',
[[[[[[[[['corge', 'grault']]]]], 'garply']]]]
]
]
]
],
'foo bar baz qux quux quuz corge grault garply'
],
[
[
'foo',
[1 && 'bar', { baz: false, bat: null }, ['hello', ['world']]],
'cya'
],
'foo bar hello world cya'
]
])('cx(%o)', (options, expected) => {
test(`returns ${expected}`, () => {
expect(cn(options)).toBe(expected)
})
})