Provides 'specflow' like bindings for CucumberJS 12.2.0 in TypeScript 5.9+.
npm install @lynxwall/cucumber-tsflow!CI
and blocks. Vue SFC blocks are disabled by default. However, when testing Vue components from a compiled library, styles can be enabled with the enableVueStyle configuration setting.
bash
npm install @lynxwall/cucumber-tsflow --save-dev
`
#### pnpm
`bash
pnpm add @lynxwall/cucumber-tsflow --save-dev
`
#### yarn
`bash
yarn add --dev @lynxwall/cucumber-tsflow
`
Note: Latest updates with context management requires use of cucumber-tsflow to execute tests. As a result, you do not need to install @cucumber/cucumber. All necessary cucumber packages are installed as dependencies of cucumber-tsflow. If you do have @cucumber/cucumber in dependencies please remove the reference to avoid conflicts.
$3
By default, Cucumber-JS looks for .feature files in a folder called 'features', so create that folder and then create a new file called 'my_feature.feature':
`gherkin
features/my_feature.feature
Feature: Example Feature
This is an example feature
Scenario: Adding two numbers
Given I enter 2 and 8
When checking the results
Then I receive the result 10
`
$3
Note: Cucumber-JS refers to any files that are used to implement tests (step definitions) along with any fixtures or utilities used in your tests as Support Files. As a result, any time you see references to support files or support code it is referring to test code.
By default, Cucumber-JS looks for support files beneath the 'features' folder. You can override this on the cucumber-tsflow command line by specifying the '-r' option. However, let's work with the default and create our code in the default location. We need to write step definitions to support the three steps that we created above.
Create a new 'ArithmeticSteps.ts' file:
`javascript
// features/ArithmeticSteps.ts
import { binding, given, then } from "@lynxwall/cucumber-tsflow";
@binding()
export default class ArithmeticSteps {
private computedResult = 0;
@given('I enter {int} and {int}')
iEnterintAndint(int: number, int2: number): any {
this.computedResult = int + int2;
}
@when('checking the results')
checkingTheResults(): any {
expect(this.computedResult).to.be.greaterThan(0);
}
@then('I receive the result {int}')
iReceiveTheResultint(int: number): any {
if (int !== this.computedResult) {
throw new Error('Arithmetic Error');
}
}
}
`
Note: how the cucumber-tsflow Decorators are being used to bind the methods in the class. During runtime, these Decorators simply call the Cucumber code on your behalf in order to register callbacks with Given(), When(), Then(), etc. The callbacks that are being registered with Cucumber are wrappers around your bound class.
$3
All support code, which includes your step definition files along with any test fixtures, utilities and references to source code are transpiled on the fly using transpilers that are included with cucumber-tsflow. This eliminates the requirement to prebuild any test code along with associated management of those builds.
If not using one of the transpilers listed below you'll need to implement your own transpiler using guidance found in Cucumber-JS documentation: Transpiling
Transpilers and TypeScript
Cucumber-tsflow provides several transpilers that can be used in your configuration. However, you are not required to use them. If a different configuration or transpiler is needed you can copy code from one of the provided transpilers.
This section focuses on the configuration used to transpile your test code, and any dependencies, into JavaScript that is executed within the Cucumber-JS test runner.
$3
As of version 7.3.0, cucumber-tsflow supports projects written in both CommonJS & ESM.
Read more about cucumber-tsflow ESM implementations.
$3
There are two different bundlers, or transpilers, used in cucumber-tsflow: ts-node and esbuild. This section covers the typescript configuration used for each bundler. Included with cucumber-ts are six variations of these transpilers used to support different types of projects. However, there are only two variations of typescript configurations used for each bundler, one that uses official decorators and one that uses experimental decorators.
#### ts-node
The following typescript configuration is used in the ts-node transpilers configured for official decorators:
`typescript
compilerOptions: {
module: 'nodeNext',
target: 'es2022',
strict: true,
allowJs: true,
allowSyntheticDefaultImports: true,
esModuleInterop: true,
experimentalDecorators: false,
resolveJsonModule: true,
skipLibCheck: true,
lib: ['es2022', 'esnext.decorators']
}
`
This next typescript configuration is used in the ts-node transpilers configured for official decorators:
`typescript
compilerOptions: {
module: 'nodeNext',
target: 'es2022',
strict: true,
allowJs: true,
allowSyntheticDefaultImports: true,
esModuleInterop: true,
experimentalDecorators: true,
resolveJsonModule: true,
skipLibCheck: true,
lib: ['es2022']
}
`
As you can see the only difference is the setting for experimentalDecorators and the lib imports.
When test runs are started, the settings from your local tsconfig.json are loaded first and then the settings from the transpiler will override the specific settings shown above. As a result, you should use these transpilers in projects that will support these settings.
For example, the settings from the cucumber-tsflow vue test project is shown below:
`json
"compilerOptions": {
"baseUrl": ".",
"module": "nodeNext",
"target": "es2022",
"strict": true,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"lib": ["es2022", "esnext.decorators"],
"typeRoots": ["../../node_modules/@types"]
}
`
These settings are similar to the default transpiler settings, which will not cause an issue.
$3
Note: The esbuild transpilers do not use compilerOptions from tsconfig. Instead, all of the options are configured within the esbuild module that's included with cucumber-tsflow.
Cucumber-tsflow provides two esbuild transpilers: one with esbuild and support for Vue using the vue-sfc transpiler, and another that only uses the esbuild transpiler. Both cucumber-tsflow transpilers use the same esbuild transpiler, which uses the following Common set of options:
`typescript
const commonOptions: CommonOptions = {
format: 'cjs',
logLevel: 'info',
target: [es2022],
minify: false,
sourcemap: 'external'
};
`
As you can see, this also uses the same target as the typescript configuration. In addition, minify is set to false, which makes it easy to debug and step into code when running tests.
In order to support both official and experimental decorators the esbuild transpiler will use different configurations based on the experimentalDecorators flag in the cucumber configuration.
#### Official Decorators
When using official decorators the following settings are added using the esbuild tsconfigRaw setting.
`typescript
commonOptions.tsconfigRaw = {
compilerOptions: {
importsNotUsedAsValues: 'remove',
strict: true
}
};
`
#### Experimental Decorators
When using experimental decorators the experimentalDecorators setting is added to the tsconfigRaw settings. As mentioned, esbuild does not use tsconfig settings from ts-node or from a tsconfig file. As a result, this is the only option available to turn on experimental decorators when using esbuild.
`typescript
commonOptions.tsconfigRaw = {
compilerOptions: {
experimentalDecorators: true,
importsNotUsedAsValues: 'remove',
strict: true
}
};
`
As mentioned at the beginning of this section, there are several transpilers provided, which can be used with your test project. The transpilers section below provides information on how to configure your project to use one of these transpilers.
Cucumber-tsflow Test Runner
As mentioned previously, with recent updates cucumber-tsflow must be used to execute tests. The reason for this update was to replace before and after hooks previously used to manage context with a message handler. Executing tests with cucumber-tsflow uses the same API calls that cucumber-js does. The only differences are updates to support new configuration parameters along with updates to step definitions that set the correct location.
The following example demonstrates executing cucumber-tsflow from the command line to execute tests:
`bash
C:\GitHub\cucumber-js-tsflow\cucumber-tsflow-specs\node (dev-0525 -> origin)
λ npx cucumber-tsflow -p esnode
Loading configuration from "cucumber.json".
Running Cucumber-TsFlow in Serial mode.
beforeAll was called
......................@basic after hook is called.
.......@basic after hook is called.
.......@basic after hook is called.
.......................................@tags1 after hook is called.
......@tagging afterTag method is called
.afterAll was called
15 scenarios (15 passed)
44 steps (44 passed)
0m00.072s (executing steps: 0m00.013s)
`
To recap, cucumber-tsflow extends cucumber-js, which means that all options and features provided by cucumber-js are supported with cucumber-tsflow. In other words, when executing tests using cucumber-tsflow the underlying cucumber API is actually used to run the tests.
$3
You can also add a script to package.json to execute the tests as shown below:
`json
"scripts": {
"test": "cucumber-tsflow -p esnode"
}
`
With this script in place you can execute the tests using npm, pnpm or yarn,
npm
`bash
npm run test
`
pnpm
`bash
pnpm test
`
yarn
`bash
yarn test
`
Note: When executing cucumber-tsflow using scripts in package.json you will not have access to the exit code. This is due to the way that scripts are handled by package managers. If the command exit code is anything greater than 0, these scripts will always return 1. In other words, the commands shown above will return 0 or 1 regardless of the exit code returned from cucumber-tsflow.
$3
When executing tests as part of Continuous Integration (CI) operations you should use the following command to execute the tests from the folder that contains your cucumber and Typescript (tsconfig) configuration files that are associated with tests you want to execute.
`bash
npx cucumber-tsflow -p default
`
This will allow you to access the exit code that is returned from cucumber-tsflow.
cmd shell
`bash
echo %errorlevel%
`
powershell
`bash
echo $LastExitCode
`
bash
`bash
echo $?
`
New Configuration options
As mentioned, when using cucumber-tsflow to execute tests all of the configuration options documented here are supported:
In addition to cucumber configuration options the following two options have been added:
| Name | Type | Repeatable | CLI Option | Description | Default |
| ------------------------ | --------- | ---------- | --------------------------- | ------------------------------------------------------------ | ------- |
| transpiler | string | No | --transpiler | Name of the transpiler to use: es-vue, ts-vue, es-node, ts-node, es-vue-esm, es-node-esm, ts-vue-esm, ts-node-esm | none |
| debugFile | string | No | --debug-file | Path to a file with steps for debugging | |
| enableVueStyle | boolean | No | --enable-vue-style | Enable Vue