From 65f58a39fa5215b0267d6340eb62ca3be47abb41 Mon Sep 17 00:00:00 2001 From: pissang Date: Sun, 1 Sep 2019 18:44:52 +0800 Subject: [PATCH] test: Fix some logic issue of controlling test in dashboard. --- test/runTest/cli.js | 25 +++++++++++---- test/runTest/client/client.css | 5 +++ test/runTest/client/client.js | 19 +++++++----- test/runTest/client/index.html | 8 ++++- test/runTest/runtime/main.js | 37 +++++++++++----------- test/runTest/server.js | 57 +++++++++++++++++----------------- test/runTest/store.js | 8 ++++- test/runTest/util.js | 23 +++++++++++++- 8 files changed, 118 insertions(+), 64 deletions(-) diff --git a/test/runTest/cli.js b/test/runTest/cli.js index 60b70edb4..afcc8b507 100644 --- a/test/runTest/cli.js +++ b/test/runTest/cli.js @@ -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 diff --git a/test/runTest/client/client.css b/test/runTest/client/client.css index 4a160491d..1d15d890c 100644 --- a/test/runTest/client/client.css +++ b/test/runTest/client/client.css @@ -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; diff --git a/test/runTest/client/client.js b/test/runTest/client/client.js index 99b8b98d1..0dc2607e0 100644 --- a/test/runTest/client/client.js +++ b/test/runTest/client/client.js @@ -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!
Do you want to start now?", 'Tip', { + app.$confirm('It seems you haven\'t run any test yet!
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; }); diff --git a/test/runTest/client/index.html b/test/runTest/client/index.html index 72fd6adc9..ac3cc8abf 100644 --- a/test/runTest/client/index.html +++ b/test/runTest/client/index.html @@ -25,7 +25,6 @@ -
+ + +

{{result.desc || result.name}}

diff --git a/test/runTest/runtime/main.js b/test/runTest/runtime/main.js index d98016dd2..df7cd2a99 100644 --- a/test/runTest/runtime/main.js +++ b/test/runTest/runtime/main.js @@ -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 +// }); diff --git a/test/runTest/server.js b/test/runTest/server.js index a35c51e25..f778a91ef 100644 --- a/test/runTest/server.js +++ b/test/runTest/server.js @@ -1,15 +1,12 @@ 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`); diff --git a/test/runTest/store.js b/test/runTest/store.js index dbfaae9b7..4cd4fc932 100644 --- a/test/runTest/store.js +++ b/test/runTest/store.js @@ -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: [] }; diff --git a/test/runTest/util.js b/test/runTest/util.js index cc721235f..95cab471d 100644 --- a/test/runTest/util.js +++ b/test/runTest/util.js @@ -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 -- GitLab