Skip to content

Commit a125a4a

Browse files
authored
test(ui): isolate toast bus state between tests (CoreBunch#92)
1 parent 1a6fbca commit a125a4a

3 files changed

Lines changed: 67 additions & 0 deletions

File tree

src/__tests__/setup.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,10 @@ if (typeof (globalThis as { EventSource?: unknown }).EventSource === 'undefined'
302302
{
303303
const { afterEach } = await import('bun:test')
304304
const { cleanup } = await import('@testing-library/react')
305+
const { __resetToastBusForTests } = await import('@ui/components/Toast/toastBus')
305306
afterEach(() => {
306307
cleanup()
308+
__resetToastBusForTests()
309+
document.getElementById('toast-root')?.remove()
307310
})
308311
}

src/__tests__/ui/toastBus.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { afterEach, describe, expect, it } from 'bun:test'
2+
import {
3+
__resetToastBusForTests,
4+
pushToast,
5+
subscribeToasts,
6+
type Toast,
7+
} from '@ui/components/Toast/toastBus'
8+
9+
afterEach(() => {
10+
__resetToastBusForTests()
11+
})
12+
13+
describe('toastBus', () => {
14+
it('sends the current queue snapshot to new subscribers', () => {
15+
const id = pushToast({
16+
kind: 'success',
17+
title: 'Saved',
18+
durationMs: null,
19+
})
20+
let capturedToasts: ReadonlyArray<Toast> = []
21+
22+
const unsubscribe = subscribeToasts((snapshot) => {
23+
capturedToasts = snapshot
24+
})
25+
26+
expect(capturedToasts.map((toast) => toast.id)).toEqual([id])
27+
unsubscribe()
28+
})
29+
30+
it('resets queued toasts and listeners for test isolation', () => {
31+
pushToast({
32+
kind: 'info',
33+
title: 'Before reset',
34+
durationMs: null,
35+
})
36+
let staleListenerCalls = 0
37+
subscribeToasts(() => {
38+
staleListenerCalls += 1
39+
})
40+
41+
__resetToastBusForTests()
42+
pushToast({
43+
kind: 'info',
44+
title: 'After reset',
45+
durationMs: null,
46+
})
47+
let capturedToasts: ReadonlyArray<Toast> = []
48+
const unsubscribe = subscribeToasts((snapshot) => {
49+
capturedToasts = snapshot
50+
})
51+
52+
expect(staleListenerCalls).toBe(1)
53+
expect(capturedToasts).toHaveLength(1)
54+
expect(capturedToasts[0]?.title).toBe('After reset')
55+
unsubscribe()
56+
})
57+
})

src/ui/components/Toast/toastBus.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,14 @@ export function dismissToast(id: string): void {
103103
*/
104104
export function subscribeToasts(listener: Listener): () => void {
105105
listeners.add(listener)
106+
listener(toasts.slice())
106107
return () => {
107108
listeners.delete(listener)
108109
}
109110
}
111+
112+
export function __resetToastBusForTests(): void {
113+
counter = 0
114+
toasts.splice(0)
115+
listeners.clear()
116+
}

0 commit comments

Comments
 (0)