Skip to content

Commit

Permalink
feat(frameworks): Support runner.afterEach in jasmine and mocha ada…
Browse files Browse the repository at this point in the history
…pter (#3988)

Closes #3894,
#3908, and
#3909
  • Loading branch information
sjelin committed Jan 27, 2017
1 parent 4a59412 commit 6c3be8c
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 1 deletion.
10 changes: 10 additions & 0 deletions lib/frameworks/__protractor_internal_afterEach_setup_spec.js
@@ -0,0 +1,10 @@
// This is spec file is automatically added by protractor to implement our
// `afterEach` functionality for jasmine and mocha.

var hooks = require('./setupAfterEach').hooks;

afterEach(function() {
if (hooks.afterEach) {
return hooks.afterEach();
}
});

This comment has been minimized.

Copy link
@martin770

martin770 May 2, 2018

Contributor

Is there any other way to implement this? I guess it would be nice if jasmine (or jasminewd2) would expose the original global afterEach function.

In my project, I hook into the global afterEach function to do some things so that I don't have to write them into every single test. I'm trying to remember off the top of my head, but it looks something like:

var myAfterEach = function() {
    return browser.controlFlow().execute(function() {
        console.log('do some extra stuff');
    });
};
var originalAfterEach = global.afterEach;
global.afterEach = function(fn) {
    return originalAfterEach(function() {
        return browser.controlFlow().execute(function() {
            return fn();
        }).then(function() {
            return myAfterEach();
        });
    });
};

This way my spec will execute whatever is in the afterEach in its spec file, followed by whatever I want it to do in myAfterEach.

When I upgraded to the newer version of protractor I noticed that it was executing myAfterEach TWO times at the end of a spec. When I removed afterEach from my spec, it was STILL executing myAfterEach so I tracked it down to this file. This file makes a call to the global afterEach, and my spec makes a call, so that would account for both occurrences.

I don't know how many other people are modifying the global.afterEach function, but I suspect they might see similar issues. I suppose you could do a similar thing by passing your function through the global.afterEach so as not to interfere with how many times it is executing. But then you are not always guaranteed to have an afterEach per file, if that is your intent.

For the moment, my simple fix is to overwrite this file with a blank file when I start my tests, but that's not a great solution.

3 changes: 3 additions & 0 deletions lib/frameworks/jasmine.js
Expand Up @@ -75,6 +75,9 @@ exports.run = function(runner, specs) {
var reporter = new RunnerReporter(runner);
jasmine.getEnv().addReporter(reporter);

// Add hooks for afterEach
require('./setupAfterEach').setup(runner, specs);

// Filter specs to run based on jasmineNodeOpts.grep and jasmineNodeOpts.invert.
jasmine.getEnv().specFilter = function(spec) {
var grepMatch = !jasmineNodeOpts ||
Expand Down
3 changes: 3 additions & 0 deletions lib/frameworks/mocha.js
Expand Up @@ -12,6 +12,9 @@ exports.run = function(runner, specs) {
var Mocha = require('mocha'),
mocha = new Mocha(runner.getConfig().mochaOpts);

// Add hooks for afterEach
require('./setupAfterEach').setup(runner, specs);

var deferred = q.defer();

// Mocha doesn't set up the ui until the pre-require event, so
Expand Down
29 changes: 29 additions & 0 deletions lib/frameworks/setupAfterEach.js
@@ -0,0 +1,29 @@
/**
* Setup afterEach hook for jasmine/mocha tests.
*
* One of the main purposes of this file is to give `__protractor_internal_afterEach_setup_spec.js`
* a place to look up `runner.afterEach` at runtime without using globals.
* This file needs to be separate from `__protractor_internal_afterEach_setup_spec.js` so that that
* file is not prematurely executed.
*/

var path = require('path');

// Queried by `protractor_internal_afterEach_setup_spec.js` for the `afterEach` hook
var hooks = {
afterEach: null
};

exports.hooks = hooks;

/**
* Setup `runner.afterEach` to be called after every spec.
*
* @param {Runner} runner The current Protractor Runner.
* @param {Array} specs Array of Directory Path Strings. Must be a reference to the same array
* instance used by the framework
*/
exports.setup = function(runner, specs) {
hooks.afterEach = runner.afterEach.bind(runner);
specs.push(path.resolve(__dirname, '__protractor_internal_afterEach_setup_spec.js'));
};
2 changes: 1 addition & 1 deletion scripts/test.js
Expand Up @@ -76,7 +76,7 @@ executor.addCommandlineTest('node built/cli.js spec/errorTest/timeoutConf.js')
message: 'Timeout - Async callback was not invoked within timeout ' +
'specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'
})
.expectTestDuration(0, 100);
.expectTestDuration(0, 1000);

executor.addCommandlineTest('node built/cli.js spec/errorTest/afterLaunchChangesExitCodeConf.js')
.expectExitCode(11)
Expand Down

0 comments on commit 6c3be8c

Please sign in to comment.