diff --git a/CHANGELOG.md b/CHANGELOG.md index 4eefdcc64..150674b2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Please see [CONTRIBUTING.md](./CONTRIBUTING.md) on how to contribute to Cucumber. ## [Unreleased] +### Changed +- Use explicit status to check if Cucumber is running when registering support code ([#2386](https://github.com/cucumber/cucumber-js/pull/2386)) ## [10.3.1] - 2024-01-16 ### Changed diff --git a/features/invalid_installation.feature b/features/invalid_installation.feature index 9f65be4d3..ebb904b47 100644 --- a/features/invalid_installation.feature +++ b/features/invalid_installation.feature @@ -19,8 +19,8 @@ Feature: Invalid installations Then it fails And the error output contains the text: """ - You're calling functions (e.g. "When") on an instance of Cucumber that isn't running. - This means you have an invalid installation, mostly likely due to: + You're calling functions (e.g. "When") on an instance of Cucumber that isn't running (status: PENDING). + This means you may have an invalid installation, potentially due to: - Cucumber being installed globally - A project structure where your support code is depending on a different instance of Cucumber Either way, you'll need to address this in order for Cucumber to work. diff --git a/src/support_code_library_builder/index.ts b/src/support_code_library_builder/index.ts index 1ea4f6840..986273e86 100644 --- a/src/support_code_library_builder/index.ts +++ b/src/support_code_library_builder/index.ts @@ -10,7 +10,7 @@ import TestStepHookDefinition from '../models/test_step_hook_definition' import TestRunHookDefinition from '../models/test_run_hook_definition' import StepDefinition from '../models/step_definition' import { formatLocation } from '../formatter/helpers' -import { doesHaveValue, doesNotHaveValue } from '../value_checker' +import { doesHaveValue } from '../value_checker' import { ICanonicalSupportCodeIds } from '../runtime/parallel/command_types' import { GherkinStepKeyword } from '../models/gherkin_step_keyword' import validateArguments from './validate_arguments' @@ -65,9 +65,10 @@ interface ITestRunHookDefinitionConfig { uri: string } +type LibraryStatus = 'PENDING' | 'OPEN' | 'FINALIZED' + export class SupportCodeLibraryBuilder { public readonly methods: IDefineSupportCodeMethods - private originalCoordinates: ISupportCodeCoordinates private afterTestCaseHookDefinitionConfigs: ITestCaseHookDefinitionConfig[] private afterTestRunHookDefinitionConfigs: ITestRunHookDefinitionConfig[] @@ -83,6 +84,7 @@ export class SupportCodeLibraryBuilder { private stepDefinitionConfigs: IStepDefinitionConfig[] private World: any private parallelCanAssign: ParallelAssignmentValidator + private status: LibraryStatus = 'PENDING' constructor() { const methods: IDefineSupportCodeMethods = { @@ -123,11 +125,11 @@ export class SupportCodeLibraryBuilder { When: this.defineStep('When', () => this.stepDefinitionConfigs), } const checkInstall = (method: string) => { - if (doesNotHaveValue(this.cwd)) { + if (this.status === 'PENDING') { throw new Error( ` - You're calling functions (e.g. "${method}") on an instance of Cucumber that isn't running. - This means you have an invalid installation, mostly likely due to: + You're calling functions (e.g. "${method}") on an instance of Cucumber that isn't running (status: ${this.status}). + This means you may have an invalid installation, potentially due to: - Cucumber being installed globally - A project structure where your support code is depending on a different instance of Cucumber Either way, you'll need to address this in order for Cucumber to work. @@ -414,6 +416,7 @@ export class SupportCodeLibraryBuilder { } finalize(canonicalIds?: ICanonicalSupportCodeIds): SupportCodeLibrary { + this.status = 'FINALIZED' const stepDefinitionsResult = this.buildStepDefinitions( canonicalIds?.stepDefinitionIds ) @@ -472,6 +475,7 @@ export class SupportCodeLibraryBuilder { this.stepDefinitionConfigs = [] this.parallelCanAssign = () => true this.World = World + this.status = 'OPEN' } } diff --git a/src/support_code_library_builder/index_spec.ts b/src/support_code_library_builder/index_spec.ts index 6ab75771b..01568cad4 100644 --- a/src/support_code_library_builder/index_spec.ts +++ b/src/support_code_library_builder/index_spec.ts @@ -1,3 +1,4 @@ +import { fail } from 'node:assert' import { describe, it } from 'mocha' import { expect } from 'chai' import sinon from 'sinon' @@ -9,6 +10,18 @@ import supportCodeLibraryBuilder from './' const { uuid } = IdGenerator describe('supportCodeLibraryBuilder', () => { + it('should throw if not been reset yet', () => { + try { + // @ts-expect-error mutating private member + supportCodeLibraryBuilder.status = 'PENDING' + supportCodeLibraryBuilder.methods.Given('some context', () => {}) + fail() + } catch (e) { + expect(e.message).to.contain('calling functions (e.g. "Given")') + expect(e.message).to.contain('status: PENDING') + } + }) + describe('no support code fns', () => { it('returns the default options', function () { // Arrange