Skip to content

Commit e020a92

Browse files
authored
Fix step context for native playwright steps (#1255)
1 parent 3c94a62 commit e020a92

File tree

10 files changed

+272
-36
lines changed

10 files changed

+272
-36
lines changed

.pnp.cjs

+16-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.

packages/allure-mocha/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
"eslint-plugin-n": "^17.10.1",
8787
"eslint-plugin-no-null": "^1.0.2",
8888
"eslint-plugin-prefer-arrow": "^1.2.3",
89-
"glob": "^11.0.0",
89+
"glob": "^11.0.1",
9090
"mocha": "^11.0.0",
9191
"npm-run-all2": "^7.0.0",
9292
"rimraf": "^6.0.0",

packages/allure-playwright/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"eslint-plugin-n": "^17.10.1",
8787
"eslint-plugin-no-null": "^1.0.2",
8888
"eslint-plugin-prefer-arrow": "^1.2.3",
89+
"glob": "^11.0.1",
8990
"npm-run-all2": "^7.0.0",
9091
"rimraf": "^6.0.0",
9192
"typescript": "^5.2.2",

packages/allure-playwright/src/index.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
type StepResult,
2222
type TestResult,
2323
} from "allure-js-commons";
24-
import type { RuntimeMessage, TestPlanV1Test } from "allure-js-commons/sdk";
24+
import type { RuntimeMessage, RuntimeStepMetadataMessage, TestPlanV1Test } from "allure-js-commons/sdk";
2525
import {
2626
extractMetadataFromString,
2727
getMessageAndTraceFromError,
@@ -306,6 +306,7 @@ export class AllureReporter implements ReporterV2 {
306306

307307
if (step.category === "attach") {
308308
const currentStep = this.allureRuntime?.currentStep(testUuid);
309+
309310
this.attachmentSteps.set(testUuid, [...(this.attachmentSteps.get(testUuid) ?? []), currentStep]);
310311
return;
311312
}
@@ -562,6 +563,18 @@ export class AllureReporter implements ReporterV2 {
562563
return false;
563564
}
564565

566+
private processStepMetadataMessage(attachmentStepUuid: string, message: RuntimeStepMetadataMessage) {
567+
const { name, parameters = [] } = message.data;
568+
569+
this.allureRuntime!.updateStep(attachmentStepUuid, (step) => {
570+
if (name) {
571+
step.name = name;
572+
}
573+
574+
step.parameters.push(...parameters);
575+
});
576+
}
577+
565578
private async processAttachment(
566579
testUuid: string,
567580
attachmentStepUuid: string | undefined,
@@ -585,18 +598,24 @@ export class AllureReporter implements ReporterV2 {
585598
if (allureRuntimeMessage) {
586599
const message = JSON.parse(attachment.body!.toString()) as RuntimeMessage;
587600

588-
// TODO fix step metadata messages
601+
if (message.type === "step_metadata") {
602+
this.processStepMetadataMessage(attachmentStepUuid!, message);
603+
return;
604+
}
605+
589606
this.allureRuntime!.applyRuntimeMessages(testUuid, [message]);
590607
return;
591608
}
592609

593610
const parentUuid = this.allureRuntime!.startStep(testUuid, attachmentStepUuid, { name: attachment.name });
611+
594612
// only stop if step is created. Step may not be created only if test with specified uuid doesn't exists.
595613
// usually, missing test by uuid means we should completely skip result processing;
596614
// the later operations are safe and will only produce console warnings
597615
if (parentUuid) {
598616
this.allureRuntime!.stopStep(parentUuid, undefined);
599617
}
618+
600619
if (attachment.body) {
601620
this.allureRuntime!.writeAttachment(testUuid, parentUuid, attachment.name, attachment.body, {
602621
contentType: attachment.contentType,

packages/allure-playwright/src/runtime.ts

+35-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { test } from "@playwright/test";
2-
import type { AttachmentOptions } from "allure-js-commons";
2+
import type { AttachmentOptions, ParameterMode } from "allure-js-commons";
33
import type { RuntimeMessage } from "allure-js-commons/sdk";
44
import { ALLURE_RUNTIME_MESSAGE_CONTENT_TYPE } from "allure-js-commons/sdk/reporter";
55
import { MessageTestRuntime } from "allure-js-commons/sdk/runtime";
@@ -9,6 +9,40 @@ export class AllurePlaywrightTestRuntime extends MessageTestRuntime {
99
super();
1010
}
1111

12+
async step(stepName: string, body: () => any) {
13+
return await test.step(stepName, async () => await body());
14+
}
15+
16+
async stepDisplayName(name: string) {
17+
await test.info().attach("Allure Step Metadata", {
18+
contentType: ALLURE_RUNTIME_MESSAGE_CONTENT_TYPE,
19+
body: Buffer.from(
20+
JSON.stringify({
21+
type: "step_metadata",
22+
data: {
23+
name,
24+
},
25+
}),
26+
"utf8",
27+
),
28+
});
29+
}
30+
31+
async stepParameter(name: string, value: string, mode?: ParameterMode) {
32+
await test.info().attach("Allure Step Metadata", {
33+
contentType: ALLURE_RUNTIME_MESSAGE_CONTENT_TYPE,
34+
body: Buffer.from(
35+
JSON.stringify({
36+
type: "step_metadata",
37+
data: {
38+
parameters: [{ name, value, mode }],
39+
},
40+
}),
41+
"utf8",
42+
),
43+
});
44+
}
45+
1246
async attachment(name: string, content: Buffer | string, options: AttachmentOptions) {
1347
await test.info().attach(name, { body: content, contentType: options.contentType });
1448
}

packages/allure-playwright/test/spec/runtime/legacy/steps.spec.ts

+72-10
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,24 @@ it("handles nested lambda steps", async () => {
8888
it("should allow to set step metadata through its context", async () => {
8989
const { tests } = await runPlaywrightInlineTest({
9090
"sample.test.ts": `
91-
import { test, allure } from "allure-playwright";
91+
import { allure, test } from "allure-playwright";
9292
9393
test("steps", async () => {
94-
await allure.step("step 1", async () => {
95-
await allure.step("step 2", async () => {
96-
await allure.step("step 3", async (stepContext) => {
97-
await stepContext.displayName("custom name");
98-
await stepContext.parameter("param", "value");
94+
await allure.step("step 1", async (ctx1) => {
95+
await ctx1.displayName("custom name 1");
96+
97+
await allure.step("step 2", async (ctx2) => {
98+
await ctx2.displayName("custom name 2");
99+
100+
await allure.step("step 3", async (ctx3) => {
101+
await ctx3.displayName("custom name 3");
102+
await ctx3.parameter("param", "value 3");
99103
});
104+
105+
await ctx2.parameter("param", "value 2");
100106
});
107+
108+
await ctx1.parameter("param", "value 1");
101109
});
102110
});
103111
`,
@@ -109,24 +117,78 @@ it("should allow to set step metadata through its context", async () => {
109117
name: "Before Hooks",
110118
});
111119
expect(tests[0].steps[1]).toMatchObject({
112-
name: "step 1",
120+
name: "custom name 1",
113121
status: Status.PASSED,
114122
stage: Stage.FINISHED,
123+
parameters: [expect.objectContaining({ name: "param", value: "value 1" })],
115124
});
116125
expect(tests[0].steps[1].steps).toHaveLength(1);
117126
expect(tests[0].steps[1].steps[0]).toMatchObject({
118-
name: "step 2",
127+
name: "custom name 2",
119128
status: Status.PASSED,
120129
stage: Stage.FINISHED,
130+
parameters: [expect.objectContaining({ name: "param", value: "value 2" })],
121131
});
122132
expect(tests[0].steps[1].steps[0].steps).toHaveLength(1);
123133
expect(tests[0].steps[1].steps[0].steps[0]).toMatchObject({
124-
name: "custom name",
125-
parameters: [expect.objectContaining({ name: "param", value: "value" })],
134+
name: "custom name 3",
126135
status: Status.PASSED,
127136
stage: Stage.FINISHED,
137+
parameters: [expect.objectContaining({ name: "param", value: "value 3" })],
128138
});
129139
expect(tests[0].steps[2]).toMatchObject({
130140
name: "After Hooks",
131141
});
132142
});
143+
144+
it("should use native playwright steps under the hood", async () => {
145+
const { tests, restFiles } = await runPlaywrightInlineTest({
146+
"playwright.config.js": `
147+
module.exports = {
148+
reporter: [
149+
[
150+
"allure-playwright",
151+
{
152+
resultsDir: "./allure-results",
153+
},
154+
],
155+
["dot"],
156+
["json", { outputFile: "./test-results.json" }],
157+
],
158+
projects: [
159+
{
160+
name: "project",
161+
},
162+
],
163+
};
164+
`,
165+
"sample.test.ts": `
166+
import { allure, test } from "allure-playwright";
167+
168+
test("steps", async () => {
169+
await allure.step("step 1", async () => {});
170+
});
171+
`,
172+
});
173+
174+
expect(tests).toHaveLength(1);
175+
expect(tests[0].steps).toHaveLength(3);
176+
expect(tests[0].steps[0]).toMatchObject({
177+
name: "Before Hooks",
178+
});
179+
expect(tests[0].steps[1]).toMatchObject({
180+
name: "step 1",
181+
status: Status.PASSED,
182+
stage: Stage.FINISHED,
183+
});
184+
expect(tests[0].steps[2]).toMatchObject({
185+
name: "After Hooks",
186+
});
187+
expect(restFiles["test-results.json"]).toBeDefined();
188+
189+
const pwTestResults = JSON.parse(restFiles["test-results.json"]);
190+
191+
expect(pwTestResults.suites[0].specs[0].tests[0].results[0].steps[0]).toMatchObject({
192+
title: "step 1",
193+
});
194+
});

0 commit comments

Comments
 (0)