diff --git a/src/base-testplane.ts b/src/base-testplane.ts index 47acd741f..f87a336ac 100644 --- a/src/base-testplane.ts +++ b/src/base-testplane.ts @@ -16,22 +16,31 @@ import { ConfigInput } from "./config/types"; export abstract class BaseTestplane extends AsyncEmitter { protected _interceptors: Interceptor[] = []; - protected _config: Config; + protected _config!: Config; + private _pendingConfig?: string | ConfigInput; - static create( + static async create( this: new (config?: string | ConfigInput) => T, config?: string | ConfigInput, - ): T { - return new this(config); + ): Promise { + const instance = new this(config); + + await instance._setup(); + + return instance; } protected constructor(config?: string | ConfigInput) { super(); this._interceptors = []; + this._pendingConfig = config; + } + protected async _setup(): Promise { registerTransformHook(this.isWorker()); - this._config = Config.create(config); + this._config = await Config.create(this._pendingConfig); + this._pendingConfig = undefined; updateTransformHook(this._config); this._setLogLevel(); diff --git a/src/cli/index.ts b/src/cli/index.ts index 1f4ae0fe2..c813ac610 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -58,7 +58,7 @@ export const run = async (opts: TestplaneRunOpts = {}): Promise => { } const configPath = preparseOption(program, "config") as string; - testplane = Testplane.create(configPath); + testplane = await Testplane.create(configPath); withCommonCliOptions({ cmd: program, actionName: "run" }) .on("--help", () => console.log(configOverriding(opts))) diff --git a/src/config/index.ts b/src/config/index.ts index fc0a2713e..215457117 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -1,65 +1,103 @@ -import * as path from "path"; -import * as _ from "lodash"; +import path from "path"; +import _ from "lodash"; import defaults from "./defaults"; import { BrowserConfig } from "./browser-config"; import parseOptions from "./options"; import * as logger from "../utils/logger"; -import { ConfigInput, ConfigParsed } from "./types"; +import { ConfigInput, ConfigInputData, ConfigParsed } from "./types"; import { addUserAgentToArgs } from "./utils"; export { TimeTravelMode } from "./types"; export class Config { - configPath!: string; + configPath?: string; - static create(config?: string | ConfigInput): Config { - return new Config(config); + static async create(config?: string | ConfigInput): Promise { + try { + const { configPath, options } = await Config._resolve(config); + + await Config._prepareEnvironment(options); + + return new Config(options, configPath); + } catch (e: unknown) { + const error = new Error(`Got an error while trying to read config: ${(e as Error).message}`); + error.stack = (e as Error).stack; + error.cause = (e as Error).cause; + + throw error; + } } - static read(configPath: string): unknown { + static async read(configPath: string): Promise { try { // eslint-disable-next-line @typescript-eslint/no-var-requires const configModule = require(path.resolve(process.cwd(), configPath)); + const exported = (configModule.__esModule ? configModule.default : configModule) as ConfigInput; - return configModule.__esModule ? configModule.default : configModule; + return await Config._resolveExportedConfig(exported); } catch (e) { logger.error(`Unable to read config from path ${configPath}`); throw e; } } - constructor(config?: string | ConfigInput) { - let options: ConfigInput; + private static async _resolve( + config?: string | ConfigInput, + ): Promise<{ configPath?: string; options: ConfigInputData }> { + if (typeof config === "function") { + return { options: await Config._resolveExportedConfig(config) }; + } + if (_.isObjectLike(config)) { - options = config as ConfigInput; - } else if (typeof config === "string") { - this.configPath = config; - options = Config.read(config) as ConfigInput; - } else { - for (const configPath of defaults.configPaths) { - try { - const resolvedConfigPath = path.resolve(configPath); - require(resolvedConfigPath); - this.configPath = resolvedConfigPath; - - break; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - } catch (err: any) { - if (err.code !== "MODULE_NOT_FOUND") { - throw err; - } + return { options: config as ConfigInputData }; + } + + if (typeof config === "string") { + return { configPath: config, options: await Config.read(config) }; + } + + const located = Config._locateConfigPath(); + + if (!located) { + throw new Error(`Unable to read config from paths: ${defaults.configPaths.join(", ")}`); + } + + return { configPath: located, options: await Config.read(located) }; + } + + private static _locateConfigPath(): string | null { + for (const configPath of defaults.configPaths) { + try { + const resolvedConfigPath = path.resolve(configPath); + // eslint-disable-next-line @typescript-eslint/no-var-requires + require(resolvedConfigPath); + + return resolvedConfigPath; + } catch (err: unknown) { + if ((err as { code?: string }).code !== "MODULE_NOT_FOUND") { + throw err; } } + } - if (!this.configPath) { - throw new Error(`Unable to read config from paths: ${defaults.configPaths.join(", ")}`); - } + return null; + } - options = Config.read(this.configPath) as ConfigInput; - } + private static async _resolveExportedConfig(exported: ConfigInput): Promise { + const resolved = typeof exported === "function" ? await (exported as () => unknown)() : exported; + + return resolved as ConfigInputData; + } + private static async _prepareEnvironment(options: ConfigInputData): Promise { if (_.isFunction(options.prepareEnvironment)) { - options.prepareEnvironment(); + await options.prepareEnvironment(); + } + } + + constructor(options: ConfigInputData, configPath?: string) { + if (configPath) { + this.configPath = configPath; } const parsedOptions = parseOptions({ diff --git a/src/config/types.ts b/src/config/types.ts index 8c15ffe10..4152e62dd 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -459,20 +459,22 @@ type PartialCommonConfig = Partial< export type HookType = (params: { config: Config }) => Promise | undefined; // Only browsers desiredCapabilities are required in input config -export type ConfigInput = Partial & { +export type ConfigInputData = Partial & { browsers: Record; plugins?: Record; sets?: Record; - prepareEnvironment?: () => void | null; + prepareEnvironment?: () => void | Promise | null; beforeAll?: HookType; afterAll?: HookType; }; +export type ConfigInput = ConfigInputData | (() => ConfigInputData) | (() => Promise); + export interface ConfigParsed extends CommonConfig { browsers: Record; plugins: Record>; sets: Record; - prepareEnvironment?: () => void | null; + prepareEnvironment?: () => void | Promise | null; beforeAll?: HookType; afterAll?: HookType; } diff --git a/src/dev-server/index.ts b/src/dev-server/index.ts index bb0560a5b..8472ef2a2 100644 --- a/src/dev-server/index.ts +++ b/src/dev-server/index.ts @@ -6,7 +6,11 @@ import { findCwd, pipeLogsWithPrefix, probeServer, waitDevServerReady } from "./ import * as logger from "../utils/logger"; import type { Testplane } from "../testplane"; -export type DevServerOpts = { testplane: Testplane; devServerConfig: Config["devServer"]; configPath: string }; +export type DevServerOpts = { + testplane: Testplane; + devServerConfig: Config["devServer"]; + configPath?: string; +}; export type InitDevServer = (opts: DevServerOpts) => Promise; @@ -45,7 +49,7 @@ export const initDevServer: InitDevServer = async ({ testplane, devServerConfig, const devServer = spawn(devServerConfig.command, devServerConfig.args, { env: { ...process.env, ...devServerConfig.env }, - cwd: devServerConfig.cwd || findCwd(configPath), + cwd: devServerConfig.cwd || (configPath ? findCwd(configPath) : process.cwd()), shell: true, windowsHide: true, }); diff --git a/src/worker/testplane-facade.ts b/src/worker/testplane-facade.ts index a3e298467..c057c1561 100644 --- a/src/worker/testplane-facade.ts +++ b/src/worker/testplane-facade.ts @@ -69,13 +69,15 @@ module.exports = class TestplaneFacade { }); } - promise = promise.then(() => { - RuntimeConfig.getInstance().extend(runtimeConfig); - const testplane = Testplane.create(configPath); - - debug("worker initialized"); - resolve(testplane); - }); + promise = promise + .then(async () => { + RuntimeConfig.getInstance().extend(runtimeConfig); + const testplane = await Testplane.create(configPath); + + debug("worker initialized"); + resolve(testplane); + }) + .catch(reject); } catch (e) { debug("worker initialization failed"); reject(e); diff --git a/src/worker/testplane.ts b/src/worker/testplane.ts index d55c3b867..8b057b9df 100644 --- a/src/worker/testplane.ts +++ b/src/worker/testplane.ts @@ -41,10 +41,14 @@ export interface Testplane { } export class Testplane extends BaseTestplane { - protected runner: Runner; + protected runner!: Runner; constructor(config?: string | ConfigInput) { super(config); + } + + protected async _setup(): Promise { + await super._setup(); this.runner = Runner.create(this._config); diff --git a/test/src/cli/commands/config/index.ts b/test/src/cli/commands/config/index.ts index 69bec5700..d9d1df43d 100644 --- a/test/src/cli/commands/config/index.ts +++ b/test/src/cli/commands/config/index.ts @@ -11,9 +11,9 @@ describe("cli/commands/config", () => { let consoleInfoStub: SinonStub; let jsonStringifyStub: SinonSpy; - const config_ = async (options: string[] = [], cli: { run: VoidFunction } = testplaneCli): Promise => { + const config_ = async (options: string[] = [], cli: { run: () => Promise } = testplaneCli): Promise => { process.argv = ["foo/bar/node", "foo/bar/script", "config", ...options]; - cli.run(); + await cli.run(); await (Command.prototype.action as SinonStub).lastCall.returnValue; }; @@ -21,7 +21,7 @@ describe("cli/commands/config", () => { beforeEach(() => { testplaneStub = Object.create(Testplane.prototype); - sandbox.stub(Testplane, "create").returns(testplaneStub); + sandbox.stub(Testplane, "create").resolves(testplaneStub); consoleInfoStub = sandbox.stub(console, "info"); jsonStringifyStub = sandbox.spy(JSON, "stringify"); diff --git a/test/src/cli/commands/install-deps/index.ts b/test/src/cli/commands/install-deps/index.ts index 62a2ab08e..6d7b95dd6 100644 --- a/test/src/cli/commands/install-deps/index.ts +++ b/test/src/cli/commands/install-deps/index.ts @@ -9,14 +9,14 @@ import type { Config } from "../../../../../src/config"; describe("cli/commands/install-deps", () => { const sandbox = sinon.createSandbox(); - let cli: { run: () => void }; + let cli: { run: () => Promise }; let loggerStub: { log: SinonStub; warn: SinonStub; error: SinonStub }; let testplaneStub: Writable; let installBrowsersWithDriversStub: SinonStub; const installBrowsers_ = async (argv: string = ""): Promise => { process.argv = ["foo/bar/node", "foo/bar/script", "install-deps", ...argv.split(" ")].filter(Boolean); - cli.run(); + await cli.run(); await new Promise(resolve => setImmediate(resolve)); }; @@ -36,7 +36,7 @@ describe("cli/commands/install-deps", () => { configurable: true, }); - sandbox.stub(Testplane, "create").returns(testplaneStub as Testplane); + sandbox.stub(Testplane, "create").resolves(testplaneStub as Testplane); sandbox.stub(process, "exit"); diff --git a/test/src/cli/commands/list-browsers/index.ts b/test/src/cli/commands/list-browsers/index.ts index 65848a396..ceef0571e 100644 --- a/test/src/cli/commands/list-browsers/index.ts +++ b/test/src/cli/commands/list-browsers/index.ts @@ -14,9 +14,12 @@ describe("cli/commands/list-browsers", () => { let loggerErrorStub: SinonStub; let consoleInfoStub: SinonStub; - const listBrowsers_ = async (options: string[] = [], cli: { run: VoidFunction } = testplaneCli): Promise => { + const listBrowsers_ = async ( + options: string[] = [], + cli: { run: () => Promise } = testplaneCli, + ): Promise => { process.argv = ["foo/bar/node", "foo/bar/script", "list-browsers", ...options]; - cli.run(); + await cli.run(); await (Command.prototype.action as SinonStub).lastCall.returnValue; }; @@ -56,7 +59,7 @@ describe("cli/commands/list-browsers", () => { configurable: true, }); - sandbox.stub(Testplane, "create").returns(testplaneStub); + sandbox.stub(Testplane, "create").resolves(testplaneStub); consoleInfoStub = sandbox.stub(console, "info"); sandbox.stub(process, "exit"); diff --git a/test/src/cli/commands/list-tests/index.ts b/test/src/cli/commands/list-tests/index.ts index 7600f7eb4..28f00782f 100644 --- a/test/src/cli/commands/list-tests/index.ts +++ b/test/src/cli/commands/list-tests/index.ts @@ -13,9 +13,9 @@ describe("cli/commands/list-tests", () => { const sandbox = sinon.createSandbox(); let testplaneCli: typeof testplaneCliOriginal; - const listTests_ = async (argv: string = "", cli: { run: VoidFunction } = testplaneCli): Promise => { + const listTests_ = async (argv: string = "", cli: { run: () => Promise } = testplaneCli): Promise => { process.argv = ["foo/bar/node", "foo/bar/script", "list-tests", ...argv.split(" ")].filter(Boolean); - cli.run(); + await cli.run(); await (Command.prototype.action as SinonStub).lastCall.returnValue; }; @@ -36,7 +36,7 @@ describe("cli/commands/list-tests", () => { }, ), }); - sandbox.stub(Testplane, "create").returns(Object.create(Testplane.prototype)); + sandbox.stub(Testplane, "create").resolves(Object.create(Testplane.prototype)); sandbox.stub(Testplane.prototype, "readTests").resolves(TestCollection.create({})); sandbox.stub(fs, "ensureDir").resolves(); diff --git a/test/src/cli/index.js b/test/src/cli/index.js index 49c74a920..ea31e5e12 100644 --- a/test/src/cli/index.js +++ b/test/src/cli/index.js @@ -45,7 +45,7 @@ describe("cli", () => { "get-port": getPortStub, }); - sandbox.stub(Testplane, "create").returns(Object.create(Testplane.prototype)); + sandbox.stub(Testplane, "create").resolves(Object.create(Testplane.prototype)); sandbox.stub(Testplane.prototype, "run").resolves(); sandbox.stub(Testplane.prototype, "extendCli"); diff --git a/test/src/config/browser-options.js b/test/src/config/browser-options.js index 2d256b542..aa52138f1 100644 --- a/test/src/config/browser-options.js +++ b/test/src/config/browser-options.js @@ -28,19 +28,19 @@ describe("config browser-options", () => { describe("desiredCapabilities", () => { describe("should throw error if desiredCapabilities", () => { - it("is missing", () => { + it("is missing", async () => { const readConfig = { browsers: { b1: {}, }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, 'Each browser must have "desiredCapabilities" option'); + await assert.isRejected(createConfig(), 'Each browser must have "desiredCapabilities" option'); }); - it("is not an object or null", () => { + it("is not an object or null", async () => { const readConfig = { browsers: { b1: { @@ -49,16 +49,16 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"desiredCapabilities" must be an object'); + await assert.isRejected(createConfig(), '"desiredCapabilities" must be an object'); }); }); describe("BiDi protocol", () => { - BROWSERS_SUPPORT_BIDI.forEach(({ name: browserName, minVersion }) => { + BROWSERS_SUPPORT_BIDI.forEach(async ({ name: browserName, minVersion }) => { describe(browserName, () => { - it("should throw error if browser not support protocol", () => { + it("should throw error if browser not support protocol", async () => { const browserVersion = `${minVersion - 1}.0`; const readConfig = { browsers: { @@ -72,16 +72,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `BiDi protocol is not supported in ${browserName}@${browserVersion}, use ${browserName}@${minVersion}.0 and higher`, ); }); - it("should not throw if browser support protocol", () => { + it("should not throw if browser support protocol", async () => { const readConfig = { browsers: { b1: { @@ -94,12 +93,12 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); - it('should not throw if "browserVersion" is not specified', () => { + it('should not throw if "browserVersion" is not specified', async () => { const readConfig = { browsers: { b1: { @@ -111,15 +110,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); }); }); - it("should set desiredCapabilities", () => { + it("should set desiredCapabilities", async () => { const readConfig = { browsers: { b1: { @@ -130,28 +129,28 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.desiredCapabilities, { browserName: "yabro" }); }); }); describe("baseUrl", () => { - it("should throw error if baseUrl is not a string", () => { + it("should throw error if baseUrl is not a string", async () => { const readConfig = { browsers: { b1: mkBrowser_({ baseUrl: ["Array"] }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"baseUrl" must be a string'); + await assert.isRejected(createConfig(), '"baseUrl" must be a string'); }); - it("should set baseUrl to all browsers", () => { + it("should set baseUrl to all browsers", async () => { const baseUrl = "http://default.com"; const readConfig = { baseUrl, @@ -161,15 +160,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.baseUrl, baseUrl); assert.equal(config.browsers.b2.baseUrl, baseUrl); }); - it("should override baseUrl option if protocol is set", () => { + it("should override baseUrl option if protocol is set", async () => { const baseUrl = "http://default.com"; const readConfig = { baseUrl, @@ -179,15 +178,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.baseUrl, baseUrl); assert.equal(config.browsers.b2.baseUrl, "http://foo.com"); }); - it("should resolve baseUrl option relative to top level baseUrl", () => { + it("should resolve baseUrl option relative to top level baseUrl", async () => { const baseUrl = "http://default.com"; const readConfig = { baseUrl, @@ -197,15 +196,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.baseUrl, baseUrl); assert.equal(config.browsers.b2.baseUrl, "http://default.com/test"); }); - it("should resolve baseUrl option relative to top level baseUrl with path", () => { + it("should resolve baseUrl option relative to top level baseUrl with path", async () => { const baseUrl = "http://default.com/search/"; const readConfig = { baseUrl, @@ -215,9 +214,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.baseUrl, baseUrl); assert.equal(config.browsers.b2.baseUrl, "http://default.com/search/test"); @@ -227,21 +226,21 @@ describe("config browser-options", () => { [ { optionName: "gridUrl", uriScheme: "http" }, { optionName: "browserWSEndpoint", uriScheme: "ws" }, - ].forEach(({ optionName, uriScheme }) => { + ].forEach(async ({ optionName, uriScheme }) => { describe(optionName, () => { - it("should throw error if option is not a string", () => { + it("should throw error if option is not a string", async () => { const readConfig = { browsers: { b1: mkBrowser_({ [optionName]: /regExp/ }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${optionName}" must be a string`); + await assert.isRejected(createConfig(), `"${optionName}" must be a string`); }); - it("should set option to all browsers", () => { + it("should set option to all browsers", async () => { const optionValue = `${uriScheme}://default.com`; const readConfig = { [optionName]: optionValue, @@ -251,15 +250,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[optionName], optionValue); assert.equal(config.browsers.b2[optionName], optionValue); }); - it("should override option", () => { + it("should override option", async () => { const optionValue = `${uriScheme}://default.com`; const readConfig = { [optionName]: optionValue, @@ -269,9 +268,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[optionName], optionValue); assert.equal(config.browsers.b2[optionName], `${uriScheme}://bar.com`); @@ -280,99 +279,97 @@ describe("config browser-options", () => { }); describe("browserWSEndpoint", () => { - it("should throw an error if option value does not start with WebSocket protocol", () => { + it("should throw an error if option value does not start with WebSocket protocol", async () => { const readConfig = { browsers: { b1: mkBrowser_({ browserWSEndpoint: "http://endpoint.com" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), /"browserWSEndpoint" must start with "ws:\/\/" or "wss:\/\/" prefix/, ); }); describe("should not throw an error if option value start with", () => { - ["ws", "wss"].forEach(protocol => { - it(protocol, () => { + ["ws", "wss"].forEach(async protocol => { + it(protocol, async () => { const readConfig = { browsers: { b1: mkBrowser_({ browserWSEndpoint: `${protocol}://endpoint.com` }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); }); }); describe("automationProtocol", () => { - it("should throw an error if option value is not string", () => { + it("should throw an error if option value is not string", async () => { const readConfig = { browsers: { b1: mkBrowser_({ automationProtocol: { not: "string" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /"automationProtocol" must be a string/); + await assert.isRejected(createConfig(), /"automationProtocol" must be a string/); }); - it(`should throw an error if option value is not "${WEBDRIVER_PROTOCOL}" or "${DEVTOOLS_PROTOCOL}"`, () => { + it(`should throw an error if option value is not "${WEBDRIVER_PROTOCOL}" or "${DEVTOOLS_PROTOCOL}"`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ automationProtocol: "foo bar" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), new RegExp(`"automationProtocol" must be "${WEBDRIVER_PROTOCOL}" or "${DEVTOOLS_PROTOCOL}"`), ); }); describe("should not throw an error if option value is", () => { - [WEBDRIVER_PROTOCOL, DEVTOOLS_PROTOCOL].forEach(value => { - it(`${value}`, () => { + [WEBDRIVER_PROTOCOL, DEVTOOLS_PROTOCOL].forEach(async value => { + it(`${value}`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ automationProtocol: value }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.automationProtocol, defaults.automationProtocol); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { automationProtocol: WEBDRIVER_PROTOCOL, browsers: { @@ -381,9 +378,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.automationProtocol, WEBDRIVER_PROTOCOL); assert.equal(config.browsers.b2.automationProtocol, DEVTOOLS_PROTOCOL); @@ -391,73 +388,75 @@ describe("config browser-options", () => { }); describe("sessionEnvFlags", () => { - it("should throw an error if option value is not an object", () => { + it("should throw an error if option value is not an object", async () => { const readConfig = { browsers: { b1: mkBrowser_({ sessionEnvFlags: "string" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /"sessionEnvFlags" must be an object/); + await assert.isRejected(createConfig(), /"sessionEnvFlags" must be an object/); }); - it("should throw an error if option value is not available", () => { + it("should throw an error if option value is not available", async () => { const readConfig = { browsers: { b1: mkBrowser_({ sessionEnvFlags: { a: "b" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /keys of "sessionEnvFlags" must be one of:/); + await assert.isRejected(createConfig(), /keys of "sessionEnvFlags" must be one of:/); }); - it("should throw an error if value inside available option is not boolean", () => { + it("should throw an error if value inside available option is not boolean", async () => { const readConfig = { browsers: { b1: mkBrowser_({ sessionEnvFlags: { isW3C: "string" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /values of "sessionEnvFlags" must be boolean/); + await assert.isRejected(createConfig(), /values of "sessionEnvFlags" must be boolean/); }); describe("should not throw an error if option key is", () => { - ["isW3C", "isChrome", "isMobile", "isIOS", "isAndroid", "isSauce", "isSeleniumStandalone"].forEach(key => { - it(`"${key}" and value is boolean`, () => { - const readConfig = { - browsers: { - b1: mkBrowser_({ sessionEnvFlags: { [key]: true } }), - }, - }; + ["isW3C", "isChrome", "isMobile", "isIOS", "isAndroid", "isSauce", "isSeleniumStandalone"].forEach( + async key => { + it(`"${key}" and value is boolean`, async () => { + const readConfig = { + browsers: { + b1: mkBrowser_({ sessionEnvFlags: { [key]: true } }), + }, + }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); - }); - }); + await assert.isFulfilled(createConfig()); + }); + }, + ); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.sessionEnvFlags, defaults.sessionEnvFlags); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { sessionEnvFlags: { isW3C: true }, browsers: { @@ -466,9 +465,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.sessionEnvFlags, { isW3C: true }); assert.deepEqual(config.browsers.b2.sessionEnvFlags, { isW3C: false }); @@ -476,19 +475,19 @@ describe("config browser-options", () => { }); describe("prepareBrowser", () => { - it("should throw error if prepareBrowser is not a null or function", () => { + it("should throw error if prepareBrowser is not a null or function", async () => { const readConfig = { browsers: { b1: mkBrowser_({ prepareBrowser: "String" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"prepareBrowser" must be a function'); + await assert.isRejected(createConfig(), '"prepareBrowser" must be a function'); }); - it("should set prepareBrowser to all browsers", () => { + it("should set prepareBrowser to all browsers", async () => { const prepareBrowser = () => {}; const readConfig = { prepareBrowser, @@ -498,15 +497,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.prepareBrowser, prepareBrowser); assert.equal(config.browsers.b2.prepareBrowser, prepareBrowser); }); - it("should override prepareBrowser option", () => { + it("should override prepareBrowser option", async () => { const prepareBrowser = () => {}; const newFunc = () => {}; @@ -518,9 +517,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.prepareBrowser, prepareBrowser); assert.equal(config.browsers.b2.prepareBrowser, newFunc); @@ -528,25 +527,25 @@ describe("config browser-options", () => { }); describe("screenshotsDir", () => { - it("should set a default screenshotsDir option if it is not set in config", () => { - const config = createConfig(); + it("should set a default screenshotsDir option if it is not set in config", async () => { + const config = await createConfig(); assert.equal(config.screenshotsDir, defaults.screenshotsDir); }); - it("should throw an error if a value is not a string or function", () => { + it("should throw an error if a value is not a string or function", async () => { const readConfig = { browsers: { b1: mkBrowser_({ screenshotsDir: ["Array"] }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"screenshotsDir" must be a string or function'); + await assert.isRejected(createConfig(), '"screenshotsDir" must be a string or function'); }); - it("should does not throw if a value is a function", () => { + it("should does not throw if a value is a function", async () => { const readConfig = { screenshotsDir: () => {}, browsers: { @@ -554,12 +553,12 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(createConfig); + await assert.isFulfilled(createConfig()); }); - it("should set screenshotsDir option to all browsers", () => { + it("should set screenshotsDir option to all browsers", async () => { const screenshotsDir = "/some/dir"; const readConfig = { screenshotsDir, @@ -569,15 +568,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.screenshotsDir, "/some/dir"); assert.equal(config.browsers.b2.screenshotsDir, "/some/dir"); }); - it("should override screenshotsDir option per browser", () => { + it("should override screenshotsDir option per browser", async () => { const screenshotsDir = "/some/dir"; const readConfig = { screenshotsDir, @@ -587,21 +586,21 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.screenshotsDir, "/some/dir"); assert.equal(config.browsers.b2.screenshotsDir, "/screens"); }); - it("should fallback default value to hermione/screens, if it exists and default dir not exists", () => { + it("should fallback default value to hermione/screens, if it exists and default dir not exists", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); sandbox .stub(fs, "existsSync") .withArgs("hermione/screens") @@ -609,19 +608,19 @@ describe("config browser-options", () => { .withArgs("testplane/screens") .returns(false); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.screenshotsDir, "hermione/screens"); assert.equal(config.browsers.b1.screenshotsDir, "hermione/screens"); }); - it("should use default testplane/screens if both hermione/screens and testplane/screens exists", () => { + it("should use default testplane/screens if both hermione/screens and testplane/screens exists", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); sandbox .stub(fs, "existsSync") .withArgs("hermione/screens") @@ -629,19 +628,19 @@ describe("config browser-options", () => { .withArgs("testplane/screens") .returns(true); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.screenshotsDir, "testplane/screens"); assert.equal(config.browsers.b1.screenshotsDir, "testplane/screens"); }); - it("should not fallback default value to hermione/screens, if not exists", () => { + it("should not fallback default value to hermione/screens, if not exists", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); sandbox .stub(fs, "existsSync") .withArgs("hermione/screens") @@ -649,20 +648,20 @@ describe("config browser-options", () => { .withArgs("testplane/screens") .returns(false); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.screenshotsDir, "testplane/screens"); assert.equal(config.browsers.b1.screenshotsDir, "testplane/screens"); }); - it("should not fallback value to hermione/screens, if defined", () => { + it("should not fallback value to hermione/screens, if defined", async () => { const readConfig = { screenshotsDir: "some/dir", browsers: { b1: mkBrowser_({ screenshotsDir: "another/dir" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); sandbox .stub(fs, "existsSync") .withArgs("hermione/screens") @@ -670,54 +669,54 @@ describe("config browser-options", () => { .withArgs("testplane/screens") .returns(false); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.screenshotsDir, "some/dir"); assert.equal(config.browsers.b1.screenshotsDir, "another/dir"); }); }); - ["sessionsPerBrowser", "waitTimeout"].forEach(option => { + ["sessionsPerBrowser", "waitTimeout"].forEach(async option => { describe(`${option}`, () => { describe(`should throw error if ${option}`, () => { - it("is not a number", () => { + it("is not a number", async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: "10" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a positive integer`); + await assert.isRejected(createConfig(), `"${option}" must be a positive integer`); }); - it("is negative number", () => { + it("is negative number", async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: -5 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a positive integer`); + await assert.isRejected(createConfig(), `"${option}" must be a positive integer`); }); - it("is float number", () => { + it("is float number", async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: 15.5 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a positive integer`); + await assert.isRejected(createConfig(), `"${option}" must be a positive integer`); }); }); - it(`should set ${option} to all browsers`, () => { + it(`should set ${option} to all browsers`, async () => { const readConfig = { [option]: 666, browsers: { @@ -726,15 +725,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[option], 666); assert.equal(config.browsers.b2[option], 666); }); - it(`should override ${option} option`, () => { + it(`should override ${option} option`, async () => { const readConfig = { [option]: 666, browsers: { @@ -743,9 +742,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[option], 666); assert.equal(config.browsers.b2[option], 13); @@ -755,44 +754,44 @@ describe("config browser-options", () => { describe("testsPerSession", () => { describe('should throw error if "testsPerSession"', () => { - it("is not a number", () => { + it("is not a number", async () => { const readConfig = { browsers: { b1: mkBrowser_({ testsPerSession: "10" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"testsPerSession" must be a positive integer or Infinity'); + await assert.isRejected(createConfig(), '"testsPerSession" must be a positive integer or Infinity'); }); - it("is a negative number", () => { + it("is a negative number", async () => { const readConfig = { browsers: { b1: mkBrowser_({ testsPerSession: -5 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"testsPerSession" must be a positive integer or Infinity'); + await assert.isRejected(createConfig(), '"testsPerSession" must be a positive integer or Infinity'); }); - it("is a float number", () => { + it("is a float number", async () => { const readConfig = { browsers: { b1: mkBrowser_({ testsPerSession: 15.5 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"testsPerSession" must be a positive integer or Infinity'); + await assert.isRejected(createConfig(), '"testsPerSession" must be a positive integer or Infinity'); }); }); - it('should set "testsPerSession" to all browsers', () => { + it('should set "testsPerSession" to all browsers', async () => { const readConfig = { testsPerSession: 666, browsers: { @@ -801,15 +800,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.testsPerSession, 666); assert.equal(config.browsers.b2.testsPerSession, 666); }); - it('should override "testsPerSession option"', () => { + it('should override "testsPerSession option"', async () => { const readConfig = { testsPerSession: 666, browsers: { @@ -818,9 +817,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.testsPerSession, 666); assert.equal(config.browsers.b2.testsPerSession, 13); @@ -828,31 +827,31 @@ describe("config browser-options", () => { }); function testNonNegativeIntegerOption(option) { - it(`should throw error if ${option} is not a number`, () => { + it(`should throw error if ${option} is not a number`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: "100500" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a non-negative integer`); + await assert.isRejected(createConfig(), `"${option}" must be a non-negative integer`); }); - it(`should throw error if ${option} is negative`, () => { + it(`should throw error if ${option} is negative`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: -7 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a non-negative integer`); + await assert.isRejected(createConfig(), `"${option}" must be a non-negative integer`); }); - it(`should set ${option} option to all browsers`, () => { + it(`should set ${option} option to all browsers`, async () => { const readConfig = { [option]: 100500, browsers: { @@ -861,15 +860,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[option], 100500); assert.equal(config.browsers.b2[option], 100500); }); - it(`should override ${option} option`, () => { + it(`should override ${option} option`, async () => { const readConfig = { [option]: 100500, browsers: { @@ -878,9 +877,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[option], 100500); assert.equal(config.browsers.b2[option], 500100); @@ -894,16 +893,16 @@ describe("config browser-options", () => { function testOptionalNonNegativeIntegerOption(option) { testNonNegativeIntegerOption(option); - it(`should does not throw an error if ${option} is null`, () => { + it(`should does not throw an error if ${option} is null`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: null }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(createConfig); + await assert.isFulfilled(createConfig()); }); } @@ -917,42 +916,42 @@ describe("config browser-options", () => { ].forEach(option => describe(option, () => testOptionalNonNegativeIntegerOption(option))); describe("meta", () => { - it('should throw error if "meta" is not a object', () => { + it('should throw error if "meta" is not a object', async () => { const readConfig = { browsers: { b1: mkBrowser_({ meta: "meta-string" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"meta" must be an object'); + await assert.isRejected(createConfig(), '"meta" must be an object'); }); - it("should set null by default", () => { + it("should set null by default", async () => { const readConfig = { browsers: { b1: mkBrowser_({}), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.meta, null); }); - it("should set provided value", () => { + it("should set provided value", async () => { const readConfig = { browsers: { b1: mkBrowser_({ meta: { k1: "v1", k2: "v2" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.meta, { k1: "v1", k2: "v2" }); }); @@ -960,96 +959,93 @@ describe("config browser-options", () => { describe("windowSize", () => { describe('should throw error if "windowSize" is', () => { - it("not object, string or null", () => { + it("not object, string or null", async () => { const readConfig = { browsers: { b1: mkBrowser_({ windowSize: 1 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"windowSize" must be string, object or null'); + await assert.isRejected(createConfig(), '"windowSize" must be string, object or null'); }); - it('object without "width" or "height" keys', () => { + it('object without "width" or "height" keys', async () => { const readConfig = { browsers: { b1: mkBrowser_({ windowSize: { width: 1 } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), '"windowSize" must be an object with "width" and "height" keys', ); }); - it('object with "width" or "height" keys that are not numbers', () => { + it('object with "width" or "height" keys that are not numbers', async () => { const readConfig = { browsers: { b1: mkBrowser_({ windowSize: { width: 1, height: "2" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), '"windowSize" must be an object with "width" and "height" keys', ); }); - it("string with wrong pattern", () => { + it("string with wrong pattern", async () => { const readConfig = { browsers: { b1: mkBrowser_({ windowSize: "some_size" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), '"windowSize" should have form of x (i.e. 1600x1200)', ); }); }); - it('should be "null" by default', () => { + it('should be "null" by default', async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.windowSize, null); }); - it("should accept string value", () => { + it("should accept string value", async () => { const readConfig = { browsers: { b1: mkBrowser_({ windowSize: "1x2" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.windowSize, { width: 1, height: 2 }); }); - it('should pass object with "width" and "height" keys as is', () => { + it('should pass object with "width" and "height" keys as is', async () => { const size = { width: 1, height: 2, check: true }; const readConfig = { browsers: { @@ -1057,14 +1053,14 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.windowSize, size); }); - it("should set option to all browsers", () => { + it("should set option to all browsers", async () => { const readConfig = { windowSize: "1x2", browsers: { @@ -1073,15 +1069,15 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.windowSize, { width: 1, height: 2 }); assert.deepEqual(config.browsers.b2.windowSize, { width: 1, height: 2 }); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { windowSize: "1x2", browsers: { @@ -1090,70 +1086,70 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.windowSize, { width: 1, height: 2 }); assert.deepEqual(config.browsers.b2.windowSize, { width: 5, height: 5 }); }); }); - ["tolerance", "antialiasingTolerance"].forEach(option => { + ["tolerance", "antialiasingTolerance"].forEach(async option => { describe(`${option}`, () => { describe("should throw an error", () => { - it("if value is not number", () => { + it("if value is not number", async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: [] }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a number`); + await assert.isRejected(createConfig(), `"${option}" must be a number`); }); - it("if value is negative", () => { + it("if value is negative", async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: -1 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be non-negative`); + await assert.isRejected(createConfig(), `"${option}" must be non-negative`); }); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config[option], defaults[option]); }); - it("should does not throw if value is 0", () => { + it("should does not throw if value is 0", async () => { const readConfig = { browsers: { b1: mkBrowser_({ [option]: 0 }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(createConfig); + await assert.isFulfilled(createConfig()); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { [option]: 100, browsers: { @@ -1162,9 +1158,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1[option], 100); assert.deepEqual(config.browsers.b2[option], 200); @@ -1173,123 +1169,123 @@ describe("config browser-options", () => { }); describe("buildDiffOpts", () => { - it('should throw error if "buildDiffOpts" is not a object', () => { + it('should throw error if "buildDiffOpts" is not a object', async () => { const readConfig = { browsers: { b1: mkBrowser_({ buildDiffOpts: "some-string" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"buildDiffOpts" must be an object'); + await assert.isRejected(createConfig(), '"buildDiffOpts" must be an object'); }); - ["ignoreAntialiasing", "ignoreCaret"].forEach(option => { - it(`should set "${option}" to "true" by default`, () => { + ["ignoreAntialiasing", "ignoreCaret"].forEach(async option => { + it(`should set "${option}" to "true" by default`, async () => { const readConfig = { browsers: { b1: mkBrowser_({}), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.buildDiffOpts[option], true); }); }); - it("should set provided value", () => { + it("should set provided value", async () => { const readConfig = { browsers: { b1: mkBrowser_({ buildDiffOpts: { k1: "v1", k2: "v2" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.buildDiffOpts, { k1: "v1", k2: "v2" }); }); }); describe("assertViewOpts", () => { - it('should throw error if "assertViewOpts" is not an object', () => { + it('should throw error if "assertViewOpts" is not an object', async () => { const readConfig = { browsers: { b1: mkBrowser_({ assertViewOpts: "some-string" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"assertViewOpts" must be an object'); + await assert.isRejected(createConfig(), '"assertViewOpts" must be an object'); }); - ["ignoreElements", "captureElementFromTop", "allowViewportOverflow"].forEach(option => { - it(`should set "${option}" option to default value if it is not set in config`, () => { + ["ignoreElements", "captureElementFromTop", "allowViewportOverflow"].forEach(async option => { + it(`should set "${option}" option to default value if it is not set in config`, async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.assertViewOpts[option], defaults.assertViewOpts[option]); }); - it(`should overridde only "${option}" and use others from defaults`, () => { + it(`should overridde only "${option}" and use others from defaults`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ assertViewOpts: { [option]: 100500 } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.assertViewOpts, { ...defaults.assertViewOpts, [option]: 100500 }); }); }); - it("should set provided values and use others from defaults", () => { + it("should set provided values and use others from defaults", async () => { const readConfig = { browsers: { b1: mkBrowser_({ assertViewOpts: { k1: "v1", k2: "v2" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.assertViewOpts, { ...defaults.assertViewOpts, k1: "v1", k2: "v2" }); }); }); function testBooleanOption(option) { - it("should throw an error if value is not a boolean", () => { + it("should throw an error if value is not a boolean", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ [option]: "foo" })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a boolean`); + await assert.isRejected(createConfig(), `"${option}" must be a boolean`); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_()); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config[option], defaults[option]); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { [option]: false, browsers: { @@ -1298,9 +1294,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.isFalse(config.browsers.b1[option]); assert.isTrue(config.browsers.b2[option]); @@ -1318,7 +1314,7 @@ describe("config browser-options", () => { ].forEach(option => describe(option, () => testBooleanOption(option))); describe("isolation", () => { - it("should set to 'true' if browser support isolation", () => { + it("should set to 'true' if browser support isolation", async () => { const readConfig = { browsers: { b1: mkBrowser_({ @@ -1329,14 +1325,14 @@ describe("config browser-options", () => { }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.isTrue(config.browsers.b1.isolation); }); - it("should set to 'false' if browser doesn't support isolation", () => { + it("should set to 'false' if browser doesn't support isolation", async () => { const readConfig = { browsers: { b1: mkBrowser_({ @@ -1347,15 +1343,15 @@ describe("config browser-options", () => { }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.isFalse(config.browsers.b1.isolation); }); describe("should set to 'false' by user even if browser support isolation", () => { - it("in top level config", () => { + it("in top level config", async () => { const readConfig = { isolation: false, browsers: { @@ -1367,14 +1363,14 @@ describe("config browser-options", () => { }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.isFalse(config.browsers.b1.isolation); }); - it("in browser config", () => { + it("in browser config", async () => { const readConfig = { browsers: { b1: mkBrowser_({ @@ -1386,9 +1382,9 @@ describe("config browser-options", () => { }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.isFalse(config.browsers.b1.isolation); }); @@ -1396,24 +1392,24 @@ describe("config browser-options", () => { }); describe("saveHistoryMode", () => { - it("should throw an error if value is not available", () => { + it("should throw an error if value is not available", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ saveHistoryMode: "foo" })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"saveHistoryMode" must be one of`); + await assert.isRejected(createConfig(), `"saveHistoryMode" must be one of`); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_()); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.saveHistory, defaults.saveHistory); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { saveHistoryMode: "none", browsers: { @@ -1422,21 +1418,21 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.saveHistoryMode, SAVE_HISTORY_MODE.NONE); assert.equal(config.browsers.b2.saveHistoryMode, SAVE_HISTORY_MODE.ALL); }); - [SAVE_HISTORY_MODE.NONE, SAVE_HISTORY_MODE.ONLY_FAILED, SAVE_HISTORY_MODE.ALL].forEach(value => { - it(`should set option for browser to "${value}"`, () => { + [SAVE_HISTORY_MODE.NONE, SAVE_HISTORY_MODE.ONLY_FAILED, SAVE_HISTORY_MODE.ALL].forEach(async value => { + it(`should set option for browser to "${value}"`, async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ saveHistoryMode: value })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.saveHistoryMode, value); }); @@ -1444,44 +1440,44 @@ describe("config browser-options", () => { }); describe("takeScreenshotOnFails", () => { - it("should throw an error if value is not an object", () => { - Config.read.returns({ takeScreenshotOnFails: "foo" }); + it("should throw an error if value is not an object", async () => { + Config.read.resolves({ takeScreenshotOnFails: "foo" }); - assert.throws(() => createConfig(), Error, '"takeScreenshotOnFails" must be an object'); + await assert.isRejected(createConfig(), '"takeScreenshotOnFails" must be an object'); }); - it("should throw an error if object value contains unknown fields", () => { - Config.read.returns({ + it("should throw an error if object value contains unknown fields", async () => { + Config.read.resolves({ takeScreenshotOnFails: { foo: "bar", bar: "foo", }, }); - assert.throws(() => createConfig(), Error, '"takeScreenshotOnFails" contains unknown properties: foo,bar.'); + await assert.isRejected(createConfig(), '"takeScreenshotOnFails" contains unknown properties: foo,bar.'); }); - it("should set a default value if it is not set in config", () => { - Config.read.returns({ + it("should set a default value if it is not set in config", async () => { + Config.read.resolves({ browsers: { b1: mkBrowser_(), }, }); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.takeScreenshotOnFails, defaults.takeScreenshotOnFails); assert.deepEqual(config.browsers.b1.takeScreenshotOnFails, defaults.takeScreenshotOnFails); }); - it("should extend object value with missing fields", () => { - Config.read.returns({ + it("should extend object value with missing fields", async () => { + Config.read.resolves({ takeScreenshotOnFails: { testFail: true, }, }); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.takeScreenshotOnFails, { testFail: true, @@ -1489,7 +1485,7 @@ describe("config browser-options", () => { }); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { takeScreenshotOnFails: { testFail: false, @@ -1504,9 +1500,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.takeScreenshotOnFails, { testFail: false, @@ -1520,61 +1516,61 @@ describe("config browser-options", () => { }); describe("screenshotMode", () => { - it("should throw an error if option is not a string", () => { + it("should throw an error if option is not a string", async () => { const readConfig = { browsers: { b1: mkBrowser_({ screenshotMode: { not: "string" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /"screenshotMode" must be a string/); + await assert.isRejected(createConfig(), /"screenshotMode" must be a string/); }); - it('should throw an error if option value is not "fullpage", "viewport" or "auto"', () => { + it('should throw an error if option value is not "fullpage", "viewport" or "auto"', async () => { const readConfig = { browsers: { b1: mkBrowser_({ screenshotMode: "foo bar" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /"screenshotMode" must be one of: fullpage, viewport, auto/); + await assert.isRejected(createConfig(), /"screenshotMode" must be one of: fullpage, viewport, auto/); }); describe("should not throw an error if option value is", () => { - ["fullpage", "viewport", "auto"].forEach(value => { - it(`${value}`, () => { + ["fullpage", "viewport", "auto"].forEach(async value => { + it(`${value}`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ screenshotMode: value }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.screenshotMode, defaults.screenshotMode); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { screenshotMode: "fullpage", browsers: { @@ -1583,16 +1579,16 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.screenshotMode, "fullpage"); assert.equal(config.browsers.b2.screenshotMode, "viewport"); }); describe("on android browser", () => { - it("should set mode to 'viewport' by default", () => { + it("should set mode to 'viewport' by default", async () => { const readConfig = { browsers: { b1: mkBrowser_({ @@ -1603,14 +1599,14 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.screenshotMode, "viewport"); }); - it("should preserve manually set mode", () => { + it("should preserve manually set mode", async () => { const readConfig = { browsers: { b1: mkBrowser_({ @@ -1622,9 +1618,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.screenshotMode, "fullpage"); }); @@ -1632,65 +1628,61 @@ describe("config browser-options", () => { }); describe("takeScreenshotOnFailsMode", () => { - it("should throw an error if option is not a string", () => { + it("should throw an error if option is not a string", async () => { const readConfig = { browsers: { b1: mkBrowser_({ takeScreenshotOnFailsMode: { not: "string" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /"takeScreenshotOnFailsMode" must be a string/); + await assert.isRejected(createConfig(), /"takeScreenshotOnFailsMode" must be a string/); }); - it('should throw an error if option value is not "fullpage" or "viewport"', () => { + it('should throw an error if option value is not "fullpage" or "viewport"', async () => { const readConfig = { browsers: { b1: mkBrowser_({ takeScreenshotOnFailsMode: "foo bar" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, - /"takeScreenshotOnFailsMode" must be one of: fullpage, viewport/, - ); + await assert.isRejected(createConfig(), /"takeScreenshotOnFailsMode" must be one of: fullpage, viewport/); }); describe("should not throw an error if option value is", () => { - ["fullpage", "viewport"].forEach(value => { - it(`${value}`, () => { + ["fullpage", "viewport"].forEach(async value => { + it(`${value}`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ takeScreenshotOnFailsMode: value }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.takeScreenshotOnFailsMode, defaults.takeScreenshotOnFailsMode); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { takeScreenshotOnFailsMode: "fullpage", browsers: { @@ -1699,9 +1691,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.takeScreenshotOnFailsMode, "fullpage"); assert.equal(config.browsers.b2.takeScreenshotOnFailsMode, "viewport"); @@ -1709,61 +1701,61 @@ describe("config browser-options", () => { }); describe("orientation", () => { - it("should throw an error if option value is not string", () => { + it("should throw an error if option value is not string", async () => { const readConfig = { browsers: { b1: mkBrowser_({ orientation: { not: "string" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /"orientation" must be a string/); + await assert.isRejected(createConfig(), /"orientation" must be a string/); }); - it('should throw an error if option value is not "landscape" or "portrait"', () => { + it('should throw an error if option value is not "landscape" or "portrait"', async () => { const readConfig = { browsers: { b1: mkBrowser_({ orientation: "foo bar" }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, /"orientation" must be "landscape" or "portrait"/); + await assert.isRejected(createConfig(), /"orientation" must be "landscape" or "portrait"/); }); describe("should not throw an error if option value is", () => { - ["landscape", "portrait"].forEach(value => { - it(`${value}`, () => { + ["landscape", "portrait"].forEach(async value => { + it(`${value}`, async () => { const readConfig = { browsers: { b1: mkBrowser_({ orientation: value }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = { browsers: { b1: mkBrowser_(), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.orientation, defaults.orientation); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { orientation: "landscape", browsers: { @@ -1772,35 +1764,35 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1.orientation, "landscape"); assert.equal(config.browsers.b2.orientation, "portrait"); }); }); - ["outputDir", "user", "key", "region"].forEach(option => { + ["outputDir", "user", "key", "region"].forEach(async option => { describe(option, () => { - it("should throw an error if value is not a null or string", () => { + it("should throw an error if value is not a null or string", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ [option]: { some: "object" } })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a string`); + await assert.isRejected(createConfig(), `"${option}" must be a string`); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_()); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config[option], defaults[option]); }); - it("should override option for browser", () => { + it("should override option for browser", async () => { const readConfig = { [option]: "init-string", browsers: { @@ -1809,9 +1801,9 @@ describe("config browser-options", () => { }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[option], "init-string"); assert.equal(config.browsers.b2[option], "new-string"); @@ -1819,56 +1811,56 @@ describe("config browser-options", () => { }); }); - ["agent", "headers"].forEach(option => { + ["agent", "headers"].forEach(async option => { describe(option, () => { - it(`should throw error if "${option}" is not an object`, () => { + it(`should throw error if "${option}" is not an object`, async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ [option]: "string" })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be an object`); + await assert.isRejected(createConfig(), `"${option}" must be an object`); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_()); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config[option], defaults[option]); }); - it("should set provided value", () => { + it("should set provided value", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ [option]: { k1: "v1", k2: "v2" } })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1[option], { k1: "v1", k2: "v2" }); }); }); }); - ["transformRequest", "transformResponse"].forEach(option => { + ["transformRequest", "transformResponse"].forEach(async option => { describe(option, () => { - it(`should throw error if ${option} is not a null or function`, () => { + it(`should throw error if ${option} is not a null or function`, async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ [option]: "string" })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"${option}" must be a function`); + await assert.isRejected(createConfig(), `"${option}" must be a function`); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_()); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config[option], defaults[option]); }); - it(`should override ${option} option`, () => { + it(`should override ${option} option`, async () => { const optionFn = () => {}; const newOptionFn = () => {}; @@ -1879,9 +1871,9 @@ describe("config browser-options", () => { b2: mkBrowser_({ [option]: newOptionFn }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.browsers.b1[option], optionFn); assert.equal(config.browsers.b2[option], newOptionFn); @@ -1890,24 +1882,24 @@ describe("config browser-options", () => { }); describe("strictSSL", () => { - it(`should throw error if option is not a null or boolean`, () => { + it(`should throw error if option is not a null or boolean`, async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ strictSSL: "string" })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, `"strictSSL" must be a boolean`); + await assert.isRejected(createConfig(), `"strictSSL" must be a boolean`); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_()); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.strictSSL, defaults.strictSSL); }); - it(`should override "strictSSL" option`, () => { + it(`should override "strictSSL" option`, async () => { const readConfig = { strictSSL: false, browsers: { @@ -1915,9 +1907,9 @@ describe("config browser-options", () => { b2: mkBrowser_({ strictSSL: true }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.isFalse(config.browsers.b1.strictSSL); assert.isTrue(config.browsers.b2.strictSSL); @@ -1925,36 +1917,35 @@ describe("config browser-options", () => { }); describe("headless", () => { - it("should throw error if option is not a null, boolean or string", () => { + it("should throw error if option is not a null, boolean or string", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ headless: { a: 1 } })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), '"headless" option should be boolean or string with "new" or "old" values', ); }); - it("should throw error if option is string with invalid values", () => { + it("should throw error if option is string with invalid values", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_({ headless: "some" })); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(() => createConfig(), Error, '"headless" option should be "new" or "old", but got "some"'); + await assert.isRejected(createConfig(), '"headless" option should be "new" or "old", but got "some"'); }); - it("should set a default value if it is not set in config", () => { + it("should set a default value if it is not set in config", async () => { const readConfig = _.set({}, "browsers.b1", mkBrowser_()); - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.headless, defaults.headless); }); - it("should override 'headless' option", () => { + it("should override 'headless' option", async () => { const readConfig = { headless: false, browsers: { @@ -1962,9 +1953,9 @@ describe("config browser-options", () => { b2: mkBrowser_({ headless: true }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.isFalse(config.browsers.b1.headless); assert.isTrue(config.browsers.b2.headless); @@ -1972,53 +1963,53 @@ describe("config browser-options", () => { }); describe("timeTravel", () => { - it("should set timeTravel to off by default", () => { + it("should set timeTravel to off by default", async () => { const readConfig = {}; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.timeTravel, { mode: "off" }); }); - it("should throw if timeTravel is not a valid string", () => { + it("should throw if timeTravel is not a valid string", async () => { const readConfig = { timeTravel: "something" }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(createConfig, /TimeTravel mode must be one of the following strings/); + await assert.isRejected(createConfig(), /TimeTravel mode must be one of the following strings/); }); - it("should parse string into object", () => { + it("should parse string into object", async () => { const readConfig = { timeTravel: TimeTravelMode.RetriesOnly }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.timeTravel, { mode: TimeTravelMode.RetriesOnly }); }); - it("should throw if timeTravel.mode is invalid", () => { + it("should throw if timeTravel.mode is invalid", async () => { const readConfig = { timeTravel: { mode: "something" } }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - assert.throws(createConfig, /TimeTravel mode must be one of the following strings/); + await assert.isRejected(createConfig(), /TimeTravel mode must be one of the following strings/); }); - it("should preserve correct object", () => { + it("should preserve correct object", async () => { const readConfig = { timeTravel: { mode: TimeTravelMode.RetriesOnly } }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.timeTravel, { mode: TimeTravelMode.RetriesOnly }); }); - it("should work correctly with browser overrides", () => { + it("should work correctly with browser overrides", async () => { const readConfig = { timeTravel: TimeTravelMode.RetriesOnly, browsers: { @@ -2026,9 +2017,9 @@ describe("config browser-options", () => { b2: mkBrowser_({ timeTravel: { mode: "off" } }), }, }; - Config.read.returns(readConfig); + Config.read.resolves(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.browsers.b1.timeTravel, { mode: TimeTravelMode.RetriesOnly }); assert.deepEqual(config.browsers.b2.timeTravel, { mode: TimeTravelMode.Off }); diff --git a/test/src/config/index.js b/test/src/config/index.js index 3f0951850..a1adcc1fd 100644 --- a/test/src/config/index.js +++ b/test/src/config/index.js @@ -10,7 +10,7 @@ describe("config", () => { let parseOptions; - const initConfig = opts => { + const initConfig = async opts => { opts = opts || {}; parseOptions = sandbox.stub().returns(opts.configParserReturns); const config = Object.prototype.hasOwnProperty.call(opts, "config") ? opts.config : "some-config-path"; @@ -31,20 +31,20 @@ describe("config", () => { afterEach(() => sandbox.restore()); describe("constructor", () => { - it("should parse options", () => { - initConfig({ configParserReturns: {} }); + it("should parse options", async () => { + await initConfig({ configParserReturns: {} }); assert.calledOnce(parseOptions); }); - it("should parse config from file", () => { - initConfig({ configParserReturns: {}, requireConfigReturns: "some-options" }); + it("should parse config from file", async () => { + await initConfig({ configParserReturns: {}, requireConfigReturns: "some-options" }); assert.calledWithMatch(parseOptions, { options: "some-options", env: process.env, argv: process.argv }); }); - it("should support default export", () => { - initConfig({ + it("should support default export", async () => { + await initConfig({ configParserReturns: {}, requireConfigReturns: { __esModule: true, default: { foo: "bar" } }, }); @@ -52,8 +52,47 @@ describe("config", () => { assert.calledWithMatch(parseOptions, { options: { foo: "bar" }, env: process.env, argv: process.argv }); }); - it("should parse config from object", () => { - initConfig({ configParserReturns: {}, config: { someOption: "some-value" } }); + it("should resolve async config function export", async () => { + await initConfig({ + configParserReturns: {}, + requireConfigReturns: async () => ({ async: "value" }), + }); + + assert.calledWithMatch(parseOptions, { + options: { async: "value" }, + env: process.env, + argv: process.argv, + }); + }); + + it("should resolve sync config function export", async () => { + await initConfig({ + configParserReturns: {}, + requireConfigReturns: () => ({ sync: "value" }), + }); + + assert.calledWithMatch(parseOptions, { + options: { sync: "value" }, + env: process.env, + argv: process.argv, + }); + }); + + it("should resolve config function passed directly", async () => { + await initConfig({ + configParserReturns: {}, + config: async () => ({ direct: "value" }), + }); + + assert.calledWithMatch(parseOptions, { + options: { direct: "value" }, + env: process.env, + argv: process.argv, + }); + }); + + it("should parse config from object", async () => { + await initConfig({ configParserReturns: {}, config: { someOption: "some-value" } }); assert.calledWithMatch(parseOptions, { options: { someOption: "some-value" }, @@ -62,18 +101,18 @@ describe("config", () => { }); }); - it("should create config", () => { - assert.include(initConfig({ configParserReturns: { some: "option" } }), { some: "option" }); + it("should create config", async () => { + assert.include(await initConfig({ configParserReturns: { some: "option" } }), { some: "option" }); }); - it("should extend config with a config path", () => { - assert.include(initConfig({ configParserReturns: {}, config: "config-path" }), { + it("should extend config with a config path", async () => { + assert.include(await initConfig({ configParserReturns: {}, config: "config-path" }), { configPath: "config-path", }); }); - it('should wrap browser config with "BrowserConfig" instance', () => { - const config = initConfig({ + it('should wrap browser config with "BrowserConfig" instance', async () => { + const config = await initConfig({ configParserReturns: { browsers: { bro1: {}, @@ -84,15 +123,15 @@ describe("config", () => { assert.instanceOf(config.forBrowser("bro1"), BrowserConfig); }); - it("should extend browser config with its id", () => { - const config = initConfig({ configParserReturns: { browsers: { bro: { some: "option" } } } }); + it("should extend browser config with its id", async () => { + const config = await initConfig({ configParserReturns: { browsers: { bro: { some: "option" } } } }); assert.include(config.forBrowser("bro"), { id: "bro" }); }); for (const configPath of defaults.configPaths) { - it(`should look for ${configPath} by default`, () => { - const config = initConfig({ + it(`should look for ${configPath} by default`, async () => { + const config = await initConfig({ config: null, configParserReturns: { system: { fileExtensions: [] }, @@ -108,24 +147,24 @@ describe("config", () => { }); describe("forBrowser", () => { - it("should get config for a browser", () => { - const config = initConfig({ configParserReturns: { browsers: { bro: { some: "option" } } } }); + it("should get config for a browser", async () => { + const config = await initConfig({ configParserReturns: { browsers: { bro: { some: "option" } } } }); assert.include(config.forBrowser("bro"), { some: "option" }); }); }); describe("getBrowserIds", () => { - it("should get browser ids", () => { - const config = initConfig({ configParserReturns: { browsers: { bro1: {}, bro2: {} } } }); + it("should get browser ids", async () => { + const config = await initConfig({ configParserReturns: { browsers: { bro1: {}, bro2: {} } } }); assert.deepEqual(config.getBrowserIds(), ["bro1", "bro2"]); }); }); describe("serialize", () => { - it("should delegate browsers serialization to browser config", () => { - const config = initConfig({ + it("should delegate browsers serialization to browser config", async () => { + const config = await initConfig({ configParserReturns: { browsers: { bro: {}, @@ -147,16 +186,16 @@ describe("config", () => { }); describe("mergeWith", () => { - it("should deeply merge config with another one", () => { - const config = initConfig({ configParserReturns: { some: { deep: { option: "foo" } } } }); + it("should deeply merge config with another one", async () => { + const config = await initConfig({ configParserReturns: { some: { deep: { option: "foo" } } } }); config.mergeWith({ some: { deep: { option: "bar" } } }); assert.deepInclude(config, { some: { deep: { option: "bar" } } }); }); - it("should not merge values of different types", () => { - const config = initConfig({ configParserReturns: { option: 100500 } }); + it("should not merge values of different types", async () => { + const config = await initConfig({ configParserReturns: { option: 100500 } }); config.mergeWith({ option: "100500" }); diff --git a/test/src/config/options.js b/test/src/config/options.js index adcf42e15..8c1736b6b 100644 --- a/test/src/config/options.js +++ b/test/src/config/options.js @@ -20,25 +20,25 @@ describe("config options", () => { describe("system", () => { describe("debug", () => { - it("should throw error if debug is not a boolean", () => { + it("should throw error if debug is not a boolean", async () => { const readConfig = _.set({}, "system.debug", "String"); Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"debug" must be a boolean'); + await assert.isRejected(createConfig(), '"debug" must be a boolean'); }); - it("should set default debug option if it does not set in config file", () => { - const config = createConfig(); + it("should set default debug option if it does not set in config file", async () => { + const config = await createConfig(); assert.equal(config.system.debug, defaults.debug); }); - it("should override debug option", () => { + it("should override debug option", async () => { const readConfig = _.set({}, "system.debug", true); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.system.debug, true); }); @@ -47,32 +47,32 @@ describe("config options", () => { [ { optionName: "mochaOpts", subOptionName: "slow" }, { optionName: "expectOpts", subOptionName: "wait" }, - ].forEach(({ optionName, subOptionName }) => { + ].forEach(async ({ optionName, subOptionName }) => { describe(`${optionName}`, () => { - it("should throw error if option is not a null or object", () => { + it("should throw error if option is not a null or object", async () => { const readConfig = _.set({}, `system.${optionName}`, ["Array"]); Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, `"${optionName}" must be an object`); + await assert.isRejected(createConfig(), `"${optionName}" must be an object`); }); - it("should set default option if it does not set in config file", () => { - const config = createConfig(); + it("should set default option if it does not set in config file", async () => { + const config = await createConfig(); assert.deepEqual(config.system[optionName], defaults[optionName]); }); - it("should override option", () => { + it("should override option", async () => { const readConfig = _.set({}, `system.${optionName}.${subOptionName}`, 100500); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.system[optionName][subOptionName], 100500); }); - it("should parse option from environment", () => { + it("should parse option from environment", async () => { const result = parse_({ options: { system: { [optionName]: {} } }, // prettier-ignore @@ -82,7 +82,7 @@ describe("config options", () => { assert.deepEqual(result.system[optionName], { some: "opts" }); }); - it("should prefer existing environment option with testplane_ prefix", () => { + it("should prefer existing environment option with testplane_ prefix", async () => { const result = parse_({ options: { system: { [optionName]: {} } }, env: { @@ -94,7 +94,7 @@ describe("config options", () => { assert.deepEqual(result.system[optionName], { baz: "qux" }); }); - it("should parse option from cli", () => { + it("should parse option from cli", async () => { const result = parse_({ options: { system: { [optionName]: {} } }, argv: [`--system-${_.kebabCase(optionName)}`, '{"some": "opts"}'], @@ -106,47 +106,47 @@ describe("config options", () => { }); describe("ctx", () => { - it("should be empty by default", () => { - const config = createConfig(); + it("should be empty by default", async () => { + const config = await createConfig(); assert.deepEqual(config.system.ctx, {}); }); - it("should override ctx option", () => { + it("should override ctx option", async () => { const readConfig = _.set({}, "system.ctx", { some: "ctx" }); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.system.ctx, { some: "ctx" }); }); }); describe("patternsOnReject", () => { - it("should be empty by default", () => { - const config = createConfig(); + it("should be empty by default", async () => { + const config = await createConfig(); assert.deepEqual(config.system.patternsOnReject, []); }); - it('should throw error if "patternsOnReject" is not an array', () => { + it('should throw error if "patternsOnReject" is not an array', async () => { const readConfig = _.set({}, "system.patternsOnReject", {}); Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"patternsOnReject" must be an array'); + await assert.isRejected(createConfig(), '"patternsOnReject" must be an array'); }); - it('should override "patternsOnReject" option', () => { + it('should override "patternsOnReject" option', async () => { const readConfig = _.set({}, "system.patternsOnReject", ["some-pattern"]); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.system.patternsOnReject, ["some-pattern"]); }); - it('should parse "patternsOnReject" option from environment', () => { + it('should parse "patternsOnReject" option from environment', async () => { const result = parse_({ options: { system: { patternsOnReject: [] } }, // prettier-ignore @@ -156,7 +156,7 @@ describe("config options", () => { assert.deepEqual(result.system.patternsOnReject, ["some-pattern"]); }); - it('should parse "patternsOnReject" options from cli', () => { + it('should parse "patternsOnReject" options from cli', async () => { const result = parse_({ options: { system: { patternsOnReject: [] } }, argv: ["--system-patterns-on-reject", '["some-pattern"]'], @@ -167,119 +167,119 @@ describe("config options", () => { }); describe("workers", () => { - it("should throw in case of not positive integer", () => { - [0, -1, "string", { foo: "bar" }].forEach(workers => { + it("should throw in case of not positive integer", async () => { + [0, -1, "string", { foo: "bar" }].forEach(async workers => { Config.read.returns({ system: { workers } }); - assert.throws(() => createConfig(), '"workers" must be a positive integer'); + await assert.isRejected(createConfig(), '"workers" must be a positive integer'); }); }); - it("should equal one by default", () => { - const config = createConfig(); + it("should equal one by default", async () => { + const config = await createConfig(); assert.equal(config.system.workers, 1); }); - it("should be overridden from a config", () => { + it("should be overridden from a config", async () => { Config.read.returns({ system: { workers: 100500 } }); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.system.workers, 100500); }); }); describe("diffColor", () => { - it("should be #ff00ff by default", () => { - const config = createConfig(); + it("should be #ff00ff by default", async () => { + const config = await createConfig(); assert.deepEqual(config.system.diffColor, "#ff00ff"); }); - it("should override diffColor option", () => { + it("should override diffColor option", async () => { const readConfig = _.set({}, "system.diffColor", "#f5f5f5"); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.system.diffColor, "#f5f5f5"); }); - it("should throw an error if option is not a string", () => { + it("should throw an error if option is not a string", async () => { const readConfig = _.set({}, "system.diffColor", 1); Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"diffColor" must be a string'); + await assert.isRejected(createConfig(), '"diffColor" must be a string'); }); - it("should throw an error if option is not a hexadecimal value", () => { + it("should throw an error if option is not a hexadecimal value", async () => { const readConfig = _.set({}, "system.diffColor", "#gggggg"); Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, /"diffColor" must be a hexadecimal/); + await assert.isRejected(createConfig(), /"diffColor" must be a hexadecimal/); }); }); describe("tempDir", () => { - it("should set default option if it does not set in config file", () => { - const config = createConfig(); + it("should set default option if it does not set in config file", async () => { + const config = await createConfig(); assert.deepEqual(config.system.tempDir, defaults.tempDir); }); - it("should override tempDir option", () => { + it("should override tempDir option", async () => { const readConfig = _.set({}, "system.tempDir", "/def/path"); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.system.tempDir, "/def/path"); }); - it("should throw an error if option is not a string", () => { + it("should throw an error if option is not a string", async () => { const readConfig = _.set({}, "system.tempDir", 1); Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"tempDir" must be a string'); + await assert.isRejected(createConfig(), '"tempDir" must be a string'); }); }); describe("parallelLimit", () => { - it("should throw error in case of not positive integer", () => { - [0, -1, "10", 10.15, { foo: "bar" }].forEach(parallelLimit => { + it("should throw error in case of not positive integer", async () => { + [0, -1, "10", 10.15, { foo: "bar" }].forEach(async parallelLimit => { Config.read.returns({ system: { parallelLimit } }); - assert.throws(() => createConfig(), '"parallelLimit" must be a positive integer'); + await assert.isRejected(createConfig(), '"parallelLimit" must be a positive integer'); }); }); - it("should be able to pass value is Infinity", () => { + it("should be able to pass value is Infinity", async () => { Config.read.returns({ system: { parallelLimit: Infinity } }); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.system.parallelLimit, Infinity); }); - it("should set default parallelLimit option if it does not set in config file", () => { - const config = createConfig(); + it("should set default parallelLimit option if it does not set in config file", async () => { + const config = await createConfig(); assert.equal(config.system.parallelLimit, defaults.parallelLimit); }); - it("should be overridden from a config", () => { + it("should be overridden from a config", async () => { Config.read.returns({ system: { parallelLimit: 5 } }); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.system.parallelLimit, 5); }); - it("should parse option from environment", () => { + it("should parse option from environment", async () => { const result = parse_({ options: { system: { mochaOpts: {} } }, // prettier-ignore @@ -289,7 +289,7 @@ describe("config options", () => { assert.equal(result.system.parallelLimit, 10); }); - it("should parse option from cli", () => { + it("should parse option from cli", async () => { const result = parse_({ options: { system: { parallelLimit: 1 } }, argv: ["--system-parallel-limit", "15"], @@ -300,48 +300,45 @@ describe("config options", () => { }); describe("fileExtensions", () => { - it("should set default extension", () => { - const config = createConfig(); + it("should set default extension", async () => { + const config = await createConfig(); assert.deepEqual(config.system.fileExtensions, defaults.fileExtensions); }); describe('should throw error if "fileExtensions" option', () => { - it("is not an array", () => { + it("is not an array", async () => { const value = {}; const readConfig = _.set({}, "system.fileExtensions", value); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `"fileExtensions" must be an array of strings but got ${JSON.stringify(value)}`, ); }); - it("is not an array of strings", () => { + it("is not an array of strings", async () => { const value = ["string", 100500]; const readConfig = _.set({}, "system.fileExtensions", value); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `fileExtensions" must be an array of strings but got ${JSON.stringify(value)}`, ); }); - it("has strings that do not start with dot symbol", () => { + it("has strings that do not start with dot symbol", async () => { const value = [".foo", "bar"]; const readConfig = _.set({}, "system.fileExtensions", value); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `Each extension from "fileExtensions" must start with dot symbol but got ${JSON.stringify( value, )}`, @@ -349,84 +346,79 @@ describe("config options", () => { }); }); - it('should set "fileExtensions" option', () => { + it('should set "fileExtensions" option', async () => { const fileExtensions = [".foo", ".bar"]; const readConfig = _.set({}, "system.fileExtensions", fileExtensions); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.system.fileExtensions, fileExtensions); }); }); describe("testRunEnv", () => { - it("should set default test run environment", () => { - const config = createConfig(); + it("should set default test run environment", async () => { + const config = await createConfig(); assert.deepEqual(config.system.testRunEnv, defaults.testRunEnv); }); describe('should throw error if "testRunEnv" option', () => { - it("is not string or array", () => { + it("is not string or array", async () => { const value = 123; const readConfig = _.set({}, "system.testRunEnv", value); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `"testRunEnv" must be an array or string but got ${JSON.stringify(value)}`, ); }); - it(`is string but not "${NODEJS_TEST_RUN_ENV}" or "${BROWSER_TEST_RUN_ENV}"`, () => { + it(`is string but not "${NODEJS_TEST_RUN_ENV}" or "${BROWSER_TEST_RUN_ENV}"`, async () => { const readConfig = _.set({}, "system.testRunEnv", "foo"); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `"testRunEnv" specified as string must be "${NODEJS_TEST_RUN_ENV}" or "${BROWSER_TEST_RUN_ENV}" but got "foo"`, ); }); - it(`is array with "${NODEJS_TEST_RUN_ENV}" value`, () => { + it(`is array with "${NODEJS_TEST_RUN_ENV}" value`, async () => { const value = [NODEJS_TEST_RUN_ENV]; const readConfig = _.set({}, "system.testRunEnv", value); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `"testRunEnv" with "${NODEJS_TEST_RUN_ENV}" value must be specified as string but got ${JSON.stringify( value, )}`, ); }); - it(`is array with "${BROWSER_TEST_RUN_ENV}" but without options as second element`, () => { + it(`is array with "${BROWSER_TEST_RUN_ENV}" but without options as second element`, async () => { const value = [BROWSER_TEST_RUN_ENV]; const readConfig = _.set({}, "system.testRunEnv", value); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `"testRunEnv" specified as array must also contain options as second argument but got ${JSON.stringify( value, )}`, ); }); - it(`is array without "${BROWSER_TEST_RUN_ENV}" as first element`, () => { + it(`is array without "${BROWSER_TEST_RUN_ENV}" as first element`, async () => { const value = ["foo"]; const readConfig = _.set({}, "system.testRunEnv", value); Config.read.returns(readConfig); - assert.throws( - () => createConfig(), - Error, + await assert.isRejected( + createConfig(), `"testRunEnv" specified as array must be in format ["${BROWSER_TEST_RUN_ENV}", ] but got ${JSON.stringify( value, )}`, @@ -434,29 +426,29 @@ describe("config options", () => { }); }); - it(`should set "testRunEnv" option with ${NODEJS_TEST_RUN_ENV}`, () => { + it(`should set "testRunEnv" option with ${NODEJS_TEST_RUN_ENV}`, async () => { const readConfig = _.set({}, "system.testRunEnv", NODEJS_TEST_RUN_ENV); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.system.testRunEnv, NODEJS_TEST_RUN_ENV); }); - it(`should set "testRunEnv" option with ${BROWSER_TEST_RUN_ENV}`, () => { + it(`should set "testRunEnv" option with ${BROWSER_TEST_RUN_ENV}`, async () => { const readConfig = _.set({}, "system.testRunEnv", BROWSER_TEST_RUN_ENV); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.system.testRunEnv, BROWSER_TEST_RUN_ENV); }); - it(`should set "testRunEnv" option with ${BROWSER_TEST_RUN_ENV} and options`, () => { + it(`should set "testRunEnv" option with ${BROWSER_TEST_RUN_ENV} and options`, async () => { const readConfig = _.set({}, "system.testRunEnv", [BROWSER_TEST_RUN_ENV, {}]); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.system.testRunEnv, [BROWSER_TEST_RUN_ENV, {}]); }); @@ -465,7 +457,7 @@ describe("config options", () => { describe("lastFailed", () => { describe("only", () => { - it("should throw error if only is not a boolean", () => { + it("should throw error if only is not a boolean", async () => { const readConfig = { lastFailed: { only: "String", @@ -474,12 +466,12 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"lastFailed.only" must be a boolean'); + await assert.isRejected(createConfig(), '"lastFailed.only" must be a boolean'); }); }); describe("input", () => { - it("should throw error if input is not a string", () => { + it("should throw error if input is not a string", async () => { const readConfig = { lastFailed: { input: false, @@ -488,10 +480,10 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"lastFailed.input" must be a string or an array'); + await assert.isRejected(createConfig(), '"lastFailed.input" must be a string or an array'); }); - it("should throw error if input is a string without .json at the end", () => { + it("should throw error if input is a string without .json at the end", async () => { const readConfig = { lastFailed: { input: "string", @@ -500,10 +492,10 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"lastFailed.input" must have .json extension'); + await assert.isRejected(createConfig(), '"lastFailed.input" must have .json extension'); }); - it("should not throw error if input is a string with .json at the end", () => { + it("should not throw error if input is a string with .json at the end", async () => { const readConfig = { lastFailed: { input: "string.json", @@ -512,10 +504,10 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); - it("should throw error if input is an array that contains a string without .json at the end", () => { + it("should throw error if input is an array that contains a string without .json at the end", async () => { const readConfig = { lastFailed: { input: ["string.json", "string"], @@ -524,10 +516,10 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"lastFailed.input" elements must have .json extension'); + await assert.isRejected(createConfig(), '"lastFailed.input" elements must have .json extension'); }); - it("should not throw error if input is an array that contains only strings with .json at the end", () => { + it("should not throw error if input is an array that contains only strings with .json at the end", async () => { const readConfig = { lastFailed: { input: ["string.json"], @@ -536,12 +528,12 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); describe("output", () => { - it("should throw error if output is not a string", () => { + it("should throw error if output is not a string", async () => { const readConfig = { lastFailed: { output: false, @@ -550,10 +542,10 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"lastFailed.output" must be a string'); + await assert.isRejected(createConfig(), '"lastFailed.output" must be a string'); }); - it("should throw error if output is a string without .json at the end", () => { + it("should throw error if output is a string without .json at the end", async () => { const readConfig = { lastFailed: { output: "string", @@ -562,10 +554,10 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"lastFailed.output" must have .json extension'); + await assert.isRejected(createConfig(), '"lastFailed.output" must have .json extension'); }); - it("should not throw error if output is a string with .json at the end", () => { + it("should not throw error if output is a string with .json at the end", async () => { const readConfig = { lastFailed: { output: "string.json", @@ -574,17 +566,17 @@ describe("config options", () => { Config.read.returns(readConfig); - assert.doesNotThrow(() => createConfig()); + await assert.isFulfilled(createConfig()); }); }); - it("should set default lastFailed option if it does not set in config file", () => { - const config = createConfig(); + it("should set default lastFailed option if it does not set in config file", async () => { + const config = await createConfig(); assert.deepEqual(config.lastFailed, defaults.lastFailed); }); - it("should override lastFailed option", () => { + it("should override lastFailed option", async () => { const newValue = { input: "some-path.json", output: "some-path.json", @@ -594,93 +586,93 @@ describe("config options", () => { Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.lastFailed, newValue); }); }); describe("prepareEnvironment", () => { - it("should throw error if prepareEnvironment is not a null or function", () => { + it("should throw error if prepareEnvironment is not a null or function", async () => { const readConfig = { prepareEnvironment: "String" }; Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"prepareEnvironment" must be a function'); + await assert.isRejected(createConfig(), '"prepareEnvironment" must be a function'); }); - it("should set default prepareEnvironment option if it does not set in config file", () => { - const config = createConfig(); + it("should set default prepareEnvironment option if it does not set in config file", async () => { + const config = await createConfig(); assert.equal(config.prepareEnvironment, defaults.prepareEnvironment); }); - it("should override prepareEnvironment option", () => { + it("should override prepareEnvironment option", async () => { const newFunc = () => {}; const readConfig = { prepareEnvironment: newFunc }; Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.prepareEnvironment, newFunc); }); }); describe("hooks beforeAll/afterAll", () => { - it("should throw error if beforeAll is not a null or function", () => { + it("should throw error if beforeAll is not a null or function", async () => { const readConfig = { beforeAll: "String" }; Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"beforeAll" must be a function'); + await assert.isRejected(createConfig(), '"beforeAll" must be a function'); }); - it("should set default beforeAll option if it does not set in config file", () => { - const config = createConfig(); + it("should set default beforeAll option if it does not set in config file", async () => { + const config = await createConfig(); assert.equal(config.beforeAll, defaults.beforeAll); }); - it("should override beforeAll option", () => { + it("should override beforeAll option", async () => { const newFunc = () => {}; const readConfig = { beforeAll: newFunc }; Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.beforeAll, newFunc); }); - it("should throw error if afterAll is not a null or function", () => { + it("should throw error if afterAll is not a null or function", async () => { const readConfig = { afterAll: "String" }; Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"afterAll" must be a function'); + await assert.isRejected(createConfig(), '"afterAll" must be a function'); }); - it("should set default afterAll option if it does not set in config file", () => { - const config = createConfig(); + it("should set default afterAll option if it does not set in config file", async () => { + const config = await createConfig(); assert.equal(config.afterAll, defaults.afterAll); }); - it("should override afterAll option", () => { + it("should override afterAll option", async () => { const newFunc = () => {}; const readConfig = { afterAll: newFunc }; Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.deepEqual(config.afterAll, newFunc); }); }); describe("plugins", () => { - it("should parse boolean value from environment", () => { + it("should parse boolean value from environment", async () => { const result = parse_({ options: { plugins: { foo: {} } }, // prettier-ignore @@ -690,7 +682,7 @@ describe("config options", () => { assert.strictEqual(result.plugins.foo, true); }); - it("should parse object value from environment", () => { + it("should parse object value from environment", async () => { const result = parse_({ options: { plugins: { foo: {} } }, // prettier-ignore @@ -700,7 +692,7 @@ describe("config options", () => { assert.deepEqual(result.plugins.foo, { opt: 1 }); }); - it("should throw error on invalid values from environment", () => { + it("should throw error on invalid values from environment", async () => { assert.throws( () => parse_({ @@ -712,7 +704,7 @@ describe("config options", () => { ); }); - it("should parse boolean value from cli", () => { + it("should parse boolean value from cli", async () => { const result = parse_({ options: { plugins: { foo: {} } }, argv: ["--plugins-foo", "true"], @@ -721,7 +713,7 @@ describe("config options", () => { assert.strictEqual(result.plugins.foo, true); }); - it("should parse object value from cli", () => { + it("should parse object value from cli", async () => { const result = parse_({ options: { plugins: { foo: {} } }, argv: ["--plugins-foo", '{"opt": 1}'], @@ -730,7 +722,7 @@ describe("config options", () => { assert.deepEqual(result.plugins.foo, { opt: 1 }); }); - it("should throw error on invalid values from cli", () => { + it("should throw error on invalid values from cli", async () => { assert.throws( () => parse_({ @@ -743,26 +735,26 @@ describe("config options", () => { }); describe("shouldRetry", () => { - it("should throw error if shouldRetry is not a function", () => { + it("should throw error if shouldRetry is not a function", async () => { const readConfig = _.set({}, "shouldRetry", "shouldRetry"); Config.read.returns(readConfig); - assert.throws(() => createConfig(), Error, '"shouldRetry" must be a function'); + await assert.isRejected(createConfig(), '"shouldRetry" must be a function'); }); - it("should set default shouldRetry option if it does not set in config file", () => { - const config = createConfig(); + it("should set default shouldRetry option if it does not set in config file", async () => { + const config = await createConfig(); assert.equal(config.shouldRetry, null); }); - it("should override shouldRetry option", () => { + it("should override shouldRetry option", async () => { const shouldRetry = () => {}; const readConfig = _.set({}, "shouldRetry", shouldRetry); Config.read.returns(readConfig); - const config = createConfig(); + const config = await createConfig(); assert.equal(config.shouldRetry, shouldRetry); }); @@ -775,7 +767,7 @@ describe("config options", () => { }; describe("files", () => { - it("should throw an error if files are not specified", () => { + it("should throw an error if files are not specified", async () => { assert.throws(() => { parseOpts_({ sets: { @@ -785,7 +777,7 @@ describe("config options", () => { }, MissingOptionError); }); - it("should convert string to array of strings", () => { + it("should convert string to array of strings", async () => { const config = parseOpts_({ sets: { someSet: { @@ -797,7 +789,7 @@ describe("config options", () => { assert.deepEqual(config.sets.someSet.files, ["some/path"]); }); - it("should throw an error if files are specified as non-string array", () => { + it("should throw an error if files are specified as non-string array", async () => { assert.throws( () => { parseOpts_({ @@ -813,7 +805,7 @@ describe("config options", () => { ); }); - it("should accept array with strings", () => { + it("should accept array with strings", async () => { const config = parseOpts_({ sets: { someSet: { @@ -827,7 +819,7 @@ describe("config options", () => { }); describe("ignoreFiles", () => { - it("should accept array with strings", () => { + it("should accept array with strings", async () => { const config = parseOpts_({ sets: { someSet: { @@ -843,7 +835,7 @@ describe("config options", () => { describe("should throw an error", () => { const errorMask = /"sets.ignoreFiles" must be an array of strings/; - it('if "ignoreFiles" is not array', () => { + it('if "ignoreFiles" is not array', async () => { assert.throws( () => { parseOpts_({ @@ -860,7 +852,7 @@ describe("config options", () => { ); }); - it('if "ignoreFiles" are specified as non-string array', () => { + it('if "ignoreFiles" are specified as non-string array', async () => { assert.throws( () => { parseOpts_({ @@ -880,7 +872,7 @@ describe("config options", () => { }); describe("browsers", () => { - it("should contain all browsers from config by default", () => { + it("should contain all browsers from config by default", async () => { const config = parseOpts_({ browsers: { b1: {}, @@ -896,7 +888,7 @@ describe("config options", () => { assert.deepEqual(config.sets.someSet.browsers, ["b1", "b2"]); }); - it("should throw an error if browsers are not specified as array", () => { + it("should throw an error if browsers are not specified as array", async () => { const config = { sets: { someSet: { @@ -909,7 +901,7 @@ describe("config options", () => { assert.throws(() => parseOpts_(config), Error, /"sets.browsers" must be an array/); }); - it("should throw an error if sets contain unknown browsers", () => { + it("should throw an error if sets contain unknown browsers", async () => { assert.throws( () => { parseOpts_({ @@ -930,7 +922,7 @@ describe("config options", () => { ); }); - it("should use browsers which are specified in config", () => { + it("should use browsers which are specified in config", async () => { const config = parseOpts_({ browsers: { b1: {}, @@ -953,7 +945,7 @@ describe("config options", () => { }); }); - it("should have default set with empty files and all browsers if sets are not specified", () => { + it("should have default set with empty files and all browsers if sets are not specified", async () => { const config = parseOpts_({ browsers: { b1: {}, @@ -978,7 +970,7 @@ describe("config options", () => { }, errorMessage); }; - it("could be a function", () => { + it("could be a function", async () => { const config = parse_({ options: { devServer: { @@ -990,7 +982,7 @@ describe("config options", () => { assert.isFunction(config.devServer.readinessProbe); }); - it("could be empty", () => { + it("could be empty", async () => { const config = parse_({ options: { devServer: { @@ -1002,7 +994,7 @@ describe("config options", () => { assert.deepEqual(config.devServer.readinessProbe, defaults.devServer.readinessProbe); }); - it("could have string url", () => { + it("could have string url", async () => { const config = parse_({ options: { devServer: { @@ -1016,7 +1008,7 @@ describe("config options", () => { assert.deepEqual(config.devServer.readinessProbe.url, "foo"); }); - it("could have custom isReady function", () => { + it("could have custom isReady function", async () => { const config = parse_({ options: { devServer: { @@ -1030,7 +1022,7 @@ describe("config options", () => { assert.isFunction(config.devServer.readinessProbe.isReady); }); - it("could have overwritted timeouts", () => { + it("could have overwritted timeouts", async () => { const config = parse_({ options: { devServer: { @@ -1054,27 +1046,27 @@ describe("config options", () => { ); }); - it("should be a function or object", () => { + it("should be a function or object", async () => { assertReadinessProbeThrows("foo", '"devServer.readinessProbe" must be a function, object or null'); }); - it("url property should be a string", () => { + it("url property should be a string", async () => { assertReadinessProbeThrows({ url: {} }, '"devServer.readinessProbe.url" must be a string or null'); }); - it("isReady property should be a function", () => { + it("isReady property should be a function", async () => { assertReadinessProbeThrows( { isReady: {} }, '"devServer.readinessProbe.isReady" must be a function or null', ); }); - it("timeouts property should be an object", () => { + it("timeouts property should be an object", async () => { assertReadinessProbeThrows({ timeouts: () => {} }, '"devServer.readinessProbe.timeouts" must be an object'); }); ["waitServerTimeout", "probeRequestTimeout", "probeRequestInterval"].forEach(timeoutName => { - it(`timeouts.${timeoutName} should be a number`, () => { + it(`timeouts.${timeoutName} should be a number`, async () => { assertReadinessProbeThrows( { timeouts: { [timeoutName]: "foo" } }, `"devServer.readinessProbe.timeouts.${timeoutName}" must be a number`, diff --git a/test/src/dev-server/utils.ts b/test/src/dev-server/utils.ts index 298f4b99e..2512fae0a 100644 --- a/test/src/dev-server/utils.ts +++ b/test/src/dev-server/utils.ts @@ -237,6 +237,7 @@ describe("dev-server/utlls", () => { it("should throw error when url is not a string", async () => { const readinessProbe = createReadinessProbe_({ url: null }); + fetchStub.resetHistory(); try { await utils.probeServer(readinessProbe); diff --git a/test/src/testplane.js b/test/src/testplane.js index 140091e57..cf73e718d 100644 --- a/test/src/testplane.js +++ b/test/src/testplane.js @@ -25,9 +25,9 @@ describe("testplane", () => { const sandbox = sinon.createSandbox(); let Testplane, initReporters, signalHandler, loggerWarnStub, loggerErrorStub; - const mkTestplane_ = config => { - Config.create.returns(config || makeConfigStub()); - return Testplane.create(); + const mkTestplane_ = async config => { + Config.create.resolves(config || makeConfigStub()); + return await Testplane.create(); }; const mkRunner_ = runFn => { @@ -88,13 +88,13 @@ describe("testplane", () => { { debug: true, WDIO_LOG_LEVEL: "trace" }, { debug: false, WDIO_LOG_LEVEL: "error" }, { WDIO_LOG_LEVEL: "error" }, - ].forEach(({ debug, WDIO_LOG_LEVEL }) => { - it(`should be "${WDIO_LOG_LEVEL}" if "debug" is "${debug}"`, () => { + ].forEach(async ({ debug, WDIO_LOG_LEVEL }) => { + it(`should be "${WDIO_LOG_LEVEL}" if "debug" is "${debug}"`, async () => { const previousWdioLogLevel = process.env.WDIO_LOG_LEVEL; delete process.env.WDIO_LOG_LEVEL; - Config.create.returns(makeConfigStub({ system: { debug } })); + Config.create.resolves(makeConfigStub({ system: { debug } })); - Testplane.create("some-config-path.js"); + await Testplane.create("some-config-path.js"); assert.equal(process.env.WDIO_LOG_LEVEL, WDIO_LOG_LEVEL); process.env.WDIO_LOG_LEVEL = previousWdioLogLevel; @@ -102,43 +102,43 @@ describe("testplane", () => { }); }); - it("should create a config from the passed path", () => { - Testplane.create("some-config-path.js"); + it("should create a config from the passed path", async () => { + await Testplane.create("some-config-path.js"); assert.calledOnceWith(Config.create, "some-config-path.js"); }); - it("should load plugins", () => { - Testplane.create(); + it("should load plugins", async () => { + await Testplane.create(); assert.calledOnce(pluginsLoader.load); }); - it("should load plugins for testplane instance", () => { - Testplane.create(); + it("should load plugins for testplane instance", async () => { + await Testplane.create(); assert.calledWith(pluginsLoader.load, sinon.match.instanceOf(Testplane)); }); - it("should load plugins from config", () => { - Config.create.returns(makeConfigStub({ plugins: { "some-plugin": true } })); + it("should load plugins from config", async () => { + Config.create.resolves(makeConfigStub({ plugins: { "some-plugin": true } })); - Testplane.create(); + await Testplane.create(); assert.calledWith(pluginsLoader.load, sinon.match.any, { "some-plugin": true }); }); // testplane does not support its own plugin prefixes. - it("should load plugins with deprecated hermione prefix", () => { - Testplane.create(); + it("should load plugins with deprecated hermione prefix", async () => { + await Testplane.create(); assert.calledWith(pluginsLoader.load, sinon.match.any, sinon.match.any, "hermione-"); }); }); describe("extendCli", () => { - it("should emit CLI event with passed parser", () => { - const testplane = mkTestplane_(); + it("should emit CLI event with passed parser", async () => { + const testplane = await mkTestplane_(); const onCli = sinon.spy().named("onCli"); const parser = { foo: "bar" }; @@ -151,32 +151,32 @@ describe("testplane", () => { }); describe("run", () => { - const runTestplane = (paths, opts) => mkTestplane_().run(paths, opts); + const runTestplane = async (paths, opts) => (await mkTestplane_()).run(paths, opts); beforeEach(() => { sandbox.stub(TestCollection.prototype, "getBrowsers").returns([]); sandbox.stub(Testplane.prototype, "halt"); }); - it("should create runner", () => { + it("should create runner", async () => { mkRunner_(); return runTestplane().then(() => assert.calledOnce(MainRunner.create)); }); - it("should create runner with config", () => { + it("should create runner with config", async () => { mkRunner_(); const config = makeConfigStub(); - Config.create.returns(config); + Config.create.resolves(config); - return mkTestplane_(config).run(() => assert.calledWith(MainRunner.create, config)); + return (await mkTestplane_(config)).run(() => assert.calledWith(MainRunner.create, config)); }); it("should create runner with interceptors", async () => { mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); const fooHandler = () => {}; const barHandler = () => {}; @@ -190,7 +190,7 @@ describe("testplane", () => { ]); }); - it("should warn about unknown browsers from cli", () => { + it("should warn about unknown browsers from cli", async () => { mkRunner_(); return runTestplane([], { browsers: ["bro3"] }).then(() => @@ -234,7 +234,7 @@ describe("testplane", () => { describe("repl mode", () => { it("should not reset test timeout to 0 if run not in repl", async () => { mkRunner_(); - const testplane = mkTestplane_( + const testplane = await mkTestplane_( makeConfigStub({ lastFailed: { only: false }, system: { mochaOpts: { timeout: 100500 } }, @@ -248,7 +248,7 @@ describe("testplane", () => { it("should reset test timeout to 0 if run in repl", async () => { mkRunner_(); - const testplane = mkTestplane_( + const testplane = await mkTestplane_( makeConfigStub({ lastFailed: { only: false }, system: { mochaOpts: { timeout: 100500 } }, @@ -264,36 +264,36 @@ describe("testplane", () => { describe("INIT", () => { beforeEach(() => mkRunner_()); - it("should emit INIT on run", () => { + it("should emit INIT on run", async () => { const onInit = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.INIT, onInit); + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, onInit); return testplane.run().then(() => assert.calledOnce(onInit)); }); - it("should reject on INIT handler fail", () => { - const testplane = mkTestplane_().on(RunnerEvents.INIT, () => Promise.reject("o.O")); + it("should reject on INIT handler fail", async () => { + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, () => Promise.reject("o.O")); return assert.isRejected(testplane.run(), /o.O/); }); - it("should wait INIT handler before running tests", () => { + it("should wait INIT handler before running tests", async () => { const afterInit = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.INIT, () => promiseDelay(20).then(afterInit)); + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, () => promiseDelay(20).then(afterInit)); return testplane.run().then(() => assert.callOrder(afterInit, MainRunner.prototype.run)); }); - it("should init runner after emit INIT", () => { + it("should init runner after emit INIT", async () => { const onInit = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.INIT, onInit); + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, onInit); return testplane.run().then(() => assert.callOrder(onInit, MainRunner.prototype.init)); }); - it("should send INIT event only once", () => { + it("should send INIT event only once", async () => { const onInit = sinon.spy().named("onInit"); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); testplane.on(RunnerEvents.INIT, onInit); return testplane @@ -304,7 +304,7 @@ describe("testplane", () => { describe("vite server", () => { it(`should do nothing if testRunEnv is ${NODEJS_TEST_RUN_ENV}`, async () => { - const testplane = mkTestplane_({ system: { testRunEnv: NODEJS_TEST_RUN_ENV } }); + const testplane = await mkTestplane_({ system: { testRunEnv: NODEJS_TEST_RUN_ENV } }); await testplane.run(); @@ -314,7 +314,7 @@ describe("testplane", () => { it("should create vite server", async () => { const config = makeConfigStub({ system: { testRunEnv: BROWSER_TEST_RUN_ENV } }); - const testplane = mkTestplane_(config); + const testplane = await mkTestplane_(config); await testplane.run(); @@ -322,7 +322,7 @@ describe("testplane", () => { }); it("should start vite server", async () => { - const testplane = mkTestplane_({ system: { testRunEnv: BROWSER_TEST_RUN_ENV } }); + const testplane = await mkTestplane_({ system: { testRunEnv: BROWSER_TEST_RUN_ENV } }); await testplane.run(); @@ -332,7 +332,7 @@ describe("testplane", () => { it("should throw error if vite server failed", async () => { ViteServer.prototype.start.rejects(new Error("o.O")); - const testplane = mkTestplane_({ + const testplane = await mkTestplane_({ system: { testRunEnv: BROWSER_TEST_RUN_ENV }, }); @@ -350,8 +350,8 @@ describe("testplane", () => { it("should initialize passed reporters", async () => { const options = { reporters: ["reporter"] }; - Config.create.returns(makeConfigStub()); - const testplane = Testplane.create(); + Config.create.resolves(makeConfigStub()); + const testplane = await Testplane.create(); await testplane.run(null, options); @@ -360,8 +360,8 @@ describe("testplane", () => { it("should initialize reporters before run tests", async () => { const options = { reporters: ["reporter"] }; - Config.create.returns(makeConfigStub()); - const testplane = Testplane.create(); + Config.create.resolves(makeConfigStub()); + const testplane = await Testplane.create(); await testplane.run(null, options); @@ -421,7 +421,7 @@ describe("testplane", () => { }); describe("running of tests", () => { - it("should run tests", () => { + it("should run tests", async () => { mkRunner_(); return runTestplane().then(() => assert.calledOnce(MainRunner.prototype.run)); @@ -441,7 +441,7 @@ describe("testplane", () => { it("should create runner stats", async () => { mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); await testplane.run(); @@ -458,13 +458,13 @@ describe("testplane", () => { assert.calledWith(MainRunner.prototype.run, sinon.match.any, "foo bar"); }); - it('should return "true" if there are no failed tests', () => { + it('should return "true" if there are no failed tests', async () => { mkRunner_(); return runTestplane().then(success => assert.isTrue(success)); }); - it('should return "false" if there are failed tests', () => { + it('should return "false" if there are failed tests', async () => { const results = { fullTitle: () => "Title", browserId: "chrome", @@ -475,8 +475,8 @@ describe("testplane", () => { return runTestplane().then(success => assert.isFalse(success)); }); - it("should halt if there were some errors", () => { - const testplane = mkTestplane_(); + it("should halt if there were some errors", async () => { + const testplane = await mkTestplane_(); const err = new Error(); mkRunner_(runner => runner.emit(RunnerEvents.ERROR, err)); @@ -507,9 +507,9 @@ describe("testplane", () => { }); describe("should passthrough", () => { - it("all synchronous runner events", () => { + it("all synchronous runner events", async () => { const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); return testplane.run().then(() => { _.forEach(CommonSyncEvents, (event, name) => { @@ -523,10 +523,10 @@ describe("testplane", () => { }); }); - it('synchronous runner events before "Runner.run" called', () => { + it('synchronous runner events before "Runner.run" called', async () => { sandbox.stub(eventsUtils, "passthroughEvent"); const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); return testplane.run().then(() => { assert.calledWith( @@ -539,9 +539,9 @@ describe("testplane", () => { }); }); - it("all asynchronous runner events", () => { + it("all asynchronous runner events", async () => { const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); return testplane.run().then(() => { _.forEach(MasterAsyncEvents, (event, name) => { @@ -555,10 +555,10 @@ describe("testplane", () => { }); }); - it('asynchronous runner events before "Runner.run" called', () => { + it('asynchronous runner events before "Runner.run" called', async () => { sandbox.stub(eventsUtils, "passthroughEventAsync"); const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); return testplane.run().then(() => { assert.calledWith( @@ -571,9 +571,9 @@ describe("testplane", () => { }); }); - it("all runner events with passed event data", () => { + it("all runner events with passed event data", async () => { const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); const results = { fullTitle: () => "Title", browserId: "chrome", @@ -593,10 +593,10 @@ describe("testplane", () => { }); }); - it("exit event from signalHandler", () => { + it("exit event from signalHandler", async () => { mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); const onExit = sinon.spy().named("onExit"); return testplane.run().then(() => { @@ -608,11 +608,11 @@ describe("testplane", () => { }); }); - it('exit event before "Runner.run" called', () => { + it('exit event before "Runner.run" called', async () => { sandbox.stub(eventsUtils, "passthroughEventAsync"); const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); return testplane.run().then(() => { assert.calledWith( @@ -630,7 +630,7 @@ describe("testplane", () => { describe("addTestToRun", () => { it("should pass test to the existing runner", async () => { const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); const test = {}; await testplane.run(); @@ -639,9 +639,9 @@ describe("testplane", () => { assert.calledOnceWith(runner.addTestToRun, test, "bro"); }); - it("should return false when testplane is not running", () => { + it("should return false when testplane is not running", async () => { const runner = mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); const added = testplane.addTestToRun({}); @@ -662,17 +662,17 @@ describe("testplane", () => { it("should create test reader", async () => { const config = makeConfigStub(); - const testplane = mkTestplane_(config); + const testplane = await mkTestplane_(config); await testplane.readTests(); assert.calledOnceWith(TestReader.create, config); }); - ["BEFORE_FILE_READ", "AFTER_FILE_READ"].forEach(event => { + ["BEFORE_FILE_READ", "AFTER_FILE_READ"].forEach(async event => { it(`should passthrough ${event} event from test reader`, async () => { const eventHandler = sandbox.stub(); - const testplane = mkTestplane_().on(RunnerEvents[event], eventHandler); + const testplane = (await mkTestplane_()).on(RunnerEvents[event], eventHandler); TestReader.prototype.read.callsFake(function () { this.emit(RunnerEvents[event], { foo: "bar" }); @@ -685,7 +685,7 @@ describe("testplane", () => { it(`should not passthrough ${event} event from test reader with silent option`, async () => { const eventHandler = sandbox.stub(); - const testplane = mkTestplane_().on(RunnerEvents[event], eventHandler); + const testplane = (await mkTestplane_()).on(RunnerEvents[event], eventHandler); TestReader.prototype.read.callsFake(function () { this.emit(RunnerEvents[event]); @@ -698,7 +698,7 @@ describe("testplane", () => { }); it("should read passed test files", async () => { - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); await testplane.readTests(["foo/bar"], { browsers: ["bro"], @@ -735,7 +735,7 @@ describe("testplane", () => { const testCollection = TestCollection.create(); TestCollection.create.withArgs(tests).returns(testCollection); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); const result = await testplane.readTests(); assert.equal(result, testCollection); @@ -746,7 +746,7 @@ describe("testplane", () => { const config = makeConfigStub({ browsers }); config.forBrowser("bar").strictTestsOrder = true; - const testplane = mkTestplane_(config); + const testplane = await mkTestplane_(config); TestCollection.prototype.getBrowsers.returns(browsers); await testplane.readTests(); @@ -759,7 +759,7 @@ describe("testplane", () => { const config = makeConfigStub({ browsers }); config.forBrowser("foo").strictTestsOrder = true; - const testplane = mkTestplane_(config); + const testplane = await mkTestplane_(config); TestCollection.prototype.getBrowsers.returns(browsers); await testplane.readTests(); @@ -773,22 +773,22 @@ describe("testplane", () => { describe("INIT", () => { it("should emit INIT on read", async () => { const onInit = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.INIT, onInit); + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, onInit); await testplane.readTests(); assert.calledOnce(onInit); }); - it("should reject on INIT handler fail", () => { - const testplane = mkTestplane_().on(RunnerEvents.INIT, () => Promise.reject("o.O")); + it("should reject on INIT handler fail", async () => { + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, () => Promise.reject("o.O")); return assert.isRejected(testplane.readTests(), /o.O/); }); it("should wait INIT handler before reading tests", async () => { const afterInit = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.INIT, () => promiseDelay(20).then(afterInit)); + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, () => promiseDelay(20).then(afterInit)); await testplane.readTests(); @@ -797,7 +797,7 @@ describe("testplane", () => { it("should not emit INIT on silent read", async () => { const onInit = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.INIT, onInit); + const testplane = (await mkTestplane_()).on(RunnerEvents.INIT, onInit); await testplane.readTests(null, { silent: true }); @@ -806,7 +806,7 @@ describe("testplane", () => { it("should send INIT event only once", async () => { const onInit = sinon.spy(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); testplane.on(RunnerEvents.INIT, onInit); await testplane.readTests(); @@ -819,7 +819,7 @@ describe("testplane", () => { describe("AFTER_TESTS_READ", () => { it("should emit AFTER_TESTS_READ on read", async () => { const onAfterTestsRead = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.AFTER_TESTS_READ, onAfterTestsRead); + const testplane = (await mkTestplane_()).on(RunnerEvents.AFTER_TESTS_READ, onAfterTestsRead); await testplane.readTests(); @@ -828,7 +828,7 @@ describe("testplane", () => { it("should pass test collection with AFTER_TESTS_READ event", async () => { const onAfterTestsRead = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.AFTER_TESTS_READ, onAfterTestsRead); + const testplane = (await mkTestplane_()).on(RunnerEvents.AFTER_TESTS_READ, onAfterTestsRead); const collection = await testplane.readTests(); @@ -837,7 +837,7 @@ describe("testplane", () => { it("should not emit AFTER_TESTS_READ in silent mode", async () => { const onAfterTestsRead = sinon.spy(); - const testplane = mkTestplane_().on(RunnerEvents.AFTER_TESTS_READ, onAfterTestsRead); + const testplane = (await mkTestplane_()).on(RunnerEvents.AFTER_TESTS_READ, onAfterTestsRead); await testplane.readTests(null, { silent: true }); @@ -847,41 +847,41 @@ describe("testplane", () => { }); describe("should provide access to", () => { - it("testplane events", () => { + it("testplane events", async () => { const expectedEvents = _.extend( { NEW_BROWSER: "newBrowser", UPDATE_REFERENCE: "updateReference" }, RunnerEvents, ); - assert.deepEqual(mkTestplane_().events, expectedEvents); + assert.deepEqual((await mkTestplane_()).events, expectedEvents); }); - it("testplane configuration", () => { + it("testplane configuration", async () => { const config = makeConfigStub(); - assert.deepEqual(mkTestplane_(config).config, config); + assert.deepEqual((await mkTestplane_(config)).config, config); }); - it("testplane errors", () => { - assert.deepEqual(mkTestplane_().errors, Errors); + it("testplane errors", async () => { + assert.deepEqual((await mkTestplane_()).errors, Errors); }); }); describe("isFailed", () => { - it('should return "false" by default', () => { - assert.isFalse(mkTestplane_().isFailed()); + it('should return "false" by default', async () => { + assert.isFalse((await mkTestplane_()).isFailed()); }); - it('should return "false" if there are no failed tests or errors', () => { + it('should return "false" if there are no failed tests or errors', async () => { mkRunner_(); - const testplane = mkTestplane_(); + const testplane = await mkTestplane_(); return testplane.run().then(() => assert.isFalse(testplane.isFailed())); }); - it('should return "true" after some test fail', () => { - const testplane = mkTestplane_(); + it('should return "true" after some test fail', async () => { + const testplane = await mkTestplane_(); const results = { fullTitle: () => "Title", @@ -900,8 +900,8 @@ describe("testplane", () => { }); describe("isWorker", () => { - it('should return "false"', () => { - const testplane = mkTestplane_(); + it('should return "false"', async () => { + const testplane = await mkTestplane_(); assert.isFalse(testplane.isWorker()); }); @@ -910,15 +910,15 @@ describe("testplane", () => { describe("halt", () => { let testplane; - beforeEach(() => { - testplane = mkTestplane_(); + beforeEach(async () => { + testplane = await mkTestplane_(); sandbox.stub(process, "exit"); sandbox.stub(MainRunner.prototype, "run").callsFake(() => testplane.emitAndWait(RunnerEvents.RUNNER_START)); sandbox.stub(MainRunner.prototype, "cancel"); }); - it("should log provided error", () => { + it("should log provided error", async () => { const err = new Error("test error"); testplane.on(RunnerEvents.RUNNER_START, () => { @@ -931,7 +931,7 @@ describe("testplane", () => { }); it("should close vite server", async () => { - testplane = mkTestplane_(makeConfigStub({ system: { testRunEnv: BROWSER_TEST_RUN_ENV } })); + testplane = await mkTestplane_(makeConfigStub({ system: { testRunEnv: BROWSER_TEST_RUN_ENV } })); await testplane.run(); @@ -940,13 +940,13 @@ describe("testplane", () => { assert.calledOnce(ViteServer.prototype.close); }); - it("should not cancel test runner if runner is not inited", () => { + it("should not cancel test runner if runner is not inited", async () => { testplane.halt(new Error("test error")); assert.notCalled(MainRunner.prototype.cancel); }); - it("should cancel test runner", () => { + it("should cancel test runner", async () => { testplane.on(RunnerEvents.RUNNER_START, () => { testplane.halt(new Error("test error")); }); @@ -956,7 +956,7 @@ describe("testplane", () => { }); }); - it("should mark test run as failed", () => { + it("should mark test run as failed", async () => { testplane.on(RunnerEvents.RUNNER_START, () => { testplane.halt(new Error("test error")); }); @@ -978,7 +978,7 @@ describe("testplane", () => { assert.callOrder(global.setTimeout, MainRunner.prototype.cancel); }); - it("should force exit if timeout is reached", () => { + it("should force exit if timeout is reached", async () => { testplane.on(RunnerEvents.RUNNER_START, () => { testplane.halt(new Error("test error"), 250); }); @@ -992,7 +992,7 @@ describe("testplane", () => { }); }); - it("should do nothing if timeout is set to zero", () => { + it("should do nothing if timeout is set to zero", async () => { sandbox.spy(global, "setTimeout"); testplane.on(RunnerEvents.RUNNER_START, () => { testplane.halt(new Error("test error"), 0); diff --git a/test/src/worker/testplane-facade.js b/test/src/worker/testplane-facade.js index dcdee9cdd..58b106d4d 100644 --- a/test/src/worker/testplane-facade.js +++ b/test/src/worker/testplane-facade.js @@ -27,7 +27,7 @@ describe("worker/testplane-facade", () => { init: sandbox.spy().named("testplaneInit"), config, }); - sandbox.stub(Testplane, "create").returns(testplane); + sandbox.stub(Testplane, "create").resolves(testplane); testplaneFacade = TestplaneFacade.create(); }); diff --git a/test/src/worker/testplane.js b/test/src/worker/testplane.js index 0ba5ff673..5fefc00c8 100644 --- a/test/src/worker/testplane.js +++ b/test/src/worker/testplane.js @@ -40,23 +40,23 @@ describe("worker/testplane", () => { }); describe("constructor", () => { - it("should create a config from the passed path", () => { - Testplane.create("some-config-path.js"); + it("should create a config from the passed path", async () => { + await Testplane.create("some-config-path.js"); assert.calledOnceWith(Config.create, "some-config-path.js"); }); - it("should create a runner instance", () => { + it("should create a runner instance", async () => { const config = makeConfigStub(); - Config.create.returns(config); + Config.create.resolves(config); - Testplane.create(); + await Testplane.create(); assert.calledOnceWith(Runner.create, config); }); - it("should passthrough all runner events", () => { - const testplane = Testplane.create(); + it("should passthrough all runner events", async () => { + const testplane = await Testplane.create(); _.forEach( { @@ -78,29 +78,29 @@ describe("worker/testplane", () => { }); describe("loading of plugins", () => { - it("should load plugins", () => { - Testplane.create(); + it("should load plugins", async () => { + await Testplane.create(); assert.calledOnce(pluginsLoader.load); }); - it("should load plugins for testplane instance", () => { - Testplane.create(); + it("should load plugins for testplane instance", async () => { + await Testplane.create(); assert.calledWith(pluginsLoader.load, sinon.match.instanceOf(Testplane)); }); - it("should load plugins from config", () => { - Config.create.returns(makeConfigStub({ plugins: { "some-plugin": true } })); + it("should load plugins from config", async () => { + Config.create.resolves(makeConfigStub({ plugins: { "some-plugin": true } })); - Testplane.create(); + await Testplane.create(); assert.calledWith(pluginsLoader.load, sinon.match.any, { "some-plugin": true }); }); // testplane does not support its own plugin prefixes. - it("should load plugins with deprecated hermione prefix", () => { - Testplane.create(); + it("should load plugins with deprecated hermione prefix", async () => { + await Testplane.create(); assert.calledWith(pluginsLoader.load, sinon.match.any, sinon.match.any, "hermione-"); }); @@ -108,22 +108,28 @@ describe("worker/testplane", () => { }); describe("should provide access to", () => { - it("testplane events", () => { + it("testplane events", async () => { const expectedEvents = _.extend({}, RunnerEvents, WorkerRunnerEvents); - assert.deepEqual(Testplane.create(makeConfigStub()).events, expectedEvents); + const testplane = await Testplane.create(makeConfigStub()); + + assert.deepEqual(testplane.events, expectedEvents); }); - it("testplane configuration", () => { + it("testplane configuration", async () => { const config = makeConfigStub(); - Config.create.returns(config); + Config.create.resolves(config); + + const testplane = await Testplane.create(makeConfigStub()); - assert.deepEqual(Testplane.create().config, config); + assert.deepEqual(testplane.config, config); }); - it("testplane errors", () => { - assert.deepEqual(Testplane.create().errors, Errors); + it("testplane errors", async () => { + const testplane = await Testplane.create(); + + assert.deepEqual(testplane.errors, Errors); }); }); @@ -132,55 +138,60 @@ describe("worker/testplane", () => { delete global.expect; }); - it('should emit "INIT"', () => { - const testplane = Testplane.create(); + it('should emit "INIT"', async () => { + const testplane = await Testplane.create(); const onInit = sinon.spy(); testplane.on(WorkerRunnerEvents.INIT, onInit); - return testplane.init().then(() => assert.calledOnce(onInit)); + await testplane.init(); + + assert.calledOnce(onInit); }); - it('should reject on "INIT" handler fail', () => { - const testplane = Testplane.create().on(WorkerRunnerEvents.INIT, () => Promise.reject("o.O")); + it('should reject on "INIT" handler fail', async () => { + const testplane = await Testplane.create(); + testplane.on(WorkerRunnerEvents.INIT, () => Promise.reject("o.O")); - return assert.isRejected(testplane.init(), /o.O/); + await assert.isRejected(testplane.init(), /o.O/); }); it("should not init expect-webdriverio if global.expect already set", async () => { global.expect = {}; - await Testplane.create().init(); + const testplane = await Testplane.create(); + await testplane.init(); assert.notCalled(ExpectWebdriverio.setOptions); }); it("should not init expect-webdriverio if global.expect not set", async () => { - Config.create.returns({ + Config.create.resolves({ system: { expectOpts: { foo: "bar" }, }, }); - await Testplane.create().init(); + const testplane = await Testplane.create(); + await testplane.init(); assert.calledOnceWith(ExpectWebdriverio.setOptions, { foo: "bar" }); }); }); describe("runTest", () => { - it("should run test", () => { + it("should run test", async () => { Runner.prototype.runTest.withArgs("fullTitle", { some: "options" }).resolves("foo bar"); - const testplane = Testplane.create(); + const testplane = await Testplane.create(); return testplane.runTest("fullTitle", { some: "options" }).then(result => assert.equal(result, "foo bar")); }); }); describe("isWorker", () => { - it('should return "true"', () => { - const testplane = Testplane.create(); + it('should return "true"', async () => { + const testplane = await Testplane.create(); assert.isTrue(testplane.isWorker()); });