diff --git a/packages/allure-jest/src/environmentFactory.ts b/packages/allure-jest/src/environmentFactory.ts index dbc990a6d..2730891d6 100644 --- a/packages/allure-jest/src/environmentFactory.ts +++ b/packages/allure-jest/src/environmentFactory.ts @@ -1,4 +1,4 @@ -import type { EnvironmentContext, JestEnvironment } from "@jest/environment"; +import type { EnvironmentContext, JestEnvironment, JestEnvironmentConfig } from "@jest/environment"; import type { Circus } from "@jest/types"; import os from "node:os"; import { dirname, sep } from "node:path"; @@ -18,7 +18,7 @@ import { } from "allure-js-commons/sdk/reporter"; import { setGlobalTestRuntime } from "allure-js-commons/sdk/runtime"; import { AllureJestTestRuntime } from "./AllureJestTestRuntime.js"; -import type { AllureJestConfig, AllureJestEnvironment, RunContext } from "./model.js"; +import type { AllureJestConfig, AllureJestEnvironment, AllureJestProjectConfig, RunContext } from "./model.js"; import { getTestId, getTestPath, isTestPresentInTestPlan, last, shouldHookBeSkipped } from "./utils.js"; const { ALLURE_TEST_MODE, ALLURE_HOST_NAME, ALLURE_THREAD_NAME, JEST_WORKER_ID } = process.env; @@ -37,9 +37,13 @@ const createJestEnvironment = (Base: T): T => skippedTestsFullNamesByTestPlan: [], }; - constructor(config: AllureJestConfig, context: EnvironmentContext) { - super(config, context); - const { resultsDir = "allure-results", ...restConfig } = config?.projectConfig?.testEnvironmentOptions || {}; + // config is AllureJestConfig in Jest v28 or greater. In older versions + // it's AllureJestProjectConfig. See https://github.com/jestjs/jest/pull/12461 + constructor(config: AllureJestConfig | AllureJestProjectConfig, context: EnvironmentContext) { + super(config as JestEnvironmentConfig, context); + + const projectConfig = "projectConfig" in config ? config.projectConfig : config; + const { resultsDir = "allure-results", ...restConfig } = projectConfig?.testEnvironmentOptions || {}; this.runtime = new ReporterRuntime({ ...restConfig, @@ -49,7 +53,7 @@ const createJestEnvironment = (Base: T): T => resultsDir, }), }); - this.testPath = context.testPath.replace(config.globalConfig.rootDir, "").replace(sep, ""); + this.testPath = context.testPath.replace(projectConfig.rootDir, "").replace(sep, ""); this.testPlan = parseTestPlan(); // @ts-ignore diff --git a/packages/allure-jest/src/jsdom.ts b/packages/allure-jest/src/jsdom.ts index 07f79be11..2d7d10bc3 100644 --- a/packages/allure-jest/src/jsdom.ts +++ b/packages/allure-jest/src/jsdom.ts @@ -1,4 +1,4 @@ -import { TestEnvironment } from "jest-environment-jsdom"; +import TestEnvironment from "jest-environment-jsdom"; import createJestEnvironment from "./environmentFactory.js"; export default createJestEnvironment(TestEnvironment); diff --git a/packages/allure-jest/src/model.ts b/packages/allure-jest/src/model.ts index a8f53f777..cebae09b1 100644 --- a/packages/allure-jest/src/model.ts +++ b/packages/allure-jest/src/model.ts @@ -1,4 +1,5 @@ import type { JestEnvironment, JestEnvironmentConfig } from "@jest/environment"; +import type { Config as JestConfig } from "@jest/types"; import type { RuntimeMessage } from "allure-js-commons/sdk"; import type { Config } from "allure-js-commons/sdk/reporter"; @@ -14,8 +15,10 @@ export interface AllureJestEnvironment extends JestEnvironment { handleAllureRuntimeMessage(message: RuntimeMessage): void; } -export interface AllureJestConfig extends JestEnvironmentConfig { - projectConfig: JestEnvironmentConfig["projectConfig"] & { - testEnvironmentOptions?: JestEnvironmentConfig["projectConfig"]["testEnvironmentOptions"] & Config; - }; -} +export type AllureJestProjectConfig = JestConfig.ProjectConfig & { + testEnvironmentOptions?: JestConfig.ProjectConfig["testEnvironmentOptions"] & Config; +}; + +export type AllureJestConfig = JestEnvironmentConfig & { + projectConfig: AllureJestProjectConfig; +}; diff --git a/packages/allure-jest/src/node.ts b/packages/allure-jest/src/node.ts index 10de6de80..b493ff394 100644 --- a/packages/allure-jest/src/node.ts +++ b/packages/allure-jest/src/node.ts @@ -1,4 +1,4 @@ -import { TestEnvironment } from "jest-environment-node"; +import TestEnvironment from "jest-environment-node"; import createJestEnvironment from "./environmentFactory.js"; export default createJestEnvironment(TestEnvironment); diff --git a/packages/allure-jest/src/utils.ts b/packages/allure-jest/src/utils.ts index c3dec46df..dc5852549 100644 --- a/packages/allure-jest/src/utils.ts +++ b/packages/allure-jest/src/utils.ts @@ -45,10 +45,17 @@ export const getTestId = (path: string[]): string => path.join(" "); */ export const getTestFullName = (path: string[]): string => path.join(" > "); +const jestHookPattern = /^at jestAdapter/i; +// A slightly different reference should be used to identify jestAdapter's global hook in some older versions of Jest. +const jestHookLegacyPattern = /jest-circus\/build\/legacy-code-todo-rewrite\/jestAdapter.js:\d+:\d+$/; + export const shouldHookBeSkipped = (hook: Circus.Hook): boolean => { - const errorFirstLine = hook?.asyncError?.stack?.split("\n")?.[1]?.trim() || ""; + // In older versions of Jest the hook's stack is direcrly in asyncError. In newer ones - in asyncError.stack. + const stackOrError: string | Error | undefined = hook?.asyncError; + const stack = typeof stackOrError === "string" ? stackOrError : stackOrError?.stack; + const errorFirstLine = stack?.split("\n")?.[1]?.trim() || ""; - return /^at jestAdapter/i.test(errorFirstLine); + return jestHookPattern.test(errorFirstLine) || jestHookLegacyPattern.test(errorFirstLine); }; export const last = (array: T[]): T => array[array.length - 1];