From bfcd8b046d489298087868fc8a07c488bc498939 Mon Sep 17 00:00:00 2001 From: slackersoft Date: Tue, 16 Dec 2014 17:45:58 -0800 Subject: [PATCH] Allow asymmetric equality testers to preempt their symmetric brethren - Also allow them to be compared to each other properly. Fixes #540 --- lib/jasmine-core/jasmine.js | 30 +++++++++++++++++++------- spec/core/matchers/matchersUtilSpec.js | 15 +++++++++++++ src/core/matchers/matchersUtil.js | 30 +++++++++++++++++++------- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 52bbd86c..d599f879 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2239,11 +2239,33 @@ getJasmineRequireObj().matchersUtil = function(j$) { return obj && j$.isA_('Function', obj.asymmetricMatch); } + function asymmetricMatch(a, b) { + var asymmetricA = isAsymmetric(a), + asymmetricB = isAsymmetric(b); + + if (asymmetricA && asymmetricB) { + return undefined; + } + + if (asymmetricA) { + return a.asymmetricMatch(b); + } + + if (asymmetricB) { + return b.asymmetricMatch(a); + } + } + // Equality function lovingly adapted from isEqual in // [Underscore](http://underscorejs.org) function eq(a, b, aStack, bStack, customTesters) { var result = true; + var asymmetricResult = asymmetricMatch(a, b); + if (!j$.util.isUndefined(asymmetricResult)) { + return asymmetricResult; + } + for (var i = 0; i < customTesters.length; i++) { var customTesterResult = customTesters[i](a, b); if (!j$.util.isUndefined(customTesterResult)) { @@ -2251,14 +2273,6 @@ getJasmineRequireObj().matchersUtil = function(j$) { } } - if (isAsymmetric(a)) { - return a.asymmetricMatch(b); - } - - if (isAsymmetric(b)) { - return b.asymmetricMatch(a); - } - if (a instanceof Error && b instanceof Error) { return a.message == b.message; } diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index d3f99833..443eef04 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -235,6 +235,21 @@ describe("matchersUtil", function() { expect(j$.matchersUtil.equals(1, 1, [tester])).toBe(false); }); + + it("passes for an asymmetric equality tester that returns true when a custom equality tester return false", function() { + var asymmetricTester = { asymmetricMatch: function(other) { return true; } }, + symmetricTester = function(a, b) { return false; }; + + expect(j$.matchersUtil.equals(asymmetricTester, true, [symmetricTester])).toBe(true); + expect(j$.matchersUtil.equals(true, asymmetricTester, [symmetricTester])).toBe(true); + }); + + it("passes when an Any is compared to an Any that checks for the same type", function() { + var any1 = new j$.Any(Function), + any2 = new j$.Any(Function); + + expect(j$.matchersUtil.equals(any1, any2)).toBe(true); + }); }); describe("contains", function() { diff --git a/src/core/matchers/matchersUtil.js b/src/core/matchers/matchersUtil.js index 015813f1..f3f84632 100644 --- a/src/core/matchers/matchersUtil.js +++ b/src/core/matchers/matchersUtil.js @@ -55,11 +55,33 @@ getJasmineRequireObj().matchersUtil = function(j$) { return obj && j$.isA_('Function', obj.asymmetricMatch); } + function asymmetricMatch(a, b) { + var asymmetricA = isAsymmetric(a), + asymmetricB = isAsymmetric(b); + + if (asymmetricA && asymmetricB) { + return undefined; + } + + if (asymmetricA) { + return a.asymmetricMatch(b); + } + + if (asymmetricB) { + return b.asymmetricMatch(a); + } + } + // Equality function lovingly adapted from isEqual in // [Underscore](http://underscorejs.org) function eq(a, b, aStack, bStack, customTesters) { var result = true; + var asymmetricResult = asymmetricMatch(a, b); + if (!j$.util.isUndefined(asymmetricResult)) { + return asymmetricResult; + } + for (var i = 0; i < customTesters.length; i++) { var customTesterResult = customTesters[i](a, b); if (!j$.util.isUndefined(customTesterResult)) { @@ -67,14 +89,6 @@ getJasmineRequireObj().matchersUtil = function(j$) { } } - if (isAsymmetric(a)) { - return a.asymmetricMatch(b); - } - - if (isAsymmetric(b)) { - return b.asymmetricMatch(a); - } - if (a instanceof Error && b instanceof Error) { return a.message == b.message; }