157 lines
5.3 KiB
TypeScript
157 lines
5.3 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest'
|
|
import type { App } from 'vue'
|
|
import {
|
|
createNychthemeron,
|
|
Button,
|
|
LoadingIcon,
|
|
InputText,
|
|
Textarea,
|
|
Checkbox,
|
|
RadioButton,
|
|
CheckboxGroup,
|
|
RadioButtonGroup,
|
|
ToggleSwitch,
|
|
Select,
|
|
Card,
|
|
Dialog,
|
|
Message,
|
|
Tag,
|
|
} from '../src/index'
|
|
|
|
//eslint-disable-next-line
|
|
const callSetup = (component: any, props: Record<string, unknown>) => {
|
|
const mergedProps: Record<string, unknown> = {}
|
|
|
|
if (component.props) {
|
|
for (const [key, propDef] of Object.entries(component.props)) {
|
|
if (typeof propDef === 'object' && propDef !== null && 'default' in propDef) {
|
|
mergedProps[key] = (propDef as { default: unknown }).default
|
|
}
|
|
}
|
|
}
|
|
|
|
Object.assign(mergedProps, props)
|
|
|
|
if (component.setup) {
|
|
const result = component.setup(mergedProps, { slots: {}, attrs: {} })
|
|
if (typeof result === 'function') {
|
|
const vnode = result()
|
|
return (vnode?.props as Record<string, unknown>) || {}
|
|
}
|
|
return result
|
|
}
|
|
return mergedProps
|
|
}
|
|
|
|
describe('createNychthemeron', () => {
|
|
it('returns a Vue plugin with install method', () => {
|
|
const plugin = createNychthemeron()
|
|
expect(typeof plugin.install).toBe('function')
|
|
})
|
|
|
|
it('install registers NychButton and NychLoadingIcon globally', () => {
|
|
const plugin = createNychthemeron()
|
|
const mockApp = { component: vi.fn() } as unknown as App
|
|
plugin.install(mockApp)
|
|
expect(mockApp.component).toHaveBeenCalledWith('NychButton', expect.anything())
|
|
expect(mockApp.component).toHaveBeenCalledWith('NychLoadingIcon', expect.anything())
|
|
})
|
|
|
|
it('exposes Button and LoadingIcon components', () => {
|
|
const { Button: btn, LoadingIcon: icon } = createNychthemeron()
|
|
expect(btn).toBeDefined()
|
|
expect(icon).toBeDefined()
|
|
})
|
|
})
|
|
|
|
describe('Button', () => {
|
|
it('is a valid Vue component', () => {
|
|
expect(Button).toBeDefined()
|
|
expect(typeof (Button as Record<string, unknown>).setup).toBe('function')
|
|
})
|
|
|
|
it('auto-disables when loading is true', () => {
|
|
const result = callSetup(Button, { pt: {}, loading: true })
|
|
expect(result.disabled).toBe(true)
|
|
})
|
|
|
|
it('stays enabled when loading is false', () => {
|
|
const result = callSetup(Button, { pt: {}, loading: false })
|
|
expect(result.disabled).toBeFalsy()
|
|
})
|
|
|
|
it('injects severity class into pt.root', () => {
|
|
const result = callSetup(Button, { pt: {}, severity: 'danger' })
|
|
expect(result.pt?.root?.class).toContain('nych-button-danger')
|
|
})
|
|
|
|
it('defaults severity to primary', () => {
|
|
const result = callSetup(Button, { pt: {} })
|
|
expect(result.pt?.root?.class).toContain('nych-button-primary')
|
|
})
|
|
|
|
it('does not leak engine internal props', () => {
|
|
const result = callSetup(Button, { pt: {} })
|
|
expect(result).not.toHaveProperty('injectedClasses')
|
|
expect(result).not.toHaveProperty('injectedStyles')
|
|
expect(result).not.toHaveProperty('stylePlug')
|
|
})
|
|
|
|
it('does not leak severity to inner component', () => {
|
|
const result = callSetup(Button, { pt: {}, severity: 'danger' })
|
|
expect(result).not.toHaveProperty('severity')
|
|
})
|
|
})
|
|
|
|
describe('LoadingIcon', () => {
|
|
it('is a valid Vue component', () => {
|
|
expect(LoadingIcon).toBeDefined()
|
|
})
|
|
})
|
|
|
|
describe('themed pt components', () => {
|
|
const cases = [
|
|
{ name: 'InputText', component: InputText, base: 'nych-input' },
|
|
{ name: 'Textarea', component: Textarea, base: 'nych-textarea' },
|
|
{ name: 'Checkbox', component: Checkbox, base: 'nych-checkbox' },
|
|
{ name: 'CheckboxGroup', component: CheckboxGroup, base: 'nych-checkbox-group' },
|
|
{ name: 'RadioButton', component: RadioButton, base: 'nych-radio' },
|
|
{ name: 'RadioButtonGroup', component: RadioButtonGroup, base: 'nych-radio-group' },
|
|
{ name: 'ToggleSwitch', component: ToggleSwitch, base: 'nych-toggleswitch' },
|
|
{ name: 'Select', component: Select, base: 'nych-select' },
|
|
{ name: 'Card', component: Card, base: 'nych-card' },
|
|
{ name: 'Dialog', component: Dialog, base: 'nych-dialog' },
|
|
{ name: 'Message', component: Message, base: 'nych-message' },
|
|
{ name: 'Tag', component: Tag, base: 'nych-tag' },
|
|
]
|
|
|
|
it.each(cases)('$name is a valid Vue component', ({ component }) => {
|
|
expect(component).toBeDefined()
|
|
expect(typeof (component as Record<string, unknown>).setup).toBe('function')
|
|
})
|
|
|
|
it.each(cases)('$name injects its base class onto pt.root', ({ component, base }) => {
|
|
const result = callSetup(component, { pt: {} })
|
|
expect(result.pt?.root?.class).toContain(base)
|
|
})
|
|
|
|
it.each(cases)('$name does not leak engine internal props', ({ component }) => {
|
|
const result = callSetup(component, { pt: {} })
|
|
expect(result).not.toHaveProperty('injectedClasses')
|
|
expect(result).not.toHaveProperty('injectedStyles')
|
|
expect(result).not.toHaveProperty('stylePlug')
|
|
})
|
|
|
|
it('Checkbox themes its box, input and icon sections', () => {
|
|
const result = callSetup(Checkbox, { pt: {} })
|
|
expect(result.pt?.box?.class).toContain('nych-checkbox-box')
|
|
expect(result.pt?.input?.class).toContain('nych-checkbox-input')
|
|
expect(result.pt?.icon?.class).toContain('nych-checkbox-icon')
|
|
})
|
|
|
|
it('Select themes its overlay and option sections', () => {
|
|
const result = callSetup(Select, { pt: {} })
|
|
expect(result.pt?.overlay?.class).toContain('nych-select-overlay')
|
|
expect(result.pt?.option?.class).toContain('nych-select-option')
|
|
})
|
|
})
|