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