// The increased timeout is especially needed with larger binaries
// like in the debug/gpu build
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000;
describe('CanvasKit\'s Animation', function() {
// Note, don't try to print the CanvasKit object - it can cause Karma/Jasmine to lock up.
var CanvasKit = null;
const LoadCanvasKit = new Promise(function(resolve, reject) {
if (CanvasKit) {
resolve();
} else {
CanvasKitInit({
locateFile: (file) => '/canvaskit/'+file,
}).ready().then((_CanvasKit) => {
CanvasKit = _CanvasKit;
resolve();
});
}
});
const LOTTIE_ANIMATIONS = ['lego_loader', 'drinks', 'confetti', 'onboarding'];
let container = document.createElement('div');
document.body.appendChild(container);
beforeEach(function() {
container.innerHTML = `
<canvas width=600 height=600 id=test></canvas>`;
});
afterEach(function() {
container.innerHTML = '';
});
function fetchAndText(url) {
return new Promise(function(resolve, reject) {
fetch(url).then((resp) => {
resp.text().then((str) => {
expect(str).toBeTruthy();
resolve(str);
});
}).catch(reject);
});
}
LOTTIE_ANIMATIONS.forEach((animStr) => {
let promises = [fetchAndText(`/assets/${animStr}.json`), LoadCanvasKit];
it(`animation loading for ${animStr}`, function(done) {
let jsonStr = '';
function setup(ctx) {
expect(jsonStr).toBeTruthy();
}
function test(ctx) {
const animation = CanvasKit.MakeAnimation(jsonStr);
animation.delete();
}
function teardown(ctx) {}
Promise.all(promises).then((responses) => {
// The result from the first promise, that is, the JSON string
// fetched by fetchAndText
jsonStr = responses[0];
benchmarkAndReport(`${animStr}_animation_load`, setup, test, teardown).then(() => {
done();
}).catch(reportError(done));
});
});
it(`animation frames in order for ${animStr}`, function(done) {
let jsonStr = '';
function setup(ctx) {
expect(jsonStr).toBeTruthy();
ctx.animation = CanvasKit.MakeAnimation(jsonStr);
expect(ctx.animation).toBeTruthy();
ctx.timer = 0;
}
function test(ctx) {
ctx.animation.seek(ctx.timer);
ctx.timer += 0.01;
if (ctx.timer > 1.0) {
ctx.timer = 0;
}
}
function teardown(ctx) {
ctx.animation.delete();
}
Promise.all(promises).then((responses) => {
// The result from the first promise, that is, the JSON string
// fetched by fetchAndText
jsonStr = responses[0];
benchmarkAndReport(`${animStr}_animation_in_order`, setup, test, teardown).then(() => {
done();
}).catch(reportError(done));
});
});
it(`animation frames in random order for ${animStr}`, function(done) {
let jsonStr = '';
function setup(ctx) {
expect(jsonStr).toBeTruthy();
ctx.animation = CanvasKit.MakeAnimation(jsonStr);
expect(ctx.animation).toBeTruthy();
}
function test(ctx) {
ctx.animation.seek(Math.random());
}
function teardown(ctx) {
ctx.animation.delete();
}
Promise.all(promises).then((responses) => {
// The result from the first promise, that is, the JSON string
// fetched by fetchAndText
jsonStr = responses[0];
benchmarkAndReport(`${animStr}_animation_random_order`, setup, test, teardown).then(() => {
done();
}).catch(reportError(done));
});
});
it(`renders to an HTML canvas ${animStr}`, function(done) {
let jsonStr = '';
function setup(ctx) {
expect(jsonStr).toBeTruthy();
ctx.animation = CanvasKit.MakeAnimation(jsonStr);
expect(ctx.animation).toBeTruthy();
ctx.animation.seek(0.5);
ctx.surface = CanvasKit.MakeCanvasSurface('test');
ctx.canvas = ctx.surface.getCanvas();
ctx.clear = CanvasKit.Color(255, 255, 255, 0.0); // transparent
}
function test(ctx) {
// This emulates what would need to be done do accurately
// draw one frame.
ctx.canvas.clear(ctx.clear);
ctx.animation.render(ctx.canvas);
ctx.surface.flush();
}
function teardown(ctx) {
ctx.animation.delete();
ctx.surface.dispose(); // ctx.canvas will also be cleaned up
}
Promise.all(promises).then((responses) => {
// The result from the first promise, that is, the JSON string
// fetched by fetchAndText
jsonStr = responses[0];
benchmarkAndReport(`${animStr}_animation_render_flush`, setup, test, teardown).then(() => {
done();
}).catch(reportError(done));
});
});
});
});