diff --git a/exports/api/report.api.md b/exports/api/report.api.md index 907c3c37fc..6b91ec9e68 100644 --- a/exports/api/report.api.md +++ b/exports/api/report.api.md @@ -101,7 +101,7 @@ export interface IRunConfiguration { export interface IRunEnvironment { cwd?: string; debug?: boolean; - env?: NodeJS.ProcessEnv; + env?: Record; stderr?: Writable; stdout?: Writable; } diff --git a/src/api/console_logger.ts b/src/api/console_logger.ts deleted file mode 100644 index 4614a91977..0000000000 --- a/src/api/console_logger.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Console } from 'node:console' -import { Writable } from 'node:stream' -import { ILogger } from '../logger' - -export class ConsoleLogger implements ILogger { - private console: Console - constructor( - private stream: Writable, - private debugEnabled: boolean - ) { - this.console = new Console(this.stream) - } - - debug(...content: any[]): void { - if (this.debugEnabled) { - this.console.debug(...content) - } - } - - error(...content: any[]): void { - this.console.error(...content) - } - - warn(...content: any[]): void { - this.console.warn(...content) - } -} diff --git a/src/api/convert_configuration.ts b/src/api/convert_configuration.ts index d9e49b7ed9..d39d247463 100644 --- a/src/api/convert_configuration.ts +++ b/src/api/convert_configuration.ts @@ -4,7 +4,7 @@ import { splitFormatDescriptor, } from '../configuration' import { IPublishConfig } from '../publish' -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { IRunConfiguration } from './types' export async function convertConfiguration( diff --git a/src/api/formatters.ts b/src/api/formatters.ts index 1f450b20bc..23ac66a2cd 100644 --- a/src/api/formatters.ts +++ b/src/api/formatters.ts @@ -5,7 +5,7 @@ import { IFormatterStream } from '../formatter' import { EventDataCollector } from '../formatter/helpers' import { SupportCodeLibrary } from '../support_code_library_builder/types' import FormatterBuilder from '../formatter/builder' -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { createStream } from '../formatter/create_stream' import { resolveImplementation } from '../formatter/resolve_implementation' import { PluginManager } from '../plugin' @@ -74,7 +74,6 @@ export async function initializeFormatters({ await pluginManager.initFormatter( implementation, configuration.options, - logger, stream.write.bind(stream), directory ) diff --git a/src/api/index.ts b/src/api/index.ts index 6572c8b97c..36dc3bf1b2 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -8,6 +8,7 @@ */ export { IConfiguration } from '../configuration' +export { IRunEnvironment } from '../environment' export { IPickleOrder } from '../filter' export { IPublishConfig } from '../publish' export * from './load_configuration' diff --git a/src/api/load_configuration.ts b/src/api/load_configuration.ts index d1d366c23c..0884086dfc 100644 --- a/src/api/load_configuration.ts +++ b/src/api/load_configuration.ts @@ -6,13 +6,9 @@ import { parseConfiguration, validateConfiguration, } from '../configuration' +import { IRunEnvironment, makeEnvironment } from '../environment' import { convertConfiguration } from './convert_configuration' -import { mergeEnvironment } from './environment' -import { - IRunEnvironment, - IResolvedConfiguration, - ILoadConfigurationOptions, -} from './types' +import { IResolvedConfiguration, ILoadConfigurationOptions } from './types' /** * Load user-authored configuration to be used in a test run @@ -25,7 +21,7 @@ export async function loadConfiguration( options: ILoadConfigurationOptions = {}, environment: IRunEnvironment = {} ): Promise { - const { cwd, env, logger } = mergeEnvironment(environment) + const { cwd, env, logger } = makeEnvironment(environment) const configFile = options.file ?? locateFile(cwd) if (configFile) { logger.debug(`Configuration will be loaded from "${configFile}"`) diff --git a/src/api/load_configuration_spec.ts b/src/api/load_configuration_spec.ts index 582b717338..29a4e27760 100644 --- a/src/api/load_configuration_spec.ts +++ b/src/api/load_configuration_spec.ts @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { IRunEnvironment } from './types' +import { IRunEnvironment } from '../environment' import { setupEnvironment, teardownEnvironment } from './test_helpers' import { loadConfiguration } from './load_configuration' diff --git a/src/api/load_sources.ts b/src/api/load_sources.ts index fd4602af29..586a9f660a 100644 --- a/src/api/load_sources.ts +++ b/src/api/load_sources.ts @@ -1,13 +1,12 @@ import { IdGenerator } from '@cucumber/messages' import { resolvePaths } from '../paths' +import { IRunEnvironment, makeEnvironment } from '../environment' import { ILoadSourcesResult, IPlannedPickle, - IRunEnvironment, ISourcesCoordinates, ISourcesError, } from './types' -import { mergeEnvironment } from './environment' import { getPicklesAndErrors } from './gherkin' import { initializeForLoadSources } from './plugins' @@ -23,11 +22,10 @@ export async function loadSources( coordinates: ISourcesCoordinates, environment: IRunEnvironment = {} ): Promise { - const mergedEnvironment = mergeEnvironment(environment) + const mergedEnvironment = makeEnvironment(environment) const { cwd, logger } = mergedEnvironment const newId = IdGenerator.uuid() const pluginManager = await initializeForLoadSources( - logger, coordinates, mergedEnvironment ) diff --git a/src/api/load_sources_spec.ts b/src/api/load_sources_spec.ts index 23a4c4a6d4..c1d3eb9db1 100644 --- a/src/api/load_sources_spec.ts +++ b/src/api/load_sources_spec.ts @@ -3,7 +3,7 @@ import { PassThrough } from 'node:stream' import { expect } from 'chai' import fs from 'mz/fs' import { IdGenerator } from '@cucumber/messages' -import { IRunEnvironment } from './types' +import { IRunEnvironment } from '../environment' import { loadSources } from './load_sources' const newId = IdGenerator.uuid() diff --git a/src/api/load_support.ts b/src/api/load_support.ts index 32835916f6..e448bd3804 100644 --- a/src/api/load_support.ts +++ b/src/api/load_support.ts @@ -1,12 +1,8 @@ import { IdGenerator } from '@cucumber/messages' import { resolvePaths } from '../paths' -import { - ILoadSupportOptions, - IRunEnvironment, - ISupportCodeLibrary, -} from './types' +import { IRunEnvironment, makeEnvironment } from '../environment' +import { ILoadSupportOptions, ISupportCodeLibrary } from './types' import { getSupportCodeLibrary } from './support' -import { mergeEnvironment } from './environment' import { initializeForLoadSupport } from './plugins' /** @@ -20,7 +16,7 @@ export async function loadSupport( options: ILoadSupportOptions, environment: IRunEnvironment = {} ): Promise { - const mergedEnvironment = mergeEnvironment(environment) + const mergedEnvironment = makeEnvironment(environment) const { cwd, logger } = mergedEnvironment const newId = IdGenerator.uuid() const supportCoordinates = Object.assign( @@ -32,7 +28,7 @@ export async function loadSupport( }, options.support ) - const pluginManager = await initializeForLoadSupport() + const pluginManager = await initializeForLoadSupport(mergedEnvironment) const resolvedPaths = await resolvePaths( logger, cwd, diff --git a/src/api/load_support_spec.ts b/src/api/load_support_spec.ts index 6853a06c3a..115f8a7e39 100644 --- a/src/api/load_support_spec.ts +++ b/src/api/load_support_spec.ts @@ -1,6 +1,6 @@ import path from 'node:path' import { expect } from 'chai' -import { IRunEnvironment } from './types' +import { IRunEnvironment } from '../environment' import { loadSupport } from './load_support' import { loadConfiguration } from './load_configuration' import { setupEnvironment, teardownEnvironment } from './test_helpers' diff --git a/src/api/plugins.ts b/src/api/plugins.ts index 3a6ecaa4ab..0f3a0f2d73 100644 --- a/src/api/plugins.ts +++ b/src/api/plugins.ts @@ -1,55 +1,41 @@ import { PluginManager } from '../plugin' import publishPlugin from '../publish' -import { ILogger } from '../logger' import filterPlugin from '../filter' -import { - IRunConfiguration, - IRunEnvironment, - ISourcesCoordinates, -} from './types' +import { UsableEnvironment } from '../environment' +import { IRunConfiguration, ISourcesCoordinates } from './types' export async function initializeForLoadSources( - logger: ILogger, coordinates: ISourcesCoordinates, - environment: Required + environment: UsableEnvironment ): Promise { // eventually we'll load plugin packages here - const pluginManager = new PluginManager() - await pluginManager.initCoordinator( - 'loadSources', - filterPlugin, - coordinates, - logger, - environment - ) + const pluginManager = new PluginManager(environment) + await pluginManager.initCoordinator('loadSources', filterPlugin, coordinates) return pluginManager } -export async function initializeForLoadSupport(): Promise { +export async function initializeForLoadSupport( + environment: UsableEnvironment +): Promise { // eventually we'll load plugin packages here - return new PluginManager() + return new PluginManager(environment) } export async function initializeForRunCucumber( - logger: ILogger, configuration: IRunConfiguration, - environment: Required + environment: UsableEnvironment ): Promise { // eventually we'll load plugin packages here - const pluginManager = new PluginManager() + const pluginManager = new PluginManager(environment) await pluginManager.initCoordinator( 'runCucumber', publishPlugin, - configuration.formats.publish, - logger, - environment + configuration.formats.publish ) await pluginManager.initCoordinator( 'runCucumber', filterPlugin, - configuration.sources, - logger, - environment + configuration.sources ) return pluginManager } diff --git a/src/api/run_cucumber.ts b/src/api/run_cucumber.ts index e9651c84e8..ec15e7d680 100644 --- a/src/api/run_cucumber.ts +++ b/src/api/run_cucumber.ts @@ -7,10 +7,10 @@ import { SupportCodeLibrary } from '../support_code_library_builder/types' import { version } from '../version' import { IFilterablePickle } from '../filter' import { makeRuntime } from '../runtime' -import { IRunOptions, IRunEnvironment, IRunResult } from './types' +import { IRunEnvironment, makeEnvironment } from '../environment' +import { IRunOptions, IRunResult } from './types' import { initializeFormatters } from './formatters' import { getSupportCodeLibrary } from './support' -import { mergeEnvironment } from './environment' import { getPicklesAndErrors } from './gherkin' import { initializeForRunCucumber } from './plugins' @@ -27,7 +27,7 @@ export async function runCucumber( environment: IRunEnvironment = {}, onMessage?: (message: Envelope) => void ): Promise { - const mergedEnvironment = mergeEnvironment(environment) + const mergedEnvironment = makeEnvironment(environment) const { cwd, stdout, stderr, env, logger } = mergedEnvironment logger.debug(`Running cucumber-js ${version} @@ -51,7 +51,6 @@ Running from: ${__dirname} ) const pluginManager = await initializeForRunCucumber( - logger, { ...options, support: supportCoordinates, diff --git a/src/api/run_cucumber_spec.ts b/src/api/run_cucumber_spec.ts index df9f82d445..1572f719b8 100644 --- a/src/api/run_cucumber_spec.ts +++ b/src/api/run_cucumber_spec.ts @@ -1,7 +1,7 @@ import { Envelope, TestStepResultStatus } from '@cucumber/messages' import { expect } from 'chai' +import { IRunEnvironment } from '../environment' import { runCucumber } from './run_cucumber' -import { IRunEnvironment } from './types' import { loadSupport } from './load_support' import { loadConfiguration } from './load_configuration' import { setupEnvironment, teardownEnvironment } from './test_helpers' diff --git a/src/api/support.ts b/src/api/support.ts index d4925f0dd3..f803e26083 100644 --- a/src/api/support.ts +++ b/src/api/support.ts @@ -4,7 +4,7 @@ import { IdGenerator } from '@cucumber/messages' import { SupportCodeLibrary } from '../support_code_library_builder/types' import supportCodeLibraryBuilder from '../support_code_library_builder' import tryRequire from '../try_require' -import { ILogger } from '../logger' +import { ILogger } from '../environment' export async function getSupportCodeLibrary({ logger, diff --git a/src/api/test_helpers.ts b/src/api/test_helpers.ts index de13446997..20e3680a04 100644 --- a/src/api/test_helpers.ts +++ b/src/api/test_helpers.ts @@ -3,7 +3,7 @@ import { PassThrough } from 'node:stream' import fs from 'mz/fs' import { reindent } from 'reindent-template-literals' import { IdGenerator } from '@cucumber/messages' -import { IRunEnvironment } from './types' +import { IRunEnvironment } from '../environment' const newId = IdGenerator.uuid() diff --git a/src/api/types.ts b/src/api/types.ts index 2b71596575..33f86e6589 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -1,4 +1,3 @@ -import { Writable } from 'node:stream' import { JsonObject } from 'type-fest' import { IPublishConfig } from '../publish' import { IConfiguration } from '../configuration' @@ -295,39 +294,6 @@ export interface IRunOptions { formats: IRunOptionsFormats } -/** - * Contextual data about the project environment - * @public - */ -export interface IRunEnvironment { - /** - * Working directory for the project - * @default process.cwd() - */ - cwd?: string - /** - * Writable stream where the test run's main formatter output is written - * @default process.stdout - */ - stdout?: Writable - /** - * Writable stream where the test run's warning/error output is written - * @default process.stderr - */ - stderr?: Writable - /** - * Environment variables - * @default process.env - */ - env?: NodeJS.ProcessEnv - /** - * Whether debug logging should be emitted to {@link IRunEnvironment.stderr} - * @default false - * @see {@link https://github.com/cucumber/cucumber-js/blob/main/docs/debugging.md} - */ - debug?: boolean -} - /** * Response from {@link runCucumber} * @public diff --git a/src/cli/helpers.ts b/src/cli/helpers.ts index ea280461f8..0f2790d86d 100644 --- a/src/cli/helpers.ts +++ b/src/cli/helpers.ts @@ -8,7 +8,7 @@ import { SupportCodeLibrary } from '../support_code_library_builder/types' import TestCaseHookDefinition from '../models/test_case_hook_definition' import TestRunHookDefinition from '../models/test_run_hook_definition' import { version } from '../version' -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { ILineAndUri } from '../types' import { IPickleOrder } from '../filter' diff --git a/src/configuration/from_file.ts b/src/configuration/from_file.ts index 747c4dc2e6..436d11bb7a 100644 --- a/src/configuration/from_file.ts +++ b/src/configuration/from_file.ts @@ -4,7 +4,7 @@ import { promisify } from 'node:util' import { pathToFileURL } from 'node:url' import YAML from 'yaml' import readPkgUp from 'read-pkg-up' -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { IConfiguration } from './types' import { mergeConfigurations } from './merge_configurations' import { parseConfiguration } from './parse_configuration' diff --git a/src/configuration/parse_configuration.ts b/src/configuration/parse_configuration.ts index 42d99f1c87..0949f9478e 100644 --- a/src/configuration/parse_configuration.ts +++ b/src/configuration/parse_configuration.ts @@ -1,5 +1,5 @@ import stringArgv from 'string-argv' -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { IConfiguration } from './types' import ArgvParser from './argv_parser' import { checkSchema } from './check_schema' diff --git a/src/configuration/split_format_descriptor.ts b/src/configuration/split_format_descriptor.ts index eefdb7efa2..347b397a45 100644 --- a/src/configuration/split_format_descriptor.ts +++ b/src/configuration/split_format_descriptor.ts @@ -1,4 +1,4 @@ -import { ILogger } from '../logger' +import { ILogger } from '../environment' export function splitFormatDescriptor( logger: ILogger, diff --git a/src/configuration/validate_configuration.ts b/src/configuration/validate_configuration.ts index f5eb682c29..8ed6b456c1 100644 --- a/src/configuration/validate_configuration.ts +++ b/src/configuration/validate_configuration.ts @@ -1,4 +1,4 @@ -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { IConfiguration } from './types' export function validateConfiguration( diff --git a/src/environment/console_logger.ts b/src/environment/console_logger.ts new file mode 100644 index 0000000000..a8e85c421c --- /dev/null +++ b/src/environment/console_logger.ts @@ -0,0 +1,28 @@ +import { Console } from 'node:console' +import { Writable } from 'node:stream' +import { ILogger } from './types' + +export class ConsoleLogger implements ILogger { + private readonly console: Console + + constructor( + private stream: Writable, + private debugEnabled: boolean + ) { + this.console = new Console(this.stream) + } + + debug(message?: any, ...optionalParams: any[]): void { + if (this.debugEnabled) { + this.console.debug(message, ...optionalParams) + } + } + + error(message?: any, ...optionalParams: any[]): void { + this.console.error(message, ...optionalParams) + } + + warn(message?: any, ...optionalParams: any[]): void { + this.console.warn(message, ...optionalParams) + } +} diff --git a/src/environment/index.ts b/src/environment/index.ts new file mode 100644 index 0000000000..5dbcb951c9 --- /dev/null +++ b/src/environment/index.ts @@ -0,0 +1,2 @@ +export * from './make_environment' +export * from './types' diff --git a/src/api/environment.ts b/src/environment/make_environment.ts similarity index 65% rename from src/api/environment.ts rename to src/environment/make_environment.ts index 5b9ac3eac3..138477b029 100644 --- a/src/api/environment.ts +++ b/src/environment/make_environment.ts @@ -1,12 +1,7 @@ -import { ILogger } from '../logger' -import { IRunEnvironment } from './types' import { ConsoleLogger } from './console_logger' +import { UsableEnvironment, IRunEnvironment } from './types' -type EnvironmentWithLogger = Required & { logger: ILogger } - -export function mergeEnvironment( - provided: IRunEnvironment -): EnvironmentWithLogger { +export function makeEnvironment(provided: IRunEnvironment): UsableEnvironment { const fullEnvironment = Object.assign( {}, { diff --git a/src/environment/types.ts b/src/environment/types.ts new file mode 100644 index 0000000000..2971748f68 --- /dev/null +++ b/src/environment/types.ts @@ -0,0 +1,44 @@ +import { Writable } from 'node:stream' + +export interface ILogger { + debug: (message?: any, ...optionalParams: any[]) => void + error: (message?: any, ...optionalParams: any[]) => void + warn: (message?: any, ...optionalParams: any[]) => void +} + +/** + * Contextual data about the project environment + * @public + */ +export interface IRunEnvironment { + /** + * Working directory for the project + * @default process.cwd() + */ + cwd?: string + /** + * Writable stream where the test run's main formatter output is written + * @default process.stdout + */ + stdout?: Writable + /** + * Writable stream where the test run's warning/error output is written + * @default process.stderr + */ + stderr?: Writable + /** + * Environment variables + * @default process.env + */ + env?: Record + /** + * Whether debug logging should be emitted to {@link IRunEnvironment.stderr} + * @default false + * @see {@link https://github.com/cucumber/cucumber-js/blob/main/docs/debugging.md} + */ + debug?: boolean +} + +export type UsableEnvironment = Required & { + logger: ILogger +} diff --git a/src/formatter/create_stream.ts b/src/formatter/create_stream.ts index b479131151..9ae164241e 100644 --- a/src/formatter/create_stream.ts +++ b/src/formatter/create_stream.ts @@ -2,7 +2,7 @@ import path from 'node:path' import { Writable } from 'node:stream' import { mkdirp } from 'mkdirp' import fs from 'mz/fs' -import { ILogger } from '../logger' +import { ILogger } from '../environment' export async function createStream( target: string, diff --git a/src/logger.ts b/src/logger.ts deleted file mode 100644 index f9bde393d4..0000000000 --- a/src/logger.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface ILogger { - debug: (...content: any[]) => void - error: (...content: any[]) => void - warn: (...content: any[]) => void -} diff --git a/src/paths/paths.ts b/src/paths/paths.ts index 4b26c7b9ec..acc7600f4f 100644 --- a/src/paths/paths.ts +++ b/src/paths/paths.ts @@ -1,7 +1,7 @@ import path from 'node:path' import { glob } from 'glob' import fs from 'mz/fs' -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { ISourcesCoordinates, ISupportCodeCoordinates } from '../api' import { IResolvedPaths } from './types' diff --git a/src/paths/paths_spec.ts b/src/paths/paths_spec.ts index 13ea5c1b92..760ddc7653 100644 --- a/src/paths/paths_spec.ts +++ b/src/paths/paths_spec.ts @@ -5,7 +5,7 @@ import fsExtra from 'fs-extra' import { describe, it } from 'mocha' import { expect } from 'chai' import { FakeLogger } from '../../test/fake_logger' -import { ILogger } from '../logger' +import { ILogger } from '../environment' import { resolvePaths } from './paths' async function buildTestWorkingDirectory(): Promise { diff --git a/src/plugin/plugin_manager.ts b/src/plugin/plugin_manager.ts index 13a0901d2a..2248bb4e6f 100644 --- a/src/plugin/plugin_manager.ts +++ b/src/plugin/plugin_manager.ts @@ -1,5 +1,4 @@ -import { IRunEnvironment } from '../api' -import { ILogger } from '../logger' +import { UsableEnvironment } from '../environment' import { CoordinatorPluginEventHandler, InternalPlugin, @@ -24,6 +23,8 @@ export class PluginManager { } private cleanupFns: PluginCleanup[] = [] + constructor(private readonly environment: UsableEnvironment) {} + private async register( event: K, handler: CoordinatorPluginEventHandler @@ -34,7 +35,6 @@ export class PluginManager { async initFormatter( plugin: FormatterPlugin, options: OptionsType, - logger: ILogger, write: (buffer: string | Uint8Array) => void, directory?: string ) { @@ -43,7 +43,7 @@ export class PluginManager { options: plugin.optionsKey ? (options as any)[plugin.optionsKey] ?? ({} as OptionsType) : options, - logger, + logger: this.environment.logger, write, directory, }) @@ -55,16 +55,18 @@ export class PluginManager { async initCoordinator( operation: Operation, plugin: InternalPlugin, - options: OptionsType, - logger: ILogger, - environment: Required + options: OptionsType ) { const cleanupFn = await plugin.coordinator({ operation, on: this.register.bind(this), options, - logger, - environment, + logger: this.environment.logger, + environment: { + cwd: this.environment.cwd, + stderr: this.environment.stderr, + env: { ...this.environment.env }, + }, }) if (typeof cleanupFn === 'function') { this.cleanupFns.push(cleanupFn) diff --git a/src/plugin/plugin_manager_spec.ts b/src/plugin/plugin_manager_spec.ts index da8fe6791d..34451d3d44 100644 --- a/src/plugin/plugin_manager_spec.ts +++ b/src/plugin/plugin_manager_spec.ts @@ -1,23 +1,22 @@ import sinon from 'sinon' import { expect } from 'chai' -import { IRunEnvironment } from '../api' -import { ILogger } from '../logger' import { FakeLogger } from '../../test/fake_logger' import { IFilterablePickle } from '../filter' +import { UsableEnvironment } from '../environment' import { PluginManager } from './plugin_manager' describe('PluginManager', () => { - const environment: Required = { + const usableEnvironment: UsableEnvironment = { cwd: 'cwd', stdout: process.stdout, stderr: process.stderr, env: {}, debug: false, + logger: new FakeLogger(), } - const logger: ILogger = new FakeLogger() it('passes the correct context to the coordinator function', async () => { - const pluginManager = new PluginManager() + const pluginManager = new PluginManager(usableEnvironment) const coordinator = sinon.fake() await pluginManager.initCoordinator( 'runCucumber', @@ -25,21 +24,23 @@ describe('PluginManager', () => { type: 'plugin', coordinator, }, - {}, - logger, - environment + {} ) expect(coordinator).to.have.been.calledOnce expect(coordinator.lastCall.firstArg.operation).to.eq('runCucumber') expect(coordinator.lastCall.firstArg.on).to.exist expect(coordinator.lastCall.firstArg.options).to.deep.eq({}) - expect(coordinator.lastCall.firstArg.logger).to.eq(logger) - expect(coordinator.lastCall.firstArg.environment).to.eq(environment) + expect(coordinator.lastCall.firstArg.logger).to.eq(usableEnvironment.logger) + expect(Object.keys(coordinator.lastCall.firstArg.environment)).to.deep.eq([ + 'cwd', + 'stderr', + 'env', + ]) }) it('calls cleanup functions from all plugins', async () => { - const pluginManager = new PluginManager() + const pluginManager = new PluginManager(usableEnvironment) const cleanup1 = sinon.fake() const cleanup2 = sinon.fake() await pluginManager.initCoordinator( @@ -48,9 +49,7 @@ describe('PluginManager', () => { type: 'plugin', coordinator: () => cleanup1, }, - {}, - logger, - environment + {} ) await pluginManager.initCoordinator( 'runCucumber', @@ -58,9 +57,7 @@ describe('PluginManager', () => { type: 'plugin', coordinator: () => cleanup2, }, - {}, - logger, - environment + {} ) await pluginManager.cleanup() @@ -71,7 +68,7 @@ describe('PluginManager', () => { describe('void events', () => { it(`emits void event to all handlers`, async () => { - const pluginManager = new PluginManager() + const pluginManager = new PluginManager(usableEnvironment) const handler1 = sinon.fake() const handler2 = sinon.fake() await pluginManager.initCoordinator( @@ -80,9 +77,7 @@ describe('PluginManager', () => { type: 'plugin', coordinator: ({ on }) => on('message', handler1), }, - {}, - logger, - environment + {} ) await pluginManager.initCoordinator( 'runCucumber', @@ -90,9 +85,7 @@ describe('PluginManager', () => { type: 'plugin', coordinator: ({ on }) => on('message', handler2), }, - {}, - logger, - environment + {} ) const value = { @@ -130,7 +123,7 @@ describe('PluginManager', () => { ] as IFilterablePickle[] it('should apply transforms in the order registered', async () => { - const pluginManager = new PluginManager() + const pluginManager = new PluginManager(usableEnvironment) await pluginManager.initCoordinator( 'runCucumber', { @@ -142,9 +135,7 @@ describe('PluginManager', () => { ) }, }, - {}, - logger, - environment + {} ) await pluginManager.initCoordinator( 'runCucumber', @@ -157,9 +148,7 @@ describe('PluginManager', () => { ) }, }, - {}, - logger, - environment + {} ) const result = await pluginManager.transform( @@ -170,7 +159,7 @@ describe('PluginManager', () => { }) it('should treat undefined as a noop', async () => { - const pluginManager = new PluginManager() + const pluginManager = new PluginManager(usableEnvironment) await pluginManager.initCoordinator( 'runCucumber', { @@ -178,9 +167,7 @@ describe('PluginManager', () => { // bail, nothing to be done coordinator: ({ on }) => on('pickles:filter', () => undefined), }, - {}, - logger, - environment + {} ) const result = await pluginManager.transform( diff --git a/src/plugin/types.ts b/src/plugin/types.ts index d466e0c3af..7850d1bc30 100644 --- a/src/plugin/types.ts +++ b/src/plugin/types.ts @@ -1,13 +1,17 @@ import { Envelope } from '@cucumber/messages' import { ArrayValues, Promisable } from 'type-fest' -import { IRunEnvironment } from '../api' -import { ILogger } from '../logger' +import { IRunEnvironment } from '../environment' +import { ILogger } from '../environment' import { IFilterablePickle } from '../filter' import { IResolvedPaths } from '../paths' import { coordinatorTransformKeys, coordinatorVoidKeys } from './events' export type Operation = 'loadSources' | 'loadSupport' | 'runCucumber' +export type CoordinatorPluginEnvironment = Required< + Pick +> + export type CoordinatorPluginVoidEventKey = ArrayValues< typeof coordinatorVoidKeys > @@ -42,7 +46,7 @@ export interface CoordinatorPluginContext { ) => void options: OptionsType logger: ILogger - environment: Required + environment: CoordinatorPluginEnvironment } export type CoordinatorPluginFunction = ( diff --git a/src/runtime/make_runtime.ts b/src/runtime/make_runtime.ts index 8a3b12368e..bd28a9a25a 100644 --- a/src/runtime/make_runtime.ts +++ b/src/runtime/make_runtime.ts @@ -1,9 +1,10 @@ import { EventEmitter } from 'node:events' import { IdGenerator } from '@cucumber/messages' -import { IRunEnvironment, IRunOptionsRuntime } from '../api' -import { ILogger } from '../logger' +import { IRunOptionsRuntime } from '../api' +import { ILogger } from '../environment' import { SourcedPickle } from '../assemble' import { SupportCodeLibrary } from '../support_code_library_builder/types' +import { IRunEnvironment } from '../environment' import { Runtime, RuntimeAdapter } from './types' import { ChildProcessAdapter } from './parallel/adapter' import { InProcessAdapter } from './serial/adapter' diff --git a/src/runtime/parallel/adapter.ts b/src/runtime/parallel/adapter.ts index b937800d85..67585f96dd 100644 --- a/src/runtime/parallel/adapter.ts +++ b/src/runtime/parallel/adapter.ts @@ -3,9 +3,9 @@ import path from 'node:path' import { EventEmitter } from 'node:events' import { SupportCodeLibrary } from '../../support_code_library_builder/types' import { AssembledTestCase } from '../../assemble' -import { ILogger } from '../../logger' +import { ILogger, IRunEnvironment } from '../../environment' import { RuntimeAdapter } from '../types' -import { IRunEnvironment, IRunOptionsRuntime } from '../../api' +import { IRunOptionsRuntime } from '../../api' import { FinalizeCommand, InitializeCommand, diff --git a/test-d/api.mts b/test-d/api.mts deleted file mode 100644 index 450592cec2..0000000000 --- a/test-d/api.mts +++ /dev/null @@ -1,8 +0,0 @@ -import { IConfiguration, loadConfiguration, runCucumber } from '../api' - -// should allow api usage from /api subpath -const provided: Partial = { - paths: ['features/foo.feature'], -} -const { runConfiguration } = await loadConfiguration({ provided }) -const { success } = await runCucumber(runConfiguration) diff --git a/test-d/api.ts b/test-d/api.ts new file mode 100644 index 0000000000..c792f1cc4b --- /dev/null +++ b/test-d/api.ts @@ -0,0 +1,13 @@ +import { IRunEnvironment } from '../api' + +// environment variables accepts an object literal +const fromLiteral: IRunEnvironment = { + env: { + FOO: 'BAR', + }, +} + +// environment variables accepts a NodeJS.ProcessEnv +const fromProcessEnv: IRunEnvironment = { + env: process.env, +} diff --git a/test/fake_logger.ts b/test/fake_logger.ts index 1c5a0fd341..1bc93a8c1e 100644 --- a/test/fake_logger.ts +++ b/test/fake_logger.ts @@ -1,5 +1,5 @@ import sinon from 'sinon' -import { ILogger } from '../src/logger' +import { ILogger } from '../src/environment' export class FakeLogger implements ILogger { debug = sinon.fake()