Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
feat: add mocha support
Browse files Browse the repository at this point in the history
  • Loading branch information
nording authored and mhevery committed Nov 15, 2016
1 parent c5130a6 commit 41a9047
Show file tree
Hide file tree
Showing 17 changed files with 512 additions and 37 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ before_script:
- ./scripts/sauce/sauce_connect_block.sh

script:
- node_modules/.bin/karma start karma-sauce.conf.js --single-run
- node_modules/.bin/karma start karma-sauce-jasmine.conf.js --single-run
- node_modules/.bin/karma start karma-sauce-mocha.conf.js --single-run
- node_modules/.bin/gulp test/node
10 changes: 10 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ gulp.task('build/jasmine-patch.min.js', ['compile-esm'], function(cb) {
return generateScript('./lib/jasmine/jasmine.ts', 'jasmine-patch.min.js', true, cb);
});

gulp.task('build/mocha-patch.js', ['compile-esm'], function(cb) {
return generateScript('./lib/mocha/mocha.ts', 'mocha-patch.js', false, cb);
});

gulp.task('build/mocha-patch.min.js', ['compile-esm'], function(cb) {
return generateScript('./lib/mocha/mocha.ts', 'mocha-patch.min.js', true, cb);
});

gulp.task('build/long-stack-trace-zone.js', ['compile-esm'], function(cb) {
return generateScript('./lib/zone-spec/long-stack-trace.ts', 'long-stack-trace-zone.js', false, cb);
});
Expand Down Expand Up @@ -142,6 +150,8 @@ gulp.task('build', [
'build/zone-node.js',
'build/jasmine-patch.js',
'build/jasmine-patch.min.js',
'build/mocha-patch.js',
'build/mocha-patch.min.js',
'build/long-stack-trace-zone.js',
'build/long-stack-trace-zone.min.js',
'build/proxy-zone.js',
Expand Down
7 changes: 7 additions & 0 deletions karma-jasmine.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

module.exports = function (config) {
require('./karma.conf')(config);

config.plugins.push(require('karma-jasmine'));
config.frameworks.push('jasmine');
};
10 changes: 10 additions & 0 deletions karma-mocha.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

module.exports = function (config) {
require('./karma.conf')(config);

config.plugins.push(require('karma-mocha'));
config.frameworks.push('mocha');
config.client.mocha = {
timeout: 5000 // copied timeout for Jasmine in WebSocket.spec (otherwise Mochas default timeout at 2 sec is to low for the tests)
};
};
13 changes: 13 additions & 0 deletions karma-sauce-jasmine.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

module.exports = function (config) {
require('./karma.conf')(config);
require('./karma-jasmine.conf')(config);
require('./sauce.conf')(config);
};
1 change: 1 addition & 0 deletions karma-sauce.conf.js → karma-sauce-mocha.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@

module.exports = function (config) {
require('./karma.conf')(config);
require('./karma-mocha.conf')(config);
require('./sauce.conf')(config);
};
4 changes: 1 addition & 3 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ module.exports = function (config) {
plugins: [
require('karma-chrome-launcher'),
require('karma-firefox-launcher'),
require('karma-jasmine'),
require('karma-sourcemap-loader'),
require('karma-sourcemap-loader')
],

preprocessors: {
Expand All @@ -42,7 +41,6 @@ module.exports = function (config) {
logLevel: config.LOG_INFO,

browsers: ['Firefox'],
frameworks: ['jasmine'],

captureTimeout: 60000,

Expand Down
164 changes: 164 additions & 0 deletions lib/mocha/mocha.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
'use strict';

((context: any) => {
var Mocha = context.Mocha;

if (typeof Mocha === 'undefined') {
throw new Error('Missing Mocha.js');
}

if (typeof Zone === 'undefined') {
throw new Error('Missing Zone.js');
}

const ProxyZoneSpec = Zone['ProxyZoneSpec'];
const SyncTestZoneSpec = Zone['SyncTestZoneSpec'];

if (!ProxyZoneSpec) {
throw new Error('Missing ProxyZoneSpec');
}

if(Mocha['__zone_patch__']){
throw new Error('"Mocha" has already been patched with "Zone".');
}

Mocha['__zone_patch__'] = true;

const rootZone = Zone.current;
const syncZone = rootZone.fork(new SyncTestZoneSpec('Mocha.describe'));
let testZone = null;
const suiteZone = rootZone.fork(new ProxyZoneSpec());

const mochaOriginal = {
after: Mocha.after,
afterEach: Mocha.afterEach,
before: Mocha.before,
beforeEach: Mocha.beforeEach,
describe: Mocha.describe,
it: Mocha.it
};

function modifyArguments(args: IArguments, syncTest: Function, asyncTest?: Function): any[] {
for (let i = 0; i < args.length; i++) {
let arg = args[i];
if (typeof arg === 'function') {
// The `done` callback is only passed through if the function expects at
// least one argument.
// Note we have to make a function with correct number of arguments,
// otherwise mocha will
// think that all functions are sync or async.
args[i] = (arg.length === 0) ? syncTest(arg) : asyncTest(arg);
// Mocha uses toString to view the test body in the result list, make sure we return the correct function body
args[i].toString = function(){
return arg.toString();
};
}
}

return args as any;
}

function wrapDescribeInZone(args: IArguments): any[] {
const syncTest: any = function(fn){
return function(){
return syncZone.run(fn, this, arguments as any as any[]);
};
};

return modifyArguments(args, syncTest);
}

function wrapTestInZone(args: IArguments): any[] {
const asyncTest = function(fn){
return function(done){
return testZone.run(fn, this, [done]);
};
};

const syncTest: any = function(fn){
return function(){
return testZone.run(fn, this);
};
};

return modifyArguments(args, syncTest, asyncTest);
}

function wrapSuiteInZone(args: IArguments): any[] {
const asyncTest = function(fn){
return function(done){
return suiteZone.run(fn, this, [done]);
};
};

const syncTest: any = function(fn){
return function(){
return suiteZone.run(fn, this);
};
};

return modifyArguments(args, syncTest, asyncTest);
};

context.describe = context.suite = Mocha.describe = function() {
return mochaOriginal.describe.apply(this, wrapDescribeInZone(arguments));
};

context.xdescribe = context.suite.skip = Mocha.describe.skip = function() {
return mochaOriginal.describe.skip.apply(this, wrapDescribeInZone(arguments));
};

context.describe.only = context.suite.only = Mocha.describe.only = function() {
return mochaOriginal.describe.only.apply(this, wrapDescribeInZone(arguments));
};

context.it = context.specify = context.test = Mocha.it = function() {
return mochaOriginal.it.apply(this, wrapTestInZone(arguments));
};

context.xit = context.xspecify = Mocha.it.skip = function() {
return mochaOriginal.it.skip.apply(this, wrapTestInZone(arguments));
};

context.it.only = context.test.only = Mocha.it.only = function() {
return mochaOriginal.it.only.apply(this, wrapTestInZone(arguments));
};

context.after = context.suiteTeardown = Mocha.after = function(){
return mochaOriginal.after.apply(this, wrapSuiteInZone(arguments));
};

context.afterEach = context.teardown = Mocha.afterEach = function(){
return mochaOriginal.afterEach.apply(this, wrapTestInZone(arguments));
};

context.before = context.suiteSetup = Mocha.before = function(){
return mochaOriginal.before.apply(this, wrapSuiteInZone(arguments));
};

context.beforeEach = context.setup = Mocha.beforeEach = function(){
return mochaOriginal.beforeEach.apply(this, wrapTestInZone(arguments));
};

((originalRunTest, originalRun) => {
Mocha.Runner.prototype.runTest = function(fn){
Zone.current.scheduleMicroTask('mocha.forceTask', () => {
originalRunTest.call(this, fn);
});
};

Mocha.Runner.prototype.run = function(fn){
this.on('test', (e) => {
if(Zone.current !== rootZone){
throw new Error('Unexpected zone: '+ Zone.current.name);
}
testZone = rootZone.fork(new ProxyZoneSpec());
});

return originalRun.call(this, fn);
};


})(Mocha.Runner.prototype.runTest, Mocha.Runner.prototype.run);

})(window);
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
"ws-server": "node ./test/ws-server.js",
"tsc": "tsc",
"tsc:w": "tsc -w",
"test": "npm run tsc && concurrently \"npm run tsc:w\" \"npm run ws-server\" \"karma start karma.conf.js\"",
"test": "npm run tsc && concurrently \"npm run tsc:w\" \"npm run ws-server\" \"karma start karma-jasmine.conf.js\"",
"test-node": "gulp test/node",
"test-mocha": "npm run tsc && concurrently \"npm run tsc:w\" \"npm run ws-server\" \"karma start karma-mocha.conf.js\"",
"serve": "python -m SimpleHTTPServer 8000"
},
"repository": {
Expand Down Expand Up @@ -52,9 +53,11 @@
"karma-chrome-launcher": "^0.2.1",
"karma-firefox-launcher": "^0.1.4",
"karma-jasmine": "^0.3.6",
"karma-mocha": "^1.2.0",
"karma-safari-launcher": "^0.1.1",
"karma-sauce-launcher": "^0.2.10",
"karma-sourcemap-loader": "^0.3.6",
"mocha": "^3.1.2",
"nodejs-websocket": "^1.2.0",
"pump": "^1.0.1",
"systemjs": "^0.19.37",
Expand Down
21 changes: 21 additions & 0 deletions test/browser-zone-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

// Must be loaded before zone loads, so that zone can detect WTF.
import './wtf_mock';

// Setup tests for Zone without microtask support
import '../lib/zone';
import '../lib/browser/browser';
import '../lib/zone-spec/async-test';
import '../lib/zone-spec/fake-async-test';
import '../lib/zone-spec/long-stack-trace';
import '../lib/zone-spec/proxy';
import '../lib/zone-spec/sync-test';
import '../lib/zone-spec/task-tracking';
import '../lib/zone-spec/wtf';
9 changes: 6 additions & 3 deletions test/browser/WebSocket.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ if (!window['soucelabs']) {

beforeEach(function(done) {
socket = new WebSocket(TEST_SERVER_URL);
socket.addEventListener('open', done);
socket.addEventListener('open', function(){
done();
});
socket.addEventListener('error', function() {
fail(
'Can\'t establish socket to ' + TEST_SERVER_URL +
Expand All @@ -31,9 +33,10 @@ if (!window['soucelabs']) {
}, TIMEOUT);

afterEach(function(done) {
socket.addEventListener('close', done);
socket.addEventListener('close', function(){
done();
});
socket.close();
done();
}, TIMEOUT);


Expand Down
18 changes: 1 addition & 17 deletions test/browser_entry_point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/

// Must be loaded before zone loads, so that zone can detect WTF.
import './wtf_mock';

// Setup tests for Zone without microtask support
import '../lib/zone';
import '../lib/browser/browser';
import '../lib/zone-spec/async-test';
import '../lib/zone-spec/fake-async-test';
import '../lib/zone-spec/long-stack-trace';
import '../lib/zone-spec/proxy';
import '../lib/zone-spec/sync-test';
import '../lib/zone-spec/task-tracking';
import '../lib/zone-spec/wtf';

// Setup test environment
import './test-env-setup';

// List all tests here:
import './common_tests';
import './browser/browser.spec';
Expand All @@ -35,3 +18,4 @@ import './browser/requestAnimationFrame.spec';
import './browser/WebSocket.spec';
import './browser/XMLHttpRequest.spec';
// import './browser/geolocation.spec.manual';
import './mocha-patch.spec';
31 changes: 20 additions & 11 deletions test/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@
* found in the LICENSE file at https://angular.io/license
*/

declare var __karma__: {loaded: Function, start: Function
declare var __karma__: {
loaded: Function, start: Function
error: Function
};

__karma__.loaded = function() {};
(window as any).global = window;
__karma__.loaded = function () { };
(window as any).global = window;

System.config({defaultJSExtensions: true});
System.import('/base/build/test/browser_entry_point')
System.config({ defaultJSExtensions: true });

System.import('/base/build/test/browser-zone-setup').then(() => {
let testFrameworkPatch = typeof (window as any).Mocha !== 'undefined' ? '/base/build/test/test-env-setup-mocha'
: '/base/build/test/test-env-setup-jasmine';
// Setup test environment
System.import(testFrameworkPatch).then(() => {
System.import('/base/build/test/browser_entry_point')
.then(
() => {
__karma__.start();
},
(error) => {
console.error(error.stack || error);
});
() => {
__karma__.start();
},
(error) => {
console.error(error.stack || error);
});
});
});
Loading

0 comments on commit 41a9047

Please sign in to comment.