test(10-04): add failing tests for toast store and ToastContainer
- 6 toast store tests: show/dismiss/auto-dismiss/duration=0/stacking - 4 ToastContainer tests: empty/render count/click dismiss/accent class - uses vi.useFakeTimers() for timer-based assertions - Teleport and AppIcon stubbed for DOM-safe mounting
This commit is contained in:
@@ -0,0 +1,57 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest'
|
||||||
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
|
import { useToastStore } from '../../../stores/toast.js'
|
||||||
|
import ToastContainer from '../ToastContainer.vue'
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia())
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('ToastContainer', () => {
|
||||||
|
it('renders nothing when store.toasts is empty', () => {
|
||||||
|
const wrapper = mount(ToastContainer, {
|
||||||
|
global: {
|
||||||
|
stubs: { AppIcon: true, Teleport: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(wrapper.find('[data-test="toast"]').exists()).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('renders one element per toast', () => {
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('First', 'success', 0)
|
||||||
|
store.show('Second', 'error', 0)
|
||||||
|
const wrapper = mount(ToastContainer, {
|
||||||
|
global: {
|
||||||
|
stubs: { AppIcon: true, Teleport: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(wrapper.findAll('[data-test="toast"]').length).toBe(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('clicking a toast calls dismiss(id)', async () => {
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('Click me', 'info', 0)
|
||||||
|
const wrapper = mount(ToastContainer, {
|
||||||
|
global: {
|
||||||
|
stubs: { AppIcon: true, Teleport: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await wrapper.find('[data-test="toast"]').trigger('click')
|
||||||
|
expect(store.toasts.length).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('accent class matches type (success -> bg-green-500)', () => {
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('Success toast', 'success', 0)
|
||||||
|
const wrapper = mount(ToastContainer, {
|
||||||
|
global: {
|
||||||
|
stubs: { AppIcon: true, Teleport: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const toast = wrapper.find('[data-test="toast"]')
|
||||||
|
const accentBar = toast.find('.bg-green-500')
|
||||||
|
expect(accentBar.exists()).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
||||||
|
import { setActivePinia, createPinia } from 'pinia'
|
||||||
|
import { useToastStore } from '../toast.js'
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
setActivePinia(createPinia())
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.useRealTimers()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('useToastStore', () => {
|
||||||
|
it('show(msg, type, duration) appends a toast with the given fields', () => {
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('Hi', 'success', 4000)
|
||||||
|
expect(store.toasts.length).toBe(1)
|
||||||
|
expect(store.toasts[0].message).toBe('Hi')
|
||||||
|
expect(store.toasts[0].type).toBe('success')
|
||||||
|
expect(store.toasts[0].duration).toBe(4000)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('show defaults type to success and duration to 4000', () => {
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('Hi')
|
||||||
|
expect(store.toasts[0].type).toBe('success')
|
||||||
|
expect(store.toasts[0].duration).toBe(4000)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('auto-dismisses after duration using fake timers', () => {
|
||||||
|
vi.useFakeTimers()
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('Hi', 'success', 4000)
|
||||||
|
expect(store.toasts.length).toBe(1)
|
||||||
|
vi.advanceTimersByTime(4000)
|
||||||
|
expect(store.toasts.length).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('dismiss(id) removes the toast immediately', () => {
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('Hi', 'success', 0)
|
||||||
|
const id = store.toasts[0].id
|
||||||
|
store.dismiss(id)
|
||||||
|
expect(store.toasts.length).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('duration=0 disables auto-dismiss', () => {
|
||||||
|
vi.useFakeTimers()
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('Hi', 'success', 0)
|
||||||
|
vi.advanceTimersByTime(10000)
|
||||||
|
expect(store.toasts.length).toBe(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('multiple toasts stack with unique ids', () => {
|
||||||
|
const store = useToastStore()
|
||||||
|
store.show('A')
|
||||||
|
store.show('B')
|
||||||
|
store.show('C')
|
||||||
|
expect(store.toasts.length).toBe(3)
|
||||||
|
const ids = store.toasts.map(t => t.id)
|
||||||
|
expect(new Set(ids).size).toBe(3)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user