Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to imperatively skip scenario Fixes #873 #912

Merged
merged 6 commits into from
Sep 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 17 additions & 1 deletion docs/support_files/hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,25 @@ defineSupportCode(function({After, Before}) {

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

## Skipping in a Before Hook

If you need to imperatively skip a test using a `Before` hook, this can be done using any of the constructs defined in [skipped steps](./step_definitions.md)

This includes using: a synchronous return, an asynchronous callback, or an asynchronous promise

```javascript
defineSupportCode(({After, Before}) => {
// Synchronous
Before(function() {
// perform some runtime check to decide whether to skip the proceeding scenario
return 'skipped'
});
});
```

## 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.
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.

Unlike `Before` / `After` these methods will not have a world instance as `this`. This is becauce each scenario gets its own world instance and these hooks run before / after **all** scenarios.

Expand Down
11 changes: 11 additions & 0 deletions docs/support_files/step_definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,14 @@ Each interface has its own way of marking a step as pending
* synchronous - return `'pending'`
* asynchronous callback - execute the callback with `null, 'pending'`
* asynchronous promise - promise resolves to `'pending'`

## Skipped steps

Marking a step as skipped will also mark the proceeding steps of the same scenario as skipped.

This can be used to mark a scenario as skipped based on a runtime condition.

Each interface has its own way of marking a step as skipped
* synchronous - return `'skipped'`
* asynchronous callback - execute the callback with `null, 'skipped'`
* asynchronous promise - promise resolves to `'skipped'`
90 changes: 90 additions & 0 deletions features/skipped_steps.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
Feature: Skipped steps

Using this feature, a scenario can be imperatively 'skipped'.

For example, skipping in a `Given` step will mark the following steps of the same scenario as skipped.

There are three methods of skipping. One for synchronous steps, one for an asynchronous callback, and one for an asynchronous promise.

Background:
Given a file named "features/skipped.feature" with:
"""
Feature: a feature
Scenario: a scenario
Given a skipped step
"""

Scenario: Synchronous skipped step
Given a file named "features/step_definitions/skipped_steps.js" with:
"""
import {defineSupportCode} from 'cucumber'

defineSupportCode(({Given}) => {
Given(/^a skipped step$/, function() {
return 'skipped'
})
})
"""
When I run cucumber.js
Then it passes
And the step "a skipped step" has status "skipped"


Scenario: Callback skipped step
Given a file named "features/step_definitions/skipped_steps.js" with:
"""
import {defineSupportCode} from 'cucumber'

defineSupportCode(({Given}) => {
Given(/^a skipped step$/, function(callback) {
callback(null, 'skipped')
})
})
"""
When I run cucumber.js
Then it passes
And the step "a skipped step" has status "skipped"

Scenario: Promise skipped step
Given a file named "features/step_definitions/skipped_steps.js" with:
"""
import {defineSupportCode} from 'cucumber'

defineSupportCode(({Given}) => {
Given(/^a skipped step$/, function(){
return {
then: function(onResolve, onReject) {
setTimeout(function() {
onResolve('skipped')
})
}
}
})
})
"""
When I run cucumber.js
Then it passes
And the step "a skipped step" has status "skipped"

Scenario: Hook skipped scenario steps
Given a file named "features/support/hooks.js" with:
"""
import {defineSupportCode} from 'cucumber'

defineSupportCode(({After, Before}) => {
Before(function() {return 'skipped'})
})
"""
And a file named "features/step_definitions/skipped_steps.js" with:
"""
import {defineSupportCode} from 'cucumber'

defineSupportCode(({Given}) => {
Given(/^a skipped step$/, function() {
var a = 1;
})
})
"""
When I run cucumber.js
Then it passes
And the step "a skipped step" has status "skipped"
4 changes: 3 additions & 1 deletion src/runtime/step_runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ async function run({

const testStepResult = { duration: endTiming() }

if (result === 'pending') {
if (result === 'skipped') {
testStepResult.status = Status.SKIPPED
} else if (result === 'pending') {
testStepResult.status = Status.PENDING
} else if (error) {
testStepResult.exception = error
Expand Down