Skip to content

Commit

Permalink
Add BeforeAll / AfterAll hooks (#878)
Browse files Browse the repository at this point in the history
  • Loading branch information
charlierudolph committed Jul 26, 2017
1 parent 93df609 commit 9499817
Show file tree
Hide file tree
Showing 17 changed files with 617 additions and 72 deletions.
21 changes: 21 additions & 0 deletions docs/support_files/api_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ Multiple `After` hooks are executed in the **reverse** order that they are defin

---

#### `AfterAll([options,] fn)`

Defines a hook which is run after all scenarios have completed.

* `options`: An object with the following keys:
* `timeout`: A hook-specific timeout, to override the default timeout.
* `fn`: A function, defined as follows:
* When using the asynchronous callback interface, have one argument for the callback function.

Multiple `AfterAll` hooks are executed in the **reverse** order that they are defined.

---

#### `Before([options,] fn)`

Defines a hook which is run before each scenario. Same interface as `After`.
Expand All @@ -68,6 +81,14 @@ Multiple `Before` hooks are executed in the order that they are defined.

---

#### `BeforeAll([options,] fn)`

Defines a hook which is run before all scenarios. Same interface as `AfterAll`.

Multiple `BeforeAll` hooks are executed in the order that they are defined.

---

#### `defineStep(pattern[, options], fn)`

Defines a step.
Expand Down
28 changes: 28 additions & 0 deletions docs/support_files/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,31 @@ defineSupportCode(function({After, Before}) {
```

See more documentation on [tag expressions](https://docs.cucumber.io/tag-expressions/)

## BeforeAll / AfterAll

If you have some setup / teardown that needs to be done before or after all scenarios, use `BeforeAll` / `AfterAll`. Like hooks and steps, these can be synchronous, accept a callback, or return a promise.

```javascript
var {defineSupportCode} = require('cucumber');

defineSupportCode(function({AfterAll, BeforeAll}) {
// Synchronous
BeforeAll(function () {
// perform some shared setup
});

// Asynchronous Callback
BeforeAll(function (callback) {
// perform some shared setup

// execute the callback (optionally passing an error when done)
});

// Asynchronous Promise
AfterAll(function () {
// perform some shared teardown
return Promise.resolve()
});
});
```
251 changes: 251 additions & 0 deletions features/before_after_all_hook_interfaces.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
Feature: before / after all hook interfaces

Rules:
- before / after all hooks can be synchronous, return a promise, or accept a callback

Background:
Given a file named "features/a.feature" with:
"""
Feature: some feature
Scenario: first scenario
Given first step
Scenario: second scenario
Given second step
"""
And a file named "features/step_definitions/my_steps.js" with:
"""
import {defineSupportCode} from 'cucumber'
defineSupportCode(({Given}) => {
Given('first step', function() {})
Given('second step', function() {})
})
"""

Scenario Outline: synchronous
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function() {})
})
"""
When I run cucumber.js
Then it passes

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

Scenario Outline: synchronously throws
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function() {
throw new Error('my error')
})
})
"""
When I run cucumber.js
Then it fails

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

Scenario Outline: callback without error
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function(callback) {
setTimeout(callback)
})
})
"""
When I run cucumber.js
Then it passes

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

Scenario Outline: callback with error
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function(callback) {
setTimeout(() => {
callback(new Error('my error'))
})
})
})
"""
When I run cucumber.js
Then it fails
And the error output contains the text:
"""
my error
"""

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

@spawn
Scenario Outline: callback asynchronously throws
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function(callback) {
setTimeout(() => {
throw new Error('my error')
})
})
})
"""
When I run cucumber.js
Then it fails
And the error output contains the text:
"""
my error
"""

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

Scenario Outline: callback - returning a promise
Given a file named "features/step_definitions/failing_steps.js" with:
"""
import {defineSupportCode} from 'cucumber'
import Promise from 'bluebird'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function(callback) {
return Promise.resolve()
})
})
"""
When I run cucumber.js
Then it fails
And the error output contains the text:
"""
function uses multiple asynchronous interfaces: callback and promise
"""

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

Scenario Outline: promise resolves
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
import Promise from 'bluebird'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function() {
return Promise.resolve()
})
})
"""
When I run cucumber.js
Then it passes

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

Scenario Outline: promise rejects with error
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
import Promise from 'bluebird'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function() {
return Promise.reject(new Error('my error'))
})
})
"""
When I run cucumber.js
Then it fails
And the error output contains the text:
"""
my error
"""

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

Scenario Outline: promise rejects without error
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
import Promise from 'bluebird'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function() {
return Promise.reject()
})
})
"""
When I run cucumber.js
Then it fails
And the error output contains the text:
"""
Promise rejected without a reason
"""

Examples:
| TYPE |
| BeforeAll |
| AfterAll |

@spawn
Scenario Outline: promise asynchronously throws
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'
import Promise from 'bluebird'
defineSupportCode(({<TYPE>}) => {
<TYPE>(function() {
return new Promise(function() {
setTimeout(() => {
throw new Error('my error')
})
})
})
})
"""
When I run cucumber.js
Then it fails
And the error output contains the text:
"""
my error
"""

Examples:
| TYPE |
| BeforeAll |
| AfterAll |
Loading

0 comments on commit 9499817

Please sign in to comment.