UNPKG

playwright-bdd

Version:
152 lines 7.23 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.TestStepRun = void 0; const messages = __importStar(require("@cucumber/messages")); const timing_1 = require("./timing"); const TestStepAttachments_1 = require("./TestStepAttachments"); const pwStepUtils_1 = require("./pwStepUtils"); const Exception_1 = require("./Exception"); /** * Run of messages.TestStep from hook or scenario. */ class TestStepRun { constructor(testCaseRun, testStep, pwStep) { this.testCaseRun = testCaseRun; this.testStep = testStep; this.pwStep = pwStep; } buildMessages() { const stepAttachments = new TestStepAttachments_1.TestStepAttachments(this.testCaseRun, this.testStep, this.pwStep); return [ this.buildTestStepStarted(), // prettier-ignore ...stepAttachments.buildMessages(), this.buildTestStepFinished(), ]; } isHook() { return Boolean(this.testStep.hookId); } wasExecuted() { return Boolean(this.pwStep); } get startTime() { return this.wasExecuted() ? this.pwStep.startTime : this.testCaseRun.result.startTime; } get duration() { return this.wasExecuted() ? this.pwStep.duration : 0; } buildTestStepStarted() { const testStepStarted = { testCaseStartedId: this.testCaseRun.id, testStepId: this.testStep.id, timestamp: (0, timing_1.toCucumberTimestamp)(this.startTime.getTime()), }; return { testStepStarted }; } buildTestStepFinished() { const error = this.getStepError(); const status = this.getStatus(error); const exception = isStepFailed(status) && error ? (0, Exception_1.buildException)(error) : undefined; const testStepFinished = { testCaseStartedId: this.testCaseRun.id, testStepId: this.testStep.id, testStepResult: { duration: messages.TimeConversion.millisecondsToDuration(this.duration), status, // There are two fields for error info: // - 'message': string message + stack. // https://github.com/cucumber/messages/blob/main/jsonschema/messages.md#teststepresultmessage // - 'exception': added in cucumber 10.4, contains structured error details. // https://github.com/cucumber/messages/blob/main/jsonschema/messages.md#exception // // Different Cucumber reporters handle these fields differently: // - html reporter: shows only exception.stackTrace, // then (exception.type + exception.message), then result.message. // https://github.com/cucumber/react-components/blob/main/src/components/results/FailedResult.tsx#L10 // - json reporter: shows only result.message // https://github.com/cucumber/cucumber-js/blob/main/src/formatter/json_formatter.ts#L270 // - junit reporter: shows exception.type, exception.message and (exception.stackTrace or result.message) // https://github.com/cucumber/junit-xml-formatter/blob/main/javascript/src/JUnitXmlPrinter.ts#L89 // https://github.com/cucumber/junit-xml-formatter/blob/main/javascript/src/JUnitXmlPrinter.ts#L179 // // So we should set both fields carefully: // - result.message = exception.stackTrace to show full error details in json reporter // // See also: https://github.com/cucumber/react-components/pull/345 exception, message: exception?.stackTrace, }, timestamp: (0, timing_1.toCucumberTimestamp)(this.startTime.getTime() + this.duration), }; return { testStepFinished }; } getStatus(error) { switch (true) { // When calling test.skip(), it actually throws an error case (0, pwStepUtils_1.isSkippedError)(error): return messages.TestStepResultStatus.SKIPPED; case Boolean(error): return messages.TestStepResultStatus.FAILED; // Steps (and hooks) that have no corresponding Playwright step were not executed // in this particular attempt and should be reported as SKIPPED. // // For scenario steps this happens when a prior step failed — subsequent steps have no pwStep. // // For BEFORE_TEST_RUN hooks (BeforeAll) this can happen on a retry: PW runs BeforeAll only // once per worker (credited to the first scenario). If scenario B fails and is retried, its // attempt 1 runs BeforeAll in the new worker (has a real pwStep). When TestCase.addHooks() // processes attempt 1, it adds BeforeAll to the shared TestCase used for all attempts. // Then buildMessages() for attempt 0 finds BeforeAll in the TestCase but has no matching // pwStep (BeforeAll was credited to scenario A in the original worker). Emitting SKIPPED is // correct: the hook was a declared prerequisite, but was already handled by a prior scenario // in the same worker and therefore did not execute as part of this attempt. case !this.wasExecuted(): return messages.TestStepResultStatus.SKIPPED; default: return messages.TestStepResultStatus.PASSED; } } getStepError() { if (this.pwStep) { return this.testCaseRun.getStepError(this.pwStep); } } } exports.TestStepRun = TestStepRun; function isStepFailed(status) { return status === messages.TestStepResultStatus.FAILED; } //# sourceMappingURL=TestStepRun.js.map