Skip to content

Commit 403cc47

Browse files
committed
chore: add socket test
1 parent 8e22ce4 commit 403cc47

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2+
import Socket from '../src/modules/socket';
3+
import type { CatcherMessage } from '@hawk.so/types';
4+
5+
const MOCK_WEBSOCKET_URL = 'ws://localhost:1234';
6+
7+
type MockWebSocket = {
8+
url: string;
9+
readyState: number;
10+
send: ReturnType<typeof vi.fn>;
11+
close: ReturnType<typeof vi.fn>;
12+
onopen?: (event: Event) => void;
13+
onclose?: (event: CloseEvent) => void;
14+
onerror?: (event: Event) => void;
15+
onmessage?: (event: MessageEvent) => void;
16+
};
17+
18+
function createMockWebSocket() {
19+
const instances: MockWebSocket[] = [];
20+
21+
const closeSpy = vi.fn(function (this: MockWebSocket) {
22+
this.readyState = WebSocket.CLOSED;
23+
this.onclose?.({ code: 1000 } as CloseEvent);
24+
});
25+
26+
const ctor = vi.fn<(url: string) => MockWebSocket>().mockImplementation(function (
27+
this: MockWebSocket,
28+
url: string
29+
) {
30+
this.url = url;
31+
this.readyState = WebSocket.CONNECTING;
32+
this.send = vi.fn();
33+
this.close = closeSpy;
34+
this.onopen = undefined;
35+
this.onclose = undefined;
36+
this.onerror = undefined;
37+
this.onmessage = undefined;
38+
39+
instances.push(this);
40+
});
41+
42+
return { ctor, closeSpy, instances };
43+
}
44+
45+
describe('Socket', () => {
46+
let ctor: ReturnType<typeof vi.fn>;
47+
let closeSpy: ReturnType<typeof vi.fn>;
48+
let instances: MockWebSocket[];
49+
50+
let addSpy: ReturnType<typeof vi.spyOn>;
51+
let removeSpy: ReturnType<typeof vi.spyOn>;
52+
53+
beforeEach(() => {
54+
({ ctor, closeSpy, instances } = createMockWebSocket());
55+
(globalThis as any).WebSocket = ctor;
56+
57+
addSpy = vi.spyOn(window, 'addEventListener');
58+
removeSpy = vi.spyOn(window, 'removeEventListener');
59+
});
60+
61+
afterEach(() => {
62+
vi.restoreAllMocks();
63+
});
64+
65+
it('should close websocket on pagehide and recreate connection on next send()', async () => {
66+
const socket = new Socket({ collectorEndpoint: MOCK_WEBSOCKET_URL });
67+
68+
const first = instances[0];
69+
first.readyState = WebSocket.OPEN;
70+
first.onopen?.(new Event('open'));
71+
const pagehideHandler = addSpy.mock.calls.find(c => c[0] === 'pagehide')![1] as EventListener;
72+
73+
window.dispatchEvent(new Event('pagehide'));
74+
75+
expect(closeSpy).toHaveBeenCalledOnce();
76+
expect(removeSpy).toHaveBeenCalledWith('pagehide', pagehideHandler, { capture: true });
77+
78+
const sendPromise = socket.send({ foo: 'bar' } as CatcherMessage);
79+
80+
const second = instances[1];
81+
second.readyState = WebSocket.OPEN;
82+
second.onopen?.(new Event('open'));
83+
await sendPromise;
84+
85+
expect(ctor).toHaveBeenCalledTimes(2);
86+
expect(second.url).toBe(MOCK_WEBSOCKET_URL);
87+
});
88+
});

0 commit comments

Comments
 (0)