creevey
Version:
Cross-browser screenshot testing tool for Storybook with fancy UI Runner
154 lines (115 loc) • 5.19 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _path = _interopRequireDefault(require("path"));
var _fs = require("fs");
var _util = require("util");
var _master = _interopRequireDefault(require("./master"));
var _api = _interopRequireDefault(require("./api"));
var _types = require("../../types");
var _utils = require("../utils");
var _messages = require("../messages");
var _logger = require("../logger");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const copyFileAsync = (0, _util.promisify)(_fs.copyFile);
const readdirAsync = (0, _util.promisify)(_fs.readdir);
const mkdirAsync = (0, _util.promisify)(_fs.mkdir);
async function copyStatics(reportDir) {
const clientDir = _path.default.join(__dirname, '../../client/web');
const files = (await readdirAsync(clientDir, {
withFileTypes: true
})).filter(dirent => dirent.isFile() && !dirent.name.endsWith('.d.ts') && !dirent.name.endsWith('.tsx')).map(dirent => dirent.name);
await mkdirAsync(reportDir, {
recursive: true
});
for (const file of files) {
await copyFileAsync(_path.default.join(clientDir, file), _path.default.join(reportDir, file));
}
}
function reportDataModule(data) {
return `
(function (root, factory) {
if (typeof module === 'object' && module.exports) {
module.exports = factory();
} else {
root.__CREEVEY_DATA__ = factory();
}
}(this, function () { return ${JSON.stringify(data)} }));
`;
}
function readDirRecursive(dirPath) {
return [].concat(...(0, _fs.readdirSync)(dirPath, {
withFileTypes: true
}).map(dirent => dirent.isDirectory() ? readDirRecursive(`${dirPath}/${dirent.name}`) : [`${dirPath}/${dirent.name}`]));
}
function outputUnnecessaryImages(imagesDir, images) {
if (!(0, _fs.existsSync)(imagesDir)) return;
const unnecessaryImages = readDirRecursive(imagesDir).map(imagePath => _path.default.posix.relative(imagesDir, imagePath)).filter(imagePath => !images.has(imagePath));
if (unnecessaryImages.length > 0) {
_logger.logger.warn('We found unnecessary screenshot images, those can be safely removed:\n', unnecessaryImages.join('\n'));
}
}
async function _default(config, options, resolveApi) {
let runner = null;
if (config.hooks.before) {
await config.hooks.before();
}
(0, _messages.subscribeOn)('shutdown', () => {
var _config$hooks$after, _config$hooks;
return (_config$hooks$after = (_config$hooks = config.hooks).after) === null || _config$hooks$after === void 0 ? void 0 : _config$hooks$after.call(_config$hooks);
});
process.removeListener('SIGINT', _messages.emitShutdownMessage);
process.on('SIGINT', () => {
var _runner, _runner2;
(_runner = runner) === null || _runner === void 0 ? void 0 : _runner.removeAllListeners('stop');
if ((_runner2 = runner) !== null && _runner2 !== void 0 && _runner2.isRunning) {
var _runner4;
// TODO Better handle stop
void Promise.race([new Promise(resolve => setTimeout(resolve, 10000)), new Promise(resolve => {
var _runner3;
return (_runner3 = runner) === null || _runner3 === void 0 ? void 0 : _runner3.once('stop', resolve);
})]).then(() => (0, _utils.shutdownWorkers)());
(_runner4 = runner) === null || _runner4 === void 0 ? void 0 : _runner4.stop();
} else {
void (0, _utils.shutdownWorkers)();
}
});
runner = await (0, _master.default)(config, {
watch: options.ui,
debug: options.debug
});
await runner.init();
if (options.saveReport) {
const reportDataPath = _path.default.join(config.reportDir, 'data.js');
await copyStatics(config.reportDir);
(0, _messages.subscribeOn)('shutdown', () => {
var _runner5;
return (0, _fs.writeFileSync)(reportDataPath, reportDataModule((_runner5 = runner) === null || _runner5 === void 0 ? void 0 : _runner5.status.tests));
});
}
if (options.ui) {
resolveApi((0, _api.default)(runner));
_logger.logger.info(`Started on http://localhost:${options.port}`);
} else {
if (Object.values(runner.status.tests).filter(test => test && !test.skip).length == 0) {
_logger.logger.warn("Don't have any tests to run"); // eslint-disable-next-line no-process-exit
void (0, _utils.shutdownWorkers)().then(() => process.exit());
return;
}
runner.once('stop', () => {
var _runner$status$tests, _runner6;
const tests = Object.values((_runner$status$tests = (_runner6 = runner) === null || _runner6 === void 0 ? void 0 : _runner6.status.tests) !== null && _runner$status$tests !== void 0 ? _runner$status$tests : {});
const isSuccess = tests.filter(_types.isDefined).filter(({
skip
}) => !skip).every(({
status
}) => status == 'success'); // TODO output summary
process.exitCode = isSuccess ? 0 : -1;
outputUnnecessaryImages(config.screenDir, (0, _utils.testsToImages)(tests)); // eslint-disable-next-line no-process-exit
void (0, _utils.shutdownWorkers)().then(() => process.exit());
}); // TODO grep
runner.start(Object.keys(runner.status.tests));
}
}