Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for cucumber e2e tests #1276

Closed
remkoboschker opened this issue Apr 18, 2019 · 33 comments
Closed

support for cucumber e2e tests #1276

remkoboschker opened this issue Apr 18, 2019 · 33 comments
Labels
outdated scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx type: feature

Comments

@remkoboschker
Copy link

Have you considered / would you consider supporting (or accepting a pr for) running cucumber tests? It would be nice to have schematics to scaffold feature and step definition files and include the configuration required to run cucumber tests using cypress. There is a cypress plugin that seems a good fit https://github.com/TheBrainFamily/cypress-cucumber-preprocessor.

@joelmuskwe
Copy link

Any luck with this when i add cypress-cucumber-preprocessor i get the attached error.
Screenshot 2019-06-18 at 07 14 37

I dont know how possible is it to allow the following ` as per Cypress documentation to enable transpiling TypeScript test files.

@vsavkin vsavkin added the scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx label Dec 5, 2019
@hnryjms
Copy link

hnryjms commented Feb 11, 2020

Hi there....

I was able to find a way to do this:

First, install the cypress-cucumber-preprocessor package:

npm install --save-dev cypress-cucumber-preprocessor
# or
yarn add --dev cypress-cucumber-preprocessor

Next, write an alternative preprocessTypescript() function by modifying your src/plugins/index.js file like so:

const wp = require('@cypress/webpack-preprocessor');
const { getWebpackConfig } = require('@nrwl/cypress/plugins/preprocessor');

function preprocessTypescript(config) {
   if (!config.env.tsConfig) {
       throw new Error(
           'Please provide an absolute path to a tsconfig.json as cypressConfig.env.tsConfig'
       );
   }

   const webpackConfig = getWebpackConfig(config);

   webpackConfig.node = { fs: "empty", child_process: "empty", readline: "empty" };
   webpackConfig.module.rules.push({
       test: /\.feature$/,
       use: [{
           loader: "cypress-cucumber-preprocessor/loader"
       }]
   }, {
       test: /\.features$/,
       use: [{
           loader: "cypress-cucumber-preprocessor/lib/featuresLoader"
       }]
   });

   return async (...args) => wp({
       webpackOptions: webpackConfig
   })(...args);
}

module.exports = (on, config) => {
   // `on` is used to hook into various events Cypress emits
   // `config` is the resolved Cypress config

   // Preprocess Typescript file using Nx helper
   on('file:preprocessor', preprocessTypescript(config));
};

Finally, add a .cypress-cucumber-preprocessorrc file to the root of your repo (or in each -e2e app) with this configuration:

{
    "stepDefinitions": "src/support/step_definitions"
}

Without the updated stepDefinitions configuration, cucumber will continue searching the cypruss/ instead of src/ directory of your -e2e/ folders.


It would be nicer if the built-in preprocessTypescript() function gave us an optional second argument for modifying the Webpack config file, so we wouldn't need to fork the work of that function. That way we wouldn't be duplicating the throw new Error and return async parts of NX.

@hnryjms
Copy link

hnryjms commented Feb 11, 2020

^ Storybook has a paradigm for custom webpack config which may be a good approach here.

@bhavyamathur
Copy link

bhavyamathur commented Feb 24, 2020

@hnryjms I created a similar nx repo and used your suggested cypress cucumber preprocessor plugin configuration, still when I run cypress it creates a cypress folder and tries to find the step definition file in it's new support folder. Can you share how your cypress, package and tsconfig looks like?

@vinayakpatil
Copy link

@hnryjms Your solution worked but I have seen a degradation in the test run times. Have you faced anything like it?

I have already logged a separate issue here: badeball/cypress-cucumber-preprocessor#336

@stahloss
Copy link

@hnryjms Your solution worked, thanks for that.

I'm not able to debug my steps in Cypress though, because the source doesn't seem to be attached. Is that something we could add to the webpack config, or is it a cypress-cucumber-preprocessor issue?

@thinuspainter
Copy link

Can you please get cucumber/gherkin integrated!?

@dbartholomae
Copy link

@hnryjms Do you have an example repo with your solution? Unfortunately I couldn't get it to run :(

@remkoboschker
Copy link
Author

I have it running just fine with:
package.json

   "cypress": "^4.6.0",
        "cypress-cucumber-preprocessor": "^2.3.1",
.....
 "cypress-cucumber-preprocessor": {
        "nonGlobalStepDefinitions": true,
        "stepDefinitions": "./src/integration",
        "cucumberJson": {
            "generate": true,
            "outputFolder": "./cucumber"
        }

/src/plugins/index.js

const { getWebpackConfig } = require('@nrwl/cypress/plugins/preprocessor');
const wp = require('@cypress/webpack-preprocessor');

module.exports = function(on, config) {
    const wpConfig = getWebpackConfig(config);
    wpConfig.node = { fs: 'empty', child_process: 'empty', readline: 'empty' };
    wpConfig.module.rules.push({
        test: /\.feature$/,
        use: [
            {
                loader: 'cypress-cucumber-preprocessor/loader'
            }
        ]
    });
    on('file:preprocessor', wp({ webpackOptions: wpConfig }));
};

cypress.json

{
    "fileServerFolder": "./",
    "fixturesFolder": "./src/fixtures",
    "integrationFolder": "./src/integration",
    "pluginsFile": "./src/plugins/index.js",
    "supportFile": "./src/support/index.ts",
    "video": true,
    "videosFolder": "../../dist/videos",
    "screenshotsFolder": "../../dist/screenshots",
    "chromeWebSecurity": false,
    "testFiles": "**/*.{feature,features}",
    "baseUrl": "https://localhost:4200",
    "ignoreTestFiles": "*.{js,ts}"
}

@huantaoliu
Copy link

huantaoliu commented May 29, 2020

If still doesn't work, this might be your case

  1. you might used custom cypress commands, that nx is not able to support now, this is the work around
    New nx workspace doesn't support custom cypress commands #1609

  2. if you also cypress-cucumber-pre-processor, you might have problem configuring your commonPath
    commonPath property doesn't work badeball/cypress-cucumber-preprocessor#213

@dbartholomae
Copy link

I didn't get the same error, but got it to work in two steps:

  1. I am using TypeScript so I had to include preprocessTypescript in the plugins/index.js function:
const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');

module.exports = function(on, config) {
  on('file:preprocessor', preprocessTypescript(config, (wpConfig) => {
    wpConfig.node = { fs: 'empty', child_process: 'empty', readline: 'empty' };
    wpConfig.module.rules.push({
      test: /\.feature$/,
      use: [{
        loader: 'cypress-cucumber-preprocessor/loader'
      }]
    });
    return wpConfig
  }));
};
  1. With the configuration above the step definitions need to be in src/integration/nameOfFeature/**/* where nameOfFeature is the name of the feature file or common. If you disable nonGlobalStepDefinitions in package.json, step files will be checked directly in src/integration.

@kbradl16
Copy link

kbradl16 commented Nov 13, 2020

@dbartholomae Do you happen to have a working example you can share? I'm not able to get it working with what you have.

I get this error:

ReferenceError: The following error originated from your test code, not from Cypress.

  > require is not defined

When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.

Cypress could not associate this error to any specific test.

We dynamically generated a new test to display this failure.

Check your console for the stack trace or click this message to see where it originated from.
    at Object.eval (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:413:1)
    at __webpack_require__ (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:20:30)
    at Object.eval (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:91:19)
    at __webpack_require__ (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:20:30)
    at Object.eval (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:388:5)
    at __webpack_require__ (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:20:30)
    at Object.eval (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:368:18)
    at __webpack_require__ (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:20:30)
    at eval (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:84:18)
    at eval (http://localhost/__cypress/tests?p=e2e\src\integration\BasePage.feature:87:10)
From previous event:
    at Object.runScripts (http://localhost/__cypress/runner/cypress_runner.js:176237:96)
    at $Cypress.onSpecWindow (http://localhost/__cypress/runner/cypress_runner.js:166148:18)

@dbartholomae
Copy link

Unfortunately not :(

@agborkowski
Copy link

@kbradl16 ill publish the completed integration of NX workspace with angular and cucumber. watch my GitHub profile. cheers

@mattgek
Copy link

mattgek commented Apr 23, 2021

any update on cypress + cucumber in nx ?

@zjkipping
Copy link

Is there any update on this? The above example @dbartholomae listed doesn't work with webpack5 on nx12.3.4, cypress 6.0.1, & cypress-cucumber-preprocessor 4.1.0.

@rkrisztian
Copy link

rkrisztian commented Jun 7, 2021

For Webpack 5

I got a working solution, practically using @dbartholomae 's config, with the same solutions as the ones I googled up before for a regular Angular CLI 12 generated project (without using @nrwl/nx).

My idea was to:

  • let both Cucumber and regular tests be executed (can be handy)
  • have the step definitions inside src/integration (this is the new way recommended by the preprocessor)

Based on that:

  1. Add to cypress.json:
{
  // ...
  "testFiles": "*.{ts,feature,features}",
  "ignoreTestFiles": "**/*.js"
}
  1. Add to package.json:
{
  // ...
  "cypress-cucumber-preprocessor": {
    "nonGlobalStepDefinitions": true,
    "stepDefinitions": "./src/integration"
  }
}
  1. Set up support/index.js like this (I've removed the comments for brevity here, but you keep them if you want):
const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');
const webpack = require('webpack');

module.exports = (on, config) => {
  on('file:preprocessor', preprocessTypescript(config, (wpConfig) => {
    wpConfig.resolve.fallback = {
      ...wpConfig.resolve.fallback,
      'path': require.resolve("path-browserify")
    };
    wpConfig.plugins.push(
      new webpack.ProvidePlugin({
        process: 'process/browser',
      })
    );
    wpConfig.module.rules.push(
      {
        test: /\.feature$/,
        use: [{
          loader: 'cypress-cucumber-preprocessor/loader'
        }]
      },
      {
        test: /\.features$/,
        use: [{
          loader: 'cypress-cucumber-preprocessor/lib/featuresLoader'
        }]
      }
    );
    return wpConfig
  }));
};

@rkrisztian
Copy link

rkrisztian commented Oct 5, 2021

With a more recent version of @nrwl/cypress, you may have seen this message:

preprocessTypescript is now deprecated since Cypress has added typescript support.
If you would still like preprocess files with webpack, use the "@cypress/webpack-preprocessor" package.

That is a problem because we still need a webpack configuration, but now we don't have the help of Nx. According to Nx's preprocessor.ts, getWebpackConfig is not yet deprecated, and still a publicly available function, but something tells me it's going to get removed along with the deprecation, so I don't think the following code should be used to remove the deprecation:

Click to expand the *wrong* solution... Only showing the changes to my previous example code:
diff --git a/path-to-project/src/plugins/index.js b/path-to-project/src/plugins/index.js
index 968157c..d5cc2f2 100644
--- a/path-to-project/src/plugins/index.js
+++ b/path-to-project/src/plugins/index.js
@@ -1,8 +1,11 @@
-const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');
+const webpackPreprocessor = require('@cypress/webpack-preprocessor')
+const { getWebpackConfig } = require('@nrwl/cypress/plugins/preprocessor');
 const webpack = require('webpack');
     
 module.exports = (on, config) => {
-  on('file:preprocessor', preprocessTypescript(config, (wpConfig) => {
+  on('file:preprocessor', webpackPreprocessor((() => {
+    const options = { webpackOptions: getWebpackConfig(config) };
+    const wpConfig = options.webpackOptions;
     wpConfig.resolve.fallback = {
       ...wpConfig.resolve.fallback,
       'path': require.resolve('path-browserify')
@@ -26,6 +29,6 @@ module.exports = (on, config) => {
         }]
       }
     );
-    return wpConfig
-  }));
+    return options;
+  })()));
 };

However, a more future-proof solution may look like this (you might need to install some packages if Nx no longer provides them transitively). Sadly it's quite some code copied out of preprocessor.ts, and I don't know any better, but it works at least:

/// <reference types="cypress" />

const webpackPreprocessor = require('@cypress/webpack-preprocessor')
const webpack = require('webpack');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const nodeExternals = require('webpack-node-externals');

/**
 * @type {Cypress.PluginConfig}
 */
module.exports = (on, config) => {
  on('file:preprocessor', webpackPreprocessor({
    webpackOptions: {
      resolve: {
        extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'],
        plugins: [
          new TsconfigPathsPlugin({
            configFile: config.env.tsConfig,
            extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx']
          }),
        ],
        fallback: {
          'path': require.resolve('path-browserify')
        }
      },
      module: {
        rules: [
          {
            test: /\.([jt])sx?$/,
            loader: 'ts-loader',
            exclude: [/node_modules/],
            options: {
              configFile: config.env.tsConfig,
              // https://github.com/TypeStrong/ts-loader/pull/685
              experimentalWatchApi: true,
              transpileOnly: true
            }
          },
          {
            test: /\.feature$/,
            use: [{
              loader: 'cypress-cucumber-preprocessor/loader'
            }]
          },
          {
            test: /\.features$/,
            use: [{
              loader: 'cypress-cucumber-preprocessor/lib/featuresLoader'
            }]
          }
        ]
      },
      plugins: [
        new ForkTsCheckerWebpackPlugin({
          typescript: {
            enabled: true,
            configFile: config.env.tsConfig,
          },
        }),
        new webpack.ProvidePlugin({
          process: 'process/browser',
        })
      ],
      externals: [nodeExternals()]
    },
  }));
}

Edit: I've checked if we can reuse webpackPreprocessor.defaultOptions but it does not seem true for our use case.

@Yohandah
Copy link

Yohandah commented Oct 6, 2021

What do you think about this config ? It works running cypress run but not nx e2e
I saw somewhere that TS was supported by default for Cypress and we don't need preprocessing anymore

const browserify = require('@cypress/browserify-preprocessor');
const cucumber = require('cypress-cucumber-preprocessor').default;
const resolve = require('resolve');
const fs = require('fs');
const path = require('path');

module.exports = (on, config) => {
  const options = {
    ...browserify.defaultOptions,
    typescript: resolve.sync('typescript', { baseDir: config.projectRoot }),
  };

  on('file:preprocessor', cucumber(options));

  on('task', {
    getSchema() {
      return fs.readFileSync(path.resolve(__dirname, '../../../x/schema.graphql'), 'utf8');
    },
  });

  on('before:browser:launch', (browser = {}, launchOptions) => {
    if (browser.family === 'firefox') {
      // auto open devtools
      launchOptions.args.push('-devtools');
      launchOptions.args.push('-no-remote');
    }
    if (browser.name === 'chrome' && browser.isHeadless) {
      launchOptions.args.push('--disable-gpu');
    }
    // whatever you return here becomes the launchOptions
    return launchOptions;
  });
  config.browsers.push({
    name: 'firefox',
    family: 'firefox',
    channel: 'stable',
    displayName: 'Firefox',
    version: '78.11.0esr',
    path: 'C:/Program Files/Mozilla Firefox/firefox.exe',
    majorVersion: '78',
  });
};

@wrslatz
Copy link
Contributor

wrslatz commented Oct 6, 2021

What do you think about this config ? It works running cypress run but not nx e2e
I saw somewhere that TS was supported by default for Cypress and we don't need preprocessing anymore

I tried the browserify + resolve setup and it works fine for TypeScript but doesn't work for configured paths aliases, which is what we're trying to find a solution for here.

@Yohandah
Copy link

Yohandah commented Oct 6, 2021

What do you think about this config ? It works running cypress run but not nx e2e
I saw somewhere that TS was supported by default for Cypress and we don't need preprocessing anymore

I tried the browserify + resolve setup and it works fine for TypeScript but doesn't work for configured paths aliases, which is what we're trying to find a solution for here.

I thought we were trying to find a solution to use cucumber tests with nx? And I'm using typescript aliases and it works fine as well.
But I can't get it to work with nx cli #7258

@wrslatz
Copy link
Contributor

wrslatz commented Oct 6, 2021

I thought we were trying to find a solution to use cucumber tests with nx?

Yep, sorry you're correct (I've mixed up the GitHub issues). I think that config you showed matches what we have and works fine (when not importing for aliased paths entries). This thread has somewhat split off into figuring out support for importing from paths aliases configured at the root of the repo (maybe should split that out to a separate issue?).

And I'm using typescript aliases and it works fine as well

Could you show how the paths in the root tsconfig.base.json in the Nx repo work with this setup? That's what I can't get working.

@wrslatz
Copy link
Contributor

wrslatz commented Oct 6, 2021

This is our config in src/plugins/index.js that works fine running Cypress e2e tests with Nx except when trying to import from paths aliases (outlined in badeball/cypress-cucumber-preprocessor#537, which I was mixing up with this issue).

  const options = {
    ...browserify.defaultOptions,
    typescript: resolve.sync('typescript', { baseDir: config.projectRoot }),
  };

  on('file:preprocessor', cucumber(options));

I've noticed this setup is pretty slow for us (takes >10 seconds just to load a handful of .feature files). I wonder if the tests hang for larger repositories.

@rkrisztian
Copy link

@Yohandah , @wrslatz , thanks, I'll try this in the near future. If I really don't need Webpack, I like the elegance of it so far. :)

@rkrisztian
Copy link

rkrisztian commented Oct 7, 2021

OK, I've tested the browserify way, and I could reproduce both problems:

  • Tests run 25% slower (to be fair, quite some feature tests are not implemented yet).
  • paths stopped working.

@wrslatz
Copy link
Contributor

wrslatz commented Oct 7, 2021

OK, I've tested the browserify way, and I could reproduce both problems:

I'll see if I can get the custom Webpack setup you shared working correctly.

Then from there we could follow up with some combo of nx, Cypress Webpack, or cypress-cucumber-preprocessor to implement the best support path going forward? I'd be fine using Webpack, but hopefully the config mostly just works out of the box with the cypress-cucumber-preprocessor webpack way.

@m-risto
Copy link

m-risto commented Oct 12, 2021

Hey guys. I have the same problem with cypres cucumber and paths. Did you find a solution, where all 3 of them work? And do you still use the nx preprocessor?

@rkrisztian
Copy link

rkrisztian commented Oct 12, 2021

@mristo , a summary for you:

@kerry-afs
Copy link

@wrslatz I was able to get Cypress-Cucumber-Preprocessor to work well with Nx using the above mentioned Webpack 5 configuration from @rkrisztian, but I am running into the paths issue noted here: badeball/cypress-cucumber-preprocessor#537

Were you able to get around your paths issue? I was able to temporarily bypass it by using relative paths, but now that I'm trying to leverage some of my application's data models (that reference other models via aliases), I'm not able to get past it.

This is a massive impediment and I can't seem to get through. Any insight is greatly appreciated!

@oburakevych
Copy link

Why is this closed? I still cannot run Cypress + Cucumber with nx v.13.2.1. I tried all of the outlined solutions here and none of them works.
Getting following errors: Error: Webpack Compilation Error Module build failed (from ../../node_modules/ts-loader/index.js): TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined at handle (/Users/ube1/projects/apac-core/node_modules/@cypress/webpack-preprocessor/dist/index.js:176:23) at finalCallback (/Users/ube1/projects/apac-core/node_modules/webpack/lib/Compiler.js:434:32) at /Users/ube1/projects/apac-core/node_modules/webpack/lib/Compiler.js:498:17

@wrslatz
Copy link
Contributor

wrslatz commented Feb 22, 2022

The custom webpack config in #1276 (comment) along with merging the tsconfig.e2e.json into tsconfig.json as described in #6917 (comment) fixed loading paths for us 🎉 (sorry for the delay in getting back to y'all)

zjkipping added a commit to zjkipping/ngrx-cypress-nx13 that referenced this issue Mar 9, 2022
@zauni
Copy link

zauni commented Aug 2, 2022

Just adding it here if anyone comes to this thread later. With the new @badeball/cypress-cucumber-preprocessor you can simplify the configuration in the plugins/index.js file.

First you have to install the dependencies:
npm install --save-dev @badeball/cypress-cucumber-preprocessor @bahmutov/cypress-esbuild-preprocessor

Then you can add to your plugins/index.js file:

/** @see https://on.cypress.io/plugins-guide */
const createBundler = require('@bahmutov/cypress-esbuild-preprocessor');
const {
  createEsbuildPlugin,
} = require('@badeball/cypress-cucumber-preprocessor/esbuild');
const {
  addCucumberPreprocessorPlugin,
} = require('@badeball/cypress-cucumber-preprocessor');

/// <reference types="cypress" />

/**
 * @type {Cypress.PluginConfig}
 */
module.exports = async (on, config) => {
  await addCucumberPreprocessorPlugin(on, config);

  on(
    'file:preprocessor',
    createBundler({
      plugins: [createEsbuildPlugin(config)],
    })
  );

  return config;
};

You also have to change your config, for example in .cypress-cucumber-preprocessorrc.json:

{
-  "nonGlobalStepDefinitions": true,
-  "stepDefinitions": "./src/integration",
-  "commonPath": "./src/integration/common"
+  "stepDefinitions": [
+    "./src/integration/[filepath]/**/*.ts",
+    "./src/integration/common/*.ts"
+  ]
}

Then you also need to change all imports in your spec files:

- import { When } from 'cypress-cucumber-preprocessor/steps';
+ import { When } from '@badeball/cypress-cucumber-preprocessor';

But please be aware that with the esbuild based preprocessor you can not use Node.js APIs in your spec files or in your support files. In my case I had to replace my calls to the path lib. For example I used the path.join and path.basename calls. Probably webpack is using a shim for the Node.js libraries, but esbuild is not adding them.
If you need Node.js libraries or just want to stick to webpack, the preprocessor also offers this. Please see here.

One thing I also changed was to merge the tsconfigs in the e2e project into one tsconfig.json file and removing the "tsConfig" configuration in angular.json (or project.json) for the @nrwl/cypress:cypress builder/executor.

@github-actions
Copy link

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx type: feature
Projects
None yet
Development

No branches or pull requests