Innovenergy_trunk/frontend/node_modules/testcafe/lib/reporter/index.js

439 lines
64 KiB
JavaScript
Raw Permalink Normal View History

"use strict";
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const is_stream_1 = require("is-stream");
const plugin_host_1 = __importDefault(require("./plugin-host"));
const plugin_methods_1 = __importDefault(require("./plugin-methods"));
const format_command_1 = __importDefault(require("./command/format-command"));
const runtime_1 = require("../errors/runtime");
const reporter_1 = require("../utils/reporter");
const resolve_path_relatively_cwd_1 = __importDefault(require("../utils/resolve-path-relatively-cwd"));
const make_dir_1 = __importDefault(require("make-dir"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const debug_1 = __importDefault(require("debug"));
const debugLog = (0, debug_1.default)('testcafe:reporter');
class Reporter {
constructor(plugin, messageBus, outStream, name) {
this.plugin = new plugin_host_1.default(plugin, outStream, name);
this.messageBus = messageBus;
this.disposed = false;
this.taskInfo = null;
this.outStream = outStream;
this._assignMessageBusEventHandlers();
}
static _isSpecialStream(stream) {
return stream.isTTY || stream === process.stdout || stream === process.stderr;
}
static _createPendingPromise() {
let resolver = null;
const promise = new Promise(resolve => {
resolver = resolve;
});
promise.resolve = resolver;
return promise;
}
async init() {
await this.dispatchToPlugin({
method: plugin_methods_1.default.init,
initialObject: null,
args: [{}],
});
}
async dispatchToPlugin({ method, initialObject, args = [] }) {
try {
// @ts-ignore
await this.plugin[method](...args);
}
catch (originalError) {
const uncaughtError = new runtime_1.ReporterPluginError({
name: this.plugin.name,
method,
originalError,
});
debugLog('Plugin error: %O', uncaughtError);
debugLog('Plugin error: initialObject: %O', initialObject);
if (initialObject)
await initialObject.emit('error', uncaughtError);
else
throw uncaughtError;
}
}
_assignMessageBusEventHandlers() {
const messageBus = this.messageBus;
messageBus.on('warning-add', async (e) => await this._onWarningAddHandler(e));
messageBus.once('start', async (task) => await this._onceTaskStartHandler(task));
messageBus.on('test-run-start', async (testRun) => await this._onTaskTestRunStartHandler(testRun));
messageBus.on('test-run-done', async (testRun) => await this._onTaskTestRunDoneHandler(testRun));
messageBus.on('test-action-start', async (e) => await this._onTaskTestActionStart(e));
messageBus.on('test-action-done', async (e) => await this._onTaskTestActionDone(e));
messageBus.once('done', async () => await this._onceTaskDoneHandler());
}
async dispose() {
var _a;
if (this.disposed)
return Promise.resolve();
this.disposed = true;
if (!(0, lodash_1.isFunction)((_a = this === null || this === void 0 ? void 0 : this.outStream) === null || _a === void 0 ? void 0 : _a.once)
|| Reporter._isSpecialStream(this.outStream)
|| !(0, is_stream_1.writable)(this.outStream))
return Promise.resolve();
const streamFinishedPromise = new Promise(resolve => {
this.outStream.once('finish', resolve);
this.outStream.once('error', resolve);
});
this.outStream.end();
return streamFinishedPromise;
}
static async _ensureOutStream(outStream) {
if (typeof outStream !== 'string')
return outStream;
const fullReporterOutputPath = (0, resolve_path_relatively_cwd_1.default)(outStream);
await (0, make_dir_1.default)(path_1.default.dirname(fullReporterOutputPath));
return fs_1.default.createWriteStream(fullReporterOutputPath);
}
static _addDefaultReporter(reporters) {
reporters.push({
name: 'spec',
output: process.stdout,
});
}
static async getReporterPlugins(reporters = []) {
if (!reporters.length)
Reporter._addDefaultReporter(reporters);
return Promise.all(reporters.map(async ({ name, output, options }) => {
const pluginFactory = (0, reporter_1.getPluginFactory)(name);
const processedName = (0, reporter_1.processReporterName)(name);
const outStream = output ? await Reporter._ensureOutStream(output) : void 0;
return {
plugin: pluginFactory(options),
name: processedName,
outStream,
};
}));
}
async _onWarningAddHandler({ message, testRun, actionId }) {
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportWarnings,
initialObject: this.messageBus,
args: [
{
message,
testRunId: testRun === null || testRun === void 0 ? void 0 : testRun.id,
actionId,
},
],
});
}
//Task
static _createTestItem(test, runsPerTest) {
return {
fixture: test.fixture,
test: test,
testRunIds: [],
screenshotPath: null,
screenshots: [],
videos: [],
quarantine: null,
errs: [],
warnings: [],
unstable: false,
startTime: null,
testRunInfo: null,
pendingRuns: runsPerTest,
pendingStarts: runsPerTest,
pendingTestRunDonePromise: Reporter._createPendingPromise(),
pendingTestRunStartPromise: Reporter._createPendingPromise(),
browsers: [],
};
}
static _createTestQueue(task) {
const runsPerTest = task.browserConnectionGroups.length;
return task.tests.map(test => Reporter._createTestItem(test, runsPerTest));
}
static _createTestRunInfo(reportItem) {
return {
errs: (0, lodash_1.sortBy)(reportItem.errs, ['userAgent', 'code']),
warnings: reportItem.warnings,
durationMs: +new Date() - reportItem.startTime,
unstable: reportItem.unstable,
screenshotPath: reportItem.screenshotPath,
screenshots: reportItem.screenshots,
videos: reportItem.videos,
quarantine: reportItem.quarantine,
skipped: reportItem.test.skip,
browsers: reportItem.browsers,
testId: reportItem.test.id,
fixture: {
id: reportItem.fixture.id,
name: reportItem.fixture.name,
path: reportItem.fixture.path,
meta: reportItem.fixture.meta,
},
};
}
_getTestItemForTestRun(taskInfo, testRun) {
return (0, lodash_1.find)(taskInfo.testQueue, i => i.test === testRun.test);
}
async _shiftTestQueue() {
if (!this.taskInfo)
return;
let currentFixture = null;
let nextReportItem = null;
let testItem = null;
const testQueue = this.taskInfo.testQueue;
while (testQueue.length && testQueue[0].testRunInfo) {
testItem = testQueue.shift();
currentFixture = testItem.fixture;
// NOTE: here we assume that tests are sorted by fixture.
// Therefore, if the next report item has a different
// fixture, we can report this fixture start.
nextReportItem = testQueue[0];
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportTestDone,
initialObject: this.taskInfo.task,
args: [
testItem.test.name,
testItem.testRunInfo,
testItem.test.meta,
],
});
if (!nextReportItem || nextReportItem.fixture === currentFixture)
continue;
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportFixtureStart,
initialObject: this.taskInfo.task,
args: [
nextReportItem.fixture.name,
nextReportItem.fixture.path,
nextReportItem.fixture.meta,
],
});
}
}
async _resolveTestItem(taskInfo, testItem, testRun) {
if (!taskInfo.task)
return;
if (taskInfo.task.screenshots.hasCapturedFor(testRun.test)) {
testItem.screenshotPath = taskInfo.task.screenshots.getPathFor(testRun.test);
testItem.screenshots = taskInfo.task.screenshots.getScreenshotsInfo(testRun.test);
}
if (taskInfo.task.videos)
testItem.videos = taskInfo.task.videos.getTestVideos(testItem.test.id);
if (testRun.quarantine) {
const testItemQuarantine = testRun.quarantine.attempts.reduce((result, { errors }, index) => {
const passed = !errors.length;
const quarantineAttempt = index + 1;
result[quarantineAttempt] = { passed };
return result;
}, {});
Object.assign(testItem.quarantine, testItemQuarantine);
}
if (!testItem.testRunInfo) {
testItem.testRunInfo = Reporter._createTestRunInfo(testItem);
if (testItem.test.skip)
taskInfo.skipped++;
else if (testItem.errs.length)
taskInfo.failed++;
else
taskInfo.passed++;
}
await this._shiftTestQueue();
testItem.pendingTestRunDonePromise.resolve();
}
_prepareReportTestActionEventArgs({ command, duration, result, testRun, err }) {
const args = {};
if (err)
args.err = err;
if (typeof duration === 'number')
args.duration = duration;
const testFixture = testRun.test.fixture;
return Object.assign(args, {
testRunId: testRun.id,
test: {
id: testRun.test.id,
name: testRun.test.name,
phase: testRun.phase,
},
fixture: {
name: testFixture.name,
id: testFixture.id,
},
command: (0, format_command_1.default)(command, result),
browser: testRun.browser,
});
}
async _onceTaskStartHandler(task) {
this.taskInfo = {
task: task,
passed: 0,
failed: 0,
skipped: 0,
testCount: task.tests.filter(test => !test.skip).length,
testQueue: Reporter._createTestQueue(task),
stopOnFirstFail: task.opts.stopOnFirstFail,
pendingTaskDonePromise: Reporter._createPendingPromise(),
};
const startTime = task.startTime;
const browserConnectionsInfo = []
.concat(...task.browserConnectionGroups)
.map(connection => connection.connectionInfo);
const first = this.taskInfo.testQueue[0];
const taskProperties = {
configuration: task.opts,
dashboardUrl: task.opts.dashboardUrl,
};
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportTaskStart,
initialObject: task,
args: [
startTime,
browserConnectionsInfo,
this.taskInfo.testCount,
task.testStructure,
taskProperties,
],
});
if (first) {
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportFixtureStart,
initialObject: task,
args: [
first.fixture.name,
first.fixture.path,
first.fixture.meta,
],
});
}
}
async _onTaskTestRunStartHandler(testRun) {
if (!this.taskInfo)
return void 0;
const testItem = this._getTestItemForTestRun(this.taskInfo, testRun);
testItem.testRunIds.push(testRun.id);
if (!testItem.startTime)
testItem.startTime = +new Date();
testItem.pendingStarts--;
if (!testItem.pendingStarts) {
// @ts-ignore
if (this.plugin.reportTestStart) {
const testStartInfo = {
testRunIds: testItem.testRunIds,
testId: testItem.test.id,
startTime: new Date(testItem.startTime),
skipped: testItem.test.skip,
};
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportTestStart,
initialObject: this.taskInfo.task,
args: [
testItem.test.name,
testItem.test.meta,
testStartInfo,
],
});
}
testItem.pendingTestRunStartPromise.resolve();
}
return testItem.pendingTestRunStartPromise;
}
async _onTaskTestRunDoneHandler(testRun) {
if (!this.taskInfo)
return;
const reportItem = this._getTestItemForTestRun(this.taskInfo, testRun);
const isTestRunStoppedTaskExecution = !!testRun.errs.length && this.taskInfo.stopOnFirstFail;
const browser = Object.assign({ testRunId: testRun.id }, testRun.browser);
reportItem.browsers.push(browser);
reportItem.pendingRuns = isTestRunStoppedTaskExecution ? 0 : reportItem.pendingRuns - 1;
reportItem.unstable = reportItem.unstable || testRun.unstable;
reportItem.errs = reportItem.errs.concat(testRun.errs);
reportItem.warnings = testRun.warningLog ? (0, lodash_1.union)(reportItem.warnings, testRun.warningLog.messages) : [];
if (testRun.quarantine) {
reportItem.quarantine = reportItem.quarantine || {};
const reportItemQuarantine = testRun.quarantine.attempts.reduce((result, { errors, testRunId }) => {
const passed = !errors.length;
result[testRunId] = { passed, errors };
browser.quarantineAttemptsTestRunIds = browser.quarantineAttemptsTestRunIds || [];
browser.quarantineAttemptsTestRunIds.push(testRunId);
return result;
}, {});
Object.assign(reportItem.quarantine, reportItemQuarantine);
}
if (!reportItem.pendingRuns)
await this._resolveTestItem(this.taskInfo, reportItem, testRun);
await reportItem.pendingTestRunDonePromise;
}
async _onTaskTestActionStart(_a) {
var { apiActionName } = _a, restArgs = __rest(_a, ["apiActionName"]);
if (!this.taskInfo)
return;
// @ts-ignore
if (this.plugin.reportTestActionStart) {
restArgs = this._prepareReportTestActionEventArgs(restArgs);
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportTestActionStart,
initialObject: this.taskInfo.task,
args: [
apiActionName,
restArgs,
],
});
}
}
async _onTaskTestActionDone(_a) {
var { apiActionName } = _a, restArgs = __rest(_a, ["apiActionName"]);
if (!this.taskInfo)
return;
// @ts-ignore
if (this.plugin.reportTestActionDone) {
restArgs = this._prepareReportTestActionEventArgs(restArgs);
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportTestActionDone,
initialObject: this.taskInfo.task,
args: [
apiActionName,
restArgs,
],
});
}
}
async _onceTaskDoneHandler() {
var _a;
if (!this.taskInfo)
return;
const endTime = new Date();
const result = {
passedCount: this.taskInfo.passed,
failedCount: this.taskInfo.failed,
skippedCount: this.taskInfo.skipped,
};
await this.dispatchToPlugin({
method: plugin_methods_1.default.reportTaskDone,
initialObject: this.taskInfo.task,
args: [
endTime,
this.taskInfo.passed,
(_a = this.taskInfo.task) === null || _a === void 0 ? void 0 : _a.warningLog.messages,
result,
],
});
this.taskInfo.pendingTaskDonePromise.resolve();
}
}
exports.default = Reporter;
module.exports = exports.default;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwb3J0ZXIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLG1DQUtnQjtBQUVoQix5Q0FBeUQ7QUFDekQsZ0VBQStDO0FBQy9DLHNFQUFvRDtBQUNwRCw4RUFBcUQ7QUFDckQsK0NBQXdEO0FBZ0J4RCxnREFBMEU7QUFDMUUsdUdBQTRFO0FBQzVFLHdEQUErQjtBQUMvQixnREFBd0I7QUFDeEIsNENBQW9CO0FBSXBCLGtEQUEwQjtBQTBGMUIsTUFBTSxRQUFRLEdBQUcsSUFBQSxlQUFLLEVBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUU1QyxNQUFxQixRQUFRO0lBT3pCLFlBQW9CLE1BQXNCLEVBQUUsVUFBc0IsRUFBRSxTQUFtQixFQUFFLElBQVk7UUFDakcsSUFBSSxDQUFDLE1BQU0sR0FBTyxJQUFJLHFCQUFrQixDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFFN0IsSUFBSSxDQUFDLFFBQVEsR0FBSSxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLFFBQVEsR0FBSSxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFFM0IsSUFBSSxDQUFDLDhCQUE4QixFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUVPLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBRSxNQUFnQjtRQUM3QyxPQUFRLE1BQXNCLENBQUMsS0FBSyxJQUFJLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxJQUFJLE1BQU0sS0FBSyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBQ25HLENBQUM7SUFFTyxNQUFNLENBQUMscUJBQXFCO1FBQ2hDLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQztRQUVwQixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFP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