Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@canvest/canvest-cli

TyrealGray24AFL-3.01.2.4

A unit testing framework for HTML5 canvas

canvas, unit-test, canvest

readme

Canvest

Writing a unit test for your HTML5 Canvas component without mocking any DOM element

Using browser to render and execute your component's unit test logic directly, outputting image snapshot to compare in pixel-level

Support TypeScript and zero config needed in most cases for JavaScript project, using API like it and describe with a few unique API for canvas snapshot

Install

Run npm cmd to install on your project

$ npm i @canvest/canvest-cli --save-dev

Create a script in your package.json

 "scripts": {
    ...
    "test": "canvest",
    ...
  },

Usage example

If you just want to test a canvas, create helloworld.canvest.js under ./canvest folder

describe('Test my canvas', () => {

    it('should render hello world text in canvas', async () => {
        let canvas = document.createElement('canvas');
        canvas.width = 800;
        canvas.height = 600;
        const a = await snapshot(canvas);
        const context = canvas.getContext('2d');
        context.fillStyle = '#ff0';
        context.fillRect(0, 0, 800, 600);

        const text = 'Hello, World!';

        context.font = 'bold 70pt Menlo';
        context.textAlign = 'center';
        context.fillStyle = '#fff';
        context.fillText(text, 200, 200);

        const b = await snapshot(canvas);

        a.notEqual(b);// this should pass

        await autoShot('test', canvas); // this create a snapshot in local that will check canvas image to test if it is still the same
    });

});

Or test the class you create, for example for pixi.js

export class MyClass
{
     ...
     updateRotation(rotation){
         this._sprite.rotation = rotation;
     }
     ...
}

Create MyClass.canvest.js under ./canvest folder

import * as PIXI from 'pixi.js';
import { MyClass } from './MyClass';

describe('Test my class', () => {

    it('should update rotation as expect', async () => {

        const app = new PIXI.Application({
            width: XXX, height: YYY,
            preserveDrawingBuffer: true //<--- important for Canvest to take snapshot, false might lead to a blank image
        });

        const myClass = new MyClass();
        app.stage.addChild(myClass._sprite);

        myClass.updateRotation(1.5);

        /** 
         * the second time this autoShot function run,
         * it will check the current Canvas's image with the local cached 'rotation_that_expected.png' file,
         * if this one is not the same with the cached image,
         * the test will fail
         **/
        await autoShot('rotation_that_expected', app.view);

        const rotation15Snapshot = await snapshot(app.view); // 1.5 rotation snapshot

        myClass.updateRotation(1.6); // rotate sprite to 1.6 rotation

        const rotation16Snapshot = await snapshot(app.view);

        rotation16Snapshot.notEqual(rotation15Snapshot); // should pass

        /**
         * if the number of different pixels between rotation16Snapshot and rotation15Snapshot is below 20%,
         * isMatch function will make the test as passed
         **/
        rotation16Snapshot.isMatch(rotation15Snapshot, 0.2);

    });
});

Then using npm cmd

$ npm test

Once you ran npm test, Canvest-cli will start running unit test that under canvest folder if files name is after *.canvest.(js|ts) pattern. Canvest-cli will start two node servers, to config the port you could change npm script by

 "scripts": {
    ...
    "test": "canvest --cachePort XXX --pagePort XXX",
    ...
  },
  • cachePort: this is the port that canvest-cli using to start the node server to cache your snapshot, default is 45670.
  • pagePort: this is the port that canvest-cli using to start the web page to run your unit test with Mocha, running webapck-dev-server under the hood.

Result

If some test case failed, you will see diff comparison under bottom showing in highlight red color.

One thing should notice is the diff for cached snapshot won't show up if cached snapshot has different size with current one.

API

Canvest framework is using Mocha with Chai under the hood, every API Mocha had in browser, Canvest should have as well by accessing mocha variable but this is not recommended.

You could create file canvest.init.js(or canvest.init.ts when using --ts) under ./canvest folder and doing all the setup in there.

autoShot(name, canvas): Promise<void>

take a snapshot of current canvas and cached in local, if local snapshot already exists, compare current snapshot with local one automatically

  • name: a unique name for snapshot to save under ./canvest/autoShot/(the-name-you-given).png
  • canvas: HTML5 canvas dom element

  • as long as your local snapshot doesn't get removed, autoShot will do the comparison instead of caching it and pass test

snapshot(canvas): Promise<snapshot Object>

take a snapshot of current canvas

  • canvas: HTML5 canvas dom element
  • snapshot Object: return a Canvest snapshot that has 4 APIs in below
    • isEqual( otherSnapshot ): snapshot should completely equal to otherSnapshot
    • notEqual( otherSnapshot ): snapshot should not equal to otherSnapshot
    • isMatch( otherSnapshot, tolerance ): snapshot could equal to otherSnapshot if test ignores number of tolerance percentage of pixels
    • notMatch( otherSnapshot, tolerance ): snapshot could not equal to otherSnapshot even after test ignores number of tolerance percentage of pixels

setThreshold(number): void

set global threshold for snapshot comparision, if you just want one snapshot comparision to be more tolerant, use isMatch or notMatch function with tolerance parameter

  • number threshold, a number that can be set to maximum 1.0. Default is 0.05, higher number will ignore more differences between snapshot comparision

Test Coverage

Canvest will create test coverage after all test is done, you could find the coverage.json and/or open index.html under ./coverage folder

TypeScript

To support TypeScript, you will need run npm i @canvest/canvest-ts --save-dev to install canvest-ts plugin

Then using canvest --ts ./path-to-your-tsconfig.json to start testing

Integrate with CI

If you want to run with headless browser in CI, you could use --ci option. This will make Canvest exit when all tests are done, and add a div inside web page <body> with className test_end or test_end_with_failed.

For example, canvest --ci ./canvest will create a canvest-test-result folder under ./canvest folder, any failed test will create a diff image in result folder.

If diff is a cached snapshot and it is not valid because new snapshot size is different, it will still create an empty file failed-Name.diff.failed.

Canvest example for pixi.js with TypeScript https://github.com/TyrealGray/canvest-pixi.js-example

Canvest example for three.js https://github.com/TyrealGray/canvest-three.js-example

License

AFL-3.0

changelog

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

Generated by auto-changelog.

v1.2.4 - 2021-03-04

Commits

  • adding better logger when using web mode 74ca439

v1.2.3 - 2021-03-04

Merged

  • Bump ini from 1.3.5 to 1.3.8 #28
  • Bump find-my-way from 2.2.4 to 2.2.5 in /packages/canvest-cli #26
  • Bump node-fetch from 2.6.0 to 2.6.1 #25
  • Bump http-proxy from 1.18.0 to 1.18.1 in /packages/canvest-cli #24

Commits

  • hotfix: fixed issue non ci mode still create image under root directory cec8d65

v1.2.2 - 2021-03-04

Commits

  • 29 add better output result 266ca1d

v1.2.1 - 2020-08-28

Fixed

  • fixed issue that no html coverage report on MacOS close #23 #23

v1.2.0 - 2020-08-27

Commits

  • fixed issue that ci params without path will create a folder name true 79a3dcf

v1.2.0-alpha.0 - 2020-08-27

Merged

  • Feature/coverage #22

Commits

  • adding script to create coverage report when test is done #21 404c7c3
  • add example for three.js 03aefcb
  • adding socket message for sending coverage json content c7eec6f

v1.1.1 - 2020-07-16

Merged

  • Bump websocket-extensions from 0.1.3 to 0.1.4 in /packages/canvest-cli #15

Commits

  • fixed issue that unable to start canvest in Windows 6c603af

v1.1.0 - 2020-05-18

Commits

  • add div when test is finished in CI mode acf2061
  • adding a way to set threshold globally ed519f2
  • make lerna update version as one 491ea49

@canvest/canvest-ts@1.0.0-alpha.0 - 2020-05-17

Fixed

  • create CI mode, close #14 #14
  • fixed canvest-ts path issue, fully support typescript. close #13 #13

Commits

@canvest/canvest-ts@0.0.2 - 2021-03-04

@canvest/canvest-dev-server@1.0.3-alpha.0 - 2020-05-17

Fixed

  • create CI mode, close #14 #14
  • fixed canvest-ts path issue, fully support typescript. close #13 #13

Commits

@canvest/canvest-dev-server@1.0.2-alpha.0 - 2020-05-16

Commits

  • create canvest-ts plugin for typescript #13 b27b38f
  • add notes about typescript support 0dcaba6
  • add example repo link c59a065
  • using more accurate word f8fa12b
  • to make how canvest search the unit test file more clear 1b93123

@canvest/canvest-dev-server@1.0.1-alpha.0 - 2020-05-09

Commits

  • adding more documentation b3f7517
  • fixed readme file picture is too small 58d8885

@canvest/canvest-dev-server@1.0.0-alpha.0 - 2020-05-09

Commits

  • adding document for Canvest usage 18d09e0

@canvest/canvest-dev-server@0.0.14 - 2020-05-09

Fixed

  • add cache snapshot feature, close #3 #3 #8

Commits

  • add websocket 24914e3
  • using pixelmatch for image pixel comparison, add rate match feature 48511c2
  • make pixelmatch threshold to be 0.05 3734bb5
  • fixed content not found issue 6333676
  • trying to fix pixelmatch is not a function error 38056db
  • add missing files 5b1cce1
  • direct import pixelmatch in core 0a0fc52

@canvest/canvest-dev-server@0.0.12 - 2020-05-02

Fixed

  • remove fork version of webpack-dev-server. close #7 #7

@canvest/canvest-dev-server@0.0.10 - 2021-03-04

@canvest/canvest-core@1.0.2-alpha.0 - 2020-05-16

Commits

  • create canvest-ts plugin for typescript #13 b27b38f
  • add notes about typescript support 0dcaba6
  • add example repo link c59a065
  • using more accurate word f8fa12b
  • to make how canvest search the unit test file more clear 1b93123

@canvest/canvest-core@1.0.1-alpha.0 - 2020-05-09

Commits

  • adding more documentation b3f7517
  • fixed readme file picture is too small 58d8885

@canvest/canvest-core@1.0.0-alpha.0 - 2020-05-09

Commits

  • adding document for Canvest usage 18d09e0
  • make pixelmatch threshold to be 0.05 3734bb5

@canvest/canvest-core@0.0.9 - 2020-05-08

Fixed

  • add cache snapshot feature, close #3 #3 #8

Commits

@canvest/canvest-core@0.0.8 - 2020-05-03

Commits

  • direct import pixelmatch in core 0a0fc52

@canvest/canvest-core@0.0.7 - 2020-05-03

Commits

  • trying to fix pixelmatch is not a function error 38056db

@canvest/canvest-core@0.0.6 - 2021-03-04

@canvest/canvest-core@0.0.10 - 2021-03-04

@canvest/canvest-cli@1.0.4-alpha.0 - 2020-05-17

Fixed

  • create CI mode, close #14 #14

Commits

@canvest/canvest-cli@1.0.3-alpha.0 - 2020-05-16

Fixed

  • fixed canvest-ts path issue, fully support typescript. close #13 #13

@canvest/canvest-cli@1.0.2-alpha.0 - 2020-05-16

Commits

  • create canvest-ts plugin for typescript #13 b27b38f
  • add notes about typescript support 0dcaba6
  • add example repo link c59a065
  • using more accurate word f8fa12b
  • to make how canvest search the unit test file more clear 1b93123

@canvest/canvest-cli@1.0.1-alpha.0 - 2020-05-09

Commits

  • adding more documentation b3f7517
  • fixed readme file picture is too small 58d8885

@canvest/canvest-cli@1.0.0-alpha.0 - 2020-05-09

Fixed

  • add cache snapshot feature, close #3 #3 #8

Commits

  • adding document for Canvest usage 18d09e0
  • add websocket 24914e3
  • using pixelmatch for image pixel comparison, add rate match feature 48511c2
  • make pixelmatch threshold to be 0.05 3734bb5
  • fixed content not found issue 6333676
  • trying to fix pixelmatch is not a function error 38056db
  • add missing files 5b1cce1
  • direct import pixelmatch in core 0a0fc52

@canvest/canvest-cli@0.0.9 - 2020-05-02

Fixed

  • remove fork version of webpack-dev-server. close #7 #7

@canvest/canvest-cli@0.0.8 - 2020-05-02

Fixed

  • support test write in typescript, close #2 #2

Commits

  • make capture object api more testing friendly 524ecd9

@canvest/canvest-cli@0.0.6 - 2020-05-02

Commits

  • using node run dev-server js file directly in cmd c149507

@canvest/canvest-cli@0.0.5 - 2021-03-04

@canvest/canvest-cli@0.0.15 - 2020-05-08

Fixed

  • add cache snapshot feature, close #3 #3 #8

Commits

@canvest/canvest-cli@0.0.14 - 2020-05-03

Commits

  • direct import pixelmatch in core 0a0fc52

@canvest/canvest-cli@0.0.13 - 2020-05-03

Commits

  • trying to fix pixelmatch is not a function error 38056db

@canvest/canvest-cli@0.0.12 - 2020-05-03

Commits

  • using pixelmatch for image pixel comparison, add rate match feature 48511c2

@canvest/canvest-cli@0.0.11 - 2020-05-02

Commits

  • fixed content not found issue 6333676

@canvest/canvest-cli@0.0.10 - 2020-05-02

Fixed

  • remove fork version of webpack-dev-server. close #7 #7
  • support test write in typescript, close #2 #2
  • improve snapshot function, snapshot more times and compare quickly to avoid timeout render issue. close #6 #6

Commits

  • create canvest-dev-server package dd84ca4
  • adding more config and example code a7798d8
  • init project b2fd4c1
  • using canvest-cli to control canvest-dev-server 4957216
  • add license c4ff7da
  • simplify canvest dev server config file, removed script-loader 1d1d58b
  • using node run dev-server js file directly in cmd c149507
  • make capture object api more testing friendly 524ecd9
  • fixed a problem that script-loader could not work without lerna environment b6cdf83
  • fixed issue that snapshot, isPixelEqual is undefined in unit test scope #1 f6df12b
  • make snapshot and isPixelEqual function accessible directly in dev-server #1 aed02ec
  • try fixing canvest cmd missing issue 3934591
  • add missing files 5b1cce1
  • add "prepublishOnly" cmd ba21fd1
  • change equal function name to isPixelEqual #1 425d1cf