提交 65f58a39 编写于 作者: P pissang

test: Fix some logic issue of controlling test in dashboard.

上级 e31266d2
......@@ -4,7 +4,7 @@ const fse = require('fs-extra');
const fs = require('fs');
const path = require('path');
const compareScreenshot = require('./compareScreenshot');
const {getTestName, getVersionDir} = require('./util');
const {getTestName, getVersionDir, buildRuntimeCode} = require('./util');
const {origin} = require('./config');
function getScreenshotDir() {
......@@ -63,7 +63,7 @@ function createWaitTimeout(maxTime) {
});
}
return {keepWait, waitTimeout}
return {keepWait, waitTimeout};
}
async function takeScreenshot(page, elementQuery, fileUrl, desc, version) {
......@@ -149,12 +149,14 @@ async function runTestPage(browser, fileUrl, version, runtimeCode) {
// screenshotPromises.push(promise);
// }, 100);
console.log('1111');
// Wait for puppeteerFinishTest() is called
// Or compare the whole page if nothing happened after 10 seconds.
await Promise.race([
pageFinishPromise,
waitTimeout().then(() => {
console.log('2222');
// console.warn('Test timeout after 3 seconds.');
// Final shot.
let desc = 'Final Shot';
......@@ -179,6 +181,14 @@ async function runTestPage(browser, fileUrl, version, runtimeCode) {
};
}
async function writePNG(diffPNG, diffPath) {
return new Promise(resolve => {
let writer = fs.createWriteStream(diffPath);
diffPNG.pack().pipe(writer);
writer.on('finish', () => {resolve();});
});
};
async function runTest(browser, testOpt, runtimeCode) {
testOpt.status === 'running';
const fileUrl = testOpt.fileUrl;
......@@ -199,7 +209,7 @@ async function runTest(browser, testOpt, runtimeCode) {
);
let diffPath = `${path.resolve(__dirname, getScreenshotDir())}/${shot.testName}-diff.png`;
diffPNG.pack().pipe(fs.createWriteStream(diffPath));
await writePNG(diffPNG, diffPath);
screenshots.push({
actual: getClientRelativePath(actual.screenshotPath),
......@@ -221,9 +231,10 @@ async function runTest(browser, testOpt, runtimeCode) {
}
async function runTests(pendingTests) {
const browser = await puppeteer.launch({ headless: true });
const browser = await puppeteer.launch({ headless: false });
// TODO Not hardcoded.
let runtimeCode = fs.readFileSync(path.join(__dirname, 'tmp/testRuntime.js'), 'utf-8');
// let runtimeCode = fs.readFileSync(path.join(__dirname, 'tmp/testRuntime.js'), 'utf-8');
let runtimeCode = await buildRuntimeCode();
try {
for (let testOpt of pendingTests) {
......@@ -243,6 +254,8 @@ async function runTests(pendingTests) {
catch(e) {
console.log(e);
}
await browser.close();
}
// Handling input arguments.
......@@ -252,6 +265,6 @@ runTests(testsFileUrlList.split(',').map(fileUrl => {
fileUrl,
name: getTestName(fileUrl),
results: [],
status: 'pending'
status: 'unsettled'
};
}));
\ No newline at end of file
......@@ -39,6 +39,10 @@
padding: 10px 10px;
background: #162436;
box-shadow: inset 0 0 5px black;
position: fixed;
top: 50px;
width: 280px;
z-index: 2;
}
.nav-toolbar .controls {
margin-top: 10px;
......@@ -49,6 +53,7 @@
background: #293c55;
margin: 0;
padding: 0;
margin-top: 80px;
}
.test-list li {
list-style: none;
......
......@@ -18,7 +18,7 @@ function processTestsData(tests, oldTestsData) {
test.summary = 'exception';
}
else {
test.summary = 'warning'
test.summary = 'warning';
}
// Keep select status not change.
......@@ -55,10 +55,11 @@ socket.on('connect', () => {
return a.name.localeCompare(b.name);
}
return a.percentage - b.percentage;
}
};
if (!this.searchString) {
return this.fullTests.sort(sortFunc);
// Not modify the original tests data.
return this.fullTests.slice().sort(sortFunc);
}
return this.fullTests.filter(test => {
......@@ -74,6 +75,10 @@ socket.on('connect', () => {
return currentTest;
},
currentTestUrl() {
return window.location.origin + '/test/' + this.currentTest.fileUrl;
},
isSelectAllIndeterminate: {
get() {
if (!this.tests.length) {
......@@ -123,7 +128,7 @@ socket.on('connect', () => {
const tests = this.fullTests.filter(test => {
return test.selected;
}).map(test => {
return test.name
return test.name;
});
if (tests.length > 0) {
this.running = true;
......@@ -142,7 +147,7 @@ socket.on('connect', () => {
socket.on('update', msg => {
let hasFinishedTest = !!msg.tests.find(test => test.status === 'finished');
if (!hasFinishedTest && firstUpdate) {
app.$confirm("It seems you haven't run any test yet!<br />Do you want to start now?", 'Tip', {
app.$confirm('It seems you haven\'t run any test yet!<br />Do you want to start now?', 'Tip', {
confirmButtonText: 'Yes',
cancelButtonText: 'No',
dangerouslyUseHTMLString: true,
......@@ -150,7 +155,7 @@ socket.on('connect', () => {
}).then(value => {
app.running = true;
socket.emit('run', msg.tests.map(test => test.name));
}).catch(() => {})
}).catch(() => {});
}
// TODO
// app.running = !!msg.running;
......@@ -162,7 +167,7 @@ socket.on('connect', () => {
app.$notify({
title: 'Test Complete',
position: 'bottom-right'
})
});
app.running = false;
});
......
......@@ -25,7 +25,6 @@
<el-button v-if="running" title="Run Selected" @click="stopTests" circle size="mini" type="primary" icon="el-icon-close"></el-button>
</el-button-group>
<el-button
style="margin-left: 10px"
title="Sort By Failue Percentage" @click="toggleSort" circle size="mini" type="primary" icon="el-icon-sort"
......@@ -62,6 +61,13 @@
</el-aside>
<el-main>
<div v-if="currentTest">
<div class="toolbar">
<h3>
<a target="_blank" :href="currentTestUrl">{{currentTest.name}}</a>
</h3>
</div>
<div class="test-result" v-for="result in currentTest.results">
<h4>{{result.desc || result.name}}</h4>
<el-row :gutter="40" class="screenshots">
......
......@@ -4,17 +4,19 @@ import lolex from 'lolex';
const NativeDate = window.Date;
const fixedTimestamp = 1566458693300;
// const actualTimestamp = NativeDate.now();
// function MockDate(params) {
// if (!params) {
// const elapsedTime = NativeDate.now() - actualTimestamp;
// return new NativeDate(fixedTimestamp + elapsedTime);
// }
// else {
// return new NativeDate(params);
// }
// }
// MockDate.prototype = new Date();
const actualTimestamp = NativeDate.now();
function MockDate(params) {
if (!params) {
const elapsedTime = NativeDate.now() - actualTimestamp;
return new NativeDate(fixedTimestamp + elapsedTime);
}
else {
return new NativeDate(params);
}
}
MockDate.prototype = new Date();
// Fixed date
window.Date = MockDate;
export function createScreenshotTest (desc, elementQuery, waitTime) {
......@@ -44,11 +46,8 @@ Math.random = function () {
return val;
};
// Fixed date
// window.Date = MockDate;
lolex.install({
shouldAdvanceTime: true,
advanceTimeDelta: 50,
now: fixedTimestamp
});
// lolex.install({
// shouldAdvanceTime: true,
// advanceTimeDelta: 200,
// now: fixedTimestamp
// });
const handler = require('serve-handler');
const http = require('http');
const rollup = require('rollup');
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const path = require('path');
const open = require('open');
const fse = require('fs-extra');
const {fork} = require('child_process');
const {port, origin} = require('./config');
const {getTestsList, prepareTestsList, saveTestsList, mergeTestsResults} = require('./store');
const {prepareEChartsVersion} = require('./util');
const {prepareEChartsVersion, buildRuntimeCode} = require('./util');
function serve() {
const server = http.createServer((request, response) => {
......@@ -31,51 +28,53 @@ function serve() {
};
};
async function buildRuntimeCode() {
const bundle = await rollup.rollup({
input: path.join(__dirname, 'runtime/main.js'),
plugins: [
resolve(),
commonjs()
]
});
const output = await bundle.generate({
format: 'iife',
name: 'autorun'
});
return output.code;
let testProcess;
let pendingTests;
function stopRunningTests() {
if (testProcess) {
testProcess.kill();
testProcess = null;
}
if (pendingTests) {
pendingTests.forEach(testOpt => {
if (testOpt.status === 'pending') {
testOpt.status = 'unsettled';
}
});
pendingTests = null;
}
}
function startTests(testsNameList, socket) {
console.log(testsNameList.join(','));
stopRunningTests();
return new Promise(resolve => {
const pendingTests = getTestsList().filter(testOpt => {
pendingTests = getTestsList().filter(testOpt => {
return testsNameList.includes(testOpt.name);
});
for (let testOpt of pendingTests) {
pendingTests.forEach(testOpt => {
// Reset all tests results
testOpt.status = 'pending';
testOpt.results = [];
}
});
socket.emit('update', {tests: getTestsList()});
let childProcess = fork(path.join(__dirname, 'cli.js'), [
testProcess = fork(path.join(__dirname, 'cli.js'), [
pendingTests.map(testOpt => testOpt.fileUrl)
]);
// Finished one test
childProcess.on('message', testOpt => {
testProcess.on('message', testOpt => {
mergeTestsResults([testOpt]);
// Merge tests.
socket.emit('update', {tests: getTestsList(), running: true});
saveTestsList();
});
// Finished all
childProcess.on('exit', () => {
testProcess.on('exit', () => {
resolve();
});
});
......@@ -86,9 +85,6 @@ async function start() {
await prepareEChartsVersion(); // Version to test
let runtimeCode = await buildRuntimeCode();
// seedrandom use crypto as external module. Set it to null to avoid not defined error.
// TODO
runtimeCode = 'window.crypto = null\n' + runtimeCode;
fse.outputFileSync(path.join(__dirname, 'tmp/testRuntime.js'), runtimeCode, 'utf-8');
// Start a static server for puppeteer open the html test cases.
......@@ -103,6 +99,9 @@ async function start() {
await startTests(testsNameList, socket);
socket.emit('finish');
});
socket.on('stop', () => {
stopRunningTests();
});
});
console.log(`Dashboard: ${origin}/test/runTest/client/index.html`);
......
......@@ -30,6 +30,11 @@ module.exports.prepareTestsList = async function () {
let cachedStr = fs.readFileSync(getCacheFilePath(), 'utf-8');
_tests = JSON.parse(cachedStr);
_tests.forEach(test => {
// In somehow tests are stopped and leave the status pending.
// Set the status to unsettled again.
if (test.status === 'pending') {
test.status = 'unsettled';
}
_testsMap[test.fileUrl] = test;
});
}
......@@ -49,7 +54,8 @@ module.exports.prepareTestsList = async function () {
let test = {
fileUrl,
name: getTestName(fileUrl),
status: 'pending',
// Default status should be unkown
// status: 'pending',
results: []
};
......
......@@ -2,6 +2,9 @@ const path = require('path');
const fse = require('fs-extra');
const https = require('https');
const fs = require('fs');
const rollup = require('rollup');
const resolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
module.exports.getTestName = function(fileUrl) {
return path.basename(fileUrl, '.html');
......@@ -42,4 +45,22 @@ module.exports.prepareEChartsVersion = function (version) {
resolve();
}
});
}
\ No newline at end of file
};
module.exports.buildRuntimeCode = async function () {
const bundle = await rollup.rollup({
input: path.join(__dirname, 'runtime/main.js'),
plugins: [
resolve(),
commonjs()
]
});
const output = await bundle.generate({
format: 'iife',
name: 'autorun'
});
// seedrandom use crypto as external module. Set it to null to avoid not defined error.
// TODO
return 'window.crypto = null\n' + output.code;
};
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册