@browserstack/testcafe
Version:
Automated browser testing for the modern web development stack.
145 lines • 19.3 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const child_process_1 = require("child_process");
const debug_1 = __importDefault(require("debug"));
const promisify_event_1 = __importDefault(require("promisify-event"));
const promisified_functions_1 = require("../../promisified-functions");
const commands_1 = __importDefault(require("./commands"));
const WORKER_PATH = require.resolve('./worker');
const WORKER_STDIO_CONFIG = ['ignore', 'pipe', 'pipe', 'ipc'];
const DEBUG_LOGGER = debug_1.default('testcafe:utils:temp-directory:cleanup-process');
class CleanupProcess {
constructor() {
this.worker = null;
this.initialized = false;
this.initPromise = Promise.resolve(void 0);
this.errorPromise = null;
this.messageCounter = 0;
this.pendingResponses = {};
}
_sendMessage(id, msg) {
return Promise.race([
promisified_functions_1.sendMessageToChildProcess(this.worker, Object.assign({ id }, msg)),
this._waitProcessError()
]);
}
_onResponse(response) {
const pendingResponse = this.pendingResponses[response.id];
if (response.error) {
if (pendingResponse)
pendingResponse.control.reject(response.error);
else
this.pendingResponses[response.id] = Promise.reject(response.error);
}
else if (pendingResponse)
pendingResponse.control.resolve();
else
this.pendingResponses[response.id] = Promise.resolve();
}
async _waitResponse(id) {
if (!this.pendingResponses[id]) {
const promiseControl = {};
this.pendingResponses[id] = new Promise((resolve, reject) => {
Object.assign(promiseControl, { resolve, reject });
});
this.pendingResponses[id].control = promiseControl;
}
try {
await this.pendingResponses[id];
}
finally {
delete this.pendingResponses[id];
}
}
async _waitResponseForMessage(msg) {
const currentId = this.messageCounter;
this.messageCounter++;
await this._sendMessage(currentId, msg);
await this._waitResponse(currentId);
}
_waitProcessExit() {
return promisify_event_1.default(this.worker, 'exit')
.then(exitCode => Promise.reject(new Error(`Worker process terminated with code ${exitCode}`)));
}
_waitProcessError() {
if (this.errorPromise)
return this.errorPromise;
this.errorPromise = promisify_event_1.default(this.worker, 'error');
this.errorPromise.then(() => {
this.errorPromise = null;
});
return this.errorPromise;
}
_setupWorkerEventHandlers() {
this.worker.on('message', message => this._onResponse(message));
this.worker.stdout.on('data', data => DEBUG_LOGGER('Worker process stdout:\n', String(data)));
this.worker.stderr.on('data', data => DEBUG_LOGGER('Worker process stderr:\n', String(data)));
}
_unrefWorkerProcess() {
this.worker.unref();
this.worker.stdout.unref();
this.worker.stderr.unref();
const channel = this.worker.channel || this.worker._channel;
channel.unref();
}
_handleProcessError(error) {
this.initialized = false;
DEBUG_LOGGER(error);
}
init() {
this.initPromise = this.initPromise
.then(async (initialized) => {
if (initialized !== void 0)
return initialized;
this.worker = child_process_1.spawn(process.argv0, [WORKER_PATH], { detached: true, stdio: WORKER_STDIO_CONFIG });
this._setupWorkerEventHandlers();
this._unrefWorkerProcess();
const exitPromise = this._waitProcessExit();
try {
await Promise.race([
this._waitResponseForMessage({ command: commands_1.default.init }),
this._waitProcessError(),
exitPromise
]);
this.initialized = true;
exitPromise.catch(error => this._handleProcessError(error));
this.worker.on('error', error => this._handleProcessError(error));
}
catch (e) {
DEBUG_LOGGER('Failed to start cleanup process');
DEBUG_LOGGER(e);
this.initialized = false;
}
return this.initialized;
});
return this.initPromise;
}
async addDirectory(path) {
if (!this.initialized)
return;
try {
await this._waitResponseForMessage({ command: commands_1.default.add, path });
}
catch (e) {
DEBUG_LOGGER(`Failed to add the ${path} directory to cleanup process`);
DEBUG_LOGGER(e);
}
}
async removeDirectory(path) {
if (!this.initialized)
return;
try {
await this._waitResponseForMessage({ command: commands_1.default.remove, path });
}
catch (e) {
DEBUG_LOGGER(`Failed to remove the ${path} directory in cleanup process`);
DEBUG_LOGGER(e);
}
}
}
exports.default = new CleanupProcess();
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvdGVtcC1kaXJlY3RvcnkvY2xlYW51cC1wcm9jZXNzL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQXNDO0FBQ3RDLGtEQUEwQjtBQUMxQixzRUFBNkM7QUFDN0MsdUVBQXdFO0FBQ3hFLDBEQUFrQztBQUdsQyxNQUFNLFdBQVcsR0FBVyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ3hELE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztBQUU5RCxNQUFNLFlBQVksR0FBRyxlQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQztBQUU1RSxNQUFNLGNBQWM7SUFDaEI7UUFDSSxJQUFJLENBQUMsTUFBTSxHQUFTLElBQUksQ0FBQztRQUN6QixJQUFJLENBQUMsV0FBVyxHQUFJLEtBQUssQ0FBQztRQUMxQixJQUFJLENBQUMsV0FBVyxHQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUM1QyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUV6QixJQUFJLENBQUMsY0FBYyxHQUFHLENBQUMsQ0FBQztRQUV4QixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxZQUFZLENBQUUsRUFBRSxFQUFFLEdBQUc7UUFDakIsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQ2hCLGlEQUF5QixDQUFDLElBQUksQ0FBQyxNQUFNLGtCQUFJLEVBQUUsSUFBSyxHQUFHLEVBQUc7WUFDdEQsSUFBSSxDQUFDLGlCQUFpQixFQUFFO1NBQzNCLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxXQUFXLENBQUUsUUFBUTtRQUNqQixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsZ0JB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QUFDO1lBQ3ZFLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNuQjtJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUFFLElBQUk7UUFDdkIsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXO1lBQ2pCLE9BQU87UUFFWCxJQUFJO1lBQ0EsTUFBTSxJQUFJLENBQUMsdUJBQXVCLENBQUMsRUFBRSxPQUFPLEVBQUUsa0JBQVEsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUMxRTtRQUNELE9BQU8sQ0FBQyxFQUFFO1lBQ04sWUFBWSxDQUFDLHdCQUF3QixJQUFJLCtCQUErQixDQUFDLENBQUM7WUFDMUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ25CO0lBQ0wsQ0FBQztDQUNKO0FBRUQsa0JBQWUsSUFBSSxjQUFjLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgZGVidWcgZnJvbSAnZGVidWcnO1xuaW1wb3J0IHByb21pc2lmeUV2ZW50IGZyb20gJ3Byb21pc2lmeS1ldmVudCc7XG5pbXBvcnQgeyBzZW5kTWVzc2FnZVRvQ2hpbGRQcm9jZXNzIH0gZnJvbSAnLi4vLi4vcHJvbWlzaWZpZWQtZnVuY3Rpb25zJztcbmltcG9ydCBDT01NQU5EUyBmcm9tICcuL2NvbW1hbmRzJztcblxuXG5jb25zdCBXT1JLRVJfUEFUSCAgICAgICAgID0gcmVxdWlyZS5yZXNvbHZlKCcuL3dvcmtlcicpO1xuY29uc3QgV09SS0VSX1NURElPX0NPTkZJRyA9IFsnaWdub3JlJywgJ3BpcGUnLCAncGlwZScsICdpcGMnXTtcblxuY29uc3QgREVCVUdfTE9HR0VSID0gZGVidWcoJ3Rlc3RjYWZlOnV0aWxzOnRlbXAtZGlyZWN0b3J5OmNsZWFudXAtcHJvY2VzcycpO1xuXG5jbGFzcyBDbGVhbnVwUHJvY2VzcyB7XG4gICAgY29uc3RydWN0b3IgKCkge1xuICAgICAgICB0aGlzLndvcmtlciAgICAgICA9IG51bGw7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaW5pdFByb21pc2UgID0gUHJvbWlzZS5yZXNvbHZlKHZvaWQgMCk7XG4gICAgICAgIHRoaXMuZXJyb3JQcm9taXNlID0gbnVsbDtcblxuICAgICAgICB0aGlzLm1lc3NhZ2VDb3VudGVyID0gMDtcblxuICAgICAgICB0aGlzLnBlbmRpbmdSZXNwb25zZXMgPSB7fTtcbiAgICB9XG5cbiAgICBfc2VuZE1lc3NhZ2UgKGlkLCBtc2cpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmFjZShbXG4gICAgICAgICAgICBzZW5kTWVzc2FnZVRvQ2hpbGRQcm9jZXNzKHRoaXMud29ya2VyLCB7IGlkLCAuLi5tc2cgfSksXG4gICAgICAgICAgICB0aGlzLl93YWl0UHJvY2Vzc0Vycm9yKClcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgX29uUmVzcG9uc2UgKHJlc3BvbnNlKSB7XG4gICAgICAgIGNvbnN0IHBlbmRpbmdSZXNwb25zZSA9IHRoaXMucGVuZGluZ1Jlc3BvbnNlc1tyZXNwb25zZS5pZF07XG5cbiAgICAgICAgaWYgKHJlc3BvbnNlLmVycm9yKSB7XG4gICAgICAgICAgICBpZiAocGVuZGluZ1Jlc3BvbnNlKVxuICAgICAgICAgICAgICAgIHBlbmRpbmdSZXNwb25zZS5jb250cm9sLnJlamVjdChyZXNwb25zZS5lcnJvcik7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW3Jlc3BvbnNlLmlkXSA9IFByb21pc2UucmVqZWN0KHJlc3BvbnNlLmVycm9yKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChwZW5kaW5nUmVzcG9uc2UpXG4gICAgICAgICAgICBwZW5kaW5nUmVzcG9uc2UuY29udHJvbC5yZXNvbHZlKCk7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRoaXMucGVuZGluZ1Jlc3BvbnNlc1tyZXNwb25zZS5pZF0gPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBhc3luYyBfd2FpdFJlc3BvbnNlIChpZCkge1xuICAgICAgICBpZiAoIXRoaXMucGVuZGluZ1Jlc3BvbnNlc1tpZF0pIHtcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VDb250cm9sID0ge307XG5cbiAgICAgICAgICAgIHRoaXMucGVuZGluZ1Jlc3BvbnNlc1tpZF0gPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihwcm9taXNlQ29udHJvbCwgeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW2lkXS5jb250cm9sID0gcHJvbWlzZUNvbnRyb2w7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5wZW5kaW5nUmVzcG9uc2VzW2lkXTtcbiAgICAgICAgfVxuICAgICAgICBmaW5hbGx5IHtcbiAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnBlbmRpbmdSZXNwb25zZXNbaWRdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgX3dhaXRSZXNwb25zZUZvck1lc3NhZ2UgKG1zZykge1xuICAgICAgICBjb25zdCBjdXJyZW50SWQgPSB0aGlzLm1lc3NhZ2VDb3VudGVyO1xuXG4gICAgICAgIHRoaXMubWVzc2FnZUNvdW50ZXIrKztcblxuICAgICAgICBhd2FpdCB0aGlzLl9zZW5kTWVzc2FnZShjdXJyZW50SWQsIG1zZyk7XG4gICAgICAgIGF3YWl0IHRoaXMuX3dhaXRSZXNwb25zZShjdXJyZW50SWQpO1xuICAgIH1cblxuICAgIF93YWl0UHJvY2Vzc0V4aXQgKCkge1xuICAgICAgICByZXR1cm4gcHJvbWlzaWZ5RXZlbnQodGhpcy53b3JrZXIsICdleGl0JylcbiAgICAgICAgICAgIC50aGVuKGV4aXRDb2RlID0+IFByb21pc2UucmVqZWN0KG5ldyBFcnJvcihgV29ya2VyIHByb2Nlc3MgdGVybWluYXRlZCB3aXRoIGNvZGUgJHtleGl0Q29kZX1gKSkpO1xuICAgIH1cblxuICAgIF93YWl0UHJvY2Vzc0Vycm9yICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZXJyb3JQcm9taXNlKVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXJyb3JQcm9taXNlO1xuXG4gICAgICAgIHRoaXMuZXJyb3JQcm9taXNlID0gcHJvbWlzaWZ5RXZlbnQodGhpcy53b3JrZXIsICdlcnJvcicpO1xuXG4gICAgICAgIHRoaXMuZXJyb3JQcm9taXNlLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5lcnJvclByb21pc2UgPSBudWxsO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcy5lcnJvclByb21pc2U7XG4gICAgfVxuXG4gICAgX3NldHVwV29ya2VyRXZlbnRIYW5kbGVycyAoKSB7XG4gICAgICAgIHRoaXMud29ya2VyLm9uKCdtZXNzYWdlJywgbWVzc2FnZSA9PiB0aGlzLl9vblJlc3BvbnNlKG1lc3NhZ2UpKTtcblxuICAgICAgICB0aGlzLndvcmtlci5zdGRvdXQub24oJ2RhdGEnLCBkYXRhID0+IERFQlVHX0xPR0dFUignV29ya2VyIHByb2Nlc3Mgc3Rkb3V0OlxcbicsIFN0cmluZyhkYXRhKSkpO1xuICAgICAgICB0aGlzLndvcmtlci5zdGRlcnIub24oJ2RhdGEnLCBkYXRhID0+IERFQlVHX0xPR0dFUignV29ya2VyIHByb2Nlc3Mgc3RkZXJyOlxcbicsIFN0cmluZyhkYXRhKSkpO1xuICAgIH1cblxuICAgIF91bnJlZldvcmtlclByb2Nlc3MgKCkge1xuICAgICAgICB0aGlzLndvcmtlci51bnJlZigpO1xuICAgICAgICB0aGlzLndvcmtlci5zdGRvdXQudW5yZWYoKTtcbiAgICAgICAgdGhpcy53b3JrZXIuc3RkZXJyLnVucmVmKCk7XG5cbiAgICAgICAgY29uc3QgY2hhbm5lbCA9IHRoaXMud29ya2VyLmNoYW5uZWwgfHwgdGhpcy53b3JrZXIuX2NoYW5uZWw7XG5cbiAgICAgICAgY2hhbm5lbC51bnJlZigpO1xuICAgIH1cblxuICAgIF9oYW5kbGVQcm9jZXNzRXJyb3IgKGVycm9yKSB7XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSBmYWxzZTtcblxuICAgICAgICBERUJVR19MT0dHRVIoZXJyb3IpO1xuICAgIH1cblxuICAgIGluaXQgKCkge1xuICAgICAgICB0aGlzLmluaXRQcm9taXNlID0gdGhpcy5pbml0UHJvbWlzZVxuICAgICAgICAgICAgLnRoZW4oYXN5bmMgaW5pdGlhbGl6ZWQgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChpbml0aWFsaXplZCAhPT0gdm9pZCAwKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5pdGlhbGl6ZWQ7XG5cbiAgICAgICAgICAgICAgICB0aGlzLndvcmtlciA9IHNwYXduKHByb2Nlc3MuYXJndjAsIFtXT1JLRVJfUEFUSF0sIHsgZGV0YWNoZWQ6IHRydWUsIHN0ZGlvOiBXT1JLRVJfU1RESU9fQ09ORklHIH0pO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0dXBXb3JrZXJFdmVudEhhbmRsZXJzKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fdW5yZWZXb3JrZXJQcm9jZXNzKCk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBleGl0UHJvbWlzZSA9IHRoaXMuX3dhaXRQcm9jZXNzRXhpdCgpO1xuXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5yYWNlKFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3dhaXRSZXNwb25zZUZvck1lc3NhZ2UoeyBjb21tYW5kOiBDT01NQU5EUy5pbml0IH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fd2FpdFByb2Nlc3NFcnJvcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgZXhpdFByb21pc2VcbiAgICAgICAgICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgZXhpdFByb21pc2UuY2F0Y2goZXJyb3IgPT4gdGhpcy5faGFuZGxlUHJvY2Vzc0Vycm9yKGVycm9yKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy53b3JrZXIub24oJ2Vycm9yJywgZXJyb3IgPT4gdGhpcy5faGFuZGxlUHJvY2Vzc0Vycm9yKGVycm9yKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIERFQlVHX0xPR0dFUignRmFpbGVkIHRvIHN0YXJ0IGNsZWFudXAgcHJvY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICBERUJVR19MT0dHRVIoZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmluaXRpYWxpemVkO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaW5pdFByb21pc2U7XG4gICAgfVxuXG4gICAgYXN5bmMgYWRkRGlyZWN0b3J5IChwYXRoKSB7XG4gICAgICAgIGlmICghdGhpcy5pbml0aWFsaXplZClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fd2FpdFJlc3BvbnNlRm9yTWVzc2FnZSh7IGNvbW1hbmQ6IENPTU1BTkRTLmFkZCwgcGF0aCB9KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgREVCVUdfTE9HR0VSKGBGYWlsZWQgdG8gYWRkIHRoZSAke3BhdGh9IGRpcmVjdG9yeSB0byBjbGVhbnVwIHByb2Nlc3NgKTtcbiAgICAgICAgICAgIERFQlVHX0xPR0dFUihlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIHJlbW92ZURpcmVjdG9yeSAocGF0aCkge1xuICAgICAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpXG4gICAgICAgICAgICByZXR1cm47XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX3dhaXRSZXNwb25zZUZvck1lc3NhZ2UoeyBjb21tYW5kOiBDT01NQU5EUy5yZW1vdmUsIHBhdGggfSk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIERFQlVHX0xPR0dFUihgRmFpbGVkIHRvIHJlbW92ZSB0aGUgJHtwYXRofSBkaXJlY3RvcnkgaW4gY2xlYW51cCBwcm9jZXNzYCk7XG4gICAgICAgICAgICBERUJVR19MT0dHRVIoZSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IG5ldyBDbGVhbnVwUHJvY2VzcygpO1xuIl19