Skip to content
This repository was archived by the owner on Jul 29, 2024. It is now read-only.

Commit 478c00a

Browse files
committed
feat(runner): add beta support for using mocha as your test framework
This change adds limited support for using mocha as the test framework instead of jasmine. Make the switch by using `--framework=mocha` on the command line or adding `framework: 'mocha'` to the config. Tests will be run using the BDD interface. The interface is adapted so that tests run asynchronously without needing to call `done()`. Note that there is currently no support for an assertion framework, so you will need to require whichever assertion framework you prefer. This means there is no adapter to make the assertions unwrap promises, so you will need to resolve promises yourself and run the assertions afterwards.
1 parent 8d7c948 commit 478c00a

File tree

10 files changed

+173
-79
lines changed

10 files changed

+173
-79
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The Protractor runner is a binary which accepts a config file. Install protracto
3131
# Run the line below to see command line options
3232
protractor
3333

34-
You will need a *configuration file* containing setup info and *test files* containing the actual test scripts. The config file specifies how the runner should start webdriver, where your test files are, and global setup options. The test files use Jasmine framework, but other adapters may be added in the future.
34+
You will need a *configuration file* containing setup info and *test files* containing the actual test scripts. The config file specifies how the runner should start webdriver, where your test files are, and global setup options. The test files use Jasmine framework by default (Mocha is supported in beta).
3535

3636
Create a configuration file - an example with detailed comments is shown in `node_modules/protractor/referenceConf.js`. Edit the configuration file to point to your test files.
3737

example/mocha/example_spec.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* This example shows how to use the protractor library in a Mocha test.
3+
*
4+
* Run this test with:
5+
* protractor example/mocha/mochaConf.js
6+
*/
7+
8+
// Note that there is nothing adapting expect.js to understand promises,
9+
// so we may only use it once promises have been resolved.
10+
var expect = require('expect.js');
11+
12+
describe('angularjs.org homepage', function() {
13+
this.timeout(80000);
14+
15+
it('should greet using binding', function() {
16+
browser.get('http://www.angularjs.org');
17+
18+
element(by.input('yourName')).sendKeys('Julie');
19+
20+
element(by.binding('{{yourName}}')).
21+
getText().then(function(text) {
22+
expect(text).to.eql('Hello Julie!');
23+
});
24+
});
25+
26+
it('should list todos', function() {
27+
browser.get('http://www.angularjs.org');
28+
29+
var todo = element(by.repeater('todo in todos').row(1));
30+
31+
todo.getText().then(function(text) {
32+
expect(text).to.eql('build an angular app');
33+
});
34+
});
35+
});

example/mocha/mochaConf.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// An example configuration file.
2+
exports.config = {
3+
// Do not start a Selenium Standalone sever - only run this using chrome.
4+
chromeOnly: true,
5+
chromeDriver: '../../selenium/chromedriver',
6+
7+
framework: 'mocha',
8+
9+
// Capabilities to be passed to the webdriver instance.
10+
capabilities: {
11+
'browserName': 'chrome'
12+
},
13+
14+
// Spec patterns are relative to the current working directly when
15+
// protractor is called.
16+
specs: ['example_spec.js'],
17+
};

example/mocha/onMocha.js

-69
This file was deleted.

lib/cli.js

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var argv = require('optimist').
2424
describe('verbose', 'Print full spec names').
2525
describe('stackTrace', 'Print stack trace on error').
2626
describe('params', 'Param object to be passed to the tests').
27+
describe('framework', 'Test framework to use. jasmine or mocha.').
2728
alias('browser', 'capabilities.browserName').
2829
alias('name', 'capabilities.name').
2930
alias('platform', 'capabilities.platform').

lib/runner.js

+62-7
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ var fs = require('fs');
44
var webdriver = require('selenium-webdriver');
55
var remote = require('selenium-webdriver/remote');
66
var chrome = require('selenium-webdriver/chrome');
7-
var minijn = require('minijasminenode');
87
var protractor = require('./protractor.js');
98
var SauceLabs = require('saucelabs');
109
var glob = require('glob');
11-
require('../jasminewd')
1210

1311
var server;
1412
var driver;
@@ -28,6 +26,7 @@ var config = {
2826
},
2927
rootElement: 'body',
3028
params: {},
29+
framework: 'jasmine',
3130
jasmineNodeOpts: {
3231
isVerbose: false,
3332
showColors: true,
@@ -210,7 +209,7 @@ var setUpSelenium = function() {
210209
* @return {webdriver.promise.Promise} A promise that will resolve
211210
* when the test run is finished.
212211
*/
213-
var runJasmineTests = function() {
212+
var runTests = function() {
214213
if (config.jasmineNodeOpts.specFolders) {
215214
throw new Error('Using config.jasmineNodeOpts.specFolders is deprecated ' +
216215
'since Protractor 0.6.0. Please switch to config.specs.');
@@ -233,7 +232,6 @@ var runJasmineTests = function() {
233232
throw new Error('Spec patterns did not match any files.');
234233
}
235234

236-
minijn.addSpecs(resolvedSpecs);
237235
// TODO: This should not be tied to the webdriver promise loop, it should use
238236
// another promise system instead.
239237
var runDeferred = webdriver.promise.defer();
@@ -269,6 +267,45 @@ var runJasmineTests = function() {
269267
global.element = browser.element;
270268
global.by = protractor.By;
271269

270+
// Do the framework setup here so that jasmine and mocha globals are
271+
// available to the onPrepare function.
272+
var minijn, mocha;
273+
if (config.framework == 'jasmine') {
274+
minijn = require('minijasminenode');
275+
require('../jasminewd');
276+
minijn.addSpecs(resolvedSpecs);
277+
} else if (config.framework == 'mocha') {
278+
var Mocha = require('mocha');
279+
280+
mocha = new Mocha({
281+
ui: 'bdd',
282+
reporter: 'list'
283+
});
284+
285+
resolvedSpecs.forEach(function(file) {
286+
mocha.addFile(file);
287+
});
288+
289+
// Mocha doesn't set up the ui until the pre-require event, so
290+
// wait until then to load mocha-webdriver adapters as well.
291+
mocha.suite.on('pre-require', function() {
292+
var mochaAdapters = require('selenium-webdriver/testing');
293+
global.after = mochaAdapters.after;
294+
global.afterEach = mochaAdapters.afterEach;
295+
global.before = mochaAdapters.before;
296+
global.beforeEach = mochaAdapters.beforeEach;
297+
298+
global.it = mochaAdapters.it;
299+
global.it.only = global.iit = mochaAdapters.it.only;
300+
global.it.skip = global.xit = mochaAdapters.xit;
301+
});
302+
303+
mocha.loadFiles();
304+
} else {
305+
throw 'config.framework ' + config.framework +
306+
' is not a valid framework.';
307+
}
308+
272309
// Let the configuration configure the protractor instance before running
273310
// the tests.
274311
webdriver.promise.controlFlow().execute(function() {
@@ -293,7 +330,25 @@ var runJasmineTests = function() {
293330
});
294331
};
295332

296-
minijn.executeSpecs(options);
333+
if (config.framework == 'jasmine') {
334+
minijn.executeSpecs(options);
335+
} else if (config.framework == 'mocha') {
336+
mocha.run(function(failures) {
337+
// Warning: hack to make it have the same signature as Jasmine 1.3.1.
338+
if (originalOnComplete) {
339+
originalOnComplete();
340+
}
341+
driver.quit().then(function() {
342+
runDeferred.fulfill({
343+
results: function() {
344+
return {
345+
failedCount: failures
346+
};
347+
}
348+
});
349+
});
350+
});
351+
}
297352
});
298353
});
299354

@@ -306,11 +361,11 @@ var runJasmineTests = function() {
306361
*/
307362
var runOnce = function() {
308363
return setUpSelenium().then(function() {
309-
// cleanUp must be registered directly onto runJasmineTests, not onto
364+
// cleanUp must be registered directly onto runTests, not onto
310365
// the chained promise, so that cleanUp is still called in case of a
311366
// timeout error. Timeout errors need to clear the control flow, which
312367
// would mess up chaining promises.
313-
return runJasmineTests().then(cleanUp);
368+
return runTests().then(cleanUp);
314369
});
315370
};
316371

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"devDependencies": {
2323
"expect.js": "~0.2.0",
2424
"jasmine-node": "~1.9.0",
25-
"mocha": "~1.10.0",
25+
"mocha": "~1.16.0",
2626
"express": "~3.3.4",
2727
"mustache": "~0.7.2"
2828
},
@@ -36,7 +36,7 @@
3636
},
3737
"main": "lib/protractor.js",
3838
"scripts": {
39-
"test": "node lib/cli.js spec/basicConf.js; node lib/cli.js spec/altRootConf.js; node lib/cli.js spec/onPrepareConf.js; node_modules/.bin/minijasminenode jasminewd/spec/adapterSpec.js"
39+
"test": "node lib/cli.js spec/basicConf.js; node lib/cli.js spec/altRootConf.js; node lib/cli.js spec/onPrepareConf.js; node lib/cli.js spec/mochaConf.js; node_modules/.bin/minijasminenode jasminewd/spec/adapterSpec.js"
4040
},
4141
"license" : "MIT",
4242
"version": "0.15.0",

referenceConf.js

+7
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ exports.config = {
9898
password: '1234'
9999
}
100100
},
101+
102+
// ----- The test framework -----
103+
//
104+
// Jasmine is fully supported as a test and assertion framework.
105+
// Mocha has limited beta support. You will need to include your own
106+
// assertion framework if working with mocha.
107+
framework: 'jasmine',
101108

102109
// ----- Options to be passed to minijasminenode -----
103110
//

spec/mocha/lib_spec.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
var expect = require('expect.js');
2+
3+
describe('no protractor at all', function() {
4+
it('should still do normal tests', function() {
5+
expect(true).to.eql(true);
6+
});
7+
});
8+
9+
describe('protractor library', function() {
10+
it('should expose the correct global variables', function() {
11+
expect(protractor).not.to.be(undefined);
12+
expect(browser).not.to.be(undefined);
13+
expect(by).not.to.be(undefined);
14+
expect(element).not.to.be(undefined);
15+
expect($).not.to.be(undefined);
16+
});
17+
18+
it('should wrap webdriver', function() {
19+
browser.get('index.html');
20+
browser.getTitle().then(function(text) {
21+
expect(text).to.eql('My AngularJS App');
22+
});
23+
});
24+
});

spec/mochaConf.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// A small suite to make sure the mocha frameowork works.
2+
exports.config = {
3+
seleniumAddress: 'http://localhost:4444/wd/hub',
4+
5+
framework: 'mocha',
6+
7+
// Spec patterns are relative to this directory.
8+
specs: [
9+
'mocha/*_spec.js'
10+
],
11+
12+
capabilities: {
13+
'browserName': 'chrome'
14+
},
15+
16+
baseUrl: 'http://localhost:8000',
17+
18+
params: {
19+
login: {
20+
user: 'Jane',
21+
password: '1234'
22+
}
23+
}
24+
};

0 commit comments

Comments
 (0)