From 18b2646d1d949d1cbb0506ca318e3da3ea6c0d0d Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Sat, 18 Jan 2020 14:16:15 -0800 Subject: [PATCH] Allow libraries to avoid "Passing custom equality testers to MatchersUtil#contains is deprecated" while remaining compatible with older jasmine versions Previously, a custom matcher library that wanted to remain compatible with Jasmine <= 3.5.x could not know whether or not Jasmine expected it to pass custom equality testers to MatchersUtil#contains. Passing them would produce a deprecation warning in newer versions and not passing them would break compatibility with older versions. Now we use matcher factory arity to determine whether to pass custom equality testers to the factory, which allows libraries to do something like this: function matcherFactory(util) { const customEqualityTesters = arguments[1]; // customEqualityTesters will be undefined in newer versions of Jasmine // and defined in older versions that expect it to be passed back to // MatchersUtil#equals. } --- lib/jasmine-core/jasmine.js | 10 ++- spec/core/AsyncExpectationSpec.js | 7 +- spec/core/ExpectationSpec.js | 34 +++++++++- .../integration/CustomAsyncMatchersSpec.js | 59 ++++++++++++---- spec/core/integration/CustomMatchersSpec.js | 67 +++++++++++++++---- spec/core/matchers/matchersUtilSpec.js | 1 - src/core/Expector.js | 10 ++- 7 files changed, 153 insertions(+), 35 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 9465e287..2ec4dda3 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -3952,7 +3952,15 @@ getJasmineRequireObj().Expector = function(j$) { this.args.unshift(this.actual); - var matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters); + // TODO: Remove support for passing customEqualityTesters in the next major release. + var matcher; + + if (matcherFactory.length >= 2) { + matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters); + } else { + matcher = matcherFactory(this.matchersUtil); + } + var comparisonFunc = this.filters.selectComparisonFunc(matcher); return comparisonFunc || matcher.compare; }; diff --git a/spec/core/AsyncExpectationSpec.js b/spec/core/AsyncExpectationSpec.js index 40f63731..a480e0ca 100644 --- a/spec/core/AsyncExpectationSpec.js +++ b/spec/core/AsyncExpectationSpec.js @@ -266,23 +266,18 @@ describe('AsyncExpectation', function() { matchersUtil = { buildFailureMessage: jasmine.createSpy('buildFailureMessage') }, - customEqualityTesters = ['a'], addExpectationResult = jasmine.createSpy('addExpectationResult'), expectation; expectation = jasmineUnderTest.Expectation.asyncFactory({ matchersUtil: matchersUtil, customAsyncMatchers: matchers, - customEqualityTesters: customEqualityTesters, actual: 'an actual', addExpectationResult: addExpectationResult }); return expectation.toFoo('hello').then(function() { - expect(matcherFactory).toHaveBeenCalledWith( - matchersUtil, - customEqualityTesters - ); + expect(matcherFactory).toHaveBeenCalledWith(matchersUtil); }); }); diff --git a/spec/core/ExpectationSpec.js b/spec/core/ExpectationSpec.js index 6ab37713..f0cdfded 100644 --- a/spec/core/ExpectationSpec.js +++ b/spec/core/ExpectationSpec.js @@ -40,6 +40,38 @@ describe('Expectation', function() { matchersUtil = { buildFailureMessage: jasmine.createSpy('buildFailureMessage') }, + addExpectationResult = jasmine.createSpy('addExpectationResult'), + expectation; + + expectation = jasmineUnderTest.Expectation.factory({ + matchersUtil: matchersUtil, + customMatchers: matchers, + actual: 'an actual', + addExpectationResult: addExpectationResult + }); + + expectation.toFoo('hello'); + + expect(matcherFactory).toHaveBeenCalledWith(matchersUtil); + }); + + // TODO: remove this in the next major release + it('passes custom equality testers when the matcher factory takes two arguments', function() { + var fakeCompare = function() { + return { pass: true }; + }, + matcherFactory = function(matchersUtil, customTesters) { + return { compare: fakeCompare }; + }, + matcherFactorySpy = jasmine + .createSpy('matcher', matcherFactory) + .and.callThrough(), + matchers = { + toFoo: matcherFactorySpy + }, + matchersUtil = { + buildFailureMessage: jasmine.createSpy('buildFailureMessage') + }, customEqualityTesters = ['a'], addExpectationResult = jasmine.createSpy('addExpectationResult'), expectation; @@ -54,7 +86,7 @@ describe('Expectation', function() { expectation.toFoo('hello'); - expect(matcherFactory).toHaveBeenCalledWith( + expect(matcherFactorySpy).toHaveBeenCalledWith( matchersUtil, customEqualityTesters ); diff --git a/spec/core/integration/CustomAsyncMatchersSpec.js b/spec/core/integration/CustomAsyncMatchersSpec.js index bd618c8b..174ddd90 100644 --- a/spec/core/integration/CustomAsyncMatchersSpec.js +++ b/spec/core/integration/CustomAsyncMatchersSpec.js @@ -80,24 +80,19 @@ describe('Custom Async Matchers (Integration)', function() { env.execute(); }); - // TODO: remove this in the next major release. - it("passes the jasmine utility and current equality testers to the matcher factory", function(done) { + it("passes the jasmine utility to the matcher factory", function (done) { jasmine.getEnv().requirePromises(); - var matcherFactory = function () { + var matcherFactory = function (util) { return { compare: function () { return Promise.resolve({pass: true}); } }; }, - matcherFactorySpy = jasmine.createSpy("matcherFactorySpy").and.callFake(matcherFactory), - customEqualityFn = function () { - return true; - }; + matcherFactorySpy = jasmine.createSpy("matcherFactorySpy", matcherFactory); - env.it("spec with expectation", function() { - env.addCustomEqualityTester(customEqualityFn); + env.it("spec with expectation", function () { env.addAsyncMatchers({ toBeReal: matcherFactorySpy }); @@ -105,17 +100,55 @@ describe('Custom Async Matchers (Integration)', function() { return env.expectAsync(true).toBeReal(); }); - var specExpectations = function() { + var specExpectations = function () { expect(matcherFactorySpy).toHaveBeenCalledWith( - jasmine.any(jasmineUnderTest.MatchersUtil), - [customEqualityFn] + jasmine.any(jasmineUnderTest.MatchersUtil) ); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); + env.addReporter({specDone: specExpectations, jasmineDone: done}); env.execute(); }); + // TODO: remove this in the next major release. + describe('When a matcher factory takes at least two arguments', function() { + it("passes the jasmine utility and current equality testers to the matcher factory", function (done) { + jasmine.getEnv().requirePromises(); + + var matcherFactory = function (util, customTesters) { + return { + compare: function () { + return Promise.resolve({pass: true}); + } + }; + }, + matcherFactorySpy = jasmine.createSpy("matcherFactorySpy", matcherFactory), + customEqualityFn = function () { + return true; + }; + + env.it("spec with expectation", function () { + env.addCustomEqualityTester(customEqualityFn); + env.addAsyncMatchers({ + toBeReal: matcherFactorySpy + }); + + return env.expectAsync(true).toBeReal(); + }); + + var specExpectations = function () { + expect(matcherFactorySpy).toHaveBeenCalledWith( + jasmine.any(jasmineUnderTest.MatchersUtil), + [customEqualityFn] + ); + }; + + spyOn(env, 'deprecated'); + env.addReporter({specDone: specExpectations, jasmineDone: done}); + env.execute(); + }); + }); + it("provides custom equality testers to the matcher factory via matchersUtil", function(done) { jasmine.getEnv().requirePromises(); diff --git a/spec/core/integration/CustomMatchersSpec.js b/spec/core/integration/CustomMatchersSpec.js index b8424e69..65ea9f00 100644 --- a/spec/core/integration/CustomMatchersSpec.js +++ b/spec/core/integration/CustomMatchersSpec.js @@ -117,7 +117,10 @@ describe("Custom Matchers (Integration)", function () { }); it("displays an appropriate failure message if a custom equality matcher fails", function(done) { + spyOn(env, 'deprecated'); + env.it("spec using custom equality matcher", function() { + var customEqualityFn = function(a, b) { // "foo" is not equal to anything if (a === 'foo' || b === 'foo') { @@ -210,15 +213,17 @@ describe("Custom Matchers (Integration)", function () { env.execute(); }); - // TODO: remove this in the next major release. - it("passes the jasmine utility and current equality testers to the matcher factory", function(done) { - var matcherFactory = function() { return { compare: function() { return {pass: true}; }}; }, - matcherFactorySpy = jasmine.createSpy("matcherFactorySpy").and.callFake(matcherFactory), - customEqualityFn = function() { return true; }; + it("passes the jasmine utility to the matcher factory", function (done) { + var matcherFactory = function (util) { + return { + compare: function () { + return {pass: true}; + } + }; + }, + matcherFactorySpy = jasmine.createSpy("matcherFactorySpy").and.callFake(matcherFactory); - - env.it("spec with expectation", function() { - env.addCustomEqualityTester(customEqualityFn); + env.it("spec with expectation", function () { env.addMatchers({ toBeReal: matcherFactorySpy }); @@ -226,17 +231,55 @@ describe("Custom Matchers (Integration)", function () { env.expect(true).toBeReal(); }); - var specExpectations = function() { + var specExpectations = function () { expect(matcherFactorySpy).toHaveBeenCalledWith( - jasmine.any(jasmineUnderTest.MatchersUtil), - [customEqualityFn] + jasmine.any(jasmineUnderTest.MatchersUtil) ); }; - env.addReporter({ specDone: specExpectations, jasmineDone: done }); + env.addReporter({specDone: specExpectations, jasmineDone: done}); env.execute(); }); + // TODO: remove this in the next major release. + describe('When a matcher factory takes at least two arguments', function() { + it("passes the jasmine utility and current equality testers to the matcher factory", function (done) { + spyOn(env, 'deprecated'); + + var matcherFactory = function (util, customTesters) { + return { + compare: function () { + return {pass: true}; + } + }; + }, + matcherFactorySpy = jasmine.createSpy("matcherFactorySpy", matcherFactory), + customEqualityFn = function () { + return true; + }; + + + env.it("spec with expectation", function () { + env.addCustomEqualityTester(customEqualityFn); + env.addMatchers({ + toBeReal: matcherFactorySpy + }); + + env.expect(true).toBeReal(); + }); + + var specExpectations = function () { + expect(matcherFactorySpy).toHaveBeenCalledWith( + jasmine.any(jasmineUnderTest.MatchersUtil), + [customEqualityFn] + ); + }; + + env.addReporter({specDone: specExpectations, jasmineDone: done}); + env.execute(); + }); + }); + it("provides custom equality testers to the matcher factory via matchersUtil", function (done) { var matcherFactory = function (matchersUtil) { return { diff --git a/spec/core/matchers/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js index 6e7d7178..dbbefce9 100644 --- a/spec/core/matchers/matchersUtilSpec.js +++ b/spec/core/matchers/matchersUtilSpec.js @@ -868,7 +868,6 @@ describe("matchersUtil", function() { deprecated = spyOn(jasmineUnderTest.getEnv(), 'deprecated'); - debugger; matchersUtil.equals(0, 0, null, new jasmineUnderTest.NullDiffBuilder()); expect(deprecated).toHaveBeenCalledWith(jasmine.stringMatching( diff --git a/src/core/Expector.js b/src/core/Expector.js index e0f7ae9c..c4a560ca 100644 --- a/src/core/Expector.js +++ b/src/core/Expector.js @@ -20,7 +20,15 @@ getJasmineRequireObj().Expector = function(j$) { this.args.unshift(this.actual); - var matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters); + // TODO: Remove support for passing customEqualityTesters in the next major release. + var matcher; + + if (matcherFactory.length >= 2) { + matcher = matcherFactory(this.matchersUtil, this.customEqualityTesters); + } else { + matcher = matcherFactory(this.matchersUtil); + } + var comparisonFunc = this.filters.selectComparisonFunc(matcher); return comparisonFunc || matcher.compare; };