Skip to content

Commit

Permalink
Move asymetric matchers from jasmine to jest
Browse files Browse the repository at this point in the history
In jestjs#2389 I moved equals but it turns out there are more!

I renamed the file `expect.js` to `jasmine-utils` and moved it to `jest-matchers` instead of `jest-matcher-utils`.

This is the big thing, otherwise it's been pretty much copy and pasted from jasmine.
  • Loading branch information
vjeux committed Dec 20, 2016
1 parent 9b16596 commit cf61b22
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 13 deletions.
10 changes: 9 additions & 1 deletion packages/jest-jasmine2/src/jest-expect.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ module.exports = (config: Config) => {
};
});

global.expect.extend(jestMatchersObject);
const expect = global.expect;

expect.anything = jasmine.anything;
expect.any = jasmine.any;
expect.objectContaining = jasmine.objectContaining;
expect.arrayContaining = jasmine.arrayContaining;
expect.stringMatching = jasmine.stringMatching;

expect.extend(jestMatchersObject);
};
};
2 changes: 0 additions & 2 deletions packages/jest-matcher-utils/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

const chalk = require('chalk');
const prettyFormat = require('pretty-format');
const equals = require('./equals');

export type ValueType =
| 'array'
Expand Down Expand Up @@ -192,7 +191,6 @@ module.exports = {
ensureExpectedIsNumber,
ensureNoExpected,
ensureNumbers,
equals,
getType,
matcherHint,
pluralize,
Expand Down
3 changes: 2 additions & 1 deletion packages/jest-matchers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"dependencies": {
"jest-diff": "^18.0.0",
"jest-matcher-utils": "^18.0.0",
"jest-util": "^18.0.0"
"jest-util": "^18.0.0",
"pretty-format": "^18.0.0"
},
"scripts": {
"test": "../../packages/jest-cli/bin/jest.js"
Expand Down
17 changes: 12 additions & 5 deletions packages/jest-matchers/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ const spyMatchers = require('./spyMatchers');
const toThrowMatchers = require('./toThrowMatchers');

const utils = require('jest-matcher-utils');
const {
any,
anything,
arrayContaining,
objectContaining,
stringMatching,
} = require('./jasmine-utils');

const GLOBAL_STATE = Symbol.for('$$jest-matchers-object');

Expand Down Expand Up @@ -136,11 +143,11 @@ expect.extend = (matchersObj: MatchersObject): void => {
Object.assign(global[GLOBAL_STATE].matchers, matchersObj);
};

expect.anything = global.jasmine.anything;
expect.any = global.jasmine.any;
expect.objectContaining = global.jasmine.objectContaining;
expect.arrayContaining = global.jasmine.arrayContaining;
expect.stringMatching = global.jasmine.stringMatching;
expect.anything = anything;
expect.any = any;
expect.objectContaining = objectContaining;
expect.arrayContaining = arrayContaining;
expect.stringMatching = stringMatching;

const _validateResult = result => {
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,31 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

'use strict';

const prettyFormat = require('pretty-format');

// Extracted out of jasmine 2.5.2
function equals(a, b, customTesters) {
customTesters = customTesters || [];
return eq(a, b, [], [], customTesters);
}

function contains(haystack, needle, customTesters) {
customTesters = customTesters || [];

if ((Object.prototype.toString.apply(haystack) === '[object Array]') ||
(!!haystack && !haystack.indexOf))
{
for (var i = 0; i < haystack.length; i++) {
if (eq(haystack[i], needle, [], [], customTesters)) {
return true;
}
}
return false;
}

return !!haystack && haystack.indexOf(needle) >= 0;
}

function isAsymmetric(obj) {
return obj && isA('Function', obj.asymmetricMatch);
}
Expand Down Expand Up @@ -252,4 +271,176 @@ function isDomNode(obj) {
return obj.nodeType > 0;
}

module.exports = equals;
function fnNameFor(func) {
if (func.name) {
return func.name;
}

var matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/);
return matches ? matches[1] : '<anonymous>';
}


function Any(expectedObject) {
if (typeof expectedObject === 'undefined') {
throw new TypeError(
'jasmine.any() expects to be passed a constructor function. ' +
'Please pass one or use jasmine.anything() to match any object.'
);
}
this.expectedObject = expectedObject;
}

function any(expectedObject) {
return new Any(expectedObject);
}

Any.prototype.asymmetricMatch = function(other) {
if (this.expectedObject == String) {
return typeof other == 'string' || other instanceof String;
}

if (this.expectedObject == Number) {
return typeof other == 'number' || other instanceof Number;
}

if (this.expectedObject == Function) {
return typeof other == 'function' || other instanceof Function;
}

if (this.expectedObject == Object) {
return typeof other == 'object';
}

if (this.expectedObject == Boolean) {
return typeof other == 'boolean';
}

return other instanceof this.expectedObject;
};

Any.prototype.jasmineToString = function() {
return '<jasmine.any(' + fnNameFor(this.expectedObject) + ')>';
};


function Anything() {}

function anything() {
return new Anything();
}

Anything.prototype.asymmetricMatch = function(other) {
return !isUndefined(other) && other !== null;
};

Anything.prototype.jasmineToString = function() {
return '<jasmine.anything>';
};


function ArrayContaining(sample) {
this.sample = sample;
}

function arrayContaining(sample) {
return new ArrayContaining(sample);
}

ArrayContaining.prototype.asymmetricMatch = function(other) {
var className = Object.prototype.toString.call(this.sample);
if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); }

for (var i = 0; i < this.sample.length; i++) {
var item = this.sample[i];
if (!contains(other, item)) {
return false;
}
}

return true;
};

ArrayContaining.prototype.jasmineToString = function () {
return '<jasmine.arrayContaining(' + prettyFormat(this.sample) +')>';
};


function ObjectContaining(sample) {
this.sample = sample;
}

function objectContaining(sample) {
return new ObjectContaining(sample);
}

function getPrototype(obj) {
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
}

if (obj.constructor.prototype == obj) {
return null;
}

return obj.constructor.prototype;
}

function hasProperty(obj, property) {
if (!obj) {
return false;
}

if (Object.prototype.hasOwnProperty.call(obj, property)) {
return true;
}

return hasProperty(getPrototype(obj), property);
}

ObjectContaining.prototype.asymmetricMatch = function(other) {
if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); }

for (var property in this.sample) {
if (!hasProperty(other, property) ||
!equals(this.sample[property], other[property])) {
return false;
}
}

return true;
};

ObjectContaining.prototype.jasmineToString = function() {
return '<jasmine.objectContaining(' + prettyFormat(this.sample) + ')>';
};


function StringMatching(expected) {
if (!isA('String', expected) && !isA('RegExp', expected)) {
throw new Error('Expected is not a String or a RegExp');
}

this.regexp = new RegExp(expected);
}

function stringMatching(expected) {
return new StringMatching(expected);
}

StringMatching.prototype.asymmetricMatch = function(other) {
return this.regexp.test(other);
};

StringMatching.prototype.jasmineToString = function() {
return '<jasmine.stringMatching(' + this.regexp + ')>';
};

module.exports = {
any,
anything,
arrayContaining,
equals,
objectContaining,
stringMatching,
};
4 changes: 3 additions & 1 deletion packages/jest-matchers/src/matchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ const {
printReceived,
printExpected,
printWithType,
equals,
} = require('jest-matcher-utils');
const {
equals,
} = require('./jasmine-utils');

type ContainIterable = (
Array<any> |
Expand Down
4 changes: 3 additions & 1 deletion packages/jest-matchers/src/spyMatchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ const {
printReceived,
printWithType,
RECEIVED_COLOR,
equals,
} = require('jest-matcher-utils');
const {
equals,
} = require('./jasmine-utils');

const RECEIVED_NAME = {
'mock function': 'jest.fn()',
Expand Down
4 changes: 3 additions & 1 deletion packages/jest-matchers/src/toThrowMatchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ const {
matcherHint,
printExpected,
printWithType,
equals,
} = require('jest-matcher-utils');
const {
equals,
} = require('./jasmine-utils');

const createMatcher = matcherName =>
(actual: Function, expected: string | Error | RegExp) => {
Expand Down

0 comments on commit cf61b22

Please sign in to comment.