This makes it easier to write high quality matchers and asymmetric equality
testers, and is also a step toward supporting custom object formatters.
Previously, Jasmine passed custom object formatters as the second argument
to matcher factories and as and the second argument to asymmetric equality
testers' `asymmetricMatch` method. Matchers and asymmetric equality testers
were responsible for passing the custom object formatters to methods like
`matchersUtil#equals`:
function toEqual(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
// ...
result.pass = util.equals(actual, expected, customEqualityTesters, diffBuilder);
And:
ArrayContaining.prototype.asymmetricMatch = function(other, customTesters) {
// ...
for (var i = 0; i < this.sample.length; i++) {
var item = this.sample[i];
if (!j$.matchersUtil.contains(other, item, customTesters)) {
return false;
}
}
With this change, that is no longer necessary. Matchers and asymmetric
equality testers can ignore the existence of custom equality testers and
still fully support them:
function toEqual(util) {
return {
compare: function(actual, expected) {
// ...
result.pass = util.equals(actual, expected, diffBuilder);
And:
ArrayContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
// ...
for (var i = 0; i < this.sample.length; i++) {
var item = this.sample[i];
if (!matchersUtil.contains(other, item)) {
return false;
}
}
The old interfaces are still supported, for now, but will be deprecated
in a future commit and removed in the next major release after that.
In addition to making matchers and custom equality testers simpler,
this change sets the stage for adding support for custom object
formatters. Those will be architecturally similar to custom equality
testers, and by injecting a `MatchersUtil` instance everywhere we can
add them without requiring user code to pass them around as used to be
the case with custom object formatters.
687 lines
18 KiB
JavaScript
687 lines
18 KiB
JavaScript
describe('Expectation', function() {
|
|
it('makes custom matchers available to this expectation', function() {
|
|
var matchers = {
|
|
toFoo: function() {},
|
|
toBar: function() {}
|
|
},
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers
|
|
});
|
|
|
|
expect(expectation.toFoo).toBeDefined();
|
|
expect(expectation.toBar).toBeDefined();
|
|
});
|
|
|
|
it('.addCoreMatchers makes matchers available to any expectation', function() {
|
|
var coreMatchers = {
|
|
toQuux: function() {}
|
|
},
|
|
expectation;
|
|
|
|
jasmineUnderTest.Expectation.addCoreMatchers(coreMatchers);
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({});
|
|
|
|
expect(expectation.toQuux).toBeDefined();
|
|
});
|
|
|
|
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
|
|
var fakeCompare = function() {
|
|
return { pass: true };
|
|
},
|
|
matcherFactory = jasmine
|
|
.createSpy('matcher')
|
|
.and.returnValue({ compare: fakeCompare }),
|
|
matchers = {
|
|
toFoo: matcherFactory
|
|
},
|
|
util = {
|
|
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
|
},
|
|
customEqualityTesters = ['a'],
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
util: util,
|
|
customMatchers: matchers,
|
|
customEqualityTesters: customEqualityTesters,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(matcherFactory).toHaveBeenCalledWith(util, customEqualityTesters);
|
|
});
|
|
|
|
it("wraps matchers's compare functions, passing the actual and expected", function() {
|
|
var fakeCompare = jasmine
|
|
.createSpy('fake-compare')
|
|
.and.returnValue({ pass: true }),
|
|
matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: fakeCompare
|
|
};
|
|
}
|
|
},
|
|
util = {
|
|
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
util: util,
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(fakeCompare).toHaveBeenCalledWith('an actual', 'hello');
|
|
});
|
|
|
|
it('reports a passing result to the spec when the comparison passes', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: true };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
util = {
|
|
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
util: util,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(true, {
|
|
matcherName: 'toFoo',
|
|
passed: true,
|
|
message: '',
|
|
error: undefined,
|
|
expected: 'hello',
|
|
actual: 'an actual',
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it('reports a failing result to the spec when the comparison fails', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: false };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
util = {
|
|
buildFailureMessage: function() {
|
|
return '';
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
util: util,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: 'an actual',
|
|
message: '',
|
|
error: undefined,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it('reports a failing result and a custom fail message to the spec when the comparison fails', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: false,
|
|
message: 'I am a custom message'
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
actual: 'an actual',
|
|
customMatchers: matchers,
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: 'an actual',
|
|
message: 'I am a custom message',
|
|
error: undefined,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it('reports a failing result with a custom fail message function to the spec when the comparison fails', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: false,
|
|
message: function() {
|
|
return 'I am a custom message';
|
|
}
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: 'an actual',
|
|
message: 'I am a custom message',
|
|
error: undefined,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it('reports a passing result to the spec when the comparison fails for a negative expectation', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: false };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
actual = 'an actual',
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
}).not;
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(true, {
|
|
matcherName: 'toFoo',
|
|
passed: true,
|
|
message: '',
|
|
error: undefined,
|
|
expected: 'hello',
|
|
actual: actual,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it('reports a failing result to the spec when the comparison passes for a negative expectation', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: true };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
util = {
|
|
buildFailureMessage: function() {
|
|
return 'default message';
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
actual = 'an actual',
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
util: util,
|
|
addExpectationResult: addExpectationResult
|
|
}).not;
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: actual,
|
|
message: 'default message',
|
|
error: undefined,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it('reports a failing result and a custom fail message to the spec when the comparison passes for a negative expectation', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: true,
|
|
message: 'I am a custom message'
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
actual = 'an actual',
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
}).not;
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: actual,
|
|
message: 'I am a custom message',
|
|
error: undefined,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it("reports a passing result to the spec when the 'not' comparison passes, given a negativeCompare", function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: true };
|
|
},
|
|
negativeCompare: function() {
|
|
return { pass: true };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
actual = 'an actual',
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
}).not;
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(true, {
|
|
matcherName: 'toFoo',
|
|
passed: true,
|
|
expected: 'hello',
|
|
actual: actual,
|
|
message: '',
|
|
error: undefined,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it("reports a failing result and a custom fail message to the spec when the 'not' comparison fails, given a negativeCompare", function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: true };
|
|
},
|
|
negativeCompare: function() {
|
|
return {
|
|
pass: false,
|
|
message: "I'm a custom message"
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
actual = 'an actual',
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
}).not;
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: actual,
|
|
message: "I'm a custom message",
|
|
error: undefined,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it('reports a custom error message to the spec', function() {
|
|
var customError = new Error('I am a custom error');
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: false,
|
|
message: 'I am a custom message',
|
|
error: customError
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
actual: 'an actual',
|
|
customMatchers: matchers,
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: 'an actual',
|
|
message: 'I am a custom message',
|
|
error: customError,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it("reports a custom message to the spec when a 'not' comparison fails", function() {
|
|
var customError = new Error('I am a custom error');
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: true,
|
|
message: 'I am a custom message',
|
|
error: customError
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
actual: 'an actual',
|
|
customMatchers: matchers,
|
|
addExpectationResult: addExpectationResult
|
|
}).not;
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: 'an actual',
|
|
message: 'I am a custom message',
|
|
error: customError,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
it("reports a custom message func to the spec when a 'not' comparison fails", function() {
|
|
var customError = new Error('I am a custom error');
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: true,
|
|
message: function() {
|
|
return 'I am a custom message';
|
|
},
|
|
error: customError
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation;
|
|
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
actual: 'an actual',
|
|
customMatchers: matchers,
|
|
addExpectationResult: addExpectationResult
|
|
}).not;
|
|
|
|
expectation.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
|
matcherName: 'toFoo',
|
|
passed: false,
|
|
expected: 'hello',
|
|
actual: 'an actual',
|
|
message: 'I am a custom message',
|
|
error: customError,
|
|
errorForStack: undefined
|
|
});
|
|
});
|
|
|
|
describe('#withContext', function() {
|
|
it('prepends the context to the generated failure message', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: false };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
util = {
|
|
buildFailureMessage: function() {
|
|
return 'failure message';
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
util: util,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.withContext('Some context').toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(
|
|
false,
|
|
jasmine.objectContaining({
|
|
message: 'Some context: failure message'
|
|
})
|
|
);
|
|
});
|
|
|
|
it('prepends the context to a custom failure message', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: false, message: 'msg' };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.withContext('Some context').toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(
|
|
false,
|
|
jasmine.objectContaining({
|
|
message: 'Some context: msg'
|
|
})
|
|
);
|
|
});
|
|
|
|
it('prepends the context to a custom failure message from a function', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: false,
|
|
message: function() {
|
|
return 'msg';
|
|
}
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.withContext('Some context').toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(
|
|
false,
|
|
jasmine.objectContaining({
|
|
message: 'Some context: msg'
|
|
})
|
|
);
|
|
});
|
|
|
|
it('works with #not', function() {
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return { pass: true };
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
customMatchers: matchers,
|
|
util: new jasmineUnderTest.MatchersUtil(),
|
|
actual: 'an actual',
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.withContext('Some context').not.toFoo();
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(
|
|
false,
|
|
jasmine.objectContaining({
|
|
message: "Some context: Expected 'an actual' not to foo."
|
|
})
|
|
);
|
|
});
|
|
|
|
it('works with #not and a custom message', function() {
|
|
var customError = new Error('I am a custom error');
|
|
var matchers = {
|
|
toFoo: function() {
|
|
return {
|
|
compare: function() {
|
|
return {
|
|
pass: true,
|
|
message: function() {
|
|
return 'I am a custom message';
|
|
},
|
|
error: customError
|
|
};
|
|
}
|
|
};
|
|
}
|
|
},
|
|
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
|
expectation = jasmineUnderTest.Expectation.factory({
|
|
actual: 'an actual',
|
|
customMatchers: matchers,
|
|
addExpectationResult: addExpectationResult
|
|
});
|
|
|
|
expectation.withContext('Some context').not.toFoo('hello');
|
|
|
|
expect(addExpectationResult).toHaveBeenCalledWith(
|
|
false,
|
|
jasmine.objectContaining({
|
|
message: 'Some context: I am a custom message'
|
|
})
|
|
);
|
|
});
|
|
});
|
|
});
|