---
title: "How it works"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{How it works}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

When `cucumber::test` is called, it scans for the feature files in the `features_dir` directory. It parses the feature files and runs the step implementations one by one, according to their order in feature files.

## Step execution order

Given such a feature file:

```gherkin
# tests/testthat/sum.feature
Feature: Sum
  Scenario: Sum should work for 2 numbers
    Given I have 1
    And I have 2
    When I add them
    Then I get 3

  Scenario: Sum should work for 3 numbers
    Given I have 1
    And I have 2
    But I have 3
    When I add them
    Then I get 6
```

And such step definitions:

```r
# tests/testthat/steps/steps_definitions.R
given("I have {int}", function(int, context) {
  print("given")
  context$numbers <- c(context$numbers, int)
})

when("I add them", function(context) {
  print("when")
  context$result <- sum(context$numbers)
})

then("I get {int}", function(int, context) {
  print("then")
  expect_equal(context$result, int)
})
```

The order of calling the steps would be:

```r
> [1] "given"
> [1] "given"
> [1] "when"
> [1] "then"
> [1] "given"
> [1] "given"
> [1] "given"
> [1] "when"
> [1] "then"
```

Notice how the feature file uses `And` and `But` keywords. They are used to continue the previous step. In the example above, `And` and `But` are used to continue the previous `Given` step, they're matched against the `given` step definition. You can use `And` and `But` to continue the previous `When` and `Then` steps as well.

When a `Scenario` is run, the `context` environment is reset so that the state doesn't leak to other scenario.

## How step definitions are loaded

You don't have to load step implementations manually. Cucumber loads them automatically when `cucumber::test` is called.

If you don't want them to be loaded automatically, you can use `steps_loader` argument to provide your own step loader function. See [inst/examples/custom_step_loader](https://github.com/jakubsob/cucumber/blob/main/inst/examples/custom_steps_loader/tests/testthat/test-cucumber.R)

Steps from feature files are matched against step definitions defined with `cucumber::given`, `cucumber::when`, and `cucumber::then` functions using regular expressions.

When you define a step by calling any of the step functions, you register that step, making it available for the tests.
