100 lines
14 KiB
JavaScript
100 lines
14 KiB
JavaScript
|
"use strict";
|
||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
const callsite_1 = __importDefault(require("callsite"));
|
||
|
const events_1 = require("events");
|
||
|
const TRACKING_MARK_RE = /^\$\$testcafe_test_run\$\$(\S+)\$\$$/;
|
||
|
const STACK_CAPACITY = 5000;
|
||
|
class TestRunTracker extends events_1.EventEmitter {
|
||
|
constructor() {
|
||
|
super();
|
||
|
this.enabled = false;
|
||
|
this.activeTestRuns = {};
|
||
|
}
|
||
|
_createContextSwitchingFunctionHook(ctxSwitchingFn, patchedArgsCount) {
|
||
|
const tracker = this;
|
||
|
return function () {
|
||
|
const testRunId = tracker.getContextTestRunId();
|
||
|
if (testRunId) {
|
||
|
for (let i = 0; i < patchedArgsCount; i++) {
|
||
|
if (typeof arguments[i] === 'function')
|
||
|
arguments[i] = tracker.addTrackingMarkerToFunction(testRunId, arguments[i]);
|
||
|
}
|
||
|
}
|
||
|
// @ts-ignore
|
||
|
return ctxSwitchingFn.apply(this, arguments);
|
||
|
};
|
||
|
}
|
||
|
_getStackFrames() {
|
||
|
// NOTE: increase stack capacity to seek deep stack entries
|
||
|
const savedLimit = Error.stackTraceLimit;
|
||
|
Error.stackTraceLimit = STACK_CAPACITY;
|
||
|
const frames = (0, callsite_1.default)();
|
||
|
Error.stackTraceLimit = savedLimit;
|
||
|
return frames;
|
||
|
}
|
||
|
getMarkedFnName(testRunId) {
|
||
|
return `$$testcafe_test_run$$${testRunId}$$`;
|
||
|
}
|
||
|
ensureEnabled() {
|
||
|
if (!this.enabled) {
|
||
|
global.setTimeout = this._createContextSwitchingFunctionHook(global.setTimeout, 1);
|
||
|
global.setInterval = this._createContextSwitchingFunctionHook(global.setInterval, 1);
|
||
|
global.setImmediate = this._createContextSwitchingFunctionHook(global.setImmediate, 1);
|
||
|
process.nextTick = this._createContextSwitchingFunctionHook(process.nextTick, 1);
|
||
|
global.Promise.prototype.then = this._createContextSwitchingFunctionHook(global.Promise.prototype.then, 2);
|
||
|
global.Promise.prototype.catch = this._createContextSwitchingFunctionHook(global.Promise.prototype.catch, 1);
|
||
|
this.enabled = true;
|
||
|
}
|
||
|
}
|
||
|
addTrackingMarkerToFunction(testRunId, fn, context) {
|
||
|
const markerFactoryBody = `
|
||
|
return function ${this.getMarkedFnName(testRunId)} () {
|
||
|
context = context || this;
|
||
|
switch (arguments.length) {
|
||
|
case 0: return fn.call(context);
|
||
|
case 1: return fn.call(context, arguments[0]);
|
||
|
case 2: return fn.call(context, arguments[0], arguments[1]);
|
||
|
case 3: return fn.call(context, arguments[0], arguments[1], arguments[2]);
|
||
|
case 4: return fn.call(context, arguments[0], arguments[1], arguments[2], arguments[3]);
|
||
|
default: return fn.apply(context, arguments);
|
||
|
}
|
||
|
};
|
||
|
`;
|
||
|
return new Function('fn', 'context', markerFactoryBody)(fn, context);
|
||
|
}
|
||
|
getContextTestRunId() {
|
||
|
const frames = this._getStackFrames();
|
||
|
// OPTIMIZATION: we start traversing from the bottom of the stack,
|
||
|
// because we'll more likely encounter a marker there.
|
||
|
// Async/await and Promise machinery executes lots of intrinsics
|
||
|
// on timers (where we have a marker). And, since a timer initiates a new
|
||
|
// stack, the marker will be at the very bottom of it.
|
||
|
for (let i = frames.length - 1; i >= 0; i--) {
|
||
|
const fnName = frames[i].getFunctionName();
|
||
|
const match = fnName && fnName.match(TRACKING_MARK_RE);
|
||
|
if (match)
|
||
|
return match[1];
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
resolveContextTestRun() {
|
||
|
const testRunId = this.getContextTestRunId();
|
||
|
if (testRunId)
|
||
|
return this.activeTestRuns[testRunId];
|
||
|
return null;
|
||
|
}
|
||
|
addActiveTestRun(testRun) {
|
||
|
this.activeTestRuns[testRun.id] = testRun;
|
||
|
testRun.onAny((eventName, eventData) => this.emit(eventName, { testRun, data: eventData }));
|
||
|
}
|
||
|
removeActiveTestRun(id) {
|
||
|
delete this.activeTestRuns[id];
|
||
|
}
|
||
|
}
|
||
|
// Tracker
|
||
|
exports.default = new TestRunTracker();
|
||
|
module.exports = exports.default;
|
||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1ydW4tdHJhY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvdGVzdC1ydW4tdHJhY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHdEQUFzQztBQUN0QyxtQ0FBc0M7QUFJdEMsTUFBTSxnQkFBZ0IsR0FBRyxzQ0FBc0MsQ0FBQztBQUNoRSxNQUFNLGNBQWMsR0FBSyxJQUFJLENBQUM7QUFFOUIsTUFBTSxjQUFlLFNBQVEscUJBQVk7SUFJckM7UUFDSSxLQUFLLEVBQUUsQ0FBQztRQUVSLElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxjQUFjLEdBQUcsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFTyxtQ0FBbUMsQ0FBRSxjQUF3QixFQUFFLGdCQUF3QjtRQUMzRixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUM7UUFFckIsT0FBTztZQUNILE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBRWhELElBQUksU0FBUyxFQUFFO2dCQUNYLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxnQkFBZ0IsRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDdkMsSUFBSSxPQUFPLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxVQUFVO3dCQUNsQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLDJCQUEyQixDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDbkY7YUFDSjtZQUVELGFBQWE7WUFDYixPQUFPLGNBQWMsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ2pELENBQUMsQ0FBQztJQUNOLENBQUM7SUFFTyxlQUFlO1FBQ25CLDJEQUEyRDtRQUMzRCxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDO1FBRXpDLEtBQUssQ0FBQyxlQUFlLEdBQUcsY0FBYyxDQUFDO1FBRXZDLE1BQU0sTUFBTSxHQUFHLElBQUEsa0JBQWMsR0FBRSxDQUFDO1FBRWhDLEtBQUssQ0FBQyxlQUFlLEdBQUcsVUFBVSxDQUFDO1FBRW5DLE9BQU8sTUFBTSxDQUFDO0lBQ2xCLENBQUM7SUFFTSxlQUFlLENBQUUsU0FBaUI7UUFDckMsT0FBTyx3QkFBd0IsU0FBUyxJQUFJLENBQUM7SUFDakQsQ0FBQztJQUVNLGFBQWE7UUFDaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDZixNQUFNLENBQUMsVUFBVSxHQUFLLElBQUksQ0FBQyxtQ0FBbUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3JGLE1BQU0sQ0FBQyxXQUFXLEdBQUksSUFBSSxDQUFDLG1DQUFtQyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdEYsTUFBTSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsbUNBQW1DLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN2RixPQUFPLENBQUMsUUFBUSxHQUFNLElBQUksQ0FBQyxtQ0FBbUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRXBGLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksR0FBSSxJQUFJLENBQUMsbUNBQW1DLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzVHLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsbUNBQW1DLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBRTdHLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1NBQ3ZCO0lBQ0wsQ0FBQztJQUVNLDJCQUEyQixDQUFFLFNBQWlCLEVBQUUsRUFBWSxFQUFFLE9BQWE7UUFDOUUsTUFBTSxpQkFBaUIsR0FBRzs4QkFDSCxJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBRTs7Ozs7Ozs7Ozs7U0FXdEQsQ0FBQztRQUVGLE9BQU8sSUFBSSxRQUFRLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN6RSxDQUFDO0lBRU0sbUJBQW1CO1FBQ3RCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUV0QyxrRUFBa0U7UUFDbEUsc0RBQXNEO1FBQ3RELGdFQUFnRTtRQUNoRSx5RUFBeUU7UUFDekUsc0RBQXNEO1FBQ3RELEtBQUssSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN6QyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDM0MsTUFBTSxLQUFLLEdBQUksTUFBTSxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUV4RCxJQUFJLEtBQUs7Z0JBQ0wsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDdkI7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRU0scUJBQXFCO1FBQ3hCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBRTdDLElBQUksU0FBUztZQUNULE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUUxQyxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0lBRU0sZ0JBQWdCLENBQUUsT0FBK0I7UUFDcEQsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDO1FBRTFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFpQixFQUFFLFNBQWtCLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDakgsQ0FBQztJQUVNLG1CQUFtQixDQUFFLEVBQVU7UUFDbEMsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLENBQUM7Q0FDSjtBQUVELFVBQVU7QUFDVixrQkFBZSxJQUFJLGNBQWMsRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGdldFN0YWNrRnJhbWVzIGZyb20gJ2NhbGxzaXRlJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2Z
|