scenario state
Step Forge breaks down overall scenario state into three distinct categories:
- Given state
- When state
- Then state
All three parts of state are immutable, typed independently, kept separate, and have distinct rules about when they can be accessed or modified. However, you control the typing of each part of state. Step Forge just handles the plumbing of state and enforcing the typing when using the parts of the state.
Given state rules
- Given state can be accessed by any step in the scenario
- Given state can only be modified by
Givensteps
When state rules
- When state can only be accessed by
WhenandThensteps - When state can only be modified by
Whensteps
Then state rules
- Then state can only be accessed by
Thensteps - Then state can only be modified by
Thensteps
Note:
Thenstate is rarely used. MostThensteps will read fromWhenstate and then make an assertion.
Setting up state
Scenario state is defined by your World class, which is how Cucumber handles state. Step Forge requires that your World class has separate given, when, and then states associated with it.
Step Forge provides a BasicWorld class that implements the state classes and provides some utilities to make it easier to work with the expected state. See the setting up Cucumber guide for an end-to-end example.
import { BasicWorld } from "@step-forge/step-forge";
export interface GivenState { // define the type of your given state here // this should be a super-set of any states needed by your tests}
export interface WhenState { // define the type of your when state here // this should be a super-set of any states needed by your tests}
export interface ThenState { // define the type of your then state here // this should be a super-set of any states needed by your tests}
export class World extends BasicWorld<GivenState, WhenState, ThenState> {}
setWorldConstructor(World);Modifying state
State can only be modified by the return value of a step function. Each step can only modify the state that matches to it’s section.
givenBuilder<GivenState>() .statement("I have a valid user") .step(() => { // Merges this user object into the given state return { user: { id: "123", name: "John Doe", email: "john.doe@example.com", }, }; });
whenBuilder<GivenState, WhenState>() .statement("I do something with the user") .step(() => { // Merges this transactionId into the when state return { transactionId: "456", }; });Reading state
State scenario state can be accessed by allowed steps with the proper dependencies declared. See the dependencies guide for more information.