Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support links in allure string metadata format #1235

Merged
merged 8 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/allure-jasmine/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,20 @@ export default class AllureJasmineReporter implements jasmine.CustomReporter {
}

specStarted(spec: jasmine.SpecResult & { filename?: string }): void {
const { fullName, labels, name } = getAllureNamesAndLabels(
const { fullName, labels, links, name } = getAllureNamesAndLabels(
spec.filename,
this.getCurrentSpecPath(),
spec.description,
);

if (!hasSkipLabel(labels)) {
this.#startScope();
this.currentAllureTestUuid = this.allureRuntime.startTest(
{
name,
fullName,
labels,
links,
stage: Stage.RUNNING,
},
this.scopesStack,
Expand Down
3 changes: 2 additions & 1 deletion packages/allure-jasmine/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ export const getAllureNamesAndLabels = (
rawSpecName: string,
) => {
const filePart = filename ? getPosixPath(getRelativePath(filename)) : undefined;
const { cleanTitle: specName, labels } = extractMetadataFromString(rawSpecName);
const { cleanTitle: specName, labels, links } = extractMetadataFromString(rawSpecName);
const specPart = [...suites, specName].join(" > ");

return {
name: specName,
fullName: filePart ? `${filePart}#${specPart}` : undefined,
labels,
links,
};
};
22 changes: 22 additions & 0 deletions packages/allure-jasmine/test/spec/metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,25 @@ it("should add labels from embedded metadata", async () => {
}),
]);
});

it("should add links from embedded metadata", async () => {
const { tests } = await runJasmineInlineTest({
"spec/test/sample.spec.js": `
it("foo @allure.link.bar=https://allurereport.org", () => {});
`,
});

expect(tests).toEqual([
expect.objectContaining({
name: "foo",
fullName: "spec/test/sample.spec.js#foo",
status: Status.PASSED,
links: expect.arrayContaining([
{
type: "bar",
url: "https://allurereport.org",
},
]),
}),
]);
});
13 changes: 8 additions & 5 deletions packages/allure-jest/src/environmentFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { env } from "node:process";
import * as allure from "allure-js-commons";
import { Stage, Status, type StatusDetails, type TestResult } from "allure-js-commons";
import type { RuntimeMessage } from "allure-js-commons/sdk";
import { getMessageAndTraceFromError, getStatusFromError } from "allure-js-commons/sdk";
import { extractMetadataFromString, getMessageAndTraceFromError, getStatusFromError } from "allure-js-commons/sdk";
import type { TestPlanV1 } from "allure-js-commons/sdk";
import {
ReporterRuntime,
Expand Down Expand Up @@ -122,9 +122,9 @@ const createJestEnvironment = <T extends typeof JestEnvironment>(Base: T): T =>
}
};

#getTestFullName(test: Circus.TestEntry) {
#getTestFullName(test: Circus.TestEntry, testTitle: string = test.name) {
const newTestSuitePath = getTestPath(test.parent);
const newTestPath = newTestSuitePath.concat(test.name);
const newTestPath = newTestSuitePath.concat(testTitle);
const newTestId = getTestId(newTestPath);

return `${getPosixPath(this.testPath)}#${newTestId}`;
Expand Down Expand Up @@ -186,7 +186,8 @@ const createJestEnvironment = <T extends typeof JestEnvironment>(Base: T): T =>

#handleTestStart(test: Circus.TestEntry) {
const newTestSuitePath = getTestPath(test.parent);
const newTestFullName = this.#getTestFullName(test);
const { cleanTitle, labels, links } = extractMetadataFromString(test.name);
const newTestFullName = this.#getTestFullName(test, cleanTitle);

if (this.testPlan && !isTestPresentInTestPlan(newTestFullName, this.testPlan)) {
test.mode = "skip";
Expand All @@ -196,7 +197,7 @@ const createJestEnvironment = <T extends typeof JestEnvironment>(Base: T): T =>

const testUuid = this.runtime.startTest(
{
name: test.name,
name: cleanTitle,
fullName: newTestFullName,
start: test.startedAt ?? undefined,
stage: Stage.RUNNING,
Expand All @@ -208,7 +209,9 @@ const createJestEnvironment = <T extends typeof JestEnvironment>(Base: T): T =>
getThreadLabel(env.JEST_WORKER_ID),
...getEnvironmentLabels(),
...getSuiteLabels(newTestSuitePath),
...labels,
],
links,
},
this.runContext.scopes,
);
Expand Down
51 changes: 51 additions & 0 deletions packages/allure-jest/test/spec/metadata.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { expect, it } from "vitest";
import { Status } from "allure-js-commons";
import { runJestInlineTest } from "../utils.js";

it("should add labels from embedded metadata", async () => {
const { tests } = await runJestInlineTest({
"spec/test/sample.spec.js": `
it("foo @allure.id:1004 @allure.label.bar=baz", () => {});
`,
});

expect(tests).toEqual([
expect.objectContaining({
name: "foo",
fullName: "spec/test/sample.spec.js#foo",
status: Status.PASSED,
labels: expect.arrayContaining([
{
name: "ALLURE_ID",
value: "1004",
},
{
name: "bar",
value: "baz",
},
]),
}),
]);
});

it("should add links from embedded metadata", async () => {
const { tests } = await runJestInlineTest({
"spec/test/sample.spec.js": `
it("foo @allure.link.bar=https://allurereport.org", () => {});
`,
});

expect(tests).toEqual([
expect.objectContaining({
name: "foo",
fullName: "spec/test/sample.spec.js#foo",
status: Status.PASSED,
links: expect.arrayContaining([
{
type: "bar",
url: "https://allurereport.org",
},
]),
}),
]);
});
10 changes: 8 additions & 2 deletions packages/allure-js-commons/src/sdk/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { FixtureResult, Label, StatusDetails, StepResult, TestResult } from "../model.js";
import type { FixtureResult, Label, Link, StatusDetails, StepResult, TestResult } from "../model.js";
import { LabelName, Status } from "../model.js";
import type { RuntimeMessage, SerializeOptions, SerializerReplacerFunc } from "./types.js";

Expand Down Expand Up @@ -74,7 +74,7 @@ type AllureTitleMetadataMatch = RegExpMatchArray & {
};

export const allureMetadataRegexp = /(?:^|\s)@?allure\.(?<type>\S+)$/;
export const allureTitleMetadataRegexp = /(?:^|\s)@?allure\.(?<type>\S+)[:=]("[^"]+"|'[^']+'|`[^`]+`|\S+)/;
export const allureTitleMetadataRegexp = /(?:^|\s)@?allure\.(?<type>[^:=\s]+)[:=]("[^"]+"|'[^']+'|`[^`]+`|\S+)/;
export const allureTitleMetadataRegexpGlobal = new RegExp(allureTitleMetadataRegexp, "g");
export const allureIdRegexp = /(?:^|\s)@?allure\.id[:=](?<id>\S+)/;
export const allureLabelRegexp = /(?:^|\s)@?allure\.label\.(?<name>[^:=\s]+)[:=](?<value>[^\s]+)/;
Expand Down Expand Up @@ -120,9 +120,11 @@ export const extractMetadataFromString = (
title: string,
): {
labels: Label[];
links: Link[];
cleanTitle: string;
} => {
const labels = [] as Label[];
const links = [] as Link[];
const metadata = title.matchAll(allureTitleMetadataRegexpGlobal);
const cleanTitle = title
.replaceAll(allureTitleMetadataRegexpGlobal, "")
Expand Down Expand Up @@ -155,11 +157,15 @@ export const extractMetadataFromString = (
case "label":
labels.push({ name, value });
break;
case "link":
links.push({ type: name, url: value });
break;
}
}

return {
labels,
links,
cleanTitle,
};
};
Expand Down
50 changes: 46 additions & 4 deletions packages/allure-js-commons/test/sdk/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,51 +238,82 @@ describe("extractMetadataFromString", () => {
expect(extractMetadataFromString("")).toEqual({
cleanTitle: "",
labels: [],
links: [],
});
expect(extractMetadataFromString("foo")).toEqual({
cleanTitle: "foo",
labels: [],
links: [],
});
});

it("should extract Allure ID", () => {
expect(extractMetadataFromString("foo @allure.id:1004")).toEqual({
cleanTitle: "foo",
labels: [{ name: "ALLURE_ID", value: "1004" }],
links: [],
});
expect(extractMetadataFromString("foo allure.id:1004")).toEqual({
cleanTitle: "foo",
labels: [{ name: "ALLURE_ID", value: "1004" }],
links: [],
});
expect(extractMetadataFromString("foo @allure.id=1004")).toEqual({
cleanTitle: "foo",
labels: [{ name: "ALLURE_ID", value: "1004" }],
links: [],
});
});

it("should extract label", () => {
expect(extractMetadataFromString("foo @allure.label.bar:baz")).toEqual({
cleanTitle: "foo",
labels: [{ name: "bar", value: "baz" }],
links: [],
});
expect(extractMetadataFromString("foo allure.label.bar:baz")).toEqual({
cleanTitle: "foo",
labels: [{ name: "bar", value: "baz" }],
links: [],
});
expect(extractMetadataFromString("foo @allure.label.bar=baz")).toEqual({
cleanTitle: "foo",
labels: [{ name: "bar", value: "baz" }],
links: [],
});
});

it("should extract links from metadata", () => {
expect(extractMetadataFromString("foo @allure.link.bar:https://allurereport.org")).toEqual({
cleanTitle: "foo",
labels: [],
links: [{ type: "bar", url: "https://allurereport.org" }],
});
expect(extractMetadataFromString("foo allure.link.bar:https://allurereport.org/foo")).toEqual({
cleanTitle: "foo",
labels: [],
links: [{ type: "bar", url: "https://allurereport.org/foo" }],
});
expect(extractMetadataFromString("foo @allure.link.bar=https://allurereport.org/foo+bar&baz")).toEqual({
cleanTitle: "foo",
labels: [],
links: [{ type: "bar", url: "https://allurereport.org/foo+bar&baz" }],
});
});

it("should extract all matches", () => {
expect(extractMetadataFromString("foo @allure.label.bar:baz @allure.id:1004 @allure.label.qux:quz")).toEqual({
expect(
extractMetadataFromString(
"foo @allure.label.bar:baz @allure.id:1004 @allure.label.qux:quz @allure.link.issue=https://example.com/issues/1",
),
).toEqual({
cleanTitle: "foo",
labels: [
{ name: "bar", value: "baz" },
{ name: "ALLURE_ID", value: "1004" },
{ name: "qux", value: "quz" },
],
links: [{ type: "issue", url: "https://example.com/issues/1" }],
});
});

Expand All @@ -294,33 +325,43 @@ describe("extractMetadataFromString", () => {
{ name: "ALLURE_ID", value: "1004" },
{ name: "l2", value: "v2" },
],
links: [],
});
});

it("should support values in single quotes", () => {
expect(
extractMetadataFromString("foo @allure.label.l1='foo bar baz' and bar @allure.id=beep @allure.label.l1=boop"),
extractMetadataFromString(
"foo @allure.label.l1='foo bar baz' and bar @allure.id=beep @allure.label.l1=boop @allure.link.my_link='https://allurereport.org'",
),
).toEqual({
cleanTitle: "foo and bar",
labels: [
{ name: "l1", value: "foo bar baz" },
{ name: LabelName.ALLURE_ID, value: "beep" },
{ name: "l1", value: "boop" },
],
links: [{ type: "my_link", url: "https://allurereport.org" }],
});
});

it("should support values in double quotes", () => {
expect(extractMetadataFromString('foo @allure.label.l1="foo bar baz"')).toEqual({
expect(
extractMetadataFromString('foo @allure.label.l1="foo bar baz" @allure.link.my_link="https://allurereport.org"'),
).toEqual({
cleanTitle: "foo",
labels: [{ name: "l1", value: "foo bar baz" }],
links: [{ type: "my_link", url: "https://allurereport.org" }],
});
});

it("should support values in backticks", () => {
expect(extractMetadataFromString("foo @allure.label.l1=`foo bar baz`")).toEqual({
expect(
extractMetadataFromString("foo @allure.label.l1=`foo bar baz` @allure.link.my_link=`https://allurereport.org`"),
).toEqual({
cleanTitle: "foo",
labels: [{ name: "l1", value: "foo bar baz" }],
links: [{ type: "my_link", url: "https://allurereport.org" }],
});
});

Expand All @@ -337,6 +378,7 @@ describe("extractMetadataFromString", () => {
{ name: "l1", value: "foo 2" },
{ name: "l1", value: "foo 3" },
],
links: [],
});
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/allure-playwright/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export class AllureReporter implements ReporterV2 {
const result: Partial<TestResult> = {
name: titleMetadata.cleanTitle,
labels: [...titleMetadata.labels, ...getEnvironmentLabels()],
links: [],
links: [...titleMetadata.links],
parameters: [],
steps: [],
testCaseId: md5(testCaseIdBase),
Expand Down
5 changes: 4 additions & 1 deletion packages/allure-playwright/test/spec/titleMetadata.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ it("has metadata from title", async () => {
"sample.test.js": `
import { test } from '@playwright/test';

test('some strange name to test @allure.id=228 @allure.label.tag=slow @allure.label.labelName=labelValue', async ({}, testInfo) => {
test('some strange name to test @allure.id=228 @allure.label.tag=slow @allure.label.labelName=labelValue @allure.link.my_link=https://allurereport.org', async ({}, testInfo) => {
});
`,
});
Expand All @@ -21,6 +21,9 @@ it("has metadata from title", async () => {
{ name: LabelName.TAG, value: "slow" },
{ name: "labelName", value: "labelValue" },
]),
links: expect.arrayContaining([
{ type: "my_link", url: "https://allurereport.org" },
]),
}),
]);
});
Expand Down
Loading