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:
curo1305
2026-06-15 20:10:00 +02:00
parent 4a45dd4801
commit b12137c4ce
2 changed files with 121 additions and 0 deletions
@@ -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)
})
})