Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start for automated tests using pixelmatch #175

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.github/
bench/
demos/
dist/
node_modules/
test/
package-lock.json
yarn.lock
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: Test

on: [push]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- run: docker-compose run test
- uses: actions/upload-artifact@v1
if: failure()
with:
name: snapshot-diffs
path: ./test/diffs/
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
package-lock.json
yarn.lock
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:12

WORKDIR /uplot

COPY package.json .
RUN npm install

COPY . .
RUN npm run build
4 changes: 2 additions & 2 deletions demos/zoom-touch.html
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@

let opts = {
title: "Pinch Zoom & Pan",
width: screen.width,
width: window.innerWidth,
height: 400,
plugins: [
touchZoomPlugin()
Expand Down Expand Up @@ -185,4 +185,4 @@
makeChart();
</script>
</body>
</html>
</html>
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: "3.7"
services:
test:
build: .
command: node ./test/demos.js
volumes:
- ./bench:/uplot/bench
- ./demos:/uplot/demos
- ./test:/uplot/test
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"typings": "./dist/uPlot.esm.d.ts",
"scripts": {
"build": "rollup -c",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "docker-compose run --rm test",
"test:update": "docker-compose run --rm test node ./test/demos.js -u"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -39,9 +40,15 @@
},
"homepage": "https://github.com/leeoniya/uPlot#readme",
"devDependencies": {
"canvas": "^2.6.1",
"canvas-5-polyfill": "^0.1.5",
"jsdom": "^16.2.2",
"pixelmatch": "^5.1.0",
"pngjs": "^3.4.0",
"rollup": "^2.3.2",
"rollup-plugin-buble": "^0.19.8",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-terser": "^5.3.0"
"rollup-plugin-terser": "^5.3.0",
"unfetch": "^4.1.0"
}
}
3 changes: 2 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function cssmin(css) {
}

let minicss = cssmin(fs.readFileSync('./src/uPlot.css', 'utf8'));
fs.mkdirSync("./dist", { recursive: true });
fs.writeFileSync('./dist/uPlot.min.css', minicss);

import buble from 'rollup-plugin-buble';
Expand Down Expand Up @@ -131,4 +132,4 @@ export default [
}),
]
},
];
];
138 changes: 138 additions & 0 deletions test/demos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
const { promises: fs } = require("fs");
const { JSDOM } = require("jsdom");
const PNG = require("pngjs").PNG;
const pixelmatch = require("pixelmatch");
require("canvas-5-polyfill");

const rootDir = `${__dirname}/..`;
const snapshotDir = `${__dirname}/snapshots`;
const diffDir = `${__dirname}/diffs`;
const demosDir = `${rootDir}/demos`;
const { mkdir, readdir, readFile, writeFile } = fs;

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const canvasToPngConverter = (FileReader) => async (canvas) => {
const blob = await new Promise((resolve) =>
canvas.toBlob(resolve, "image/png")
);
const arrayBuffer = await new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result);
};
reader.readAsArrayBuffer(blob);
});
return Buffer.from(new Uint8Array(arrayBuffer));
};

const demoRunner = async () => {
const fetchPolyfill = await readFile(
require.resolve("unfetch/polyfill"),
"utf8"
);

return async (demo) => {
const dom = await JSDOM.fromFile(`${demosDir}/${demo}`, {
pretendToBeVisual: true,
resources: "usable",
runScripts: "dangerously",
beforeParse(window) {
window.Path2D = Path2D;
window.eval(fetchPolyfill);
},
});
await delay(500);
const canvases = dom.window.document.querySelectorAll("canvas");
const convertToPng = canvasToPngConverter(dom.window.FileReader);
const buffers = await Promise.all(
Array.from(canvases).map(convertToPng)
);
dom.window.close();
return buffers;
};
};

const loadSnapshot = async (demoFile, canvasIndex) =>
await readFile(
`${snapshotDir}/${demoFile.replace(/\.html$/, `.${canvasIndex}.png`)}`
);

const saveSnapshot = async (demoFile, canvasIndex, buffer) => {
await mkdir(snapshotDir, { recursive: true });
await writeFile(
`${snapshotDir}/${demoFile.replace(/\.html$/, `.${canvasIndex}.png`)}`,
buffer
);
};

const generateDiff = (buffer1, buffer2) => {
const img1 = PNG.sync.read(buffer1);
const img2 = PNG.sync.read(buffer2);
const { width, height } = img1;
const diff = new PNG({ width, height });
const differentPixels = pixelmatch(
img1.data,
img2.data,
diff.data,
width,
height,
{
threshold: 0.1,
}
);
if (differentPixels > 0) {
return {
differentPixels,
buffer: PNG.sync.write(diff),
};
}
};

const saveDiff = async (demoFile, canvasIndex, buffer) => {
await mkdir(diffDir, { recursive: true });
await writeFile(
`${diffDir}/${demoFile.replace(/\.html$/, `.${canvasIndex}.png`)}`,
buffer
);
};

const main = async () => {
const isUpdateSnapshotMode = process.argv[2] === "-u";

const runDemo = await demoRunner();
const demoFiles = (await readdir(demosDir)).filter(
(entry) => entry.endsWith(".html") && entry !== "index.html"
);
for (const demoFile of demoFiles) {
console.group(demoFile);
try {
const images = await runDemo(demoFile);
for (let i = 0; i < images.length; i++) {
if (isUpdateSnapshotMode) {
await saveSnapshot(demoFile, i, images[i]);
} else {
const snapshot = await loadSnapshot(demoFile, i);
const diff = generateDiff(snapshot, images[i]);
if (diff) {
await saveDiff(demoFile, i, diff.buffer);
console.error(
`${i}. canvas doesn't match snapshot. ${diff.differentPixels} pixels are different. Diff has been saved. Run with "-u" to update snapshot.`
);
process.exitCode = 1;
}
}
}
} catch (err) {
console.error(err);
process.exitCode = 1;
} finally {
console.groupEnd();
}
}
};

main().catch((err) => {
console.error(err);
process.exit(1);
});
Binary file added test/snapshots/add-del-series.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/area-fill.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/axis-control.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/candlestick-ohlc.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/cursor-tooltip.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/dependent-scale.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/draw-hooks.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/focus-cursor.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/high-low-bands.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/line-smoothing.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/missing-data.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/months-ru.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/months.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/multi-bars.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/resize.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.12.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.15.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.17.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/snapshots/sparklines.18.png
Binary file added test/snapshots/sparklines.19.png
Binary file added test/snapshots/sparklines.2.png
Binary file added test/snapshots/sparklines.3.png
Binary file added test/snapshots/sparklines.4.png
Binary file added test/snapshots/sparklines.5.png
Binary file added test/snapshots/sparklines.6.png
Binary file added test/snapshots/sparklines.7.png
Binary file added test/snapshots/sparklines.8.png
Binary file added test/snapshots/sparklines.9.png
Binary file added test/snapshots/stacked-series.0.png
Binary file added test/snapshots/stacked-series.1.png
Binary file added test/snapshots/stream-data.0.png
Binary file added test/snapshots/stream-data.1.png
Binary file added test/snapshots/stream-data.2.png
Binary file added test/snapshots/sync-cursor.0.png
Binary file added test/snapshots/sync-cursor.1.png
Binary file added test/snapshots/sync-cursor.2.png
Binary file added test/snapshots/time-periods.0.png
Binary file added test/snapshots/time-periods.1.png
Binary file added test/snapshots/time-periods.2.png
Binary file added test/snapshots/timezones-dst.0.png
Binary file added test/snapshots/timezones-dst.1.png
Binary file added test/snapshots/timezones-dst.10.png
Binary file added test/snapshots/timezones-dst.11.png
Binary file added test/snapshots/timezones-dst.2.png
Binary file added test/snapshots/timezones-dst.3.png
Binary file added test/snapshots/timezones-dst.4.png
Binary file added test/snapshots/timezones-dst.5.png
Binary file added test/snapshots/timezones-dst.6.png
Binary file added test/snapshots/timezones-dst.7.png
Binary file added test/snapshots/timezones-dst.8.png
Binary file added test/snapshots/timezones-dst.9.png
Binary file added test/snapshots/tooltips.0.png
Binary file added test/snapshots/trendlines.0.png
Binary file added test/snapshots/zoom-fetch.0.png
Binary file added test/snapshots/zoom-ranger.0.png
Binary file added test/snapshots/zoom-ranger.1.png
Binary file added test/snapshots/zoom-touch.0.png
Binary file added test/snapshots/zoom-wheel.0.png