Permalink
Browse files

Document AfterFeatures event (close #171)

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...
1 parent 745c40d commit ca9bea36c3483b91898a75293c656de289e73669 @eddieloeffen eddieloeffen committed with jbpros Jun 30, 2014
Showing with 141 additions and 5 deletions.
  1. +31 −0 README.md
  2. +83 −0 features/cli.feature
  3. +27 −5 features/step_definitions/cli_steps.js
View
@@ -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*:
View
@@ -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"
@@ -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'];

0 comments on commit ca9bea3

Please sign in to comment.