chore: init e2e testing

This commit is contained in:
chenshenhai 2021-06-04 14:43:42 +08:00
parent 038cb40b5d
commit cc15b9d799
46 changed files with 309 additions and 42 deletions

69
__tests__/e2e.test.js Normal file
View file

@ -0,0 +1,69 @@
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const jimp = require('jimp');
const pixelmatch = require('pixelmatch');
const pngjs = require('pngjs');
const { delay } = require('./../scripts/util/time');
const { pageList } = require('./../scripts/screen.config');
const { createScreenshot } = require('../scripts/util/screen');
const snapshotDir = path.join(__dirname, 'snapshot');
const diffDir = path.join(__dirname, 'diff');
const { PNG } = pngjs;
async function diff() {
const middlewares = [];
const diffRateList = [];
pageList.forEach((p) => {
middlewares.push(async (ctx = {}, next) => {
const { page, port } = ctx;
const width = p.w;
const height = p.h;
await page.setViewport( { width: p.w, height: p.h } );
const pageUrl = `http://127.0.0.1:${port}/packages/${p.path || ''}`;
await page.goto(pageUrl);
await delay(p.delay || 100);
const buf = await page.screenshot();
const snapshotPicPath = parsePicPath(path.join(snapshotDir, p.path));
const actual = (await jimp.read(buf)).scale(1).quality(100).bitmap;
const expected = (await jimp.read(fs.readFileSync(snapshotPicPath))).bitmap;
const diffBuf = new PNG({ width, height });
const failedPixel = pixelmatch(expected.data, actual.data, diffBuf.data, actual.width, actual.height);
const failRate = failedPixel / (width * height);
if (failRate > 0) {
(await jimp.read(diffBuf)).scale(1).quality(100).write(parsePicPath(path.join(diffDir, p.path)));
}
diffRateList.push(failRate);
await next();
});
});
await createScreenshot(middlewares, { baseDir: path.join(__dirname, '..') });
return diffRateList;
}
function parsePicPath(pagePath) {
// const picPath = pagePath.replace(/\.html$/, '.jpg');
const picPath = pagePath + '.jpg';
return picPath;
}
describe('Screenshot testing', function() {
it('testing...', function(done){
this.timeout(1000 * 60 * 2);
diff().then((rateList) => {
assert.ok(Array.isArray(rateList));
assert.ok(rateList.length > 0);
rateList.forEach((rate) => {
console.log('diff-rate =', rate);
assert.ok(rate < 0.05);
});
done();
}).catch(done);
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

View file

@ -26,7 +26,7 @@ function isPointInElement(board, p = {x, y}) {
function moveElement(board, idx, moveX, moveY) {
const data = getData();
const scale = getScale();
const scale = getScale() || 1;
if (data.elements[idx]) {
// data.elements[idx].x += (moveX * scale * opts.devicePixelRatio);
// data.elements[idx].y += (moveY * scale * opts.devicePixelRatio);

View file

@ -3,6 +3,9 @@ let hasInited = false;
export function doScale(board, scale) {
if (hasInited === true) return;
if (!input) {
return;
}
if (scale > 0) {
input.value = scale;
board.scale(scale);
@ -19,6 +22,9 @@ export function doScale(board, scale) {
}
export function getScale() {
if (!input) {
return;
}
let val = 1;
if (input.value * 1 > 0) {
val = input.value * 1;

View file

@ -4,6 +4,9 @@ let hasInited = false;
export function doScroll(board, conf = {}) {
if (hasInited === true) return;
if (!(inputX && inputY)) {
return;
}
if (conf.scrollX >= 0) {
inputX.value = conf.scrollX;

View file

@ -0,0 +1,29 @@
<html>
<head>
<style></style>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<style>
html,body {
margin: 0;
padding: 0;
}
#mount canvas {
border-right: 1px solid #aaaaaa40;
border-bottom: 1px solid #aaaaaa40;
background-image:
linear-gradient(#aaaaaa40 1px, transparent 0),
linear-gradient(90deg, #aaaaaa40 1px, transparent 0),
linear-gradient(#aaa 1px, transparent 0),
linear-gradient(90deg, #aaa 1px, transparent 0);
background-size: 10px 10px, 10px 10px, 50px 50px, 50px 50px;
}
</style>
</head>
<body>
<div id="mount"></div>
<script src="./../../dist/index.global.js"></script>
<script type="module" src="./main.js"></script>
</body>
</html>

View file

@ -1,17 +0,0 @@
import dataRect from './rect.js';
import dataImage from './image.js';
import dataSVG from './svg.js';
import dataText from './text.js';
const url = new URLSearchParams(window.location.search);
const dataMap = {
'rect': dataRect,
'image': dataImage,
'svg': dataSVG,
'text': dataText
}
export function getData() {
return dataMap[url.get('data')] || dataMap['rect'];
}

View file

@ -0,0 +1,25 @@
<html>
<head>
<style></style>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="stylesheet" href="./css/index.css" />
<style>
html, body { margin: 0; padding: 0; }
.dashboard .row { margin: 0 }
</style>
</head>
<body>
<div class="dashboard">
<div class="row">
<div class="col">
<div id="mount"></div>
</div>
</div>
</div>
<script src="./../../dist/index.global.js"></script>
<script type="module" src="./lib/main.js"></script>
</body>
</html>

View file

@ -31,7 +31,7 @@
</div>
<script src="./../dist/index.global.js"></script>
<script type="module" src="./main.js"></script>
<script src="./../../dist/index.global.js"></script>
<script type="module" src="./lib/main.js"></script>
</body>
</html>

View file

@ -15,7 +15,7 @@ const data = {
// angle: 30,
// angle: 0,
desc: {
src: './images/computer.png',
src: './../images/computer.png',
}
},
{
@ -30,7 +30,7 @@ const data = {
borderColor: '#bd0b64',
type: 'image',
desc: {
src: './images/chart.png',
src: './../images/chart.png',
}
},
{
@ -42,7 +42,7 @@ const data = {
type: 'image',
angle: 80,
desc: {
src: './images/phone.png',
src: './../images/phone.png',
}
},
{
@ -53,7 +53,7 @@ const data = {
h: 100,
type: 'image',
desc: {
src: './images/building-001.png',
src: './../images/building-001.png',
}
},
{
@ -64,7 +64,7 @@ const data = {
h: 100,
type: 'image',
desc: {
src: './images/building-002.png',
src: './../images/building-002.png',
}
},
{
@ -75,7 +75,7 @@ const data = {
h: 100,
type: 'image',
desc: {
src: './images/building-003.png',
src: './../images/building-003.png',
}
}
]

View file

@ -0,0 +1,42 @@
import dataRect from './rect.js';
import dataImage from './image.js';
import dataSVG from './svg.js';
import dataText from './text.js';
const url = new URLSearchParams(window.location.search);
const dataMap = {
'rect': dataRect,
'image': dataImage,
'svg': dataSVG,
'text': dataText
}
export function getData() {
return dataMap[getPageName()] || dataMap[url.get('data')] || dataMap['rect'];
}
function getPageName() {
// const pathname = window.location.pathname || '';
// const reg = /(?<pageName>[\w+]{1,})\.html$/;
// const page = reg.exec(pathname)?.groups?.pageName || '';
// return page;
const pathname = window.location.pathname || '';
const list = pathname.split('/');
let pageName = list.pop() || '';
pageName = pageName.replace(/\.html$/ig, '');
return pageName;
// return getQueryString('data') || 'rect';
}
// function getQueryString(name) {
// let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
// let r = window.location.search.substr(1).match(reg);
// if (r != null) {
// return decodeURIComponent(r[2]);
// };
// return null;
// }

View file

@ -5,6 +5,7 @@ let hasInited = false;
export function doElemens(core) {
if (hasInited === true) return;
if (!dom) return;
renderElemens(core);
listenElements(core);
}

View file

@ -1,16 +1,11 @@
import { getData } from './lib/data/index.js';
import { doScale } from './lib/scale.js';
import { doScroll } from './lib/scroll.js';
import { doElemens } from './lib/element.js';
import { getData } from './data/index.js';
import { doScale } from './scale.js';
import { doScroll } from './scroll.js';
import { doElemens } from './element.js';
const { Core } = window.iDraw;
const data = getData();
const mount = document.querySelector('#mount');
// const defaultConf = {
// scale: 0.8,
// scrollX: 100,
// scrollY: 50,
// }
const defaultConf = {
scale: 1,
@ -23,9 +18,11 @@ const core = new Core(mount, {
devicePixelRatio: 4
});
console.log('core ===', core);
core.setData(data);
core.draw();
doScale(core, defaultConf.scale);
doScroll(core, defaultConf);
doElemens(core);

View file

@ -3,6 +3,7 @@ let hasInited = false;
export function doScale(core, scale) {
if (hasInited === true) return;
if (!input) return;
if (scale > 0) {
input.value = scale;
core.scale(scale);

View file

@ -3,7 +3,8 @@ const inputY = document.querySelector('#scrollY');
let hasInited = false;
export function doScroll(core, conf = {}) {
if (hasInited === true) return;
if (hasInited === true) return;
if (!(inputY && inputX)) return;
if (conf.scrollX >= 0) {
inputX.value = conf.scrollX;

View file

@ -0,0 +1,25 @@
<html>
<head>
<style></style>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="stylesheet" href="./css/index.css" />
<style>
html, body { margin: 0; padding: 0; }
.dashboard .row { margin: 0 }
</style>
</head>
<body>
<div class="dashboard">
<div class="row">
<div class="col">
<div id="mount"></div>
</div>
</div>
</div>
<script src="./../../dist/index.global.js"></script>
<script type="module" src="./lib/main.js"></script>
</body>
</html>

View file

@ -0,0 +1,25 @@
<html>
<head>
<style></style>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="stylesheet" href="./css/index.css" />
<style>
html, body { margin: 0; padding: 0; }
.dashboard .row { margin: 0 }
</style>
</head>
<body>
<div class="dashboard">
<div class="row">
<div class="col">
<div id="mount"></div>
</div>
</div>
</div>
<script src="./../../dist/index.global.js"></script>
<script type="module" src="./lib/main.js"></script>
</body>
</html>

View file

@ -0,0 +1,25 @@
<html>
<head>
<style></style>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="stylesheet" href="./css/index.css" />
<style>
html, body { margin: 0; padding: 0; }
.dashboard .row { margin: 0 }
</style>
</head>
<body>
<div class="dashboard">
<div class="row">
<div class="col">
<div id="mount"></div>
</div>
</div>
</div>
<script src="./../../dist/index.global.js"></script>
<script type="module" src="./lib/main.js"></script>
</body>
</html>

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View file

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 222 KiB

View file

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 142 KiB

View file

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View file

@ -1,7 +1,10 @@
const pageList = [
// { path: 'paint/examples/path/draw.html', w: 600, h: 600, delay: 200 },
// { path: 'paint/examples/path/play.html', w: 600, h: 600, delay: 8000 },
{ path: 'drag-core/examples/demo.html', w: 500, h: 1000, delay: 2000 },
{ path: 'board/examples/features/test.html', w: 600, h: 400, delay: 1000 },
{ path: 'core/examples/features/rect.html', w: 600, h: 400, delay: 1000 },
{ path: 'core/examples/features/text.html', w: 600, h: 400, delay: 1000 },
{ path: 'core/examples/features/svg.html', w: 600, h: 400, delay: 1000 },
{ path: 'core/examples/features/image.html', w: 600, h: 400, delay: 1000 },
// { path: 'core/examples/test.html', w: 600, h: 600, delay: 8000 },
]
module.exports = {

View file

@ -2,6 +2,7 @@ const jimp = require('jimp');
const path = require('path');
const { delay } = require('./util/time');
const { createScreenshot } = require('./util/screen');
const { removeFullDir } = require('./util/file');
const { pageList } = require('./screen.config');
const snapshotDir = path.join(__dirname, '..', '__tests__', 'snapshot');
@ -9,13 +10,18 @@ const snapshotDir = path.join(__dirname, '..', '__tests__', 'snapshot');
main();
async function main() {
removeFullDir(snapshotDir);
const middlewares = [];
pageList.forEach((p) => {
middlewares.push(async (ctx = {}, next) => {
const { page, port } = ctx;
await page.setViewport( { width: p.w, height: p.h } );
const pageUrl = `http://127.0.0.1:${port}/packages/${p.path || ''}`;
await page.goto(pageUrl);
const result = await page.goto(pageUrl);
if (result.status() === 404) {
console.error(`404 Not Found: ${pageUrl}`)
throw Error('404 status code found in result')
}
await delay(p.delay || 100);
const buf = await page.screenshot();
(await jimp.read(buf)).scale(1).quality(100).write(createPicPath(p.path));
@ -28,7 +34,7 @@ async function main() {
function createPicPath(pagePath) {
let picPath = path.join(snapshotDir, pagePath);
picPath = picPath.replace(/\.html$/, '.jpg');
picPath = picPath + '.jpg'; // picPath.replace(/\.html$/, '.jpg');
return picPath;
}

26
scripts/util/file.js Normal file
View file

@ -0,0 +1,26 @@
const fs = require('fs');
const path = require('path');
function removeFullDir(dirPath) {
let files = [];
if (fs.existsSync(dirPath)) {
files = fs.readdirSync(dirPath);
files.forEach((filename) => {
let curPath = path.join(dirPath, filename);
const stat = fs.statSync(curPath);
if(stat.isDirectory()) {
removeFullDir(curPath);
} else if (stat.isFile()) {
// fs.unlinkSync(curPath);
fs.rmSync(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(dirPath);
}
}
module.exports = {
removeFullDir,
}