diff --git a/src/config/defaults.js b/src/config/defaults.js index e7840e997..1af25c836 100644 --- a/src/config/defaults.js +++ b/src/config/defaults.js @@ -42,6 +42,8 @@ module.exports = { compositeImage: true, prepareBrowser: null, prepareEnvironment: null, + beforeAll: null, + afterAll: null, waitTimeout: 3000, waitInterval: 500, httpTimeout: 30000, diff --git a/src/config/options.js b/src/config/options.js index 771b81f70..cbb8d3657 100644 --- a/src/config/options.js +++ b/src/config/options.js @@ -16,6 +16,8 @@ const rootSection = section( browsers: map(section(browserOptions.getPerBrowser())), prepareEnvironment: options.optionalFunction("prepareEnvironment"), + beforeAll: options.optionalFunction("beforeAll"), + afterAll: options.optionalFunction("afterAll"), system: section({ debug: options.boolean("debug"), diff --git a/src/config/types.ts b/src/config/types.ts index d07bc3c37..3bfc237ca 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -3,6 +3,7 @@ import type { BrowserTestRunEnvOptions } from "../runner/browser-env/vite/types" import type { Test } from "../types"; import type { ChildProcessWithoutNullStreams } from "child_process"; import type { RequestOptions } from "https"; +import type { Config } from "./index"; export interface CompareOptsConfig { shouldCluster: boolean; @@ -379,12 +380,16 @@ type PartialCommonConfig = Partial< devServer?: Partial; }; +export type HookType = (params: { config: Config }) => Promise | undefined; + // Only browsers desiredCapabilities are required in input config export type ConfigInput = Partial & { browsers: Record; plugins?: Record; sets?: Record; prepareEnvironment?: () => void | null; + beforeAll?: HookType; + afterAll?: HookType; }; export interface ConfigParsed extends CommonConfig { @@ -392,6 +397,8 @@ export interface ConfigParsed extends CommonConfig { plugins: Record>; sets: Record; prepareEnvironment?: () => void | null; + beforeAll?: HookType; + afterAll?: HookType; } export interface RuntimeConfig { diff --git a/src/testplane.ts b/src/testplane.ts index 0b3cdfc07..ca9183f16 100644 --- a/src/testplane.ts +++ b/src/testplane.ts @@ -153,11 +153,19 @@ export class Testplane extends BaseTestplane { preloadWebdriverIO(); + if (this.config.beforeAll) { + await this.config.beforeAll.call({ config: this.config }, { config: this.config }); + } + await runner.run( await this._readTests(testPaths, { browsers, sets, grep, replMode, keepBrowserMode }), RunnerStats.create(this), ); + if (this.config.afterAll) { + await this.config.afterAll.call({ config: this.config }, { config: this.config }); + } + return !this.isFailed(); } diff --git a/test/src/config/options.js b/test/src/config/options.js index 360ba8aea..adcf42e15 100644 --- a/test/src/config/options.js +++ b/test/src/config/options.js @@ -627,6 +627,58 @@ describe("config options", () => { }); }); + describe("hooks beforeAll/afterAll", () => { + it("should throw error if beforeAll is not a null or function", () => { + const readConfig = { beforeAll: "String" }; + + Config.read.returns(readConfig); + + assert.throws(() => createConfig(), Error, '"beforeAll" must be a function'); + }); + + it("should set default beforeAll option if it does not set in config file", () => { + const config = createConfig(); + + assert.equal(config.beforeAll, defaults.beforeAll); + }); + + it("should override beforeAll option", () => { + const newFunc = () => {}; + const readConfig = { beforeAll: newFunc }; + + Config.read.returns(readConfig); + + const config = createConfig(); + + assert.deepEqual(config.beforeAll, newFunc); + }); + + it("should throw error if afterAll is not a null or function", () => { + const readConfig = { afterAll: "String" }; + + Config.read.returns(readConfig); + + assert.throws(() => createConfig(), Error, '"afterAll" must be a function'); + }); + + it("should set default afterAll option if it does not set in config file", () => { + const config = createConfig(); + + assert.equal(config.afterAll, defaults.afterAll); + }); + + it("should override afterAll option", () => { + const newFunc = () => {}; + const readConfig = { afterAll: newFunc }; + + Config.read.returns(readConfig); + + const config = createConfig(); + + assert.deepEqual(config.afterAll, newFunc); + }); + }); + describe("plugins", () => { it("should parse boolean value from environment", () => { const result = parse_({