提交 936afc26 编写于 作者: P pissang

test(visual): provide reload helper

上级 a1803cd2
......@@ -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__();
}
}]
}
......
......@@ -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__();
}
}]
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -183,7 +183,7 @@ under the License.
? target.checked ? 1 : 0
: target.value
);
location.reload();
typeof __VST_RELOAD__ !== 'undefined' && __VST_RELOAD__();
}
};
}
......
......@@ -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);
......
......@@ -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() {
......
......@@ -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.
......
......@@ -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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册