vizard
Version:
An automated visual regression testing framework
175 lines (135 loc) • 6.7 kB
JavaScript
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
const VizardInstance = require('./vizard');
const toolkit = require('./toolkit');
// Intentionally runs immediately rather than waiting for DOM because the tests do `describe()` straight away
(function () {
const vizardInstance = new VizardInstance();
// describe('BA01BtnPr', function () {...});
window.describe = function (suiteName, testCreator, suiteOptions) {
vizardInstance.registerSuite({suiteName, testCreator, suiteOptions});
};
// it('focused', function (target) {...});
window.it = function (testName, testRunner, testOptions) {
vizardInstance.registerTestCase({testName, testRunner, testOptions});
};
window._registerTests = () => vizardInstance.registerAllTests();
window._runTests = (props) => vizardInstance.runTests(props);
window._getSuites = () => vizardInstance.registeredSuites;
window._getTests = () => vizardInstance.registeredTests;
window._reset = () => vizardInstance.reset;
window.toolkit = toolkit;
})();
},{"./toolkit":2,"./vizard":3}],2:[function(require,module,exports){
const noop = () => {}; // eslint-disable-line no-empty-function
const _setup = () => {
Object.assign(window, {
resetMouse: noop,
takeScreenshot: (args) => console.log('Screenshot would be taken with these args', args),
puppeteerHover: (selector) => console.log('This test involves hovering on this element', document.querySelector(selector)),
puppeteerClick: (selector) => document.querySelector(selector).click(),
});
if (!window._getTests().length) {
window._registerTests();
}
// Clear the target root
const targetRoot = document.getElementById('vizardTargetRoot');
while (targetRoot.hasChildNodes()) {
targetRoot.removeChild(targetRoot.lastChild);
}
};
const runTest = (suiteName, testName) => {
_setup();
const allTests = window._getTests();
const test = allTests.find((test) => test.suiteName === suiteName && test.testName === testName);
if (!test) {
console.warn(`No such test: ${suiteName}/${testName}. Run window._getTests() to see what's available.`);
return;
}
const testTarget = document.getElementById('vizardTargetRoot').appendChild(document.createElement('div'));
console.log(`Running visualisation ${suiteName}/${testName}`);
test.testRunner(testTarget)
.then((elem) => console.log('Screenshot would be taken of this element', elem));
};
module.exports = {
_setup,
runTest,
};
},{}],3:[function(require,module,exports){
const runPromisesSequentially = require('../util/run-promises-sequentially');
const wait = require('../util/wait');
function VizardInstance() {
this.registeredSuites = [];
this.registeredTests = [];
this.currentSuiteName = null;
}
VizardInstance.prototype.registerSuite = function ({suiteName, testCreator, suiteOptions = {}}) {
this.registeredSuites.push({suiteName, testCreator, suiteOptions});
};
VizardInstance.prototype.registerAllTests = function () {
this.registeredSuites.forEach(({testCreator, suiteName}) => {
// Attach the current suite name to the class so when we call `it` we can work out which test we're under
this.currentSuiteName = suiteName;
// Calls the function which will do a bunch of `test('foo', function () {...});
testCreator();
});
};
VizardInstance.prototype.registerTestCase = function ({testName, testRunner, testOptions = {}}) {
this.registeredTests.push({testName, testRunner, suiteName: this.currentSuiteName, testOptions});
};
// Customise those props to run, for example, every 10th tests starting at test 5
// This helps if you want to run tests in parallel
VizardInstance.prototype.runTests = async function ({
tests,
} = {}) {
const vizardTargetRoot = document.getElementById('vizardTargetRoot');
await runPromisesSequentially(tests.map(({screenshotOutputPath, testName, suiteName, options}) => async () => {
const hungConsoleWarningTimeout = setTimeout(() => {
console.log(`${suiteName}/${testName} being slow.`);
}, 5 * 1000); // This is to call out tests that may be 'hung', which is helpful for debugging
const target = vizardTargetRoot.appendChild(document.createElement('div'));
const {testRunner} = this.registeredTests.find((test) => test.testName === testName && test.suiteName === suiteName);
// Run the test to render something to the viewport
let screenshotTarget;
try {
screenshotTarget = await testRunner(target);
} catch (e) {
console.error(`Error running test ${suiteName}/${testName}`, e);
}
if (!screenshotTarget) {
throw new Error(`No screenshot target returned from test ${suiteName}/${testName}. Did you forget to 'return'?`);
}
if (options && options.postRenderDelayMs) {
await wait(options.postRenderDelayMs);
}
await window.takeScreenshot({targetRect: (screenshotTarget || target).getBoundingClientRect(), screenshotOutputPath});
vizardTargetRoot.removeChild(target);
await window.resetMouse();
clearTimeout(hungConsoleWarningTimeout);
}));
};
VizardInstance.prototype.reset = function () {
this.registeredSuites = [];
this.registeredTests = [];
this.currentSuiteName = null;
};
module.exports = VizardInstance;
},{"../util/run-promises-sequentially":4,"../util/wait":5}],4:[function(require,module,exports){
/*
* Given a list of functions returning promises, runs them all in order and resolves an array of the results
*/
module.exports = function runPromisesSequentially(promisesArray) {
return promisesArray.reduce((promiseChain, currentTask) => (
promiseChain.then((chainResults) =>
currentTask().then((currentResult) =>
[...chainResults, currentResult]))
), Promise.resolve([]));
};
},{}],5:[function(require,module,exports){
module.exports = async function wait(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, timeout);
});
};
},{}]},{},[1]);