creevey
Version:
Cross-browser screenshot testing tool for Storybook with fancy UI Runner
110 lines • 4.94 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = start;
const path_1 = __importDefault(require("path"));
const fs_1 = require("fs");
const url_1 = require("url");
const promises_1 = require("fs/promises");
const master_js_1 = __importDefault(require("./master.js"));
const api_js_1 = __importDefault(require("./api.js"));
const types_js_1 = require("../../types.js");
const utils_js_1 = require("../utils.js");
const messages_js_1 = require("../messages.js");
const logger_js_1 = require("../logger.js");
const telemetry_js_1 = require("../telemetry.js");
const importMetaUrl = (0, url_1.pathToFileURL)(__filename).href;
async function copyStatics(reportDir) {
const clientDir = path_1.default.join(path_1.default.dirname((0, url_1.fileURLToPath)(importMetaUrl)), '../../client/web');
const files = (await (0, promises_1.readdir)(clientDir, { withFileTypes: true }))
.filter((dirent) => dirent.isFile() && !dirent.name.endsWith('.d.ts') && !dirent.name.endsWith('.tsx'))
.map((dirent) => dirent.name);
await (0, promises_1.mkdir)(reportDir, { recursive: true });
for (const file of files) {
await (0, promises_1.copyFile)(path_1.default.join(clientDir, file), path_1.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 outputUnnecessaryImages(imagesDir, images) {
if (!(0, fs_1.existsSync)(imagesDir))
return;
const unnecessaryImages = (0, utils_js_1.readDirRecursive)(imagesDir)
.map((imagePath) => path_1.default.posix.relative(imagesDir, imagePath))
.filter((imagePath) => !images.has(imagePath));
if (unnecessaryImages.length > 0) {
(0, logger_js_1.logger)().warn('We found unnecessary screenshot images, those can be safely removed:\n', unnecessaryImages.join('\n'));
}
}
async function start(config, options, resolveApi) {
let runner = null;
if (config.hooks.before) {
await config.hooks.before();
}
(0, messages_js_1.subscribeOn)('shutdown', () => config.hooks.after?.());
process.removeListener('SIGINT', utils_js_1.shutdown);
process.on('SIGINT', () => {
runner?.removeAllListeners('stop');
if (runner?.isRunning) {
// TODO Better handle stop
void Promise.race([
new Promise((resolve) => setTimeout(resolve, 10000)),
new Promise((resolve) => runner?.once('stop', resolve)),
]).then(() => (0, utils_js_1.shutdownWorkers)());
runner.stop();
}
else {
void (0, utils_js_1.shutdownWorkers)();
}
});
runner = await (0, master_js_1.default)(config, { watch: options.ui, debug: options.debug, port: options.port });
if (options.saveReport) {
runner.on('stop', () => {
void copyStatics(config.reportDir).then(() => (0, promises_1.writeFile)(path_1.default.join(config.reportDir, 'data.js'), reportDataModule(runner.status.tests)));
});
}
if (options.ui) {
resolveApi((0, api_js_1.default)(runner));
(0, logger_js_1.logger)().info(`Started on http://localhost:${options.port}`);
}
else {
if (Object.values(runner.status.tests).filter((test) => test && !test.skip).length == 0) {
(0, logger_js_1.logger)().warn("Don't have any tests to run");
void (0, utils_js_1.shutdownWorkers)().then(() => process.exit());
return;
}
runner.once('stop', () => {
const tests = Object.values(runner.status.tests);
const isSuccess = tests
.filter(types_js_1.isDefined)
.filter(({ skip }) => !skip)
.every(({ status }) => status == 'success');
// TODO output summary
process.exitCode = isSuccess ? 0 : -1;
if (!config.failFast)
outputUnnecessaryImages(config.screenDir, (0, utils_js_1.testsToImages)(tests));
void (0, telemetry_js_1.sendScreenshotsCount)(config, options, runner.status)
.catch((reason) => {
const error = reason instanceof Error ? (reason.stack ?? reason.message) : reason;
(0, logger_js_1.logger)().warn(`Can't send telemetry: ${error}`);
})
.finally(() => {
void (0, utils_js_1.shutdownWorkers)().then(() => process.exit());
});
});
// TODO grep
runner.start(Object.keys(runner.status.tests));
}
}
//# sourceMappingURL=index.js.map