@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/engine/classic-animation-loop.d.ts +137 -0
- package/dist/engine/classic-animation-loop.d.ts.map +1 -0
- package/dist/engine/classic-animation-loop.js +435 -0
- package/dist/engine/classic-animation-loop.js.map +1 -0
- package/dist/index.cjs +461 -14
- package/dist/snapshot-test-runner.d.ts +0 -1
- package/dist/snapshot-test-runner.d.ts.map +1 -1
- package/dist/snapshot-test-runner.js +0 -2
- package/dist/snapshot-test-runner.js.map +1 -1
- package/dist/test-runner.d.ts +11 -5
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +16 -9
- package/dist/test-runner.js.map +1 -1
- package/package.json +9 -5
- package/src/engine/classic-animation-loop.ts +714 -0
- package/src/snapshot-test-runner.ts +2 -1
- package/src/test-runner.ts +30 -17
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/
|
|
147
|
-
|
|
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:
|
|
590
|
+
onInitialize: () => __async(void 0, null, function* () {
|
|
591
|
+
}),
|
|
152
592
|
onRender: ({ done }) => done(),
|
|
153
|
-
onFinalize:
|
|
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
|
|
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.
|
|
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;
|
|
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","
|
|
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"}
|
package/dist/test-runner.d.ts
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import { AnimationProps } from '@luma.gl/
|
|
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<
|
|
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
|
-
|
|
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":"
|
|
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"}
|