quake2ts 0.0.562 → 0.0.563
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 +1 -1
- package/packages/test-utils/dist/index.cjs +197 -5
- package/packages/test-utils/dist/index.cjs.map +1 -1
- package/packages/test-utils/dist/index.d.cts +65 -8
- package/packages/test-utils/dist/index.d.ts +65 -8
- package/packages/test-utils/dist/index.js +191 -5
- package/packages/test-utils/dist/index.js.map +1 -1
package/package.json
CHANGED
|
@@ -35,10 +35,13 @@ __export(index_exports, {
|
|
|
35
35
|
MockTransport: () => MockTransport,
|
|
36
36
|
captureAudioEvents: () => captureAudioEvents,
|
|
37
37
|
captureCanvasDrawCalls: () => captureCanvasDrawCalls,
|
|
38
|
+
captureGameScreenshot: () => captureGameScreenshot,
|
|
38
39
|
captureGameState: () => captureGameState,
|
|
40
|
+
compareScreenshots: () => compareScreenshots,
|
|
39
41
|
createBinaryStreamMock: () => createBinaryStreamMock,
|
|
40
42
|
createBinaryWriterMock: () => createBinaryWriterMock,
|
|
41
43
|
createControlledTimer: () => createControlledTimer,
|
|
44
|
+
createCustomNetworkCondition: () => createCustomNetworkCondition,
|
|
42
45
|
createEntity: () => createEntity,
|
|
43
46
|
createEntityStateFactory: () => createEntityStateFactory,
|
|
44
47
|
createGameStateSnapshotFactory: () => createGameStateSnapshotFactory,
|
|
@@ -69,6 +72,7 @@ __export(index_exports, {
|
|
|
69
72
|
createSpawnContext: () => createSpawnContext,
|
|
70
73
|
createStorageTestScenario: () => createStorageTestScenario,
|
|
71
74
|
createTestContext: () => createTestContext,
|
|
75
|
+
createVisualTestScenario: () => createVisualTestScenario,
|
|
72
76
|
intersects: () => import_shared3.intersects,
|
|
73
77
|
ladderTrace: () => import_shared3.ladderTrace,
|
|
74
78
|
makeAxisBrush: () => makeAxisBrush,
|
|
@@ -83,9 +87,11 @@ __export(index_exports, {
|
|
|
83
87
|
setupNodeEnvironment: () => setupNodeEnvironment,
|
|
84
88
|
simulateFrames: () => simulateFrames,
|
|
85
89
|
simulateFramesWithMock: () => simulateFramesWithMock,
|
|
90
|
+
simulateNetworkCondition: () => simulateNetworkCondition,
|
|
86
91
|
stairTrace: () => import_shared3.stairTrace,
|
|
87
92
|
teardownBrowserEnvironment: () => teardownBrowserEnvironment,
|
|
88
93
|
teardownMockAudioContext: () => teardownMockAudioContext,
|
|
94
|
+
throttleBandwidth: () => throttleBandwidth,
|
|
89
95
|
waitForGameReady: () => waitForGameReady
|
|
90
96
|
});
|
|
91
97
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -1169,8 +1175,8 @@ function createMockImage(width, height, src) {
|
|
|
1169
1175
|
}
|
|
1170
1176
|
|
|
1171
1177
|
// src/setup/node.ts
|
|
1172
|
-
function setupNodeEnvironment() {
|
|
1173
|
-
if (typeof global.fetch === "undefined") {
|
|
1178
|
+
function setupNodeEnvironment(options = {}) {
|
|
1179
|
+
if (options.polyfillFetch && typeof global.fetch === "undefined") {
|
|
1174
1180
|
}
|
|
1175
1181
|
}
|
|
1176
1182
|
|
|
@@ -1199,6 +1205,61 @@ function createMockIndexedDB() {
|
|
|
1199
1205
|
return indexedDB;
|
|
1200
1206
|
}
|
|
1201
1207
|
function createStorageTestScenario(storageType = "local") {
|
|
1208
|
+
if (storageType === "indexed") {
|
|
1209
|
+
const dbName = `test-db-${Math.random().toString(36).substring(7)}`;
|
|
1210
|
+
const storeName = "test-store";
|
|
1211
|
+
const storage2 = createMockIndexedDB();
|
|
1212
|
+
return {
|
|
1213
|
+
storage: storage2,
|
|
1214
|
+
populate: async (data) => {
|
|
1215
|
+
return new Promise((resolve, reject) => {
|
|
1216
|
+
const req = storage2.open(dbName, 1);
|
|
1217
|
+
req.onupgradeneeded = (e) => {
|
|
1218
|
+
const db = e.target.result;
|
|
1219
|
+
db.createObjectStore(storeName);
|
|
1220
|
+
};
|
|
1221
|
+
req.onsuccess = (e) => {
|
|
1222
|
+
const db = e.target.result;
|
|
1223
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1224
|
+
const store = tx.objectStore(storeName);
|
|
1225
|
+
Object.entries(data).forEach(([k, v]) => store.put(v, k));
|
|
1226
|
+
tx.oncomplete = () => {
|
|
1227
|
+
db.close();
|
|
1228
|
+
resolve();
|
|
1229
|
+
};
|
|
1230
|
+
tx.onerror = () => reject(tx.error);
|
|
1231
|
+
};
|
|
1232
|
+
req.onerror = () => reject(req.error);
|
|
1233
|
+
});
|
|
1234
|
+
},
|
|
1235
|
+
verify: async (key, value) => {
|
|
1236
|
+
return new Promise((resolve, reject) => {
|
|
1237
|
+
const req = storage2.open(dbName, 1);
|
|
1238
|
+
req.onsuccess = (e) => {
|
|
1239
|
+
const db = e.target.result;
|
|
1240
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
1241
|
+
db.close();
|
|
1242
|
+
resolve(false);
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
const tx = db.transaction(storeName, "readonly");
|
|
1246
|
+
const store = tx.objectStore(storeName);
|
|
1247
|
+
const getReq = store.get(key);
|
|
1248
|
+
getReq.onsuccess = () => {
|
|
1249
|
+
const result = getReq.result === value;
|
|
1250
|
+
db.close();
|
|
1251
|
+
resolve(result);
|
|
1252
|
+
};
|
|
1253
|
+
getReq.onerror = () => {
|
|
1254
|
+
db.close();
|
|
1255
|
+
resolve(false);
|
|
1256
|
+
};
|
|
1257
|
+
};
|
|
1258
|
+
req.onerror = () => reject(req.error);
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1202
1263
|
const storage = storageType === "local" ? createMockLocalStorage() : createMockSessionStorage();
|
|
1203
1264
|
return {
|
|
1204
1265
|
storage,
|
|
@@ -1213,7 +1274,7 @@ function createStorageTestScenario(storageType = "local") {
|
|
|
1213
1274
|
|
|
1214
1275
|
// src/setup/audio.ts
|
|
1215
1276
|
function createMockAudioContext() {
|
|
1216
|
-
|
|
1277
|
+
const context = {
|
|
1217
1278
|
createGain: () => ({
|
|
1218
1279
|
connect: () => {
|
|
1219
1280
|
},
|
|
@@ -1262,8 +1323,23 @@ function createMockAudioContext() {
|
|
|
1262
1323
|
sampleRate,
|
|
1263
1324
|
numberOfChannels: channels,
|
|
1264
1325
|
getChannelData: () => new Float32Array(length)
|
|
1265
|
-
})
|
|
1326
|
+
}),
|
|
1327
|
+
// Helper to track events if needed
|
|
1328
|
+
_events: []
|
|
1266
1329
|
};
|
|
1330
|
+
return new Proxy(context, {
|
|
1331
|
+
get(target, prop, receiver) {
|
|
1332
|
+
if (prop === "_events") return target._events;
|
|
1333
|
+
const value = Reflect.get(target, prop, receiver);
|
|
1334
|
+
if (typeof value === "function") {
|
|
1335
|
+
return (...args) => {
|
|
1336
|
+
target._events.push({ type: String(prop), args });
|
|
1337
|
+
return Reflect.apply(value, target, args);
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
return value;
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1267
1343
|
}
|
|
1268
1344
|
function setupMockAudioContext() {
|
|
1269
1345
|
if (typeof global.AudioContext === "undefined" && typeof global.window !== "undefined") {
|
|
@@ -1284,7 +1360,7 @@ function teardownMockAudioContext() {
|
|
|
1284
1360
|
}
|
|
1285
1361
|
}
|
|
1286
1362
|
function captureAudioEvents(context) {
|
|
1287
|
-
return [];
|
|
1363
|
+
return context._events || [];
|
|
1288
1364
|
}
|
|
1289
1365
|
|
|
1290
1366
|
// src/setup/timing.ts
|
|
@@ -1576,6 +1652,116 @@ async function captureGameState(page) {
|
|
|
1576
1652
|
return {};
|
|
1577
1653
|
});
|
|
1578
1654
|
}
|
|
1655
|
+
|
|
1656
|
+
// src/e2e/network.ts
|
|
1657
|
+
var CONDITIONS = {
|
|
1658
|
+
"good": {
|
|
1659
|
+
offline: false,
|
|
1660
|
+
downloadThroughput: 10 * 1024 * 1024,
|
|
1661
|
+
// 10 Mbps
|
|
1662
|
+
uploadThroughput: 5 * 1024 * 1024,
|
|
1663
|
+
// 5 Mbps
|
|
1664
|
+
latency: 20
|
|
1665
|
+
},
|
|
1666
|
+
"slow": {
|
|
1667
|
+
offline: false,
|
|
1668
|
+
downloadThroughput: 500 * 1024,
|
|
1669
|
+
// 500 Kbps
|
|
1670
|
+
uploadThroughput: 500 * 1024,
|
|
1671
|
+
latency: 400
|
|
1672
|
+
},
|
|
1673
|
+
"unstable": {
|
|
1674
|
+
offline: false,
|
|
1675
|
+
downloadThroughput: 1 * 1024 * 1024,
|
|
1676
|
+
uploadThroughput: 1 * 1024 * 1024,
|
|
1677
|
+
latency: 100
|
|
1678
|
+
},
|
|
1679
|
+
"offline": {
|
|
1680
|
+
offline: true,
|
|
1681
|
+
downloadThroughput: 0,
|
|
1682
|
+
uploadThroughput: 0,
|
|
1683
|
+
latency: 0
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
function simulateNetworkCondition(condition) {
|
|
1687
|
+
const config = CONDITIONS[condition];
|
|
1688
|
+
return createCustomNetworkCondition(config.latency, 0, 0, config);
|
|
1689
|
+
}
|
|
1690
|
+
function createCustomNetworkCondition(latency, jitter = 0, packetLoss = 0, baseConfig) {
|
|
1691
|
+
return {
|
|
1692
|
+
async apply(page) {
|
|
1693
|
+
const client = await page.context().newCDPSession(page);
|
|
1694
|
+
await client.send("Network.enable");
|
|
1695
|
+
await client.send("Network.emulateNetworkConditions", {
|
|
1696
|
+
offline: baseConfig?.offline || false,
|
|
1697
|
+
latency: latency + Math.random() * jitter,
|
|
1698
|
+
downloadThroughput: baseConfig?.downloadThroughput || -1,
|
|
1699
|
+
uploadThroughput: baseConfig?.uploadThroughput || -1
|
|
1700
|
+
});
|
|
1701
|
+
},
|
|
1702
|
+
async clear(page) {
|
|
1703
|
+
const client = await page.context().newCDPSession(page);
|
|
1704
|
+
await client.send("Network.emulateNetworkConditions", {
|
|
1705
|
+
offline: false,
|
|
1706
|
+
latency: 0,
|
|
1707
|
+
downloadThroughput: -1,
|
|
1708
|
+
uploadThroughput: -1
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
async function throttleBandwidth(page, bytesPerSecond) {
|
|
1714
|
+
const simulator = createCustomNetworkCondition(0, 0, 0, {
|
|
1715
|
+
offline: false,
|
|
1716
|
+
latency: 0,
|
|
1717
|
+
downloadThroughput: bytesPerSecond,
|
|
1718
|
+
uploadThroughput: bytesPerSecond
|
|
1719
|
+
});
|
|
1720
|
+
await simulator.apply(page);
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
// src/e2e/visual.ts
|
|
1724
|
+
var import_path = __toESM(require("path"), 1);
|
|
1725
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
1726
|
+
async function captureGameScreenshot(page, name, options = {}) {
|
|
1727
|
+
const dir = options.dir || "__screenshots__";
|
|
1728
|
+
const screenshotPath = import_path.default.join(dir, `${name}.png`);
|
|
1729
|
+
await import_promises.default.mkdir(dir, { recursive: true });
|
|
1730
|
+
return await page.screenshot({
|
|
1731
|
+
path: screenshotPath,
|
|
1732
|
+
fullPage: options.fullPage ?? false,
|
|
1733
|
+
animations: "disabled",
|
|
1734
|
+
caret: "hide"
|
|
1735
|
+
});
|
|
1736
|
+
}
|
|
1737
|
+
async function compareScreenshots(baseline, current, threshold = 0.1) {
|
|
1738
|
+
if (baseline.equals(current)) {
|
|
1739
|
+
return { pixelDiff: 0, matched: true };
|
|
1740
|
+
}
|
|
1741
|
+
return {
|
|
1742
|
+
pixelDiff: -1,
|
|
1743
|
+
// Unknown magnitude
|
|
1744
|
+
matched: false
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1747
|
+
function createVisualTestScenario(page, sceneName) {
|
|
1748
|
+
return {
|
|
1749
|
+
async capture(snapshotName) {
|
|
1750
|
+
return await captureGameScreenshot(page, `${sceneName}-${snapshotName}`);
|
|
1751
|
+
},
|
|
1752
|
+
async compare(snapshotName, baselineDir) {
|
|
1753
|
+
const name = `${sceneName}-${snapshotName}`;
|
|
1754
|
+
const current = await captureGameScreenshot(page, name, { dir: "__screenshots__/current" });
|
|
1755
|
+
try {
|
|
1756
|
+
const baselinePath = import_path.default.join(baselineDir, `${name}.png`);
|
|
1757
|
+
const baseline = await import_promises.default.readFile(baselinePath);
|
|
1758
|
+
return await compareScreenshots(baseline, current);
|
|
1759
|
+
} catch (e) {
|
|
1760
|
+
return { pixelDiff: -1, matched: false };
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1579
1765
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1580
1766
|
0 && (module.exports = {
|
|
1581
1767
|
InputInjector,
|
|
@@ -1583,10 +1769,13 @@ async function captureGameState(page) {
|
|
|
1583
1769
|
MockTransport,
|
|
1584
1770
|
captureAudioEvents,
|
|
1585
1771
|
captureCanvasDrawCalls,
|
|
1772
|
+
captureGameScreenshot,
|
|
1586
1773
|
captureGameState,
|
|
1774
|
+
compareScreenshots,
|
|
1587
1775
|
createBinaryStreamMock,
|
|
1588
1776
|
createBinaryWriterMock,
|
|
1589
1777
|
createControlledTimer,
|
|
1778
|
+
createCustomNetworkCondition,
|
|
1590
1779
|
createEntity,
|
|
1591
1780
|
createEntityStateFactory,
|
|
1592
1781
|
createGameStateSnapshotFactory,
|
|
@@ -1617,6 +1806,7 @@ async function captureGameState(page) {
|
|
|
1617
1806
|
createSpawnContext,
|
|
1618
1807
|
createStorageTestScenario,
|
|
1619
1808
|
createTestContext,
|
|
1809
|
+
createVisualTestScenario,
|
|
1620
1810
|
intersects,
|
|
1621
1811
|
ladderTrace,
|
|
1622
1812
|
makeAxisBrush,
|
|
@@ -1631,9 +1821,11 @@ async function captureGameState(page) {
|
|
|
1631
1821
|
setupNodeEnvironment,
|
|
1632
1822
|
simulateFrames,
|
|
1633
1823
|
simulateFramesWithMock,
|
|
1824
|
+
simulateNetworkCondition,
|
|
1634
1825
|
stairTrace,
|
|
1635
1826
|
teardownBrowserEnvironment,
|
|
1636
1827
|
teardownMockAudioContext,
|
|
1828
|
+
throttleBandwidth,
|
|
1637
1829
|
waitForGameReady
|
|
1638
1830
|
});
|
|
1639
1831
|
//# sourceMappingURL=index.cjs.map
|