import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { mount } from '@vue/test-utils' import { defineComponent, h, toRef } from 'vue' import { useBackendEvents } from '../backendEvents' const { emitMock } = vi.hoisted(() => ({ emitMock: vi.fn(), })) vi.mock('../eventBus', () => ({ eventBus: { emit: emitMock, }, })) class MockEventSource { static instances: MockEventSource[] = [] public onmessage: ((event: MessageEvent) => void) | null = null public close = vi.fn(() => { this.closed = true }) public closed = false constructor(public url: string) { MockEventSource.instances.push(this) } } const TestHarness = defineComponent({ name: 'BackendEventsHarness', props: { userId: { type: String, required: true, }, }, setup(props) { useBackendEvents(toRef(props, 'userId')) return () => h('div') }, }) describe('useBackendEvents', () => { beforeEach(() => { vi.clearAllMocks() MockEventSource.instances = [] vi.stubGlobal('EventSource', MockEventSource) }) afterEach(() => { vi.unstubAllGlobals() }) it('connects when user id becomes available after mount', async () => { const wrapper = mount(TestHarness, { props: { userId: '' } }) expect(MockEventSource.instances.length).toBe(0) await wrapper.setProps({ userId: 'user-1' }) expect(MockEventSource.instances.length).toBe(1) expect(MockEventSource.instances[0]?.url).toBe('/events?user_id=user-1') }) it('reconnects when user id changes and closes previous connection', async () => { const wrapper = mount(TestHarness, { props: { userId: 'user-1' } }) expect(MockEventSource.instances.length).toBe(1) const firstConnection = MockEventSource.instances[0] await wrapper.setProps({ userId: 'user-2' }) expect(firstConnection?.close).toHaveBeenCalledTimes(1) expect(MockEventSource.instances.length).toBe(2) expect(MockEventSource.instances[1]?.url).toBe('/events?user_id=user-2') }) it('emits parsed backend events on message', async () => { mount(TestHarness, { props: { userId: 'user-1' } }) const connection = MockEventSource.instances[0] expect(connection).toBeDefined() connection?.onmessage?.({ data: JSON.stringify({ type: 'profile_updated', payload: { id: 'user-1' } }), } as MessageEvent) expect(emitMock).toHaveBeenCalledWith('profile_updated', { type: 'profile_updated', payload: { id: 'user-1' }, }) expect(emitMock).toHaveBeenCalledWith('sse', { type: 'profile_updated', payload: { id: 'user-1' }, }) }) it('closes the event source on unmount', () => { const wrapper = mount(TestHarness, { props: { userId: 'user-1' } }) const connection = MockEventSource.instances[0] wrapper.unmount() expect(connection?.close).toHaveBeenCalledTimes(1) }) })