You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by sh...@apache.org on 2021/05/04 08:12:14 UTC
[echarts] branch enhance-visual-regression-test updated:
test(visual): save run config in server and share between clients
This is an automated email from the ASF dual-hosted git repository.
shenyi pushed a commit to branch enhance-visual-regression-test
in repository https://gitbox.apache.org/repos/asf/echarts.git
The following commit(s) were added to refs/heads/enhance-visual-regression-test by this push:
new 3d04768 test(visual): save run config in server and share between clients
3d04768 is described below
commit 3d04768a9eb54e6be644310f6d650722bc357cbd
Author: pissang <bm...@gmail.com>
AuthorDate: Tue May 4 16:10:38 2021 +0800
test(visual): save run config in server and share between clients
---
test/runTest/client/client.js | 158 ++++++++++++++++++-----------------------
test/runTest/client/index.html | 18 +++--
test/runTest/server.js | 43 +++++++++--
test/runTest/util.js | 10 ++-
4 files changed, 124 insertions(+), 105 deletions(-)
diff --git a/test/runTest/client/client.js b/test/runTest/client/client.js
index 8c3d841..bf1db75 100644
--- a/test/runTest/client/client.js
+++ b/test/runTest/client/client.js
@@ -21,6 +21,16 @@ const socket = io('/client');
// const LOCAL_SAVE_KEY = 'visual-regression-testing-config';
+function getChangedObject(target, source) {
+ let changedObject = {};
+ Object.keys(source).forEach(key => {
+ if (target[key] !== source[key]) {
+ changedObject[key] = source[key];
+ }
+ });
+ return changedObject;
+}
+
function parseParams(str) {
if (!str) {
return {};
@@ -79,13 +89,13 @@ function processTestsData(tests, oldTestsData) {
return tests;
}
-const storedConfig = {};
+const urlRunConfig = {};
const urlParams = parseParams(window.location.search.substr(1))
// Save and restore
try {
const runConfig = JSON.parse(urlParams.runConfig);
- Object.assign(storedConfig, runConfig);
+ Object.assign(urlRunConfig, runConfig);
}
catch (e) {}
@@ -100,8 +110,8 @@ const app = new Vue({
allSelected: false,
lastSelectedIndex: -1,
- actualVersionsList: [],
expectedVersionsList: [],
+ actualVersionsList: [],
loadingVersion: false,
@@ -113,6 +123,8 @@ const app = new Vue({
showRunsDialog: false,
testsRuns: [],
+ pageInvisible: false,
+
runConfig: Object.assign({
sortBy: 'name',
@@ -126,21 +138,39 @@ const app = new Vue({
renderer: 'canvas',
threads: 4
- }, storedConfig)
+ }, urlRunConfig)
},
mounted() {
- this.fetchVersions(false);
- this.fetchVersions(true).then(() => {
- socket.emit('setTestVersions', {
- expectedVersion: app.runConfig.expectedVersion,
- actualVersion: app.runConfig.actualVersion,
- renderer: app.runConfig.renderer,
- });
- setTimeout(() => {
- this.scrollToCurrent();
- }, 500);
- })
+ // Sync config from server when first time open
+ // or switching back
+ socket.emit('syncRunConfig', {
+ runConfig: this.runConfig,
+ // Override server config from URL.
+ forceSet: Object.keys(urlRunConfig).length > 0
+ });
+ socket.on('syncRunConfig_return', res => {
+ this.expectedVersionsList = res.expectedVersionsList;
+ this.actualVersionsList = res.actualVersionsList;
+ // Only assign on changed object to avoid unnecessary vue change.
+ Object.assign(this.runConfig, getChangedObject(this.runConfig, res.runConfig));
+
+ updateUrl();
+ });
+
+ setTimeout(() => {
+ this.scrollToCurrent();
+ }, 500);
+
+ document.addEventListener("visibilitychange", () => {
+ if (document.visibilityState === 'visible') {
+ this.pageInvisible = false;
+ socket.emit('syncRunConfig', {});
+ }
+ else {
+ this.pageInvisible = true;
+ }
+ });
},
computed: {
@@ -232,12 +262,6 @@ const app = new Vue({
},
watch: {
- 'runConfig.isActualNightly'() {
- this.fetchVersions(true);
- },
- 'runConfig.isExpectedNightly'() {
- this.fetchVersions(false);
- },
'runConfig.sortBy'() {
setTimeout(() => {
this.scrollToCurrent();
@@ -259,7 +283,7 @@ const app = new Vue({
changeTest(target, testName) {
if (!target.matches('input[type="checkbox"]') && !target.matches('.el-checkbox__inner')) {
app.currentTestName = testName;
- updateUrl(true);
+ updateUrl();
}
},
toggleSort() {
@@ -331,27 +355,6 @@ const app = new Vue({
this.showIframeDialog = true;
},
- fetchVersions(isActual) {
- const prop = isActual ? 'actualVersionsList' : 'expectedVersionsList';
- this[prop] = [];
-
- const url = this.runConfig[isActual ? 'isActualNightly' : 'isExpectedNightly']
- ? 'https://data.jsdelivr.com/v1/package/npm/echarts-nightly'
- : 'https://data.jsdelivr.com/v1/package/npm/echarts'
- return fetch(url, {
- mode: 'cors'
- }).then(res => res.json()).then(json => {
- this[prop] = json.versions;
- this[prop].unshift('local');
-
- if (!isActual) {
- if (!this[prop].includes(this.runConfig.expectedVersion)) {
- this.runConfig.expectedVersion = json.tags.latest;
- }
- }
- });
- },
-
showAllTestsRuns() {
this.showRunsDialog = true;
socket.emit('getAllTestsRuns');
@@ -428,17 +431,18 @@ let firstUpdate = true;
socket.on('update', msg => {
app.$el.style.display = 'block';
- let hasFinishedTest = !!msg.tests.find(test => test.status === 'finished');
- if (!hasFinishedTest && firstUpdate) {
- app.$confirm('You haven\'t run any test on these two versions yet!<br />Do you want to start now?', 'Tip', {
- confirmButtonText: 'Yes',
- cancelButtonText: 'No',
- dangerouslyUseHTMLString: true,
- center: true
- }).then(value => {
- runTests(msg.tests.map(test => test.name));
- }).catch(() => {});
- }
+ // let hasFinishedTest = !!msg.tests.find(test => test.status === 'finished');
+ // if (!hasFinishedTest && firstUpdate) {
+ // app.$confirm('You haven\'t run any test on these two versions yet!<br />Do you want to start now?', 'Tip', {
+ // confirmButtonText: 'Yes',
+ // cancelButtonText: 'No',
+ // dangerouslyUseHTMLString: true,
+ // center: true
+ // }).then(value => {
+ // runTests(msg.tests.map(test => test.name));
+ // }).catch(() => {});
+ // }
+
// TODO
app.running = !!msg.running;
app.fullTests = processTestsData(msg.tests, app.fullTests);
@@ -472,47 +476,21 @@ socket.on('genTestsRunReport_return', res => {
window.open(res.reportUrl, '_blank');
});
-let isFallbacking = false;
-function updateUrl(notRefresh, fallbackParams) {
+function updateUrl() {
const searchUrl = assembleParams({
test: app.currentTestName,
runConfig: JSON.stringify(app.runConfig)
});
- if (notRefresh) {
- history.pushState({}, '', location.pathname + '?' + searchUrl);
- }
- else {
- if (app.running) {
- app.$confirm('Change versions will stop the running tests. <br />Do you still want to continue?', 'Warn', {
- confirmButtonText: 'Yes',
- cancelButtonText: 'No',
- dangerouslyUseHTMLString: true,
- center: true
- }).then(value => {
- window.location.search = '?' + searchUrl;
- }).catch(() => {
- isFallbacking = true;
- Object.assign(app.runConfig, fallbackParams);
- });
- }
- else {
- window.location.search = '?' + searchUrl;
- }
- }
+ history.pushState({}, '', location.pathname + '?' + searchUrl);
}
// Only update url when version is changed.
-app.$watch(() => {
- return {
- actualVersion: app.runConfig.actualVersion,
- expectedVersion: app.runConfig.expectedVersion,
- renderer: app.runConfig.renderer
- };
-}, (newVal, oldVal) => {
- if (!isFallbacking) {
- updateUrl(false, oldVal)
+app.$watch('runConfig', (newVal, oldVal) => {
+ if (!app.pageInvisible) {
+ socket.emit('syncRunConfig', {
+ runConfig: app.runConfig,
+ // Override server config from URL.
+ forceSet: true
+ });
}
- isFallbacking = false;
-});
-// app.$watch('runConfig.expectedVersion', () => updateUrl());
-// app.$watch('runConfig.renderer', () => updateUrl());
\ No newline at end of file
+}, { deep: true });
\ No newline at end of file
diff --git a/test/runTest/client/index.html b/test/runTest/client/index.html
index d8baaaa..dbb376a 100644
--- a/test/runTest/client/index.html
+++ b/test/runTest/client/index.html
@@ -123,7 +123,7 @@ under the License.
<el-progress
type="circle"
:percentage="finishedPercentage"
- :width="25"
+ :width="20"
:stroke-width="4"
:show-text="false"
></el-progress>
@@ -156,10 +156,10 @@ under the License.
<span class="label">
Expected
<el-tooltip content="Use Nightly Build">
- <el-checkbox v-model="runConfig.isExpectedNightly" size="mini"></el-checkbox>
+ <el-checkbox :disabled="running" v-model="runConfig.isExpectedNightly" size="mini"></el-checkbox>
</el-tooltip>
</span>
- <el-select size="mini" v-model="runConfig.expectedVersion" placeholder="Select Version"
+ <el-select :disabled="running" size="mini" v-model="runConfig.expectedVersion" placeholder="Select Version"
:style="`width: ${runConfig.isExpectedNightly ? 160 : 80}px;`"
>
<el-option v-for="version in expectedVersionsList" :key="version" :label="version" :value="version"></el-option>
@@ -168,10 +168,10 @@ under the License.
<span class="label">
Actual
<el-tooltip content="Use Nightly Build">
- <el-checkbox v-model="runConfig.isActualNightly" size="mini"></el-checkbox>
+ <el-checkbox :disabled="running" v-model="runConfig.isActualNightly" size="mini"></el-checkbox>
</el-tooltip>
</span>
- <el-select size="mini" v-model="runConfig.actualVersion" placeholder="Select Version"
+ <el-select :disabled="running" size="mini" v-model="runConfig.actualVersion" placeholder="Select Version"
:style="`width: ${runConfig.isActualNightly ? 160 : 80}px;`"
>
<el-option v-for="version in actualVersionsList" :key="version" :label="version" :value="version"></el-option>
@@ -179,14 +179,18 @@ under the License.
</div>
<div class="run-config-item">
<span class="label">Renderer</span>
- <el-select size="mini" style="width: 100px;" v-model="runConfig.renderer" placeholder="Select Renderer">
+ <el-select :disabled="running" size="mini" style="width: 100px;" v-model="runConfig.renderer" placeholder="Select Renderer">
<el-option key="canvas" label="canvas" value="canvas"></el-option>
<el-option key="svg" label="svg" value="svg"></el-option>
</el-select>
</div>
<div class="run-config-item">
<span class="label">Threads</span>
- <el-slider style="width: 100px;" v-model="runConfig.threads" :step="1" :min="1" :max="8" show-stops></el-slider>
+
+ <el-select :disabled="running" size="mini" v-model="runConfig.threads" style="width: 58px">
+ <el-option v-for="t in [1, 2, 4, 8]" :key="t" :label="t" :value="t"></el-option>
+ </el-select>
+ <!-- <el-slider style="width: 100px;" v-model="runConfig.threads" :step="1" :min="1" :max="8" show-stops></el-slider> -->
</div>
</div>
diff --git a/test/runTest/server.js b/test/runTest/server.js
index 02b1e1e..dd42188 100644
--- a/test/runTest/server.js
+++ b/test/runTest/server.js
@@ -37,7 +37,7 @@ const {
RESULTS_ROOT_DIR,
checkStoreVersion
} = require('./store');
-const {prepareEChartsLib, getActionsFullPath} = require('./util');
+const {prepareEChartsLib, getActionsFullPath, fetchVersions} = require('./util');
const fse = require('fs-extra');
const fs = require('fs');
const open = require('open');
@@ -220,6 +220,7 @@ async function start() {
let _currentTestHash;
+ let _currentRunConfig;
// let runtimeCode = await buildRuntimeCode();
// fse.outputFileSync(path.join(__dirname, 'tmp/testRuntime.js'), runtimeCode, 'utf-8');
@@ -227,6 +228,11 @@ async function start() {
// Start a static server for puppeteer open the html test cases.
let {io} = serve();
+ const stableVersions = await fetchVersions(false);
+ const nightlyVersions = await fetchVersions(true);
+ stableVersions.unshift('local');
+ nightlyVersions.unshift('local');
+
io.of('/client').on('connect', async socket => {
function abortTests() {
if (!running) {
@@ -237,13 +243,40 @@ async function start() {
running = false;
}
- socket.on('setTestVersions', async (params) => {
- if (_currentTestHash !== getRunHash(params)) {
- abortTests();
+ socket.on('syncRunConfig', async ({
+ runConfig,
+ forceSet
+ }) => {
+ // First time open.
+ if ((!_currentRunConfig || forceSet) && runConfig) {
+ _currentRunConfig = runConfig;
+ }
+
+ if (!_currentRunConfig) {
+ return;
+ }
+
+ const expectedVersionsList = _currentRunConfig.isExpectedNightly ? nightlyVersions : stableVersions;
+ const actualVersionsList = _currentRunConfig.isActualNightly ? nightlyVersions : stableVersions;
+ if (!expectedVersionsList.includes(_currentRunConfig.expectedVersion)) {
+ // Pick first version not local
+ _currentRunConfig.expectedVersion = expectedVersionsList[1];
+ }
+ if (!actualVersionsList.includes(_currentRunConfig.actualVersion)) {
+ _currentRunConfig.actualVersion = 'local';
}
+ socket.emit('syncRunConfig_return', {
+ runConfig: _currentRunConfig,
+ expectedVersionsList,
+ actualVersionsList
+ });
+
+ if (_currentTestHash !== getRunHash(_currentRunConfig)) {
+ abortTests();
+ }
await updateTestsList(
- _currentTestHash = getRunHash(params),
+ _currentTestHash = getRunHash(_currentRunConfig),
!running // Set to unsettled if not running
);
diff --git a/test/runTest/util.js b/test/runTest/util.js
index eebe944..53a0937 100644
--- a/test/runTest/util.js
+++ b/test/runTest/util.js
@@ -87,9 +87,13 @@ module.exports.prepareEChartsLib = function (version) {
});
};
-module.exports.fetchVersions = function () {
+module.exports.fetchVersions = function (isNighlty) {
return new Promise((resolve, reject) => {
- https.get(`https://registry.npmjs.org/echarts`, res => {
+ https.get(
+ isNighlty
+ ? `https://registry.npmjs.org/echarts-nightly`
+ : `https://registry.npmjs.org/echarts`
+ , res => {
if (res.statusCode !== 200) {
res.destroy();
reject('Failed fetch versions from https://registry.npmjs.org/echarts');
@@ -100,7 +104,7 @@ module.exports.fetchVersions = function () {
res.on('end', function () {
try {
var data = Buffer.concat(buffers);
- resolve(Object.keys(JSON.parse(data).versions));
+ resolve(Object.keys(JSON.parse(data).versions).reverse());
}
catch (e) {
reject(e.toString());
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org