You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2025/06/24 04:38:57 UTC
(echarts) 02/14: test: Manually sync test utilities.
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a commit to branch fix/contain-label-name
in repository https://gitbox.apache.org/repos/asf/echarts.git
commit 4a42f512257502d8e177a051c6982839a523ffba
Author: 100pah <su...@gmail.com>
AuthorDate: Thu Apr 10 22:20:01 2025 +0800
test: Manually sync test utilities.
---
test/lib/reset.css | 6 +++++
test/lib/testHelper.js | 1 +
test/runTest/cli.js | 42 ++++++++++++++++++++++++++--------
test/runTest/compareScreenshot.js | 6 ++++-
test/runTest/runtime/ActionPlayback.js | 30 ++++++++++++++++++++----
test/runTest/runtime/main.js | 24 ++++++++++++++++++-
6 files changed, 93 insertions(+), 16 deletions(-)
diff --git a/test/lib/reset.css b/test/lib/reset.css
index d17312f5a..f1666779c 100644
--- a/test/lib/reset.css
+++ b/test/lib/reset.css
@@ -52,6 +52,12 @@ body > .main {
padding-right: 2px;
}
+/*
+ * [ CAUTION ]
+ * The existing CSS class names below MUST NOT be modified;
+ * otherwise, some recorded visual test cases may fail.
+ */
+
.test-inputs button {
margin: 10px 5px;
}
diff --git a/test/lib/testHelper.js b/test/lib/testHelper.js
index ae58e64ff..224c2a133 100644
--- a/test/lib/testHelper.js
+++ b/test/lib/testHelper.js
@@ -191,6 +191,7 @@
inputsContainer.className = [
'test-inputs',
+ 'test-buttons', // deprecated but backward compat.
'test-inputs-style-' + (opt.inputsStyle || opt.buttonsStyle || 'normal'),
(inputsHeight != null ? 'test-inputs-fix-height' : '')
].join(' ');
diff --git a/test/runTest/cli.js b/test/runTest/cli.js
index cd9360ce3..cbc40ac5a 100644
--- a/test/runTest/cli.js
+++ b/test/runTest/cli.js
@@ -173,7 +173,7 @@ async function runTestPage(browser, testOpt, source, version, runtimeCode, isExp
const fileUrl = testOpt.fileUrl;
const screenshots = [];
const logs = [];
- const errors = [];
+ const errors = []; // string[]
const page = await browser.newPage();
page.setRequestInterception(true);
@@ -207,14 +207,36 @@ async function runTestPage(browser, testOpt, source, version, runtimeCode, isExp
await page.exposeFunction('__VRT_MOUSE_MOVE__', async (x, y) => {
await page.mouse.move(x, y);
});
- await page.exposeFunction('__VRT_MOUSE_DOWN__', async () => {
- await page.mouse.down();
+ await page.exposeFunction('__VRT_MOUSE_DOWN__', async (errMsgPart) => {
+ try {
+ await page.mouse.down();
+ }
+ catch (err) {
+ // e.g., if double mousedown without a mouseup, error "'left' is already pressed." will be thrown.
+ // Report to users to re-record the test case.
+ if (errMsgPart) {
+ if ((err.message + '').indexOf('already pressed') >= 0) {
+ errMsgPart += ' May be caused by duplicated mousedowns without a mouseup.'
+ + ' Please re-record the test case.';
+ }
+ err.message = err.message + ' ' + errMsgPart;
+ }
+ throw err;
+ }
});
- await page.exposeFunction('__VRT_MOUSE_UP__', async () => {
- await page.mouse.up();
+ await page.exposeFunction('__VRT_MOUSE_UP__', async (errMsgPart) => {
+ try {
+ await page.mouse.up();
+ }
+ catch (err) {
+ if (errMsgPart) {
+ err.message = err.message + ' ' + errMsgPart;
+ }
+ throw err;
+ }
});
- await page.exposeFunction('__VRT_LOAD_ERROR__', async (err) => {
- errors.push(err);
+ await page.exposeFunction('__VRT_LOAD_ERROR__', async (errStr) => {
+ errors.push(errStr);
});
// await page.exposeFunction('__VRT_WAIT_FOR_NETWORK_IDLE__', async () => {
// await waitForNetworkIdle();
@@ -234,8 +256,8 @@ async function runTestPage(browser, testOpt, source, version, runtimeCode, isExp
});
});
- page.exposeFunction('__VRT_LOG_ERRORS__', (err) => {
- errors.push(err);
+ page.exposeFunction('__VRT_LOG_ERRORS__', (errStr) => {
+ errors.push(errStr);
});
let actionScreenshotCount = {};
@@ -276,7 +298,7 @@ async function runTestPage(browser, testOpt, source, version, runtimeCode, isExp
try {
await page.setViewport({
width: 800,
- height: 600
+ height: 600,
});
await page.goto(`${origin}/test/${fileUrl}?__RENDERER__=${program.renderer}&__COARSE__POINTER__=${program.useCoarsePointer}`, {
waitUntil: 'networkidle2',
diff --git a/test/runTest/compareScreenshot.js b/test/runTest/compareScreenshot.js
index dc239666b..769c1b739 100644
--- a/test/runTest/compareScreenshot.js
+++ b/test/runTest/compareScreenshot.js
@@ -47,7 +47,11 @@ module.exports = function (expectedShotPath, actualShotPath, threshold = 0.01) {
(width !== actualImg.width)
|| (height !== actualImg.height)
) {
- throw new Error('Image size not match');
+ throw new Error(
+ 'Image size not match. '
+ + ' expect: ' + width + 'x' + height
+ + ' actual: ' + actualImg.width + 'x' + actualImg.height
+ );
}
const diffPNG = new PNG({width, height});
let diffPixelsCount = pixelmatch(expectedImg.data, actualImg.data, diffPNG.data, width, height, {threshold});
diff --git a/test/runTest/runtime/ActionPlayback.js b/test/runTest/runtime/ActionPlayback.js
index aa50caa67..cad29497c 100644
--- a/test/runTest/runtime/ActionPlayback.js
+++ b/test/runTest/runtime/ActionPlayback.js
@@ -37,6 +37,8 @@ export class ActionPlayback {
this._currentOpIndex = 0;
this._isLastOpMousewheel = false;
+
+ this._isMouseDown = false;
}
getContext() {
@@ -52,6 +54,7 @@ export class ActionPlayback {
this._current = Date.now();
this._elapsedTime = 0;
this._isLastOpMousewheel = false;
+ this._isMouseDown = false;
}
_restoreContext(ctx) {
@@ -103,7 +106,7 @@ export class ActionPlayback {
try {
// Execute all if there are multiple ops in one frame.
do {
- const executed = await self._update(takeScreenshot);
+ const executed = await self._update(takeScreenshot, action.name);
if (!executed) {
break;
}
@@ -117,6 +120,14 @@ export class ActionPlayback {
if (self._currentOpIndex >= self._ops.length) {
// Finished
+ if (self._isMouseDown) {
+ reject(new Error(
+ action.name + ' has finished, but the page remains in mousedown state.'
+ + ' A mouseup is needed; otherwise the subsequent test case may be affected.'
+ + ' Please re-record this test case.'
+ ));
+ return;
+ }
resolve();
}
else {
@@ -135,7 +146,7 @@ export class ActionPlayback {
}
}
- async _update(takeScreenshot) {
+ async _update(takeScreenshot, actionName) {
let op = this._ops[this._currentOpIndex];
if (!op || (op.time > this._elapsedTime)) {
@@ -144,18 +155,23 @@ export class ActionPlayback {
}
let screenshotTaken = false;
+ let errMsgPart;
switch (op.type) {
case 'mousedown':
+ errMsgPart = actionName + ' ' + op.type + ' (' + op.x + ',' + op.y + ')';
// Pause timeline to avoid frame not sync.
timeline.pause();
await __VRT_MOUSE_MOVE__(op.x, op.y);
- await __VRT_MOUSE_DOWN__();
+ await __VRT_MOUSE_DOWN__(errMsgPart);
+ this._isMouseDown = true;
timeline.resume();
break;
case 'mouseup':
+ errMsgPart = actionName + ' ' + op.type + ' (' + op.x + ',' + op.y + ')';
timeline.pause();
await __VRT_MOUSE_MOVE__(op.x, op.y);
- await __VRT_MOUSE_UP__();
+ await __VRT_MOUSE_UP__(errMsgPart);
+ this._isMouseDown = false;
if (window.__VRT_RELOAD_TRIGGERED__) {
return;
}
@@ -187,6 +203,12 @@ export class ActionPlayback {
break;
case 'valuechange':
const selector = document.querySelector(op.selector);
+ if (!selector) {
+ throw new Error(
+ '[Test Case Error] (' + actionName + ') Selector not found: ' + op.selector
+ + '. It may be caused by test case changes.'
+ );
+ }
selector.value = op.value;
// changing value via js won't trigger `change` event, so trigger it manually
selector.dispatchEvent(new Event('change'));
diff --git a/test/runTest/runtime/main.js b/test/runTest/runtime/main.js
index 633911d32..c83bd6640 100644
--- a/test/runTest/runtime/main.js
+++ b/test/runTest/runtime/main.js
@@ -103,7 +103,16 @@ window.__VRT_RUN_ACTIONS__ = async function (actions, restoredActionIndex, resto
continue;
}
window.scrollTo(action.scrollX, action.scrollY);
- await actionPlayback.runAction(action, index === restoredActionIndex ? restoredActionContext : null);
+ try {
+ await actionPlayback.runAction(action, index === restoredActionIndex ? restoredActionContext : null);
+ }
+ catch (err) {
+ // Any error in this JS task must be handled; otherwise __VRT_FINISH_ACTIONS__
+ // can not be called and the entire test execution will be blocked.
+ const errStr = errToStr(err);
+ // console.error(errStr);
+ __VRT_LOG_ERRORS__(errStr);
+ }
}
actionPlayback.stop();
@@ -111,6 +120,19 @@ window.__VRT_RUN_ACTIONS__ = async function (actions, restoredActionIndex, resto
__VRT_FINISH_ACTIONS__();
}
+function errToStr(err) {
+ if (typeof err === 'string') {
+ return err;
+ }
+ if (err && err.message != null) {
+ return err.message + (err.stack ? ' ' + err.stack : '');
+ }
+ if (err && err.toString) {
+ return err.toString();
+ }
+ return '[error] ' + err;
+}
+
window.addEventListener('DOMContentLoaded', () => {
let style = document.createElement('style');
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org