diff --git a/grunt/config/concat.js b/grunt/config/concat.js index dcc6624e..4fb0bae3 100644 --- a/grunt/config/concat.js +++ b/grunt/config/concat.js @@ -22,12 +22,12 @@ module.exports = { jasmine: { src: [ 'src/core/requireCore.js', + 'src/core/matchers/requireMatchers.js', 'src/core/base.js', 'src/core/util.js', 'src/core/Spec.js', 'src/core/Env.js', 'src/core/JsApiReporter.js', - 'src/core/Matchers', 'src/core/PrettyPrinter', 'src/core/Suite', 'src/core/**/*.js', diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 9c1158e8..7ac6623d 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -42,7 +42,6 @@ getJasmineRequireObj().core = function(jRequire) { j$.Expectation = jRequire.Expectation(); j$.buildExpectationResult = jRequire.buildExpectationResult(); j$.JsApiReporter = jRequire.JsApiReporter(); - j$.matchers = jRequire.matchers(j$); j$.matchersUtil = jRequire.matchersUtil(j$); j$.ObjectContaining = jRequire.ObjectContaining(j$); j$.StringPrettyPrinter = jRequire.StringPrettyPrinter(j$); @@ -52,9 +51,40 @@ getJasmineRequireObj().core = function(jRequire) { j$.Suite = jRequire.Suite(); j$.version = jRequire.version(); + j$.matchers = jRequire.requireMatchers(jRequire); + return j$; }; +getJasmineRequireObj().requireMatchers = function(jRequire) { + var availableMatchers = [ + "toBe", + "toBeCloseTo", + "toBeDefined", + "toBeFalsy", + "toBeGreaterThan", + "toBeLessThan", + "toBeNaN", + "toBeNull", + "toBeTruthy", + "toBeUndefined", + "toContain", + "toEqual", + "toHaveBeenCalled", + "toHaveBeenCalledWith", + "toMatch", + "toThrow" + ], + matchers = {}; + + for (var i = 0; i < availableMatchers.length; i++) { + var name = availableMatchers[i]; + matchers[name] = jRequire[name](); + } + + return matchers; +}; + getJasmineRequireObj().base = function(j$) { j$.unimplementedMethod_ = function() { throw new Error("unimplemented method"); @@ -1536,275 +1566,6 @@ if (typeof window == void 0 && typeof exports == "object") { exports.Suite = jasmineRequire.Suite; } -getJasmineRequireObj().matchers = function() { - matchers = {}; - - matchers.toBe = function() { - return { - compare: function(actual, expected) { - return { - pass: actual === expected - }; - } - }; - }; - - matchers.toBeCloseTo = function() { - return { - compare: function(actual, expected, precision) { - if (precision !== 0) { - precision = precision || 2; - } - - return { - pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) - }; - } - }; - }; - - matchers.toBeDefined = function() { - return { - compare: function(actual) { - return { - pass: (void 0 !== actual) - }; - } - }; - }; - - matchers.toBeFalsy = function() { - return { - compare: function(actual) { - return { - pass: !!!actual - }; - } - }; - }; - - matchers.toBeGreaterThan = function() { - return { - compare: function(actual, expected) { - return { - pass: actual > expected - }; - } - }; - }; - - matchers.toBeLessThan = function() { - return { - - compare: function(actual, expected) { - return { - pass: actual < expected - }; - } - }; - }; - - matchers.toBeNaN = function() { - return { - compare: function(actual) { - var result = { - pass: (actual !== actual) - }; - - if (result.pass) { - result.message = "Expected actual not to be NaN."; - } else { - result.message = "Expected " + j$.pp(actual) + " to be NaN."; - } - - return result; - } - }; - }; - - matchers.toBeNull = function() { - return { - compare: function(actual) { - return { - pass: actual === null - }; - } - }; - }; - - matchers.toBeTruthy = function() { - return { - compare: function(actual) { - return { - pass: !!actual - }; - } - }; - }; - - matchers.toBeUndefined = function() { - return { - compare: function(actual) { - return { - pass: void 0 === actual - }; - } - }; - }; - - matchers.toEqual = function(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - var result = { - pass: false - }; - - result.pass = util.equals(actual, expected, customEqualityTesters); - - return result; - } - }; - }; - - matchers.toHaveBeenCalled = function() { - return { - compare: function(actual) { - var result = {}; - - if (!j$.isSpy(actual)) { - throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); - } - - if (arguments.length > 1) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - result.pass = actual.wasCalled; - - result.message = result.pass ? - "Expected spy " + actual.identity + " not to have been called." : - "Expected spy " + actual.identity + " to have been called."; - - return result; - } - }; - }; - - matchers.toHaveBeenCalledWith = function(util) { - return { - compare: function() { - var args = Array.prototype.slice.call(arguments, 0), - actual = args[0], - expectedArgs = args.slice(1); - - if (!j$.isSpy(actual)) { - throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); - } - - return { - pass: util.contains(actual.argsForCall, expectedArgs) - }; - }, - message: function(actual) { - return { - affirmative: "Expected spy " + actual.identity + " to have been called.", - negative: "Expected spy " + actual.identity + " not to have been called." - }; - } - }; - }; - - matchers.toMatch = function() { - return { - compare: function(actual, expected) { - var regexp = new RegExp(expected); - - return { - pass: regexp.test(actual) - }; - } - }; - }; - - matchers.toThrow = function() { - return { - compare: function(actual, expected) { - var result = { pass: false }, - exception; - - if (typeof actual != "function") { - throw new Error("Actual is not a Function"); - } - - if (expectedCannotBeTreatedAsException()) { - throw new Error("Expected cannot be treated as an exception."); - } - - try { - actual(); - } catch (e) { - exception = new Error(e); - } - - if (!exception) { - result.message = "Expected function to throw an exception."; - return result; - } - - if (void 0 == expected) { - result.pass = true; - result.message = "Expected function not to throw an exception."; - } else if (exception.message == expected) { - result.pass = true; - result.message = "Expected function not to throw an exception \"" + expected + "\"."; - } else if (exception.message == expected.message) { - result.pass = true; - result.message = "Expected function not to throw an exception \"" + expected.message + "\"."; - } else if (expected instanceof RegExp) { - if (expected.test(exception.message)) { - result.pass = true; - result.message = "Expected function not to throw an exception matching " + expected + "."; - } else { - result.pass = false; - result.message = "Expected function to throw an exception matching " + expected + "."; - } - } else { - result.pass = false; - result.message = "Expected function to throw an exception \"" + (expected.message || expected) + "\"."; - } - - return result; - - function expectedCannotBeTreatedAsException() { - return !( - (void 0 == expected) || - (expected instanceof Error) || - (typeof expected == "string") || - (expected instanceof RegExp) - ); - } - } - }; - }; - - matchers.toContain = function(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - - return { - pass: util.contains(actual, expected, customEqualityTesters) - }; - } - }; - }; - - return matchers; -}; - getJasmineRequireObj().matchersUtil = function(j$) { // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? @@ -1982,6 +1743,344 @@ getJasmineRequireObj().matchersUtil = function(j$) { } } }; +getJasmineRequireObj().toBe = function() { + function toBe() { + return { + compare: function(actual, expected) { + return { + pass: actual === expected + }; + } + }; + } + + return toBe; +}; + +getJasmineRequireObj().toBeCloseTo = function() { + + function toBeCloseTo() { + return { + compare: function(actual, expected, precision) { + if (precision !== 0) { + precision = precision || 2; + } + + return { + pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) + }; + } + }; + } + + return toBeCloseTo; +}; + +getJasmineRequireObj().toBeDefined = function() { + function toBeDefined() { + return { + compare: function(actual) { + return { + pass: (void 0 !== actual) + }; + } + }; + } + + return toBeDefined; +}; + +getJasmineRequireObj().toBeFalsy = function() { + function toBeFalsy() { + return { + compare: function(actual) { + return { + pass: !!!actual + }; + } + }; + } + + return toBeFalsy; +}; + +getJasmineRequireObj().toBeGreaterThan = function() { + + function toBeGreaterThan() { + return { + compare: function(actual, expected) { + return { + pass: actual > expected + }; + } + }; + } + + return toBeGreaterThan; +}; + + +getJasmineRequireObj().toBeLessThan = function() { + function toBeLessThan() { + return { + + compare: function(actual, expected) { + return { + pass: actual < expected + }; + } + }; + } + + return toBeLessThan; +}; +getJasmineRequireObj().toBeNaN = function() { + + function toBeNaN() { + return { + compare: function(actual) { + var result = { + pass: (actual !== actual) + }; + + if (result.pass) { + result.message = "Expected actual not to be NaN."; + } else { + result.message = "Expected " + j$.pp(actual) + " to be NaN."; + } + + return result; + } + }; + } + + return toBeNaN; +}; + +getJasmineRequireObj().toBeNull = function() { + + function toBeNull() { + return { + compare: function(actual) { + return { + pass: actual === null + }; + } + }; + } + + return toBeNull; +}; + +getJasmineRequireObj().toBeTruthy = function() { + + function toBeTruthy() { + return { + compare: function(actual) { + return { + pass: !!actual + }; + } + }; + } + + return toBeTruthy; +}; + +getJasmineRequireObj().toBeUndefined = function() { + + function toBeUndefined() { + return { + compare: function(actual) { + return { + pass: void 0 === actual + }; + } + }; + } + + return toBeUndefined; +}; + +getJasmineRequireObj().toContain = function() { + function toContain(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + + return { + pass: util.contains(actual, expected, customEqualityTesters) + }; + } + }; + } + + return toContain; +}; + +getJasmineRequireObj().toEqual = function() { + + function toEqual(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + var result = { + pass: false + }; + + result.pass = util.equals(actual, expected, customEqualityTesters); + + return result; + } + }; + } + + return toEqual; +}; + +getJasmineRequireObj().toHaveBeenCalled = function() { + + function toHaveBeenCalled() { + return { + compare: function(actual) { + var result = {}; + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + if (arguments.length > 1) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + result.pass = actual.wasCalled; + + result.message = result.pass ? + "Expected spy " + actual.identity + " not to have been called." : + "Expected spy " + actual.identity + " to have been called."; + + return result; + } + }; + } + + return toHaveBeenCalled; +}; + +getJasmineRequireObj().toHaveBeenCalledWith = function() { + + function toHaveBeenCalledWith(util) { + return { + compare: function() { + var args = Array.prototype.slice.call(arguments, 0), + actual = args[0], + expectedArgs = args.slice(1); + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + return { + pass: util.contains(actual.argsForCall, expectedArgs) + }; + }, + message: function(actual) { + return { + affirmative: "Expected spy " + actual.identity + " to have been called.", + negative: "Expected spy " + actual.identity + " not to have been called." + }; + } + }; + } + + return toHaveBeenCalledWith; +}; + +getJasmineRequireObj().toMatch = function() { + + function toMatch() { + return { + compare: function(actual, expected) { + var regexp = new RegExp(expected); + + return { + pass: regexp.test(actual) + }; + } + }; + } + + return toMatch; +}; + +getJasmineRequireObj().toThrow = function() { + + function toThrow() { + return { + compare: function(actual, expected) { + var result = { pass: false }, + exception; + + if (typeof actual != "function") { + throw new Error("Actual is not a Function"); + } + + if (expectedCannotBeTreatedAsException()) { + throw new Error("Expected cannot be treated as an exception."); + } + + try { + actual(); + } catch (e) { + exception = new Error(e); + } + + if (!exception) { + result.message = "Expected function to throw an exception."; + return result; + } + + if (void 0 == expected) { + result.pass = true; + result.message = "Expected function not to throw an exception."; + } else if (exception.message == expected) { + result.pass = true; + result.message = "Expected function not to throw an exception \"" + expected + "\"."; + } else if (exception.message == expected.message) { + result.pass = true; + result.message = "Expected function not to throw an exception \"" + expected.message + "\"."; + } else if (expected instanceof RegExp) { + if (expected.test(exception.message)) { + result.pass = true; + result.message = "Expected function not to throw an exception matching " + expected + "."; + } else { + result.pass = false; + result.message = "Expected function to throw an exception matching " + expected + "."; + } + } else { + result.pass = false; + result.message = "Expected function to throw an exception \"" + (expected.message || expected) + "\"."; + } + + return result; + + function expectedCannotBeTreatedAsException() { + return !( + (void 0 == expected) || + (expected instanceof Error) || + (typeof expected == "string") || + (expected instanceof RegExp) + ); + } + } + }; + } + + return toThrow; +}; + getJasmineRequireObj().version = function() { return "2.0.0-alpha"; }; \ No newline at end of file diff --git a/spec/core/matchersUtilSpec.js b/spec/core/matchers/matchersUtilSpec.js similarity index 100% rename from spec/core/matchersUtilSpec.js rename to spec/core/matchers/matchersUtilSpec.js diff --git a/spec/core/matchers/toBeCloseToSpec.js b/spec/core/matchers/toBeCloseToSpec.js new file mode 100644 index 00000000..c7975bd0 --- /dev/null +++ b/spec/core/matchers/toBeCloseToSpec.js @@ -0,0 +1,51 @@ +describe("toBeCloseTo", function() { + it("passes when within two decimal places by default", function() { + var matcher = j$.matchers.toBeCloseTo(), + result; + + result = matcher.compare(0, 0); + expect(result.pass).toBe(true); + + result = matcher.compare(0, 0.001); + expect(result.pass).toBe(true); + }); + + it("fails when not within two decimal places by default", function() { + var matcher = j$.matchers.toBeCloseTo(), + result; + + result = matcher.compare(0, 0.01); + expect(result.pass).toBe(false); + }); + + it("accepts an optional precision argument", function() { + var matcher = j$.matchers.toBeCloseTo(), + result; + + result = matcher.compare(0, 0.1, 0); + expect(result.pass).toBe(true); + + result = matcher.compare(0, 0.0001, 3); + expect(result.pass).toBe(true); + }); + + it("rounds expected values", function() { + var matcher = j$.matchers.toBeCloseTo(), + result; + + result = matcher.compare(1.23, 1.229); + expect(result.pass).toBe(true); + + result = matcher.compare(1.23, 1.226); + expect(result.pass).toBe(true); + + result = matcher.compare(1.23, 1.225); + expect(result.pass).toBe(true); + + result = matcher.compare(1.23, 1.2249999); + expect(result.pass).toBe(false); + + result = matcher.compare(1.23, 1.234); + expect(result.pass).toBe(true); + }); +}); diff --git a/spec/core/matchers/toBeDefinedSpec.js b/spec/core/matchers/toBeDefinedSpec.js new file mode 100644 index 00000000..7e6626a6 --- /dev/null +++ b/spec/core/matchers/toBeDefinedSpec.js @@ -0,0 +1,18 @@ +describe("toBeDefined", function() { + it("matches for defined values", function() { + var matcher = j$.matchers.toBeDefined(), + result; + + + result = matcher.compare('foo'); + expect(result.pass).toBe(true); + }); + + it("fails when matching undefined values", function() { + var matcher = j$.matchers.toBeDefined(), + result; + + result = matcher.compare(void 0); + expect(result.pass).toBe(false); + }) +}); diff --git a/spec/core/matchers/toBeFalsySpec.js b/spec/core/matchers/toBeFalsySpec.js new file mode 100644 index 00000000..aa612838 --- /dev/null +++ b/spec/core/matchers/toBeFalsySpec.js @@ -0,0 +1,38 @@ +describe("toBeFalsy", function() { + it("passes for 'falsy' values", function() { + var matcher = j$.matchers.toBeFalsy(), + result; + + result = matcher.compare(false); + expect(result.pass).toBe(true); + + result = matcher.compare(0); + expect(result.pass).toBe(true); + + result = matcher.compare(''); + expect(result.pass).toBe(true); + + result = matcher.compare(null); + expect(result.pass).toBe(true); + + result = matcher.compare(void 0); + expect(result.pass).toBe(true); + }); + + it("fails for 'truthy' values", function() { + var matcher = j$.matchers.toBeFalsy(), + result; + + result = matcher.compare(true); + expect(result.pass).toBe(false); + + result = matcher.compare(1); + expect(result.pass).toBe(false); + + result = matcher.compare("foo"); + expect(result.pass).toBe(false); + + result = matcher.compare({}); + expect(result.pass).toBe(false); + }); +}); diff --git a/spec/core/matchers/toBeGreaterThanSpec.js b/spec/core/matchers/toBeGreaterThanSpec.js new file mode 100644 index 00000000..397c0e55 --- /dev/null +++ b/spec/core/matchers/toBeGreaterThanSpec.js @@ -0,0 +1,19 @@ +describe("toBeGreaterThan", function() { + it("passes when actual > expected", function() { + var matcher = j$.matchers.toBeGreaterThan(), + result; + + result = matcher.compare(2, 1); + expect(result.pass).toBe(true); + }); + + it("fails when actual <= expected", function() { + var matcher = j$.matchers.toBeGreaterThan(); + + result = matcher.compare(1, 1); + expect(result.pass).toBe(false); + + result = matcher.compare(1, 2); + expect(result.pass).toBe(false); + }); +}); diff --git a/spec/core/matchers/toBeLessThanSpec.js b/spec/core/matchers/toBeLessThanSpec.js new file mode 100644 index 00000000..53938d2c --- /dev/null +++ b/spec/core/matchers/toBeLessThanSpec.js @@ -0,0 +1,20 @@ +describe("toBeLessThan", function() { + it("passes when actual < expected", function() { + var matcher = j$.matchers.toBeLessThan(), + result; + + result = matcher.compare(1, 2); + expect(result.pass).toBe(true); + }); + + it("fails when actual <= expected", function() { + var matcher = j$.matchers.toBeLessThan(), + result; + + result = matcher.compare(1, 1); + expect(result.pass).toBe(false); + + result = matcher.compare(2, 1); + expect(result.pass).toBe(false); + }); +}); diff --git a/spec/core/matchers/toBeNaNSpec.js b/spec/core/matchers/toBeNaNSpec.js new file mode 100644 index 00000000..d4a00b4d --- /dev/null +++ b/spec/core/matchers/toBeNaNSpec.js @@ -0,0 +1,36 @@ +describe("toBeNaN", function() { + it("passes for NaN with a custom .not fail", function() { + var matcher = j$.matchers.toBeNaN(), + result; + + result = matcher.compare(Number.NaN); + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected actual not to be NaN."); + }); + + it("fails for anything not a NaN", function() { + var matcher = j$.matchers.toBeNaN(); + + result = matcher.compare(1); + expect(result.pass).toBe(false); + + result = matcher.compare(null); + expect(result.pass).toBe(false); + + result = matcher.compare(void 0); + expect(result.pass).toBe(false); + + result = matcher.compare(''); + expect(result.pass).toBe(false); + + result = matcher.compare(Number.POSITIVE_INFINITY); + expect(result.pass).toBe(false); + }); + + it("has a custom message on failure", function() { + var matcher = j$.matchers.toBeNaN(), + result = matcher.compare(0); + + expect(result.message).toEqual("Expected 0 to be NaN."); + }); +}); diff --git a/spec/core/matchers/toBeNullSpec.js b/spec/core/matchers/toBeNullSpec.js new file mode 100644 index 00000000..8a178d5c --- /dev/null +++ b/spec/core/matchers/toBeNullSpec.js @@ -0,0 +1,17 @@ +describe("toBeNull", function() { + it("passes for null", function() { + var matcher = j$.matchers.toBeNull(), + result; + + result = matcher.compare(null); + expect(result.pass).toBe(true); + }); + + it("fails for non-null", function() { + var matcher = j$.matchers.toBeNull(), + result; + + result = matcher.compare('foo'); + expect(result.pass).toBe(false); + }); +}); diff --git a/spec/core/matchers/toBeSpec.js b/spec/core/matchers/toBeSpec.js new file mode 100644 index 00000000..908c2978 --- /dev/null +++ b/spec/core/matchers/toBeSpec.js @@ -0,0 +1,17 @@ +describe("toBe", function() { + it("passes when actual === expected", function() { + var matcher = j$.matchers.toBe(), + result; + + result = matcher.compare(1, 1); + expect(result.pass).toBe(true); + }); + + it("fails when actual !== expected", function() { + var matcher = j$.matchers.toBe(), + result; + + result = matcher.compare(1, 2); + expect(result.pass).toBe(false); + }); +}); diff --git a/spec/core/matchers/toBeTruthySpec.js b/spec/core/matchers/toBeTruthySpec.js new file mode 100644 index 00000000..3acb1ffe --- /dev/null +++ b/spec/core/matchers/toBeTruthySpec.js @@ -0,0 +1,38 @@ +describe("toBeTruthy", function() { + it("passes for 'truthy' values", function() { + var matcher = j$.matchers.toBeTruthy(), + result; + + result = matcher.compare(true); + expect(result.pass).toBe(true); + + result = matcher.compare(1); + expect(result.pass).toBe(true); + + result = matcher.compare("foo"); + expect(result.pass).toBe(true); + + result = matcher.compare({}); + expect(result.pass).toBe(true); + }); + + it("fails for 'falsy' values", function() { + var matcher = j$.matchers.toBeTruthy(), + result; + + result = matcher.compare(false); + expect(result.pass).toBe(false); + + result = matcher.compare(0); + expect(result.pass).toBe(false); + + result = matcher.compare(''); + expect(result.pass).toBe(false); + + result = matcher.compare(null); + expect(result.pass).toBe(false); + + result = matcher.compare(void 0); + expect(result.pass).toBe(false); + }); +}); diff --git a/spec/core/matchers/toBeUndefinedSpec.js b/spec/core/matchers/toBeUndefinedSpec.js new file mode 100644 index 00000000..9d166276 --- /dev/null +++ b/spec/core/matchers/toBeUndefinedSpec.js @@ -0,0 +1,17 @@ +describe("toBeUndefined", function() { + it("passes for undefined values", function() { + var matcher = j$.matchers.toBeUndefined(), + result; + + result = matcher.compare(void 0); + expect(result.pass).toBe(true); + + }); + + it("fails when matching defined values", function() { + var matcher = j$.matchers.toBeUndefined(); + + result = matcher.compare('foo'); + expect(result.pass).toBe(false); + }) +}); diff --git a/spec/core/matchers/toContainSpec.js b/spec/core/matchers/toContainSpec.js new file mode 100644 index 00000000..93635e1e --- /dev/null +++ b/spec/core/matchers/toContainSpec.js @@ -0,0 +1,24 @@ +describe("toContain", function() { + it("delegates to j$.matchersUtil.contains", function() { + var util = { + contains: j$.createSpy('delegated-contains').andReturn(true) + }, + matcher = j$.matchers.toContain(util); + + result = matcher.compare("ABC", "B"); + expect(util.contains).toHaveBeenCalledWith("ABC", "B", []); + expect(result.pass).toBe(true); + }); + + it("delegates to j$.matchersUtil.contains, passing in equality testers if present", function() { + var util = { + contains: j$.createSpy('delegated-contains').andReturn(true) + }, + customEqualityTesters = ['a', 'b'], + matcher = j$.matchers.toContain(util, customEqualityTesters); + + result = matcher.compare("ABC", "B"); + expect(util.contains).toHaveBeenCalledWith("ABC", "B", ['a', 'b']); + expect(result.pass).toBe(true); + }); +}); diff --git a/spec/core/matchers/toEqualSpec.js b/spec/core/matchers/toEqualSpec.js new file mode 100644 index 00000000..b5717f97 --- /dev/null +++ b/spec/core/matchers/toEqualSpec.js @@ -0,0 +1,28 @@ +describe("toEqual", function() { + it("delegates to equals function", function() { + var util = { + equals: j$.createSpy('delegated-equals').andReturn(true) + }, + matcher = j$.matchers.toEqual(util), + result; + + result = matcher.compare(1, 1); + + expect(util.equals).toHaveBeenCalledWith(1, 1, []); + expect(result.pass).toBe(true); + }); + + it("delegates custom equality testers, if present", function() { + var util = { + equals: j$.createSpy('delegated-equals').andReturn(true) + }, + customEqualityTesters = ['a', 'b'], + matcher = j$.matchers.toEqual(util, customEqualityTesters), + result; + + result = matcher.compare(1, 1); + + expect(util.equals).toHaveBeenCalledWith(1, 1, ['a', 'b']); + expect(result.pass).toBe(true); + }); +}); diff --git a/spec/core/matchers/toHaveBeenCalledSpec.js b/spec/core/matchers/toHaveBeenCalledSpec.js new file mode 100644 index 00000000..88c8d4a7 --- /dev/null +++ b/spec/core/matchers/toHaveBeenCalledSpec.js @@ -0,0 +1,46 @@ +describe("toHaveBeenCalled", function() { + it("passes when the actual was called, with a custom .not fail message", function() { + var matcher = j$.matchers.toHaveBeenCalled(), + calledSpy = j$.createSpy('called-spy'), + result; + + calledSpy(); + + result = matcher.compare(calledSpy); + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected spy called-spy not to have been called."); + }); + + it("fails when the actual was not called", function() { + var matcher = j$.matchers.toHaveBeenCalled(), + uncalledSpy = j$.createSpy('uncalled spy'); + + result = matcher.compare(uncalledSpy); + expect(result.pass).toBe(false); + }); + + it("throws an exception when the actual is not a spy", function() { + var matcher = j$.matchers.toHaveBeenCalled(), + fn = function() {}; + + expect(function() { matcher.compare(fn) }).toThrow(new Error("Expected a spy, but got Function.")); + }); + + it("throws an exception when invoked with any arguments", function() { + var matcher = j$.matchers.toHaveBeenCalled(), + spy = j$.createSpy('sample spy'); + + expect(function() { matcher.compare(spy, 'foo') }).toThrow(new Error("toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith")); + }); + + it("has a custom message on failure", function() { + var matcher = j$.matchers.toHaveBeenCalled(), + spy = j$.createSpy('sample-spy'), + result; + + result = matcher.compare(spy); + + expect(result.message).toEqual("Expected spy sample-spy to have been called."); + }); +}); + diff --git a/spec/core/matchers/toHaveBeenCalledWithSpec.js b/spec/core/matchers/toHaveBeenCalledWithSpec.js new file mode 100644 index 00000000..96f52158 --- /dev/null +++ b/spec/core/matchers/toHaveBeenCalledWithSpec.js @@ -0,0 +1,57 @@ +describe("toHaveBeenCalledWith", function() { + it("passes when the actual was called with matching parameters", function() { + var util = { + contains: j$.createSpy('delegated-contains').andReturn(true) + }, + matcher = j$.matchers.toHaveBeenCalledWith(util) + calledSpy = j$.createSpy('called-spy'), + result; + + calledSpy('a', 'b'); + result = matcher.compare(calledSpy, 'a', 'b'); + + expect(result.pass).toBe(true); + }); + + it("fails when the actual was not called", function() { + var util = { + contains: j$.createSpy('delegated-contains').andReturn(false) + }, + matcher = j$.matchers.toHaveBeenCalledWith(util), + uncalledSpy = j$.createSpy('uncalled spy'), + result; + + result = matcher.compare(uncalledSpy); + expect(result.pass).toBe(false); + }); + + it("fails when the actual was called with different parameters", function() { + var util = { + contains: j$.createSpy('delegated-contains').andReturn(false) + }, + matcher = j$.matchers.toHaveBeenCalledWith(util), + calledSpy = j$.createSpy('called spy'), + result; + + calledSpy('a'); + result = matcher.compare(calledSpy, 'a', 'b'); + + expect(result.pass).toBe(false); + }); + + it("throws an exception when the actual is not a spy", function() { + var matcher = j$.matchers.toHaveBeenCalledWith(), + fn = function() {}; + + expect(function() { matcher.compare(fn) }).toThrow(new Error("Expected a spy, but got Function.")); + }); + + it("has a custom message on failure", function() { + var matcher = j$.matchers.toHaveBeenCalledWith(), + spy = j$.createSpy('sample-spy'), + messages = matcher.message(spy); + + expect(messages.affirmative).toEqual("Expected spy sample-spy to have been called.") + expect(messages.negative).toEqual("Expected spy sample-spy not to have been called.") + }); +}); diff --git a/spec/core/matchers/toMatchSpec.js b/spec/core/matchers/toMatchSpec.js new file mode 100644 index 00000000..ae4c2e8e --- /dev/null +++ b/spec/core/matchers/toMatchSpec.js @@ -0,0 +1,34 @@ +describe("toMatch", function() { + it("passes when RegExps are equivalent", function() { + var matcher = j$.matchers.toMatch(), + result; + + result = matcher.compare(/foo/, /foo/); + expect(result.pass).toBe(true); + }); + + it("fails when RegExps are not equivalent", function() { + var matcher = j$.matchers.toMatch(), + result; + + result = matcher.compare(/bar/, /foo/); + expect(result.pass).toBe(false); + }); + + it("passes when the actual matches the expected string as a pattern", function() { + var matcher = j$.matchers.toMatch(), + result; + + result = matcher.compare('foosball', 'foo'); + expect(result.pass).toBe(true); + }); + + it("fails when the actual matches the expected string as a pattern", function() { + var matcher = j$.matchers.toMatch(), + result; + + result = matcher.compare('bar', 'foo'); + expect(result.pass).toBe(false); + }); +}); + diff --git a/spec/core/matchers/toThrowSpec.js b/spec/core/matchers/toThrowSpec.js new file mode 100644 index 00000000..ed65a0cd --- /dev/null +++ b/spec/core/matchers/toThrowSpec.js @@ -0,0 +1,151 @@ +describe("toThrow", function() { + it("throw an error when the acutal is not a function ", function() { + var matcher = j$.matchers.toThrow(); + + expect(function() { + matcher.compare({}); + }).toThrow(new Error("Actual is not a Function")); + }); + + it("throws an error when the expected can't be turned into an exception", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "foo"; + }, + result; + + expect(function() { + matcher.compare(fn, 1); + }).toThrow(new Error("Expected cannot be treated as an exception.")); + }); + + it("passes if the actual throws any exception", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "foo"; + }, + result; + + result = matcher.compare(fn); + + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected function not to throw an exception."); + }); + + it("fails if the actual does not throw an exception", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + return 0; + }, + result; + + result = matcher.compare(fn); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected function to throw an exception."); + }); + + it("passes if the actual throws an exception with the expected message", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "foo"; + }, + result; + + result = matcher.compare(fn, "foo"); + + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected function not to throw an exception \"foo\"."); + }); + + it("fails if the actual throws an exception with a different message", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "foo"; + }, + result; + + result = matcher.compare(fn, "bar"); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected function to throw an exception \"bar\"."); + }); + + it("passes if the actual throws an exception and matches the message of the expected exception", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "foo"; + }, + result; + + result = matcher.compare(fn, new Error("foo")); + + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected function not to throw an exception \"foo\"."); + }); + + it("fails if the actual throws an exception and it does not match the message of the expected exception with a custom message", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "foo"; + }, + result; + + result = matcher.compare(fn, new Error("bar")); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected function to throw an exception \"bar\"."); + }); + + it("passes if the actual throws an exception and the message matches the expected regular expression", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "a long message"; + }, + result; + + result = matcher.compare(fn, /long/); + + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected function not to throw an exception matching /long/."); + }); + + it("fails if the actual throws an exception and the message does not match the expected regular expression", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw "a long message"; + }, + result; + + result = matcher.compare(fn, /short/); + + expect(result.pass).toBe(false); + expect(result.message).toEqual("Expected function to throw an exception matching /short/."); + }); + + it("passes if the actual throws an exception with an undefined message", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw void 0; + }, + result; + + result = matcher.compare(fn); + + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected function not to throw an exception."); + }); + + it("passes if the actual throws an exception with an empty message", function() { + var matcher = j$.matchers.toThrow(), + fn = function() { + throw ""; + }, + result; + + result = matcher.compare(fn); + + expect(result.pass).toBe(true); + expect(result.message).toEqual("Expected function not to throw an exception."); + }); +}); \ No newline at end of file diff --git a/spec/core/matchersSpec.js b/spec/core/matchersSpec.js deleted file mode 100644 index 4b88153d..00000000 --- a/spec/core/matchersSpec.js +++ /dev/null @@ -1,626 +0,0 @@ -describe("Matchers", function() { - describe("toBe", function() { - it("passes when actual === expected", function() { - var matcher = j$.matchers.toBe(), - result; - - result = matcher.compare(1, 1); - expect(result.pass).toBe(true); - }); - - it("fails when actual !== expected", function() { - var matcher = j$.matchers.toBe(), - result; - - result = matcher.compare(1, 2); - expect(result.pass).toBe(false); - }); - }); - - describe("toBeCloseTo", function() { - it("passes when within two decimal places by default", function() { - var matcher = j$.matchers.toBeCloseTo(), - result; - - result = matcher.compare(0, 0); - expect(result.pass).toBe(true); - - result = matcher.compare(0, 0.001); - expect(result.pass).toBe(true); - }); - - it("fails when not within two decimal places by default", function() { - var matcher = j$.matchers.toBeCloseTo(), - result; - - result = matcher.compare(0, 0.01); - expect(result.pass).toBe(false); - }); - - it("accepts an optional precision argument", function() { - var matcher = j$.matchers.toBeCloseTo(), - result; - - result = matcher.compare(0, 0.1, 0); - expect(result.pass).toBe(true); - - result = matcher.compare(0, 0.0001, 3); - expect(result.pass).toBe(true); - }); - - it("rounds expected values", function() { - var matcher = j$.matchers.toBeCloseTo(), - result; - - result = matcher.compare(1.23, 1.229); - expect(result.pass).toBe(true); - - result = matcher.compare(1.23, 1.226); - expect(result.pass).toBe(true); - - result = matcher.compare(1.23, 1.225); - expect(result.pass).toBe(true); - - result = matcher.compare(1.23, 1.2249999); - expect(result.pass).toBe(false); - - result = matcher.compare(1.23, 1.234); - expect(result.pass).toBe(true); - }); - }); - - describe("toBeDefined", function() { - it("matches for defined values", function() { - var matcher = j$.matchers.toBeDefined(), - result; - - - result = matcher.compare('foo'); - expect(result.pass).toBe(true); - }); - - it("fails when matching undefined values", function() { - var matcher = j$.matchers.toBeDefined(), - result; - - result = matcher.compare(void 0); - expect(result.pass).toBe(false); - }) - }); - - describe("toBeFalsy", function() { - it("passes for 'falsy' values", function() { - var matcher = j$.matchers.toBeFalsy(), - result; - - result = matcher.compare(false); - expect(result.pass).toBe(true); - - result = matcher.compare(0); - expect(result.pass).toBe(true); - - result = matcher.compare(''); - expect(result.pass).toBe(true); - - result = matcher.compare(null); - expect(result.pass).toBe(true); - - result = matcher.compare(void 0); - expect(result.pass).toBe(true); - }); - - it("fails for 'truthy' values", function() { - var matcher = j$.matchers.toBeFalsy(), - result; - - result = matcher.compare(true); - expect(result.pass).toBe(false); - - result = matcher.compare(1); - expect(result.pass).toBe(false); - - result = matcher.compare("foo"); - expect(result.pass).toBe(false); - - result = matcher.compare({}); - expect(result.pass).toBe(false); - }); - }); - - describe("toBeGreaterThan", function() { - it("passes when actual > expected", function() { - var matcher = j$.matchers.toBeGreaterThan(), - result; - - result = matcher.compare(2, 1); - expect(result.pass).toBe(true); - }); - - it("fails when actual <= expected", function() { - var matcher = j$.matchers.toBeGreaterThan(); - - result = matcher.compare(1, 1); - expect(result.pass).toBe(false); - - result = matcher.compare(1, 2); - expect(result.pass).toBe(false); - }); - }); - - describe("toBeLessThan", function() { - it("passes when actual < expected", function() { - var matcher = j$.matchers.toBeLessThan(), - result; - - result = matcher.compare(1, 2); - expect(result.pass).toBe(true); - }); - - it("fails when actual <= expected", function() { - var matcher = j$.matchers.toBeLessThan(), - result; - - result = matcher.compare(1, 1); - expect(result.pass).toBe(false); - - result = matcher.compare(2, 1); - expect(result.pass).toBe(false); - }); - }); - - describe("toBeNaN", function() { - it("passes for NaN with a custom .not fail", function() { - var matcher = j$.matchers.toBeNaN(), - result; - - result = matcher.compare(Number.NaN); - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected actual not to be NaN."); - }); - - it("fails for anything not a NaN", function() { - var matcher = j$.matchers.toBeNaN(); - - result = matcher.compare(1); - expect(result.pass).toBe(false); - - result = matcher.compare(null); - expect(result.pass).toBe(false); - - result = matcher.compare(void 0); - expect(result.pass).toBe(false); - - result = matcher.compare(''); - expect(result.pass).toBe(false); - - result = matcher.compare(Number.POSITIVE_INFINITY); - expect(result.pass).toBe(false); - }); - - it("has a custom message on failure", function() { - var matcher = j$.matchers.toBeNaN(), - result = matcher.compare(0); - - expect(result.message).toEqual("Expected 0 to be NaN."); - }); - }); - - describe("toBeNull", function() { - it("passes for null", function() { - var matcher = j$.matchers.toBeNull(), - result; - - result = matcher.compare(null); - expect(result.pass).toBe(true); - }); - - it("fails for non-null", function() { - var matcher = j$.matchers.toBeNull(), - result; - - result = matcher.compare('foo'); - expect(result.pass).toBe(false); - }); - }); - - describe("toBeTruthy", function() { - it("passes for 'truthy' values", function() { - var matcher = j$.matchers.toBeTruthy(), - result; - - result = matcher.compare(true); - expect(result.pass).toBe(true); - - result = matcher.compare(1); - expect(result.pass).toBe(true); - - result = matcher.compare("foo"); - expect(result.pass).toBe(true); - - result = matcher.compare({}); - expect(result.pass).toBe(true); - }); - - it("fails for 'falsy' values", function() { - var matcher = j$.matchers.toBeTruthy(), - result; - - result = matcher.compare(false); - expect(result.pass).toBe(false); - - result = matcher.compare(0); - expect(result.pass).toBe(false); - - result = matcher.compare(''); - expect(result.pass).toBe(false); - - result = matcher.compare(null); - expect(result.pass).toBe(false); - - result = matcher.compare(void 0); - expect(result.pass).toBe(false); - }); - }); - - describe("toBeUndefined", function() { - it("passes for undefined values", function() { - var matcher = j$.matchers.toBeUndefined(), - result; - - result = matcher.compare(void 0); - expect(result.pass).toBe(true); - - }); - - it("fails when matching defined values", function() { - var matcher = j$.matchers.toBeUndefined(); - - result = matcher.compare('foo'); - expect(result.pass).toBe(false); - }) - }); - - describe("toContain", function() { - it("delegates to j$.matchersUtil.contains", function() { - var util = { - contains: j$.createSpy('delegated-contains').andReturn(true) - }, - matcher = j$.matchers.toContain(util); - - result = matcher.compare("ABC", "B"); - expect(util.contains).toHaveBeenCalledWith("ABC", "B", []); - expect(result.pass).toBe(true); - }); - - it("delegates to j$.matchersUtil.contains, passing in equality testers if present", function() { - var util = { - contains: j$.createSpy('delegated-contains').andReturn(true) - }, - customEqualityTesters = ['a', 'b'], - matcher = j$.matchers.toContain(util, customEqualityTesters); - - result = matcher.compare("ABC", "B"); - expect(util.contains).toHaveBeenCalledWith("ABC", "B", ['a', 'b']); - expect(result.pass).toBe(true); - }); - }); - - describe("toEqual", function() { - it("delegates to equals function", function() { - var util = { - equals: j$.createSpy('delegated-equals').andReturn(true) - }, - matcher = j$.matchers.toEqual(util), - result; - - result = matcher.compare(1, 1); - - expect(util.equals).toHaveBeenCalledWith(1, 1, []); - expect(result.pass).toBe(true); - }); - - it("delegates custom equality testers, if present", function() { - var util = { - equals: j$.createSpy('delegated-equals').andReturn(true) - }, - customEqualityTesters = ['a', 'b'], - matcher = j$.matchers.toEqual(util, customEqualityTesters), - result; - - result = matcher.compare(1, 1); - - expect(util.equals).toHaveBeenCalledWith(1, 1, ['a', 'b']); - expect(result.pass).toBe(true); - }); - }); - - describe("toHaveBeenCalled", function() { - it("passes when the actual was called, with a custom .not fail message", function() { - var matcher = j$.matchers.toHaveBeenCalled(), - calledSpy = j$.createSpy('called-spy'), - result; - - calledSpy(); - - result = matcher.compare(calledSpy); - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected spy called-spy not to have been called."); - }); - - it("fails when the actual was not called", function() { - var matcher = j$.matchers.toHaveBeenCalled(), - uncalledSpy = j$.createSpy('uncalled spy'); - - result = matcher.compare(uncalledSpy); - expect(result.pass).toBe(false); - }); - - it("throws an exception when the actual is not a spy", function() { - var matcher = j$.matchers.toHaveBeenCalled(), - fn = function() {}; - - expect(function() { matcher.compare(fn) }).toThrow(new Error("Expected a spy, but got Function.")); - }); - - it("throws an exception when invoked with any arguments", function() { - var matcher = j$.matchers.toHaveBeenCalled(), - spy = j$.createSpy('sample spy'); - - expect(function() { matcher.compare(spy, 'foo') }).toThrow(new Error("toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith")); - }); - - it("has a custom message on failure", function() { - var matcher = j$.matchers.toHaveBeenCalled(), - spy = j$.createSpy('sample-spy'), - result; - - result = matcher.compare(spy); - - expect(result.message).toEqual("Expected spy sample-spy to have been called."); - }); - }); - - describe("toHaveBeenCalledWith", function() { - it("passes when the actual was called with matching parameters", function() { - var util = { - contains: j$.createSpy('delegated-contains').andReturn(true) - }, - matcher = j$.matchers.toHaveBeenCalledWith(util) - calledSpy = j$.createSpy('called-spy'), - result; - - calledSpy('a', 'b'); - result = matcher.compare(calledSpy, 'a', 'b'); - - expect(result.pass).toBe(true); - }); - - it("fails when the actual was not called", function() { - var util = { - contains: j$.createSpy('delegated-contains').andReturn(false) - }, - matcher = j$.matchers.toHaveBeenCalledWith(util), - uncalledSpy = j$.createSpy('uncalled spy'), - result; - - result = matcher.compare(uncalledSpy); - expect(result.pass).toBe(false); - }); - - it("fails when the actual was called with different parameters", function() { - var util = { - contains: j$.createSpy('delegated-contains').andReturn(false) - }, - matcher = j$.matchers.toHaveBeenCalledWith(util), - calledSpy = j$.createSpy('called spy'), - result; - - calledSpy('a'); - result = matcher.compare(calledSpy, 'a', 'b'); - - expect(result.pass).toBe(false); - }); - - it("throws an exception when the actual is not a spy", function() { - var matcher = j$.matchers.toHaveBeenCalledWith(), - fn = function() {}; - - expect(function() { matcher.compare(fn) }).toThrow(new Error("Expected a spy, but got Function.")); - }); - - it("has a custom message on failure", function() { - var matcher = j$.matchers.toHaveBeenCalledWith(), - spy = j$.createSpy('sample-spy'), - messages = matcher.message(spy); - - expect(messages.affirmative).toEqual("Expected spy sample-spy to have been called.") - expect(messages.negative).toEqual("Expected spy sample-spy not to have been called.") - }); - }); - - describe("toMatch", function() { - it("passes when RegExps are equivalent", function() { - var matcher = j$.matchers.toMatch(), - result; - - result = matcher.compare(/foo/, /foo/); - expect(result.pass).toBe(true); - }); - - it("fails when RegExps are not equivalent", function() { - var matcher = j$.matchers.toMatch(), - result; - - result = matcher.compare(/bar/, /foo/); - expect(result.pass).toBe(false); - }); - - it("passes when the actual matches the expected string as a pattern", function() { - var matcher = j$.matchers.toMatch(), - result; - - result = matcher.compare('foosball', 'foo'); - expect(result.pass).toBe(true); - }); - - it("fails when the actual matches the expected string as a pattern", function() { - var matcher = j$.matchers.toMatch(), - result; - - result = matcher.compare('bar', 'foo'); - expect(result.pass).toBe(false); - }); - }); - - describe("toThrow", function() { - it("throw an error when the acutal is not a function ", function() { - var matcher = j$.matchers.toThrow(); - - expect(function() { - matcher.compare({}); - }).toThrow(new Error("Actual is not a Function")); - }); - - it("throws an error when the expected can't be turned into an exception", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "foo"; - }, - result; - - expect(function() { - matcher.compare(fn, 1); - }).toThrow(new Error("Expected cannot be treated as an exception.")); - }); - - it("passes if the actual throws any exception", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "foo"; - }, - result; - - result = matcher.compare(fn); - - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected function not to throw an exception."); - }); - - it("fails if the actual does not throw an exception", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - return 0; - }, - result; - - result = matcher.compare(fn); - - expect(result.pass).toBe(false); - expect(result.message).toEqual("Expected function to throw an exception."); - }); - - it("passes if the actual throws an exception with the expected message", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "foo"; - }, - result; - - result = matcher.compare(fn, "foo"); - - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected function not to throw an exception \"foo\"."); - }); - - it("fails if the actual throws an exception with a different message", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "foo"; - }, - result; - - result = matcher.compare(fn, "bar"); - - expect(result.pass).toBe(false); - expect(result.message).toEqual("Expected function to throw an exception \"bar\"."); - }); - - it("passes if the actual throws an exception and matches the message of the expected exception", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "foo"; - }, - result; - - result = matcher.compare(fn, new Error("foo")); - - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected function not to throw an exception \"foo\"."); - }); - - it("fails if the actual throws an exception and it does not match the message of the expected exception with a custom message", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "foo"; - }, - result; - - result = matcher.compare(fn, new Error("bar")); - - expect(result.pass).toBe(false); - expect(result.message).toEqual("Expected function to throw an exception \"bar\"."); - }); - - it("passes if the actual throws an exception and the message matches the expected regular expression", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "a long message"; - }, - result; - - result = matcher.compare(fn, /long/); - - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected function not to throw an exception matching /long/."); - }); - - it("fails if the actual throws an exception and the message does not match the expected regular expression", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw "a long message"; - }, - result; - - result = matcher.compare(fn, /short/); - - expect(result.pass).toBe(false); - expect(result.message).toEqual("Expected function to throw an exception matching /short/."); - }); - - it("passes if the actual throws an exception with an undefined message", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw void 0; - }, - result; - - result = matcher.compare(fn); - - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected function not to throw an exception."); - }); - - it("passes if the actual throws an exception with an empty message", function() { - var matcher = j$.matchers.toThrow(), - fn = function() { - throw ""; - }, - result; - - result = matcher.compare(fn); - - expect(result.pass).toBe(true); - expect(result.message).toEqual("Expected function not to throw an exception."); - }); - }); -}); \ No newline at end of file diff --git a/spec/jasmine.yml b/spec/jasmine.yml index e1458cd7..17134f02 100644 --- a/spec/jasmine.yml +++ b/spec/jasmine.yml @@ -9,9 +9,9 @@ src_files: - 'core/Spec.js' - 'core/Env.js' - 'core/JsApiReporter.js' - - 'core/Matchers.js' - 'core/PrettyPrinter.js' - 'core/Suite.js' + - 'core/**/*.js' - 'html/**.js' - '**/*.js' stylesheets: diff --git a/spec/node_suite.js b/spec/node_suite.js index 802504d9..86be7686 100644 --- a/spec/node_suite.js +++ b/spec/node_suite.js @@ -86,25 +86,25 @@ function executeSpecs(specs, done, isVerbose, showColors) { } function getFiles(dir, matcher) { - specs = []; + var allFiles = []; if (fs.statSync(dir).isFile() && dir.match(matcher)) { - specs.push(dir); + allFiles.push(dir); } else { var files = fs.readdirSync(dir); for (var i = 0, len = files.length; i < len; ++i) { var filename = dir + '/' + files[i]; if (fs.statSync(filename).isFile() && filename.match(matcher)) { - specs.push(filename); + allFiles.push(filename); } else if (fs.statSync(filename).isDirectory()) { - var subfiles = getSpecFiles(filename); + var subfiles = getFiles(filename); subfiles.forEach(function(result) { - specs.push(result); + allFiles.push(result); }); } } } - return specs; + return allFiles; } function getSpecFiles(dir) { diff --git a/src/core/matchers.js b/src/core/matchers.js deleted file mode 100644 index 206d3ab2..00000000 --- a/src/core/matchers.js +++ /dev/null @@ -1,268 +0,0 @@ -getJasmineRequireObj().matchers = function() { - matchers = {}; - - matchers.toBe = function() { - return { - compare: function(actual, expected) { - return { - pass: actual === expected - }; - } - }; - }; - - matchers.toBeCloseTo = function() { - return { - compare: function(actual, expected, precision) { - if (precision !== 0) { - precision = precision || 2; - } - - return { - pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) - }; - } - }; - }; - - matchers.toBeDefined = function() { - return { - compare: function(actual) { - return { - pass: (void 0 !== actual) - }; - } - }; - }; - - matchers.toBeFalsy = function() { - return { - compare: function(actual) { - return { - pass: !!!actual - }; - } - }; - }; - - matchers.toBeGreaterThan = function() { - return { - compare: function(actual, expected) { - return { - pass: actual > expected - }; - } - }; - }; - - matchers.toBeLessThan = function() { - return { - - compare: function(actual, expected) { - return { - pass: actual < expected - }; - } - }; - }; - - matchers.toBeNaN = function() { - return { - compare: function(actual) { - var result = { - pass: (actual !== actual) - }; - - if (result.pass) { - result.message = "Expected actual not to be NaN."; - } else { - result.message = "Expected " + j$.pp(actual) + " to be NaN."; - } - - return result; - } - }; - }; - - matchers.toBeNull = function() { - return { - compare: function(actual) { - return { - pass: actual === null - }; - } - }; - }; - - matchers.toBeTruthy = function() { - return { - compare: function(actual) { - return { - pass: !!actual - }; - } - }; - }; - - matchers.toBeUndefined = function() { - return { - compare: function(actual) { - return { - pass: void 0 === actual - }; - } - }; - }; - - matchers.toEqual = function(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - var result = { - pass: false - }; - - result.pass = util.equals(actual, expected, customEqualityTesters); - - return result; - } - }; - }; - - matchers.toHaveBeenCalled = function() { - return { - compare: function(actual) { - var result = {}; - - if (!j$.isSpy(actual)) { - throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); - } - - if (arguments.length > 1) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - result.pass = actual.wasCalled; - - result.message = result.pass ? - "Expected spy " + actual.identity + " not to have been called." : - "Expected spy " + actual.identity + " to have been called."; - - return result; - } - }; - }; - - matchers.toHaveBeenCalledWith = function(util) { - return { - compare: function() { - var args = Array.prototype.slice.call(arguments, 0), - actual = args[0], - expectedArgs = args.slice(1); - - if (!j$.isSpy(actual)) { - throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); - } - - return { - pass: util.contains(actual.argsForCall, expectedArgs) - }; - }, - message: function(actual) { - return { - affirmative: "Expected spy " + actual.identity + " to have been called.", - negative: "Expected spy " + actual.identity + " not to have been called." - }; - } - }; - }; - - matchers.toMatch = function() { - return { - compare: function(actual, expected) { - var regexp = new RegExp(expected); - - return { - pass: regexp.test(actual) - }; - } - }; - }; - - matchers.toThrow = function() { - return { - compare: function(actual, expected) { - var result = { pass: false }, - exception; - - if (typeof actual != "function") { - throw new Error("Actual is not a Function"); - } - - if (expectedCannotBeTreatedAsException()) { - throw new Error("Expected cannot be treated as an exception."); - } - - try { - actual(); - } catch (e) { - exception = new Error(e); - } - - if (!exception) { - result.message = "Expected function to throw an exception."; - return result; - } - - if (void 0 == expected) { - result.pass = true; - result.message = "Expected function not to throw an exception."; - } else if (exception.message == expected) { - result.pass = true; - result.message = "Expected function not to throw an exception \"" + expected + "\"."; - } else if (exception.message == expected.message) { - result.pass = true; - result.message = "Expected function not to throw an exception \"" + expected.message + "\"."; - } else if (expected instanceof RegExp) { - if (expected.test(exception.message)) { - result.pass = true; - result.message = "Expected function not to throw an exception matching " + expected + "."; - } else { - result.pass = false; - result.message = "Expected function to throw an exception matching " + expected + "."; - } - } else { - result.pass = false; - result.message = "Expected function to throw an exception \"" + (expected.message || expected) + "\"."; - } - - return result; - - function expectedCannotBeTreatedAsException() { - return !( - (void 0 == expected) || - (expected instanceof Error) || - (typeof expected == "string") || - (expected instanceof RegExp) - ); - } - } - }; - }; - - matchers.toContain = function(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - - return { - pass: util.contains(actual, expected, customEqualityTesters) - }; - } - }; - }; - - return matchers; -}; diff --git a/src/core/matchersUtil.js b/src/core/matchers/matchersUtil.js similarity index 100% rename from src/core/matchersUtil.js rename to src/core/matchers/matchersUtil.js diff --git a/src/core/matchers/requireMatchers.js b/src/core/matchers/requireMatchers.js new file mode 100644 index 00000000..8bfc7ea5 --- /dev/null +++ b/src/core/matchers/requireMatchers.js @@ -0,0 +1,28 @@ +getJasmineRequireObj().requireMatchers = function(jRequire) { + var availableMatchers = [ + "toBe", + "toBeCloseTo", + "toBeDefined", + "toBeFalsy", + "toBeGreaterThan", + "toBeLessThan", + "toBeNaN", + "toBeNull", + "toBeTruthy", + "toBeUndefined", + "toContain", + "toEqual", + "toHaveBeenCalled", + "toHaveBeenCalledWith", + "toMatch", + "toThrow" + ], + matchers = {}; + + for (var i = 0; i < availableMatchers.length; i++) { + var name = availableMatchers[i]; + matchers[name] = jRequire[name](); + } + + return matchers; +}; diff --git a/src/core/matchers/toBe.js b/src/core/matchers/toBe.js new file mode 100644 index 00000000..f0bf88f6 --- /dev/null +++ b/src/core/matchers/toBe.js @@ -0,0 +1,13 @@ +getJasmineRequireObj().toBe = function() { + function toBe() { + return { + compare: function(actual, expected) { + return { + pass: actual === expected + }; + } + }; + } + + return toBe; +}; diff --git a/src/core/matchers/toBeCloseTo.js b/src/core/matchers/toBeCloseTo.js new file mode 100644 index 00000000..52e63121 --- /dev/null +++ b/src/core/matchers/toBeCloseTo.js @@ -0,0 +1,18 @@ +getJasmineRequireObj().toBeCloseTo = function() { + + function toBeCloseTo() { + return { + compare: function(actual, expected, precision) { + if (precision !== 0) { + precision = precision || 2; + } + + return { + pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) + }; + } + }; + } + + return toBeCloseTo; +}; diff --git a/src/core/matchers/toBeDefined.js b/src/core/matchers/toBeDefined.js new file mode 100644 index 00000000..68bca653 --- /dev/null +++ b/src/core/matchers/toBeDefined.js @@ -0,0 +1,13 @@ +getJasmineRequireObj().toBeDefined = function() { + function toBeDefined() { + return { + compare: function(actual) { + return { + pass: (void 0 !== actual) + }; + } + }; + } + + return toBeDefined; +}; diff --git a/src/core/matchers/toBeFalsy.js b/src/core/matchers/toBeFalsy.js new file mode 100644 index 00000000..663c84e8 --- /dev/null +++ b/src/core/matchers/toBeFalsy.js @@ -0,0 +1,13 @@ +getJasmineRequireObj().toBeFalsy = function() { + function toBeFalsy() { + return { + compare: function(actual) { + return { + pass: !!!actual + }; + } + }; + } + + return toBeFalsy; +}; diff --git a/src/core/matchers/toBeGreaterThan.js b/src/core/matchers/toBeGreaterThan.js new file mode 100644 index 00000000..61961591 --- /dev/null +++ b/src/core/matchers/toBeGreaterThan.js @@ -0,0 +1,15 @@ +getJasmineRequireObj().toBeGreaterThan = function() { + + function toBeGreaterThan() { + return { + compare: function(actual, expected) { + return { + pass: actual > expected + }; + } + }; + } + + return toBeGreaterThan; +}; + diff --git a/src/core/matchers/toBeLessThan.js b/src/core/matchers/toBeLessThan.js new file mode 100644 index 00000000..2c29be35 --- /dev/null +++ b/src/core/matchers/toBeLessThan.js @@ -0,0 +1,14 @@ +getJasmineRequireObj().toBeLessThan = function() { + function toBeLessThan() { + return { + + compare: function(actual, expected) { + return { + pass: actual < expected + }; + } + }; + } + + return toBeLessThan; +}; \ No newline at end of file diff --git a/src/core/matchers/toBeNaN.js b/src/core/matchers/toBeNaN.js new file mode 100644 index 00000000..f9a09d74 --- /dev/null +++ b/src/core/matchers/toBeNaN.js @@ -0,0 +1,22 @@ +getJasmineRequireObj().toBeNaN = function() { + + function toBeNaN() { + return { + compare: function(actual) { + var result = { + pass: (actual !== actual) + }; + + if (result.pass) { + result.message = "Expected actual not to be NaN."; + } else { + result.message = "Expected " + j$.pp(actual) + " to be NaN."; + } + + return result; + } + }; + } + + return toBeNaN; +}; diff --git a/src/core/matchers/toBeNull.js b/src/core/matchers/toBeNull.js new file mode 100644 index 00000000..47ba8ea5 --- /dev/null +++ b/src/core/matchers/toBeNull.js @@ -0,0 +1,14 @@ +getJasmineRequireObj().toBeNull = function() { + + function toBeNull() { + return { + compare: function(actual) { + return { + pass: actual === null + }; + } + }; + } + + return toBeNull; +}; diff --git a/src/core/matchers/toBeTruthy.js b/src/core/matchers/toBeTruthy.js new file mode 100644 index 00000000..5ab044b5 --- /dev/null +++ b/src/core/matchers/toBeTruthy.js @@ -0,0 +1,14 @@ +getJasmineRequireObj().toBeTruthy = function() { + + function toBeTruthy() { + return { + compare: function(actual) { + return { + pass: !!actual + }; + } + }; + } + + return toBeTruthy; +}; diff --git a/src/core/matchers/toBeUndefined.js b/src/core/matchers/toBeUndefined.js new file mode 100644 index 00000000..dfae8f41 --- /dev/null +++ b/src/core/matchers/toBeUndefined.js @@ -0,0 +1,14 @@ +getJasmineRequireObj().toBeUndefined = function() { + + function toBeUndefined() { + return { + compare: function(actual) { + return { + pass: void 0 === actual + }; + } + }; + } + + return toBeUndefined; +}; diff --git a/src/core/matchers/toContain.js b/src/core/matchers/toContain.js new file mode 100644 index 00000000..ac05cd24 --- /dev/null +++ b/src/core/matchers/toContain.js @@ -0,0 +1,16 @@ +getJasmineRequireObj().toContain = function() { + function toContain(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + + return { + pass: util.contains(actual, expected, customEqualityTesters) + }; + } + }; + } + + return toContain; +}; diff --git a/src/core/matchers/toEqual.js b/src/core/matchers/toEqual.js new file mode 100644 index 00000000..653541bc --- /dev/null +++ b/src/core/matchers/toEqual.js @@ -0,0 +1,20 @@ +getJasmineRequireObj().toEqual = function() { + + function toEqual(util, customEqualityTesters) { + customEqualityTesters = customEqualityTesters || []; + + return { + compare: function(actual, expected) { + var result = { + pass: false + }; + + result.pass = util.equals(actual, expected, customEqualityTesters); + + return result; + } + }; + } + + return toEqual; +}; diff --git a/src/core/matchers/toHaveBeenCalled.js b/src/core/matchers/toHaveBeenCalled.js new file mode 100644 index 00000000..e63a755b --- /dev/null +++ b/src/core/matchers/toHaveBeenCalled.js @@ -0,0 +1,28 @@ +getJasmineRequireObj().toHaveBeenCalled = function() { + + function toHaveBeenCalled() { + return { + compare: function(actual) { + var result = {}; + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + if (arguments.length > 1) { + throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); + } + + result.pass = actual.wasCalled; + + result.message = result.pass ? + "Expected spy " + actual.identity + " not to have been called." : + "Expected spy " + actual.identity + " to have been called."; + + return result; + } + }; + } + + return toHaveBeenCalled; +}; diff --git a/src/core/matchers/toHaveBeenCalledWith.js b/src/core/matchers/toHaveBeenCalledWith.js new file mode 100644 index 00000000..37f8462a --- /dev/null +++ b/src/core/matchers/toHaveBeenCalledWith.js @@ -0,0 +1,28 @@ +getJasmineRequireObj().toHaveBeenCalledWith = function() { + + function toHaveBeenCalledWith(util) { + return { + compare: function() { + var args = Array.prototype.slice.call(arguments, 0), + actual = args[0], + expectedArgs = args.slice(1); + + if (!j$.isSpy(actual)) { + throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); + } + + return { + pass: util.contains(actual.argsForCall, expectedArgs) + }; + }, + message: function(actual) { + return { + affirmative: "Expected spy " + actual.identity + " to have been called.", + negative: "Expected spy " + actual.identity + " not to have been called." + }; + } + }; + } + + return toHaveBeenCalledWith; +}; diff --git a/src/core/matchers/toMatch.js b/src/core/matchers/toMatch.js new file mode 100644 index 00000000..38309fd0 --- /dev/null +++ b/src/core/matchers/toMatch.js @@ -0,0 +1,16 @@ +getJasmineRequireObj().toMatch = function() { + + function toMatch() { + return { + compare: function(actual, expected) { + var regexp = new RegExp(expected); + + return { + pass: regexp.test(actual) + }; + } + }; + } + + return toMatch; +}; diff --git a/src/core/matchers/toThrow.js b/src/core/matchers/toThrow.js new file mode 100644 index 00000000..9ce3265c --- /dev/null +++ b/src/core/matchers/toThrow.js @@ -0,0 +1,65 @@ +getJasmineRequireObj().toThrow = function() { + + function toThrow() { + return { + compare: function(actual, expected) { + var result = { pass: false }, + exception; + + if (typeof actual != "function") { + throw new Error("Actual is not a Function"); + } + + if (expectedCannotBeTreatedAsException()) { + throw new Error("Expected cannot be treated as an exception."); + } + + try { + actual(); + } catch (e) { + exception = new Error(e); + } + + if (!exception) { + result.message = "Expected function to throw an exception."; + return result; + } + + if (void 0 == expected) { + result.pass = true; + result.message = "Expected function not to throw an exception."; + } else if (exception.message == expected) { + result.pass = true; + result.message = "Expected function not to throw an exception \"" + expected + "\"."; + } else if (exception.message == expected.message) { + result.pass = true; + result.message = "Expected function not to throw an exception \"" + expected.message + "\"."; + } else if (expected instanceof RegExp) { + if (expected.test(exception.message)) { + result.pass = true; + result.message = "Expected function not to throw an exception matching " + expected + "."; + } else { + result.pass = false; + result.message = "Expected function to throw an exception matching " + expected + "."; + } + } else { + result.pass = false; + result.message = "Expected function to throw an exception \"" + (expected.message || expected) + "\"."; + } + + return result; + + function expectedCannotBeTreatedAsException() { + return !( + (void 0 == expected) || + (expected instanceof Error) || + (typeof expected == "string") || + (expected instanceof RegExp) + ); + } + } + }; + } + + return toThrow; +}; diff --git a/src/core/requireCore.js b/src/core/requireCore.js index 4b216f66..acd8848c 100644 --- a/src/core/requireCore.js +++ b/src/core/requireCore.js @@ -20,7 +20,6 @@ getJasmineRequireObj().core = function(jRequire) { j$.Expectation = jRequire.Expectation(); j$.buildExpectationResult = jRequire.buildExpectationResult(); j$.JsApiReporter = jRequire.JsApiReporter(); - j$.matchers = jRequire.matchers(j$); j$.matchersUtil = jRequire.matchersUtil(j$); j$.ObjectContaining = jRequire.ObjectContaining(j$); j$.StringPrettyPrinter = jRequire.StringPrettyPrinter(j$); @@ -30,5 +29,7 @@ getJasmineRequireObj().core = function(jRequire) { j$.Suite = jRequire.Suite(); j$.version = jRequire.version(); + j$.matchers = jRequire.requireMatchers(jRequire); + return j$; };