@datametria/vue-components
Version:
DATAMETRIA Vue.js 3 Component Library with Multi-Brand Theming - 51 components + 10 composables with theming support, WCAG 2.2 AA, dark mode, responsive system
147 lines (127 loc) • 3.76 kB
text/typescript
/**
* useTheme Composable Tests
* @author Vander Loto - CTO DATAMETRIA
* @date 13/11/2025
*/
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import { h } from 'vue'
import ThemeProvider from '../ThemeProvider.vue'
import { useTheme } from '../useTheme'
import { defaultTokens } from '../tokens'
import type { Theme } from '../types'
const testTheme: Theme = {
name: 'Test Theme',
tokens: defaultTokens
}
describe('useTheme', () => {
it('should throw error when used outside ThemeProvider', () => {
// Suprimir warnings do Vue durante este teste
const originalWarn = console.warn
console.warn = () => {}
expect(() => {
const TestComponent = {
setup() {
useTheme()
return () => h('div', 'Test')
}
}
mount(TestComponent)
}).toThrow('useTheme must be used within a ThemeProvider')
// Restaurar console.warn
console.warn = originalWarn
})
it('should return theme when used inside ThemeProvider', () => {
const TestComponent = {
setup() {
const theme = useTheme()
expect(theme).toBeDefined()
expect(theme.value.name).toBe('Test Theme')
return () => h('div', theme.value.name)
}
}
const wrapper = mount(ThemeProvider, {
props: { theme: testTheme },
slots: {
default: h(TestComponent)
}
})
expect(wrapper.text()).toContain('Test Theme')
})
it('should return theme tokens', () => {
const TestComponent = {
setup() {
const theme = useTheme()
expect(theme.value.tokens).toBeDefined()
expect(theme.value.tokens.colors.primary).toBe('#0072CE')
return () => h('div', 'Test')
}
}
mount(ThemeProvider, {
props: { theme: testTheme },
slots: {
default: h(TestComponent)
}
})
})
it('should access all token categories', () => {
const TestComponent = {
setup() {
const theme = useTheme()
expect(theme.value.tokens.colors).toBeDefined()
expect(theme.value.tokens.typography).toBeDefined()
expect(theme.value.tokens.spacing).toBeDefined()
expect(theme.value.tokens.radius).toBeDefined()
expect(theme.value.tokens.shadows).toBeDefined()
expect(theme.value.tokens.transitions).toBeDefined()
return () => h('div', 'Test')
}
}
mount(ThemeProvider, {
props: { theme: testTheme },
slots: {
default: h(TestComponent)
}
})
})
it('should work in nested components', () => {
const GrandchildComponent = {
setup() {
const theme = useTheme()
return () => h('div', { class: 'grandchild' }, theme.value.name)
}
}
const ChildComponent = {
setup() {
return () => h('div', { class: 'child' }, h(GrandchildComponent))
}
}
const wrapper = mount(ThemeProvider, {
props: { theme: testTheme },
slots: {
default: h(ChildComponent)
}
})
expect(wrapper.find('.grandchild').text()).toContain('Test Theme')
})
it('should provide helpful error message', () => {
// Suprimir warnings do Vue durante este teste
const originalWarn = console.warn
console.warn = () => {}
try {
const TestComponent = {
setup() {
useTheme()
return () => h('div', 'Test')
}
}
mount(TestComponent)
} catch (error) {
expect(error).toBeInstanceOf(Error)
expect((error as Error).message).toContain('ThemeProvider')
expect((error as Error).message).toContain('Wrap your component tree')
}
// Restaurar console.warn
console.warn = originalWarn
})
})