@1upmonster/versus 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1upmonster/versus",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -16,8 +16,8 @@
16
16
  "dist"
17
17
  ],
18
18
  "dependencies": {
19
- "@1upmonster/sdk": "0.1.0",
20
- "@1upmonster/types": "0.1.0"
19
+ "@1upmonster/sdk": "0.1.1",
20
+ "@1upmonster/types": "0.1.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "typescript": "^5.7.2",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=client.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/test/client.test.ts"],"names":[],"mappings":""}
@@ -1,290 +0,0 @@
1
- import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
2
- import { VersusClient, MatchProposal } from "../client.js";
3
- import { Room } from "../room.js";
4
- import { FakeWebSocket } from "./fake-ws.js";
5
- // ---------------------------------------------------------------------------
6
- // Test setup
7
- // ---------------------------------------------------------------------------
8
- const BASE_URL = "https://api.test.internal";
9
- const TOKEN = "test-session-jwt";
10
- const API_KEY = "1up_testapikey";
11
- function makeClient() {
12
- return new VersusClient({ baseUrl: BASE_URL, token: TOKEN, gameApiKey: API_KEY });
13
- }
14
- let queueWs;
15
- let roomWs;
16
- let wsCallCount = 0;
17
- function stubWebSocket() {
18
- wsCallCount = 0;
19
- vi.stubGlobal("WebSocket", class extends FakeWebSocket {
20
- constructor(url) {
21
- super(url);
22
- wsCallCount++;
23
- if (wsCallCount === 1) {
24
- queueWs = this; // first WS = queue WS
25
- }
26
- else {
27
- roomWs = this; // second WS = room WS (created by Room constructor)
28
- }
29
- }
30
- });
31
- }
32
- function stubFetch(ok = true, body) {
33
- vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
34
- ok,
35
- text: vi.fn().mockResolvedValue(ok ? "" : "Error"),
36
- json: vi.fn().mockResolvedValue(body ?? {}),
37
- }));
38
- }
39
- afterEach(() => {
40
- vi.restoreAllMocks();
41
- vi.useRealTimers();
42
- });
43
- // ---------------------------------------------------------------------------
44
- // matchmake()
45
- // ---------------------------------------------------------------------------
46
- describe("VersusClient — matchmake()", () => {
47
- beforeEach(() => {
48
- stubWebSocket();
49
- stubFetch(true);
50
- });
51
- it("POSTs to /versus/:gameId/queue with correct headers", async () => {
52
- // Resolve with match_found quickly
53
- const matchmakePromise = makeClient().matchmake("game1");
54
- // Let the async fetch complete
55
- await vi.waitFor(() => expect(queueWs).toBeDefined());
56
- const fetchMock = vi.mocked(globalThis.fetch);
57
- const [url, init] = fetchMock.mock.calls[0];
58
- expect(url).toBe(`${BASE_URL}/versus/game1/queue`);
59
- expect(init.headers["Authorization"]).toBe(`Bearer ${TOKEN}`);
60
- expect(init.headers["X-Api-Key"]).toBe(API_KEY);
61
- expect(init.method).toBe("POST");
62
- // Resolve the promise to avoid unhandled rejection
63
- queueWs.receive(JSON.stringify({
64
- type: "match_found",
65
- payload: {
66
- matchId: "m1",
67
- opponents: [{ walletPubkey: "p2", elo: 1000 }],
68
- acceptDeadline: Date.now() + 15000,
69
- },
70
- }));
71
- await matchmakePromise;
72
- });
73
- it("opens queue WebSocket with token and apiKey params", async () => {
74
- const matchmakePromise = makeClient().matchmake("game1");
75
- await vi.waitFor(() => expect(queueWs).toBeDefined());
76
- expect(queueWs.url).toContain(`/versus/game1/queue/ws`);
77
- expect(queueWs.url).toContain(`token=`);
78
- expect(queueWs.url).toContain(`apiKey=`);
79
- queueWs.receive(JSON.stringify({
80
- type: "match_found",
81
- payload: { matchId: "m1", opponents: [], acceptDeadline: Date.now() + 15000 },
82
- }));
83
- await matchmakePromise;
84
- });
85
- it("calls onQueued callback after successful HTTP join", async () => {
86
- const onQueued = vi.fn();
87
- const matchmakePromise = makeClient().matchmake("game1", onQueued);
88
- await vi.waitFor(() => expect(onQueued).toHaveBeenCalled());
89
- queueWs.receive(JSON.stringify({
90
- type: "match_found",
91
- payload: { matchId: "m1", opponents: [], acceptDeadline: Date.now() + 15000 },
92
- }));
93
- await matchmakePromise;
94
- });
95
- it("resolves with MatchProposal on match_found", async () => {
96
- const matchmakePromise = makeClient().matchmake("game1");
97
- await vi.waitFor(() => expect(queueWs).toBeDefined());
98
- const payload = {
99
- matchId: "match-abc",
100
- opponents: [{ walletPubkey: "p2", elo: 1050 }],
101
- acceptDeadline: Date.now() + 15000,
102
- };
103
- queueWs.receive(JSON.stringify({ type: "match_found", payload }));
104
- const proposal = await matchmakePromise;
105
- expect(proposal).toBeInstanceOf(MatchProposal);
106
- expect(proposal.matchId).toBe("match-abc");
107
- expect(proposal.opponents).toEqual(payload.opponents);
108
- expect(proposal.acceptDeadline).toBe(payload.acceptDeadline);
109
- });
110
- it("rejects on queue_expired", async () => {
111
- const matchmakePromise = makeClient().matchmake("game1");
112
- await vi.waitFor(() => expect(queueWs).toBeDefined());
113
- queueWs.receive(JSON.stringify({ type: "queue_expired" }));
114
- await expect(matchmakePromise).rejects.toThrow(/expired/i);
115
- });
116
- it("rejects on unexpected WebSocket close", async () => {
117
- const matchmakePromise = makeClient().matchmake("game1");
118
- await vi.waitFor(() => expect(queueWs).toBeDefined());
119
- queueWs.serverClose(); // wasClean=false
120
- await expect(matchmakePromise).rejects.toThrow();
121
- });
122
- it("rejects when HTTP join fails", async () => {
123
- vi.stubGlobal("fetch", vi.fn().mockResolvedValue({ ok: false, text: vi.fn().mockResolvedValue("Queue full") }));
124
- await expect(makeClient().matchmake("game1")).rejects.toThrow("Queue full");
125
- });
126
- });
127
- // ---------------------------------------------------------------------------
128
- // MatchProposal.accept()
129
- // ---------------------------------------------------------------------------
130
- describe("MatchProposal — accept()", () => {
131
- beforeEach(() => {
132
- stubWebSocket();
133
- stubFetch(true);
134
- });
135
- async function getProposal() {
136
- const matchmakePromise = makeClient().matchmake("game1");
137
- await vi.waitFor(() => expect(queueWs).toBeDefined());
138
- queueWs.open(); // WS must be OPEN for accept()/decline() to send messages
139
- queueWs.receive(JSON.stringify({
140
- type: "match_found",
141
- payload: { matchId: "m1", opponents: [], acceptDeadline: Date.now() + 15000 },
142
- }));
143
- return matchmakePromise;
144
- }
145
- it("sends accept_match message to the queue WS", async () => {
146
- const proposal = await getProposal();
147
- const sentBefore = queueWs.sent.length;
148
- const acceptPromise = proposal.accept();
149
- // accept_match should have been sent synchronously in the Promise executor
150
- expect(queueWs.sent.length).toBeGreaterThan(sentBefore);
151
- const lastSent = JSON.parse(queueWs.sent[queueWs.sent.length - 1]);
152
- expect(lastSent).toEqual({ type: "accept_match" });
153
- // Resolve with match_ready
154
- queueWs.receive(JSON.stringify({
155
- type: "match_ready",
156
- payload: { matchId: "m1", roomToken: "room-jwt", roomUrl: "wss://api.test.internal/versus/rooms/m1" },
157
- }));
158
- await acceptPromise;
159
- });
160
- it("resolves with a Room instance on match_ready", async () => {
161
- const proposal = await getProposal();
162
- const acceptPromise = proposal.accept();
163
- queueWs.receive(JSON.stringify({
164
- type: "match_ready",
165
- payload: {
166
- matchId: "m1",
167
- roomToken: "room-jwt-token",
168
- roomUrl: "wss://api.test.internal/versus/rooms/m1",
169
- },
170
- }));
171
- const room = await acceptPromise;
172
- expect(room).toBeInstanceOf(Room);
173
- // Token is passed in the URL — Worker validates it before forwarding to the Room DO
174
- expect(roomWs?.url ?? queueWs.url).toContain("room-jwt-token");
175
- });
176
- it("rejects on match_declined", async () => {
177
- const proposal = await getProposal();
178
- const acceptPromise = proposal.accept();
179
- queueWs.receive(JSON.stringify({
180
- type: "match_declined",
181
- payload: { reason: "declined", walletPubkey: "p2" },
182
- }));
183
- await expect(acceptPromise).rejects.toThrow(/cancelled/i);
184
- });
185
- });
186
- // ---------------------------------------------------------------------------
187
- // MatchProposal.decline()
188
- // ---------------------------------------------------------------------------
189
- describe("MatchProposal — decline()", () => {
190
- beforeEach(() => {
191
- stubWebSocket();
192
- stubFetch(true);
193
- });
194
- it("sends decline_match and closes the queue WS", async () => {
195
- const matchmakePromise = makeClient().matchmake("game1");
196
- await vi.waitFor(() => expect(queueWs).toBeDefined());
197
- queueWs.open(); // WS must be OPEN for decline() to send
198
- queueWs.receive(JSON.stringify({
199
- type: "match_found",
200
- payload: { matchId: "m1", opponents: [], acceptDeadline: Date.now() + 15000 },
201
- }));
202
- const proposal = await matchmakePromise;
203
- proposal.decline();
204
- const sentMsgs = queueWs.sent.map((s) => JSON.parse(s));
205
- expect(sentMsgs).toContainEqual({ type: "decline_match" });
206
- expect(queueWs.readyState).toBe(FakeWebSocket.CLOSED);
207
- });
208
- });
209
- // ---------------------------------------------------------------------------
210
- // MatchProposal.abandon() — resource leak cleanup (GAP-32)
211
- // ---------------------------------------------------------------------------
212
- describe("MatchProposal — abandon() (GAP-32)", () => {
213
- beforeEach(() => {
214
- stubWebSocket();
215
- stubFetch(true);
216
- });
217
- async function getProposal() {
218
- const matchmakePromise = makeClient().matchmake("game1");
219
- await vi.waitFor(() => expect(queueWs).toBeDefined());
220
- queueWs.open();
221
- queueWs.receive(JSON.stringify({
222
- type: "match_found",
223
- payload: { matchId: "m1", opponents: [], acceptDeadline: Date.now() + 15000 },
224
- }));
225
- return matchmakePromise;
226
- }
227
- it("closes the WebSocket on abandon()", async () => {
228
- const proposal = await getProposal();
229
- proposal.abandon();
230
- expect(queueWs.readyState).toBe(FakeWebSocket.CLOSED);
231
- });
232
- it("does not send accept_match or decline_match on abandon()", async () => {
233
- const proposal = await getProposal();
234
- const sentBefore = queueWs.sent.length;
235
- proposal.abandon();
236
- const newMsgs = queueWs.sent.slice(sentBefore).map((s) => JSON.parse(s));
237
- expect(newMsgs.map((m) => m.type)).not.toContain("accept_match");
238
- expect(newMsgs.map((m) => m.type)).not.toContain("decline_match");
239
- });
240
- });
241
- // ---------------------------------------------------------------------------
242
- // leaveQueue()
243
- // ---------------------------------------------------------------------------
244
- describe("VersusClient — leaveQueue()", () => {
245
- it("POSTs to /versus/:gameId/queue/leave with correct headers", async () => {
246
- stubFetch(true);
247
- await makeClient().leaveQueue("game1");
248
- const fetchMock = vi.mocked(globalThis.fetch);
249
- const [url, init] = fetchMock.mock.calls[0];
250
- expect(url).toBe(`${BASE_URL}/versus/game1/queue/leave`);
251
- expect(init.method).toBe("POST");
252
- expect(init.headers["Authorization"]).toBe(`Bearer ${TOKEN}`);
253
- });
254
- });
255
- // ---------------------------------------------------------------------------
256
- // getConfig / setConfig / listMatches / inspectMatch
257
- // ---------------------------------------------------------------------------
258
- describe("VersusClient — REST helpers", () => {
259
- beforeEach(() => {
260
- vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
261
- ok: true,
262
- json: vi.fn().mockResolvedValue({}),
263
- }));
264
- });
265
- it("getConfig: GET /versus/:gameId/config with auth headers", async () => {
266
- await makeClient().getConfig("g1");
267
- const [url, init] = vi.mocked(fetch).mock.calls[0];
268
- expect(url).toBe(`${BASE_URL}/versus/g1/config`);
269
- expect(init.method).toBeUndefined(); // default GET
270
- expect(init.headers["Authorization"]).toBe(`Bearer ${TOKEN}`);
271
- });
272
- it("setConfig: PUT /versus/:gameId/config", async () => {
273
- await makeClient().setConfig("g1", { queueTtl: 60 });
274
- const [url, init] = vi.mocked(fetch).mock.calls[0];
275
- expect(url).toBe(`${BASE_URL}/versus/g1/config`);
276
- expect(init.method).toBe("PUT");
277
- expect(JSON.parse(init.body)).toMatchObject({ queueTtl: 60 });
278
- });
279
- it("listMatches: GET /versus/:gameId/matches", async () => {
280
- await makeClient().listMatches("g1");
281
- const [url] = vi.mocked(fetch).mock.calls[0];
282
- expect(url).toBe(`${BASE_URL}/versus/g1/matches`);
283
- });
284
- it("inspectMatch: GET /versus/matches/:matchId", async () => {
285
- await makeClient().inspectMatch("match-123");
286
- const [url] = vi.mocked(fetch).mock.calls[0];
287
- expect(url).toBe(`${BASE_URL}/versus/matches/match-123`);
288
- });
289
- });
290
- //# sourceMappingURL=client.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/test/client.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,QAAQ,GAAG,2BAA2B,CAAC;AAC7C,MAAM,KAAK,GAAG,kBAAkB,CAAC;AACjC,MAAM,OAAO,GAAG,gBAAgB,CAAC;AAEjC,SAAS,UAAU;IACjB,OAAO,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;AACpF,CAAC;AAED,IAAI,OAAsB,CAAC;AAC3B,IAAI,MAAqB,CAAC;AAC1B,IAAI,WAAW,GAAG,CAAC,CAAC;AAEpB,SAAS,aAAa;IACpB,WAAW,GAAG,CAAC,CAAC;IAChB,EAAE,CAAC,UAAU,CACX,WAAW,EACX,KAAM,SAAQ,aAAa;QACzB,YAAY,GAAiB;YAC3B,KAAK,CAAC,GAAG,CAAC,CAAC;YACX,WAAW,EAAE,CAAC;YACd,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;gBACtB,OAAO,GAAG,IAAI,CAAC,CAAC,sBAAsB;YACxC,CAAC;iBAAM,CAAC;gBACN,MAAM,GAAG,IAAI,CAAC,CAAC,oDAAoD;YACrE,CAAC;QACH,CAAC;KACF,CACF,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,IAAc;IAC1C,EAAE,CAAC,UAAU,CACX,OAAO,EACP,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;QACxB,EAAE;QACF,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;QAClD,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,IAAI,EAAE,CAAC;KAC5C,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,eAAe,EAAE,CAAC;IACrB,EAAE,CAAC,aAAa,EAAE,CAAC;AACrB,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,EAAE,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,mCAAmC;QACnC,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,+BAA+B;QAC/B,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAEtD,MAAM,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA0B,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,qBAAqB,CAAC,CAAC;QACnD,MAAM,CAAE,IAAI,CAAC,OAAkC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;QAC1F,MAAM,CAAE,IAAI,CAAC,OAAkC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5E,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEjC,mDAAmD;QACnD,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE;gBACP,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;gBAC9C,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;aACnC;SACF,CAAC,CACH,CAAC;QACF,MAAM,gBAAgB,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAEtD,MAAM,CAAC,OAAQ,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACzD,MAAM,CAAC,OAAQ,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,OAAQ,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAE1C,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE;SAC9E,CAAC,CACH,CAAC;QACF,MAAM,gBAAgB,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACnE,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAE5D,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE;SAC9E,CAAC,CACH,CAAC;QACF,MAAM,gBAAgB,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAEtD,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;YAC9C,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SACnC,CAAC;QACF,OAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAEnE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;QACxC,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QAC/C,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACtD,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QACxC,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAEtD,OAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC,CAAC;QAE5D,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAEtD,OAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,iBAAiB;QAEzC,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,EAAE,CAAC,UAAU,CACX,OAAO,EACP,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,CAAC,CACxF,CAAC;QACF,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,EAAE,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,WAAW;QACxB,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACtD,OAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,0DAA0D;QAC3E,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE;SAC9E,CAAC,CACH,CAAC;QACF,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,OAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QACxC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAExC,2EAA2E;QAC3E,MAAM,CAAC,OAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAQ,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC;QACtE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAEnD,2BAA2B;QAC3B,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,yCAAyC,EAAE;SACtG,CAAC,CACH,CAAC;QACF,MAAM,aAAa,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAExC,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE;gBACP,OAAO,EAAE,IAAI;gBACb,SAAS,EAAE,gBAAgB;gBAC3B,OAAO,EAAE,yCAAyC;aACnD;SACF,CAAC,CACH,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAClC,oFAAoF;QACpF,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,OAAQ,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;QAExC,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE;SACpD,CAAC,CACH,CAAC;QACF,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,0BAA0B;AAC1B,8EAA8E;AAE9E,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,EAAE,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACtD,OAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,wCAAwC;QACzD,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE;SAC9E,CAAC,CACH,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;QAExC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAEnB,MAAM,QAAQ,GAAG,OAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,OAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,2DAA2D;AAC3D,8EAA8E;AAE9E,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,EAAE,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,KAAK,UAAU,WAAW;QACxB,MAAM,gBAAgB,GAAG,UAAU,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACtD,OAAQ,CAAC,IAAI,EAAE,CAAC;QAChB,OAAQ,CAAC,OAAO,CACd,IAAI,CAAC,SAAS,CAAC;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,EAAE;SAC9E,CAAC,CACH,CAAC;QACF,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,CAAC,OAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,OAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QACxC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,OAAO,GAAG,OAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAqB,CAAC,CAAC;QAC9F,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;QACjE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,UAAU,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAEvC,MAAM,SAAS,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA0B,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,2BAA2B,CAAC,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,CAAE,IAAI,CAAC,OAAkC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,qDAAqD;AACrD,8EAA8E;AAE9E,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,UAAU,CACX,OAAO,EACP,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YACxB,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;SACpC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,UAAU,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA0B,CAAC;QAC5E,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,mBAAmB,CAAC,CAAC;QACjD,MAAM,CAAE,IAA4B,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,cAAc;QAC5E,MAAM,CAAE,IAAI,CAAC,OAAkC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,UAAU,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAW,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAA0B,CAAC;QAC5E,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,mBAAmB,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,UAAU,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAa,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,oBAAoB,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,UAAU,EAAE,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAC7C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAa,CAAC;QACzD,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,QAAQ,2BAA2B,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,35 +0,0 @@
1
- /**
2
- * Hand-rolled FakeWebSocket for unit-testing Room and VersusClient.
3
- *
4
- * Usage:
5
- * vi.stubGlobal("WebSocket", FakeWebSocket);
6
- * // construct Room / VersusClient — they will get a FakeWebSocket instance
7
- * fakeWs.open(); // trigger the "open" event
8
- * fakeWs.receive(data); // inject a "message" event
9
- * fakeWs.serverClose(); // inject a dirty "close" event (wasClean=false)
10
- * fakeWs.sent // inspect outbound messages
11
- */
12
- export declare class FakeWebSocket extends EventTarget {
13
- static readonly CONNECTING = 0;
14
- static readonly OPEN = 1;
15
- static readonly CLOSING = 2;
16
- static readonly CLOSED = 3;
17
- readonly CONNECTING = 0;
18
- readonly OPEN = 1;
19
- readonly CLOSING = 2;
20
- readonly CLOSED = 3;
21
- readyState: number;
22
- readonly url: string;
23
- /** All payloads passed to send() while OPEN. */
24
- sent: string[];
25
- constructor(url: string | URL);
26
- send(data: string): void;
27
- close(_code?: number, _reason?: string): void;
28
- /** Test helper: fire the "open" event and move to OPEN state. */
29
- open(): void;
30
- /** Test helper: inject an incoming message from the server. */
31
- receive(data: string): void;
32
- /** Test helper: inject an unclean "close" event (wasClean=false). */
33
- serverClose(code?: number, reason?: string): void;
34
- }
35
- //# sourceMappingURL=fake-ws.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fake-ws.d.ts","sourceRoot":"","sources":["../../src/test/fake-ws.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,SAAQ,WAAW;IAC5C,MAAM,CAAC,QAAQ,CAAC,UAAU,KAAK;IAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK;IACzB,MAAM,CAAC,QAAQ,CAAC,OAAO,KAAK;IAC5B,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK;IAE3B,QAAQ,CAAC,UAAU,KAAK;IACxB,QAAQ,CAAC,IAAI,KAAK;IAClB,QAAQ,CAAC,OAAO,KAAK;IACrB,QAAQ,CAAC,MAAM,KAAK;IAEpB,UAAU,EAAE,MAAM,CAA4B;IAC9C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,MAAM,EAAE,CAAM;gBAER,GAAG,EAAE,MAAM,GAAG,GAAG;IAK7B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMxB,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAM7C,iEAAiE;IACjE,IAAI,IAAI,IAAI;IAKZ,+DAA+D;IAC/D,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI3B,qEAAqE;IACrE,WAAW,CAAC,IAAI,SAAO,EAAE,MAAM,SAAK,GAAG,IAAI;CAK5C"}
@@ -1,57 +0,0 @@
1
- /**
2
- * Hand-rolled FakeWebSocket for unit-testing Room and VersusClient.
3
- *
4
- * Usage:
5
- * vi.stubGlobal("WebSocket", FakeWebSocket);
6
- * // construct Room / VersusClient — they will get a FakeWebSocket instance
7
- * fakeWs.open(); // trigger the "open" event
8
- * fakeWs.receive(data); // inject a "message" event
9
- * fakeWs.serverClose(); // inject a dirty "close" event (wasClean=false)
10
- * fakeWs.sent // inspect outbound messages
11
- */
12
- export class FakeWebSocket extends EventTarget {
13
- static CONNECTING = 0;
14
- static OPEN = 1;
15
- static CLOSING = 2;
16
- static CLOSED = 3;
17
- CONNECTING = 0;
18
- OPEN = 1;
19
- CLOSING = 2;
20
- CLOSED = 3;
21
- readyState = FakeWebSocket.CONNECTING;
22
- url;
23
- /** All payloads passed to send() while OPEN. */
24
- sent = [];
25
- constructor(url) {
26
- super();
27
- this.url = url.toString();
28
- }
29
- send(data) {
30
- if (this.readyState === FakeWebSocket.OPEN) {
31
- this.sent.push(data);
32
- }
33
- }
34
- close(_code, _reason) {
35
- if (this.readyState === FakeWebSocket.CLOSED)
36
- return;
37
- this.readyState = FakeWebSocket.CLOSED;
38
- this.dispatchEvent(new CloseEvent("close", { wasClean: true }));
39
- }
40
- /** Test helper: fire the "open" event and move to OPEN state. */
41
- open() {
42
- this.readyState = FakeWebSocket.OPEN;
43
- this.dispatchEvent(new Event("open"));
44
- }
45
- /** Test helper: inject an incoming message from the server. */
46
- receive(data) {
47
- this.dispatchEvent(new MessageEvent("message", { data }));
48
- }
49
- /** Test helper: inject an unclean "close" event (wasClean=false). */
50
- serverClose(code = 1006, reason = "") {
51
- if (this.readyState === FakeWebSocket.CLOSED)
52
- return;
53
- this.readyState = FakeWebSocket.CLOSED;
54
- this.dispatchEvent(new CloseEvent("close", { wasClean: false, code, reason }));
55
- }
56
- }
57
- //# sourceMappingURL=fake-ws.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fake-ws.js","sourceRoot":"","sources":["../../src/test/fake-ws.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,OAAO,aAAc,SAAQ,WAAW;IAC5C,MAAM,CAAU,UAAU,GAAG,CAAC,CAAC;IAC/B,MAAM,CAAU,IAAI,GAAG,CAAC,CAAC;IACzB,MAAM,CAAU,OAAO,GAAG,CAAC,CAAC;IAC5B,MAAM,CAAU,MAAM,GAAG,CAAC,CAAC;IAElB,UAAU,GAAG,CAAC,CAAC;IACf,IAAI,GAAG,CAAC,CAAC;IACT,OAAO,GAAG,CAAC,CAAC;IACZ,MAAM,GAAG,CAAC,CAAC;IAEpB,UAAU,GAAW,aAAa,CAAC,UAAU,CAAC;IACrC,GAAG,CAAS;IACrB,gDAAgD;IAChD,IAAI,GAAa,EAAE,CAAC;IAEpB,YAAY,GAAiB;QAC3B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC;IAED,IAAI,CAAC,IAAY;QACf,IAAI,IAAI,CAAC,UAAU,KAAK,aAAa,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAc,EAAE,OAAgB;QACpC,IAAI,IAAI,CAAC,UAAU,KAAK,aAAa,CAAC,MAAM;YAAE,OAAO;QACrD,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,iEAAiE;IACjE,IAAI;QACF,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC;QACrC,IAAI,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,+DAA+D;IAC/D,OAAO,CAAC,IAAY;QAClB,IAAI,CAAC,aAAa,CAAC,IAAI,YAAY,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,qEAAqE;IACrE,WAAW,CAAC,IAAI,GAAG,IAAI,EAAE,MAAM,GAAG,EAAE;QAClC,IAAI,IAAI,CAAC,UAAU,KAAK,aAAa,CAAC,MAAM;YAAE,OAAO;QACrD,IAAI,CAAC,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACjF,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=room.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"room.test.d.ts","sourceRoot":"","sources":["../../src/test/room.test.ts"],"names":[],"mappings":""}
@@ -1,181 +0,0 @@
1
- import { describe, expect, it, beforeEach, afterEach, vi } from "vitest";
2
- import { Room } from "../room.js";
3
- import { FakeWebSocket } from "./fake-ws.js";
4
- // ---------------------------------------------------------------------------
5
- // Helpers
6
- // ---------------------------------------------------------------------------
7
- let fakeWs;
8
- /** Stubs global WebSocket to capture the FakeWebSocket instance. */
9
- function stubWs() {
10
- vi.stubGlobal("WebSocket", class extends FakeWebSocket {
11
- constructor(url) {
12
- super(url);
13
- fakeWs = this;
14
- }
15
- });
16
- }
17
- afterEach(() => {
18
- vi.restoreAllMocks();
19
- vi.useRealTimers();
20
- });
21
- // ---------------------------------------------------------------------------
22
- // Constructor
23
- // ---------------------------------------------------------------------------
24
- describe("Room — constructor", () => {
25
- beforeEach(stubWs);
26
- it("opens WebSocket with ?token= in URL", () => {
27
- new Room("wss://test.internal/versus/rooms/m1", "my-room-token");
28
- // Token must appear in the URL — Worker validates it before forwarding to DO
29
- expect(fakeWs.url).toContain("token=my-room-token");
30
- });
31
- it("starts pinging after open (every 5s)", () => {
32
- vi.useFakeTimers();
33
- new Room("wss://test.internal/versus/rooms/m1", "tok");
34
- fakeWs.open(); // trigger "open" event → starts ping
35
- // No auth frame — token is in the URL
36
- expect(fakeWs.sent).toHaveLength(0);
37
- vi.advanceTimersByTime(5001);
38
- // first ping
39
- expect(fakeWs.sent).toHaveLength(1);
40
- expect(JSON.parse(fakeWs.sent[0])).toEqual({ type: "ping" });
41
- vi.advanceTimersByTime(5000);
42
- // second ping
43
- expect(fakeWs.sent).toHaveLength(2);
44
- });
45
- it("stops pinging after close", () => {
46
- vi.useFakeTimers();
47
- new Room("wss://test.internal/versus/rooms/m1", "tok");
48
- fakeWs.open();
49
- vi.advanceTimersByTime(5001);
50
- expect(fakeWs.sent).toHaveLength(1); // ping
51
- fakeWs.close();
52
- vi.advanceTimersByTime(10_000);
53
- // No more pings after close
54
- expect(fakeWs.sent).toHaveLength(1); // still 1 ping
55
- });
56
- });
57
- // ---------------------------------------------------------------------------
58
- // on / off
59
- // ---------------------------------------------------------------------------
60
- describe("Room — on/off", () => {
61
- beforeEach(stubWs);
62
- it("listener fires on matching event", () => {
63
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
64
- fakeWs.open();
65
- const calls = [];
66
- room.on("game_message", (p) => calls.push(p));
67
- fakeWs.receive(JSON.stringify({ type: "game_message", payload: { from: "p2", data: { x: 1 } } }));
68
- expect(calls).toHaveLength(1);
69
- expect(calls[0]).toEqual({ from: "p2", data: { x: 1 } });
70
- });
71
- it("off removes only the specified listener", () => {
72
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
73
- fakeWs.open();
74
- const calls1 = [];
75
- const calls2 = [];
76
- const listener1 = (p) => calls1.push(p);
77
- room.on("room_ready", listener1);
78
- room.on("room_ready", (p) => calls2.push(p));
79
- room.off("room_ready", listener1);
80
- fakeWs.receive(JSON.stringify({ type: "room_ready" }));
81
- expect(calls1).toHaveLength(0);
82
- expect(calls2).toHaveLength(1);
83
- });
84
- });
85
- // ---------------------------------------------------------------------------
86
- // ready()
87
- // ---------------------------------------------------------------------------
88
- describe("Room — ready()", () => {
89
- beforeEach(stubWs);
90
- it("sends {type:'ready'} when WS is OPEN", () => {
91
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
92
- fakeWs.open();
93
- room.ready();
94
- expect(fakeWs.sent.map((s) => JSON.parse(s))).toContainEqual({ type: "ready" });
95
- });
96
- it("does not send when WS is not OPEN", () => {
97
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
98
- // fakeWs starts in CONNECTING state — auth is only sent on open event
99
- room.ready();
100
- expect(fakeWs.sent).toHaveLength(0);
101
- });
102
- });
103
- // ---------------------------------------------------------------------------
104
- // broadcast(data)
105
- // ---------------------------------------------------------------------------
106
- describe("Room — broadcast()", () => {
107
- beforeEach(stubWs);
108
- it("sends {type:'game_message', payload: data}", () => {
109
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
110
- fakeWs.open(); // starts ping interval, no auth frame
111
- room.broadcast({ move: "up" });
112
- const sentMsgs = fakeWs.sent.map((s) => JSON.parse(s));
113
- expect(sentMsgs).toContainEqual({ type: "game_message", payload: { move: "up" } });
114
- });
115
- });
116
- // ---------------------------------------------------------------------------
117
- // leave()
118
- // ---------------------------------------------------------------------------
119
- describe("Room — leave()", () => {
120
- beforeEach(stubWs);
121
- it("closes the WebSocket and stops pinging", () => {
122
- vi.useFakeTimers();
123
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
124
- fakeWs.open(); // starts ping interval
125
- vi.advanceTimersByTime(5001);
126
- // 1 ping (no auth frame)
127
- expect(fakeWs.sent).toHaveLength(1);
128
- room.leave();
129
- expect(fakeWs.readyState).toBe(FakeWebSocket.CLOSED);
130
- vi.advanceTimersByTime(10_000);
131
- expect(fakeWs.sent).toHaveLength(1); // no more pings
132
- });
133
- });
134
- // ---------------------------------------------------------------------------
135
- // Incoming message routing
136
- // ---------------------------------------------------------------------------
137
- describe("Room — incoming message routing", () => {
138
- beforeEach(stubWs);
139
- it("routes room_ready to listener with no payload", () => {
140
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
141
- fakeWs.open();
142
- const calls = [];
143
- room.on("room_ready", (p) => calls.push(p));
144
- fakeWs.receive(JSON.stringify({ type: "room_ready" }));
145
- expect(calls).toHaveLength(1);
146
- });
147
- it("routes game_message payload to listener", () => {
148
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
149
- fakeWs.open();
150
- const calls = [];
151
- room.on("game_message", (p) => calls.push(p));
152
- fakeWs.receive(JSON.stringify({ type: "game_message", payload: { from: "p2", data: 42 } }));
153
- expect(calls[0]).toEqual({ from: "p2", data: 42 });
154
- });
155
- it("routes opponent_disconnected to listener", () => {
156
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
157
- fakeWs.open();
158
- const calls = [];
159
- room.on("opponent_disconnected", (p) => calls.push(p));
160
- fakeWs.receive(JSON.stringify({ type: "opponent_disconnected" }));
161
- expect(calls).toHaveLength(1);
162
- });
163
- it("routes match_expired to listener", () => {
164
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
165
- fakeWs.open();
166
- const calls = [];
167
- room.on("match_expired", (p) => calls.push(p));
168
- fakeWs.receive(JSON.stringify({ type: "match_expired" }));
169
- expect(calls).toHaveLength(1);
170
- });
171
- it("silently ignores malformed JSON", () => {
172
- const room = new Room("wss://test.internal/versus/rooms/m1", "tok");
173
- fakeWs.open();
174
- const errors = [];
175
- room.on("error", (e) => errors.push(e));
176
- expect(() => fakeWs.receive("not json at all {{{{")).not.toThrow();
177
- // No error events should be emitted for JSON parse failures
178
- expect(errors).toHaveLength(0);
179
- });
180
- });
181
- //# sourceMappingURL=room.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"room.test.js","sourceRoot":"","sources":["../../src/test/room.test.ts"],"names":[],"mappings":"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"}