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.
}
This commit is contained in:
Steve Gravrock
2020-01-18 14:16:15 -08:00
committed by Steve Gravrock
parent 9aed55bb91
commit 18b2646d1d
7 changed files with 153 additions and 35 deletions

View File

@@ -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;
};

View File

@@ -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);
});
});

View File

@@ -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
);

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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(

View File

@@ -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;
};