Skip to content

Commit

Permalink
Document AfterFeatures event (close #171)
Browse files Browse the repository at this point in the history
I spent ages doing the wrong setup for AfterFeatures to try and close my browser at the end of the tests, so I thought that including a test and better documentation might help other people.

This also fixes the unimplemented cli.feature step, and failing assert due to console coloring.

I had to apply the patch from comments in #120 to get these tests to run correctly.

Conflicts:
	bin/cucumber.js
	features/cli.feature
	features/step_definitions/cli_steps.js
  • Loading branch information
eddiefletchernz authored and jbpros committed Jun 30, 2014
1 parent 745c40d commit ca9bea3
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 5 deletions.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,37 @@ var myAfterHooks = function () {
module.exports = myAfterHooks;
```

##### After features event
The *after features event* is emitted once all features have been executed, just before the process exits. It can be used for tasks such as closing your browser after running automated browser tests with [selenium](https://code.google.com/p/selenium/wiki/WebDriverJs) or [phantomjs](http://phantomjs.org/).

note: There are "Before" and "After" events for each of the following: "Features", "Feature", "Scenario", "Step" as well as the standalone events "Background" and "StepResult". e.g. "BeforeScenario".

```javascript
// features/support/world.js
var webdriver = require("selenium-webdriver");

var World = function World(callback) {
this.driver = new webdriver.Builder().
withCapabilities(webdriver.Capabilities.chrome()).
build();

callback();
}

module.exports = World;

// features/support/after_hooks.js
var myAfterHooks = function () {
this.registerHandler('AfterFeatures', function (event, callback) {
this.driver.close();
callback();
});
}

module.exports = myAfterHooks;
```


##### Around hooks

It's also possible to combine both before and after hooks in one single definition with the help of *around hooks*:
Expand Down
83 changes: 83 additions & 0 deletions features/cli.feature
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,86 @@ Feature: Command line interface
Scenario: display help (short flag)
When I run `cucumber.js -h`
Then I see the help of Cucumber

Scenario: run a single failing feature
Given a file named "features/a.feature" with:
"""
Feature: some feature
Scenario:
When a step is failing
"""
And a file named "features/step_definitions/cucumber_steps.js" with:
"""
var cucumberSteps = function() {
this.When(/^a step is failing$/, function(callback) { callback("forced error"); });
};
module.exports = cucumberSteps;
"""
When I run `cucumber.js features/a.feature`
Then it should fail with:
"""
1 scenario (1 failed)
1 step (1 failed)
"""
And it should exit with code "1"


Scenario: run a single failing feature with an empty hooks file
Given a file named "features/a.feature" with:
"""
Feature: some feature
Scenario:
When a step is failing
"""
And a file named "features/step_definitions/cucumber_steps.js" with:
"""
var cucumberSteps = function() {
this.When(/^a step is failing$/, function(callback) { callback("forced error"); });
};
module.exports = cucumberSteps;
"""
And a file named "features/support/hooks.js" with:
"""
"""
When I run `cucumber.js features/a.feature`
Then it should fail with:
"""
1 scenario (1 failed)
1 step (1 failed)
"""
And it should exit with code "1"


Scenario: run a single failing feature with an AfterFeatures hook
Given a file named "features/a.feature" with:
"""
Feature: some feature
Scenario:
When a step is failing
"""
And a file named "features/step_definitions/cucumber_steps.js" with:
"""
var cucumberSteps = function() {
this.When(/^a step is failing$/, function(callback) { callback("forced error"); });
};
module.exports = cucumberSteps;
"""
And a file named "features/support/hooks.js" with:
"""
var hooks = function() {
this.registerHandler('AfterFeatures', function (event, callback) {
callback();
});
};
module.exports = hooks;
"""
When I run `cucumber.js features/a.feature`
Then it should fail with:
"""
1 scenario (1 failed)
1 step (1 failed)
"""
And it should exit with code "1"
32 changes: 27 additions & 5 deletions features/step_definitions/cli_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,40 @@ var cliSteps = function cliSteps() {
});
});

this.Then(/^it should pass with:$/, function(expectedOutput, callback) {
this.Then(/^it should (pass|fail) with:$/, function (passOrFail, expectedOutput, callback) {
var actualOutput = lastRun['stdout'];
var actualError = lastRun['error'];
var actualError = lastRun['error'];
var actualStderr = lastRun['stderr'];
function cleanString(str) {
//Strips colour codes and normalise line endings

if (actualOutput == actualError)
return str
.replace(/\033\[[0-9;]*m/g, '')
.replace(/\r\n|\r/g, "\n");
};

actualOutput = cleanString(actualOutput);
expectedOutput = cleanString(expectedOutput);

if (actualOutput.indexOf(expectedOutput) === -1) {
throw new Error("Expected output to match the following:\n'" + expectedOutput + "'\nGot:\n'" + actualOutput + "'.\n" +
"Error:\n'" + actualError + "'.\n" +
"stderr:\n'" + actualStderr +"'.");
"Error:\n'" + actualError + "'.\n" +
"stderr:\n'" + actualStderr + "'.");
}

callback();
});

this.Then(/^it should exit with code "([^"]*)"$/, function (code, callback) {
var actualCode = lastRun['error'] ? lastRun['error'].code : "0";

if (actualCode != code) {
throw new Error("Exit code expected: \"" + code + "\"\nGot: \"" + actualCode + "\"\n");
}

callback();
});

this.Then(/^it outputs this json:$/, function(expectedOutput, callback) {
var actualOutput = lastRun['stdout'];
var actualError = lastRun['error'];
Expand Down

0 comments on commit ca9bea3

Please sign in to comment.