UNPKG

@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
"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