Skip to content

Commit

Permalink
support metadata in playwright test and group annotations v2.0 (fixes #…
Browse files Browse the repository at this point in the history
  • Loading branch information
epszaw authored Jan 28, 2025
1 parent ecad277 commit fa62742
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 4 deletions.
1 change: 1 addition & 0 deletions packages/allure-js-commons/src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export {
getStatusFromError,
getMessageAndTraceFromError,
isMetadataTag,
getMetadataLabel,
extractMetadataFromString,
isAllStepsEnded,
isAnyStepFailed,
Expand Down
19 changes: 18 additions & 1 deletion packages/allure-js-commons/src/sdk/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type AllureTitleMetadataMatch = RegExpMatchArray & {
};
};

export const allureMetadataRegexp = /(?:^|\s)@?allure\.(?<type>\S+)$/;
export const allureTitleMetadataRegexp = /(?:^|\s)@?allure\.(?<type>\S+)[:=]("[^"]+"|'[^']+'|`[^`]+`|\S+)/;
export const allureTitleMetadataRegexpGlobal = new RegExp(allureTitleMetadataRegexp, "g");
export const allureIdRegexp = /(?:^|\s)@?allure\.id[:=](?<id>\S+)/;
Expand All @@ -96,7 +97,23 @@ export const getValueFromAllureTitleMetadataMatch = (match: AllureTitleMetadataM
};

export const isMetadataTag = (tag: string) => {
return allureTitleMetadataRegexp.test(tag);
return allureMetadataRegexp.test(tag);
};

export const getMetadataLabel = (tag: string, value?: string): Label | undefined => {
const match = tag.match(allureMetadataRegexp);
const type = match?.groups?.type;

if (!type) {
return undefined;
}

const [subtype, name] = type.split(".");

return {
name: subtype === "id" ? LabelName.ALLURE_ID : name,
value: value ?? "",
};
};

export const extractMetadataFromString = (
Expand Down
61 changes: 60 additions & 1 deletion packages/allure-playwright/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,25 @@ import {
type ImageDiffAttachment,
type Label,
LabelName,
LinkType,
Stage,
Status,
type TestResult,
} from "allure-js-commons";
import type { RuntimeMessage, TestPlanV1Test } from "allure-js-commons/sdk";
import { extractMetadataFromString, getMessageAndTraceFromError, hasLabel, stripAnsi } from "allure-js-commons/sdk";
import {
extractMetadataFromString,
getMessageAndTraceFromError,
getMetadataLabel,
hasLabel,
stripAnsi,
} from "allure-js-commons/sdk";
import {
ALLURE_RUNTIME_MESSAGE_CONTENT_TYPE,
ReporterRuntime,
createDefaultWriter,
escapeRegExp,
formatLink,
getEnvironmentLabels,
getFrameworkLabel,
getHostLabel,
Expand Down Expand Up @@ -179,6 +187,7 @@ export class AllureReporter implements ReporterV2 {
labels: [...titleMetadata.labels, ...getEnvironmentLabels()],
links: [],
parameters: [],
steps: [],
testCaseId: md5(testCaseIdBase),
fullName: `${relativeFile}:${test.location.line}:${test.location.column}`,
};
Expand All @@ -197,6 +206,56 @@ export class AllureReporter implements ReporterV2 {
result.labels!.push(...tags);
}

if ("annotations" in test) {
for (const annotation of test.annotations) {
if (annotation.type === "skip" || annotation.type === "fixme") {
continue;
}

if (annotation.type === "issue") {
result.links!.push(
formatLink(this.options.links ?? {}, {
type: LinkType.ISSUE,
url: annotation.description!,
}),
);
continue;
}

if (annotation.type === "tms" || annotation.type === "test_key") {
result.links!.push(
formatLink(this.options.links ?? {}, {
type: LinkType.TMS,
url: annotation.description!,
}),
);
continue;
}

if (annotation.type === "description") {
result.description = annotation.description;
continue;
}

const annotationLabel = getMetadataLabel(annotation.type, annotation.description);

if (annotationLabel) {
result.labels!.push(annotationLabel);
continue;
}

result.steps!.push({
name: `${annotation.type}: ${annotation.description!}`,
status: Status.PASSED,
stage: Stage.FINISHED,
parameters: [],
steps: [],
attachments: [],
statusDetails: {},
});
}
}

if (project?.name) {
result.parameters!.push({ name: "Project", value: project.name });
}
Expand Down
141 changes: 141 additions & 0 deletions packages/allure-playwright/test/spec/annotations.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect, it } from "vitest";
import { LabelName, LinkType } from "allure-js-commons";
import { runPlaywrightInlineTest } from "../utils.js";

it("should support skip annotation", async () => {
Expand Down Expand Up @@ -56,3 +57,143 @@ it("should support fixme annotation", async () => {
]),
);
});

it("should support allure metadata in playwright annotation", async () => {
const { tests } = await runPlaywrightInlineTest({
"sample.test.js": `
import { test } from '@playwright/test';
import { LabelName } from 'allure-js-commons';
test('test full report', {
annotation: [
{ type: "skip", description: "skipped via skip annotation" },
{ type: "fixme", description: "skipped via fixme annotation" },
{ type: "@allure.id", description: "foo" },
{ type: "@allure.label.foo", description: "bar" },
{ type: "allure.label.epic", description: "baz" },
{ type: "issue", description: "anything 2" },
{ type: "tms", description: "anything 3" },
{ type: "test_key", description: "anything 4" },
{ type: "description", description: "new test description" },
],
}, async () => {
});
`,
});

expect(tests).toHaveLength(1);
expect(tests[0].description).toBe("new test description");
expect(tests[0].labels).not.toContainEqual({ name: "description", value: "new test description" });
expect(tests[0].labels).not.toContainEqual({ name: "skip", value: "skipped via skip annotation" });
expect(tests[0].labels).not.toContainEqual({
name: "fixme",
value: "skipped via fixme annotation",
});
expect(tests[0].labels).toContainEqual({ name: LabelName.ALLURE_ID, value: "foo" });
expect(tests[0].labels).toContainEqual({ name: LabelName.EPIC, value: "baz" });
expect(tests[0].labels).toContainEqual({ name: "foo", value: "bar" });
expect(tests[0].links).toContainEqual({ type: LinkType.ISSUE, url: "anything 2" });
expect(tests[0].links).toContainEqual({ type: LinkType.TMS, url: "anything 3" });
expect(tests[0].links).toContainEqual({ type: LinkType.TMS, url: "anything 4" });
});

it("should append unknown playwright annotation to the test description", async () => {
const { tests } = await runPlaywrightInlineTest({
"sample.test.js": `
import { test } from '@playwright/test';
import { LabelName } from 'allure-js-commons';
test('test full report', {
annotation: [
{ type: "skip", description: "skipped via skip annotation" },
{ type: "fixme", description: "skipped via fixme annotation" },
{ type: "@allure.id", description: "foo" },
{ type: "@allure.label.foo", description: "bar" },
{ type: "allure.label.epic", description: "baz" },
{ type: "issue", description: "anything 2" },
{ type: "tms", description: "anything 3" },
{ type: "test_key", description: "anything 4" },
{ type: "description", description: "new test description" },
{ type: "unknown", description: "unknown annotation" },
],
}, async () => {
});
`,
});

expect(tests).toHaveLength(1);
expect(tests[0].description).toBe("new test description");
expect(tests[0].labels).not.toContainEqual({ name: "description", value: "new test description" });
expect(tests[0].labels).not.toContainEqual({ name: "skip", value: "skipped via skip annotation" });
expect(tests[0].labels).not.toContainEqual({
name: "fixme",
value: "skipped via fixme annotation",
});
expect(tests[0].labels).toContainEqual({ name: LabelName.ALLURE_ID, value: "foo" });
expect(tests[0].labels).toContainEqual({ name: LabelName.EPIC, value: "baz" });
expect(tests[0].labels).toContainEqual({ name: "foo", value: "bar" });
expect(tests[0].links).toContainEqual({ type: LinkType.ISSUE, url: "anything 2" });
expect(tests[0].links).toContainEqual({ type: LinkType.TMS, url: "anything 3" });
expect(tests[0].links).toContainEqual({ type: LinkType.TMS, url: "anything 4" });
expect(tests[0].steps).toContainEqual(expect.objectContaining({ name: "unknown: unknown annotation" }));
});

it("should support allure metadata in playwright group annotation", async () => {
const { tests } = await runPlaywrightInlineTest({
"sample.test.js": `
import { test } from '@playwright/test';
import { LabelName } from 'allure-js-commons';
test.describe(
'nested',
{
annotation: [
{ type: "skip", description: "skipped via skip annotation" },
{ type: "fixme", description: "skipped via fixme annotation" },
{ type: "@allure.id", description: "foo" },
{ type: "@allure.label.foo", description: "bar" },
{ type: "allure.label.epic", description: "baz" },
{ type: "issue", description: "anything 2" },
{ type: "tms", description: "anything 3" },
{ type: "test_key", description: "anything 4" },
{ type: "description", description: "new test description" },
{ type: "unknown", description: "unknown annotation" },
],
},
() => {
test('test full report 1', async () => {
});
test('test full report 2', async () => {
});
},
);
`,
});

expect(tests).toHaveLength(2);
expect(tests[0].description).toBe("new test description");
expect(tests[0].labels).not.toContainEqual({ name: "description", value: "new test description" });
expect(tests[0].labels).not.toContainEqual({ name: "skip", value: "skipped via skip annotation" });
expect(tests[0].labels).not.toContainEqual({
name: "fixme",
value: "skipped via fixme annotation",
});
expect(tests[0].labels).toContainEqual({ name: LabelName.ALLURE_ID, value: "foo" });
expect(tests[0].labels).toContainEqual({ name: LabelName.EPIC, value: "baz" });
expect(tests[0].labels).toContainEqual({ name: "foo", value: "bar" });
expect(tests[0].links).toContainEqual({ type: LinkType.ISSUE, url: "anything 2" });
expect(tests[0].links).toContainEqual({ type: LinkType.TMS, url: "anything 3" });
expect(tests[0].links).toContainEqual({ type: LinkType.TMS, url: "anything 4" });
expect(tests[0].steps).toContainEqual(expect.objectContaining({ name: "unknown: unknown annotation" }));
expect(tests[1].description).toBe("new test description");
expect(tests[1].labels).not.toContainEqual({ name: "description", value: "new test description" });
expect(tests[1].labels).not.toContainEqual({ name: "skip", value: "skipped via skip annotation" });
expect(tests[1].labels).not.toContainEqual({
name: "fixme",
value: "skipped via fixme annotation",
});
expect(tests[1].labels).toContainEqual({ name: LabelName.ALLURE_ID, value: "foo" });
expect(tests[1].labels).toContainEqual({ name: LabelName.EPIC, value: "baz" });
expect(tests[1].labels).toContainEqual({ name: "foo", value: "bar" });
expect(tests[1].links).toContainEqual({ type: LinkType.ISSUE, url: "anything 2" });
expect(tests[1].links).toContainEqual({ type: LinkType.TMS, url: "anything 3" });
expect(tests[1].links).toContainEqual({ type: LinkType.TMS, url: "anything 4" });
expect(tests[1].steps).toContainEqual(expect.objectContaining({ name: "unknown: unknown annotation" }));
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ it("sets multiply tags", async () => {
{ name: LabelName.TAG, value: "TestInfo" },
{ name: LabelName.TAG, value: "some" },
{ name: LabelName.TAG, value: "other" },
{ name: LabelName.TAG, value: "other" },
{ name: LabelName.TAG, value: "tags" },
]),
}),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ it("sets multiply tags", async () => {
{ name: LabelName.TAG, value: "TestInfo" },
{ name: LabelName.TAG, value: "some" },
{ name: LabelName.TAG, value: "other" },
{ name: LabelName.TAG, value: "other" },
{ name: LabelName.TAG, value: "tags" },
]),
}),
]);
Expand Down

0 comments on commit fa62742

Please sign in to comment.