Custom object formatters allow users to customize how an object is
stringified in matcher failure messages. This can already be done by
adding a `jasmineToString` method to the objects in question. But
it's not always desirable or possible to do that, particularly when
objects of a given "type" do not inherit from a specific prototype.
For instance, suppose a web service returns a list of foos that are
deserialized from JSON, e.g.:
{ fooId: 42, /* more properties */ }
The only way to define `jasmineToString` on those is by writing code to
add it to each instance at runtime. But a custom object formatter can
recognize that the object it's looking at is a foo and format it
accordingly:
jasmine.addCustomObjectFormatter(function(obj) {
if (typeof obj.fooId !== 'number') {
return undefined;
}
return '[Foo with ID ' + obj.fooId + ']';
});
Unlike `jasmineToString`, custom object formatters are scoped to a
particular spec or suite and don't require any changes to the code
under test.
665 lines
18 KiB
JavaScript
665 lines
18 KiB
JavaScript
describe('Matchers (Integration)', function() {
|
|
function verifyPasses(expectations) {
|
|
it('passes', function(done) {
|
|
var env = new jasmineUnderTest.Env();
|
|
env.it('a spec', function() {
|
|
expectations(env);
|
|
});
|
|
|
|
var specExpectations = function(result) {
|
|
expect(result.status).toEqual('passed');
|
|
expect(result.passedExpectations.length)
|
|
.withContext('Number of passed expectations')
|
|
.toEqual(1);
|
|
expect(result.failedExpectations.length)
|
|
.withContext('Number of failed expectations')
|
|
.toEqual(0);
|
|
expect(result.failedExpectations[0] && result.failedExpectations[0].message)
|
|
.withContext('Failure message')
|
|
.toBeUndefined();
|
|
};
|
|
|
|
env.addReporter({ specDone: specExpectations, jasmineDone: done });
|
|
env.execute();
|
|
});
|
|
}
|
|
|
|
function verifyFails(expectations) {
|
|
it('fails', function(done) {
|
|
var env = new jasmineUnderTest.Env();
|
|
env.it('a spec', function() {
|
|
expectations(env);
|
|
});
|
|
|
|
var specExpectations = function(result) {
|
|
expect(result.status).toEqual('failed');
|
|
expect(result.failedExpectations.length)
|
|
.withContext('Number of failed expectations')
|
|
.toEqual(1);
|
|
expect(result.failedExpectations[0].message)
|
|
.withContext('Failed with a thrown error rather than a matcher failure')
|
|
.not.toMatch(/^Error: /);
|
|
expect(result.failedExpectations[0].matcherName).withContext('Matcher name')
|
|
.not.toEqual('');
|
|
};
|
|
|
|
env.addReporter({ specDone: specExpectations, jasmineDone: done });
|
|
env.execute();
|
|
});
|
|
}
|
|
|
|
function verifyFailsWithCustomObjectFormatters(config) {
|
|
it('uses custom object formatters', function(done) {
|
|
var env = new jasmineUnderTest.Env();
|
|
env.it('a spec', function () {
|
|
env.addCustomObjectFormatter(config.formatter);
|
|
config.expectations(env);
|
|
});
|
|
|
|
var specExpectations = function (result) {
|
|
expect(result.status).toEqual('failed');
|
|
expect(result.failedExpectations.length)
|
|
.withContext('Number of failed expectations')
|
|
.toEqual(1);
|
|
expect(result.failedExpectations[0].message)
|
|
.toEqual(config.expectedMessage);
|
|
};
|
|
|
|
env.addReporter({specDone: specExpectations, jasmineDone: done});
|
|
env.execute();
|
|
});
|
|
}
|
|
|
|
function verifyPassesAsync(expectations) {
|
|
it('passes', function(done) {
|
|
jasmine.getEnv().requirePromises();
|
|
var env = new jasmineUnderTest.Env();
|
|
|
|
env.it('a spec', function() {
|
|
return expectations(env);
|
|
});
|
|
|
|
var specExpectations = function(result) {
|
|
expect(result.status).toEqual('passed');
|
|
expect(result.passedExpectations.length)
|
|
.withContext('Number of passed expectations')
|
|
.toEqual(1);
|
|
expect(result.failedExpectations.length)
|
|
.withContext('Number of failed expectations')
|
|
.toEqual(0);
|
|
expect(result.failedExpectations[0] && result.failedExpectations[0].message)
|
|
.withContext('Failure message')
|
|
.toBeUndefined();
|
|
};
|
|
|
|
env.addReporter({ specDone: specExpectations, jasmineDone: done });
|
|
env.execute();
|
|
});
|
|
}
|
|
|
|
function verifyFailsAsync(expectations) {
|
|
it('fails', function(done) {
|
|
var env = new jasmineUnderTest.Env();
|
|
jasmine.getEnv().requirePromises();
|
|
|
|
env.it('a spec', function() {
|
|
return expectations(env);
|
|
});
|
|
|
|
var specExpectations = function(result) {
|
|
expect(result.status).toEqual('failed');
|
|
expect(result.failedExpectations.length)
|
|
.withContext('Number of failed expectations')
|
|
.toEqual(1);
|
|
expect(result.failedExpectations[0].message)
|
|
.withContext('Failed with a thrown error rather than a matcher failure')
|
|
.not.toMatch(/^Error: /);
|
|
expect(result.failedExpectations[0].matcherName).withContext('Matcher name')
|
|
.not.toEqual('');
|
|
};
|
|
|
|
env.addReporter({ specDone: specExpectations, jasmineDone: done });
|
|
env.execute();
|
|
});
|
|
}
|
|
|
|
function verifyFailsWithCustomObjectFormattersAsync(config) {
|
|
it('uses custom object formatters', function(done) {
|
|
var env = new jasmineUnderTest.Env();
|
|
jasmine.getEnv().requirePromises();
|
|
env.it('a spec', function () {
|
|
env.addCustomObjectFormatter(config.formatter);
|
|
return config.expectations(env);
|
|
});
|
|
|
|
var specExpectations = function (result) {
|
|
expect(result.status).toEqual('failed');
|
|
expect(result.failedExpectations.length)
|
|
.withContext('Number of failed expectations')
|
|
.toEqual(1);
|
|
expect(result.failedExpectations[0].message)
|
|
.toEqual(config.expectedMessage);
|
|
};
|
|
|
|
env.addReporter({specDone: specExpectations, jasmineDone: done});
|
|
env.execute();
|
|
});
|
|
}
|
|
|
|
|
|
describe('nothing', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect().nothing();
|
|
});
|
|
});
|
|
|
|
describe('toBe', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(1).toBe(1);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(2).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe('toBeCloseTo', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(1.001).toBeCloseTo(1, 2);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(1.1).toBeCloseTo(1, 2);
|
|
});
|
|
});
|
|
|
|
describe('toBeDefined', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect({}).toBeDefined();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(undefined).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('toBeFalse', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(false).toBeFalse();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(true).toBeFalse();
|
|
});
|
|
});
|
|
|
|
describe('toBeFalsy', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(false).toBeFalsy();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(true).toBeFalsy();
|
|
});
|
|
});
|
|
|
|
describe('toBeGreaterThan', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(2).toBeGreaterThan(1);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(1).toBeGreaterThan(2);
|
|
});
|
|
});
|
|
|
|
describe('toBeGreaterThanOrEqual', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(2).toBeGreaterThanOrEqual(1);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(1).toBeGreaterThanOrEqual(2);
|
|
});
|
|
});
|
|
|
|
describe('toBeInstanceOf', function() {
|
|
function Ctor() {}
|
|
|
|
verifyPasses(function(env) {
|
|
env.expect(new Ctor()).toBeInstanceOf(Ctor);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect({}).toBeInstanceOf(Ctor);
|
|
});
|
|
});
|
|
|
|
describe('toBeLessThan', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(1).toBeLessThan(2);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(2).toBeLessThan(1);
|
|
});
|
|
});
|
|
|
|
describe('toBeLessThanOrEqual', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(1).toBeLessThanOrEqual(2);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(2).toBeLessThanOrEqual(1);
|
|
});
|
|
});
|
|
|
|
describe('toBeNaN', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(NaN).toBeNaN();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(2).toBeNaN();
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
env.expect(1).toBeNaN();
|
|
},
|
|
expectedMessage: 'Expected |1| to be NaN.'
|
|
});
|
|
});
|
|
|
|
describe('toBeNegativeInfinity', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(Number.NEGATIVE_INFINITY).toBeNegativeInfinity();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(2).toBeNegativeInfinity();
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
env.expect(1).toBeNegativeInfinity();
|
|
},
|
|
expectedMessage: 'Expected |1| to be -Infinity.'
|
|
});
|
|
});
|
|
|
|
describe('toBeNull', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(null).toBeNull();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(2).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('toBePositiveInfinity', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(Number.POSITIVE_INFINITY).toBePositiveInfinity();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(2).toBePositiveInfinity();
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
env.expect(1).toBePositiveInfinity();
|
|
},
|
|
expectedMessage: 'Expected |1| to be Infinity.'
|
|
})
|
|
});
|
|
|
|
describe('toBeResolved', function() {
|
|
verifyPassesAsync(function(env) {
|
|
return env.expectAsync(Promise.resolve()).toBeResolved();
|
|
});
|
|
|
|
verifyFailsAsync(function(env) {
|
|
return env.expectAsync(Promise.reject()).toBeResolved();
|
|
});
|
|
});
|
|
|
|
describe('toBeResolvedTo', function() {
|
|
verifyPassesAsync(function(env) {
|
|
env.addCustomEqualityTester(function(a, b) {
|
|
return a.toString() === b.toString();
|
|
});
|
|
return env.expectAsync(Promise.resolve('5')).toBeResolvedTo(5);
|
|
});
|
|
|
|
verifyFailsAsync(function(env) {
|
|
return env.expectAsync(Promise.resolve('foo')).toBeResolvedTo('bar');
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormattersAsync({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
return env.expectAsync(Promise.resolve('x')).toBeResolvedTo('y');
|
|
},
|
|
expectedMessage: 'Expected a promise to be resolved to |y| ' +
|
|
'but it was resolved to |x|.'
|
|
});
|
|
});
|
|
|
|
describe('toBeRejected', function() {
|
|
verifyPassesAsync(function(env) {
|
|
return env.expectAsync(Promise.reject('nope')).toBeRejected();
|
|
});
|
|
|
|
verifyFailsAsync(function(env) {
|
|
return env.expectAsync(Promise.resolve()).toBeRejected();
|
|
});
|
|
});
|
|
|
|
describe('toBeRejectedWith', function() {
|
|
verifyPassesAsync(function(env) {
|
|
env.addCustomEqualityTester(function(a, b) {
|
|
return a.toString() === b.toString();
|
|
});
|
|
return env.expectAsync(Promise.reject('5')).toBeRejectedWith(5);
|
|
});
|
|
|
|
verifyFailsAsync(function(env) {
|
|
return env.expectAsync(Promise.resolve()).toBeRejectedWith('nope');
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormattersAsync({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
return env.expectAsync(Promise.reject('x')).toBeRejectedWith('y');
|
|
},
|
|
expectedMessage: 'Expected a promise to be rejected with |y| ' +
|
|
'but it was rejected with |x|.'
|
|
});
|
|
});
|
|
|
|
describe('toBeRejectedWithError', function() {
|
|
verifyPassesAsync(function(env) {
|
|
return env.expectAsync(Promise.reject(new Error())).toBeRejectedWithError(Error);
|
|
});
|
|
|
|
verifyFailsAsync(function(env) {
|
|
return env.expectAsync(Promise.resolve()).toBeRejectedWithError(Error);
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormattersAsync({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
return env.expectAsync(Promise.reject('foo')).toBeRejectedWithError('foo');
|
|
},
|
|
expectedMessage: 'Expected a promise to be rejected with Error: |foo| ' +
|
|
'but it was rejected with |foo|.'
|
|
});
|
|
});
|
|
|
|
describe('toBeTrue', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(true).toBeTrue();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(false).toBeTrue();
|
|
});
|
|
});
|
|
|
|
describe('toBeTruthy', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(true).toBeTruthy();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(false).toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe('toBeUndefined', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(undefined).toBeUndefined();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(1).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('toContain', function() {
|
|
verifyPasses(function(env) {
|
|
env.addCustomEqualityTester(function(a, b) {
|
|
return a.toString() === b.toString();
|
|
});
|
|
env.expect(['1', '2', '3']).toContain(2);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect('bar').toContain('oo');
|
|
});
|
|
});
|
|
|
|
describe('toEqual', function() {
|
|
verifyPasses(function(env) {
|
|
env.addCustomEqualityTester(function(a, b) {
|
|
return a.toString() === b.toString();
|
|
});
|
|
env.expect(5).toEqual('5');
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect('a').toEqual('b');
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
if (val === 5) {
|
|
return "five"
|
|
} else if (val === 4) {
|
|
return "four"
|
|
}
|
|
},
|
|
expectations: function(env) {
|
|
env.expect([{foo: 4}]).toEqual([{foo: 5}]);
|
|
},
|
|
expectedMessage: 'Expected $[0].foo = four to equal five.'
|
|
});
|
|
});
|
|
|
|
describe('toHaveBeenCalled', function() {
|
|
verifyPasses(function(env) {
|
|
var spy = env.createSpy('spy');
|
|
spy();
|
|
env.expect(spy).toHaveBeenCalled();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
var spy = env.createSpy('spy');
|
|
env.expect(spy).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('toHaveBeenCalledBefore', function() {
|
|
verifyPasses(function(env) {
|
|
var a = env.createSpy('a'), b = env.createSpy('b');
|
|
a();
|
|
b();
|
|
env.expect(a).toHaveBeenCalledBefore(b);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
var a = env.createSpy('a'), b = env.createSpy('b');
|
|
b();
|
|
a();
|
|
env.expect(a).toHaveBeenCalledBefore(b);
|
|
});
|
|
});
|
|
|
|
describe('toHaveBeenCalledTimes', function() {
|
|
verifyPasses(function(env) {
|
|
var spy = env.createSpy('spy');
|
|
spy();
|
|
env.expect(spy).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
var spy = env.createSpy('spy');
|
|
env.expect(spy).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('toHaveBeenCalledWith', function() {
|
|
verifyPasses(function(env) {
|
|
var spy = env.createSpy();
|
|
spy('5');
|
|
env.addCustomEqualityTester(function(a, b) {
|
|
return a.toString() === b.toString();
|
|
});
|
|
env.expect(spy).toHaveBeenCalledWith(5);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
var spy = env.createSpy();
|
|
env.expect(spy).toHaveBeenCalledWith('foo');
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
var spy = env.createSpy('foo');
|
|
env.expect(spy).toHaveBeenCalledWith('x');
|
|
},
|
|
expectedMessage: 'Expected spy foo to have been called with:\n' +
|
|
' |x|\n' +
|
|
'but it was never called.'
|
|
});
|
|
});
|
|
|
|
describe('toHaveClass', function() {
|
|
beforeEach(function() {
|
|
this.domHelpers = jasmine.getEnv().domHelpers();
|
|
});
|
|
|
|
verifyPasses(function(env) {
|
|
var domHelpers = jasmine.getEnv().domHelpers();
|
|
var el = domHelpers.createElementWithClassName('foo');
|
|
env.expect(el).toHaveClass('foo');
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
var domHelpers = jasmine.getEnv().domHelpers();
|
|
var el = domHelpers.createElementWithClassName('foo');
|
|
env.expect(el).toHaveClass('bar');
|
|
});
|
|
});
|
|
|
|
describe('toMatch', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect('foo').toMatch(/oo$/);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect('bar').toMatch(/oo$/);
|
|
});
|
|
});
|
|
|
|
describe('toThrow', function() {
|
|
verifyPasses(function(env) {
|
|
env.addCustomEqualityTester(function(a, b) {
|
|
return a.toString() === b.toString();
|
|
});
|
|
env.expect(function() { throw '5'; }).toThrow(5);
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(function() {}).toThrow();
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
var spy = env.createSpy('foo');
|
|
env.expect(function() {
|
|
throw 'x'
|
|
}).not.toThrow();
|
|
},
|
|
expectedMessage: 'Expected function not to throw, but it threw |x|.'
|
|
});
|
|
});
|
|
|
|
describe('toThrowError', function() {
|
|
verifyPasses(function(env) {
|
|
env.expect(function() { throw new Error(); }).toThrowError();
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(function() { }).toThrowError();
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
var spy = env.createSpy('foo');
|
|
env.expect(function() {
|
|
throw 'x'
|
|
}).toThrowError();
|
|
},
|
|
expectedMessage: 'Expected function to throw an Error, but it threw |x|.'
|
|
});
|
|
});
|
|
|
|
describe('toThrowMatching', function() {
|
|
function throws() {
|
|
throw new Error('nope');
|
|
}
|
|
|
|
verifyPasses(function(env) {
|
|
env.expect(throws).toThrowMatching(function() { return true; });
|
|
});
|
|
|
|
verifyFails(function(env) {
|
|
env.expect(throws).toThrowMatching(function() { return false; });
|
|
});
|
|
|
|
verifyFailsWithCustomObjectFormatters({
|
|
formatter: function(val) {
|
|
return '|' + val + '|';
|
|
},
|
|
expectations: function(env) {
|
|
var spy = env.createSpy('foo');
|
|
env.expect(function() {
|
|
throw new Error('nope')
|
|
}).toThrowMatching(function() {
|
|
return false;
|
|
});
|
|
},
|
|
expectedMessage: 'Expected function to throw an exception matching ' +
|
|
'a predicate, but it threw Error with message |nope|.'
|
|
});
|
|
});
|
|
});
|