Skip to content

Commit

Permalink
Support links in allure string metadata format (#1235)
Browse files Browse the repository at this point in the history
  • Loading branch information
epszaw authored Jan 29, 2025
1 parent fa62742 commit 4b8bfd1
Show file tree
Hide file tree
Showing 27 changed files with 249 additions and 33 deletions.
10 changes: 9 additions & 1 deletion packages/allure-codeceptjs/test/spec/titleMetadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ it("handles title metadata", async () => {
const { tests } = await runCodeceptJsInlineTest({
"sample.test.js": `
Feature("sample feature");
Scenario("some strange name to test @allure.id=228 @allure.label.tag=slow @allure.label.labelName=labelValue", async () => {});
Scenario("some strange name to test @allure.id=228 @allure.label.tag=slow @allure.label.labelName=labelValue @allure.link.my_link=https://allurereport.org", async () => {});
`,
});

Expand All @@ -28,4 +28,12 @@ it("handles title metadata", async () => {
},
]),
);
expect(tests[0].links).toEqual(
expect.arrayContaining([
{
type: "my_link",
url: "https://allurereport.org",
},
]),
);
});
4 changes: 2 additions & 2 deletions packages/allure-cypress/src/browser/testplan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { LabelName } from "allure-js-commons";
import type { TestPlanV1 } from "allure-js-commons/sdk";
import type { CypressSuite, CypressTest } from "../types.js";
import { getAllureTestPlan } from "./state.js";
import { getNamesAndLabels, resolveSpecRelativePath } from "./utils.js";
import { getTestMetadata, resolveSpecRelativePath } from "./utils.js";

export const applyTestPlan = (spec: Cypress.Spec, root: CypressSuite) => {
const testPlan = getAllureTestPlan();
Expand Down Expand Up @@ -36,7 +36,7 @@ const getIndicesOfDeselectedTests = (
) => {
const indicesToRemove: number[] = [];
tests.forEach((test, index) => {
const { fullNameSuffix, labels } = getNamesAndLabels(spec, test);
const { fullNameSuffix, labels } = getTestMetadata(test);
const fullName = `${specPath}#${fullNameSuffix}`;
const allureId = labels.find(({ name }) => name === LabelName.ALLURE_ID)?.value;

Expand Down
8 changes: 4 additions & 4 deletions packages/allure-cypress/src/browser/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const uint8ArrayToBase64 = (data: unknown) => {
};

export const getTestStartData = (test: CypressTest) => ({
...getNamesAndLabels(Cypress.spec, test),
...getTestMetadata(test),
start:
typeof test.wallClockStartedAt === "string"
? Date.parse(test.wallClockStartedAt)
Expand Down Expand Up @@ -100,12 +100,12 @@ export const getSuiteTitlePath = (test: CypressTest): string[] =>

export const generateApiStepId = () => (getAllureState().nextApiStepId++).toString();

export const getNamesAndLabels = (spec: Cypress.Spec, test: CypressTest) => {
export const getTestMetadata = (test: CypressTest) => {
const rawName = test.title;
const { cleanTitle: name, labels } = extractMetadataFromString(rawName);
const { cleanTitle: name, labels, links } = extractMetadataFromString(rawName);
const suites = test.titlePath().slice(0, -1);
const fullNameSuffix = `${[...suites, name].join(" ")}`;
return { name, labels, fullNameSuffix };
return { name, labels, links, fullNameSuffix };
};

export const isAllureHook = (hook: CypressHook) => hook.title.includes(ALLURE_REPORT_SYSTEM_HOOK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ it("title metadata", async () => {
"cypress/e2e/sample.cy.js": ({ allureCommonsModulePath }) => `
import { label } from "${allureCommonsModulePath}";
it("foo @allure.id=1 @allure.label.foo=2", () => {
it("foo @allure.id=1 @allure.label.foo=2 @allure.link.my_link=https://allurereport.org", () => {
label("bar", "3");
});
`,
Expand All @@ -32,4 +32,10 @@ it("title metadata", async () => {
value: "3",
}),
);
expect(tests[0].links).toContainEqual(
expect.objectContaining({
type: "my_link",
url: "https://allurereport.org",
}),
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ it("title metadata", async () => {
"cypress/e2e/sample.cy.js": ({ allureCommonsModulePath }) => `
import { label } from "${allureCommonsModulePath}";
it("foo @allure.id=1 @allure.label.foo=2", () => {
it("foo @allure.id=1 @allure.label.foo=2 @allure.link.my_link=https://allurereport.org", () => {
label("bar", "3");
});
`,
Expand All @@ -32,4 +32,10 @@ it("title metadata", async () => {
value: "3",
}),
);
expect(tests[0].links).toContainEqual(
expect.objectContaining({
type: "my_link",
url: "https://allurereport.org",
}),
);
});
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
Loading

0 comments on commit 4b8bfd1

Please sign in to comment.