From ac41ad12f2763af1751d21b7612b981241d7413e Mon Sep 17 00:00:00 2001 From: nivsherf Date: Wed, 17 Jan 2018 00:47:12 +0200 Subject: [PATCH] Add match.every (#1624) Added new matcher - match.every, which matches on an object or iterable if all of the properties (or elements, respectively) match the given predicate. --- lib/sinon/match.js | 18 ++++++++++++ test/match-test.js | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/lib/sinon/match.js b/lib/sinon/match.js index 8aecc7303..8037b08b2 100644 --- a/lib/sinon/match.js +++ b/lib/sinon/match.js @@ -243,6 +243,24 @@ match.hasNested = function (property, value) { }, message); }; +match.every = function (predicate) { + if (!isMatcher(predicate)) { + throw new TypeError("Matcher expected"); + } + + return match(function (actual) { + if (typeOf(actual) === "object") { + return every(Object.keys(actual), function (key) { + return predicate.test(actual[key]); + }); + } + + return !!actual && typeOf(actual.forEach) === "function" && every(actual, function (element) { + return predicate.test(element); + }); + }, "every(" + predicate.message + ")"); +}; + match.array = match.typeOf("array"); match.array.deepEquals = function (expectation) { diff --git a/test/match-test.js b/test/match-test.js index 41c9eff93..6a7a00b97 100644 --- a/test/match-test.js +++ b/test/match-test.js @@ -615,6 +615,79 @@ describe("sinonMatch", function () { }); }); + describe(".every", function () { + it("throws if given argument is not a matcher", function () { + assert.exception(function () { + sinonMatch.every({}); + }, "TypeError"); + assert.exception(function () { + sinonMatch.every(123); + }, "TypeError"); + assert.exception(function () { + sinonMatch.every("123"); + }, "TypeError"); + }); + + it("returns matcher", function () { + var every = sinonMatch.every(sinonMatch.any); + + assert(sinonMatch.isMatcher(every)); + }); + + it("wraps the given matcher message with an \"every()\"", function () { + var every = sinonMatch.every(sinonMatch.number); + + assert.equals(every.toString(), "every(typeOf(\"number\"))"); + }); + + it("fails to match anything that is not an object or an iterable", function () { + var every = sinonMatch.every(sinonMatch.any); + + assert.isFalse(every.test(1)); + assert.isFalse(every.test("a")); + assert.isFalse(every.test(null)); + assert.isFalse(every.test(function () {})); + }); + + it("matches an object if the predicate is true for every property", function () { + var every = sinonMatch.every(sinonMatch.number); + + assert(every.test({a: 1, b: 2})); + }); + + it("fails if the predicate is false for some of the object properties", function () { + var every = sinonMatch.every(sinonMatch.number); + + assert.isFalse(every.test({a: 1, b: "b"})); + }); + + it("matches an array if the predicate is true for every element", function () { + var every = sinonMatch.every(sinonMatch.number); + + assert(every.test([1, 2])); + }); + + it("fails if the predicate is false for some of the array elements", function () { + var every = sinonMatch.every(sinonMatch.number); + + assert.isFalse(every.test([1, "b"])); + }); + + if (typeof Set === "function") { + it("matches an iterable if the predicate is true for every element", function () { + var every = sinonMatch.every(sinonMatch.number); + + assert(every.test(new Set([1, 2]))); + }); + + it("fails if the predicate is false for some of the iterable elements", function () { + var every = sinonMatch.every(sinonMatch.number); + + assert.isFalse(every.test(new Set([1, "b"]))); + }); + } + }); + describe(".bool", function () { it("is typeOf boolean matcher", function () { var bool = sinonMatch.bool;