chore: add @idraw/core jest testing

This commit is contained in:
chenshenhai 2021-06-09 14:27:13 +08:00
parent 4c4913c5ae
commit 5dd5bc0797
9 changed files with 391 additions and 7 deletions

View file

@ -70,7 +70,7 @@ class Context implements TypeContext {
}
fill(fillRule?: CanvasFillRule | undefined) {
return this._ctx.fill(fillRule);
return this._ctx.fill(fillRule || 'nonzero');
}
arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean | undefined): void {

View file

@ -0,0 +1,95 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`@idraw/core @idraw/core: context 1`] = `
Array [
Object {
"props": Object {
"height": 1600,
"width": 2400,
"x": 0,
"y": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "clearRect",
},
Object {
"props": Object {
"dHeight": 1600,
"dWidth": 2400,
"dx": 0,
"dy": 0,
"img": <canvas
height="1600"
width="2400"
/>,
"sHeight": 1600,
"sWidth": 2400,
"sx": 0,
"sy": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "drawImage",
},
]
`;
exports[`@idraw/core @idraw/core: context 2`] = `
Array [
Object {
"props": Object {
"height": 1600,
"width": 2400,
"x": 0,
"y": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "clearRect",
},
Object {
"props": Object {
"dHeight": 1600,
"dWidth": 2400,
"dx": 0,
"dy": 0,
"img": <canvas
height="1600"
width="2400"
/>,
"sHeight": 1600,
"sWidth": 2400,
"sx": 0,
"sy": 0,
},
"transform": Array [
1,
0,
0,
1,
0,
0,
],
"type": "drawImage",
},
]
`;

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,46 @@
import { requestAnimationFrameMock } from './polyfill/requestanimateframe';
import './polyfill/image';
import Core from './../src';
import { getData } from './data';
describe("@idraw/core", () => {
beforeEach(() => {
requestAnimationFrameMock.reset();
})
test('@idraw/core: context', async () => {
document.body.innerHTML = `
<div id="mount"></div>
`;
const opts = {
width: 600,
height: 400,
contextWidth: 600,
contextHeight: 400,
devicePixelRatio: 4
}
const mount = document.querySelector('#mount') as HTMLDivElement;
const core = new Core(mount, opts);
const data = getData();
core.initData(data);
core.draw();
requestAnimationFrameMock.triggerNextAnimationFrame();
const originCtx = core.__getOriginContext();
// @ts-ignore;
const originCalls = originCtx.__getDrawCalls();
expect(originCalls).toMatchSnapshot();
const displayCtx = core.__getDisplayContext();
// @ts-ignore;
const displayCalls = displayCtx.__getDrawCalls();
expect(displayCalls).toMatchSnapshot();
});
});

View file

@ -0,0 +1,9 @@
// @ts-ignore
window.Image = class {
constructor() {
setTimeout(() => {
// @ts-ignore
this.onload();
}, 50);
}
}

View file

@ -0,0 +1,124 @@
// https://stackoverflow.com/questions/61593774/how-do-i-test-code-that-uses-requestanimationframe-in-jest
import { requestAnimationFrameMock } from "./requestanimateframe";
describe("mock_requestAnimationFrame", () => {
beforeEach(() => {
requestAnimationFrameMock.reset();
})
test("reqest -> trigger", () => {
const order: any = [];
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([]);
requestAnimationFrame(t => order.push(1));
expect(requestAnimationFrameMock.queue.size).toBe(1);
expect(order).toEqual([]);
requestAnimationFrameMock.triggerNextAnimationFrame();
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([1]);
});
test("reqest -> request -> trigger -> trigger", () => {
const order: any = [];
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([]);
requestAnimationFrame(t => order.push(1));
requestAnimationFrame(t => order.push(2));
expect(requestAnimationFrameMock.queue.size).toBe(2);
expect(order).toEqual([]);
requestAnimationFrameMock.triggerNextAnimationFrame();
expect(requestAnimationFrameMock.queue.size).toBe(1);
expect(order).toEqual([1]);
requestAnimationFrameMock.triggerNextAnimationFrame();
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([1, 2]);
});
test("reqest -> cancel", () => {
const order: any = [];
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([]);
const handle = requestAnimationFrame(t => order.push(1));
expect(requestAnimationFrameMock.queue.size).toBe(1);
expect(order).toEqual([]);
cancelAnimationFrame(handle);
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([]);
});
test("reqest -> request -> cancel(1) -> trigger", () => {
const order: any = [];
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([]);
const handle = requestAnimationFrame(t => order.push(1));
requestAnimationFrame(t => order.push(2));
expect(requestAnimationFrameMock.queue.size).toBe(2);
expect(order).toEqual([]);
cancelAnimationFrame(handle);
expect(requestAnimationFrameMock.queue.size).toBe(1);
expect(order).toEqual([]);
requestAnimationFrameMock.triggerNextAnimationFrame();
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([2]);
});
test("reqest -> request -> cancel(2) -> trigger", () => {
const order: any = [];
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([]);
requestAnimationFrame(t => order.push(1));
const handle = requestAnimationFrame(t => order.push(2));
expect(requestAnimationFrameMock.queue.size).toBe(2);
expect(order).toEqual([]);
cancelAnimationFrame(handle);
expect(requestAnimationFrameMock.queue.size).toBe(1);
expect(order).toEqual([]);
requestAnimationFrameMock.triggerNextAnimationFrame();
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([1]);
});
test("triggerAllAnimationFrames", () => {
const order: any = [];
expect(requestAnimationFrameMock.queue.size).toBe(0);
expect(order).toEqual([]);
requestAnimationFrame(t => order.push(1));
requestAnimationFrame(t => order.push(2));
requestAnimationFrameMock.triggerAllAnimationFrames();
expect(order).toEqual([1,2]);
});
test("does not fail if triggerNextAnimationFrame() is called with an empty queue.", () => {
requestAnimationFrameMock.triggerNextAnimationFrame();
})
});

View file

@ -0,0 +1,37 @@
// https://stackoverflow.com/questions/61593774/how-do-i-test-code-that-uses-requestanimationframe-in-jest
// mock_requestAnimationFrame.js
class RequestAnimationFrameMockSession {
handleCounter = 0;
queue = new Map();
requestAnimationFrame(callback: Function) {
const handle = this.handleCounter++;
this.queue.set(handle, callback);
return handle;
}
cancelAnimationFrame(handle: Function) {
this.queue.delete(handle);
}
triggerNextAnimationFrame(time=performance.now()) {
const nextEntry = this.queue.entries().next().value;
if(nextEntry === undefined) return;
const [nextHandle, nextCallback] = nextEntry;
nextCallback(time);
this.queue.delete(nextHandle);
}
triggerAllAnimationFrames(time=performance.now()) {
while(this.queue.size > 0) this.triggerNextAnimationFrame(time);
}
reset() {
this.queue.clear();
this.handleCounter = 0;
}
};
export const requestAnimationFrameMock = new RequestAnimationFrameMockSession();
window.requestAnimationFrame = requestAnimationFrameMock.requestAnimationFrame.bind(requestAnimationFrameMock);
// @ts-ignore
window.cancelAnimationFrame = requestAnimationFrameMock.cancelAnimationFrame.bind(requestAnimationFrameMock);

View file

@ -193,6 +193,14 @@ class Core {
this[_coreEvent].off(key, callback);
}
__getDisplayContext(): CanvasRenderingContext2D {
return this[_board].getDisplayContext()
}
__getOriginContext(): CanvasRenderingContext2D {
return this[_board].getOriginContext()
}
private _initEvent(): void {
if (this[_hasInited] === true) {
return;

View file

@ -28,13 +28,13 @@ export class Renderer {
});
// TODO
this._loader.on('load', (res) => {
// console.log('load: ', res);
console.log('load: ', res);
});
this._loader.on('error', (res) => {
// console.log('error: ', res);
console.log('error: ', res);
});
this._loader.on('complete', (res) => {
// console.log('complete: ', res);
console.log('complete: ', res);
})
}
@ -50,7 +50,9 @@ export class Renderer {
private _drawFrame() {
requestAnimationFrame(() => {
const ctx = this._board.getContext();
// console.log('------ render frame ------', this._loader.isComplete())
let item: QueueItem | undefined = this._queue[0];
let isLastFrame = false;
if (this._queue.length > 1) {
@ -60,11 +62,12 @@ export class Renderer {
}
if (this._loader.isComplete() !== true) {
this._drawFrame();
if (item) {
drawContext(ctx, item.data, item.helper, this._loader);
this._board.draw();
}
} else if (item) {
const ctx = this._board.getContext();
drawContext(ctx, item.data, item.helper, this._loader);
this._board.draw();
this._retainQueueOneItem();
if (!isLastFrame) {