diff --git a/.pnp.cjs b/.pnp.cjs index d63ce152a..b4a5c34ca 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -6020,6 +6020,7 @@ const RAW_RUNTIME_STATE = ["allure-js-commons", "virtual:4dfda025008308960858af02ce2de23e6fbf02744b9548c2fa0efde5067623eaf08fec37555d32d6a86a61adf128d2c2890eef9d442aef417f3e2d1f5492c52d#workspace:packages/allure-js-commons"],\ ["allure-vitest", "virtual:4dfda025008308960858af02ce2de23e6fbf02744b9548c2fa0efde5067623eaf08fec37555d32d6a86a61adf128d2c2890eef9d442aef417f3e2d1f5492c52d#workspace:packages/allure-vitest"],\ ["babel-plugin-add-module-exports", "npm:1.0.4"],\ + ["babel-plugin-transform-import-meta", "virtual:e64d7f26127b0c38f2abe71db23f0a141b0538db2f417ca2c220511e19f5e4f807ad3daa66e38a4a857f9c6bfd539c632538c990ab69f65c09d763e405a3f457#npm:2.2.1"],\ ["eslint", "npm:8.57.0"],\ ["eslint-config-prettier", "virtual:a59b12f7fe7bf3b80fc61d73eaaa33af60483f6ce31789d384fbe8ef169791f667d2559ec5f2fbae1a273a658ce021f1f5f1ea0718c56f81b30ad4e95a5668dd#npm:9.1.0"],\ ["eslint-plugin-import", "virtual:a59b12f7fe7bf3b80fc61d73eaaa33af60483f6ce31789d384fbe8ef169791f667d2559ec5f2fbae1a273a658ce021f1f5f1ea0718c56f81b30ad4e95a5668dd#npm:2.29.1"],\ @@ -6232,7 +6233,7 @@ const RAW_RUNTIME_STATE = ["allure-js-commons", "virtual:4dfda025008308960858af02ce2de23e6fbf02744b9548c2fa0efde5067623eaf08fec37555d32d6a86a61adf128d2c2890eef9d442aef417f3e2d1f5492c52d#workspace:packages/allure-js-commons"],\ ["allure-vitest", "virtual:4dfda025008308960858af02ce2de23e6fbf02744b9548c2fa0efde5067623eaf08fec37555d32d6a86a61adf128d2c2890eef9d442aef417f3e2d1f5492c52d#workspace:packages/allure-vitest"],\ ["babel-plugin-add-module-exports", "npm:1.0.4"],\ - ["babel-plugin-transform-import-meta", "virtual:ab27e3168e0bdfb2dc5b30f86375269d7862a0be07fda8f1a257183a90c281219d82f6498de90bd23a4b5fcb916cfc7e850768c6711fc7742befb82622788606#npm:2.2.1"],\ + ["babel-plugin-transform-import-meta", "virtual:e64d7f26127b0c38f2abe71db23f0a141b0538db2f417ca2c220511e19f5e4f807ad3daa66e38a4a857f9c6bfd539c632538c990ab69f65c09d763e405a3f457#npm:2.2.1"],\ ["eslint", "npm:8.57.0"],\ ["eslint-config-prettier", "virtual:a59b12f7fe7bf3b80fc61d73eaaa33af60483f6ce31789d384fbe8ef169791f667d2559ec5f2fbae1a273a658ce021f1f5f1ea0718c56f81b30ad4e95a5668dd#npm:9.1.0"],\ ["eslint-plugin-import", "virtual:a59b12f7fe7bf3b80fc61d73eaaa33af60483f6ce31789d384fbe8ef169791f667d2559ec5f2fbae1a273a658ce021f1f5f1ea0718c56f81b30ad4e95a5668dd#npm:2.29.1"],\ @@ -6925,10 +6926,10 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ - ["virtual:ab27e3168e0bdfb2dc5b30f86375269d7862a0be07fda8f1a257183a90c281219d82f6498de90bd23a4b5fcb916cfc7e850768c6711fc7742befb82622788606#npm:2.2.1", {\ - "packageLocation": "./.yarn/__virtual__/babel-plugin-transform-import-meta-virtual-4f7e20a233/0/cache/babel-plugin-transform-import-meta-npm-2.2.1-0927fef047-d6db38b379.zip/node_modules/babel-plugin-transform-import-meta/",\ + ["virtual:e64d7f26127b0c38f2abe71db23f0a141b0538db2f417ca2c220511e19f5e4f807ad3daa66e38a4a857f9c6bfd539c632538c990ab69f65c09d763e405a3f457#npm:2.2.1", {\ + "packageLocation": "./.yarn/__virtual__/babel-plugin-transform-import-meta-virtual-fd84808a15/0/cache/babel-plugin-transform-import-meta-npm-2.2.1-0927fef047-d6db38b379.zip/node_modules/babel-plugin-transform-import-meta/",\ "packageDependencies": [\ - ["babel-plugin-transform-import-meta", "virtual:ab27e3168e0bdfb2dc5b30f86375269d7862a0be07fda8f1a257183a90c281219d82f6498de90bd23a4b5fcb916cfc7e850768c6711fc7742befb82622788606#npm:2.2.1"],\ + ["babel-plugin-transform-import-meta", "virtual:e64d7f26127b0c38f2abe71db23f0a141b0538db2f417ca2c220511e19f5e4f807ad3daa66e38a4a857f9c6bfd539c632538c990ab69f65c09d763e405a3f457#npm:2.2.1"],\ ["@babel/core", "npm:7.24.6"],\ ["@babel/template", "npm:7.24.7"],\ ["@types/babel__core", "npm:7.20.5"],\ diff --git a/packages/allure-jasmine/babel.cjs.json b/packages/allure-jasmine/babel.cjs.json index 8d5e10dfa..d3de84c86 100644 --- a/packages/allure-jasmine/babel.cjs.json +++ b/packages/allure-jasmine/babel.cjs.json @@ -8,7 +8,7 @@ ], ["@babel/preset-env", { "modules": "commonjs" }] ], - "plugins": ["babel-plugin-add-module-exports"], + "plugins": ["babel-plugin-add-module-exports", "babel-plugin-transform-import-meta"], "targets": { "esmodules": false, "node": 18 diff --git a/packages/allure-jasmine/package.json b/packages/allure-jasmine/package.json index f8fa78088..0f9accff8 100644 --- a/packages/allure-jasmine/package.json +++ b/packages/allure-jasmine/package.json @@ -57,6 +57,7 @@ "allure-commandline": "^2.29.0", "allure-vitest": "workspace:*", "babel-plugin-add-module-exports": "^1.0.4", + "babel-plugin-transform-import-meta": "^2.2.1", "eslint": "^8.57.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.28.1", diff --git a/packages/allure-jasmine/src/index.ts b/packages/allure-jasmine/src/index.ts index 33b82b1d5..fc9c84f69 100644 --- a/packages/allure-jasmine/src/index.ts +++ b/packages/allure-jasmine/src/index.ts @@ -1,4 +1,4 @@ -import { cwd, env } from "node:process"; +import { env } from "node:process"; import * as allure from "allure-js-commons"; import { Stage, Status } from "allure-js-commons"; import type { RuntimeMessage } from "allure-js-commons/sdk"; @@ -10,10 +10,12 @@ import { ReporterRuntime, getEnvironmentLabels, getSuiteLabels, + hasSkipLabel, } from "allure-js-commons/sdk/reporter"; import { MessageTestRuntime, setGlobalTestRuntime } from "allure-js-commons/sdk/runtime"; import type { JasmineBeforeAfterFn } from "./model.js"; -import { findAnyError, findMessageAboutThrow, last } from "./utils.js"; +import { enableAllureJasmineTestPlan } from "./testplan.js"; +import { findAnyError, findMessageAboutThrow, getAllureNamesAndLabels, last } from "./utils.js"; class AllureJasmineTestRuntime extends MessageTestRuntime { constructor(private readonly allureJasmineReporter: AllureJasmineReporter) { @@ -51,7 +53,7 @@ export default class AllureJasmineReporter implements jasmine.CustomReporter { setGlobalTestRuntime(testRuntime); - this.#enableAllureFixtures(); + this.#enableAllureFeatures(); // the best place to start global container for hooks and nested suites const scopeUuid = this.allureRuntime.startScope(); @@ -71,13 +73,6 @@ export default class AllureJasmineReporter implements jasmine.CustomReporter { )[0] as string[]; } - private getSpecFullName(spec: jasmine.SpecResult & { filename?: string }) { - const specFilename = (spec.filename || "").replace(cwd(), "").replace(/^[/\\]/, ""); - const specPath = this.getCurrentSpecPath().concat(spec.description).join(" > "); - - return `${specFilename}#${specPath}`; - } - getAllureInterface() { return allure; } @@ -125,16 +120,24 @@ export default class AllureJasmineReporter implements jasmine.CustomReporter { this.#stopScope(); } - specStarted(spec: jasmine.SpecResult): void { - this.#startScope(); - this.currentAllureTestUuid = this.allureRuntime.startTest( - { - name: spec.description, - fullName: this.getSpecFullName(spec), - stage: Stage.RUNNING, - }, - this.scopesStack, + specStarted(spec: jasmine.SpecResult & { filename?: string }): void { + const { fullName, labels, name } = getAllureNamesAndLabels( + spec.filename, + this.getCurrentSpecPath(), + spec.description, ); + if (!hasSkipLabel(labels)) { + this.#startScope(); + this.currentAllureTestUuid = this.allureRuntime.startTest( + { + name, + fullName, + labels, + stage: Stage.RUNNING, + }, + this.scopesStack, + ); + } } specDone(spec: jasmine.SpecResult): void { @@ -228,6 +231,11 @@ export default class AllureJasmineReporter implements jasmine.CustomReporter { } }; + #enableAllureFeatures = () => { + this.#enableAllureFixtures(); + enableAllureJasmineTestPlan(); + }; + #enableAllureFixtures(): void { const jasmineBeforeAll: JasmineBeforeAfterFn = global.beforeAll; const jasmineAfterAll: JasmineBeforeAfterFn = global.afterAll; diff --git a/packages/allure-jasmine/src/model.ts b/packages/allure-jasmine/src/model.ts index dc81833fc..e4f8f8f23 100644 --- a/packages/allure-jasmine/src/model.ts +++ b/packages/allure-jasmine/src/model.ts @@ -1 +1,10 @@ -export type JasmineBeforeAfterFn = typeof beforeEach; +export type JasmineBeforeAfterFn = typeof global.beforeEach; + +export type JasmineSpecFn = typeof global.it; + +export type JasmineSuiteFn = typeof global.describe; + +export type TestPlanIndex = { + ids: ReadonlySet; + fullNames: ReadonlySet; +}; diff --git a/packages/allure-jasmine/src/testplan.ts b/packages/allure-jasmine/src/testplan.ts new file mode 100644 index 000000000..c8f88a890 --- /dev/null +++ b/packages/allure-jasmine/src/testplan.ts @@ -0,0 +1,113 @@ +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { LabelName } from "allure-js-commons"; +import type { Label } from "allure-js-commons"; +import { addSkipLabelAsMeta, parseTestPlan } from "allure-js-commons/sdk/reporter"; +import type { JasmineSpecFn, JasmineSuiteFn, TestPlanIndex } from "./model.js"; +import { getAllureNamesAndLabels } from "./utils.js"; + +const dirname = path.dirname(fileURLToPath(import.meta.url)); + +const getCallerFileStackTraceFormatFn = (_: Error, stackTraces: NodeJS.CallSite[]): string | undefined => { + return stackTraces[0]?.getFileName(); +}; + +const getCallerFile = any>(fn: TFn) => { + const originalPrepareStackTrace = Error.prepareStackTrace; + Error.prepareStackTrace = getCallerFileStackTraceFormatFn; + try { + const obj = {}; + Error.captureStackTrace(obj, fn); + return (obj as any).stack as ReturnType; + } finally { + Error.prepareStackTrace = originalPrepareStackTrace; + } +}; + +const originalErrorToString = (e: Error) => Error.prototype.toString.call(e); + +const defaultPrepareStackTrace = (error: Error, stackTraces: NodeJS.CallSite[]): string => + stackTraces.length === 0 + ? originalErrorToString(error) + : [originalErrorToString(error), ...stackTraces].join("\n at "); + +const isAllureJasmineFrame = (frame: NodeJS.CallSite) => frame.getFileName()?.startsWith(dirname + path.sep) ?? false; + +const createStackFilter = + (prepareStackTrace: (error: Error, stackTraces: NodeJS.CallSite[]) => any) => + (error: Error, stackTraces: NodeJS.CallSite[]) => + prepareStackTrace( + error, + stackTraces.filter((frame) => !isAllureJasmineFrame(frame)), + ); + +const hideAllureFramesFromFunc = TReturn>( + target: TFn, + ...args: TArgs +) => { + const originalPrepareStackTrace = Error.prepareStackTrace; + const underlyingPrepareStackTrace = originalPrepareStackTrace ?? defaultPrepareStackTrace; + Error.prepareStackTrace = createStackFilter(underlyingPrepareStackTrace); + try { + return target(...args); + } finally { + Error.prepareStackTrace = originalPrepareStackTrace; + } +}; + +const getIndexedTestPlan = (): TestPlanIndex | undefined => { + const testplan = parseTestPlan(); + if (testplan) { + return { + ids: new Set(testplan.tests.filter((e) => e.id).map((e) => e.id!.toString())), + fullNames: new Set(testplan.tests.filter((e) => e.selector).map((e) => e.selector!)), + }; + } +}; + +const isInTestPlan = (testplan: TestPlanIndex | undefined, fullName: string, labels: readonly Label[]) => { + if (testplan && !testplan.fullNames.has(fullName)) { + const allureId = labels.find((l) => l.name === LabelName.ALLURE_ID)?.value; + return allureId && testplan.ids.has(allureId); + } + return true; +}; + +export const enableAllureJasmineTestPlan = () => { + const jasmineDescribe: JasmineSuiteFn = global.describe; + const jasmineIt: JasmineSpecFn = global.it; + const jasmineXit: JasmineSpecFn = global.xit; + + const suites: string[] = []; + let currentFile: string | undefined; + const testplan = getIndexedTestPlan(); + + global.describe = (description: string, specDefinitions: () => void) => { + const callerFile = getCallerFile(global.describe); + if (!callerFile) { + return hideAllureFramesFromFunc(jasmineDescribe, description, specDefinitions); + } else { + if (callerFile !== currentFile) { + currentFile = callerFile; + suites.splice(0, suites.length); + } + + suites.push(description); + try { + return hideAllureFramesFromFunc(jasmineDescribe, description, specDefinitions); + } finally { + suites.pop(); + } + } + }; + + global.it = (expectation: string, assertion?: jasmine.ImplementationCallback, timeout?: number) => { + const filename = currentFile ?? getCallerFile(global.it); + const { fullName, labels } = getAllureNamesAndLabels(filename, suites, expectation); + if (isInTestPlan(testplan, fullName, labels)) { + return hideAllureFramesFromFunc(jasmineIt, expectation, assertion, timeout); + } else { + return hideAllureFramesFromFunc(jasmineXit, addSkipLabelAsMeta(expectation), assertion, timeout); + } + }; +}; diff --git a/packages/allure-jasmine/src/utils.ts b/packages/allure-jasmine/src/utils.ts index 97ebad441..43ed62993 100644 --- a/packages/allure-jasmine/src/utils.ts +++ b/packages/allure-jasmine/src/utils.ts @@ -1,4 +1,6 @@ -// eslint-disable-next-line no-undef +import { cwd } from "node:process"; +import { extractMetadataFromString } from "allure-js-commons/sdk"; + import FailedExpectation = jasmine.FailedExpectation; export const findAnyError = (expectations?: FailedExpectation[]): FailedExpectation | null => { @@ -14,3 +16,19 @@ export const findMessageAboutThrow = (expectations?: FailedExpectation[]) => { }; export const last = (arr: readonly T[]) => (arr.length ? arr[arr.length - 1] : undefined); + +export const getAllureNamesAndLabels = ( + filename: string | undefined, + suites: readonly string[], + rawSpecName: string, +) => { + const filePart = (filename || "").replace(cwd(), "").replace(/^[/\\]/, ""); + const { cleanTitle: specName, labels } = extractMetadataFromString(rawSpecName); + const specPart = [...suites, specName].join(" > "); + + return { + name: specName, + fullName: `${filePart}#${specPart}`, + labels, + }; +}; diff --git a/packages/allure-jasmine/test/spec/hooks.test.ts b/packages/allure-jasmine/test/spec/hooks.test.ts index f810f72d5..fbe7c3318 100644 --- a/packages/allure-jasmine/test/spec/hooks.test.ts +++ b/packages/allure-jasmine/test/spec/hooks.test.ts @@ -420,10 +420,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: expect.objectContaining({ - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }), }), ]); expect(groups, "has broken fixture").toEqual([ @@ -458,10 +454,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: expect.objectContaining({ - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }), }), ]); expect(groups, "has broken fixture").toEqual([ @@ -497,10 +489,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: expect.objectContaining({ - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }), }), ]); expect(groups, "has broken fixture").toEqual([ @@ -535,10 +523,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: expect.objectContaining({ - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }), }), ]); expect(groups, "has broken fixture").toEqual([ @@ -573,10 +557,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: { - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }, }), ]); expect(groups, "has broken fixture").toEqual([ @@ -610,10 +590,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: { - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }, }), ]); expect(groups, "has broken fixture").toEqual([ @@ -647,10 +623,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: { - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }, }), ]); expect(groups, "has broken fixture").toEqual([ @@ -685,10 +657,6 @@ describe("hook failures", () => { expect.objectContaining({ name: "bar", status: Status.BROKEN, - statusDetails: { - message: expect.stringContaining("Not run because a beforeAll function failed"), - trace: expect.anything(), - }, }), ]); expect(groups, "has broken fixture").toEqual([ diff --git a/packages/allure-jasmine/test/spec/metadata.test.ts b/packages/allure-jasmine/test/spec/metadata.test.ts new file mode 100644 index 000000000..d420a6bd7 --- /dev/null +++ b/packages/allure-jasmine/test/spec/metadata.test.ts @@ -0,0 +1,29 @@ +import { expect, it } from "vitest"; +import { Status } from "allure-js-commons"; +import { runJasmineInlineTest } from "../utils.js"; + +it("should add labels from embedded metadata", async () => { + const { tests } = await runJasmineInlineTest({ + "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", + }, + ]), + }), + ]); +}); diff --git a/packages/allure-jasmine/test/spec/testplan.test.ts b/packages/allure-jasmine/test/spec/testplan.test.ts new file mode 100644 index 000000000..6c2c5f16f --- /dev/null +++ b/packages/allure-jasmine/test/spec/testplan.test.ts @@ -0,0 +1,65 @@ +import { expect, it } from "vitest"; +import { Status } from "allure-js-commons"; +import { runJasmineInlineTest } from "../utils.js"; + +it("should filter tests by selector", async () => { + const { tests } = await runJasmineInlineTest( + { + "spec/test/sample.spec.js": ` + it("foo", () => {}); + it("bar", () => {}); + it("baz", () => {}); + it("qux", () => {}); + `, + "testplan.json": JSON.stringify({ + tests: [{ selector: "spec/test/sample.spec.js#foo" }, { selector: "spec/test/sample.spec.js#baz" }], + }), + }, + { ALLURE_TESTPLAN_PATH: "testplan.json" }, + ); + + expect(tests).toHaveLength(2); + expect(tests).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: "foo", + status: Status.PASSED, + }), + expect.objectContaining({ + name: "baz", + status: Status.PASSED, + }), + ]), + ); +}); + +it("should filter tests by id", async () => { + const { tests } = await runJasmineInlineTest( + { + "spec/test/sample.spec.js": ` + it("foo @allure.id:1004", () => {}); + it("bar", () => {}); + it("baz @allure.id:1005", () => {}); + it("qux @allure.id:1006", () => {}); + `, + "testplan.json": JSON.stringify({ + tests: [{ id: "1004" }, { id: "1005" }], + }), + }, + { ALLURE_TESTPLAN_PATH: "testplan.json" }, + ); + + expect(tests).toHaveLength(2); + expect(tests).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + name: "foo", + status: Status.PASSED, + }), + expect.objectContaining({ + name: "baz", + status: Status.PASSED, + }), + ]), + ); +}); diff --git a/packages/allure-js-commons/src/sdk/reporter/ReporterRuntime.ts b/packages/allure-js-commons/src/sdk/reporter/ReporterRuntime.ts index 9dbe655e5..f624005b2 100644 --- a/packages/allure-js-commons/src/sdk/reporter/ReporterRuntime.ts +++ b/packages/allure-js-commons/src/sdk/reporter/ReporterRuntime.ts @@ -22,6 +22,7 @@ import type { import { LifecycleState } from "./LifecycleState.js"; import { Notifier } from "./Notifier.js"; import { createFixtureResult, createStepResult, createTestResult } from "./factory.js"; +import { hasSkipLabel } from "./testplan.js"; import type { Config, FixtureType, FixtureWrapper, LinkConfig, TestScope, Writer } from "./types.js"; import { deepClone, formatLinks, getTestResultHistoryId, getTestResultTestCaseId, randomUuid } from "./utils.js"; import { buildAttachmentFileName } from "./utils/attachments.js"; @@ -246,7 +247,7 @@ export class ReporterRuntime { return; } - if (testResult.labels.find((label) => label.name === "ALLURE_TESTPLAN_SKIP")) { + if (hasSkipLabel(testResult.labels)) { this.state.deleteTestResult(uuid); return; } diff --git a/packages/allure-js-commons/src/sdk/reporter/testplan.ts b/packages/allure-js-commons/src/sdk/reporter/testplan.ts index dd1b70f9e..0093a2a91 100644 --- a/packages/allure-js-commons/src/sdk/reporter/testplan.ts +++ b/packages/allure-js-commons/src/sdk/reporter/testplan.ts @@ -1,4 +1,5 @@ import { readFileSync } from "node:fs"; +import type { Label } from "../../model.js"; import type { TestPlanV1 } from "../types.js"; import { allureIdRegexp } from "../utils.js"; @@ -39,3 +40,13 @@ export const includedInTestPlan = ( return idMatched || selectorMatched; }); }; + +export const addSkipLabel = (labels: Label[]) => { + labels.push({ name: "ALLURE_TESTPLAN_SKIP", value: "true" }); +}; + +export const addSkipLabelAsMeta = (name: string) => { + return `${name} @allure.label.ALLURE_TESTPLAN_SKIP:true`; +}; + +export const hasSkipLabel = (labels: readonly Label[]) => labels.some(({ name }) => name === "ALLURE_TESTPLAN_SKIP"); diff --git a/packages/allure-js-commons/test/sdk/reporter/testplan.spec.ts b/packages/allure-js-commons/test/sdk/reporter/testplan.spec.ts index 1be3e5097..1cad7e3a6 100644 --- a/packages/allure-js-commons/test/sdk/reporter/testplan.spec.ts +++ b/packages/allure-js-commons/test/sdk/reporter/testplan.spec.ts @@ -3,7 +3,14 @@ import { mkdtempSync, writeFileSync } from "fs"; import os from "os"; import path from "path"; import { afterEach, describe, expect, it } from "vitest"; -import { includedInTestPlan, parseTestPlan } from "../../../src/sdk/reporter/testplan.js"; +import type { Label } from "../../../src/model.js"; +import { + addSkipLabel, + addSkipLabelAsMeta, + hasSkipLabel, + includedInTestPlan, + parseTestPlan, +} from "../../../src/sdk/reporter/testplan.js"; import type { TestPlanV1 } from "../../../src/sdk/types.js"; const originalEnv = process.env; @@ -111,3 +118,39 @@ describe("includedInTestPlan", () => { expect(r2).toBe(false); }); }); + +describe("skip labels", () => { + describe("addSkipLabel", () => { + it("should add the label", () => { + const labels: Label[] = []; + addSkipLabel(labels); + + expect(labels).toEqual([{ name: "ALLURE_TESTPLAN_SKIP", value: "true" }]); + }); + }); + + describe("addSkipLabelAsMeta", () => { + it("should append the label meta to the name", () => { + const newName = addSkipLabelAsMeta("name"); + + expect(newName).toEqual("name @allure.label.ALLURE_TESTPLAN_SKIP:true"); + }); + }); + + describe("hasSkipLabel", () => { + it("should return true is the label is present", () => { + const value = hasSkipLabel([ + { name: "foo", value: "bar" }, + { name: "ALLURE_TESTPLAN_SKIP", value: "" }, + ]); + + expect(value).toBe(true); + }); + + it("should return false is the label is not present", () => { + const value = hasSkipLabel([{ name: "foo", value: "bar" }]); + + expect(value).toBe(false); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 4c5ab01dd..939fb4489 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4054,6 +4054,7 @@ __metadata: allure-js-commons: "workspace:*" allure-vitest: "workspace:*" babel-plugin-add-module-exports: "npm:^1.0.4" + babel-plugin-transform-import-meta: "npm:^2.2.1" eslint: "npm:^8.57.0" eslint-config-prettier: "npm:^9.0.0" eslint-plugin-import: "npm:^2.28.1"