Skip to content

Commit

Permalink
fix(playwright): fix step statuses and tests structure (fixes #1240, …
Browse files Browse the repository at this point in the history
…via #1244)
  • Loading branch information
epszaw authored Feb 10, 2025
1 parent 0eb0fb1 commit da8f17f
Show file tree
Hide file tree
Showing 7 changed files with 445 additions and 8 deletions.
69 changes: 67 additions & 2 deletions packages/allure-js-commons/src/sdk/reporter/ReporterRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { deepClone, formatLinks, getTestResultHistoryId, getTestResultTestCaseId
import { buildAttachmentFileName } from "./utils/attachments.js";
import { resolveWriter } from "./writer/loader.js";

interface StepStack {
export interface StepStack {
clear(): void;

removeRoot(rootUuid: string): void;
Expand All @@ -48,7 +48,72 @@ interface StepStack {
removeStep(stepUuid: string): void;
}

class DefaultStepStack implements StepStack {
/**
* Simpler steps stack implementation that contains only the current steps without root nodes
* Useful, when you need to create steps without binding them to a specific test or fixture
* @example
* ```js
* const stack = new ShallowStepsStack();
*
* stack.startStep({ name: "step 1" });
* stack.startStep({ name: "step 1.1" });
* stack.stopStep({ status: Status.FAILED });
* stack.stopStep({ status: Status.PASSED });
* stack.steps // => [{ name: "step 1", status: Status.PASSED, steps: [{ name: "step 1.1", status: Status.FAILED }] }]
* ```
*/
export class ShallowStepsStack {
steps: StepResult[] = [];

#runningSteps: StepResult[] = [];

get #currentStep() {
return this.#runningSteps[this.#runningSteps.length - 1];
}

startStep(step: Partial<StepResult>) {
const stepResult: StepResult = {
...createStepResult(),
...step,
};

if (this.#currentStep) {
this.#currentStep.steps.push(stepResult);
} else {
this.steps.push(stepResult);
}

this.#runningSteps.push(stepResult);
}

updateStep(updateFunc: (result: StepResult) => void) {
if (!this.#currentStep) {
// eslint-disable-next-line no-console
console.error("There is no running step in the stack to update!");
return;
}

updateFunc(this.#currentStep);
}

stopStep(opts?: { stop?: number; duration?: number }) {
if (!this.#currentStep) {
// eslint-disable-next-line no-console
console.error("There is no running step in the stack to stop!");
return;
}

const { stop, duration = 0 } = opts ?? {};

this.updateStep((result) => {
result.stop = stop ?? result.start ? result.start! + duration : undefined;
});

this.#runningSteps.pop();
}
}

export class DefaultStepStack implements StepStack {
private stepsByRoot: Map<string, string[]> = new Map();
private rootsByStep: Map<string, string> = new Map();

Expand Down
2 changes: 1 addition & 1 deletion packages/allure-js-commons/src/sdk/reporter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export * from "./utils.js";
export * from "./testplan.js";
export * from "./factory.js";
export { LifecycleState } from "./LifecycleState.js";
export { ReporterRuntime } from "./ReporterRuntime.js";
export { type StepStack, DefaultStepStack, ReporterRuntime, ShallowStepsStack } from "./ReporterRuntime.js";
export { InMemoryWriter } from "./writer/InMemoryWriter.js";
export { FileSystemWriter } from "./writer/FileSystemWriter.js";
export { MessageWriter } from "./writer/MessageWriter.js";
Expand Down
1 change: 1 addition & 0 deletions packages/allure-js-commons/src/sdk/reporter/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const getWorstTestStepResult = (steps: StepResult[]): StepResult | undefi
if (steps.length === 0) {
return;
}

return [...steps].sort((a, b) => statusToPriority(a.status) - statusToPriority(b.status))[0];
};

Expand Down
136 changes: 135 additions & 1 deletion packages/allure-js-commons/test/sdk/reporter/ReporterRuntime.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { describe, expect, it } from "vitest";
import { type Link, Stage, Status, type TestResult } from "../../../src/model.js";
import { getTestResultHistoryId } from "../../../src/sdk/reporter";
import { ReporterRuntime } from "../../../src/sdk/reporter/ReporterRuntime.js";
import { ReporterRuntime, ShallowStepsStack } from "../../../src/sdk/reporter/ReporterRuntime.js";
import { mockWriter } from "../../utils/writer.js";

const fixtures = {
Expand Down Expand Up @@ -788,4 +788,138 @@ describe("ReporterRuntime", () => {
new ReporterRuntime({ writer: "InMemoryWriter" });
});
});

describe("ShallowStepsStack", () => {
it("should start and stop single step", () => {
const stack = new ShallowStepsStack();

stack.startStep({ name: "step1" });
stack.updateStep((result) => {
result.status = Status.PASSED;
result.stage = Stage.FINISHED;
});
stack.stopStep();

expect(stack.steps).toEqual([
expect.objectContaining({
name: "step1",
steps: [],
}),
]);
});

it("should start and stop multiple same level steps", () => {
const stack = new ShallowStepsStack();

stack.startStep({ name: "step1" });
stack.stopStep();
stack.startStep({ name: "step2" });
stack.stopStep();
stack.startStep({ name: "step3" });
stack.stopStep();

expect(stack.steps).toEqual([
expect.objectContaining({
name: "step1",
steps: [],
}),
expect.objectContaining({
name: "step2",
steps: [],
}),
expect.objectContaining({
name: "step3",
steps: [],
}),
]);
});

it("should start and stop nested steps", () => {
const stack = new ShallowStepsStack();

stack.startStep({ name: "step1" });
stack.startStep({ name: "step1.1" });
stack.startStep({ name: "step1.1.1" });
stack.stopStep();
stack.stopStep();
stack.stopStep();

expect(stack.steps).toEqual([
expect.objectContaining({
name: "step1",
steps: [
expect.objectContaining({
name: "step1.1",
steps: [
expect.objectContaining({
name: "step1.1.1",
steps: [],
}),
],
}),
],
}),
]);
});

it("should start and stop nested and same level steps", () => {
const stack = new ShallowStepsStack();

stack.startStep({ name: "step1" });
stack.startStep({ name: "step1.1" });
stack.startStep({ name: "step1.1.1" });
stack.stopStep();
stack.stopStep();
stack.stopStep();
stack.startStep({ name: "step2" });
stack.stopStep();
stack.startStep({ name: "step3" });
stack.startStep({ name: "step3.1" });
stack.startStep({ name: "step3.1.1" });
stack.stopStep();
stack.stopStep();
stack.startStep({ name: "step3.2" });
stack.stopStep();
stack.stopStep();

expect(stack.steps).toEqual([
expect.objectContaining({
name: "step1",
steps: [
expect.objectContaining({
name: "step1.1",
steps: [
expect.objectContaining({
name: "step1.1.1",
steps: [],
}),
],
}),
],
}),
expect.objectContaining({
name: "step2",
steps: [],
}),
expect.objectContaining({
name: "step3",
steps: [
expect.objectContaining({
name: "step3.1",
steps: [
expect.objectContaining({
name: "step3.1.1",
steps: [],
}),
],
}),
expect.objectContaining({
name: "step3.2",
steps: [],
}),
],
}),
]);
});
});
});
Loading

0 comments on commit da8f17f

Please sign in to comment.