Skip to content

Commit ca9bea3

Browse files
eddiefletchernzjbpros
authored andcommitted
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
1 parent 745c40d commit ca9bea3

File tree

3 files changed

+141
-5
lines changed

3 files changed

+141
-5
lines changed

README.md

+31
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,37 @@ var myAfterHooks = function () {
364364
module.exports = myAfterHooks;
365365
```
366366

367+
##### After features event
368+
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/).
369+
370+
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".
371+
372+
```javascript
373+
// features/support/world.js
374+
var webdriver = require("selenium-webdriver");
375+
376+
var World = function World(callback) {
377+
this.driver = new webdriver.Builder().
378+
withCapabilities(webdriver.Capabilities.chrome()).
379+
build();
380+
381+
callback();
382+
}
383+
384+
module.exports = World;
385+
386+
// features/support/after_hooks.js
387+
var myAfterHooks = function () {
388+
this.registerHandler('AfterFeatures', function (event, callback) {
389+
this.driver.close();
390+
callback();
391+
});
392+
}
393+
394+
module.exports = myAfterHooks;
395+
```
396+
397+
367398
##### Around hooks
368399

369400
It's also possible to combine both before and after hooks in one single definition with the help of *around hooks*:

features/cli.feature

+83
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,86 @@ Feature: Command line interface
131131
Scenario: display help (short flag)
132132
When I run `cucumber.js -h`
133133
Then I see the help of Cucumber
134+
135+
Scenario: run a single failing feature
136+
Given a file named "features/a.feature" with:
137+
"""
138+
Feature: some feature
139+
Scenario:
140+
When a step is failing
141+
"""
142+
And a file named "features/step_definitions/cucumber_steps.js" with:
143+
"""
144+
var cucumberSteps = function() {
145+
this.When(/^a step is failing$/, function(callback) { callback("forced error"); });
146+
};
147+
module.exports = cucumberSteps;
148+
"""
149+
When I run `cucumber.js features/a.feature`
150+
Then it should fail with:
151+
"""
152+
1 scenario (1 failed)
153+
1 step (1 failed)
154+
155+
"""
156+
And it should exit with code "1"
157+
158+
159+
Scenario: run a single failing feature with an empty hooks file
160+
Given a file named "features/a.feature" with:
161+
"""
162+
Feature: some feature
163+
Scenario:
164+
When a step is failing
165+
"""
166+
And a file named "features/step_definitions/cucumber_steps.js" with:
167+
"""
168+
var cucumberSteps = function() {
169+
this.When(/^a step is failing$/, function(callback) { callback("forced error"); });
170+
};
171+
module.exports = cucumberSteps;
172+
"""
173+
And a file named "features/support/hooks.js" with:
174+
"""
175+
"""
176+
When I run `cucumber.js features/a.feature`
177+
Then it should fail with:
178+
"""
179+
1 scenario (1 failed)
180+
1 step (1 failed)
181+
182+
"""
183+
And it should exit with code "1"
184+
185+
186+
Scenario: run a single failing feature with an AfterFeatures hook
187+
Given a file named "features/a.feature" with:
188+
"""
189+
Feature: some feature
190+
Scenario:
191+
When a step is failing
192+
"""
193+
And a file named "features/step_definitions/cucumber_steps.js" with:
194+
"""
195+
var cucumberSteps = function() {
196+
this.When(/^a step is failing$/, function(callback) { callback("forced error"); });
197+
};
198+
module.exports = cucumberSteps;
199+
"""
200+
And a file named "features/support/hooks.js" with:
201+
"""
202+
var hooks = function() {
203+
this.registerHandler('AfterFeatures', function (event, callback) {
204+
callback();
205+
});
206+
};
207+
module.exports = hooks;
208+
"""
209+
When I run `cucumber.js features/a.feature`
210+
Then it should fail with:
211+
"""
212+
1 scenario (1 failed)
213+
1 step (1 failed)
214+
215+
"""
216+
And it should exit with code "1"

features/step_definitions/cli_steps.js

+27-5
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,40 @@ var cliSteps = function cliSteps() {
6262
});
6363
});
6464

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

70-
if (actualOutput == actualError)
72+
return str
73+
.replace(/\033\[[0-9;]*m/g, '')
74+
.replace(/\r\n|\r/g, "\n");
75+
};
76+
77+
actualOutput = cleanString(actualOutput);
78+
expectedOutput = cleanString(expectedOutput);
79+
80+
if (actualOutput.indexOf(expectedOutput) === -1) {
7181
throw new Error("Expected output to match the following:\n'" + expectedOutput + "'\nGot:\n'" + actualOutput + "'.\n" +
72-
"Error:\n'" + actualError + "'.\n" +
73-
"stderr:\n'" + actualStderr +"'.");
82+
"Error:\n'" + actualError + "'.\n" +
83+
"stderr:\n'" + actualStderr + "'.");
84+
}
85+
7486
callback();
7587
});
7688

89+
this.Then(/^it should exit with code "([^"]*)"$/, function (code, callback) {
90+
var actualCode = lastRun['error'] ? lastRun['error'].code : "0";
91+
92+
if (actualCode != code) {
93+
throw new Error("Exit code expected: \"" + code + "\"\nGot: \"" + actualCode + "\"\n");
94+
}
95+
96+
callback();
97+
});
98+
7799
this.Then(/^it outputs this json:$/, function(expectedOutput, callback) {
78100
var actualOutput = lastRun['stdout'];
79101
var actualError = lastRun['error'];

0 commit comments

Comments
 (0)