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