creevey
Version:
creevey is a tool for automated visual testing, that tightly integrated with storybook
171 lines (135 loc) • 15.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _cluster = _interopRequireDefault(require("cluster"));
var _events = require("events");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
class Pool extends _events.EventEmitter {
get isRunning() {
return this.workers.length !== this.freeWorkers.length;
}
constructor(config, browser) {
super();
_defineProperty(this, "maxRetries", void 0);
_defineProperty(this, "browser", void 0);
_defineProperty(this, "config", void 0);
_defineProperty(this, "workers", []);
_defineProperty(this, "queue", []);
_defineProperty(this, "forcedStop", false);
this.maxRetries = config.maxRetries;
this.browser = browser;
this.config = config.browsers[browser];
}
async init() {
this.workers = Array.from({
length: this.config.limit || 1
}).map(() => {
_cluster.default.setupMaster({
args: ['--browser', this.browser, ...process.argv.slice(2)]
});
const worker = _cluster.default.fork();
this.exitHandler(worker);
return worker;
}); // TODO handle errors
const [data] = await Promise.all(this.workers.map(worker => new Promise(resolve => worker.once('message', resolve))));
const message = JSON.parse(data);
if (message.type == 'ready') return;
if (message.type == 'error') throw message.payload.error;
}
start(tests) {
if (this.isRunning) return false;
this.queue = tests.map(({
id,
path
}) => ({
id,
path,
retries: 0
}));
this.process();
return true;
}
stop() {
// TODO Timeout
if (!this.isRunning) {
// TODO this.emit("stop");
return;
}
this.forcedStop = true;
this.queue = [];
}
process() {
const worker = this.getFreeWorker();
const [test] = this.queue;
if (this.queue.length == 0 && this.workers.length === this.freeWorkers.length) {
this.forcedStop = false;
this.emit('stop');
return;
}
if (!worker || !test) return;
const {
id
} = test;
this.queue.shift();
this.sendStatus({
id,
status: 'running'
});
worker.isRunning = true;
worker.once('message', data => {
const message = JSON.parse(data);
if (message.type == 'ready') return;
if (message.type == 'error') worker.disconnect();
const {
payload: result
} = message;
const {
status
} = result;
const shouldRetry = status == 'failed' && test.retries < this.maxRetries && !this.forcedStop;
if (shouldRetry) {
test.retries += 1;
this.queue.push(test);
}
worker.isRunning = false;
this.sendStatus({
id,
status,
result
});
this.process();
});
worker.send(JSON.stringify(test));
this.process();
}
sendStatus(message) {
this.emit('test', message);
}
getFreeWorker() {
return this.freeWorkers[Math.floor(Math.random() * this.freeWorkers.length)];
}
get aliveWorkers() {
return this.workers.filter(worker => !worker.exitedAfterDisconnect);
}
get freeWorkers() {
return this.aliveWorkers.filter(worker => !worker.isRunning);
}
exitHandler(worker) {
worker.once('exit', () => {
_cluster.default.setupMaster({
args: ['--browser', this.browser, ...process.argv.slice(2)]
});
const newWorker = _cluster.default.fork();
this.exitHandler(newWorker); // TODO handle errors
newWorker.once('message', () => {
this.workers[this.workers.indexOf(worker)] = newWorker;
this.process();
});
});
}
}
exports.default = Pool;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zZXJ2ZXIvbWFzdGVyL3Bvb2wudHMiXSwibmFtZXMiOlsiUG9vbCIsIkV2ZW50RW1pdHRlciIsImlzUnVubmluZyIsIndvcmtlcnMiLCJsZW5ndGgiLCJmcmVlV29ya2VycyIsImNvbnN0cnVjdG9yIiwiY29uZmlnIiwiYnJvd3NlciIsIm1heFJldHJpZXMiLCJicm93c2VycyIsImluaXQiLCJBcnJheSIsImZyb20iLCJsaW1pdCIsIm1hcCIsImNsdXN0ZXIiLCJzZXR1cE1hc3RlciIsImFyZ3MiLCJwcm9jZXNzIiwiYXJndiIsInNsaWNlIiwid29ya2VyIiwiZm9yayIsImV4aXRIYW5kbGVyIiwiZGF0YSIsIlByb21pc2UiLCJhbGwiLCJyZXNvbHZlIiwib25jZSIsIm1lc3NhZ2UiLCJKU09OIiwicGFyc2UiLCJ0eXBlIiwicGF5bG9hZCIsImVycm9yIiwic3RhcnQiLCJ0ZXN0cyIsInF1ZXVlIiwiaWQiLCJwYXRoIiwicmV0cmllcyIsInN0b3AiLCJmb3JjZWRTdG9wIiwiZ2V0RnJlZVdvcmtlciIsInRlc3QiLCJlbWl0Iiwic2hpZnQiLCJzZW5kU3RhdHVzIiwic3RhdHVzIiwiZGlzY29ubmVjdCIsInJlc3VsdCIsInNob3VsZFJldHJ5IiwicHVzaCIsInNlbmQiLCJzdHJpbmdpZnkiLCJNYXRoIiwiZmxvb3IiLCJyYW5kb20iLCJhbGl2ZVdvcmtlcnMiLCJmaWx0ZXIiLCJleGl0ZWRBZnRlckRpc2Nvbm5lY3QiLCJuZXdXb3JrZXIiLCJpbmRleE9mIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7Ozs7OztBQUdlLE1BQU1BLElBQU4sU0FBbUJDLG9CQUFuQixDQUFnQztBQU83QyxNQUFXQyxTQUFYLEdBQWdDO0FBQzlCLFdBQU8sS0FBS0MsT0FBTCxDQUFhQyxNQUFiLEtBQXdCLEtBQUtDLFdBQUwsQ0FBaUJELE1BQWhEO0FBQ0Q7O0FBQ0RFLEVBQUFBLFdBQVcsQ0FBQ0MsTUFBRCxFQUFpQkMsT0FBakIsRUFBa0M7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T0FBTDtBQUNELE9BSEQ7QUFJRCxLQVREO0FBVUQ7O0FBM0g0QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjbHVzdGVyIGZyb20gJ2NsdXN0ZXInO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcbmltcG9ydCB7IFdvcmtlciwgQ29uZmlnLCBUZXN0UmVzdWx0LCBCcm93c2VyQ29uZmlnLCBXb3JrZXJNZXNzYWdlLCBUZXN0U3RhdHVzIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQb29sIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgcHJpdmF0ZSBtYXhSZXRyaWVzOiBudW1iZXI7XG4gIHByaXZhdGUgYnJvd3Nlcjogc3RyaW5nO1xuICBwcml2YXRlIGNvbmZpZzogQnJvd3NlckNvbmZpZztcbiAgcHJpdmF0ZSB3b3JrZXJzOiBXb3JrZXJbXSA9IFtdO1xuICBwcml2YXRlIHF1ZXVlOiB7IGlkOiBzdHJpbmc7IHBhdGg6IHN0cmluZ1tdOyByZXRyaWVzOiBudW1iZXIgfVtdID0gW107XG4gIHByaXZhdGUgZm9yY2VkU3RvcCA9IGZhbHNlO1xuICBwdWJsaWMgZ2V0IGlzUnVubmluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy53b3JrZXJzLmxlbmd0aCAhPT0gdGhpcy5mcmVlV29ya2Vycy5sZW5ndGg7XG4gIH1cbiAgY29uc3RydWN0b3IoY29uZmlnOiBDb25maWcsIGJyb3dzZXI6IHN0cmluZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLm1heFJldHJpZXMgPSBjb25maWcubWF4UmV0cmllcztcbiAgICB0aGlzLmJyb3dzZXIgPSBicm93c2VyO1xuICAgIHRoaXMuY29uZmlnID0gY29uZmlnLmJyb3dzZXJzW2Jyb3dzZXJdIGFzIEJyb3dzZXJDb25maWc7XG4gIH1cblxuICBhc3luYyBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMud29ya2VycyA9IEFycmF5LmZyb20oeyBsZW5ndGg6IHRoaXMuY29uZmlnLmxpbWl0IHx8IDEgfSkubWFwKCgpID0+IHtcbiAgICAgIGNsdXN0ZXIuc2V0dXBNYXN0ZXIoeyBhcmdzOiBbJy0tYnJvd3NlcicsIHRoaXMuYnJvd3NlciwgLi4ucHJvY2Vzcy5hcmd2LnNsaWNlKDIpXSB9KTtcbiAgICAgIGNvbnN0IHdvcmtlciA9IGNsdXN0ZXIuZm9yaygpO1xuICAgICAgdGhpcy5leGl0SGFuZGxlcih3b3JrZXIpO1xuICAgICAgcmV0dXJuIHdvcmtlcjtcbiAgICB9KTtcbiAgICAvLyBUT0RPIGhhbmRsZSBlcnJvcnNcbiAgICBjb25zdCBbZGF0YV0gPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIHRoaXMud29ya2Vycy5tYXAoKHdvcmtlcikgPT4gbmV3IFByb21pc2UoKHJlc29sdmU6ICh2YWx1ZTogc3RyaW5nKSA9PiB2b2lkKSA9PiB3b3JrZXIub25jZSgnbWVzc2FnZScsIHJlc29sdmUpKSksXG4gICAgKTtcbiAgICBjb25zdCBtZXNzYWdlOiBXb3JrZXJNZXNzYWdlID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICBpZiAobWVzc2FnZS50eXBlID09ICdyZWFkeScpIHJldHVybjtcbiAgICBpZiAobWVzc2FnZS50eXBlID09ICdlcnJvcicpIHRocm93IG1lc3NhZ2UucGF5bG9hZC5lcnJvcjtcbiAgfVxuXG4gIHN0YXJ0KHRlc3RzOiB7IGlkOiBzdHJpbmc7IHBhdGg6IHN0cmluZ1tdIH1bXSk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlzUnVubmluZykgcmV0dXJuIGZhbHNlO1xuXG4gICAgdGhpcy5xdWV1ZSA9IHRlc3RzLm1hcCgoeyBpZCwgcGF0aCB9KSA9PiAoeyBpZCwgcGF0aCwgcmV0cmllczogMCB9KSk7XG4gICAgdGhpcy5wcm9jZXNzKCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHN0b3AoKTogdm9pZCB7XG4gICAgLy8gVE9ETyBUaW1lb3V0XG4gICAgaWYgKCF0aGlzLmlzUnVubmluZykge1xuICAgICAgLy8gVE9ETyB0aGlzLmVtaXQoXCJzdG9wXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZm9yY2VkU3RvcCA9IHRydWU7XG4gICAgdGhpcy5xdWV1ZSA9IFtdO1xuICB9XG5cbiAgcHJvY2VzcygpOiB2b2lkIHtcbiAgICBjb25zdCB3b3JrZXIgPSB0aGlzLmdldEZyZWVXb3JrZXIoKTtcbiAgICBjb25zdCBbdGVzdF0gPSB0aGlzLnF1ZXVlO1xuXG4gICAgaWYgKHRoaXMucXVldWUubGVuZ3RoID09IDAgJiYgdGhpcy53b3JrZXJzLmxlbmd0aCA9PT0gdGhpcy5mcmVlV29ya2Vycy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZm9yY2VkU3RvcCA9IGZhbHNlO1xuICAgICAgdGhpcy5lbWl0KCdzdG9wJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCF3b3JrZXIgfHwgIXRlc3QpIHJldHVybjtcblxuICAgIGNvbnN0IHsgaWQgfSA9IHRlc3Q7XG5cbiAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG5cbiAgICB0aGlzLnNlbmRTdGF0dXMoeyBpZCwgc3RhdHVzOiAncnVubmluZycgfSk7XG5cbiAgICB3b3JrZXIuaXNSdW5uaW5nID0gdHJ1ZTtcbiAgICB3b3JrZXIub25jZSgnbWVzc2FnZScsIChkYXRhKSA9PiB7XG4gICAgICBjb25zdCBtZXNzYWdlOiBXb3JrZXJNZXNzYWdlID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgIGlmIChtZXNzYWdlLnR5cGUgPT0gJ3JlYWR5JykgcmV0dXJuO1xuICAgICAgaWYgKG1lc3NhZ2UudHlwZSA9PSAnZXJyb3InKSB3b3JrZXIuZGlzY29ubmVjdCgpO1xuXG4gICAgICBjb25zdCB7IHBheWxvYWQ6IHJlc3VsdCB9ID0gbWVzc2FnZTtcbiAgICAgIGNvbnN0IHsgc3RhdHVzIH0gPSByZXN1bHQ7XG4gICAgICBjb25zdCBzaG91bGRSZXRyeSA9IHN0YXR1cyA9PSAnZmFpbGVkJyAmJiB0ZXN0LnJldHJpZXMgPCB0aGlzLm1heFJldHJpZXMgJiYgIXRoaXMuZm9yY2VkU3RvcDtcblxuICAgICAgaWYgKHNob3VsZFJldHJ5KSB7XG4gICAgICAgIHRlc3QucmV0cmllcyArPSAxO1xuICAgICAgICB0aGlzLnF1ZXVlLnB1c2godGVzdCk7XG4gICAgICB9XG5cbiAgICAgIHdvcmtlci5pc1J1bm5pbmcgPSBmYWxzZTtcblxuICAgICAgdGhpcy5zZW5kU3RhdHVzKHsgaWQsIHN0YXR1cywgcmVzdWx0IH0pO1xuICAgICAgdGhpcy5wcm9jZXNzKCk7XG4gICAgfSk7XG4gICAgd29ya2VyLnNlbmQoSlNPTi5zdHJpbmdpZnkodGVzdCkpO1xuICAgIHRoaXMucHJvY2VzcygpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZW5kU3RhdHVzKG1lc3NhZ2U6IHsgaWQ6IHN0cmluZzsgc3RhdHVzOiBUZXN0U3RhdHVzOyByZXN1bHQ/OiBUZXN0UmVzdWx0IH0pOiB2b2lkIHtcbiAgICB0aGlzLmVtaXQoJ3Rlc3QnLCBtZXNzYWdlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RnJlZVdvcmtlcigpOiBXb3JrZXIgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmZyZWVXb3JrZXJzW01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIHRoaXMuZnJlZVdvcmtlcnMubGVuZ3RoKV07XG4gIH1cblxuICBwcml2YXRlIGdldCBhbGl2ZVdvcmtlcnMoKTogV29ya2VyW10ge1xuICAgIHJldHVybiB0aGlzLndvcmtlcnMuZmlsdGVyKCh3b3JrZXIpID0+ICF3b3JrZXIuZXhpdGVkQWZ0ZXJEaXNjb25uZWN0KTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IGZyZWVXb3JrZXJzKCk6IFdvcmtlcltdIHtcbiAgICByZXR1cm4gdGhpcy5hbGl2ZVdvcmtlcnMuZmlsdGVyKCh3b3JrZXIpID0+ICF3b3JrZXIuaXNSdW5uaW5nKTtcbiAgfVxuXG4gIHByaXZhdGUgZXhpdEhhbmRsZXIod29ya2VyOiBXb3JrZXIpOiB2b2lkIHtcbiAgICB3b3JrZXIub25jZSgnZXhpdCcsICgpID0+IHtcbiAgICAgIGNsdXN0ZXIuc2V0dXBNYXN0ZXIoeyBhcmdzOiBbJy0tYnJvd3NlcicsIHRoaXMuYnJvd3NlciwgLi4ucHJvY2Vzcy5hcmd2LnNsaWNlKDIpXSB9KTtcbiAgICAgIGNvbnN0IG5ld1dvcmtlciA9IGNsdXN0ZXIuZm9yaygpO1xuICAgICAgdGhpcy5leGl0SGFuZGxlcihuZXdXb3JrZXIpO1xuICAgICAgLy8gVE9ETyBoYW5kbGUgZXJyb3JzXG4gICAgICBuZXdXb3JrZXIub25jZSgnbWVzc2FnZScsICgpID0+IHtcbiAgICAgICAgdGhpcy53b3JrZXJzW3RoaXMud29ya2Vycy5pbmRleE9mKHdvcmtlcildID0gbmV3V29ya2VyO1xuICAgICAgICB0aGlzLnByb2Nlc3MoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59XG4iXX0=