Added support for custom object formatters
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.
This commit is contained in:
committed by
Steve Gravrock
parent
1f23f1e4d2
commit
25816a6e77
@@ -44,4 +44,30 @@ describe("DiffBuilder", function() {
|
||||
|
||||
expect(diffBuilder.getMessage()).toEqual("I find your lack of foo disturbing. (was bar, at $.x)");
|
||||
});
|
||||
|
||||
it("uses the injected pretty-printer", function() {
|
||||
var prettyPrinter = function(val) {
|
||||
return '|' + val + '|';
|
||||
},
|
||||
diffBuilder = jasmineUnderTest.DiffBuilder({prettyPrinter: prettyPrinter});
|
||||
|
||||
diffBuilder.withPath('foo', function() {
|
||||
diffBuilder.record('actual', 'expected');
|
||||
});
|
||||
|
||||
expect(diffBuilder.getMessage()).toEqual("Expected $.foo = |actual| to equal |expected|.");
|
||||
});
|
||||
|
||||
|
||||
it("passes the injected pretty-printer to the diff formatter", function() {
|
||||
var diffFormatter = jasmine.createSpy('diffFormatter'),
|
||||
prettyPrinter = function() {},
|
||||
diffBuilder = jasmineUnderTest.DiffBuilder({prettyPrinter: prettyPrinter});
|
||||
|
||||
diffBuilder.withPath('x', function() {
|
||||
diffBuilder.record('bar', 'foo', diffFormatter);
|
||||
});
|
||||
|
||||
expect(diffFormatter).toHaveBeenCalledWith('bar', 'foo', jasmine.anything(), prettyPrinter);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -840,7 +840,7 @@ describe("matchersUtil", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildMessage", function() {
|
||||
describe("buildFailureMessage", function() {
|
||||
|
||||
it("builds an English sentence for a failure case", function() {
|
||||
var actual = "foo",
|
||||
@@ -873,15 +873,17 @@ describe("matchersUtil", function() {
|
||||
expect(message).toEqual("Expected 'foo' to bar 'quux', 'corge'.");
|
||||
});
|
||||
|
||||
it("uses the injected pretty-printer to format the expected", function() {
|
||||
it("uses the injected pretty-printer to format the expecteds and actual", function() {
|
||||
var actual = "foo",
|
||||
expected1 = "qux",
|
||||
expected2 = "grault",
|
||||
name = "toBar",
|
||||
isNot = false,
|
||||
pp = function(value) { return '<' + value + '>'; },
|
||||
matchersUtil = new jasmineUnderTest.MatchersUtil({pp: pp}),
|
||||
message = message = matchersUtil.buildFailureMessage(name, isNot, actual);
|
||||
message = message = matchersUtil.buildFailureMessage(name, isNot, actual, expected1, expected2);
|
||||
|
||||
expect(message).toEqual("Expected <foo> to bar.");
|
||||
expect(message).toEqual("Expected <foo> to bar <qux>, <grault>.");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,4 +59,16 @@ describe("toBe", function() {
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toBe("Expected Object({ foo: 'bar' }) to be Object({ foo: 'bar' }). Tip: To check for deep equality, use .toEqual() instead of .toBe().")
|
||||
});
|
||||
|
||||
it("works with custom object formatters when expected is an object", function() {
|
||||
var formatter = function(x) { return '<' + x.foo + '>'; },
|
||||
prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]),
|
||||
util = new jasmineUnderTest.MatchersUtil({pp: prettyPrinter}),
|
||||
matcher = jasmineUnderTest.matchers.toBe(util),
|
||||
result;
|
||||
|
||||
result = matcher.compare({foo: "bar"}, {foo: "bar"});
|
||||
expect(result.pass).toBe(false);
|
||||
expect(result.message).toBe("Expected <bar> to be <bar>. Tip: To check for deep equality, use .toEqual() instead of .toBe().")
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,14 +97,34 @@ describe("toEqual", function() {
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports extra and missing properties together", function() {
|
||||
it("uses custom object formatters to pretty-print properties", function() {
|
||||
function formatter(x) { return '|' + x + '|'; }
|
||||
|
||||
var actual = {x: {y: 1, z: 2, f: 4}},
|
||||
expected = {x: {y: 1, z: 2, g: 3}},
|
||||
pp = jasmineUnderTest.makePrettyPrinter([formatter]),
|
||||
util = new jasmineUnderTest.MatchersUtil({pp: pp}),
|
||||
matcher = jasmineUnderTest.matchers.toEqual(util),
|
||||
message =
|
||||
"Expected $.x to have properties\n" +
|
||||
" g: 3\n" +
|
||||
" g: |3|\n" +
|
||||
"Expected $.x not to have properties\n" +
|
||||
" f: 4";
|
||||
" f: |4|";
|
||||
|
||||
expect(matcher.compare(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("uses custom object formatters to build diffs", function() {
|
||||
function formatter(x) { return '|' + x + '|'; }
|
||||
|
||||
var actual = [{foo: 4}],
|
||||
expected = [{foo: 5}],
|
||||
prettyPrinter = jasmineUnderTest.makePrettyPrinter([formatter]),
|
||||
util = new jasmineUnderTest.MatchersUtil({pp: prettyPrinter}),
|
||||
matcher = jasmineUnderTest.matchers.toEqual(util),
|
||||
message = "Expected $[0].foo = |4| to equal |5|.";
|
||||
|
||||
expect(matcher.compare(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports extra and missing properties of the root-level object", function() {
|
||||
@@ -277,12 +297,27 @@ describe("toEqual", function() {
|
||||
function Bar() {}
|
||||
|
||||
var actual = {x: new Foo()},
|
||||
expected = {x: new Bar()},
|
||||
message = "Expected $.x to be a kind of Bar, but was Foo({ }).";
|
||||
expected = {x: new Bar()},
|
||||
message = "Expected $.x to be a kind of Bar, but was Foo({ }).";
|
||||
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("uses custom object formatters to report objects with different constructors", function () {
|
||||
function Foo() {}
|
||||
function Bar() {}
|
||||
function formatter(x) { return '|' + x + '|'; }
|
||||
|
||||
var actual = {x: new Foo()},
|
||||
expected = {x: new Bar()},
|
||||
message = "Expected $.x to be a kind of Bar, but was |[object Object]|.",
|
||||
pp = jasmineUnderTest.makePrettyPrinter([formatter]),
|
||||
util = new jasmineUnderTest.MatchersUtil({pp: pp}),
|
||||
matcher = jasmineUnderTest.matchers.toEqual(util);
|
||||
|
||||
expect(matcher.compare(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("reports type mismatches at the root level", function () {
|
||||
function Foo() {}
|
||||
function Bar() {}
|
||||
@@ -803,6 +838,20 @@ describe("toEqual", function() {
|
||||
expect(compareEquals(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("uses custom object formatters when the actual array is longer", function() {
|
||||
function formatter(x) { return '|' + x + '|'; }
|
||||
|
||||
var actual = [1, 1, 2, 3, 5],
|
||||
expected = [1, 1, 2, 3],
|
||||
pp = jasmineUnderTest.makePrettyPrinter([formatter]),
|
||||
util = new jasmineUnderTest.MatchersUtil({pp: pp}),
|
||||
matcher = jasmineUnderTest.matchers.toEqual(util),
|
||||
message = 'Expected $.length = |5| to equal |4|.\n' +
|
||||
'Unexpected $[4] = |5| in array.';
|
||||
|
||||
expect(matcher.compare(actual, expected).message).toEqual(message);
|
||||
});
|
||||
|
||||
it("expected array is longer", function() {
|
||||
var actual = [1, 1, 2, 3],
|
||||
expected = [1, 1, 2, 3, 5],
|
||||
|
||||
Reference in New Issue
Block a user