@luma.gl/test-utils 9.0.0-alpha.21 → 9.0.0-alpha.23

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/dist/index.cjs CHANGED
@@ -87,9 +87,6 @@ var import_gl = __toESM(require("gl"), 1);
87
87
  (0, import_webgl.registerHeadlessGL)(import_gl.default);
88
88
  import_api.luma.registerDevices([import_webgl.WebGLDevice, import_webgpu.WebGPUDevice]);
89
89
 
90
- // src/test-runner.ts
91
- var import_webgl_legacy = require("@luma.gl/webgl-legacy");
92
-
93
90
  // src/create-test-device.ts
94
91
  var import_api2 = require("@luma.gl/api");
95
92
  var import_webgl2 = require("@luma.gl/webgl");
@@ -143,22 +140,470 @@ function getTestDevices() {
143
140
  });
144
141
  }
145
142
 
146
- // src/test-runner.ts
147
- function noop() {
143
+ // src/engine/classic-animation-loop.ts
144
+ var import_api3 = require("@luma.gl/api");
145
+ var import_env = require("@probe.gl/env");
146
+ var import_webgl3 = require("@luma.gl/webgl");
147
+ var isPage = (0, import_env.isBrowser)() && typeof document !== "undefined";
148
+ function getHTMLCanvasElement(canvas) {
149
+ return typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement ? canvas : null;
148
150
  }
151
+ var statIdCounter = 0;
152
+ var DEFAULT_CLASSIC_ANIMATION_LOOP_PROPS = {
153
+ onCreateDevice: (props) => import_api3.luma.createDevice(props),
154
+ onCreateContext: void 0,
155
+ onAddHTML: void 0,
156
+ onInitialize: () => ({}),
157
+ onRender: () => {
158
+ },
159
+ onFinalize: () => {
160
+ },
161
+ onError: (error) => console.error(error),
162
+ // eslint-disable-line no-console
163
+ device: null,
164
+ // debug: true,
165
+ // view parameters
166
+ useDevicePixels: true,
167
+ autoResizeViewport: true,
168
+ autoResizeDrawingBuffer: true,
169
+ stats: import_api3.luma.stats.get(`animation-loop-${statIdCounter++}`),
170
+ // deprecated
171
+ // onCreateContext: (opts) => createGLContext(opts),
172
+ gl: void 0,
173
+ glOptions: {},
174
+ createFramebuffer: false
175
+ };
176
+ var ClassicAnimationLoop = class {
177
+ /*
178
+ */
179
+ constructor(props = {}) {
180
+ // framebuffer: ClassicFramebuffer = null;
181
+ this.timeline = null;
182
+ this.needsRedraw = "initialized";
183
+ this._initialized = false;
184
+ this._running = false;
185
+ this._animationFrameId = null;
186
+ this._pageLoadPromise = null;
187
+ this._nextFramePromise = null;
188
+ this._resolveNextFrame = null;
189
+ this._cpuStartTime = 0;
190
+ this.props = __spreadValues(__spreadValues({}, DEFAULT_CLASSIC_ANIMATION_LOOP_PROPS), props);
191
+ props = this.props;
192
+ let { useDevicePixels = true } = this.props;
193
+ if ("useDevicePixelRatio" in props) {
194
+ import_api3.log.deprecated("useDevicePixelRatio", "useDevicePixels")();
195
+ useDevicePixels = props.useDevicePixelRatio;
196
+ }
197
+ this.device = props.device;
198
+ this.gl = this.device && this.device.gl || props.gl;
199
+ this.stats = props.stats;
200
+ this.cpuTime = this.stats.get("CPU Time");
201
+ this.gpuTime = this.stats.get("GPU Time");
202
+ this.frameRate = this.stats.get("Frame Rate");
203
+ this.setProps({
204
+ autoResizeViewport: props.autoResizeViewport,
205
+ autoResizeDrawingBuffer: props.autoResizeDrawingBuffer,
206
+ useDevicePixels
207
+ });
208
+ this.start = this.start.bind(this);
209
+ this.stop = this.stop.bind(this);
210
+ this._onMousemove = this._onMousemove.bind(this);
211
+ this._onMouseleave = this._onMouseleave.bind(this);
212
+ }
213
+ destroy() {
214
+ this.stop();
215
+ this._setDisplay(null);
216
+ }
217
+ /** @deprecated Use .destroy() */
218
+ delete() {
219
+ this.destroy();
220
+ }
221
+ setNeedsRedraw(reason) {
222
+ this.needsRedraw = this.needsRedraw || reason;
223
+ return this;
224
+ }
225
+ setProps(props) {
226
+ if ("autoResizeViewport" in props) {
227
+ this.props.autoResizeViewport = props.autoResizeViewport;
228
+ }
229
+ if ("autoResizeDrawingBuffer" in props) {
230
+ this.props.autoResizeDrawingBuffer = props.autoResizeDrawingBuffer;
231
+ }
232
+ if ("useDevicePixels" in props) {
233
+ this.props.useDevicePixels = props.useDevicePixels;
234
+ }
235
+ return this;
236
+ }
237
+ start(opts = {}) {
238
+ this._start(opts);
239
+ return this;
240
+ }
241
+ /** Starts a render loop if not already running */
242
+ _start(props) {
243
+ return __async(this, null, function* () {
244
+ if (this._running) {
245
+ return this;
246
+ }
247
+ this._running = true;
248
+ try {
249
+ yield this._getPageLoadPromise();
250
+ if (!this._running) {
251
+ return null;
252
+ }
253
+ let appContext;
254
+ if (!this._initialized) {
255
+ this._initialized = true;
256
+ yield this._createDevice(props);
257
+ this._initialize(props);
258
+ appContext = yield this.onInitialize(this.animationProps);
259
+ this._addCallbackData(appContext || {});
260
+ }
261
+ if (!this._running) {
262
+ return null;
263
+ }
264
+ if (appContext !== false) {
265
+ this._cancelAnimationFrame();
266
+ this._requestAnimationFrame();
267
+ }
268
+ return this;
269
+ } catch (error) {
270
+ this.props.onError(error);
271
+ return null;
272
+ }
273
+ });
274
+ }
275
+ /** Explicitly draw a frame */
276
+ redraw() {
277
+ if (this.isContextLost()) {
278
+ return this;
279
+ }
280
+ this._beginTimers();
281
+ this._setupFrame();
282
+ this._updateCallbackData();
283
+ this._renderFrame(this.animationProps);
284
+ this._clearNeedsRedraw();
285
+ if (this._resolveNextFrame) {
286
+ this._resolveNextFrame(this);
287
+ this._nextFramePromise = null;
288
+ this._resolveNextFrame = null;
289
+ }
290
+ this._endTimers();
291
+ return this;
292
+ }
293
+ // Stops a render loop if already running, finalizing
294
+ stop() {
295
+ if (this._running) {
296
+ this._finalizeCallbackData();
297
+ this._cancelAnimationFrame();
298
+ this._nextFramePromise = null;
299
+ this._resolveNextFrame = null;
300
+ this._running = false;
301
+ }
302
+ return this;
303
+ }
304
+ attachTimeline(timeline) {
305
+ this.timeline = timeline;
306
+ return this.timeline;
307
+ }
308
+ detachTimeline() {
309
+ this.timeline = null;
310
+ }
311
+ waitForRender() {
312
+ this.setNeedsRedraw("waitForRender");
313
+ if (!this._nextFramePromise) {
314
+ this._nextFramePromise = new Promise((resolve) => {
315
+ this._resolveNextFrame = resolve;
316
+ });
317
+ }
318
+ return this._nextFramePromise;
319
+ }
320
+ toDataURL() {
321
+ return __async(this, null, function* () {
322
+ var _a;
323
+ this.setNeedsRedraw("toDataURL");
324
+ yield this.waitForRender();
325
+ return (_a = getHTMLCanvasElement(this.gl.canvas)) == null ? void 0 : _a.toDataURL();
326
+ });
327
+ }
328
+ isContextLost() {
329
+ return this.gl.isContextLost();
330
+ }
331
+ onCreateDevice(deviceProps) {
332
+ const { onCreateDevice } = this.props;
333
+ return onCreateDevice(deviceProps);
334
+ }
335
+ onInitialize(animationProps) {
336
+ const { onInitialize } = this.props;
337
+ return onInitialize(animationProps);
338
+ }
339
+ onRender(animationProps) {
340
+ const { onRender } = this.props;
341
+ return onRender(animationProps);
342
+ }
343
+ onFinalize(animationProps) {
344
+ const { onFinalize } = this.props;
345
+ return onFinalize(animationProps);
346
+ }
347
+ // DEPRECATED/REMOVED METHODS
348
+ /** @deprecated Use .onCreateDevice() */
349
+ onCreateContext(props) {
350
+ const { onCreateContext } = this.props;
351
+ return onCreateContext(props);
352
+ }
353
+ /** @deprecated */
354
+ getHTMLControlValue(id, defaultValue = 1) {
355
+ const element = document.getElementById(id);
356
+ return element ? Number(element.value) : defaultValue;
357
+ }
358
+ // PRIVATE METHODS
359
+ _initialize(props) {
360
+ this._createFramebuffer();
361
+ this._startEventHandling();
362
+ this._initializeCallbackData();
363
+ this._updateCallbackData();
364
+ this._resizeCanvasDrawingBuffer();
365
+ this._resizeViewport();
366
+ }
367
+ _getPageLoadPromise() {
368
+ if (!this._pageLoadPromise) {
369
+ this._pageLoadPromise = isPage ? new Promise((resolve, reject) => {
370
+ if (isPage && document.readyState === "complete") {
371
+ resolve(document);
372
+ return;
373
+ }
374
+ window.addEventListener("load", () => {
375
+ resolve(document);
376
+ });
377
+ }) : Promise.resolve({});
378
+ }
379
+ return this._pageLoadPromise;
380
+ }
381
+ _setDisplay(display) {
382
+ if (this.display) {
383
+ this.display.destroy();
384
+ this.display.animationLoop = null;
385
+ }
386
+ if (display) {
387
+ display.animationLoop = this;
388
+ }
389
+ this.display = display;
390
+ }
391
+ _requestAnimationFrame() {
392
+ if (!this._running) {
393
+ return;
394
+ }
395
+ this._animationFrameId = (0, import_api3.requestAnimationFrame)(this._animationFrame.bind(this));
396
+ }
397
+ _cancelAnimationFrame() {
398
+ if (this._animationFrameId !== null) {
399
+ return;
400
+ }
401
+ (0, import_api3.cancelAnimationFrame)(this._animationFrameId);
402
+ this._animationFrameId = null;
403
+ }
404
+ _animationFrame() {
405
+ if (!this._running) {
406
+ return;
407
+ }
408
+ this.redraw();
409
+ this._requestAnimationFrame();
410
+ }
411
+ // Called on each frame, can be overridden to call onRender multiple times
412
+ // to support e.g. stereoscopic rendering
413
+ _renderFrame(props) {
414
+ if (this.display) {
415
+ this.display._renderFrame(props);
416
+ return;
417
+ }
418
+ this.onRender(props);
419
+ }
420
+ _clearNeedsRedraw() {
421
+ this.needsRedraw = null;
422
+ }
423
+ _setupFrame() {
424
+ this._resizeCanvasDrawingBuffer();
425
+ this._resizeViewport();
426
+ this._resizeFramebuffer();
427
+ }
428
+ /* eslint-disable @typescript-eslint/unbound-method */
429
+ // Initialize the object that will be passed to app callbacks
430
+ _initializeCallbackData() {
431
+ this.animationProps = {
432
+ device: this.device,
433
+ gl: this.gl,
434
+ stop: this.stop,
435
+ canvas: this.gl.canvas,
436
+ // Initial values
437
+ useDevicePixels: this.props.useDevicePixels,
438
+ needsRedraw: null,
439
+ // Animation props
440
+ startTime: Date.now(),
441
+ engineTime: 0,
442
+ tick: 0,
443
+ tock: 0,
444
+ timeline: this.timeline,
445
+ // @ts-ignore
446
+ animationLoop: this,
447
+ // Timeline time for back compatibility
448
+ time: 0,
449
+ // Experimental
450
+ _mousePosition: null,
451
+ // Event props
452
+ /** @deprecated */
453
+ // framebuffer: this.framebuffer,
454
+ /** @deprecated */
455
+ _timeline: this.timeline,
456
+ /** @deprecated */
457
+ _loop: this,
458
+ /** @deprecated */
459
+ _animationLoop: this
460
+ };
461
+ }
462
+ // Update the context object that will be passed to app callbacks
463
+ _updateCallbackData() {
464
+ const { width, height, aspect } = this._getSizeAndAspect();
465
+ if (width !== this.animationProps.width || height !== this.animationProps.height) {
466
+ this.setNeedsRedraw("drawing buffer resized");
467
+ }
468
+ if (aspect !== this.animationProps.aspect) {
469
+ this.setNeedsRedraw("drawing buffer aspect changed");
470
+ }
471
+ this.animationProps.width = width;
472
+ this.animationProps.height = height;
473
+ this.animationProps.aspect = aspect;
474
+ this.animationProps.needsRedraw = this.needsRedraw;
475
+ this.animationProps.engineTime = Date.now() - this.animationProps.startTime;
476
+ if (this.timeline) {
477
+ this.timeline.update(this.animationProps.engineTime);
478
+ }
479
+ this.animationProps.tick = Math.floor(this.animationProps.time / 1e3 * 60);
480
+ this.animationProps.tock++;
481
+ this.animationProps.time = this.timeline ? this.timeline.getTime() : this.animationProps.engineTime;
482
+ }
483
+ _finalizeCallbackData() {
484
+ this.onFinalize(this.animationProps);
485
+ }
486
+ /** Add application's data to the app context object */
487
+ _addCallbackData(appContext) {
488
+ if (typeof appContext === "object" && appContext !== null) {
489
+ this.animationProps = Object.assign({}, this.animationProps, appContext);
490
+ }
491
+ }
492
+ /** Either uses supplied or existing context, or calls provided callback to create one */
493
+ _createDevice(props) {
494
+ return __async(this, null, function* () {
495
+ const deviceProps = __spreadValues(__spreadValues(__spreadValues({}, this.props), props), this.props.glOptions);
496
+ this.device = yield this.onCreateDevice(deviceProps);
497
+ this.gl = this.device.gl;
498
+ if (!(0, import_webgl3.isWebGL)(this.gl)) {
499
+ throw new Error("ClassicAnimationLoop.onCreateContext - illegal context returned");
500
+ }
501
+ (0, import_webgl3.resetParameters)(this.gl);
502
+ this._createInfoDiv();
503
+ });
504
+ }
505
+ _createInfoDiv() {
506
+ const canvas = getHTMLCanvasElement(this.gl.canvas);
507
+ if (canvas && this.props.onAddHTML) {
508
+ const wrapperDiv = document.createElement("div");
509
+ document.body.appendChild(wrapperDiv);
510
+ wrapperDiv.style.position = "relative";
511
+ const div = document.createElement("div");
512
+ div.style.position = "absolute";
513
+ div.style.left = "10px";
514
+ div.style.bottom = "10px";
515
+ div.style.width = "300px";
516
+ div.style.background = "white";
517
+ if (canvas) {
518
+ wrapperDiv.appendChild(canvas);
519
+ }
520
+ wrapperDiv.appendChild(div);
521
+ const html = this.props.onAddHTML(div);
522
+ if (html) {
523
+ div.innerHTML = html;
524
+ }
525
+ }
526
+ }
527
+ _getSizeAndAspect() {
528
+ const width = this.gl.drawingBufferWidth;
529
+ const height = this.gl.drawingBufferHeight;
530
+ let aspect = 1;
531
+ const canvas = getHTMLCanvasElement(this.gl.canvas);
532
+ if (canvas && canvas.clientHeight) {
533
+ aspect = canvas.clientWidth / canvas.clientHeight;
534
+ } else if (width > 0 && height > 0) {
535
+ aspect = width / height;
536
+ }
537
+ return { width, height, aspect };
538
+ }
539
+ /** Default viewport setup */
540
+ _resizeViewport() {
541
+ if (this.props.autoResizeViewport) {
542
+ this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);
543
+ }
544
+ }
545
+ /**
546
+ * Resize the render buffer of the canvas to match canvas client size
547
+ * Optionally multiplying with devicePixel ratio
548
+ */
549
+ _resizeCanvasDrawingBuffer() {
550
+ if (this.props.autoResizeDrawingBuffer) {
551
+ this.device.canvasContext.resize({ useDevicePixels: this.props.useDevicePixels });
552
+ }
553
+ }
554
+ _beginTimers() {
555
+ this.frameRate.timeEnd();
556
+ this.frameRate.timeStart();
557
+ this.cpuTime.timeStart();
558
+ }
559
+ _endTimers() {
560
+ this.cpuTime.timeEnd();
561
+ }
562
+ // Event handling
563
+ _startEventHandling() {
564
+ const { canvas } = this.gl;
565
+ if (canvas) {
566
+ canvas.addEventListener("mousemove", this._onMousemove);
567
+ canvas.addEventListener("mouseleave", this._onMouseleave);
568
+ }
569
+ }
570
+ _onMousemove(e) {
571
+ this.animationProps._mousePosition = [e.offsetX, e.offsetY];
572
+ }
573
+ _onMouseleave(e) {
574
+ this.animationProps._mousePosition = null;
575
+ }
576
+ // Deprecated
577
+ /** @deprecated */
578
+ _createFramebuffer() {
579
+ if (this.props.createFramebuffer) {
580
+ }
581
+ }
582
+ /** @deprecated */
583
+ _resizeFramebuffer() {
584
+ }
585
+ };
586
+
587
+ // src/test-runner.ts
149
588
  var DEFAULT_TEST_CASE = {
150
589
  name: "Unnamed test",
151
- onInitialize: noop,
590
+ onInitialize: () => __async(void 0, null, function* () {
591
+ }),
152
592
  onRender: ({ done }) => done(),
153
- onFinalize: noop
593
+ onFinalize: () => {
594
+ }
154
595
  };
155
596
  var DEFAULT_TEST_PROPS = {
597
+ width: void 0,
598
+ height: void 0,
156
599
  // test lifecycle callback
157
600
  onTestStart: (testCase) => console.log(`# ${testCase.name}`),
158
- onTestPass: (testCase) => console.log(`ok ${testCase.name} passed`),
159
- onTestFail: (testCase) => console.log(`not ok ${testCase.name} failed`),
601
+ onTestPass: (testCase, result) => console.log(`ok ${testCase.name} passed`),
602
+ onTestFail: (testCase, error) => console.log(`not ok ${testCase.name} failed`),
160
603
  // milliseconds to wait for each test case before aborting
161
- timeout: 2e3
604
+ timeout: 2e3,
605
+ maxFramesToRender: void 0,
606
+ imageDiffOptions: void 0
162
607
  };
163
608
  var TestRunner = class {
164
609
  /**
@@ -169,9 +614,10 @@ var TestRunner = class {
169
614
  this.device = webglDevice;
170
615
  this.isRunning = false;
171
616
  this.testOptions = __spreadValues({}, DEFAULT_TEST_PROPS);
172
- this._animationProps = {};
173
617
  this._testCases = [];
174
618
  this._testCaseData = null;
619
+ // should be defined in snapshot-test-runner
620
+ this.isDiffing = false;
175
621
  // @ts-expect-error
176
622
  this.isHeadless = Boolean(window.browserTestDriver_isHeadless);
177
623
  this.props = props;
@@ -194,7 +640,7 @@ var TestRunner = class {
194
640
  run(options = {}) {
195
641
  this.testOptions = __spreadValues(__spreadValues({}, this.testOptions), options);
196
642
  return new Promise((resolve, reject) => {
197
- this._animationLoop = new import_webgl_legacy.AnimationLoop(__spreadProps(__spreadValues({}, this.props), {
643
+ this._animationLoop = new ClassicAnimationLoop(__spreadProps(__spreadValues({}, this.props), {
198
644
  device: this.device,
199
645
  onRender: this._onRender.bind(this),
200
646
  onFinalize: () => {
@@ -275,7 +721,7 @@ var TestRunner = class {
275
721
  for (const key in this._testCaseData) {
276
722
  const value = this._testCaseData[key];
277
723
  if (value && value.delete) {
278
- value.delete();
724
+ value.destroy();
279
725
  }
280
726
  }
281
727
  this._currentTestCase.onFinalize(Object.assign({}, animationProps, this._testCaseData));
@@ -318,9 +764,10 @@ function getBoundingBoxInPage(domElement) {
318
764
 
319
765
  // src/snapshot-test-runner.ts
320
766
  var SnapshotTestRunner = class extends TestRunner {
767
+ // should be defined here but hack access in TestRunner
768
+ // private isDiffing: boolean = false;
321
769
  constructor(props) {
322
770
  super(props);
323
- this.isDiffing = false;
324
771
  this.testOptions.imageDiffOptions = {};
325
772
  }
326
773
  initTestCase(testCase) {
@@ -10,7 +10,6 @@ export declare type SnapshotTestRunnerTestCase = TestRunnerTestCase & {
10
10
  };
11
11
  export declare type SnapshotTestRunnerProps = TestRunnerProps;
12
12
  export declare class SnapshotTestRunner extends TestRunner {
13
- private isDiffing;
14
13
  constructor(props: SnapshotTestRunnerProps);
15
14
  initTestCase(testCase: SnapshotTestRunnerTestCase): void;
16
15
  shouldRender(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-test-runner.d.ts","sourceRoot":"","sources":["../src/snapshot-test-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAG9E,2BAA2B;AAC3B,oBAAY,0BAA0B,GAAG,kBAAkB,GAAG;IAC5D,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,gBAAgB,CAAC,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAC;CACzC,CAAA;AAED,oBAAY,uBAAuB,GAAG,eAAe,CAAC;AAEtD,qBAAa,kBAAmB,SAAQ,UAAU;IAChD,OAAO,CAAC,SAAS,CAAkB;gBAEvB,KAAK,EAAE,uBAAuB;IAKjC,YAAY,CAAC,QAAQ,EAAE,0BAA0B,GAAG,IAAI;IAOxD,YAAY,IAAI,OAAO;IAKjB,MAAM,CAAC,QAAQ,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CAgC3E"}
1
+ {"version":3,"file":"snapshot-test-runner.d.ts","sourceRoot":"","sources":["../src/snapshot-test-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,eAAe,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAG9E,2BAA2B;AAC3B,oBAAY,0BAA0B,GAAG,kBAAkB,GAAG;IAC5D,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,gBAAgB,CAAC,EAAE;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAAC;CACzC,CAAA;AAED,oBAAY,uBAAuB,GAAG,eAAe,CAAC;AAEtD,qBAAa,kBAAmB,SAAQ,UAAU;gBAIpC,KAAK,EAAE,uBAAuB;IAKjC,YAAY,CAAC,QAAQ,EAAE,0BAA0B,GAAG,IAAI;IAOxD,YAAY,IAAI,OAAO;IAKjB,MAAM,CAAC,QAAQ,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CAgC3E"}
@@ -1,10 +1,8 @@
1
- import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
2
1
  import { TestRunner } from "./test-runner.js";
3
2
  import { getBoundingBoxInPage } from "./utils.js";
4
3
  export class SnapshotTestRunner extends TestRunner {
5
4
  constructor(props) {
6
5
  super(props);
7
- _defineProperty(this, "isDiffing", false);
8
6
  this.testOptions.imageDiffOptions = {};
9
7
  }
10
8
  initTestCase(testCase) {
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-test-runner.js","names":["TestRunner","getBoundingBoxInPage","SnapshotTestRunner","constructor","props","_defineProperty","testOptions","imageDiffOptions","initTestCase","testCase","goldenImage","Error","concat","name","shouldRender","isDiffing","assert","_this$_animationProps","canvas","_animationProps","HTMLCanvasElement","diffOptions","region","result","globalThis","browserTestDriver_captureAndDiffScreen","success","_pass","_fail","_next"],"sources":["../src/snapshot-test-runner.ts"],"sourcesContent":["import {TestRunner, TestRunnerProps, TestRunnerTestCase} from './test-runner';\nimport {getBoundingBoxInPage} from './utils';\n\n/** A snapshot test case */\nexport type SnapshotTestRunnerTestCase = TestRunnerTestCase & {\n /** URL to golden image */\n goldenImage: string;\n /** Diff options */\n imageDiffOptions?: {[key: string]: any}; \n}\n\nexport type SnapshotTestRunnerProps = TestRunnerProps;\n\nexport class SnapshotTestRunner extends TestRunner {\n private isDiffing: boolean = false;\n\n constructor(props: SnapshotTestRunnerProps) {\n super(props);\n this.testOptions.imageDiffOptions = {};\n }\n\n override initTestCase(testCase: SnapshotTestRunnerTestCase): void {\n super.initTestCase(testCase);\n if (!testCase.goldenImage) {\n throw new Error(`Test case ${testCase.name} does not have golden image`);\n }\n }\n\n override shouldRender(): boolean {\n // wait for the current diffing to finish\n return !this.isDiffing;\n }\n\n override async assert(testCase: SnapshotTestRunnerTestCase): Promise<void> {\n if (this.isDiffing) {\n // Already performing diffing\n return;\n }\n this.isDiffing = true;\n\n const canvas = this._animationProps?.canvas;\n if (!(canvas instanceof HTMLCanvasElement)) {\n throw new Error('canvas');\n }\n\n const diffOptions = {\n ...this.testOptions.imageDiffOptions,\n ...testCase.imageDiffOptions,\n goldenImage: testCase.goldenImage,\n region: getBoundingBoxInPage(canvas)\n };\n\n // Take screenshot and compare\n const result = await globalThis.browserTestDriver_captureAndDiffScreen(diffOptions);\n\n // invoke user callback\n if (result.success) {\n this._pass(result);\n } else {\n this._fail(result);\n }\n\n this.isDiffing = false;\n this._next();\n }\n}\n"],"mappings":";SAAQA,UAAU;AAAA,SACVC,oBAAoB;AAY5B,OAAO,MAAMC,kBAAkB,SAASF,UAAU,CAAC;EAGjDG,WAAWA,CAACC,KAA8B,EAAE;IAC1C,KAAK,CAACA,KAAK,CAAC;IAACC,eAAA,oBAHc,KAAK;IAIhC,IAAI,CAACC,WAAW,CAACC,gBAAgB,GAAG,CAAC,CAAC;EACxC;EAESC,YAAYA,CAACC,QAAoC,EAAQ;IAChE,KAAK,CAACD,YAAY,CAACC,QAAQ,CAAC;IAC5B,IAAI,CAACA,QAAQ,CAACC,WAAW,EAAE;MACzB,MAAM,IAAIC,KAAK,cAAAC,MAAA,CAAcH,QAAQ,CAACI,IAAI,iCAA8B;IAC1E;EACF;EAESC,YAAYA,CAAA,EAAY;IAE/B,OAAO,CAAC,IAAI,CAACC,SAAS;EACxB;EAEA,MAAeC,MAAMA,CAACP,QAAoC,EAAiB;IAAA,IAAAQ,qBAAA;IACzE,IAAI,IAAI,CAACF,SAAS,EAAE;MAElB;IACF;IACA,IAAI,CAACA,SAAS,GAAG,IAAI;IAErB,MAAMG,MAAM,IAAAD,qBAAA,GAAG,IAAI,CAACE,eAAe,cAAAF,qBAAA,uBAApBA,qBAAA,CAAsBC,MAAM;IAC3C,IAAI,EAAEA,MAAM,YAAYE,iBAAiB,CAAC,EAAE;MAC1C,MAAM,IAAIT,KAAK,CAAC,QAAQ,CAAC;IAC3B;IAEA,MAAMU,WAAW,GAAG;MAClB,GAAG,IAAI,CAACf,WAAW,CAACC,gBAAgB;MACpC,GAAGE,QAAQ,CAACF,gBAAgB;MAC5BG,WAAW,EAAED,QAAQ,CAACC,WAAW;MACjCY,MAAM,EAAErB,oBAAoB,CAACiB,MAAM;IACrC,CAAC;IAGD,MAAMK,MAAM,GAAG,MAAMC,UAAU,CAACC,sCAAsC,CAACJ,WAAW,CAAC;IAGnF,IAAIE,MAAM,CAACG,OAAO,EAAE;MAClB,IAAI,CAACC,KAAK,CAACJ,MAAM,CAAC;IACpB,CAAC,MAAM;MACL,IAAI,CAACK,KAAK,CAACL,MAAM,CAAC;IACpB;IAEA,IAAI,CAACR,SAAS,GAAG,KAAK;IACtB,IAAI,CAACc,KAAK,EAAE;EACd;AACF"}
1
+ {"version":3,"file":"snapshot-test-runner.js","names":["TestRunner","getBoundingBoxInPage","SnapshotTestRunner","constructor","props","testOptions","imageDiffOptions","initTestCase","testCase","goldenImage","Error","concat","name","shouldRender","isDiffing","assert","_this$_animationProps","canvas","_animationProps","HTMLCanvasElement","diffOptions","region","result","globalThis","browserTestDriver_captureAndDiffScreen","success","_pass","_fail","_next"],"sources":["../src/snapshot-test-runner.ts"],"sourcesContent":["import {TestRunner, TestRunnerProps, TestRunnerTestCase} from './test-runner';\nimport {getBoundingBoxInPage} from './utils';\n\n/** A snapshot test case */\nexport type SnapshotTestRunnerTestCase = TestRunnerTestCase & {\n /** URL to golden image */\n goldenImage: string;\n /** Diff options */\n imageDiffOptions?: {[key: string]: any}; \n}\n\nexport type SnapshotTestRunnerProps = TestRunnerProps;\n\nexport class SnapshotTestRunner extends TestRunner {\n // should be defined here but hack access in TestRunner\n // private isDiffing: boolean = false;\n\n constructor(props: SnapshotTestRunnerProps) {\n super(props);\n this.testOptions.imageDiffOptions = {};\n }\n\n override initTestCase(testCase: SnapshotTestRunnerTestCase): void {\n super.initTestCase(testCase);\n if (!testCase.goldenImage) {\n throw new Error(`Test case ${testCase.name} does not have golden image`);\n }\n }\n\n override shouldRender(): boolean {\n // wait for the current diffing to finish\n return !this.isDiffing;\n }\n\n override async assert(testCase: SnapshotTestRunnerTestCase): Promise<void> {\n if (this.isDiffing) {\n // Already performing diffing\n return;\n }\n this.isDiffing = true;\n\n const canvas = this._animationProps?.canvas;\n if (!(canvas instanceof HTMLCanvasElement)) {\n throw new Error('canvas');\n }\n\n const diffOptions = {\n ...this.testOptions.imageDiffOptions,\n ...testCase.imageDiffOptions,\n goldenImage: testCase.goldenImage,\n region: getBoundingBoxInPage(canvas)\n };\n\n // Take screenshot and compare\n const result = await globalThis.browserTestDriver_captureAndDiffScreen(diffOptions);\n\n // invoke user callback\n if (result.success) {\n this._pass(result);\n } else {\n this._fail(result);\n }\n\n this.isDiffing = false;\n this._next();\n }\n}\n"],"mappings":"SAAQA,UAAU;AAAA,SACVC,oBAAoB;AAY5B,OAAO,MAAMC,kBAAkB,SAASF,UAAU,CAAC;EAIjDG,WAAWA,CAACC,KAA8B,EAAE;IAC1C,KAAK,CAACA,KAAK,CAAC;IACZ,IAAI,CAACC,WAAW,CAACC,gBAAgB,GAAG,CAAC,CAAC;EACxC;EAESC,YAAYA,CAACC,QAAoC,EAAQ;IAChE,KAAK,CAACD,YAAY,CAACC,QAAQ,CAAC;IAC5B,IAAI,CAACA,QAAQ,CAACC,WAAW,EAAE;MACzB,MAAM,IAAIC,KAAK,cAAAC,MAAA,CAAcH,QAAQ,CAACI,IAAI,iCAA8B;IAC1E;EACF;EAESC,YAAYA,CAAA,EAAY;IAE/B,OAAO,CAAC,IAAI,CAACC,SAAS;EACxB;EAEA,MAAeC,MAAMA,CAACP,QAAoC,EAAiB;IAAA,IAAAQ,qBAAA;IACzE,IAAI,IAAI,CAACF,SAAS,EAAE;MAElB;IACF;IACA,IAAI,CAACA,SAAS,GAAG,IAAI;IAErB,MAAMG,MAAM,IAAAD,qBAAA,GAAG,IAAI,CAACE,eAAe,cAAAF,qBAAA,uBAApBA,qBAAA,CAAsBC,MAAM;IAC3C,IAAI,EAAEA,MAAM,YAAYE,iBAAiB,CAAC,EAAE;MAC1C,MAAM,IAAIT,KAAK,CAAC,QAAQ,CAAC;IAC3B;IAEA,MAAMU,WAAW,GAAG;MAClB,GAAG,IAAI,CAACf,WAAW,CAACC,gBAAgB;MACpC,GAAGE,QAAQ,CAACF,gBAAgB;MAC5BG,WAAW,EAAED,QAAQ,CAACC,WAAW;MACjCY,MAAM,EAAEpB,oBAAoB,CAACgB,MAAM;IACrC,CAAC;IAGD,MAAMK,MAAM,GAAG,MAAMC,UAAU,CAACC,sCAAsC,CAACJ,WAAW,CAAC;IAGnF,IAAIE,MAAM,CAACG,OAAO,EAAE;MAClB,IAAI,CAACC,KAAK,CAACJ,MAAM,CAAC;IACpB,CAAC,MAAM;MACL,IAAI,CAACK,KAAK,CAACL,MAAM,CAAC;IACpB;IAEA,IAAI,CAACR,SAAS,GAAG,KAAK;IACtB,IAAI,CAACc,KAAK,EAAE;EACd;AACF"}
@@ -1,24 +1,26 @@
1
- import { AnimationProps } from '@luma.gl/webgl-legacy';
1
+ import { AnimationProps } from '@luma.gl/engine';
2
+ import { ClassicAnimationLoop as AnimationLoop } from './engine/classic-animation-loop';
2
3
  /** Describes a test case */
3
4
  export declare type TestRunnerTestCase = {
4
5
  /** Name of the test case (for logging) */
5
6
  name: string;
6
7
  /** Initialize the test case. Can return a promise */
7
- onInitialize: (props: AnimationProps) => Promise<unknown>;
8
+ onInitialize: (props: AnimationProps) => Promise<void | {}>;
8
9
  /** Perform rendering */
9
10
  onRender: (props: AnimationProps & {
10
11
  done: any;
11
12
  }) => void;
12
13
  /** Clean up after the test case */
13
14
  onFinalize: (props: AnimationProps) => void;
15
+ animationLoop?: AnimationLoop;
14
16
  };
15
17
  /** Options for a TestRunner */
16
18
  export declare type TestRunnerProps = {
17
19
  width?: number;
18
20
  height?: number;
19
21
  onTestStart?: (testCase: TestRunnerTestCase) => void;
20
- onTestPass?: (testCase: TestRunnerTestCase) => void;
21
- onTestFail?: (testCase: TestRunnerTestCase) => void;
22
+ onTestPass?: (testCase: TestRunnerTestCase, result?: unknown) => void;
23
+ onTestFail?: (testCase: TestRunnerTestCase, error?: unknown) => void;
22
24
  /** milliseconds to wait for each test case before aborting */
23
25
  timeout?: number;
24
26
  maxFramesToRender?: number;
@@ -29,11 +31,15 @@ export declare class TestRunner {
29
31
  device: import("modules/webgl/dist").WebGLDevice;
30
32
  props: Record<string, any>;
31
33
  isRunning: boolean;
32
- readonly testOptions: Required<TestRunnerProps>;
34
+ testOptions: Required<TestRunnerProps>;
33
35
  readonly _animationProps?: AnimationProps;
34
36
  private _animationLoop;
35
37
  private _testCases;
36
38
  private _testCaseData;
39
+ private _currentTestCase;
40
+ private _currentTestCaseStartTime;
41
+ private _currentTestCaseStartTick;
42
+ isDiffing: boolean;
37
43
  isHeadless: boolean;
38
44
  /**
39
45
  * props
@@ -1 +1 @@
1
- {"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAGpE,4BAA4B;AAC5B,oBAAY,kBAAkB,GAAG;IAC/B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,wBAAwB;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG;QAAC,IAAI,MAAA;KAAC,KAAK,IAAI,CAAC;IACnD,mCAAmC;IACnC,UAAU,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC7C,CAAC;AAWF,+BAA+B;AAC/B,oBAAY,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACrD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACpD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACpD,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,gBAAgB,CAAC,EAAE,GAAG,CAAC;CACxB,CAAC;AAYF,kCAAkC;AAClC,qBAAa,UAAU;IACrB,MAAM,2CAAe;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAS;IAC3B,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,eAAe,CAAC,CAA2B;IAC1E,QAAQ,CAAC,eAAe,CAAC,EAAE,cAAc,CAAM;IAC/C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,aAAa,CAAa;IAGlC,UAAU,EAAE,OAAO,CAAgD;IAEnE;;;OAGG;gBACS,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM;IAI3C;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAU1C;;QAEI;IACJ,GAAG,CAAC,OAAO,GAAE,MAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BxC,YAAY,CAAC,QAAQ,EAAE,kBAAkB;IAYzC,YAAY,CAAC,cAAc,KAAA,GAAG,OAAO;IAIrC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAO1C,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAK5B,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAK5B,KAAK,IAAI,IAAI;IAMb,SAAS,CAAC,cAAc,KAAA,GAAG,IAAI;IA2C/B,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAuD7C"}
1
+ {"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,cAAc,EAAC,MAAM,iBAAiB,CAAC;AAI/C,OAAO,EAAC,oBAAoB,IAAI,aAAa,EAAC,MAAM,iCAAiC,CAAC;AAEtF,4BAA4B;AAC5B,oBAAY,kBAAkB,GAAG;IAC/B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAC5D,wBAAwB;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG;QAAC,IAAI,MAAA;KAAC,KAAK,IAAI,CAAC;IACnD,mCAAmC;IACnC,UAAU,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC5C,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,CAAC;AASF,+BAA+B;AAC/B,oBAAY,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,WAAW,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACrD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACtE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACrE,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,gBAAgB,CAAC,EAAE,GAAG,CAAC;CACxB,CAAC;AAiBF,kCAAkC;AAClC,qBAAa,UAAU;IACrB,MAAM,2CAAe;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAS;IAC3B,WAAW,EAAE,QAAQ,CAAC,eAAe,CAAC,CAA2B;IACjE,QAAQ,CAAC,eAAe,CAAC,EAAE,cAAc,CAAC;IAC1C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,yBAAyB,CAAS;IAC1C,OAAO,CAAC,yBAAyB,CAAS;IAG1C,SAAS,EAAE,OAAO,CAAS;IAG3B,UAAU,EAAE,OAAO,CAAgD;IAEnE;;;OAGG;gBACS,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM;IAI3C;;OAEG;IACH,GAAG,CAAC,SAAS,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAU1C;;QAEI;IACJ,GAAG,CAAC,OAAO,GAAE,MAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BxC,YAAY,CAAC,QAAQ,EAAE,kBAAkB;IAYzC,YAAY,CAAC,cAAc,KAAA,GAAG,OAAO;IAIrC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAO1C,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAK5B,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAK5B,KAAK,IAAI,IAAI;IAMb,SAAS,CAAC,cAAc,KAAA,GAAG,IAAI;IA2C/B,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC;CAuD7C"}