Gherkin feature files for Jest.
This project is a re-imagining of Gherkin features for JavaScript, based on lessons learned from writing and consuming specification-based test libraries for many languages.
The project was started by copying the specifications from TypeSpec (which I wrote for TypeScript).
The idea is to use Jest to provide the test goodies, but allow Gherkin specifications to drive the tests.
There are three files:
- A specification file written in Gherkin
- A step file that runs each step
- A Jest test that wraps the specification
Calculator.feature
Feature: Basic Working Example
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers
Scenario: Basic Example with Calculator
Given I am using a calculator
And I enter 50 into the calculator
And I enter 70 into the calculator
When I press the total button
Then the result should be 120 on the screen
The step file exports a steps
function that maps each sentence to a processor function. The processor function always takes the test context
as the first argument (and returns the context
at the end).
If you have arguments in your specification, they are passed after the context
.
calculator.steps.mjs
import { Calculator } from '../../sample/calculator.mjs';
export function steps(map) {
map(/I am using a calculator$/i, (context) => {
context.calculator = new Calculator();
return context;
});
map(/I enter (\d+) into the calculator$/i, (context, number) => {
context.calculator.add(number);
return context;
});
map(/I press the total button$/gi, (context) => {
context.total = context.calculator.getTotal();
return context;
});
map(/the result should be (\d+) on the screen$/i, (context, expected) => {
expected = parseInt(expected, 10);
expect(context.total).toBe(expected);
return context;
});
}
The Jest test in a file such as calculator.test.mjs
import { JestSpec } from 'jest-spec';
import * as CalculatorSteps from './steps/calculator.steps.mjs';
const spec = new JestSpec();
spec.addSteps(CalculatorSteps);
test('Async steps', async () => {
await spec.run('/src/specifications/AsyncSteps.feature');
});
JestSpec works with most JavaScript test frameworks.
The example is based on running specifications within Jest, but in practice, you can use other test frameworks to wrap your specifications. Just use the appropriate assertions in your step files and the relevant test code to wrap the await spec.run
call.
JestSpec will warn you if you have a missing step and supplies a code snippet to get you started:
console.error
Missing step. Consider adding code:
map(/the result should be (\"\d+\") on the screen$/i, (context, p0) => {
context.calculator = new Calculator();
return context;
});
The step code will contain regular expressions for any quoted variables, but if you aren't quoting variables, you can replace hard-coded values with:
- String:
(.*)
- Number:
(\d+)
- Boolean:
(true|false)
We recommend you quote string variables, as the matching can be too general with no quotes. You might choose to quote all your variables, as the auto-generated steps will then be ready to use!
Scenario outlines are supported. Tables are forgiving to whether you include the divider between the header and body of the table (|---|---|---|
), the first row will be used as the header where it is left out.
Feature: Scenario Outline
In order to make features less verbose
As a BDD enthusiast
I want to use scenario outlines with tables of examples
Scenario Outline: Basic Example with Calculator
Given I am using a calculator
And I enter <Number 1> into the calculator
And I enter <Number 2> into the calculator
When I press the total button
Then the result should be <Total> on the screen
Examples:
| Number 1 | Number 2 | Total |
|----------|----------|-------|
| 1 | 1 | 2 |
| 1 | 2 | 3 |
| 2 | 3 | 5 |
| 8 | 3 | 11 |
| 9 | 8 | 17 |