| 45 | }; |
| 46 | |
| 47 | export function createMockWebSocket( |
| 48 | url: string, |
| 49 | protocol?: string | string[] | undefined, |
| 50 | ): readonly [MockWebSocket, MockWebSocketServer] { |
| 51 | if (!url.startsWith("ws://") && !url.startsWith("wss://")) { |
| 52 | throw new Error("URL must start with ws:// or wss://"); |
| 53 | } |
| 54 | |
| 55 | const activeProtocol = Array.isArray(protocol) |
| 56 | ? protocol.join(" ") |
| 57 | : (protocol ?? ""); |
| 58 | |
| 59 | let isOpen = true; |
| 60 | const store: CallbackStore = { |
| 61 | message: new Set(), |
| 62 | error: new Set(), |
| 63 | close: new Set(), |
| 64 | open: new Set(), |
| 65 | }; |
| 66 | |
| 67 | const sentData: SocketSendData[] = []; |
| 68 | |
| 69 | const mockSocket: MockWebSocket = { |
| 70 | CONNECTING: 0, |
| 71 | OPEN: 1, |
| 72 | CLOSING: 2, |
| 73 | CLOSED: 3, |
| 74 | |
| 75 | url, |
| 76 | protocol: activeProtocol, |
| 77 | readyState: 1, |
| 78 | binaryType: "blob", |
| 79 | bufferedAmount: 0, |
| 80 | extensions: "", |
| 81 | onclose: null, |
| 82 | onerror: null, |
| 83 | onmessage: null, |
| 84 | onopen: null, |
| 85 | dispatchEvent: vi.fn(), |
| 86 | |
| 87 | send: vi.fn((data) => { |
| 88 | if (!isOpen) { |
| 89 | return; |
| 90 | } |
| 91 | sentData.push(data); |
| 92 | }), |
| 93 | |
| 94 | addEventListener: <E extends WebSocketEventType>( |
| 95 | eventType: E, |
| 96 | callback: (event: WebSocketEventMap[E]) => void, |
| 97 | ) => { |
| 98 | if (!isOpen) { |
| 99 | return; |
| 100 | } |
| 101 | const subscribers = store[eventType]; |
| 102 | subscribers.add(callback); |
| 103 | }, |
| 104 | |