Skip to content

Commit

Permalink
Allow features in arbitrary locations
Browse files Browse the repository at this point in the history
This fixes #1225 [1].

[1] #1225
  • Loading branch information
badeball committed Sep 26, 2024
1 parent c226178 commit ab68362
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 27 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ Other changees:

- Support project directories containing square brackets, EG. `/home/[foo] my project/`, relates to [#1196](https://github.com/badeball/cypress-cucumber-preprocessor/discussions/1196).

- Allow features in arbitrary locations, fixes [#1225](https://github.com/badeball/cypress-cucumber-preprocessor/issues/1225).

## v20.1.2

- Updated all dependencies, including esbuild, relates to [#1068](https://github.com/badeball/cypress-cucumber-preprocessor/issues/1068).
Expand Down
35 changes: 34 additions & 1 deletion docs/step-definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Step definitions

Step definitions are resolved using search paths that are configurable through the `stepDefinitions` property. The preprocessor uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig), which means you can place configuration options in EG. `.cypress-cucumber-preprocessorrc.json` or `package.json`. The default search paths are shown below.
Step definitions are resolved using search paths that are configurable through the `stepDefinitions` property. The preprocessor uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig), which means you can place configuration options in EG. `.cypress-cucumber-preprocessorrc.json` or `package.json`. The default (almost true[^1]) search paths are shown below.

```json
{
Expand Down Expand Up @@ -147,3 +147,36 @@ All of these will be used to replace `[filepart]`. Thus, a single configuration
The library makes use of [glob](https://github.com/isaacs/node-glob) to turn patterns into a list of files. This has some implications, explained below (list is non-exhaustive and will be expanded on demand).

* Single term inside braces, EG. `foo/bar.{js}`, doesn't work as you might expect, ref. https://github.com/isaacs/node-glob/issues/434.

[^1]: I claim that the default configuration is of that below and this is almost always true.

```json
{
"stepDefinitions": [
"cypress/e2e/[filepath]/**/*.{js,ts}",
"cypress/e2e/[filepath].{js,ts}",
"cypress/support/step_definitions/**/*.{js,ts}",
]
}
```

The reality is a bit more complex, in order to support a variety of use-cases out-of-the-box.
Most users will place their feature files in `cypress/e2e` and in those cases, the default
configuration will be that of my claim.

However, users that decide on a different location, let's say. `cypress/features` - in their
case, the default behavior of the preprocessor will be _as if_ you configured `stepDefinitions`
shown like below.

```json
{
"stepDefinitions": [
"cypress/features/[filepath]/**/*.{js,ts}",
"cypress/features/[filepath].{js,ts}",
"cypress/support/step_definitions/**/*.{js,ts}",
]
}
```

Essentially, the first part of the two first elements, is determined finding out the common
ancestor path of all your feature files and thus the default configuration is dynamic.
26 changes: 6 additions & 20 deletions lib/step-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import util from "util";

import assert from "assert";

import isPathInside from "is-path-inside";

import debug from "./helpers/debug";

import {
Expand Down Expand Up @@ -55,27 +53,15 @@ export function pathParts(relativePath: string): string[] {
}

export function getStepDefinitionPatterns(
configuration: {
cypress: Pick<ICypressRuntimeConfiguration, "projectRoot">;
preprocessor: Pick<
IPreprocessorConfiguration,
"stepDefinitions" | "implicitIntegrationFolder"
>;
},
configuration: Pick<
IPreprocessorConfiguration,
"stepDefinitions" | "implicitIntegrationFolder"
>,
filepath: string,
): string[] {
const projectRoot = configuration.cypress.projectRoot;

if (!isPathInside(filepath, projectRoot)) {
throw new Error(`${filepath} is not inside ${projectRoot}`);
}

const filepathReplacement = glob.escape(
trimFeatureExtension(
path.relative(
configuration.preprocessor.implicitIntegrationFolder,
filepath,
),
path.relative(configuration.implicitIntegrationFolder, filepath),
),
{ windowsPathsNoEscape: true },
);
Expand All @@ -86,7 +72,7 @@ export function getStepDefinitionPatterns(

debug(`replacing [filepart] with ${util.inspect(parts)}`);

const stepDefinitions = [configuration.preprocessor.stepDefinitions].flat();
const stepDefinitions = [configuration.stepDefinitions].flat();

return stepDefinitions.flatMap((pattern) => {
if (pattern.includes("[filepath]") && pattern.includes("[filepart]")) {
Expand Down
7 changes: 2 additions & 5 deletions lib/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,11 @@ export async function compile(
const { stepDefinitions } = preprocessor;

debug(
`resolving step definitions using template(s) ${inspect(stepDefinitions)}`,
`resolving step definitio|ns using template(s) ${inspect(stepDefinitions)}`,
);

const stepDefinitionPatterns = getStepDefinitionPatterns(
{
cypress: configuration,
preprocessor,
},
preprocessor,
uri,
).map((pattern) => ensureIsRelative(configuration.projectRoot, pattern));

Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
"error-stack-parser": "^2.1.4",
"find-cypress-specs": "^1.45.2",
"glob": "^10.4.5",
"is-path-inside": "^3.0.3",
"mocha": "^10.7.0",
"seedrandom": "^3.0.5",
"source-map": "^0.7.4",
Expand Down

0 comments on commit ab68362

Please sign in to comment.