@serenity-js/playwright-test
Version:
Serenity/JS test runner adapter for Playwright Test, combining Playwright's developer experience with the advanced reporting and automation capabilities of Serenity/JS
116 lines • 5.23 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SerenityReporterForPlaywrightTest = void 0;
const core_1 = require("@serenity-js/core");
const events_1 = require("@serenity-js/core/lib/events");
const model_1 = require("@serenity-js/core/lib/model");
const PlaywrightErrorParser_1 = require("./PlaywrightErrorParser");
const PlaywrightEventBuffer_1 = require("./PlaywrightEventBuffer");
const PlaywrightTestSceneIdFactory_1 = require("./PlaywrightTestSceneIdFactory");
/**
* Serenity/JS reporter that receives notifications from Playwright Test and emits them as
* Serenity/JS [Serenity/JS domain events](https://serenity-js.org/api/core-events/class/DomainEvent/) which can be used by
* Serenity/JS [stage crew members](https://serenity-js.org/api/core/interface/StageCrewMember/).
*/
class SerenityReporterForPlaywrightTest {
errorParser = new PlaywrightErrorParser_1.PlaywrightErrorParser();
sceneIdFactory;
serenity;
unhandledError;
eventBuffer = new PlaywrightEventBuffer_1.PlaywrightEventBuffer();
suiteTestCounts = new Map();
/**
* @param config
*/
constructor(config) {
this.sceneIdFactory = new PlaywrightTestSceneIdFactory_1.PlaywrightTestSceneIdFactory();
this.serenity = new core_1.Serenity(new core_1.Clock(), process.cwd(), this.sceneIdFactory);
this.serenity.configure(config);
}
onBegin(config, suite) {
this.eventBuffer.configure(config);
this.serenity.announce(new events_1.TestRunStarts(this.serenity.currentTime()));
this.countTestsPerSuite(suite);
}
countTestsPerSuite(suite) {
suite.allTests().forEach(test => {
let currentSuite = test.parent;
while (currentSuite) {
const count = this.suiteTestCounts.get(currentSuite) ?? 0;
this.suiteTestCounts.set(currentSuite, count + 1);
currentSuite = currentSuite.parent;
}
});
}
onTestBegin(test, result) {
this.eventBuffer.appendTestStart(test, result);
}
// TODO might be nice to support that by emitting TestStepStarted / Finished
// onStepBegin(test: TestCase, _result: TestResult, step: TestStep): void {
// // console.log('>> onStepBegin');
// }
// todo: add stdout -> Log https://github.com/microsoft/playwright/blob/main/packages/playwright/src/reporters/list.ts#L67
// onStepEnd(test: TestCase, _result: TestResult, step: TestStep): void {
// // console.log('>> onStepEnd');
// }
onTestEnd(test, result) {
const pendingAfterAllHooks = this.countPendingAfterAllHooks(test);
if (test.retries > 0) {
this.eventBuffer.appendRetryableSceneEvents(test, result);
}
this.eventBuffer.appendCrashedWorkerEvents(test, result);
this.eventBuffer.appendSceneEvents(test, result);
if (pendingAfterAllHooks === 0) {
this.eventBuffer.appendSceneFinishedEvent(test, result);
const events = this.eventBuffer.flush(test, result);
this.serenity.announce(...events);
}
else {
this.eventBuffer.deferAppendingSceneFinishedEvent(test, result);
}
}
countPendingAfterAllHooks(test) {
let currentSuite = test.parent;
const pendingAfterAllHooks = [];
while (currentSuite) {
const remainingSuites = (this.suiteTestCounts.get(currentSuite) || 0) - 1;
this.suiteTestCounts.set(currentSuite, remainingSuites);
if (remainingSuites === 0 && currentSuite['_hooks'].some((hook) => hook.type === 'afterAll')) {
pendingAfterAllHooks.push(currentSuite);
}
currentSuite = currentSuite.parent;
}
return pendingAfterAllHooks.length;
}
onError(error) {
if (!this.unhandledError) {
this.unhandledError = this.errorParser.errorFrom(error);
}
}
async onEnd(fullResult) {
const deferredEvents = this.eventBuffer.flushAllDeferred();
this.serenity.announce(...deferredEvents);
const fullDuration = core_1.Duration.ofMilliseconds(Math.round(fullResult.duration));
const endTime = new core_1.Timestamp(fullResult.startTime).plus(fullDuration);
this.serenity.announce(new events_1.TestRunFinishes(endTime));
try {
await this.serenity.waitForNextCue();
const outcome = this.unhandledError
? new model_1.ExecutionFailedWithError(this.unhandledError)
: new model_1.ExecutionSuccessful();
this.serenity.announce(new events_1.TestRunFinished(outcome, endTime));
}
catch (error) {
this.serenity.announce(new events_1.TestRunFinished(new model_1.ExecutionFailedWithError(error), endTime));
throw error;
}
}
// TODO emit a text artifact with stdout
// reporter.onStdErr(chunk, test, result)
// reporter.onStdOut(chunk, test, result)
printsToStdio() {
return true;
}
}
exports.SerenityReporterForPlaywrightTest = SerenityReporterForPlaywrightTest;
//# sourceMappingURL=SerenityReporterForPlaywrightTest.js.map