This repository has been archived by the owner on Feb 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 407
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(test): add jest support to Mocha runner
- Loading branch information
1 parent
e7d43fe
commit 9478a81
Showing
13 changed files
with
1,136 additions
and
201 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** | ||
* @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 | ||
*/ | ||
|
||
import './jest'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* @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 | ||
*/ | ||
|
||
export function mappingBDD(jest: any, Mocha: any, global: any) { | ||
const mappings: {jest: string, Mocha: string}[] = [ | ||
// other Jest APIs has already mapping in jasmine2mocha patch | ||
{jest: 'test', Mocha: 'it'} | ||
]; | ||
mappings.forEach(map => { | ||
if (!global[map.jest]) { | ||
const mocha = map.Mocha; | ||
const chains = mocha.split('.'); | ||
let mochaMethod: any = null; | ||
for (let i = 0; i < chains.length; i++) { | ||
mochaMethod = mochaMethod ? mochaMethod[chains[i]] : global[chains[i]]; | ||
} | ||
global[map.jest] = jest[map.jest] = mochaMethod; | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
/** | ||
* @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 | ||
*/ | ||
import { Any, eq, toMatch } from '../jasmine-bridge/jasmine.util'; | ||
export function expandExpect(global: any) { | ||
const jasmine = global.jasmine; | ||
const expect: any = global.expect; | ||
|
||
class Anything { } | ||
|
||
expect.anything = function () { | ||
return new Anything(); | ||
}; | ||
|
||
expect.any = function (obj: any) { | ||
return new Any(obj); | ||
}; | ||
|
||
class ArrayContaining { | ||
constructor(public expectedArray: any[]) { } | ||
} | ||
|
||
expect.arrayContaining = function (expectedArray: string[]) { | ||
return new ArrayContaining(expectedArray); | ||
} | ||
|
||
class ObjectContaining { | ||
constructor(public expectedObject: any) { } | ||
} | ||
|
||
expect.objectContaining = function (expectedObject: any) { | ||
return new ObjectContaining(expectedObject); | ||
} | ||
|
||
class StringContaining { | ||
constructor(public expectedString: string) { } | ||
} | ||
|
||
expect.stringContaining = function (expectedString: string) { | ||
return new StringContaining(expectedString); | ||
} | ||
|
||
class StringMatching { | ||
constructor(public expectedMatcher: RegExp | string) { } | ||
} | ||
|
||
expect.stringMatching = function (expectedMatcher: RegExp | string) { | ||
return new StringMatching(expectedMatcher); | ||
} | ||
|
||
const assertions: { test: any, numbers: number }[] = expect.__zone_symbol__assertionsMap = []; | ||
|
||
jasmine.addCustomEqualityTester((a: any, b: any) => { | ||
if (b instanceof Anything) { | ||
if (a === null || a === undefined) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
if (b instanceof Any) { | ||
return b.eq(a); | ||
} | ||
if (b instanceof ArrayContaining && Array.isArray(a)) { | ||
for (let i = 0; i < b.expectedArray.length; i++) { | ||
let found = false; | ||
const bitem = b.expectedArray[i]; | ||
for (let j = 0; j < a.length; j++) { | ||
if (eq(a[j], bitem)) { | ||
found = true; | ||
break; | ||
} | ||
} | ||
if (!found) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
if (b instanceof ObjectContaining) { | ||
Object.keys(b.expectedObject).forEach(key => { | ||
if (b.expectedObject.hasOwnProperty(key)) { | ||
if (!eq(a[key], b.expectedObject[key]) || !toMatch(b.expectedObject[key], a[key])) { | ||
return false; | ||
} | ||
} | ||
}); | ||
return true; | ||
} | ||
if (b instanceof StringContaining) { | ||
let astr = a; | ||
if (typeof a !== 'string') { | ||
astr = Object.prototype.toString.call(a); | ||
} | ||
if (!astr) { | ||
return false; | ||
} | ||
return astr.indexOf(b.expectedString) !== -1; | ||
} | ||
if (b instanceof StringMatching) { | ||
let astr = a; | ||
if (typeof a !== 'string') { | ||
astr = Object.prototype.toString.call(a); | ||
} | ||
return toMatch(b.expectedMatcher, astr); | ||
} | ||
}); | ||
|
||
expect.extend = function (extendedMatchers: any) { | ||
const jasmineMatchers: any = {}; | ||
Object.keys(extendedMatchers).forEach(key => { | ||
if (extendedMatchers.hasOwnProperty(key)) { | ||
const matcher = extendedMatchers[key]; | ||
jasmineMatchers[key] = function (util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any) { | ||
const result = matcher(actual, expected); | ||
return result.pass; | ||
} | ||
}; | ||
} | ||
} | ||
}); | ||
jasmine.addMatchers(jasmineMatchers); | ||
}; | ||
|
||
jasmine.addMatchers({ | ||
toHaveBeenCalledTimes: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any) { | ||
return expected.calls.count() === actual; | ||
} | ||
}; | ||
}, | ||
lastCalledWith: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any) { | ||
return util.equals(actual, expected.calls.last().args); | ||
} | ||
}; | ||
}, | ||
toHaveBeenLastCalledWith: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any) { | ||
return util.equals(actual, expected.calls.last().args); | ||
} | ||
}; | ||
}, | ||
toBeInstanceOf: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any) { | ||
return actual instanceof expected; | ||
} | ||
}; | ||
}, | ||
toContainEqual: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any) { | ||
if (!Array.isArray(actual)) { | ||
return false; | ||
} | ||
return actual.filter(a => util.equals(a, expected)).length > 0; | ||
} | ||
}; | ||
}, | ||
toHaveLength: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any) { | ||
return actual.length === expected; | ||
} | ||
}; | ||
}, | ||
toHaveProperty: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function (actual: any, expected: any, expectedValue: any) { | ||
const split: string[] = Array.isArray(expected) ? expected : expected.split('.'); | ||
let value = null; | ||
let hasKey = false; | ||
for (let i = 0; i < split.length; i++) { | ||
const prop = split[i]; | ||
const isIndex = typeof prop === 'number'; | ||
if (value) { | ||
hasKey = isIndex ? Array.isArray(value) && (value as any).length > prop : | ||
Object.keys(value).filter(a => util.equals(a, prop)).length > 0; | ||
value = value[prop]; | ||
} else { | ||
hasKey = isIndex ? Array.isArray(actual) && (actual as any).length > prop : | ||
Object.keys(actual).filter(a => util.equals(a, prop)).length > 0; | ||
value = actual[prop]; | ||
} | ||
if (!hasKey) { | ||
return false; | ||
} | ||
} | ||
|
||
if (expectedValue !== undefined) { | ||
return util.equals(expectedValue, value); | ||
} else { | ||
return true; | ||
} | ||
} | ||
}; | ||
}, | ||
toMatchObject: function(util: any, customEqualityTester: any) { | ||
return { | ||
compare: function(actual: any, expected: any) { | ||
Object.keys(expected).forEach(key => { | ||
if (expected.hasOwnProperty(key)) { | ||
if (!util.equals(actual[key], expected[key]) && | ||
!util.toMatch(actual[key], expected[key])) { | ||
return false; | ||
} | ||
} | ||
}); | ||
return true; | ||
} | ||
}; | ||
}, | ||
}); | ||
|
||
expect.assertions = function (numbers: number) { | ||
if (typeof numbers !== 'number') { | ||
return; | ||
} | ||
const currentTest = global.Mocha.__zone_symbol__test; | ||
assertions.push({ test: currentTest, numbers }); | ||
} | ||
|
||
expect.hasAssertions = function () { | ||
const currentTest = global.Mocha.__zone_symbol__test; | ||
assertions.push({ test: currentTest, numbers: 1 }); | ||
} | ||
|
||
if (!global.Mocha.__zone_symbol__afterEach) { | ||
global.Mocha.__zone_symbol__afterEach = []; | ||
} | ||
|
||
global.Mocha.__zone_symbol__afterEach.push((test: any) => { | ||
// check assertions | ||
for (let i = 0; i < assertions.length; i++) { | ||
const ass = assertions[i]; | ||
if (ass.test === test) { | ||
assertions.splice(i, 1); | ||
const actual = jasmine.__zone_symbol__expect_assertions; | ||
jasmine.__zone_symbol__expect_assertions = 0; | ||
if (ass.numbers != actual) { | ||
throw new Error(`Assertions failed, expect should be called ${ | ||
ass.numbers} times, it was actual called ${actual} times.`); | ||
} | ||
return; | ||
} | ||
} | ||
}); | ||
} |
Oops, something went wrong.