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/08 12:39:05 UTC

[echarts] 02/02: test(visual): provide reload helper

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

commit 936afc26618065013cfc69a98632a147706203f0
Author: pissang <bm...@gmail.com>
AuthorDate: Sat May 8 20:37:56 2021 +0800

    test(visual): provide reload helper
---
 test/hoverStyle.html                   |  4 +-
 test/hoverStyle2.html                  |  4 +-
 test/lib/simpleRequire.js              | 12 ++++++
 test/line-endLabel.html                |  2 +-
 test/new-tooltip.html                  |  2 +-
 test/runTest/cli.js                    | 15 ++++++--
 test/runTest/runtime/ActionPlayback.js | 22 ++++++++++-
 test/runTest/runtime/main.js           | 67 +++++++++++++++++++++++++++++-----
 test/runTest/runtime/timeline.js       |  6 ++-
 9 files changed, 114 insertions(+), 20 deletions(-)

diff --git a/test/hoverStyle.html b/test/hoverStyle.html
index 513e054..b3b6a0b 100644
--- a/test/hoverStyle.html
+++ b/test/hoverStyle.html
@@ -105,13 +105,13 @@ under the License.
                     text: 'NOT use hoverLayer',
                     onclick: function () {
                         setUseHoverLayer(false);
-                        location.reload();
+                        typeof __VST_RELOAD__ !== 'undefined' && __VST_RELOAD__();
                     }
                 }, {
                     text: 'Use hoverLayer',
                     onclick: function () {
                         setUseHoverLayer(true);
-                        location.reload();
+                        typeof __VST_RELOAD__ !== 'undefined' && __VST_RELOAD__();
                     }
                 }]
             }
diff --git a/test/hoverStyle2.html b/test/hoverStyle2.html
index 7439439..47caadb 100644
--- a/test/hoverStyle2.html
+++ b/test/hoverStyle2.html
@@ -91,13 +91,13 @@ under the License.
                     text: 'NOT use hoverLayer',
                     onclick: function () {
                         setUseHoverLayer(false);
-                        location.reload();
+                        typeof __VST_RELOAD__ !==  'undefined' && __VST_RELOAD__();
                     }
                 }, {
                     text: 'Use hoverLayer',
                     onclick: function () {
                         setUseHoverLayer(true);
-                        location.reload();
+                        typeof __VST_RELOAD__ !==  'undefined' && __VST_RELOAD__();
                     }
                 }]
             }
diff --git a/test/lib/simpleRequire.js b/test/lib/simpleRequire.js
index 53dcd8f..741d2ac 100644
--- a/test/lib/simpleRequire.js
+++ b/test/lib/simpleRequire.js
@@ -29,9 +29,21 @@
 (function (global) {
 
     if (typeof __VST_INIT__ !== 'undefined') {
+        // In the visual regression test environment.
         __VST_INIT__();
+
+        var vstRunContextStr = localStorage.getItem('vstRunContext');
+        if (vstRunContextStr) {
+            window.__VST_RUN_CONTEXT__ = JSON.parse(vstRunContextStr);
+            localStorage.removeItem('vstRunContext');
+        }
+        else {
+            // Clear localStorage to make sure clean run.
+            localStorage.clear();
+        }
     }
 
+
     var requireCfg = { paths: {} }
 
     var currentDefinedFactory;
diff --git a/test/line-endLabel.html b/test/line-endLabel.html
index 2357a23..026fc4a 100644
--- a/test/line-endLabel.html
+++ b/test/line-endLabel.html
@@ -109,7 +109,7 @@ under the License.
                     btn.onclick = (function (cfg) {
                         return function () {
                             setLocalStorage(cfg.text);
-                            location.reload();
+                            typeof __VST_RELOAD__ !== 'undefined' && __VST_RELOAD__();
                         };
                     })(config);
                     fmtBtnBox.appendChild(btn);
diff --git a/test/new-tooltip.html b/test/new-tooltip.html
index 487de29..27733bb 100644
--- a/test/new-tooltip.html
+++ b/test/new-tooltip.html
@@ -183,7 +183,7 @@ under the License.
                             ? target.checked ? 1 : 0
                             : target.value
                     );
-                    location.reload();
+                    typeof __VST_RELOAD__ !== 'undefined' && __VST_RELOAD__();
                 }
             };
         }
diff --git a/test/runTest/cli.js b/test/runTest/cli.js
index 9463c5a..9c6e88f 100644
--- a/test/runTest/cli.js
+++ b/test/runTest/cli.js
@@ -179,6 +179,12 @@ async function runTestPage(browser, testOpt, version, runtimeCode, isExpected) {
         });
     });
 
+    const waitForActionFinishManually = new Promise((resolve) => {
+        page.exposeFunction('__VST_FINISH_ACTIONS__', async () =>  {
+            resolve();
+        });
+    });
+
     page.exposeFunction('__VST_LOG_ERRORS__', (err) =>  {
         errors.push(err);
     });
@@ -210,6 +216,7 @@ async function runTestPage(browser, testOpt, version, runtimeCode, isExpected) {
         logs.push(msg.text());
     });
     page.on('pageerror', error => {
+        console.error('Page Error: ', error.toString());
         errors.push(error.toString());
     });
     page.on('dialog', async dialog => {
@@ -235,7 +242,6 @@ async function runTestPage(browser, testOpt, version, runtimeCode, isExpected) {
         // Wait do screenshot after inited
         await waitForScreenshot;
 
-        // Run actions
         let actions = [];
         try {
             let actContent = fs.readFileSync(path.join(__dirname, 'actions', testOpt.name + '.json'));
@@ -244,14 +250,17 @@ async function runTestPage(browser, testOpt, version, runtimeCode, isExpected) {
         catch (e) {}
         if (actions.length > 0) {
             try {
-                await page.evaluate(async (actions) => {
-                    await __VST_RUN_ACTIONS__(actions);
+                page.evaluate((actions) => {
+                    __VST_RUN_ACTIONS__(actions);
                 }, actions);
             }
             catch (e) {
                 errors.push(e.toString());
             }
         }
+        // We need to use the actions finish signal if there is reload happens in the page.
+        // Because the original __VST_RUN_ACTIONS__ not exists anymore.
+        await waitForActionFinishManually;
     }
     catch(e) {
         console.error(e);
diff --git a/test/runTest/runtime/ActionPlayback.js b/test/runTest/runtime/ActionPlayback.js
index 270f16c..a7de86b 100644
--- a/test/runTest/runtime/ActionPlayback.js
+++ b/test/runTest/runtime/ActionPlayback.js
@@ -39,6 +39,14 @@ export class ActionPlayback {
         this._isLastOpMousewheel = false;
     }
 
+    getContext() {
+        return {
+            elapsedTime: this._elapsedTime,
+            currentOpIndex: this._currentOpIndex,
+            isLastOpMouseWheel: this._isLastOpMousewheel
+        }
+    }
+
     _reset() {
         this._currentOpIndex = 0;
         this._current = Date.now();
@@ -46,8 +54,13 @@ export class ActionPlayback {
         this._isLastOpMousewheel = false;
     }
 
+    _restoreContext(ctx) {
+        this._elapsedTime = ctx.elapsedTime;
+        this._currentOpIndex = ctx.currentOpIndex;
+        this._isLastOpMousewheel = ctx.isLastOpMouseWheel;
+    }
 
-    async runAction(action, playbackSpeed) {
+    async runAction(action, playbackSpeed, ctxToRestore) {
         this.stop();
 
         playbackSpeed = playbackSpeed || 1;
@@ -66,6 +79,13 @@ export class ActionPlayback {
 
         this._reset();
 
+        if (ctxToRestore) {
+            this._restoreContext(ctxToRestore);
+            // Usually restore context happens when page is reloaded after mouseup.
+            // In this case the _currentOpIndex is not increased yet.
+            this._currentOpIndex++;
+        }
+
         let self = this;
 
         async function takeScreenshot() {
diff --git a/test/runTest/runtime/main.js b/test/runTest/runtime/main.js
index ef076b3..4a55030 100644
--- a/test/runTest/runtime/main.js
+++ b/test/runTest/runtime/main.js
@@ -45,24 +45,73 @@ window.__VST_START__ = function () {
     }
     vstStarted = true;
     timeline.start();
-    // Screenshot after 500ms
-    setTimeout(async () => {
-        // Pause timeline until run actions.
-        timeline.pause();
-        await __VST_FULL_SCREENSHOT__();
-    }, 500);
+
+    // TODO not support reload without simpleRequire
+    if (window.__VST_RUN_CONTEXT__) {
+        // Restore from previous run
+        setTimeout(async () => {
+            await __VST_RUN_ACTIONS__(
+                window.__VST_RUN_CONTEXT__.actions,
+                window.__VST_RUN_CONTEXT__.currentActionIndex,
+                window.__VST_RUN_CONTEXT__.currentActionContext
+            )
+        }, 500);
+    }
+    else {
+        // Screenshot after 2000ms (400ms if 5x speed), wait the animation to be finished
+        setTimeout(async () => {
+            // Pause timeline until run actions.
+            timeline.pause();
+            await __VST_FULL_SCREENSHOT__();
+        }, 2000);
+    }
+}
+
+function saveRunningContext(actions, actionIndex, playback) {
+    localStorage.setItem('vstRunContext', JSON.stringify({
+        actions: actions,
+        currentActionIndex: actionIndex,
+        currentActionContext: playback.getContext()
+    }));
 }
 
-window.__VST_RUN_ACTIONS__ = async function (actions) {
+window.__VST_RUN_ACTIONS__ = async function (actions, restoredActionIndex, restoredActionContext) {
+    // Actions can only bu runned once.
     timeline.resume();
+
     const actionPlayback = new ActionPlayback();
-    for (let action of actions) {
+
+    const nativeLocation = window.location;
+    let currentActionIndex = 0;
+
+    // Some test cases change the params through reload().
+    // We need to save the running info and keep running after reload.
+    // window.location seems can't be redefined anymore. So we can only provide helper functions.
+    window.__VST_RELOAD__ = function () {
+        saveRunningContext(actions, currentActionIndex, actionPlayback);
+        timeline.pause();   // Pause timeline to avoid send more messages.
+        timeline.nativeSetTimeout(() => {
+            // CDPSession pay be disconnected if reload immediately.
+            nativeLocation.reload();
+        }, 100);
+    }
+
+    for (const [index, action] of actions.entries()) {
+        currentActionIndex = index;
+        if (index < restoredActionIndex) {
+            continue;
+        }
         window.scrollTo(action.scrollX, action.scrollY);
-        await actionPlayback.runAction(action, __VST_PLAYBACK_SPEED__);
+        await actionPlayback.runAction(action, __VST_PLAYBACK_SPEED__, index === restoredActionIndex ? restoredActionContext : null);
+
     }
     actionPlayback.stop();
+
+    __VST_FINISH_ACTIONS__();
 }
 
+
+
 window.addEventListener('DOMContentLoaded', () => {
     let style = document.createElement('style');
     // Disable all css animation since it will cause screenshot inconsistent.
diff --git a/test/runTest/runtime/timeline.js b/test/runTest/runtime/timeline.js
index 23ba565..c81c631 100644
--- a/test/runTest/runtime/timeline.js
+++ b/test/runTest/runtime/timeline.js
@@ -21,6 +21,8 @@ if (typeof __VST_PLAYBACK_SPEED__ === 'undefined') {
     window.__VST_PLAYBACK_SPEED__ = 1;
 }
 const nativeRaf = window.requestAnimationFrame;
+const nativeSetTimeout = window.setTimeout;
+const nativeSetInterval = window.setInterval;
 const FIXED_FRAME_TIME = 16;
 const MAX_FRAME_TIME = 80;
 const TIMELINE_START = 1566458693300;
@@ -189,4 +191,6 @@ export function pause() {
 
 export function resume() {
     window.__VST_TIMELINE_PAUSED__ = false;
-}
\ No newline at end of file
+}
+
+export { nativeRaf, nativeSetInterval, nativeSetTimeout };
\ No newline at end of file

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org