quake2ts 0.0.556 → 0.0.557
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/client/dist/browser/index.global.js +17 -17
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/client/dist/cjs/index.cjs +4607 -2885
- package/packages/client/dist/cjs/index.cjs.map +1 -1
- package/packages/client/dist/esm/index.js +4607 -2885
- package/packages/client/dist/esm/index.js.map +1 -1
- package/packages/engine/dist/cjs/index.cjs +2256 -534
- package/packages/engine/dist/cjs/index.cjs.map +1 -1
- package/packages/engine/dist/esm/index.js +2266 -538
- package/packages/engine/dist/esm/index.js.map +1 -1
- package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/engine/dist/types/assets/visibilityAnalyzer.d.ts +7 -2
- package/packages/engine/dist/types/assets/visibilityAnalyzer.d.ts.map +1 -1
- package/packages/test-utils/dist/index.cjs +808 -194
- package/packages/test-utils/dist/index.cjs.map +1 -1
- package/packages/test-utils/dist/index.d.cts +220 -1
- package/packages/test-utils/dist/index.d.ts +220 -1
- package/packages/test-utils/dist/index.js +771 -193
- package/packages/test-utils/dist/index.js.map +1 -1
|
@@ -395,123 +395,99 @@ function createEntity() {
|
|
|
395
395
|
import { JSDOM } from "jsdom";
|
|
396
396
|
import { Canvas, Image, ImageData } from "@napi-rs/canvas";
|
|
397
397
|
import "fake-indexeddb/auto";
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
global.DragEvent = dom.window.DragEvent;
|
|
412
|
-
global.MouseEvent = dom.window.MouseEvent;
|
|
413
|
-
global.KeyboardEvent = dom.window.KeyboardEvent;
|
|
414
|
-
global.FocusEvent = dom.window.FocusEvent;
|
|
415
|
-
global.WheelEvent = dom.window.WheelEvent;
|
|
416
|
-
global.InputEvent = dom.window.InputEvent;
|
|
417
|
-
global.UIEvent = dom.window.UIEvent;
|
|
418
|
-
try {
|
|
419
|
-
global.localStorage = dom.window.localStorage;
|
|
420
|
-
} catch (e) {
|
|
421
|
-
}
|
|
422
|
-
if (!global.localStorage) {
|
|
423
|
-
const storage = /* @__PURE__ */ new Map();
|
|
424
|
-
global.localStorage = {
|
|
425
|
-
getItem: (key) => storage.get(key) || null,
|
|
426
|
-
setItem: (key, value) => storage.set(key, value),
|
|
427
|
-
removeItem: (key) => storage.delete(key),
|
|
428
|
-
clear: () => storage.clear(),
|
|
429
|
-
key: (index) => Array.from(storage.keys())[index] || null,
|
|
430
|
-
get length() {
|
|
431
|
-
return storage.size;
|
|
398
|
+
|
|
399
|
+
// src/e2e/input.ts
|
|
400
|
+
var MockPointerLock = class {
|
|
401
|
+
static setup(doc) {
|
|
402
|
+
let _pointerLockElement = null;
|
|
403
|
+
Object.defineProperty(doc, "pointerLockElement", {
|
|
404
|
+
get: () => _pointerLockElement,
|
|
405
|
+
configurable: true
|
|
406
|
+
});
|
|
407
|
+
doc.exitPointerLock = () => {
|
|
408
|
+
if (_pointerLockElement) {
|
|
409
|
+
_pointerLockElement = null;
|
|
410
|
+
doc.dispatchEvent(new Event("pointerlockchange"));
|
|
432
411
|
}
|
|
433
412
|
};
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
if (tagName.toLowerCase() === "canvas") {
|
|
438
|
-
const napiCanvas = new Canvas(300, 150);
|
|
439
|
-
const domCanvas = originalCreateElement("canvas", options2);
|
|
440
|
-
Object.defineProperty(domCanvas, "width", {
|
|
441
|
-
get: () => napiCanvas.width,
|
|
442
|
-
set: (value) => {
|
|
443
|
-
napiCanvas.width = value;
|
|
444
|
-
},
|
|
445
|
-
enumerable: true,
|
|
446
|
-
configurable: true
|
|
447
|
-
});
|
|
448
|
-
Object.defineProperty(domCanvas, "height", {
|
|
449
|
-
get: () => napiCanvas.height,
|
|
450
|
-
set: (value) => {
|
|
451
|
-
napiCanvas.height = value;
|
|
452
|
-
},
|
|
453
|
-
enumerable: true,
|
|
454
|
-
configurable: true
|
|
455
|
-
});
|
|
456
|
-
const originalGetContext = domCanvas.getContext.bind(domCanvas);
|
|
457
|
-
domCanvas.getContext = function(contextId, options3) {
|
|
458
|
-
if (contextId === "2d") {
|
|
459
|
-
return napiCanvas.getContext("2d", options3);
|
|
460
|
-
}
|
|
461
|
-
if (contextId === "webgl" || contextId === "webgl2") {
|
|
462
|
-
return originalGetContext(contextId, options3);
|
|
463
|
-
}
|
|
464
|
-
return napiCanvas.getContext(contextId, options3);
|
|
465
|
-
};
|
|
466
|
-
domCanvas.__napiCanvas = napiCanvas;
|
|
467
|
-
return domCanvas;
|
|
468
|
-
}
|
|
469
|
-
return originalCreateElement(tagName, options2);
|
|
470
|
-
};
|
|
471
|
-
global.Image = Image;
|
|
472
|
-
global.ImageData = ImageData;
|
|
473
|
-
if (typeof global.createImageBitmap === "undefined") {
|
|
474
|
-
global.createImageBitmap = async function(image, _options) {
|
|
475
|
-
if (image && typeof image.width === "number" && typeof image.height === "number") {
|
|
476
|
-
const canvas2 = new Canvas(image.width, image.height);
|
|
477
|
-
const ctx = canvas2.getContext("2d");
|
|
478
|
-
if (image.data) {
|
|
479
|
-
ctx.putImageData(image, 0, 0);
|
|
480
|
-
}
|
|
481
|
-
return canvas2;
|
|
482
|
-
}
|
|
483
|
-
const canvas = new Canvas(100, 100);
|
|
484
|
-
return canvas;
|
|
413
|
+
global.HTMLElement.prototype.requestPointerLock = function() {
|
|
414
|
+
_pointerLockElement = this;
|
|
415
|
+
doc.dispatchEvent(new Event("pointerlockchange"));
|
|
485
416
|
};
|
|
486
417
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
418
|
+
};
|
|
419
|
+
var InputInjector = class {
|
|
420
|
+
constructor(doc, win) {
|
|
421
|
+
this.doc = doc;
|
|
422
|
+
this.win = win;
|
|
491
423
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
424
|
+
keyDown(key, code) {
|
|
425
|
+
const event = new this.win.KeyboardEvent("keydown", {
|
|
426
|
+
key,
|
|
427
|
+
code: code || key,
|
|
428
|
+
bubbles: true,
|
|
429
|
+
cancelable: true,
|
|
430
|
+
view: this.win
|
|
431
|
+
});
|
|
432
|
+
this.doc.dispatchEvent(event);
|
|
496
433
|
}
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
delete global.ImageData;
|
|
507
|
-
delete global.createImageBitmap;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// src/setup/node.ts
|
|
511
|
-
function setupNodeEnvironment() {
|
|
512
|
-
if (typeof global.fetch === "undefined") {
|
|
434
|
+
keyUp(key, code) {
|
|
435
|
+
const event = new this.win.KeyboardEvent("keyup", {
|
|
436
|
+
key,
|
|
437
|
+
code: code || key,
|
|
438
|
+
bubbles: true,
|
|
439
|
+
cancelable: true,
|
|
440
|
+
view: this.win
|
|
441
|
+
});
|
|
442
|
+
this.doc.dispatchEvent(event);
|
|
513
443
|
}
|
|
514
|
-
|
|
444
|
+
mouseMove(movementX, movementY, clientX = 0, clientY = 0) {
|
|
445
|
+
const event = new this.win.MouseEvent("mousemove", {
|
|
446
|
+
bubbles: true,
|
|
447
|
+
cancelable: true,
|
|
448
|
+
view: this.win,
|
|
449
|
+
clientX,
|
|
450
|
+
clientY,
|
|
451
|
+
movementX,
|
|
452
|
+
// Note: JSDOM might not support this standard property fully on event init
|
|
453
|
+
movementY
|
|
454
|
+
});
|
|
455
|
+
Object.defineProperty(event, "movementX", { value: movementX });
|
|
456
|
+
Object.defineProperty(event, "movementY", { value: movementY });
|
|
457
|
+
const target = this.doc.pointerLockElement || this.doc;
|
|
458
|
+
target.dispatchEvent(event);
|
|
459
|
+
}
|
|
460
|
+
mouseDown(button = 0) {
|
|
461
|
+
const event = new this.win.MouseEvent("mousedown", {
|
|
462
|
+
button,
|
|
463
|
+
bubbles: true,
|
|
464
|
+
cancelable: true,
|
|
465
|
+
view: this.win
|
|
466
|
+
});
|
|
467
|
+
const target = this.doc.pointerLockElement || this.doc;
|
|
468
|
+
target.dispatchEvent(event);
|
|
469
|
+
}
|
|
470
|
+
mouseUp(button = 0) {
|
|
471
|
+
const event = new this.win.MouseEvent("mouseup", {
|
|
472
|
+
button,
|
|
473
|
+
bubbles: true,
|
|
474
|
+
cancelable: true,
|
|
475
|
+
view: this.win
|
|
476
|
+
});
|
|
477
|
+
const target = this.doc.pointerLockElement || this.doc;
|
|
478
|
+
target.dispatchEvent(event);
|
|
479
|
+
}
|
|
480
|
+
wheel(deltaY) {
|
|
481
|
+
const event = new this.win.WheelEvent("wheel", {
|
|
482
|
+
deltaY,
|
|
483
|
+
bubbles: true,
|
|
484
|
+
cancelable: true,
|
|
485
|
+
view: this.win
|
|
486
|
+
});
|
|
487
|
+
const target = this.doc.pointerLockElement || this.doc;
|
|
488
|
+
target.dispatchEvent(event);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
515
491
|
|
|
516
492
|
// src/setup/webgl.ts
|
|
517
493
|
function createMockWebGL2Context(canvas) {
|
|
@@ -637,113 +613,708 @@ function createMockWebGL2Context(canvas) {
|
|
|
637
613
|
return gl;
|
|
638
614
|
}
|
|
639
615
|
|
|
640
|
-
// src/
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
616
|
+
// src/setup/browser.ts
|
|
617
|
+
function setupBrowserEnvironment(options = {}) {
|
|
618
|
+
const {
|
|
619
|
+
url = "http://localhost",
|
|
620
|
+
pretendToBeVisual = true,
|
|
621
|
+
resources = void 0,
|
|
622
|
+
enableWebGL2 = false,
|
|
623
|
+
enablePointerLock = false
|
|
624
|
+
} = options;
|
|
625
|
+
const dom = new JSDOM("<!DOCTYPE html><html><head></head><body></body></html>", {
|
|
626
|
+
url,
|
|
627
|
+
pretendToBeVisual,
|
|
628
|
+
resources
|
|
629
|
+
});
|
|
630
|
+
global.window = dom.window;
|
|
631
|
+
global.document = dom.window.document;
|
|
632
|
+
try {
|
|
633
|
+
global.navigator = dom.window.navigator;
|
|
634
|
+
} catch (e) {
|
|
635
|
+
try {
|
|
636
|
+
Object.defineProperty(global, "navigator", {
|
|
637
|
+
value: dom.window.navigator,
|
|
638
|
+
writable: true,
|
|
639
|
+
configurable: true
|
|
640
|
+
});
|
|
641
|
+
} catch (e2) {
|
|
642
|
+
console.warn("Could not assign global.navigator, skipping.");
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
global.location = dom.window.location;
|
|
646
|
+
global.HTMLElement = dom.window.HTMLElement;
|
|
647
|
+
global.HTMLCanvasElement = dom.window.HTMLCanvasElement;
|
|
648
|
+
global.Event = dom.window.Event;
|
|
649
|
+
global.CustomEvent = dom.window.CustomEvent;
|
|
650
|
+
global.DragEvent = dom.window.DragEvent;
|
|
651
|
+
global.MouseEvent = dom.window.MouseEvent;
|
|
652
|
+
global.KeyboardEvent = dom.window.KeyboardEvent;
|
|
653
|
+
global.FocusEvent = dom.window.FocusEvent;
|
|
654
|
+
global.WheelEvent = dom.window.WheelEvent;
|
|
655
|
+
global.InputEvent = dom.window.InputEvent;
|
|
656
|
+
global.UIEvent = dom.window.UIEvent;
|
|
657
|
+
try {
|
|
658
|
+
global.localStorage = dom.window.localStorage;
|
|
659
|
+
} catch (e) {
|
|
660
|
+
}
|
|
661
|
+
if (!global.localStorage) {
|
|
662
|
+
const storage = /* @__PURE__ */ new Map();
|
|
663
|
+
global.localStorage = {
|
|
664
|
+
getItem: (key) => storage.get(key) || null,
|
|
665
|
+
setItem: (key, value) => storage.set(key, value),
|
|
666
|
+
removeItem: (key) => storage.delete(key),
|
|
667
|
+
clear: () => storage.clear(),
|
|
668
|
+
key: (index) => Array.from(storage.keys())[index] || null,
|
|
669
|
+
get length() {
|
|
670
|
+
return storage.size;
|
|
652
671
|
}
|
|
653
672
|
};
|
|
654
|
-
global.HTMLElement.prototype.requestPointerLock = function() {
|
|
655
|
-
_pointerLockElement = this;
|
|
656
|
-
doc.dispatchEvent(new Event("pointerlockchange"));
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
};
|
|
660
|
-
var InputInjector = class {
|
|
661
|
-
constructor(doc, win) {
|
|
662
|
-
this.doc = doc;
|
|
663
|
-
this.win = win;
|
|
664
673
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
+
const originalCreateElement = document.createElement.bind(document);
|
|
675
|
+
document.createElement = function(tagName, options2) {
|
|
676
|
+
if (tagName.toLowerCase() === "canvas") {
|
|
677
|
+
const napiCanvas = new Canvas(300, 150);
|
|
678
|
+
const domCanvas = originalCreateElement("canvas", options2);
|
|
679
|
+
Object.defineProperty(domCanvas, "width", {
|
|
680
|
+
get: () => napiCanvas.width,
|
|
681
|
+
set: (value) => {
|
|
682
|
+
napiCanvas.width = value;
|
|
683
|
+
},
|
|
684
|
+
enumerable: true,
|
|
685
|
+
configurable: true
|
|
686
|
+
});
|
|
687
|
+
Object.defineProperty(domCanvas, "height", {
|
|
688
|
+
get: () => napiCanvas.height,
|
|
689
|
+
set: (value) => {
|
|
690
|
+
napiCanvas.height = value;
|
|
691
|
+
},
|
|
692
|
+
enumerable: true,
|
|
693
|
+
configurable: true
|
|
694
|
+
});
|
|
695
|
+
const originalGetContext = domCanvas.getContext.bind(domCanvas);
|
|
696
|
+
domCanvas.getContext = function(contextId, options3) {
|
|
697
|
+
if (contextId === "2d") {
|
|
698
|
+
return napiCanvas.getContext("2d", options3);
|
|
699
|
+
}
|
|
700
|
+
if (enableWebGL2 && contextId === "webgl2") {
|
|
701
|
+
return createMockWebGL2Context(domCanvas);
|
|
702
|
+
}
|
|
703
|
+
if (contextId === "webgl" || contextId === "webgl2") {
|
|
704
|
+
return originalGetContext(contextId, options3);
|
|
705
|
+
}
|
|
706
|
+
return napiCanvas.getContext(contextId, options3);
|
|
707
|
+
};
|
|
708
|
+
domCanvas.__napiCanvas = napiCanvas;
|
|
709
|
+
return domCanvas;
|
|
710
|
+
}
|
|
711
|
+
return originalCreateElement(tagName, options2);
|
|
712
|
+
};
|
|
713
|
+
if (enableWebGL2) {
|
|
714
|
+
const originalProtoGetContext = global.HTMLCanvasElement.prototype.getContext;
|
|
715
|
+
global.HTMLCanvasElement.prototype.getContext = function(contextId, options2) {
|
|
716
|
+
if (contextId === "webgl2") {
|
|
717
|
+
return createMockWebGL2Context(this);
|
|
718
|
+
}
|
|
719
|
+
return originalProtoGetContext.call(this, contextId, options2);
|
|
720
|
+
};
|
|
674
721
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
722
|
+
global.Image = Image;
|
|
723
|
+
global.ImageData = ImageData;
|
|
724
|
+
if (typeof global.createImageBitmap === "undefined") {
|
|
725
|
+
global.createImageBitmap = async function(image, _options) {
|
|
726
|
+
if (image && typeof image.width === "number" && typeof image.height === "number") {
|
|
727
|
+
const canvas2 = new Canvas(image.width, image.height);
|
|
728
|
+
const ctx = canvas2.getContext("2d");
|
|
729
|
+
if (image.data) {
|
|
730
|
+
ctx.putImageData(image, 0, 0);
|
|
731
|
+
}
|
|
732
|
+
return canvas2;
|
|
733
|
+
}
|
|
734
|
+
const canvas = new Canvas(100, 100);
|
|
735
|
+
return canvas;
|
|
736
|
+
};
|
|
684
737
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
view: this.win,
|
|
690
|
-
clientX,
|
|
691
|
-
clientY,
|
|
692
|
-
movementX,
|
|
693
|
-
// Note: JSDOM might not support this standard property fully on event init
|
|
694
|
-
movementY
|
|
695
|
-
});
|
|
696
|
-
Object.defineProperty(event, "movementX", { value: movementX });
|
|
697
|
-
Object.defineProperty(event, "movementY", { value: movementY });
|
|
698
|
-
const target = this.doc.pointerLockElement || this.doc;
|
|
699
|
-
target.dispatchEvent(event);
|
|
738
|
+
if (typeof global.btoa === "undefined") {
|
|
739
|
+
global.btoa = function(str) {
|
|
740
|
+
return Buffer.from(str, "binary").toString("base64");
|
|
741
|
+
};
|
|
700
742
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
cancelable: true,
|
|
706
|
-
view: this.win
|
|
707
|
-
});
|
|
708
|
-
const target = this.doc.pointerLockElement || this.doc;
|
|
709
|
-
target.dispatchEvent(event);
|
|
743
|
+
if (typeof global.atob === "undefined") {
|
|
744
|
+
global.atob = function(str) {
|
|
745
|
+
return Buffer.from(str, "base64").toString("binary");
|
|
746
|
+
};
|
|
710
747
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
button,
|
|
714
|
-
bubbles: true,
|
|
715
|
-
cancelable: true,
|
|
716
|
-
view: this.win
|
|
717
|
-
});
|
|
718
|
-
const target = this.doc.pointerLockElement || this.doc;
|
|
719
|
-
target.dispatchEvent(event);
|
|
748
|
+
if (enablePointerLock) {
|
|
749
|
+
MockPointerLock.setup(global.document);
|
|
720
750
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
751
|
+
if (typeof global.requestAnimationFrame === "undefined") {
|
|
752
|
+
let lastTime = 0;
|
|
753
|
+
global.requestAnimationFrame = (callback) => {
|
|
754
|
+
const currTime = Date.now();
|
|
755
|
+
const timeToCall = Math.max(0, 16 - (currTime - lastTime));
|
|
756
|
+
const id = setTimeout(() => {
|
|
757
|
+
callback(currTime + timeToCall);
|
|
758
|
+
}, timeToCall);
|
|
759
|
+
lastTime = currTime + timeToCall;
|
|
760
|
+
return id;
|
|
761
|
+
};
|
|
762
|
+
global.cancelAnimationFrame = (id) => {
|
|
763
|
+
clearTimeout(id);
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
function teardownBrowserEnvironment() {
|
|
768
|
+
delete global.window;
|
|
769
|
+
delete global.document;
|
|
770
|
+
delete global.navigator;
|
|
771
|
+
delete global.localStorage;
|
|
772
|
+
delete global.location;
|
|
773
|
+
delete global.HTMLElement;
|
|
774
|
+
delete global.HTMLCanvasElement;
|
|
775
|
+
delete global.Image;
|
|
776
|
+
delete global.ImageData;
|
|
777
|
+
delete global.createImageBitmap;
|
|
778
|
+
delete global.Event;
|
|
779
|
+
delete global.CustomEvent;
|
|
780
|
+
delete global.DragEvent;
|
|
781
|
+
delete global.MouseEvent;
|
|
782
|
+
delete global.KeyboardEvent;
|
|
783
|
+
delete global.FocusEvent;
|
|
784
|
+
delete global.WheelEvent;
|
|
785
|
+
delete global.InputEvent;
|
|
786
|
+
delete global.UIEvent;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// src/setup/node.ts
|
|
790
|
+
function setupNodeEnvironment() {
|
|
791
|
+
if (typeof global.fetch === "undefined") {
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
// src/setup/canvas.ts
|
|
796
|
+
import { Canvas as Canvas2, Image as Image2, ImageData as ImageData2 } from "@napi-rs/canvas";
|
|
797
|
+
function createMockCanvas(width = 300, height = 150) {
|
|
798
|
+
if (typeof document !== "undefined" && document.createElement) {
|
|
799
|
+
const canvas2 = document.createElement("canvas");
|
|
800
|
+
canvas2.width = width;
|
|
801
|
+
canvas2.height = height;
|
|
802
|
+
return canvas2;
|
|
803
|
+
}
|
|
804
|
+
const canvas = new Canvas2(width, height);
|
|
805
|
+
const originalGetContext = canvas.getContext.bind(canvas);
|
|
806
|
+
canvas.getContext = function(contextId, options) {
|
|
807
|
+
if (contextId === "webgl2") {
|
|
808
|
+
return createMockWebGL2Context(canvas);
|
|
809
|
+
}
|
|
810
|
+
if (contextId === "2d") {
|
|
811
|
+
return originalGetContext("2d", options);
|
|
812
|
+
}
|
|
813
|
+
return originalGetContext(contextId, options);
|
|
814
|
+
};
|
|
815
|
+
return canvas;
|
|
816
|
+
}
|
|
817
|
+
function createMockCanvasContext2D(canvas) {
|
|
818
|
+
if (!canvas) {
|
|
819
|
+
canvas = createMockCanvas();
|
|
820
|
+
}
|
|
821
|
+
return canvas.getContext("2d");
|
|
822
|
+
}
|
|
823
|
+
function captureCanvasDrawCalls(context) {
|
|
824
|
+
const drawCalls = [];
|
|
825
|
+
const methodsToSpy = [
|
|
826
|
+
"fillRect",
|
|
827
|
+
"strokeRect",
|
|
828
|
+
"clearRect",
|
|
829
|
+
"fillText",
|
|
830
|
+
"strokeText",
|
|
831
|
+
"drawImage",
|
|
832
|
+
"beginPath",
|
|
833
|
+
"closePath",
|
|
834
|
+
"moveTo",
|
|
835
|
+
"lineTo",
|
|
836
|
+
"arc",
|
|
837
|
+
"arcTo",
|
|
838
|
+
"bezierCurveTo",
|
|
839
|
+
"quadraticCurveTo",
|
|
840
|
+
"stroke",
|
|
841
|
+
"fill",
|
|
842
|
+
"putImageData"
|
|
843
|
+
];
|
|
844
|
+
methodsToSpy.forEach((method) => {
|
|
845
|
+
const original = context[method];
|
|
846
|
+
if (typeof original === "function") {
|
|
847
|
+
context[method] = function(...args) {
|
|
848
|
+
drawCalls.push({ method, args });
|
|
849
|
+
return original.apply(this, args);
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
return drawCalls;
|
|
854
|
+
}
|
|
855
|
+
function createMockImageData(width, height, fillColor) {
|
|
856
|
+
const imageData = new ImageData2(width, height);
|
|
857
|
+
if (fillColor) {
|
|
858
|
+
const [r, g, b, a] = fillColor;
|
|
859
|
+
for (let i = 0; i < imageData.data.length; i += 4) {
|
|
860
|
+
imageData.data[i] = r;
|
|
861
|
+
imageData.data[i + 1] = g;
|
|
862
|
+
imageData.data[i + 2] = b;
|
|
863
|
+
imageData.data[i + 3] = a;
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return imageData;
|
|
867
|
+
}
|
|
868
|
+
function createMockImage(width, height, src) {
|
|
869
|
+
const img = new Image2();
|
|
870
|
+
if (width) img.width = width;
|
|
871
|
+
if (height) img.height = height;
|
|
872
|
+
if (src) img.src = src;
|
|
873
|
+
return img;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
// src/setup/timing.ts
|
|
877
|
+
function createMockRAF() {
|
|
878
|
+
let callbacks = [];
|
|
879
|
+
let nextId = 1;
|
|
880
|
+
let currentTime = 0;
|
|
881
|
+
const originalRAF = global.requestAnimationFrame;
|
|
882
|
+
const originalCancelRAF = global.cancelAnimationFrame;
|
|
883
|
+
const raf = (callback) => {
|
|
884
|
+
const id = nextId++;
|
|
885
|
+
callbacks.push({ id, callback });
|
|
886
|
+
return id;
|
|
887
|
+
};
|
|
888
|
+
const cancel = (id) => {
|
|
889
|
+
callbacks = callbacks.filter((cb) => cb.id !== id);
|
|
890
|
+
};
|
|
891
|
+
const mock = {
|
|
892
|
+
tick(timestamp) {
|
|
893
|
+
if (typeof timestamp !== "number") {
|
|
894
|
+
currentTime += 16.6;
|
|
895
|
+
} else {
|
|
896
|
+
currentTime = timestamp;
|
|
897
|
+
}
|
|
898
|
+
const currentCallbacks = [...callbacks];
|
|
899
|
+
callbacks = [];
|
|
900
|
+
currentCallbacks.forEach(({ callback }) => {
|
|
901
|
+
callback(currentTime);
|
|
902
|
+
});
|
|
903
|
+
},
|
|
904
|
+
advance(deltaMs = 16.6) {
|
|
905
|
+
this.tick(currentTime + deltaMs);
|
|
906
|
+
},
|
|
907
|
+
getCallbacks() {
|
|
908
|
+
return callbacks.map((c) => c.callback);
|
|
909
|
+
},
|
|
910
|
+
reset() {
|
|
911
|
+
callbacks = [];
|
|
912
|
+
nextId = 1;
|
|
913
|
+
currentTime = 0;
|
|
914
|
+
},
|
|
915
|
+
enable() {
|
|
916
|
+
global.requestAnimationFrame = raf;
|
|
917
|
+
global.cancelAnimationFrame = cancel;
|
|
918
|
+
},
|
|
919
|
+
disable() {
|
|
920
|
+
if (originalRAF) {
|
|
921
|
+
global.requestAnimationFrame = originalRAF;
|
|
922
|
+
} else {
|
|
923
|
+
delete global.requestAnimationFrame;
|
|
924
|
+
}
|
|
925
|
+
if (originalCancelRAF) {
|
|
926
|
+
global.cancelAnimationFrame = originalCancelRAF;
|
|
927
|
+
} else {
|
|
928
|
+
delete global.cancelAnimationFrame;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
return mock;
|
|
933
|
+
}
|
|
934
|
+
function createMockPerformance(startTime = 0) {
|
|
935
|
+
let currentTime = startTime;
|
|
936
|
+
const mockPerf = {
|
|
937
|
+
now: () => currentTime,
|
|
938
|
+
timeOrigin: startTime,
|
|
939
|
+
timing: {
|
|
940
|
+
navigationStart: startTime
|
|
941
|
+
},
|
|
942
|
+
// Add minimal navigation/resource timing interfaces to satisfy types if needed
|
|
943
|
+
clearMarks: () => {
|
|
944
|
+
},
|
|
945
|
+
clearMeasures: () => {
|
|
946
|
+
},
|
|
947
|
+
clearResourceTimings: () => {
|
|
948
|
+
},
|
|
949
|
+
getEntries: () => [],
|
|
950
|
+
getEntriesByName: () => [],
|
|
951
|
+
getEntriesByType: () => [],
|
|
952
|
+
mark: () => {
|
|
953
|
+
},
|
|
954
|
+
measure: () => {
|
|
955
|
+
},
|
|
956
|
+
setResourceTimingBufferSize: () => {
|
|
957
|
+
},
|
|
958
|
+
toJSON: () => ({}),
|
|
959
|
+
addEventListener: () => {
|
|
960
|
+
},
|
|
961
|
+
removeEventListener: () => {
|
|
962
|
+
},
|
|
963
|
+
dispatchEvent: () => true
|
|
964
|
+
};
|
|
965
|
+
mockPerf.advance = (deltaMs) => {
|
|
966
|
+
currentTime += deltaMs;
|
|
967
|
+
};
|
|
968
|
+
mockPerf.setTime = (time) => {
|
|
969
|
+
currentTime = time;
|
|
970
|
+
};
|
|
971
|
+
return mockPerf;
|
|
972
|
+
}
|
|
973
|
+
function simulateFrames(count, frameTimeMs = 16.6, callback) {
|
|
974
|
+
const raf = global.requestAnimationFrame;
|
|
975
|
+
if (!raf) return;
|
|
976
|
+
}
|
|
977
|
+
function simulateFramesWithMock(mock, count, frameTimeMs = 16.6, callback) {
|
|
978
|
+
for (let i = 0; i < count; i++) {
|
|
979
|
+
if (callback) callback(i);
|
|
980
|
+
mock.advance(frameTimeMs);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/setup/storage.ts
|
|
985
|
+
import "fake-indexeddb/auto";
|
|
986
|
+
function createMockLocalStorage(initialData = {}) {
|
|
987
|
+
const storage = new Map(Object.entries(initialData));
|
|
988
|
+
return {
|
|
989
|
+
getItem: (key) => storage.get(key) || null,
|
|
990
|
+
setItem: (key, value) => storage.set(key, value),
|
|
991
|
+
removeItem: (key) => storage.delete(key),
|
|
992
|
+
clear: () => storage.clear(),
|
|
993
|
+
key: (index) => Array.from(storage.keys())[index] || null,
|
|
994
|
+
get length() {
|
|
995
|
+
return storage.size;
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
function createMockSessionStorage(initialData = {}) {
|
|
1000
|
+
return createMockLocalStorage(initialData);
|
|
1001
|
+
}
|
|
1002
|
+
function createMockIndexedDB() {
|
|
1003
|
+
if (typeof indexedDB === "undefined") {
|
|
1004
|
+
throw new Error("IndexedDB mock not found. Ensure fake-indexeddb is loaded.");
|
|
1005
|
+
}
|
|
1006
|
+
return indexedDB;
|
|
1007
|
+
}
|
|
1008
|
+
function createStorageTestScenario(storageType = "local") {
|
|
1009
|
+
const storage = storageType === "local" ? createMockLocalStorage() : createMockSessionStorage();
|
|
1010
|
+
return {
|
|
1011
|
+
storage,
|
|
1012
|
+
populate(data) {
|
|
1013
|
+
Object.entries(data).forEach(([k, v]) => storage.setItem(k, v));
|
|
1014
|
+
},
|
|
1015
|
+
verify(key, value) {
|
|
1016
|
+
return storage.getItem(key) === value;
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// src/setup/audio.ts
|
|
1022
|
+
function createMockAudioContext() {
|
|
1023
|
+
return {
|
|
1024
|
+
createGain: () => ({
|
|
1025
|
+
connect: () => {
|
|
1026
|
+
},
|
|
1027
|
+
gain: { value: 1, setValueAtTime: () => {
|
|
1028
|
+
} }
|
|
1029
|
+
}),
|
|
1030
|
+
createOscillator: () => ({
|
|
1031
|
+
connect: () => {
|
|
1032
|
+
},
|
|
1033
|
+
start: () => {
|
|
1034
|
+
},
|
|
1035
|
+
stop: () => {
|
|
1036
|
+
},
|
|
1037
|
+
frequency: { value: 440 }
|
|
1038
|
+
}),
|
|
1039
|
+
createBufferSource: () => ({
|
|
1040
|
+
connect: () => {
|
|
1041
|
+
},
|
|
1042
|
+
start: () => {
|
|
1043
|
+
},
|
|
1044
|
+
stop: () => {
|
|
1045
|
+
},
|
|
1046
|
+
buffer: null,
|
|
1047
|
+
playbackRate: { value: 1 },
|
|
1048
|
+
loop: false
|
|
1049
|
+
}),
|
|
1050
|
+
destination: {},
|
|
1051
|
+
currentTime: 0,
|
|
1052
|
+
state: "running",
|
|
1053
|
+
resume: async () => {
|
|
1054
|
+
},
|
|
1055
|
+
suspend: async () => {
|
|
1056
|
+
},
|
|
1057
|
+
close: async () => {
|
|
1058
|
+
},
|
|
1059
|
+
decodeAudioData: async (buffer) => ({
|
|
1060
|
+
duration: 1,
|
|
1061
|
+
length: 44100,
|
|
1062
|
+
sampleRate: 44100,
|
|
1063
|
+
numberOfChannels: 2,
|
|
1064
|
+
getChannelData: () => new Float32Array(44100)
|
|
1065
|
+
}),
|
|
1066
|
+
createBuffer: (channels, length, sampleRate) => ({
|
|
1067
|
+
duration: length / sampleRate,
|
|
1068
|
+
length,
|
|
1069
|
+
sampleRate,
|
|
1070
|
+
numberOfChannels: channels,
|
|
1071
|
+
getChannelData: () => new Float32Array(length)
|
|
1072
|
+
})
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
function setupMockAudioContext() {
|
|
1076
|
+
if (typeof global.AudioContext === "undefined" && typeof global.window !== "undefined") {
|
|
1077
|
+
global.AudioContext = class {
|
|
1078
|
+
constructor() {
|
|
1079
|
+
return createMockAudioContext();
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
global.window.AudioContext = global.AudioContext;
|
|
1083
|
+
global.window.webkitAudioContext = global.AudioContext;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
function teardownMockAudioContext() {
|
|
1087
|
+
if (global.AudioContext && global.AudioContext.toString().includes("class")) {
|
|
1088
|
+
delete global.AudioContext;
|
|
1089
|
+
delete global.window.AudioContext;
|
|
1090
|
+
delete global.window.webkitAudioContext;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function captureAudioEvents(context) {
|
|
1094
|
+
return [];
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
// src/e2e/playwright.ts
|
|
1098
|
+
import { chromium } from "playwright";
|
|
1099
|
+
async function createPlaywrightTestClient(options = {}) {
|
|
1100
|
+
const browser = await chromium.launch({
|
|
1101
|
+
headless: options.headless ?? true,
|
|
1102
|
+
args: options.args || [
|
|
1103
|
+
"--use-gl=egl",
|
|
1104
|
+
"--ignore-gpu-blocklist",
|
|
1105
|
+
"--no-sandbox",
|
|
1106
|
+
"--disable-setuid-sandbox"
|
|
1107
|
+
]
|
|
1108
|
+
});
|
|
1109
|
+
const context = await browser.newContext({
|
|
1110
|
+
viewport: options.viewport || { width: 1280, height: 720 },
|
|
1111
|
+
recordVideo: options.recordVideo,
|
|
1112
|
+
deviceScaleFactor: 1
|
|
1113
|
+
});
|
|
1114
|
+
const page = await context.newPage();
|
|
1115
|
+
const waitForGame = async (timeout = 1e4) => {
|
|
1116
|
+
try {
|
|
1117
|
+
await page.waitForFunction(() => {
|
|
1118
|
+
return window.game || document.querySelector("canvas");
|
|
1119
|
+
}, null, { timeout });
|
|
1120
|
+
} catch (e) {
|
|
1121
|
+
throw new Error(`Game did not initialize within ${timeout}ms`);
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
const client = {
|
|
1125
|
+
browser,
|
|
1126
|
+
context,
|
|
1127
|
+
page,
|
|
1128
|
+
async navigate(url) {
|
|
1129
|
+
await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
1130
|
+
},
|
|
1131
|
+
async waitForGame(timeout) {
|
|
1132
|
+
await waitForGame(timeout);
|
|
1133
|
+
},
|
|
1134
|
+
async injectInput(type, key) {
|
|
1135
|
+
if (type === "keydown") {
|
|
1136
|
+
await page.keyboard.down(key);
|
|
1137
|
+
} else {
|
|
1138
|
+
await page.keyboard.up(key);
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
async injectMouse(type, x = 0, y = 0, button = 0) {
|
|
1142
|
+
if (type === "move") {
|
|
1143
|
+
await page.mouse.move(x, y);
|
|
1144
|
+
} else if (type === "down") {
|
|
1145
|
+
await page.mouse.down({ button: button === 0 ? "left" : button === 2 ? "right" : "middle" });
|
|
1146
|
+
} else if (type === "up") {
|
|
1147
|
+
await page.mouse.up({ button: button === 0 ? "left" : button === 2 ? "right" : "middle" });
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
async screenshot(path2) {
|
|
1151
|
+
await page.screenshot({ path: path2 });
|
|
1152
|
+
},
|
|
1153
|
+
async close() {
|
|
1154
|
+
await browser.close();
|
|
1155
|
+
}
|
|
1156
|
+
};
|
|
1157
|
+
return client;
|
|
1158
|
+
}
|
|
1159
|
+
async function waitForGameReady(page, timeout = 1e4) {
|
|
1160
|
+
await page.waitForFunction(() => {
|
|
1161
|
+
return window.game || document.querySelector("canvas");
|
|
1162
|
+
}, null, { timeout });
|
|
1163
|
+
}
|
|
1164
|
+
async function captureGameState(page) {
|
|
1165
|
+
return await page.evaluate(() => {
|
|
1166
|
+
const game = window.game;
|
|
1167
|
+
if (!game) return {};
|
|
1168
|
+
return {};
|
|
1169
|
+
});
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// src/e2e/network.ts
|
|
1173
|
+
var CONDITIONS = {
|
|
1174
|
+
"good": {
|
|
1175
|
+
offline: false,
|
|
1176
|
+
downloadThroughput: 10 * 1024 * 1024,
|
|
1177
|
+
// 10 Mbps
|
|
1178
|
+
uploadThroughput: 5 * 1024 * 1024,
|
|
1179
|
+
// 5 Mbps
|
|
1180
|
+
latency: 20
|
|
1181
|
+
},
|
|
1182
|
+
"slow": {
|
|
1183
|
+
offline: false,
|
|
1184
|
+
downloadThroughput: 500 * 1024,
|
|
1185
|
+
// 500 Kbps
|
|
1186
|
+
uploadThroughput: 500 * 1024,
|
|
1187
|
+
latency: 400
|
|
1188
|
+
},
|
|
1189
|
+
"unstable": {
|
|
1190
|
+
offline: false,
|
|
1191
|
+
downloadThroughput: 1 * 1024 * 1024,
|
|
1192
|
+
uploadThroughput: 1 * 1024 * 1024,
|
|
1193
|
+
latency: 100
|
|
1194
|
+
// Jitter needs logic not simple preset
|
|
1195
|
+
},
|
|
1196
|
+
"offline": {
|
|
1197
|
+
offline: true,
|
|
1198
|
+
downloadThroughput: 0,
|
|
1199
|
+
uploadThroughput: 0,
|
|
1200
|
+
latency: 0
|
|
730
1201
|
}
|
|
731
1202
|
};
|
|
1203
|
+
function simulateNetworkCondition(condition) {
|
|
1204
|
+
const config = CONDITIONS[condition];
|
|
1205
|
+
return createCustomNetworkCondition(config.latency, 0, 0, config);
|
|
1206
|
+
}
|
|
1207
|
+
function createCustomNetworkCondition(latency, jitter = 0, packetLoss = 0, baseConfig) {
|
|
1208
|
+
return {
|
|
1209
|
+
async apply(page) {
|
|
1210
|
+
const client = await page.context().newCDPSession(page);
|
|
1211
|
+
await client.send("Network.enable");
|
|
1212
|
+
await client.send("Network.emulateNetworkConditions", {
|
|
1213
|
+
offline: baseConfig?.offline || false,
|
|
1214
|
+
latency: latency + Math.random() * jitter,
|
|
1215
|
+
// Basic jitter application on setup (static)
|
|
1216
|
+
downloadThroughput: baseConfig?.downloadThroughput || -1,
|
|
1217
|
+
uploadThroughput: baseConfig?.uploadThroughput || -1
|
|
1218
|
+
});
|
|
1219
|
+
},
|
|
1220
|
+
async clear(page) {
|
|
1221
|
+
const client = await page.context().newCDPSession(page);
|
|
1222
|
+
await client.send("Network.emulateNetworkConditions", {
|
|
1223
|
+
offline: false,
|
|
1224
|
+
latency: 0,
|
|
1225
|
+
downloadThroughput: -1,
|
|
1226
|
+
uploadThroughput: -1
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
async function throttleBandwidth(page, bytesPerSecond) {
|
|
1232
|
+
const simulator = createCustomNetworkCondition(0, 0, 0, {
|
|
1233
|
+
offline: false,
|
|
1234
|
+
latency: 0,
|
|
1235
|
+
downloadThroughput: bytesPerSecond,
|
|
1236
|
+
uploadThroughput: bytesPerSecond
|
|
1237
|
+
});
|
|
1238
|
+
await simulator.apply(page);
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
// src/e2e/visual.ts
|
|
1242
|
+
import path from "path";
|
|
1243
|
+
import fs from "fs/promises";
|
|
1244
|
+
async function captureGameScreenshot(page, name, options = {}) {
|
|
1245
|
+
const dir = options.dir || "__screenshots__";
|
|
1246
|
+
const screenshotPath = path.join(dir, `${name}.png`);
|
|
1247
|
+
await fs.mkdir(dir, { recursive: true });
|
|
1248
|
+
return await page.screenshot({
|
|
1249
|
+
path: screenshotPath,
|
|
1250
|
+
fullPage: options.fullPage ?? false,
|
|
1251
|
+
animations: "disabled",
|
|
1252
|
+
// Try to freeze animations if possible
|
|
1253
|
+
caret: "hide"
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
async function compareScreenshots(baseline, current, threshold = 0.1) {
|
|
1257
|
+
if (baseline.equals(current)) {
|
|
1258
|
+
return { pixelDiff: 0, matched: true };
|
|
1259
|
+
}
|
|
1260
|
+
return {
|
|
1261
|
+
pixelDiff: -1,
|
|
1262
|
+
// Unknown magnitude
|
|
1263
|
+
matched: false
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
function createVisualTestScenario(page, sceneName) {
|
|
1267
|
+
return {
|
|
1268
|
+
async capture(snapshotName) {
|
|
1269
|
+
return await captureGameScreenshot(page, `${sceneName}-${snapshotName}`);
|
|
1270
|
+
},
|
|
1271
|
+
async compare(snapshotName, baselineDir) {
|
|
1272
|
+
const name = `${sceneName}-${snapshotName}`;
|
|
1273
|
+
const current = await captureGameScreenshot(page, name, { dir: "__screenshots__/current" });
|
|
1274
|
+
try {
|
|
1275
|
+
const baselinePath = path.join(baselineDir, `${name}.png`);
|
|
1276
|
+
const baseline = await fs.readFile(baselinePath);
|
|
1277
|
+
return await compareScreenshots(baseline, current);
|
|
1278
|
+
} catch (e) {
|
|
1279
|
+
return { pixelDiff: -1, matched: false };
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
732
1284
|
export {
|
|
733
1285
|
InputInjector,
|
|
734
1286
|
MockPointerLock,
|
|
1287
|
+
captureAudioEvents,
|
|
1288
|
+
captureCanvasDrawCalls,
|
|
1289
|
+
captureGameScreenshot,
|
|
1290
|
+
captureGameState,
|
|
1291
|
+
compareScreenshots,
|
|
735
1292
|
createBinaryStreamMock,
|
|
736
1293
|
createBinaryWriterMock,
|
|
1294
|
+
createCustomNetworkCondition,
|
|
737
1295
|
createEntity,
|
|
738
1296
|
createEntityStateFactory,
|
|
739
1297
|
createGameStateSnapshotFactory,
|
|
1298
|
+
createMockAudioContext,
|
|
1299
|
+
createMockCanvas,
|
|
1300
|
+
createMockCanvasContext2D,
|
|
740
1301
|
createMockEngine,
|
|
741
1302
|
createMockGame,
|
|
1303
|
+
createMockImage,
|
|
1304
|
+
createMockImageData,
|
|
1305
|
+
createMockIndexedDB,
|
|
1306
|
+
createMockLocalStorage,
|
|
1307
|
+
createMockPerformance,
|
|
1308
|
+
createMockRAF,
|
|
1309
|
+
createMockSessionStorage,
|
|
742
1310
|
createMockWebGL2Context,
|
|
743
1311
|
createNetChanMock,
|
|
744
1312
|
createPlayerStateFactory,
|
|
1313
|
+
createPlaywrightTestClient,
|
|
745
1314
|
createSpawnContext,
|
|
1315
|
+
createStorageTestScenario,
|
|
746
1316
|
createTestContext,
|
|
1317
|
+
createVisualTestScenario,
|
|
747
1318
|
intersects,
|
|
748
1319
|
ladderTrace,
|
|
749
1320
|
makeAxisBrush,
|
|
@@ -754,8 +1325,15 @@ export {
|
|
|
754
1325
|
makeNode,
|
|
755
1326
|
makePlane,
|
|
756
1327
|
setupBrowserEnvironment,
|
|
1328
|
+
setupMockAudioContext,
|
|
757
1329
|
setupNodeEnvironment,
|
|
1330
|
+
simulateFrames,
|
|
1331
|
+
simulateFramesWithMock,
|
|
1332
|
+
simulateNetworkCondition,
|
|
758
1333
|
stairTrace,
|
|
759
|
-
teardownBrowserEnvironment
|
|
1334
|
+
teardownBrowserEnvironment,
|
|
1335
|
+
teardownMockAudioContext,
|
|
1336
|
+
throttleBandwidth,
|
|
1337
|
+
waitForGameReady
|
|
760
1338
|
};
|
|
761
1339
|
//# sourceMappingURL=index.js.map
|