quake2ts 0.0.582 → 0.0.584

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.
@@ -1912,7 +1912,7 @@ function teardownBrowserEnvironment() {
1912
1912
  }
1913
1913
 
1914
1914
  // src/setup/canvas.ts
1915
- import { Canvas as Canvas2, Image as Image2, ImageData as ImageData2 } from "@napi-rs/canvas";
1915
+ import { Canvas as Canvas2, ImageData as ImageData2 } from "@napi-rs/canvas";
1916
1916
  function createMockCanvas(width = 300, height = 150) {
1917
1917
  if (typeof document !== "undefined" && document.createElement) {
1918
1918
  const canvas2 = document.createElement("canvas");
@@ -1920,75 +1920,92 @@ function createMockCanvas(width = 300, height = 150) {
1920
1920
  canvas2.height = height;
1921
1921
  return canvas2;
1922
1922
  }
1923
- const canvas = new Canvas2(width, height);
1924
- const originalGetContext = canvas.getContext.bind(canvas);
1925
- canvas.getContext = function(contextId, options) {
1926
- if (contextId === "webgl2") {
1927
- return createMockWebGL2Context(canvas);
1928
- }
1929
- if (contextId === "2d") {
1930
- return originalGetContext("2d", options);
1931
- }
1932
- return originalGetContext(contextId, options);
1923
+ const napiCanvas = new Canvas2(width, height);
1924
+ const canvas = {
1925
+ width,
1926
+ height,
1927
+ getContext: (contextId, options) => {
1928
+ if (contextId === "2d") {
1929
+ return napiCanvas.getContext("2d", options);
1930
+ }
1931
+ if (contextId === "webgl2") {
1932
+ return createMockWebGL2Context(canvas);
1933
+ }
1934
+ return null;
1935
+ },
1936
+ toDataURL: () => napiCanvas.toDataURL(),
1937
+ toBuffer: (mime) => napiCanvas.toBuffer(mime)
1938
+ // Add other properties as needed
1933
1939
  };
1934
1940
  return canvas;
1935
1941
  }
1936
1942
  function createMockCanvasContext2D(canvas) {
1937
- if (!canvas) {
1938
- canvas = createMockCanvas();
1943
+ const c = canvas || createMockCanvas();
1944
+ const ctx = c.getContext("2d");
1945
+ if (!ctx) {
1946
+ throw new Error("Failed to create 2D context");
1939
1947
  }
1940
- return canvas.getContext("2d");
1948
+ return ctx;
1941
1949
  }
1942
1950
  function captureCanvasDrawCalls(context) {
1943
- const drawCalls = [];
1944
- const methodsToSpy = [
1945
- "fillRect",
1946
- "strokeRect",
1947
- "clearRect",
1948
- "fillText",
1949
- "strokeText",
1950
- "drawImage",
1951
- "beginPath",
1952
- "closePath",
1953
- "moveTo",
1954
- "lineTo",
1955
- "arc",
1956
- "arcTo",
1957
- "bezierCurveTo",
1958
- "quadraticCurveTo",
1959
- "stroke",
1960
- "fill",
1961
- "putImageData"
1962
- ];
1963
- methodsToSpy.forEach((method) => {
1964
- const original = context[method];
1965
- if (typeof original === "function") {
1966
- context[method] = function(...args) {
1967
- drawCalls.push({ method, args });
1968
- return original.apply(this, args);
1951
+ const calls = [];
1952
+ const proto = Object.getPrototypeOf(context);
1953
+ for (const key of Object.getOwnPropertyNames(proto)) {
1954
+ const value = context[key];
1955
+ if (typeof value === "function") {
1956
+ context[key] = function(...args) {
1957
+ calls.push({ method: key, args });
1958
+ return value.apply(context, args);
1969
1959
  };
1970
1960
  }
1971
- });
1972
- return drawCalls;
1961
+ }
1962
+ return calls;
1973
1963
  }
1974
1964
  function createMockImageData(width, height, fillColor) {
1975
- const imageData = new ImageData2(width, height);
1965
+ if (typeof global.ImageData !== "undefined") {
1966
+ const data2 = new Uint8ClampedArray(width * height * 4);
1967
+ if (fillColor) {
1968
+ for (let i = 0; i < data2.length; i += 4) {
1969
+ data2[i] = fillColor[0];
1970
+ data2[i + 1] = fillColor[1];
1971
+ data2[i + 2] = fillColor[2];
1972
+ data2[i + 3] = fillColor[3];
1973
+ }
1974
+ }
1975
+ return new global.ImageData(data2, width, height);
1976
+ }
1977
+ const data = new Uint8ClampedArray(width * height * 4);
1976
1978
  if (fillColor) {
1977
- const [r, g, b, a] = fillColor;
1978
- for (let i = 0; i < imageData.data.length; i += 4) {
1979
- imageData.data[i] = r;
1980
- imageData.data[i + 1] = g;
1981
- imageData.data[i + 2] = b;
1982
- imageData.data[i + 3] = a;
1979
+ for (let i = 0; i < data.length; i += 4) {
1980
+ data[i] = fillColor[0];
1981
+ data[i + 1] = fillColor[1];
1982
+ data[i + 2] = fillColor[2];
1983
+ data[i + 3] = fillColor[3];
1983
1984
  }
1984
1985
  }
1985
- return imageData;
1986
+ return new ImageData2(data, width, height);
1986
1987
  }
1987
- function createMockImage(width, height, src) {
1988
- const img = new Image2();
1989
- if (width) img.width = width;
1990
- if (height) img.height = height;
1991
- if (src) img.src = src;
1988
+ function createMockImage(width = 100, height = 100, src = "") {
1989
+ if (typeof document !== "undefined" && document.createElement) {
1990
+ const img2 = document.createElement("img");
1991
+ img2.width = width;
1992
+ img2.height = height;
1993
+ if (src) img2.src = src;
1994
+ return img2;
1995
+ }
1996
+ const img = {
1997
+ width,
1998
+ height,
1999
+ src,
2000
+ complete: true,
2001
+ onload: null,
2002
+ onerror: null
2003
+ };
2004
+ if (src) {
2005
+ setTimeout(() => {
2006
+ if (img.onload) img.onload();
2007
+ }, 0);
2008
+ }
1992
2009
  return img;
1993
2010
  }
1994
2011
 
@@ -2056,193 +2073,89 @@ function setupWebGPUMocks() {
2056
2073
  }
2057
2074
 
2058
2075
  // src/setup/timing.ts
2059
- var activeMockRAF;
2060
2076
  function createMockRAF() {
2061
2077
  let callbacks = [];
2062
- let nextId = 1;
2078
+ let lastId = 0;
2063
2079
  let currentTime = 0;
2064
2080
  const originalRAF = global.requestAnimationFrame;
2065
2081
  const originalCancelRAF = global.cancelAnimationFrame;
2066
- const raf = (callback) => {
2067
- const id = nextId++;
2068
- callbacks.push({ id, callback });
2069
- return id;
2082
+ global.requestAnimationFrame = (callback) => {
2083
+ lastId++;
2084
+ callbacks.push({ id: lastId, callback });
2085
+ return lastId;
2070
2086
  };
2071
- const cancel = (id) => {
2087
+ global.cancelAnimationFrame = (id) => {
2072
2088
  callbacks = callbacks.filter((cb) => cb.id !== id);
2073
2089
  };
2074
- const mock = {
2075
- tick(timestamp) {
2076
- if (typeof timestamp !== "number") {
2077
- currentTime += 16.6;
2078
- } else {
2079
- currentTime = timestamp;
2080
- }
2090
+ return {
2091
+ tick(time) {
2092
+ if (time) currentTime = time;
2093
+ else currentTime += 16.66;
2081
2094
  const currentCallbacks = [...callbacks];
2082
2095
  callbacks = [];
2083
- currentCallbacks.forEach(({ callback }) => {
2084
- callback(currentTime);
2085
- });
2096
+ currentCallbacks.forEach((cb) => cb.callback(currentTime));
2086
2097
  },
2087
- advance(deltaMs = 16.6) {
2088
- this.tick(currentTime + deltaMs);
2098
+ advance(ms) {
2099
+ currentTime += ms;
2100
+ this.tick(currentTime);
2089
2101
  },
2090
2102
  getCallbacks() {
2091
- return callbacks.map((c) => c.callback);
2092
- },
2093
- reset() {
2094
- callbacks = [];
2095
- nextId = 1;
2096
- currentTime = 0;
2097
- },
2098
- enable() {
2099
- activeMockRAF = this;
2100
- global.requestAnimationFrame = raf;
2101
- global.cancelAnimationFrame = cancel;
2102
- },
2103
- disable() {
2104
- if (activeMockRAF === this) {
2105
- activeMockRAF = void 0;
2106
- }
2107
- if (originalRAF) {
2108
- global.requestAnimationFrame = originalRAF;
2109
- } else {
2110
- delete global.requestAnimationFrame;
2111
- }
2112
- if (originalCancelRAF) {
2113
- global.cancelAnimationFrame = originalCancelRAF;
2114
- } else {
2115
- delete global.cancelAnimationFrame;
2116
- }
2103
+ return callbacks;
2117
2104
  }
2118
2105
  };
2119
- return mock;
2120
2106
  }
2121
2107
  function createMockPerformance(startTime = 0) {
2122
- let currentTime = startTime;
2123
- const mockPerf = {
2124
- now: () => currentTime,
2108
+ let now = startTime;
2109
+ const mockPerformance = {
2110
+ now: () => now,
2125
2111
  timeOrigin: startTime,
2126
2112
  timing: {
2127
2113
  navigationStart: startTime
2128
2114
  },
2129
- clearMarks: () => {
2130
- },
2131
- clearMeasures: () => {
2115
+ mark: (_name) => {
2132
2116
  },
2133
- clearResourceTimings: () => {
2117
+ measure: (_name, _start, _end) => {
2134
2118
  },
2135
2119
  getEntries: () => [],
2136
- getEntriesByName: () => [],
2137
- getEntriesByType: () => [],
2138
- mark: () => {
2139
- },
2140
- measure: () => {
2120
+ getEntriesByName: (_name) => [],
2121
+ getEntriesByType: (_type) => [],
2122
+ clearMarks: (_name) => {
2141
2123
  },
2142
- setResourceTimingBufferSize: () => {
2124
+ clearMeasures: (_name) => {
2143
2125
  },
2144
- toJSON: () => ({}),
2145
- addEventListener: () => {
2126
+ clearResourceTimings: () => {
2146
2127
  },
2147
- removeEventListener: () => {
2128
+ setResourceTimingBufferSize: (_maxSize) => {
2148
2129
  },
2149
- dispatchEvent: () => true
2150
- };
2151
- mockPerf.advance = (deltaMs) => {
2152
- currentTime += deltaMs;
2130
+ onresourcetimingbufferfull: null,
2131
+ toJSON: () => ({})
2153
2132
  };
2154
- mockPerf.setTime = (time) => {
2155
- currentTime = time;
2156
- };
2157
- return mockPerf;
2133
+ if (typeof global.performance === "undefined") {
2134
+ global.performance = mockPerformance;
2135
+ }
2136
+ return mockPerformance;
2158
2137
  }
2159
2138
  function createControlledTimer() {
2160
- let currentTime = 0;
2161
- let timers = [];
2162
- let nextId = 1;
2163
- const originalSetTimeout = global.setTimeout;
2164
- const originalClearTimeout = global.clearTimeout;
2165
- const originalSetInterval = global.setInterval;
2166
- const originalClearInterval = global.clearInterval;
2167
- const mockSetTimeout = (callback, delay = 0, ...args) => {
2168
- const id = nextId++;
2169
- timers.push({ id, callback, dueTime: currentTime + delay, args });
2170
- return id;
2171
- };
2172
- const mockClearTimeout = (id) => {
2173
- timers = timers.filter((t) => t.id !== id);
2174
- };
2175
- const mockSetInterval = (callback, delay = 0, ...args) => {
2176
- const id = nextId++;
2177
- timers.push({ id, callback, dueTime: currentTime + delay, interval: delay, args });
2178
- return id;
2179
- };
2180
- const mockClearInterval = (id) => {
2181
- timers = timers.filter((t) => t.id !== id);
2182
- };
2183
- global.setTimeout = mockSetTimeout;
2184
- global.clearTimeout = mockClearTimeout;
2185
- global.setInterval = mockSetInterval;
2186
- global.clearInterval = mockClearInterval;
2139
+ console.warn("createControlledTimer: Recommend using vi.useFakeTimers() instead.");
2187
2140
  return {
2188
- tick() {
2189
- this.advanceBy(0);
2141
+ advanceBy: (ms) => {
2190
2142
  },
2191
- advanceBy(ms) {
2192
- const targetTime = currentTime + ms;
2193
- while (true) {
2194
- let earliest = null;
2195
- for (const t of timers) {
2196
- if (!earliest || t.dueTime < earliest.dueTime) {
2197
- earliest = t;
2198
- }
2199
- }
2200
- if (!earliest || earliest.dueTime > targetTime) {
2201
- break;
2202
- }
2203
- currentTime = earliest.dueTime;
2204
- const { callback, args, interval, id } = earliest;
2205
- if (interval !== void 0) {
2206
- earliest.dueTime += interval;
2207
- if (interval === 0) earliest.dueTime += 1;
2208
- } else {
2209
- timers = timers.filter((t) => t.id !== id);
2210
- }
2211
- callback(...args);
2212
- }
2213
- currentTime = targetTime;
2143
+ runAll: () => {
2214
2144
  },
2215
- clear() {
2216
- timers = [];
2217
- },
2218
- restore() {
2219
- global.setTimeout = originalSetTimeout;
2220
- global.clearTimeout = originalClearTimeout;
2221
- global.setInterval = originalSetInterval;
2222
- global.clearInterval = originalClearInterval;
2145
+ clear: () => {
2223
2146
  }
2224
2147
  };
2225
2148
  }
2226
- function simulateFrames(count, frameTimeMs = 16.6, callback) {
2227
- if (!activeMockRAF) {
2228
- throw new Error("simulateFrames requires an active MockRAF. Ensure createMockRAF().enable() is called.");
2229
- }
2149
+ function simulateFrames(count, frameTime = 16, callback) {
2230
2150
  for (let i = 0; i < count; i++) {
2231
2151
  if (callback) callback(i);
2232
- activeMockRAF.advance(frameTimeMs);
2233
- }
2234
- }
2235
- function simulateFramesWithMock(mock, count, frameTimeMs = 16.6, callback) {
2236
- for (let i = 0; i < count; i++) {
2237
- if (callback) callback(i);
2238
- mock.advance(frameTimeMs);
2239
2152
  }
2240
2153
  }
2241
2154
 
2242
2155
  // src/setup/node.ts
2243
2156
  function setupNodeEnvironment(options = {}) {
2244
- if (options.polyfillFetch && typeof global.fetch === "undefined") {
2245
- }
2157
+ }
2158
+ function teardownNodeEnvironment() {
2246
2159
  }
2247
2160
 
2248
2161
  // src/engine/rendering.ts
@@ -2304,186 +2217,141 @@ function createMockRenderingContext() {
2304
2217
  }
2305
2218
 
2306
2219
  // src/setup/storage.ts
2307
- import "fake-indexeddb/auto";
2308
- function createMockLocalStorage(initialData = {}) {
2309
- const storage = new Map(Object.entries(initialData));
2220
+ function createStorageMock(initialData = {}) {
2221
+ const store = new Map(Object.entries(initialData));
2310
2222
  return {
2311
- getItem: (key) => storage.get(key) || null,
2312
- setItem: (key, value) => storage.set(key, value),
2313
- removeItem: (key) => storage.delete(key),
2314
- clear: () => storage.clear(),
2315
- key: (index) => Array.from(storage.keys())[index] || null,
2223
+ getItem: (key) => store.get(key) || null,
2224
+ setItem: (key, value) => store.set(key, value.toString()),
2225
+ removeItem: (key) => store.delete(key),
2226
+ clear: () => store.clear(),
2227
+ key: (index) => Array.from(store.keys())[index] || null,
2316
2228
  get length() {
2317
- return storage.size;
2229
+ return store.size;
2318
2230
  }
2319
2231
  };
2320
2232
  }
2233
+ function createMockLocalStorage(initialData = {}) {
2234
+ return createStorageMock(initialData);
2235
+ }
2321
2236
  function createMockSessionStorage(initialData = {}) {
2322
- return createMockLocalStorage(initialData);
2237
+ return createStorageMock(initialData);
2323
2238
  }
2324
- function createMockIndexedDB() {
2325
- if (typeof indexedDB === "undefined") {
2326
- throw new Error("IndexedDB mock not found. Ensure fake-indexeddb is loaded.");
2327
- }
2328
- return indexedDB;
2239
+ function createMockIndexedDB(databases) {
2240
+ return global.indexedDB;
2329
2241
  }
2330
2242
  function createStorageTestScenario(storageType = "local") {
2331
- if (storageType === "indexed") {
2332
- const dbName = `test-db-${Math.random().toString(36).substring(7)}`;
2333
- const storeName = "test-store";
2334
- const storage2 = createMockIndexedDB();
2335
- return {
2336
- storage: storage2,
2337
- populate: async (data) => {
2338
- return new Promise((resolve, reject) => {
2339
- const req = storage2.open(dbName, 1);
2340
- req.onupgradeneeded = (e) => {
2341
- const db = e.target.result;
2342
- db.createObjectStore(storeName);
2343
- };
2344
- req.onsuccess = (e) => {
2345
- const db = e.target.result;
2346
- const tx = db.transaction(storeName, "readwrite");
2347
- const store = tx.objectStore(storeName);
2348
- Object.entries(data).forEach(([k, v]) => store.put(v, k));
2349
- tx.oncomplete = () => {
2350
- db.close();
2351
- resolve();
2352
- };
2353
- tx.onerror = () => reject(tx.error);
2354
- };
2355
- req.onerror = () => reject(req.error);
2356
- });
2357
- },
2358
- verify: async (key, value) => {
2359
- return new Promise((resolve, reject) => {
2360
- const req = storage2.open(dbName, 1);
2361
- req.onsuccess = (e) => {
2362
- const db = e.target.result;
2363
- if (!db.objectStoreNames.contains(storeName)) {
2364
- db.close();
2365
- resolve(false);
2366
- return;
2367
- }
2368
- const tx = db.transaction(storeName, "readonly");
2369
- const store = tx.objectStore(storeName);
2370
- const getReq = store.get(key);
2371
- getReq.onsuccess = () => {
2372
- const result = getReq.result === value;
2373
- db.close();
2374
- resolve(result);
2375
- };
2376
- getReq.onerror = () => {
2377
- db.close();
2378
- resolve(false);
2379
- };
2380
- };
2381
- req.onerror = () => reject(req.error);
2382
- });
2383
- }
2384
- };
2385
- }
2386
- const storage = storageType === "local" ? createMockLocalStorage() : createMockSessionStorage();
2387
2243
  return {
2388
- storage,
2389
- populate(data) {
2390
- Object.entries(data).forEach(([k, v]) => storage.setItem(k, v));
2391
- },
2392
- verify(key, value) {
2393
- return storage.getItem(key) === value;
2394
- }
2244
+ localStorage: createMockLocalStorage(),
2245
+ sessionStorage: createMockSessionStorage(),
2246
+ indexedDB: createMockIndexedDB()
2395
2247
  };
2396
2248
  }
2397
2249
 
2398
2250
  // src/setup/audio.ts
2399
- function createMockAudioContext() {
2400
- const context = {
2401
- createGain: () => ({
2402
- connect: () => {
2403
- },
2404
- gain: { value: 1, setValueAtTime: () => {
2405
- } }
2406
- }),
2407
- createOscillator: () => ({
2408
- connect: () => {
2409
- },
2410
- start: () => {
2411
- },
2412
- stop: () => {
2413
- },
2414
- frequency: { value: 440 }
2415
- }),
2416
- createBufferSource: () => ({
2417
- connect: () => {
2418
- },
2419
- start: () => {
2420
- },
2421
- stop: () => {
2422
- },
2423
- buffer: null,
2424
- playbackRate: { value: 1 },
2425
- loop: false
2426
- }),
2427
- destination: {},
2428
- currentTime: 0,
2429
- state: "running",
2430
- resume: async () => {
2431
- },
2432
- suspend: async () => {
2433
- },
2434
- close: async () => {
2435
- },
2436
- decodeAudioData: async (buffer) => ({
2437
- duration: 1,
2438
- length: 44100,
2439
- sampleRate: 44100,
2440
- numberOfChannels: 2,
2441
- getChannelData: () => new Float32Array(44100)
2442
- }),
2443
- createBuffer: (channels, length2, sampleRate) => ({
2444
- duration: length2 / sampleRate,
2445
- length: length2,
2446
- sampleRate,
2447
- numberOfChannels: channels,
2448
- getChannelData: () => new Float32Array(length2)
2449
- }),
2450
- // Helper to track events if needed
2451
- _events: []
2452
- };
2453
- return new Proxy(context, {
2454
- get(target, prop, receiver) {
2455
- if (prop === "_events") return target._events;
2456
- const value = Reflect.get(target, prop, receiver);
2457
- if (typeof value === "function") {
2458
- return (...args) => {
2459
- target._events.push({ type: String(prop), args });
2460
- return Reflect.apply(value, target, args);
2461
- };
2462
- }
2463
- return value;
2464
- }
2465
- });
2466
- }
2467
2251
  function setupMockAudioContext() {
2468
- if (typeof global.AudioContext === "undefined" && typeof global.window !== "undefined") {
2469
- global.AudioContext = class {
2470
- constructor() {
2471
- return createMockAudioContext();
2472
- }
2473
- };
2474
- global.window.AudioContext = global.AudioContext;
2475
- global.window.webkitAudioContext = global.AudioContext;
2252
+ class MockAudioContext {
2253
+ constructor() {
2254
+ this.state = "suspended";
2255
+ this.destination = {};
2256
+ this.currentTime = 0;
2257
+ this.listener = {
2258
+ positionX: { value: 0 },
2259
+ positionY: { value: 0 },
2260
+ positionZ: { value: 0 },
2261
+ forwardX: { value: 0 },
2262
+ forwardY: { value: 0 },
2263
+ forwardZ: { value: 0 },
2264
+ upX: { value: 0 },
2265
+ upY: { value: 0 },
2266
+ upZ: { value: 0 },
2267
+ setOrientation: () => {
2268
+ },
2269
+ setPosition: () => {
2270
+ }
2271
+ };
2272
+ }
2273
+ createGain() {
2274
+ return {
2275
+ gain: { value: 1, linearRampToValueAtTime: () => {
2276
+ } },
2277
+ connect: () => {
2278
+ },
2279
+ disconnect: () => {
2280
+ }
2281
+ };
2282
+ }
2283
+ createBufferSource() {
2284
+ return {
2285
+ buffer: null,
2286
+ loop: false,
2287
+ playbackRate: { value: 1 },
2288
+ connect: () => {
2289
+ },
2290
+ start: () => {
2291
+ },
2292
+ stop: () => {
2293
+ },
2294
+ disconnect: () => {
2295
+ },
2296
+ onended: null
2297
+ };
2298
+ }
2299
+ createPanner() {
2300
+ return {
2301
+ panningModel: "equalpower",
2302
+ distanceModel: "inverse",
2303
+ positionX: { value: 0 },
2304
+ positionY: { value: 0 },
2305
+ positionZ: { value: 0 },
2306
+ orientationX: { value: 0 },
2307
+ orientationY: { value: 0 },
2308
+ orientationZ: { value: 0 },
2309
+ coneInnerAngle: 360,
2310
+ coneOuterAngle: 360,
2311
+ coneOuterGain: 0,
2312
+ connect: () => {
2313
+ },
2314
+ disconnect: () => {
2315
+ },
2316
+ setPosition: () => {
2317
+ },
2318
+ setOrientation: () => {
2319
+ }
2320
+ };
2321
+ }
2322
+ createBuffer(numOfChannels, length2, sampleRate) {
2323
+ return {
2324
+ duration: length2 / sampleRate,
2325
+ length: length2,
2326
+ sampleRate,
2327
+ numberOfChannels: numOfChannels,
2328
+ getChannelData: () => new Float32Array(length2)
2329
+ };
2330
+ }
2331
+ decodeAudioData(data, success) {
2332
+ const buffer = this.createBuffer(2, 100, 44100);
2333
+ if (success) success(buffer);
2334
+ return Promise.resolve(buffer);
2335
+ }
2336
+ resume() {
2337
+ return Promise.resolve();
2338
+ }
2339
+ suspend() {
2340
+ return Promise.resolve();
2341
+ }
2342
+ close() {
2343
+ return Promise.resolve();
2344
+ }
2476
2345
  }
2346
+ global.AudioContext = MockAudioContext;
2347
+ global.webkitAudioContext = MockAudioContext;
2477
2348
  }
2478
2349
  function teardownMockAudioContext() {
2479
- if (global.AudioContext && global.AudioContext.toString().includes("class")) {
2480
- delete global.AudioContext;
2481
- delete global.window.AudioContext;
2482
- delete global.window.webkitAudioContext;
2483
- }
2350
+ delete global.AudioContext;
2351
+ delete global.webkitAudioContext;
2484
2352
  }
2485
2353
  function captureAudioEvents(context) {
2486
- return context._events || [];
2354
+ return [];
2487
2355
  }
2488
2356
 
2489
2357
  // ../../node_modules/.pnpm/gl-matrix@3.4.4/node_modules/gl-matrix/esm/common.js
@@ -2973,217 +2841,110 @@ function simulateCameraMovement(camera, input, deltaTime) {
2973
2841
  }
2974
2842
 
2975
2843
  // src/e2e/playwright.ts
2976
- import { chromium } from "playwright";
2977
- import { createServer } from "http";
2978
- import handler from "serve-handler";
2979
2844
  async function createPlaywrightTestClient(options = {}) {
2980
- let staticServer;
2981
- let clientUrl = options.clientUrl;
2982
- const rootPath = options.rootPath || process.cwd();
2983
- if (!clientUrl) {
2984
- staticServer = createServer((request, response) => {
2985
- return handler(request, response, {
2986
- public: rootPath,
2987
- cleanUrls: false,
2988
- headers: [
2989
- {
2990
- source: "**/*",
2991
- headers: [
2992
- { key: "Cache-Control", value: "no-cache" },
2993
- { key: "Access-Control-Allow-Origin", value: "*" },
2994
- { key: "Cross-Origin-Opener-Policy", value: "same-origin" },
2995
- { key: "Cross-Origin-Embedder-Policy", value: "require-corp" }
2996
- ]
2997
- }
2998
- ]
2999
- });
3000
- });
3001
- await new Promise((resolve) => {
3002
- if (!staticServer) return;
3003
- staticServer.listen(0, () => {
3004
- const addr = staticServer?.address();
3005
- const port = typeof addr === "object" ? addr?.port : 0;
3006
- clientUrl = `http://localhost:${port}`;
3007
- console.log(`Test client serving from ${rootPath} at ${clientUrl}`);
3008
- resolve();
3009
- });
3010
- });
2845
+ let playwright;
2846
+ try {
2847
+ playwright = await import("playwright");
2848
+ } catch (e) {
2849
+ throw new Error("Playwright is not installed. Please install it to use this utility.");
3011
2850
  }
3012
- const browser = await chromium.launch({
3013
- headless: options.headless ?? true,
3014
- args: [
3015
- "--use-gl=egl",
3016
- "--ignore-gpu-blocklist",
3017
- ...options.launchOptions?.args || []
3018
- ],
3019
- ...options.launchOptions
2851
+ const browser = await playwright.chromium.launch({
2852
+ headless: options.headless ?? true
3020
2853
  });
3021
- const width = options.width || 1280;
3022
- const height = options.height || 720;
3023
2854
  const context = await browser.newContext({
3024
- viewport: { width, height },
3025
- deviceScaleFactor: 1,
3026
- ...options.contextOptions
2855
+ viewport: options.viewport || { width: 1280, height: 720 }
3027
2856
  });
3028
2857
  const page = await context.newPage();
3029
- const close = async () => {
3030
- await browser.close();
3031
- if (staticServer) {
3032
- staticServer.close();
3033
- }
3034
- };
3035
- const navigate = async (url) => {
3036
- const targetUrl = url || clientUrl;
3037
- if (!targetUrl) throw new Error("No URL to navigate to");
3038
- let finalUrl = targetUrl;
3039
- if (options.serverUrl && !targetUrl.includes("connect=")) {
3040
- const separator = targetUrl.includes("?") ? "&" : "?";
3041
- finalUrl = `${targetUrl}${separator}connect=${encodeURIComponent(options.serverUrl)}`;
3042
- }
3043
- console.log(`Navigating to: ${finalUrl}`);
3044
- await page.goto(finalUrl, { waitUntil: "domcontentloaded" });
3045
- };
3046
2858
  return {
3047
- browser,
3048
- context,
3049
2859
  page,
3050
- server: staticServer,
3051
- close,
3052
- navigate,
3053
- waitForGame: async (timeout = 1e4) => {
3054
- await waitForGameReady(page, timeout);
2860
+ browser,
2861
+ async navigate(url) {
2862
+ await page.goto(url);
3055
2863
  },
3056
- injectInput: async (type, data) => {
2864
+ async waitForGame() {
2865
+ await waitForGameReady(page);
2866
+ },
2867
+ async injectInput(type, data) {
3057
2868
  await page.evaluate(({ type: type2, data: data2 }) => {
3058
- if (window.injectGameInput) window.injectGameInput(type2, data2);
2869
+ console.log("Injecting input", type2, data2);
3059
2870
  }, { type, data });
2871
+ },
2872
+ async screenshot(name) {
2873
+ return await page.screenshot({ path: `${name}.png` });
2874
+ },
2875
+ async close() {
2876
+ await browser.close();
3060
2877
  }
3061
2878
  };
3062
2879
  }
3063
2880
  async function waitForGameReady(page, timeout = 1e4) {
3064
- try {
3065
- await page.waitForFunction(() => {
3066
- return window.gameInstance && window.gameInstance.isReady;
3067
- }, null, { timeout });
3068
- } catch (e) {
3069
- await page.waitForSelector("canvas", { timeout });
3070
- }
2881
+ await page.waitForFunction(() => {
2882
+ return window.game && window.game.isRunning;
2883
+ }, { timeout });
3071
2884
  }
3072
2885
  async function captureGameState(page) {
3073
2886
  return await page.evaluate(() => {
3074
- if (window.gameInstance && window.gameInstance.getState) {
3075
- return window.gameInstance.getState();
3076
- }
3077
- return {};
2887
+ const game = window.game;
2888
+ return {
2889
+ time: game ? game.time : 0,
2890
+ entities: game && game.entities ? game.entities.length : 0
2891
+ };
3078
2892
  });
3079
2893
  }
3080
2894
 
3081
2895
  // src/e2e/network.ts
3082
- var CONDITIONS = {
3083
- "good": {
3084
- offline: false,
3085
- downloadThroughput: 10 * 1024 * 1024,
3086
- // 10 Mbps
3087
- uploadThroughput: 5 * 1024 * 1024,
3088
- // 5 Mbps
3089
- latency: 20
3090
- },
3091
- "slow": {
3092
- offline: false,
3093
- downloadThroughput: 500 * 1024,
3094
- // 500 Kbps
3095
- uploadThroughput: 500 * 1024,
3096
- latency: 400
3097
- },
3098
- "unstable": {
3099
- offline: false,
3100
- downloadThroughput: 1 * 1024 * 1024,
3101
- uploadThroughput: 1 * 1024 * 1024,
3102
- latency: 100
3103
- },
3104
- "offline": {
3105
- offline: true,
3106
- downloadThroughput: 0,
3107
- uploadThroughput: 0,
3108
- latency: 0
3109
- }
3110
- };
3111
2896
  function simulateNetworkCondition(condition) {
3112
- const config = CONDITIONS[condition];
3113
- return createCustomNetworkCondition(config.latency, 0, 0, config);
3114
- }
3115
- function createCustomNetworkCondition(latency, jitter = 0, packetLoss = 0, baseConfig) {
2897
+ switch (condition) {
2898
+ case "good":
2899
+ return { latency: 20, jitter: 5, packetLoss: 0, bandwidth: 10 * 1024 * 1024 };
2900
+ case "slow":
2901
+ return { latency: 150, jitter: 20, packetLoss: 0.01, bandwidth: 1 * 1024 * 1024 };
2902
+ case "unstable":
2903
+ return { latency: 100, jitter: 100, packetLoss: 0.05, bandwidth: 512 * 1024 };
2904
+ case "offline":
2905
+ return { latency: 0, jitter: 0, packetLoss: 1, bandwidth: 0 };
2906
+ case "custom":
2907
+ default:
2908
+ return { latency: 0, jitter: 0, packetLoss: 0, bandwidth: Infinity };
2909
+ }
2910
+ }
2911
+ function createCustomNetworkCondition(latency, jitter, packetLoss) {
3116
2912
  return {
3117
- async apply(page) {
3118
- const client = await page.context().newCDPSession(page);
3119
- await client.send("Network.enable");
3120
- await client.send("Network.emulateNetworkConditions", {
3121
- offline: baseConfig?.offline || false,
3122
- latency: latency + Math.random() * jitter,
3123
- downloadThroughput: baseConfig?.downloadThroughput || -1,
3124
- uploadThroughput: baseConfig?.uploadThroughput || -1
3125
- });
3126
- },
3127
- async clear(page) {
3128
- const client = await page.context().newCDPSession(page);
3129
- await client.send("Network.emulateNetworkConditions", {
3130
- offline: false,
3131
- latency: 0,
3132
- downloadThroughput: -1,
3133
- uploadThroughput: -1
3134
- });
3135
- }
2913
+ latency,
2914
+ jitter,
2915
+ packetLoss,
2916
+ bandwidth: Infinity
2917
+ // Default to unlimited unless specified
3136
2918
  };
3137
2919
  }
3138
- async function throttleBandwidth(page, bytesPerSecond) {
3139
- const simulator = createCustomNetworkCondition(0, 0, 0, {
3140
- offline: false,
3141
- latency: 0,
3142
- downloadThroughput: bytesPerSecond,
3143
- uploadThroughput: bytesPerSecond
3144
- });
3145
- await simulator.apply(page);
2920
+ function throttleBandwidth(bytesPerSecond) {
3146
2921
  }
3147
2922
 
3148
2923
  // src/e2e/visual.ts
3149
- import path from "path";
3150
- import fs from "fs/promises";
3151
- async function captureGameScreenshot(page, name, options = {}) {
3152
- const dir = options.dir || "__screenshots__";
3153
- const screenshotPath = path.join(dir, `${name}.png`);
3154
- await fs.mkdir(dir, { recursive: true });
3155
- return await page.screenshot({
3156
- path: screenshotPath,
3157
- fullPage: options.fullPage ?? false,
3158
- animations: "disabled",
3159
- caret: "hide"
3160
- });
3161
- }
3162
- async function compareScreenshots(baseline, current, threshold = 0.1) {
3163
- if (baseline.equals(current)) {
3164
- return { pixelDiff: 0, matched: true };
2924
+ async function captureGameScreenshot(page, name) {
2925
+ return await page.screenshot({ path: `${name}.png` });
2926
+ }
2927
+ function compareScreenshots(baseline, current, threshold = 0.01) {
2928
+ if (baseline.length !== current.length) {
2929
+ return { diffPercentage: 1 };
2930
+ }
2931
+ let diffPixels = 0;
2932
+ const totalPixels = baseline.length;
2933
+ for (let i = 0; i < baseline.length; i++) {
2934
+ if (baseline[i] !== current[i]) {
2935
+ diffPixels++;
2936
+ }
3165
2937
  }
2938
+ const diffPercentage = diffPixels / totalPixels;
3166
2939
  return {
3167
- pixelDiff: -1,
3168
- // Unknown magnitude
3169
- matched: false
2940
+ diffPercentage
2941
+ // Generating a diff image buffer would require a library like pixelmatch
3170
2942
  };
3171
2943
  }
3172
- function createVisualTestScenario(page, sceneName) {
2944
+ function createVisualTestScenario(sceneName) {
3173
2945
  return {
3174
- async capture(snapshotName) {
3175
- return await captureGameScreenshot(page, `${sceneName}-${snapshotName}`);
3176
- },
3177
- async compare(snapshotName, baselineDir) {
3178
- const name = `${sceneName}-${snapshotName}`;
3179
- const current = await captureGameScreenshot(page, name, { dir: "__screenshots__/current" });
3180
- try {
3181
- const baselinePath = path.join(baselineDir, `${name}.png`);
3182
- const baseline = await fs.readFile(baselinePath);
3183
- return await compareScreenshots(baseline, current);
3184
- } catch (e) {
3185
- return { pixelDiff: -1, matched: false };
3186
- }
2946
+ sceneName,
2947
+ setup: async () => {
3187
2948
  }
3188
2949
  };
3189
2950
  }
@@ -3214,7 +2975,6 @@ export {
3214
2975
  createMockAI,
3215
2976
  createMockAmmoItem,
3216
2977
  createMockArmorItem,
3217
- createMockAudioContext,
3218
2978
  createMockCamera,
3219
2979
  createMockCanvas,
3220
2980
  createMockCanvasContext2D,
@@ -3300,7 +3060,6 @@ export {
3300
3060
  simulateBandwidthLimit,
3301
3061
  simulateCameraMovement,
3302
3062
  simulateFrames,
3303
- simulateFramesWithMock,
3304
3063
  simulateHandshake,
3305
3064
  simulateNetworkCondition,
3306
3065
  simulatePlayerInput,
@@ -3313,6 +3072,7 @@ export {
3313
3072
  stairTrace,
3314
3073
  teardownBrowserEnvironment,
3315
3074
  teardownMockAudioContext,
3075
+ teardownNodeEnvironment,
3316
3076
  throttleBandwidth,
3317
3077
  verifySnapshotConsistency,
3318
3078
  waitForGameReady