From 8615f8a8be400c966ea27ce306ac592150aa3bd2 Mon Sep 17 00:00:00 2001 From: Jonas Amundsen Date: Fri, 28 Apr 2023 17:24:34 +0200 Subject: [PATCH] Refactor configuration combination a tiny bit This fixes #951. --- CHANGELOG.md | 2 + lib/preprocessor-configuration.ts | 230 +++++++++++++++--------------- lib/step-definitions.test.ts | 11 +- lib/step-definitions.ts | 7 +- 4 files changed, 127 insertions(+), 123 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ffc5104..a406083b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file. - More precise snippet suggestions, fixes [#974](https://github.com/badeball/cypress-cucumber-preprocessor/issues/974). +- Report resolved configuration correctly, [#951](https://github.com/badeball/cypress-cucumber-preprocessor/issues/951). + ## v16.0.3 - Update dependency on `@badeball/cypress-configuration`, fixing an issue where specs in node_modules weren't ignored. diff --git a/lib/preprocessor-configuration.ts b/lib/preprocessor-configuration.ts index ad7065fc..b7e5ddc2 100644 --- a/lib/preprocessor-configuration.ts +++ b/lib/preprocessor-configuration.ts @@ -21,10 +21,10 @@ function hasOwnProperty, Y extends string>( return Object.prototype.hasOwnProperty.call(value, property); } -function validateConfigurationEntry( +function validateUserConfigurationEntry( key: string, value: Record -): Partial { +): Partial { switch (key) { case "stepDefinitions": if (!isStringOrStringArray(value)) { @@ -292,7 +292,7 @@ function validateEnvironmentOverrides( return overrides; } -export function stringToMaybeBoolean(value: string): boolean | undefined { +function stringToMaybeBoolean(value: string): boolean | undefined { if (value === "") { return; } @@ -306,8 +306,20 @@ export function stringToMaybeBoolean(value: string): boolean | undefined { } } -export interface IPreprocessorConfiguration { - readonly stepDefinitions: string | string[]; +interface IEnvironmentOverrides { + stepDefinitions?: string | string[]; + messagesEnabled?: boolean; + messagesOutput?: string; + jsonEnabled?: boolean; + jsonOutput?: string; + htmlEnabled?: boolean; + htmlOutput?: string; + filterSpecs?: boolean; + omitFiltered?: boolean; +} + +export interface IUserConfiguration { + readonly stepDefinitions?: string | string[]; readonly messages?: { enabled: boolean; output?: string; @@ -322,114 +334,95 @@ export interface IPreprocessorConfiguration { }; readonly filterSpecs?: boolean; readonly omitFiltered?: boolean; - readonly implicitIntegrationFolder: string; } -export interface IEnvironmentOverrides { - stepDefinitions?: string | string[]; - messagesEnabled?: boolean; - messagesOutput?: string; - jsonEnabled?: boolean; - jsonOutput?: string; - htmlEnabled?: boolean; - htmlOutput?: string; - filterSpecs?: boolean; - omitFiltered?: boolean; +export interface IPreprocessorConfiguration { + readonly stepDefinitions: string | string[]; + readonly messages: { + enabled: boolean; + output: string; + }; + readonly json: { + enabled: boolean; + output: string; + }; + readonly html: { + enabled: boolean; + output: string; + }; + readonly filterSpecs: boolean; + readonly omitFiltered: boolean; + readonly implicitIntegrationFolder: string; } -export const DEFAULT_STEP_DEFINITIONS = [ +const DEFAULT_STEP_DEFINITIONS = [ "[integration-directory]/[filepath]/**/*.{js,mjs,ts,tsx}", "[integration-directory]/[filepath].{js,mjs,ts,tsx}", "cypress/support/step_definitions/**/*.{js,mjs,ts,tsx}", ]; -export class PreprocessorConfiguration implements IPreprocessorConfiguration { - constructor( - private explicitValues: Partial, - private environmentOverrides: IEnvironmentOverrides, - private cypressConfiguration: ICypressConfiguration, - public implicitIntegrationFolder: string - ) {} - - get stepDefinitions() { - const explicit = - this.environmentOverrides.stepDefinitions ?? - this.explicitValues.stepDefinitions; - - if (explicit) { - return explicit; - } - - const config = this.cypressConfiguration; - - return DEFAULT_STEP_DEFINITIONS.map((pattern) => - pattern.replace( - "[integration-directory]", - ensureIsRelative( - config.projectRoot, - "integrationFolder" in config - ? config.integrationFolder - : this.implicitIntegrationFolder - ) +export function combineIntoConfiguration( + configuration: IUserConfiguration, + overrides: IEnvironmentOverrides, + cypress: ICypressConfiguration, + implicitIntegrationFolder: string +): IPreprocessorConfiguration { + const defaultStepDefinitions = DEFAULT_STEP_DEFINITIONS.map((pattern) => + pattern.replace( + "[integration-directory]", + ensureIsRelative( + cypress.projectRoot, + "integrationFolder" in cypress + ? cypress.integrationFolder + : implicitIntegrationFolder ) - ); - } + ) + ); - get messages() { - return { - enabled: - this.json.enabled || - this.html.enabled || - (this.environmentOverrides.messagesEnabled ?? - this.explicitValues.messages?.enabled ?? - false), - output: - this.environmentOverrides.messagesOutput ?? - this.explicitValues.messages?.output ?? - "cucumber-messages.ndjson", - }; - } + const stepDefinitions: IPreprocessorConfiguration["stepDefinitions"] = + overrides.stepDefinitions ?? + configuration.stepDefinitions ?? + defaultStepDefinitions; - get json() { - return { - enabled: - this.environmentOverrides.jsonEnabled ?? - this.explicitValues.json?.enabled ?? - false, - output: - this.environmentOverrides.jsonOutput ?? - (this.explicitValues.json?.output || "cucumber-report.json"), - }; - } + const json: IPreprocessorConfiguration["json"] = { + enabled: overrides.jsonEnabled ?? configuration.json?.enabled ?? false, + output: + overrides.jsonOutput ?? + (configuration.json?.output || "cucumber-report.json"), + }; - get html() { - return { - enabled: - this.environmentOverrides.htmlEnabled ?? - this.explicitValues.html?.enabled ?? - false, - output: - this.environmentOverrides.htmlOutput ?? - this.explicitValues.html?.output ?? - "cucumber-report.html", - }; - } + const html: IPreprocessorConfiguration["html"] = { + enabled: overrides.htmlEnabled ?? configuration.html?.enabled ?? false, + output: + overrides.htmlOutput ?? + (configuration.html?.output || "cucumber-report.html"), + }; - get filterSpecs() { - return ( - this.environmentOverrides.filterSpecs ?? - this.explicitValues.filterSpecs ?? - false - ); - } + const messages: IPreprocessorConfiguration["messages"] = { + enabled: + json.enabled || + html.enabled || + (overrides.messagesEnabled ?? configuration.messages?.enabled ?? false), + output: + overrides.messagesOutput ?? + (configuration.messages?.output || "cucumber-messages.ndjson"), + }; - get omitFiltered() { - return ( - this.environmentOverrides.omitFiltered ?? - this.explicitValues.omitFiltered ?? - false - ); - } + const filterSpecs: IPreprocessorConfiguration["filterSpecs"] = + overrides.filterSpecs ?? configuration.filterSpecs ?? false; + + const omitFiltered: IPreprocessorConfiguration["omitFiltered"] = + overrides.omitFiltered ?? configuration.omitFiltered ?? false; + + return { + stepDefinitions, + messages, + json, + html, + filterSpecs, + omitFiltered, + implicitIntegrationFolder, + }; } async function cosmiconfigResolver(projectRoot: string) { @@ -449,11 +442,15 @@ export async function resolve( environment: Record, implicitIntegrationFolder: string, configurationFileResolver: ConfigurationFileResolver = cosmiconfigResolver -) { +): Promise { const result = await configurationFileResolver(cypressConfig.projectRoot); const environmentOverrides = validateEnvironmentOverrides(environment); + debug(`resolved environment overrides ${util.inspect(environmentOverrides)}`); + + let explicitConfiguration: Partial; + if (result) { if (typeof result !== "object" || result == null) { throw new Error( @@ -463,29 +460,32 @@ export async function resolve( ); } - const config: Partial = Object.assign( + explicitConfiguration = Object.assign( {}, ...Object.entries(result).map((entry) => - validateConfigurationEntry(...entry) + validateUserConfigurationEntry(...entry) ) ); - debug(`resolved configuration ${util.inspect(config)}`); - - return new PreprocessorConfiguration( - config, - environmentOverrides, - cypressConfig, - implicitIntegrationFolder + debug( + `resolved explicit user configuration ${util.inspect( + explicitConfiguration + )}` ); } else { - debug("resolved no configuration"); + explicitConfiguration = {}; - return new PreprocessorConfiguration( - {}, - environmentOverrides, - cypressConfig, - implicitIntegrationFolder - ); + debug("resolved no explicit user configuration"); } + + const configuration = combineIntoConfiguration( + explicitConfiguration, + environmentOverrides, + cypressConfig, + implicitIntegrationFolder + ); + + debug(`resolved configuration ${util.inspect(configuration)}`); + + return configuration; } diff --git a/lib/step-definitions.test.ts b/lib/step-definitions.test.ts index 4d2e51f4..81fc2817 100644 --- a/lib/step-definitions.test.ts +++ b/lib/step-definitions.test.ts @@ -11,7 +11,8 @@ import { import { IPreprocessorConfiguration, - PreprocessorConfiguration, + IUserConfiguration, + combineIntoConfiguration, } from "./preprocessor-configuration"; import { @@ -49,7 +50,7 @@ function pre10example( const actual = getStepDefinitionPatternsPre10( { cypress: cypressConfiguration, - preprocessor: new PreprocessorConfiguration( + preprocessor: combineIntoConfiguration( preprocessorConfiguration, {}, cypressConfiguration, @@ -87,7 +88,7 @@ const DUMMY_POST10_CONFIG: ICypressPost10Configuration = { function post10example( filepath: string, partialCypressConfiguration: Partial, - preprocessorConfiguration: Partial, + preprocessorConfiguration: IUserConfiguration, implicitIntegrationFolder: string, expected: string[] ) { @@ -104,7 +105,7 @@ function post10example( const actual = getStepDefinitionPatternsPost10( { cypress: cypressConfiguration, - preprocessor: new PreprocessorConfiguration( + preprocessor: combineIntoConfiguration( preprocessorConfiguration, {}, cypressConfiguration, @@ -197,7 +198,6 @@ describe("getStepDefinitionPatternsPre10()", () => { }, preprocessor: { stepDefinitions: [], - implicitIntegrationFolder: "/foo/bar/cypress/integration", }, }, "/foo/bar/cypress/features/baz.feature" @@ -215,7 +215,6 @@ describe("getStepDefinitionPatternsPre10()", () => { }, preprocessor: { stepDefinitions: [], - implicitIntegrationFolder: "/foo/bar/cypress/integration", }, }, "/foo/bar/cypress/integration/baz.feature" diff --git a/lib/step-definitions.ts b/lib/step-definitions.ts index b76edf64..3a812cff 100644 --- a/lib/step-definitions.ts +++ b/lib/step-definitions.ts @@ -72,7 +72,10 @@ export function getStepDefinitionPatterns( export function getStepDefinitionPatternsPost10( configuration: { cypress: Pick; - preprocessor: IPreprocessorConfiguration; + preprocessor: Pick< + IPreprocessorConfiguration, + "stepDefinitions" | "implicitIntegrationFolder" + >; }, filepath: string ): string[] { @@ -128,7 +131,7 @@ export function getStepDefinitionPatternsPre10( ICypressPre10Configuration, "projectRoot" | "integrationFolder" >; - preprocessor: IPreprocessorConfiguration; + preprocessor: Pick; }, filepath: string ): string[] {