testcafe
Version:
Automated browser testing for the modern web development stack.
120 lines • 15.4 kB
JavaScript
;
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 pinkie_1 = __importDefault(require("pinkie"));
const os_family_1 = __importDefault(require("os-family"));
const promisify_event_1 = __importDefault(require("promisify-event"));
const delay_1 = __importDefault(require("../utils/delay"));
const CHECK_PROCESS_IS_KILLED_TIMEOUT = 5000;
const CHECK_KILLED_DELAY = 1000;
const NEW_LINE_SEPERATOR_RE = /(\r\n)|(\n\r)|\n|\r/g;
const cannotGetListOfProcessError = 'Cannot get list of processes';
const killProcessTimeoutError = 'Kill process timeout';
function getProcessOutputUnix() {
const error = new Error(cannotGetListOfProcessError);
return new pinkie_1.default((resolve, reject) => {
const child = child_process_1.spawn('ps', ['-eo', 'pid,command']);
let stdout = '';
let stderr = '';
child.stdout.on('data', data => {
stdout += data.toString();
});
child.stderr.on('data', data => {
stderr += data.toString();
});
child.on('exit', () => {
if (stderr)
reject(error);
else
resolve(stdout);
});
child.on('error', () => {
reject(error);
});
});
}
function findProcessIdUnix(browserId, psOutput) {
const processIdRegex = new RegExp('^\\s*(\\d+)\\s+.*' + browserId);
const lines = psOutput.split(NEW_LINE_SEPERATOR_RE);
for (let i = 0; i < lines.length; i++) {
const match = processIdRegex.exec(lines[i]);
if (match)
return parseInt(match[1], 10);
}
return null;
}
function isProcessExistUnix(processId, psOutput) {
const processIdRegex = new RegExp('^\\s*' + processId + '\\s+.*');
const lines = psOutput.split(NEW_LINE_SEPERATOR_RE);
return lines.some(line => processIdRegex.test(line));
}
async function findProcessUnix(browserId) {
const output = await getProcessOutputUnix();
return findProcessIdUnix(browserId, output);
}
async function checkUnixProcessIsKilled(processId) {
const output = await getProcessOutputUnix();
if (isProcessExistUnix(processId, output)) {
await delay_1.default(CHECK_KILLED_DELAY);
await checkUnixProcessIsKilled();
}
}
async function killProcessUnix(processId) {
let timeoutError = false;
process.kill(processId);
const killTimeoutTimer = delay_1.default(CHECK_PROCESS_IS_KILLED_TIMEOUT)
.then(() => {
timeoutError = true;
});
return pinkie_1.default.race([killTimeoutTimer, checkUnixProcessIsKilled(processId)]).then(() => {
if (timeoutError)
throw new Error(killProcessTimeoutError);
});
}
async function runWMIC(args) {
const wmicProcess = child_process_1.spawn('wmic.exe', args, { detached: true });
let wmicOutput = '';
wmicProcess.stdout.on('data', data => {
wmicOutput += data.toString();
});
try {
await pinkie_1.default.race([
promisify_event_1.default(wmicProcess.stdout, 'end'),
promisify_event_1.default(wmicProcess, 'error')
]);
return wmicOutput;
}
catch (e) {
return '';
}
}
async function findProcessWin(browserId) {
const wmicArgs = ['process', 'where', `commandline like '%${browserId}%' and name <> 'cmd.exe' and name <> 'wmic.exe'`, 'get', 'processid'];
const wmicOutput = await runWMIC(wmicArgs);
let processList = wmicOutput.split(/\s*\n/);
processList = processList
// NOTE: remove list's header and empty last element, caused by trailing newline
.slice(1, -1)
.map(pid => ({ pid: Number(pid) }));
return processList[0] ? processList[0].pid : null;
}
async function killBrowserProcess(browserId) {
const processId = os_family_1.default.win ? await findProcessWin(browserId) : await findProcessUnix(browserId);
if (!processId)
return true;
try {
if (os_family_1.default.win)
process.kill(processId);
else
await killProcessUnix(processId);
return true;
}
catch (e) {
return false;
}
}
exports.killBrowserProcess = killBrowserProcess;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvY2Vzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9wcm9jZXNzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsaURBQXNDO0FBQ3RDLG9EQUE2QjtBQUM3QiwwREFBMkI7QUFDM0Isc0VBQTZDO0FBQzdDLDJEQUFtQztBQUVuQyxNQUFNLCtCQUErQixHQUFHLElBQUksQ0FBQztBQUM3QyxNQUFNLGtCQUFrQixHQUFnQixJQUFJLENBQUM7QUFDN0MsTUFBTSxxQkFBcUIsR0FBYSxzQkFBc0IsQ0FBQztBQUMvRCxNQUFNLDJCQUEyQixHQUFPLDhCQUE4QixDQUFDO0FBQ3ZFLE1BQU0sdUJBQXVCLEdBQVcsc0JBQXNCLENBQUM7QUFFL0QsU0FBUyxvQkFBb0I7SUFDekIsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQztJQUVyRCxPQUFPLElBQUksZ0JBQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtRQUNuQyxNQUFNLEtBQUssR0FBRyxxQkFBSyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBQ2xELElBQUksTUFBTSxHQUFJLEVBQUUsQ0FBQztRQUNqQixJQUFJLE1BQU0sR0FBSSxFQUFFLENBQUM7UUFFakIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxFQUFFO1lBQzNCLE1BQU0sSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDOUIsQ0FBQyxDQUFDLENBQUM7UUFFSCxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEVBQUU7WUFDM0IsTUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztRQUVILEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFF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a0JBQWtCLENBQUUsU0FBUztJQUMvQyxNQUFNLFNBQVMsR0FBRyxtQkFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sZUFBZSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRTlGLElBQUksQ0FBQyxTQUFTO1FBQ1YsT0FBTyxJQUFJLENBQUM7SUFFaEIsSUFBSTtRQUNBLElBQUksbUJBQUUsQ0FBQyxHQUFHO1lBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQzs7WUFFeEIsTUFBTSxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFckMsT0FBTyxJQUFJLENBQUM7S0FDZjtJQUNELE9BQU8sQ0FBQyxFQUFFO1FBQ04sT0FBTyxLQUFLLENBQUM7S0FDaEI7QUFDTCxDQUFDO0FBakJELGdEQWlCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgUHJvbWlzZSBmcm9tICdwaW5raWUnO1xuaW1wb3J0IE9TIGZyb20gJ29zLWZhbWlseSc7XG5pbXBvcnQgcHJvbWlzaWZ5RXZlbnQgZnJvbSAncHJvbWlzaWZ5LWV2ZW50JztcbmltcG9ydCBkZWxheSBmcm9tICcuLi91dGlscy9kZWxheSc7XG5cbmNvbnN0IENIRUNLX1BST0NFU1NfSVNfS0lMTEVEX1RJTUVPVVQgPSA1MDAwO1xuY29uc3QgQ0hFQ0tfS0lMTEVEX0RFTEFZICAgICAgICAgICAgICA9IDEwMDA7XG5jb25zdCBORVdfTElORV9TRVBFUkFUT1JfUkUgICAgICAgICAgID0gLyhcXHJcXG4pfChcXG5cXHIpfFxcbnxcXHIvZztcbmNvbnN0IGNhbm5vdEdldExpc3RPZlByb2Nlc3NFcnJvciAgICAgPSAnQ2Fubm90IGdldCBsaXN0IG9mIHByb2Nlc3Nlcyc7XG5jb25zdCBraWxsUHJvY2Vzc1RpbWVvdXRFcnJvciAgICAgICAgID0gJ0tpbGwgcHJvY2VzcyB0aW1lb3V0JztcblxuZnVuY3Rpb24gZ2V0UHJvY2Vzc091dHB1dFVuaXggKCkge1xuICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKGNhbm5vdEdldExpc3RPZlByb2Nlc3NFcnJvcik7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBjb25zdCBjaGlsZCA9IHNwYXduKCdwcycsIFsnLWVvJywgJ3BpZCxjb21tYW5kJ10pO1xuICAgICAgICBsZXQgc3Rkb3V0ICA9ICcnO1xuICAgICAgICBsZXQgc3RkZXJyICA9ICcnO1xuXG4gICAgICAgIGNoaWxkLnN0ZG91dC5vbignZGF0YScsIGRhdGEgPT4ge1xuICAgICAgICAgICAgc3Rkb3V0ICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY2hpbGQuc3RkZXJyLm9uKCdkYXRhJywgZGF0YSA9PiB7XG4gICAgICAgICAgICBzdGRlcnIgKz0gZGF0YS50b1N0cmluZygpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjaGlsZC5vbignZXhpdCcsICgpID0+IHtcbiAgICAgICAgICAgIGlmIChzdGRlcnIpXG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICByZXNvbHZlKHN0ZG91dCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNoaWxkLm9uKCdlcnJvcicsICgpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBmaW5kUHJvY2Vzc0lkVW5peCAoYnJvd3NlcklkLCBwc091dHB1dCkge1xuICAgIGNvbnN0IHByb2Nlc3NJZFJlZ2V4ICAgPSBuZXcgUmVnRXhwKCdeXFxcXHMqKFxcXFxkKylcXFxccysuKicgKyBicm93c2VySWQpO1xuICAgIGNvbnN0IGxpbmVzICAgICAgICAgICAgPSBwc091dHB1dC5zcGxpdChORVdfTElORV9TRVBFUkFUT1JfUkUpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBtYXRjaCA9IHByb2Nlc3NJZFJlZ2V4LmV4ZWMobGluZXNbaV0pO1xuXG4gICAgICAgIGlmIChtYXRjaClcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludChtYXRjaFsxXSwgMTApO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBpc1Byb2Nlc3NFeGlzdFVuaXggKHByb2Nlc3NJZCwgcHNPdXRwdXQpIHtcbiAgICBjb25zdCBwcm9jZXNzSWRSZWdleCAgID0gbmV3IFJlZ0V4cCgnXlxcXFxzKicgKyBwcm9jZXNzSWQgKyAnXFxcXHMrLionKTtcbiAgICBjb25zdCBsaW5lcyAgICAgICAgICAgID0gcHNPdXRwdXQuc3BsaXQoTkVXX0xJTkVfU0VQRVJBVE9SX1JFKTtcblxuICAgIHJldHVybiBsaW5lcy5zb21lKGxpbmUgPT4gcHJvY2Vzc0lkUmVnZXgudGVzdChsaW5lKSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmRQcm9jZXNzVW5peCAoYnJvd3NlcklkKSB7XG4gICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgZ2V0UHJvY2Vzc091dHB1dFVuaXgoKTtcblxuICAgIHJldHVybiBmaW5kUHJvY2Vzc0lkVW5peChicm93c2VySWQsIG91dHB1dCk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNoZWNrVW5peFByb2Nlc3NJc0tpbGxlZCAocHJvY2Vzc0lkKSB7XG4gICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgZ2V0UHJvY2Vzc091dHB1dFVuaXgoKTtcblxuICAgIGlmIChpc1Byb2Nlc3NFeGlzdFVuaXgocHJvY2Vzc0lkLCBvdXRwdXQpKSB7XG4gICAgICAgIGF3YWl0IGRlbGF5KENIRUNLX0tJTExFRF9ERUxBWSk7XG5cbiAgICAgICAgYXdhaXQgY2hlY2tVbml4UHJvY2Vzc0lzS2lsbGVkKCk7XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBraWxsUHJvY2Vzc1VuaXggKHByb2Nlc3NJZCkge1xuICAgIGxldCB0aW1lb3V0RXJyb3IgPSBmYWxzZTtcblxuICAgIHByb2Nlc3Mua2lsbChwcm9jZXNzSWQpO1xuXG4gICAgY29uc3Qga2lsbFRpbWVvdXRUaW1lciA9IGRlbGF5KENIRUNLX1BST0NFU1NfSVNfS0lMTEVEX1RJTUVPVVQpXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHRpbWVvdXRFcnJvciA9IHRydWU7XG4gICAgICAgIH0pO1xuXG4gICAgcmV0dXJuIFByb21pc2UucmFjZShba2lsbFRpbWVvdXRUaW1lciwgY2hlY2tVbml4UHJvY2Vzc0lzS2lsbGVkKHByb2Nlc3NJZCldKS50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKHRpbWVvdXRFcnJvcilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihraWxsUHJvY2Vzc1RpbWVvdXRFcnJvcik7XG4gICAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1bldNSUMgKGFyZ3MpIHtcbiAgICBjb25zdCB3bWljUHJvY2VzcyA9IHNwYXduKCd3bWljLmV4ZScsIGFyZ3MsIHsgZGV0YWNoZWQ6IHRydWUgfSk7XG5cbiAgICBsZXQgd21pY091dHB1dCAgPSAnJztcblxuICAgIHdtaWNQcm9jZXNzLnN0ZG91dC5vbignZGF0YScsIGRhdGEgPT4ge1xuICAgICAgICB3bWljT3V0cHV0ICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgICAgICAgICBwcm9taXNpZnlFdmVudCh3bWljUHJvY2Vzcy5zdGRvdXQsICdlbmQnKSxcbiAgICAgICAgICAgIHByb21pc2lmeUV2ZW50KHdtaWNQcm9jZXNzLCAnZXJyb3InKVxuICAgICAgICBdKTtcblxuICAgICAgICByZXR1cm4gd21pY091dHB1dDtcbiAgICB9XG4gICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZmluZFByb2Nlc3NXaW4gKGJyb3dzZXJJZCkge1xuICAgIGNvbnN0IHdtaWNBcmdzICAgID0gWydwcm9jZXNzJywgJ3doZXJlJywgYGNvbW1hbmRsaW5lIGxpa2UgJyUke2Jyb3dzZXJJZH0lJyBhbmQgbmFtZSA8PiAnY21kLmV4ZScgYW5kIG5hbWUgPD4gJ3dtaWMuZXhlJ2AsICdnZXQnLCAncHJvY2Vzc2lkJ107XG4gICAgY29uc3Qgd21pY091dHB1dCAgPSBhd2FpdCBydW5XTUlDKHdtaWNBcmdzKTtcbiAgICBsZXQgcHJvY2Vzc0xpc3QgPSB3bWljT3V0cHV0LnNwbGl0KC9cXHMqXFxuLyk7XG5cbiAgICBwcm9jZXNzTGlzdCA9IHByb2Nlc3NMaXN0XG4gICAgLy8gTk9URTogcmVtb3ZlIGxpc3QncyBoZWFkZXIgYW5kIGVtcHR5IGxhc3QgZWxlbWVudCwgY2F1c2VkIGJ5IHRyYWlsaW5nIG5ld2xpbmVcbiAgICAgICAgLnNsaWNlKDEsIC0xKVxuICAgICAgICAubWFwKHBpZCA9PiAoeyBwaWQ6IE51bWJlcihwaWQpIH0pKTtcblxuICAgIHJldHVybiBwcm9jZXNzTGlzdFswXSA/IHByb2Nlc3NMaXN0WzBdLnBpZCA6IG51bGw7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBraWxsQnJvd3NlclByb2Nlc3MgKGJyb3dzZXJJZCkge1xuICAgIGNvbnN0IHByb2Nlc3NJZCA9IE9TLndpbiA/IGF3YWl0IGZpbmRQcm9jZXNzV2luKGJyb3dzZXJJZCkgOiBhd2FpdCBmaW5kUHJvY2Vzc1VuaXgoYnJvd3NlcklkKTtcblxuICAgIGlmICghcHJvY2Vzc0lkKVxuICAgICAgICByZXR1cm4gdHJ1ZTtcblxuICAgIHRyeSB7XG4gICAgICAgIGlmIChPUy53aW4pXG4gICAgICAgICAgICBwcm9jZXNzLmtpbGwocHJvY2Vzc0lkKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgYXdhaXQga2lsbFByb2Nlc3NVbml4KHByb2Nlc3NJZCk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG4iXX0=