UNPKG

flagpole

Version:

Simple and fast DOM integration, headless or headful browser, and REST API testing framework.

329 lines 12.8 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SuiteTaskManager = void 0; const bluebird = require("bluebird"); const util_1 = require("../util"); class SuiteTaskManager { constructor(suite) { this._scenarios = []; this._dateStarted = null; this._dateExecutionBegan = null; this._dateExecutionCompleted = null; this._dateFinished = null; this._beforeAllCallbacks = []; this._afterAllCallbacks = []; this._successCallbacks = []; this._failureCallbacks = []; this._finallyCallbacks = []; this._beforeEachCallbacks = []; this._afterEachCallbacks = []; this._statusCallbacks = []; this._concurrencyLimit = 99; this._maxScenarioDuration = 30000; this._maxSuiteDuration = 60000; this._finishedResolve = () => { }; this._suite = suite; this._dateInitialized = Date.now(); this._finishedPromise = new Promise((resolve) => { this._finishedResolve = resolve; }); } get finished() { return this._finishedPromise; } get maxScenarioDuration() { return this._maxScenarioDuration; } set maxScenarioDuration(value) { this._maxScenarioDuration = value; } get maxSuiteDuration() { return this._maxSuiteDuration; } set maxSuiteDuration(value) { this._maxSuiteDuration = value; } get concurrencyLimit() { return this._concurrencyLimit; } set concurrencyLimit(value) { if (this.hasExecutionBegan) { throw "Can not change concurrency limit after execution has started."; } this._concurrencyLimit = value; } get scenarioCount() { return this._scenarios.length; } get hasStarted() { return this._dateStarted !== null; } get hasExecutionBegan() { return this._dateExecutionBegan !== null; } get hasExecutionCompleted() { return this._dateExecutionCompleted !== null; } get hasFinished() { return this._dateFinished !== null; } get canAllSuitesExecute() { return !this._scenarios.some((scenario) => { return !scenario.isReadyToExecute; }); } get haveAnyFailed() { return this._scenarios.some((scenario) => { return scenario.hasFailed; }); } get haveAllPassed() { return this._scenarios.every((scenario) => { return !scenario.hasFailed && scenario.hasFinished; }); } get totalDuration() { return this._dateFinished !== null ? this._dateFinished - this._dateInitialized : null; } get executionDuration() { return this._dateExecutionBegan !== null && this._dateExecutionCompleted !== null ? this._dateExecutionCompleted - this._dateExecutionBegan : null; } get scenarios() { return [...this._scenarios]; } get scenariosNotReadyToExecute() { return this._scenarios.filter((scenario) => { return !scenario.isReadyToExecute; }); } get scenariosReadyToExecute() { return this._scenarios.filter((scenario) => { return scenario.isReadyToExecute; }); } get scenariosFailed() { return this._scenarios.filter((scenario) => { return !scenario.hasPassed && scenario.hasExecuted; }); } get scenariosWaitingToExecute() { return this._scenarios.filter((scenario) => { return scenario.isPending; }); } get scenariosCurrentlyExcuting() { return this._scenarios.filter((scenario) => { return scenario.hasExecuted && !scenario.hasFinished; }); } beforeAll(a, b = false, c = false) { if (this.hasStarted) { throw "Can not add new beforeAll callback after suite has started running."; } this._addCallback("beforeAll", a, b, c); } beforeEach(a, b = false, c = false) { if (this.hasFinished) { throw "Can not add new beforeEach callback after suite has finished running."; } this._addCallback("beforeEach", a, b, c); } afterAll(a, b = false, c = false) { if (this.hasFinished) { throw "Can not add new afterAll callback after suite has finished running."; } this._addCallback("afterAll", a, b, c); } afterEach(a, b = false, c = false) { if (this.hasFinished) { throw "Can not add new afterEach callback after suite has finished running."; } this._addCallback("afterEach", a, b, c); } failure(a, b = false, c = false) { if (this.hasFinished) { throw "Can not add new failure callback after suite has finished running."; } this._addCallback("failure", a, b, c); } success(a, b = false, c = false) { if (this.hasFinished) { throw "Can not add new success callback after suite has finished running."; } this._addCallback("success", a, b, c); } finally(a, b = false, c = false) { if (this.hasFinished) { throw "Can not add new finally callback after suite has finished running."; } this._addCallback("finally", a, b, c); } registerScenario(scenario) { if (this.hasExecutionCompleted) { throw "Can not register new scenario after the suite has completed execution"; } this._scenarios.push(scenario); scenario.before(() => { this._fireScenarioCallbacks(this._beforeEachCallbacks, scenario); }); scenario.after(() => __awaiter(this, void 0, void 0, function* () { this._fireScenarioCallbacks(this._afterEachCallbacks, scenario); })); setTimeout(() => { this._go(); }, 10); } subscribe(callback) { this._statusCallbacks.push(callback); } _go() { return __awaiter(this, void 0, void 0, function* () { if (!this.hasStarted && this.scenarioCount > 0) { this._dateStarted = Date.now(); yield this._fireSuiteCallbacks(this._beforeAllCallbacks); yield this._executeScenarios(); yield this._fireSuiteCallbacks(this._afterAllCallbacks); this.haveAllPassed ? yield this._fireSuiteCallbacks(this._successCallbacks) : yield this._fireSuiteCallbacks(this._failureCallbacks); yield this._fireSuiteCallbacks(this._finallyCallbacks); this._finishedResolve(); } }); } _executeScenarios() { return __awaiter(this, void 0, void 0, function* () { if (this.hasExecutionBegan) { throw "Execution already started"; } this._dateExecutionBegan = Date.now(); return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { const execute = () => __awaiter(this, void 0, void 0, function* () { const scenariosExecuting = yield this._startExecutingScenarios(); if (scenariosExecuting === null) { return resolve(this._cancelScenariosAnyNotFinished("Timed out")); } if (this.scenariosWaitingToExecute.length === 0) { return resolve(this._markSuiteExecutionAsCompleted()); } if (scenariosExecuting.length > 0) { return execute(); } util_1.runAsync(() => { if (this.scenariosWaitingToExecute.length > 0 && this._dateExecutionBegan && Date.now() - this._dateExecutionBegan > this._maxSuiteDuration) { resolve(this._cancelPendingScenarios("Suite timed out! This scenario was never called or had no assertions.")); } if (this.scenariosWaitingToExecute.length > 0) { return execute(); } resolve(this._cancelPendingScenarios("Not able to execute")); }, 50); }); yield execute(); })); }); } _cancelPendingScenarios(reason) { this.scenariosNotReadyToExecute.forEach((scenario) => { scenario.cancel(`Cancelled this scenario. Reason: ${reason}`); }); this._markSuiteExecutionAsCompleted(); return true; } _cancelScenariosAnyNotFinished(reason) { this.scenarios.forEach((scenario) => { if (!scenario.hasFinished) { scenario.cancelOrAbort(`Aborted this scenario. Reason: ${reason}`); } }); this._markSuiteExecutionAsCompleted(); return true; } _startExecutingScenarios() { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { const batch = this.scenariosReadyToExecute; const waitForBrowserToCloseBuffer = 200; if (batch.length > 0) { yield bluebird .map(batch, (scenario) => __awaiter(this, void 0, void 0, function* () { yield this._executeScenario(scenario); yield scenario.waitForFinished(); yield new Promise((resolve) => setTimeout(resolve, waitForBrowserToCloseBuffer)); }), { concurrency: this._concurrencyLimit, }) .timeout(this.maxScenarioDuration + waitForBrowserToCloseBuffer) .catch((err) => { resolve(null); }); } resolve(batch); })); }); } _markSuiteExecutionAsCompleted() { this._dateExecutionCompleted = Date.now(); return true; } _executeScenario(scenario) { return __awaiter(this, void 0, void 0, function* () { if (scenario.hasExecuted) { throw `Scenario ${scenario.title} has already started executing`; } if (!scenario.isReadyToExecute) { throw `Scenario ${scenario.title} is not ready to execute`; } yield scenario.go(); return scenario; }); } _fireSuiteCallbacks(callbacks) { return __awaiter(this, void 0, void 0, function* () { return bluebird.mapSeries(callbacks, (callback) => { return callback.callback(this._suite); }); }); } _fireScenarioCallbacks(callbacks, scenario) { return __awaiter(this, void 0, void 0, function* () { return bluebird.mapSeries(callbacks, (callback) => { return callback.callback(scenario, this._suite); }); }); } _addCallback(whichCallback, a, b = false, c = false) { const message = typeof a === "string" ? a : ""; const callback = (() => { const callback = typeof b === "boolean" ? a : b; return typeof callback === "string" ? () => { } : callback; })(); const prepend = typeof b === "boolean" ? b : c; const callbackAndMessage = { callback: callback, message: message, }; const callbackArrayName = `_${whichCallback}Callbacks`; prepend ? this[callbackArrayName].unshift(callbackAndMessage) : this[callbackArrayName].push(callbackAndMessage); } } exports.SuiteTaskManager = SuiteTaskManager; //# sourceMappingURL=suite-task-manager.js.map