I have an Angular project with an Nrwl Nx workspace. For my e2e test I use cypress with typescript. For this tests I would like to enable support for Feature files with Gherkin Syntax.
I added the "cypress-cucumber-preprocessor" to the project. This setup works fine when I write the bindings with js. But as soon as I try to setup the steps for typescript I get errors and I can't make it work.
Setup for js:
const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');
const cucumber = require('cypress-cucumber-preprocessor').default;
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
// Code Coverage
on('task', require('@cypress/code-coverage/task'));
// Preprocess Typescript
on('file:preprocessor', preprocessTypescript(config));
// Gherkin support
on('file:preprocessor', cucumber());
};
Setup for ts:
const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');
const cucumber = require('cypress-cucumber-preprocessor').default;
const browserify = require('@cypress/browserify-preprocessor');
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
// Code Coverage
on('task', require('@cypress/code-coverage/task'));
// Preprocess Typescript
on('file:preprocessor', preprocessTypescript(config));
// Gherkin support
const options = browserify.defaultOptions;
options.browserifyOptions.plugin.unshift(['tsify']);
on('file:preprocessor', cucumber());
};
{
"name": "client-app",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"nx": "nx",
"start": "ng serve",
"start:browser": "ng serve -o --port 54055",
"build": "ng build",
"build:ssr": "ng run client-app:server:production",
"test": "ng test",
"lint": "nx workspace-lint && ng lint",
"e2e": "ng e2e",
"e2e:watch": "ng e2e --watch",
"e2e:headless": "ng e2e --prod --headless",
"affected:apps": "nx affected:apps",
"affected:libs": "nx affected:libs",
"affected:build": "nx affected:build",
"affected:e2e": "nx affected:e2e",
"affected:test": "nx affected:test",
"affected:lint": "nx affected:lint",
"affected:dep-graph": "nx affected:dep-graph",
"affected": "nx affected",
"format": "nx format:write",
"format:write": "nx format:write",
"format:check": "nx format:check",
"update": "ng update @nrwl/workspace",
"update:check": "ng update",
"workspace-schematic": "nx workspace-schematic",
"dep-graph": "nx dep-graph",
"help": "nx help",
"extract:clientApp": "ngx-translate-extract --input ./apps/client-app/src --output ./apps/client-app/src/assets/i18n/de.json ./apps/client-app/src/assets/i18n/en.json ./apps/client-app/src/assets/i18n/fr.json ./apps/client-app/src/assets/i18n/it.json --clean --sort",
"extract:clientAppe2e": "ngx-translate-extract --input ./apps/client-app/src --output ./apps/client-app-e2e/src/fixtures/i18n/de.json ./apps/client-app-e2e/src/fixtures/i18n/en.json ./apps/client-app-e2e/src/fixtures/i18n/fr.json ./apps/client-app-e2e/src/fixtures/i18n/it.json --clean --sort"
},
"private": true,
"dependencies": {
"@angular/animations": "^8.0.0",
"@angular/cdk": "^8.1.1",
"@angular/common": "^8.0.0",
"@angular/compiler": "^8.0.0",
"@angular/core": "^8.0.0",
"@angular/flex-layout": "^8.0.0-beta.26",
"@angular/forms": "^8.0.0",
"@angular/material": "^8.1.1",
"@angular/platform-browser": "^8.0.0",
"@angular/platform-browser-dynamic": "^8.0.0",
"@angular/platform-server": "^8.1.3",
"@angular/pwa": "^0.801.2",
"@angular/router": "^8.0.0",
"@angular/service-worker": "^8.0.0",
"@aspnet/signalr": "1.0.3",
"@ngrx/effects": "^8.2.0",
"@ngrx/entity": "^8.2.0",
"@ngrx/router-store": "^8.2.0",
"@ngrx/store": "^8.2.0",
"@nguniversal/module-map-ngfactory-loader": "^8.1.1",
"@ngx-translate/core": "^11.0.1",
"@ngx-translate/http-loader": "^4.0.0",
"@nrwl/angular": "8.4.0",
"@types/file-saver": "^2.0.1",
"applicationinsights-js": "^1.0.20",
"aspnet-prerendering": "^3.0.1",
"core-js": "^2.5.4",
"file-saver": "^2.0.2",
"hammerjs": "^2.0.8",
"ngx-infinite-scroll": "^7.2.0",
"rxjs": "~6.4.0",
"zone.js": "^0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.800.1",
"@angular/cli": "8.1.1",
"@angular/compiler-cli": "^8.0.0",
"@angular/language-service": "^8.0.0",
"@biesbjerg/ngx-translate-extract": "^2.3.4",
"@cypress/code-coverage": "^1.8.0",
"@ngrx/store-devtools": "^8.2.0",
"@nrwl/cypress": "8.4.0",
"@nrwl/jest": "8.4.0",
"@nrwl/linter": "^8.4.1",
"@nrwl/workspace": "8.4.0",
"@types/applicationinsights-js": "^1.0.9",
"@types/cypress-cucumber-preprocessor": "^1.12.0",
"@types/jest": "24.0.9",
"@types/node": "^12.6.8",
"codelyzer": "~5.0.1",
"cypress": "3.4.0",
"cypress-cucumber-preprocessor": "^1.16.0",
"dotenv": "6.2.0",
"istanbul-lib-coverage": "^2.0.5",
"jest": "24.1.0",
"jest-preset-angular": "7.0.0",
"ngrx-store-freeze": "^0.2.4",
"nyc": "^14.1.1",
"prettier": "1.16.4",
"ts-jest": "24.0.0",
"ts-node": "~7.0.0",
"tsify": "^4.0.1",
"tslint": "~5.11.0",
"typescript": "~3.4.5"
},
"cypress-cucumber-preprocessor": {
"nonGlobalStepDefinitions": true
}
}
I have following error with this setup:
SyntaxError: 'import' and 'export' may appear only with 'sourceType: module'
Cypress is a test runner built for the modern web. It has a lot of great features: Time travel. Real-time reloads.
The workspace plugin contains executors and generators that are useful for any Nx workspace. It should be present in every Nx workspace and other plugins build on it.
The cypress-cucumber-preprocessor adds support for using feature files when testing with Cypress. You can follow the documentation below, or if you prefer to hack on a working example, take a look at https://github.com/TheBrainFamily/cypress-cucumber-example.
I've found an article written by Balázs Tápai: I'm in a Pickle - Configuring Gherkin with NX Workspaces. It was for some reason not totally complete but really helpful.
After several hours of sweating and crying, I could have a running example. Read the article and then follow the following steps:
npm i -D cypress-cucumber-preprocessor
Please note that tsify
is not required.
At the root of the nx project, add a file named cypress-cucumber-preprocessor.config.js
The cypress-cucumber-preprocessor
property in package.json
is redundant and should be removed if present.
const path = require("path");
const stepDefinitionsPath = path.resolve(process.cwd(), "./src/integration");
const outputFolder = path.resolve(process.cwd(), "../../cyreport/cucumber-json");
module.exports = {
nonGlobalStepDefinitions: true,
stepDefinitions: stepDefinitionsPath,
commonPath: stepDefinitionsPath, // I added this line, not sure if necessary
cucumberJson: {
generate: true,
outputFolder: outputFolder,
filePrefix: "",
fileSuffix: ".cucumber"
}
};
In the folder integration
of your e2e project:
simple.feature
Feature: Simple test
Simple test feature
@focus
Scenario: I always pass
Given I pass
Then I see "the expected text"
simple.test.ts
import { assert } from 'console';
import { Given, Then } from 'cypress-cucumber-preprocessor/steps';
Given(/I pass/, () => {
console.log('Congrats!');
});
Then('I see {string}', (text: string) => {
console.log(text === 'the expected text');
});
cypress.json
looks like this:{
"fileServerFolder": ".",
"fixturesFolder": "./src/fixtures",
"integrationFolder": "./src/integration",
"modifyObstructiveCode": false,
"pluginsFile": "./src/plugins/index",
"supportFile": "./src/support/index.ts",
"video": true,
"videosFolder": "../../dist/cypress/apps/sandbox-e2e/videos",
"screenshotsFolder": "../../dist/cypress/apps/sandbox-e2e/screenshots",
"chromeWebSecurity": false,
"testFiles": "**/*.{feature,features}"
}
plugins/index.js
This part is slightly different than the one in the article.
const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor');
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
module.exports = (on, config) => {
on('file:preprocessor', preprocessTypescript(config, customizeWebpackConfig));
return config;
}
function customizeWebpackConfig(webPackConfig) {
webPackConfig.node = {
fs: "empty",
child_process: "empty",
readline: "empty",
};
pushFeature(webPackConfig);
pushFeatures(webPackConfig);
return webPackConfig;
}
function pushFeature(webPackConfig) {
pushModuleRule(webPackConfig, /\.feature$/, 'cypress-cucumber-preprocessor/loader');
}
function pushFeatures(webPackConfig) {
pushModuleRule(webPackConfig, /\.features$/, 'cypress-cucumber-preprocessor/lib/featuresLoader');
}
function pushModuleRule(webPackConfig, testRegex, loaderLib) {
webPackConfig.module.rules.push({
test: testRegex,
use: [{ loader: loaderLib }]
});
}
I tried using @cypress/code-coverage
but it does not work. So I removed it from the solution.
The article describe then how to add html report for Business Owner. It is straighforward (if you install for dev chalk
and cucumber-html-reporter
) thus was not not copied here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With