From ce886e20e48cb2866c5a7f5e489217cf780dc429 Mon Sep 17 00:00:00 2001 From: gvanhove Date: Sat, 12 Mar 2011 13:04:30 -0800 Subject: [PATCH 1/8] commit updated version into jasmine.js --- lib/jasmine-core/jasmine.js | 2 +- pages | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 8bba9262..e7c6ab33 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -2472,5 +2472,5 @@ jasmine.version_= { "major": 1, "minor": 1, "build": 0, - "revision": 1320442951 + "revision": 1299963843 }; diff --git a/pages b/pages index a9d577eb..d08ce2de 160000 --- a/pages +++ b/pages @@ -1 +1 @@ -Subproject commit a9d577eb45346c088c857af5bb301540c2a121f4 +Subproject commit d08ce2de245d6782c09c652045a12e93af0dc7ec From 992367dcbc7d114d95fc139f889c1c63043b073a Mon Sep 17 00:00:00 2001 From: gvanhove Date: Wed, 9 Mar 2011 18:56:28 -0800 Subject: [PATCH 2/8] New matcher "hashContaining" similar to rspec's hash_including --- lib/jasmine-core/jasmine.js | 52 +++++++++++++++++++++++ spec/core/MatchersSpec.js | 84 +++++++++++++++++++++++++++++++++++++ src/core/Env.js | 8 ++++ src/core/Matchers.js | 29 +++++++++++++ src/core/base.js | 15 +++++++ 5 files changed, 188 insertions(+) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index e7c6ab33..2093f95d 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -196,6 +196,21 @@ jasmine.any = function(clazz) { return new jasmine.Matchers.Any(clazz); }; +/** + * Returns a matchable subset of a hash/JSON object. For use in expectations when you don't care about all of the + * attributes on the object. + * + * @example + * // don't care about any other attributes than foo. + * expect(mySpy).toHaveBeenCalledWith(jasmine.hashContaining({foo: "bar"}); + * + * @param sample {Object} sample + * @returns matchable object for the sample + */ +jasmine.hashContaining = function (sample) { + return new jasmine.Matchers.HashContaining(sample); +}; + /** * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. * @@ -922,6 +937,14 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { return b.matches(a); } + if (a instanceof jasmine.Matchers.HashContaining) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.HashContaining) { + return b.matches(a); + } + if (jasmine.isString_(a) && jasmine.isString_(b)) { return (a == b); } @@ -1477,6 +1500,35 @@ jasmine.Matchers.Any.prototype.toString = function() { return ''; }; +jasmine.Matchers.HashContaining = function (sample) { + this.sample = sample; +}; + +jasmine.Matchers.HashContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var env = jasmine.getEnv(); + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Matchers.HashContaining.prototype.toString = function () { + return ""; +}; /** * @constructor */ diff --git a/spec/core/MatchersSpec.js b/spec/core/MatchersSpec.js index cb58208d..e655bf0a 100644 --- a/spec/core/MatchersSpec.js +++ b/spec/core/MatchersSpec.js @@ -830,6 +830,90 @@ describe("jasmine.Matchers", function() { }); }); + describe("HashContaining", function () { + describe("with an empty hash", function () { + var containing; + beforeEach(function () { + containing = new jasmine.Matchers.HashContaining({}); + }); + it("matches everything", function () { + expect(containing.matches("foo", [], [])).toBe(true); + }); + + it("says it didn't expect to contain anything", function () { + expect(containing.toString()).toEqual(""); + }); + }); + + describe("with a hash with items in it", function () { + var containing, mismatchKeys, mismatchValues; + beforeEach(function () { + mismatchKeys = []; + mismatchValues = []; + containing = new jasmine.Matchers.HashContaining({foo: "fooVal", bar: "barVal"}); + }); + + it("doesn't match an empty object", function () { + expect(containing.matches({}, mismatchKeys, mismatchValues)).toBe(false); + }); + + it("doesn't match an object with none of the specified options", function () { + expect(containing.matches({baz:"stuff"}, mismatchKeys, mismatchValues)).toBe(false); + }); + + it("adds a message for each missing key", function () { + containing.matches({foo: "fooVal"}, mismatchKeys, mismatchValues); + expect(mismatchKeys.length).toEqual(1); + }); + + it("doesn't match an object when the values are different", function () { + expect(containing.matches({foo:"notFoo", bar:"notBar"}, mismatchKeys, mismatchValues)).toBe(false); + }); + + it("adds a message when values don't match", function () { + containing.matches({foo: "fooVal", bar: "notBar"}, mismatchKeys, mismatchValues); + expect(mismatchValues.length).toEqual(1); + }); + + it("doesn't match an object with only one of the values matching", function () { + expect(containing.matches({foo:"notFoo", bar:"barVal"}, mismatchKeys, mismatchValues)).toBe(false); + }); + + it("matches when all the values are the same", function () { + expect(containing.matches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues)).toBe(true); + }); + + it("matches when there are additional values", function () { + expect(containing.matches({foo: "fooVal", bar: "barVal", baz: "bazVal"}, mismatchKeys, mismatchValues)).toBe(true); + }); + + it("doesn't modify missingKeys or missingValues when match is successful", function () { + containing.matches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues); + expect(mismatchKeys.length).toEqual(0); + expect(mismatchValues.length).toEqual(0); + }); + + it("says what it expects to contain", function () { + expect(containing.toString()).toEqual(""); + }); + }); + + describe("in real life", function () { + var method; + beforeEach(function () { + method = jasmine.createSpy("method"); + method({a:"b", c:"d"}); + }); + it("works correctly for positive matches", function () { + expect(method).toHaveBeenCalledWith(jasmine.hashContaining({a:"b"})); + }); + + it("works correctly for negative matches", function () { + expect(method).not.toHaveBeenCalledWith(jasmine.hashContaining({z:"x"})); + }); + }); + }); + describe("all matchers", function() { it("should return null, for future-proofing, since we might eventually allow matcher chaining", function() { expect(match(true).toBe(true)).toBeUndefined(); diff --git a/src/core/Env.js b/src/core/Env.js index 1ba67597..bf72c88c 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -238,6 +238,14 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { return b.matches(a); } + if (a instanceof jasmine.Matchers.HashContaining) { + return a.matches(b); + } + + if (b instanceof jasmine.Matchers.HashContaining) { + return b.matches(a); + } + if (jasmine.isString_(a) && jasmine.isString_(b)) { return (a == b); } diff --git a/src/core/Matchers.js b/src/core/Matchers.js index f3bf0579..122e32b4 100644 --- a/src/core/Matchers.js +++ b/src/core/Matchers.js @@ -369,3 +369,32 @@ jasmine.Matchers.Any.prototype.toString = function() { return ''; }; +jasmine.Matchers.HashContaining = function (sample) { + this.sample = sample; +}; + +jasmine.Matchers.HashContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) { + mismatchKeys = mismatchKeys || []; + mismatchValues = mismatchValues || []; + + var env = jasmine.getEnv(); + + var hasKey = function(obj, keyName) { + return obj != null && obj[keyName] !== jasmine.undefined; + }; + + for (var property in this.sample) { + if (!hasKey(other, property) && hasKey(this.sample, property)) { + mismatchKeys.push("expected has key '" + property + "', but missing from actual."); + } + else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) { + mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual."); + } + } + + return (mismatchKeys.length === 0 && mismatchValues.length === 0); +}; + +jasmine.Matchers.HashContaining.prototype.toString = function () { + return ""; +}; diff --git a/src/core/base.js b/src/core/base.js index bb0c5550..cf84c07d 100755 --- a/src/core/base.js +++ b/src/core/base.js @@ -196,6 +196,21 @@ jasmine.any = function(clazz) { return new jasmine.Matchers.Any(clazz); }; +/** + * Returns a matchable subset of a hash/JSON object. For use in expectations when you don't care about all of the + * attributes on the object. + * + * @example + * // don't care about any other attributes than foo. + * expect(mySpy).toHaveBeenCalledWith(jasmine.hashContaining({foo: "bar"}); + * + * @param sample {Object} sample + * @returns matchable object for the sample + */ +jasmine.hashContaining = function (sample) { + return new jasmine.Matchers.HashContaining(sample); +}; + /** * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks. * From 7158fc24262db0318f4595e7bec0531e1970e5d0 Mon Sep 17 00:00:00 2001 From: gvanhove Date: Thu, 10 Mar 2011 07:59:19 -0800 Subject: [PATCH 3/8] Rename hashContaining to objectContaining, since this is javascript. Also call the toString from prettyPrinter --- lib/jasmine-core/jasmine.js | 14 +++++++------- spec/core/MatchersSpec.js | 12 ++++++------ spec/core/PrettyPrintSpec.js | 7 +++++++ src/core/Env.js | 4 ++-- src/core/Matchers.js | 8 ++++---- src/core/PrettyPrinter.js | 2 ++ src/core/base.js | 8 ++++---- 7 files changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 2093f95d..f1099d17 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -207,8 +207,8 @@ jasmine.any = function(clazz) { * @param sample {Object} sample * @returns matchable object for the sample */ -jasmine.hashContaining = function (sample) { - return new jasmine.Matchers.HashContaining(sample); +jasmine.objectContaining = function (sample) { + return new jasmine.Matchers.ObjectContaining(sample); }; /** @@ -937,11 +937,11 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { return b.matches(a); } - if (a instanceof jasmine.Matchers.HashContaining) { + if (a instanceof jasmine.Matchers.ObjectContaining) { return a.matches(b); } - if (b instanceof jasmine.Matchers.HashContaining) { + if (b instanceof jasmine.Matchers.ObjectContaining) { return b.matches(a); } @@ -1500,11 +1500,11 @@ jasmine.Matchers.Any.prototype.toString = function() { return ''; }; -jasmine.Matchers.HashContaining = function (sample) { +jasmine.Matchers.ObjectContaining = function (sample) { this.sample = sample; }; -jasmine.Matchers.HashContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) { +jasmine.Matchers.ObjectContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) { mismatchKeys = mismatchKeys || []; mismatchValues = mismatchValues || []; @@ -1526,7 +1526,7 @@ jasmine.Matchers.HashContaining.prototype.matches = function(other, mismatchKeys return (mismatchKeys.length === 0 && mismatchValues.length === 0); }; -jasmine.Matchers.HashContaining.prototype.toString = function () { +jasmine.Matchers.ObjectContaining.prototype.toString = function () { return ""; }; /** diff --git a/spec/core/MatchersSpec.js b/spec/core/MatchersSpec.js index e655bf0a..ceaafc01 100644 --- a/spec/core/MatchersSpec.js +++ b/spec/core/MatchersSpec.js @@ -834,14 +834,14 @@ describe("jasmine.Matchers", function() { describe("with an empty hash", function () { var containing; beforeEach(function () { - containing = new jasmine.Matchers.HashContaining({}); + containing = new jasmine.Matchers.ObjectContaining({}); }); it("matches everything", function () { expect(containing.matches("foo", [], [])).toBe(true); }); it("says it didn't expect to contain anything", function () { - expect(containing.toString()).toEqual(""); + expect(containing.toString()).toEqual(""); }); }); @@ -850,7 +850,7 @@ describe("jasmine.Matchers", function() { beforeEach(function () { mismatchKeys = []; mismatchValues = []; - containing = new jasmine.Matchers.HashContaining({foo: "fooVal", bar: "barVal"}); + containing = new jasmine.Matchers.ObjectContaining({foo: "fooVal", bar: "barVal"}); }); it("doesn't match an empty object", function () { @@ -894,7 +894,7 @@ describe("jasmine.Matchers", function() { }); it("says what it expects to contain", function () { - expect(containing.toString()).toEqual(""); + expect(containing.toString()).toEqual(""); }); }); @@ -905,11 +905,11 @@ describe("jasmine.Matchers", function() { method({a:"b", c:"d"}); }); it("works correctly for positive matches", function () { - expect(method).toHaveBeenCalledWith(jasmine.hashContaining({a:"b"})); + expect(method).toHaveBeenCalledWith(jasmine.objectContaining({a:"b"})); }); it("works correctly for negative matches", function () { - expect(method).not.toHaveBeenCalledWith(jasmine.hashContaining({z:"x"})); + expect(method).not.toHaveBeenCalledWith(jasmine.objectContaining({z:"x"})); }); }); }); diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index 37f71041..2faea310 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -83,5 +83,12 @@ describe("jasmine.pp", function () { expect(jasmine.pp(jasmine.createSpy("something"))).toEqual("spy on something"); }); + it("calls toString for ObjectContaining objects", function () { + var containing = new jasmine.Matchers.ObjectContaining({}); + spyOn(containing, "toString").andReturn("stringified!"); + + expect(jasmine.pp(containing)).toEqual("stringified!"); + expect(containing.toString).toHaveBeenCalled(); + }); }); diff --git a/src/core/Env.js b/src/core/Env.js index bf72c88c..e9a672de 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -238,11 +238,11 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { return b.matches(a); } - if (a instanceof jasmine.Matchers.HashContaining) { + if (a instanceof jasmine.Matchers.ObjectContaining) { return a.matches(b); } - if (b instanceof jasmine.Matchers.HashContaining) { + if (b instanceof jasmine.Matchers.ObjectContaining) { return b.matches(a); } diff --git a/src/core/Matchers.js b/src/core/Matchers.js index 122e32b4..ddcc6600 100644 --- a/src/core/Matchers.js +++ b/src/core/Matchers.js @@ -369,11 +369,11 @@ jasmine.Matchers.Any.prototype.toString = function() { return ''; }; -jasmine.Matchers.HashContaining = function (sample) { +jasmine.Matchers.ObjectContaining = function (sample) { this.sample = sample; }; -jasmine.Matchers.HashContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) { +jasmine.Matchers.ObjectContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) { mismatchKeys = mismatchKeys || []; mismatchValues = mismatchValues || []; @@ -395,6 +395,6 @@ jasmine.Matchers.HashContaining.prototype.matches = function(other, mismatchKeys return (mismatchKeys.length === 0 && mismatchValues.length === 0); }; -jasmine.Matchers.HashContaining.prototype.toString = function () { - return ""; +jasmine.Matchers.ObjectContaining.prototype.toString = function () { + return ""; }; diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index 7d890c02..d44bb24d 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -25,6 +25,8 @@ jasmine.PrettyPrinter.prototype.format = function(value) { this.emitScalar(''); } else if (value instanceof jasmine.Matchers.Any) { this.emitScalar(value.toString()); + } else if (value instanceof jasmine.Matchers.ObjectContaining) { + this.emitScalar(value.toString()); } else if (typeof value === 'string') { this.emitString(value); } else if (jasmine.isSpy(value)) { diff --git a/src/core/base.js b/src/core/base.js index cf84c07d..3a61b3d8 100755 --- a/src/core/base.js +++ b/src/core/base.js @@ -197,18 +197,18 @@ jasmine.any = function(clazz) { }; /** - * Returns a matchable subset of a hash/JSON object. For use in expectations when you don't care about all of the + * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the * attributes on the object. * * @example * // don't care about any other attributes than foo. - * expect(mySpy).toHaveBeenCalledWith(jasmine.hashContaining({foo: "bar"}); + * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"}); * * @param sample {Object} sample * @returns matchable object for the sample */ -jasmine.hashContaining = function (sample) { - return new jasmine.Matchers.HashContaining(sample); +jasmine.objectContaining = function (sample) { + return new jasmine.Matchers.ObjectContaining(sample); }; /** From 4f2fcff15ab307144b408a826c8b3055eb6d510e Mon Sep 17 00:00:00 2001 From: gvanhove Date: Mon, 14 Mar 2011 18:50:08 -0700 Subject: [PATCH 4/8] Use jasmineToString for printing out complicated matchers --- spec/core/MatchersSpec.js | 41 ++++++++++++++++++++++++++++++++++++ spec/core/PrettyPrintSpec.js | 10 ++++----- src/core/Matchers.js | 2 +- src/core/PrettyPrinter.js | 6 ++---- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/spec/core/MatchersSpec.js b/spec/core/MatchersSpec.js index ceaafc01..0326b68f 100644 --- a/spec/core/MatchersSpec.js +++ b/spec/core/MatchersSpec.js @@ -914,6 +914,47 @@ describe("jasmine.Matchers", function() { }); }); + describe("Matchers.Any", function () { + var any; + describe(".jasmineToString", function () { + describe("with Object", function () { + it ("says it's looking for an object", function () { + any = jasmine.any(Object); + expect(any.jasmineToString()).toMatch(//); + }); + }); + + describe("with Function", function () { + it ("says it's looking for a function", function () { + any = jasmine.any(Function); + expect(any.jasmineToString()).toMatch(//); + }); + }); + + describe("with String", function () { + it ("says it's looking for a string", function () { + any = jasmine.any(String); + expect(any.jasmineToString()).toMatch(//); + }); + }); + + describe("with Number", function () { + it ("says it's looking for a number", function () { + any = jasmine.any(Number); + expect(any.jasmineToString()).toMatch(//); + }); + }); + + describe("with some other defined 'class'", function () { + it ("says it's looking for an object", function () { + function MyClass () {} + any = jasmine.any(MyClass); + expect(any.jasmineToString()).toMatch(//); + }); + }); + }); + }); + describe("all matchers", function() { it("should return null, for future-proofing, since we might eventually allow matcher chaining", function() { expect(match(true).toBe(true)).toBeUndefined(); diff --git a/spec/core/PrettyPrintSpec.js b/spec/core/PrettyPrintSpec.js index 2faea310..becf8a61 100644 --- a/spec/core/PrettyPrintSpec.js +++ b/spec/core/PrettyPrintSpec.js @@ -83,12 +83,12 @@ describe("jasmine.pp", function () { expect(jasmine.pp(jasmine.createSpy("something"))).toEqual("spy on something"); }); - it("calls toString for ObjectContaining objects", function () { - var containing = new jasmine.Matchers.ObjectContaining({}); - spyOn(containing, "toString").andReturn("stringified!"); + it("should stringify objects that implement jasmineToString", function () { + var obj = { + jasmineToString: function () { return "strung"; } + }; - expect(jasmine.pp(containing)).toEqual("stringified!"); - expect(containing.toString).toHaveBeenCalled(); + expect(jasmine.pp(obj)).toEqual("strung"); }); }); diff --git a/src/core/Matchers.js b/src/core/Matchers.js index ddcc6600..e2072021 100644 --- a/src/core/Matchers.js +++ b/src/core/Matchers.js @@ -365,7 +365,7 @@ jasmine.Matchers.Any.prototype.matches = function(other) { return other instanceof this.expectedClass; }; -jasmine.Matchers.Any.prototype.toString = function() { +jasmine.Matchers.Any.prototype.jasmineToString = function() { return ''; }; diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index d44bb24d..c7845107 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -23,10 +23,8 @@ jasmine.PrettyPrinter.prototype.format = function(value) { this.emitScalar('null'); } else if (value === jasmine.getGlobal()) { this.emitScalar(''); - } else if (value instanceof jasmine.Matchers.Any) { - this.emitScalar(value.toString()); - } else if (value instanceof jasmine.Matchers.ObjectContaining) { - this.emitScalar(value.toString()); + } else if (value.hasOwnProperty("jasmineToString")) { + this.emitScalar(value.jasmineToString()); } else if (typeof value === 'string') { this.emitString(value); } else if (jasmine.isSpy(value)) { From 67ec0af2548dc02a5b3845477598bc3100fc583c Mon Sep 17 00:00:00 2001 From: gvanhove Date: Tue, 15 Mar 2011 08:23:38 -0700 Subject: [PATCH 5/8] use jasmineMatches for equality testing of complicated matchers --- spec/core/MatchersSpec.js | 148 ++++++++++++++++++++++++++++++++++++++ src/core/Env.js | 8 +-- src/core/Matchers.js | 2 +- src/core/PrettyPrinter.js | 2 +- 4 files changed, 154 insertions(+), 6 deletions(-) diff --git a/spec/core/MatchersSpec.js b/spec/core/MatchersSpec.js index 0326b68f..19411df1 100644 --- a/spec/core/MatchersSpec.js +++ b/spec/core/MatchersSpec.js @@ -352,6 +352,33 @@ describe("jasmine.Matchers", function() { }]).toEqual(["a", jasmine.any(Function)])).toPass(); }); + describe("toEqual with an object implementing jasmineMatches", function () { + var matcher; + beforeEach(function () { + matcher = { + jasmineMatches: jasmine.createSpy("jasmineMatches") + }; + }); + + describe("on the left side", function () { + it("uses the jasmineMatches function", function () { + matcher.jasmineMatches.andReturn(false); + expect(match(matcher).toEqual("foo")).toFail(); + matcher.jasmineMatches.andReturn(true); + expect(match(matcher).toEqual("foo")).toPass(); + }); + }); + + describe("on the right side", function () { + it("uses the jasmineMatches function", function () { + matcher.jasmineMatches.andReturn(false); + expect(match("foo").toEqual(matcher)).toFail(); + matcher.jasmineMatches.andReturn(true); + expect(match("foo").toEqual(matcher)).toPass(); + }); + }); + }); + it("toEqual handles circular objects ok", function() { expect(match({foo: "bar", baz: jasmine.undefined}).toEqual({foo: "bar", baz: jasmine.undefined})).toPass(); expect(match({foo:['bar','baz','quux']}).toEqual({foo:['bar','baz','quux']})).toPass(); @@ -953,6 +980,127 @@ describe("jasmine.Matchers", function() { }); }); }); + + describe(".jasmineMatches", function () { + describe("with Object", function () { + beforeEach(function () { + any = jasmine.any(Object); + }); + + it("matches an empty object", function () { + expect(any.jasmineMatches({})).toEqual(true); + }); + + it("matches a newed up object", function () { + expect(any.jasmineMatches(new Object())).toEqual(true); + }); + + it("doesn't match a string", function () { + expect(any.jasmineMatches("")).toEqual(false); + }); + + it("doesn't match a number", function () { + expect(any.jasmineMatches(123)).toEqual(false); + }); + + it("doesn't match a function", function () { + expect(any.jasmineMatches(function () {})).toEqual(false); + }); + }); + + describe("with Function", function () { + beforeEach(function () { + any = jasmine.any(Function); + }); + + it("doesn't match an object", function () { + expect(any.jasmineMatches({})).toEqual(false); + }); + + it("doesn't match a string", function () { + expect(any.jasmineMatches("")).toEqual(false); + }); + + it("doesn't match a number", function () { + expect(any.jasmineMatches(123)).toEqual(false); + }); + + it("matches a function", function () { + expect(any.jasmineMatches(function () {})).toEqual(true); + }); + }); + + describe("with Number", function () { + beforeEach(function () { + any = jasmine.any(Number); + }); + + it("doesn't match an object", function () { + expect(any.jasmineMatches({})).toEqual(false); + }); + + it("doesn't match a string", function () { + expect(any.jasmineMatches("")).toEqual(false); + }); + + it("matches a number", function () { + expect(any.jasmineMatches(123)).toEqual(true); + }); + + it("doesn't match a function", function () { + expect(any.jasmineMatches(function () {})).toEqual(false); + }); + }); + + describe("with String", function () { + beforeEach(function () { + any = jasmine.any(String); + }); + + it("doesn't match an object", function () { + expect(any.jasmineMatches({})).toEqual(false); + }); + + it("matches a string", function () { + expect(any.jasmineMatches("")).toEqual(true); + }); + + it("doesn't match a number", function () { + expect(any.jasmineMatches(123)).toEqual(false); + }); + + it("doesn't match a function", function () { + expect(any.jasmineMatches(function () {})).toEqual(false); + }); + }); + + describe("with some defined 'class'", function () { + function MyClass () {} + beforeEach(function () { + any = jasmine.any(MyClass); + }); + + it("doesn't match an object", function () { + expect(any.jasmineMatches({})).toEqual(false); + }); + + it("doesn't match a string", function () { + expect(any.jasmineMatches("")).toEqual(false); + }); + + it("doesn't match a number", function () { + expect(any.jasmineMatches(123)).toEqual(false); + }); + + it("doesn't match a function", function () { + expect(any.jasmineMatches(function () {})).toEqual(false); + }); + + it("matches an instance of the defined class", function () { + expect(any.jasmineMatches(new MyClass())).toEqual(true); + }); + }); + }); }); describe("all matchers", function() { diff --git a/src/core/Env.js b/src/core/Env.js index e9a672de..4ebc0963 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -230,12 +230,12 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) { return a.getTime() == b.getTime(); } - if (a instanceof jasmine.Matchers.Any) { - return a.matches(b); + if (a.jasmineMatches) { + return a.jasmineMatches(b); } - if (b instanceof jasmine.Matchers.Any) { - return b.matches(a); + if (b.jasmineMatches) { + return b.jasmineMatches(a); } if (a instanceof jasmine.Matchers.ObjectContaining) { diff --git a/src/core/Matchers.js b/src/core/Matchers.js index e2072021..de372575 100644 --- a/src/core/Matchers.js +++ b/src/core/Matchers.js @@ -345,7 +345,7 @@ jasmine.Matchers.Any = function(expectedClass) { this.expectedClass = expectedClass; }; -jasmine.Matchers.Any.prototype.matches = function(other) { +jasmine.Matchers.Any.prototype.jasmineMatches = function(other) { if (this.expectedClass == String) { return typeof other == 'string' || other instanceof String; } diff --git a/src/core/PrettyPrinter.js b/src/core/PrettyPrinter.js index c7845107..a7d283b6 100644 --- a/src/core/PrettyPrinter.js +++ b/src/core/PrettyPrinter.js @@ -23,7 +23,7 @@ jasmine.PrettyPrinter.prototype.format = function(value) { this.emitScalar('null'); } else if (value === jasmine.getGlobal()) { this.emitScalar(''); - } else if (value.hasOwnProperty("jasmineToString")) { + } else if (value.jasmineToString) { this.emitScalar(value.jasmineToString()); } else if (typeof value === 'string') { this.emitString(value); From 08d72926ffdb3db4486f88fb49e564a5112386a5 Mon Sep 17 00:00:00 2001 From: gvanhove Date: Tue, 15 Mar 2011 18:30:05 -0700 Subject: [PATCH 6/8] More renaming of hash --- spec/core/MatchersSpec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/core/MatchersSpec.js b/spec/core/MatchersSpec.js index 19411df1..fcf7eb62 100644 --- a/spec/core/MatchersSpec.js +++ b/spec/core/MatchersSpec.js @@ -857,8 +857,8 @@ describe("jasmine.Matchers", function() { }); }); - describe("HashContaining", function () { - describe("with an empty hash", function () { + describe("ObjectContaining", function () { + describe("with an empty object", function () { var containing; beforeEach(function () { containing = new jasmine.Matchers.ObjectContaining({}); @@ -872,7 +872,7 @@ describe("jasmine.Matchers", function() { }); }); - describe("with a hash with items in it", function () { + describe("with an object with items in it", function () { var containing, mismatchKeys, mismatchValues; beforeEach(function () { mismatchKeys = []; From ac096f99118ef5c09b346f57f2a4e6dd894d7573 Mon Sep 17 00:00:00 2001 From: gvanhove Date: Tue, 15 Mar 2011 18:40:11 -0700 Subject: [PATCH 7/8] convert objectContaining to use jasmineMatches and jasmineToString --- spec/core/MatchersSpec.js | 24 ++++++++++++------------ src/core/Matchers.js | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/spec/core/MatchersSpec.js b/spec/core/MatchersSpec.js index fcf7eb62..405be7db 100644 --- a/spec/core/MatchersSpec.js +++ b/spec/core/MatchersSpec.js @@ -864,11 +864,11 @@ describe("jasmine.Matchers", function() { containing = new jasmine.Matchers.ObjectContaining({}); }); it("matches everything", function () { - expect(containing.matches("foo", [], [])).toBe(true); + expect(containing.jasmineMatches("foo", [], [])).toBe(true); }); it("says it didn't expect to contain anything", function () { - expect(containing.toString()).toEqual(""); + expect(containing.jasmineToString()).toEqual(""); }); }); @@ -881,47 +881,47 @@ describe("jasmine.Matchers", function() { }); it("doesn't match an empty object", function () { - expect(containing.matches({}, mismatchKeys, mismatchValues)).toBe(false); + expect(containing.jasmineMatches({}, mismatchKeys, mismatchValues)).toBe(false); }); it("doesn't match an object with none of the specified options", function () { - expect(containing.matches({baz:"stuff"}, mismatchKeys, mismatchValues)).toBe(false); + expect(containing.jasmineMatches({baz:"stuff"}, mismatchKeys, mismatchValues)).toBe(false); }); it("adds a message for each missing key", function () { - containing.matches({foo: "fooVal"}, mismatchKeys, mismatchValues); + containing.jasmineMatches({foo: "fooVal"}, mismatchKeys, mismatchValues); expect(mismatchKeys.length).toEqual(1); }); it("doesn't match an object when the values are different", function () { - expect(containing.matches({foo:"notFoo", bar:"notBar"}, mismatchKeys, mismatchValues)).toBe(false); + expect(containing.jasmineMatches({foo:"notFoo", bar:"notBar"}, mismatchKeys, mismatchValues)).toBe(false); }); it("adds a message when values don't match", function () { - containing.matches({foo: "fooVal", bar: "notBar"}, mismatchKeys, mismatchValues); + containing.jasmineMatches({foo: "fooVal", bar: "notBar"}, mismatchKeys, mismatchValues); expect(mismatchValues.length).toEqual(1); }); it("doesn't match an object with only one of the values matching", function () { - expect(containing.matches({foo:"notFoo", bar:"barVal"}, mismatchKeys, mismatchValues)).toBe(false); + expect(containing.jasmineMatches({foo:"notFoo", bar:"barVal"}, mismatchKeys, mismatchValues)).toBe(false); }); it("matches when all the values are the same", function () { - expect(containing.matches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues)).toBe(true); + expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues)).toBe(true); }); it("matches when there are additional values", function () { - expect(containing.matches({foo: "fooVal", bar: "barVal", baz: "bazVal"}, mismatchKeys, mismatchValues)).toBe(true); + expect(containing.jasmineMatches({foo: "fooVal", bar: "barVal", baz: "bazVal"}, mismatchKeys, mismatchValues)).toBe(true); }); it("doesn't modify missingKeys or missingValues when match is successful", function () { - containing.matches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues); + containing.jasmineMatches({foo: "fooVal", bar: "barVal"}, mismatchKeys, mismatchValues); expect(mismatchKeys.length).toEqual(0); expect(mismatchValues.length).toEqual(0); }); it("says what it expects to contain", function () { - expect(containing.toString()).toEqual(""); + expect(containing.jasmineToString()).toEqual(""); }); }); diff --git a/src/core/Matchers.js b/src/core/Matchers.js index de372575..4f078f3b 100644 --- a/src/core/Matchers.js +++ b/src/core/Matchers.js @@ -373,7 +373,7 @@ jasmine.Matchers.ObjectContaining = function (sample) { this.sample = sample; }; -jasmine.Matchers.ObjectContaining.prototype.matches = function(other, mismatchKeys, mismatchValues) { +jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) { mismatchKeys = mismatchKeys || []; mismatchValues = mismatchValues || []; @@ -395,6 +395,6 @@ jasmine.Matchers.ObjectContaining.prototype.matches = function(other, mismatchKe return (mismatchKeys.length === 0 && mismatchValues.length === 0); }; -jasmine.Matchers.ObjectContaining.prototype.toString = function () { +jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () { return ""; }; From d70e733f70174b20dd2236611a99683bb8e686dc Mon Sep 17 00:00:00 2001 From: gvanhove Date: Mon, 14 Nov 2011 18:43:13 -0800 Subject: [PATCH 8/8] remove unwanted spaces in it calls, and make the spec counting regex tolerate them if they exist so counts match even when using bad style --- spec/core/MatchersSpec.js | 10 +++++----- tasks/spec.rb | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/core/MatchersSpec.js b/spec/core/MatchersSpec.js index 405be7db..a8e965ac 100644 --- a/spec/core/MatchersSpec.js +++ b/spec/core/MatchersSpec.js @@ -945,35 +945,35 @@ describe("jasmine.Matchers", function() { var any; describe(".jasmineToString", function () { describe("with Object", function () { - it ("says it's looking for an object", function () { + it("says it's looking for an object", function () { any = jasmine.any(Object); expect(any.jasmineToString()).toMatch(//); }); }); describe("with Function", function () { - it ("says it's looking for a function", function () { + it("says it's looking for a function", function () { any = jasmine.any(Function); expect(any.jasmineToString()).toMatch(//); }); }); describe("with String", function () { - it ("says it's looking for a string", function () { + it("says it's looking for a string", function () { any = jasmine.any(String); expect(any.jasmineToString()).toMatch(//); }); }); describe("with Number", function () { - it ("says it's looking for a number", function () { + it("says it's looking for a number", function () { any = jasmine.any(Number); expect(any.jasmineToString()).toMatch(//); }); }); describe("with some other defined 'class'", function () { - it ("says it's looking for an object", function () { + it("says it's looking for an object", function () { function MyClass () {} any = jasmine.any(MyClass); expect(any.jasmineToString()).toMatch(//); diff --git a/tasks/spec.rb b/tasks/spec.rb index 30ef2f7b..2760e00d 100644 --- a/tasks/spec.rb +++ b/tasks/spec.rb @@ -31,7 +31,7 @@ end def count_specs_in(files) files.inject(0) do |count, file| - File.read(file).scan(/\sit\(/) {|s| count += 1} + File.read(file).scan(/\sit\s*\(/) {|s| count += 1} count end end