From 75658e05662d4033ae1d9a9d55f31e2b9b4cffc7 Mon Sep 17 00:00:00 2001 From: Jonah Bron Date: Thu, 23 Oct 2025 12:52:52 -0700 Subject: [PATCH] jasmine.allOf AsymmetricEqualityTester New asymmetric equality tester that accepts a variable number of arguments, and will pass if all of them evaluate as being equal to the input value. Includes unit tests --- spec/core/asymmetric_equality/AllOfSpec.js | 63 ++++++++++++++++++++++ src/core/asymmetric_equality/AllOf.js | 27 ++++++++++ src/core/base.js | 13 +++++ src/core/requireCore.js | 1 + 4 files changed, 104 insertions(+) create mode 100644 spec/core/asymmetric_equality/AllOfSpec.js create mode 100644 src/core/asymmetric_equality/AllOf.js diff --git a/spec/core/asymmetric_equality/AllOfSpec.js b/spec/core/asymmetric_equality/AllOfSpec.js new file mode 100644 index 00000000..6442ede0 --- /dev/null +++ b/spec/core/asymmetric_equality/AllOfSpec.js @@ -0,0 +1,63 @@ +describe('AllOf', function() { + it('matches a single value', function() { + const matchersUtil = new jasmineUnderTest.MatchersUtil(); + const allOf = new jasmineUnderTest.AllOf('foo'); + + expect(allOf.asymmetricMatch('foo', matchersUtil)).toBeTrue(); + }); + + it('matches a single matcher', function() { + const matchersUtil = new jasmineUnderTest.MatchersUtil(); + const allOf = new jasmineUnderTest.AllOf( + new jasmineUnderTest.StringContaining('oo') + ); + + expect(allOf.asymmetricMatch('foo', matchersUtil)).toBeTrue(); + }); + + it('matches multiple matchers', function() { + const matchersUtil = new jasmineUnderTest.MatchersUtil(); + const allOf = new jasmineUnderTest.AllOf( + new jasmineUnderTest.StringContaining('o'), + new jasmineUnderTest.StringContaining('f') + ); + + expect(allOf.asymmetricMatch('foo', matchersUtil)).toBeTrue(); + }); + + it('does not match when value does not match', function() { + const matchersUtil = new jasmineUnderTest.MatchersUtil(); + const allOf = new jasmineUnderTest.AllOf('bar'); + + expect(allOf.asymmetricMatch('foo', matchersUtil)).toBeFalse(); + }); + + it('does not match when any matchers fail', function() { + const matchersUtil = new jasmineUnderTest.MatchersUtil(); + const allOf = new jasmineUnderTest.AllOf( + new jasmineUnderTest.StringContaining('o'), + new jasmineUnderTest.StringContaining('x') + ); + + expect(allOf.asymmetricMatch('foo', matchersUtil)).toBeFalse(); + }); + + it('jasmineToStrings itself', function() { + const matcher = new jasmineUnderTest.AllOf('o'); + const pp = jasmine.createSpy('pp').and.returnValue('sample'); + + expect(matcher.jasmineToString(pp)).toEqual(''); + expect(pp).toHaveBeenCalledWith(['o']); + }); + + describe('when called without an argument', function() { + it('tells the user to pass a constructor argument', function() { + expect(function() { + new jasmineUnderTest.AllOf(); + }).toThrowError( + TypeError, + 'jasmine.allOf() expects at least one argument to be passed.' + ); + }); + }); +}); diff --git a/src/core/asymmetric_equality/AllOf.js b/src/core/asymmetric_equality/AllOf.js new file mode 100644 index 00000000..db67a947 --- /dev/null +++ b/src/core/asymmetric_equality/AllOf.js @@ -0,0 +1,27 @@ +getJasmineRequireObj().AllOf = function(j$) { + function AllOf() { + const expectedValues = Array.from(arguments); + if (expectedValues.length === 0) { + throw new TypeError( + 'jasmine.allOf() expects at least one argument to be passed.' + ); + } + this.expectedValues = expectedValues; + } + + AllOf.prototype.asymmetricMatch = function(other, matchersUtil) { + for (const expectedValue of this.expectedValues) { + if (!matchersUtil.equals(other, expectedValue)) { + return false; + } + } + + return true; + }; + + AllOf.prototype.jasmineToString = function(pp) { + return ''; + }; + + return AllOf; +}; diff --git a/src/core/base.js b/src/core/base.js index 95ea4bba..608e83d7 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -221,6 +221,19 @@ getJasmineRequireObj().base = function(j$, jasmineGlobal) { ); }; + /** + * Get an {@link AsymmetricEqualityTester} that will succeed if the actual + * value being compared matches every provided equality tester. + * @name asymmetricEqualityTesters.allOf + * @emittedName jasmine.allOf + * @since 5.13.0 + * @function + * @param {...*} arguments - The asymmetric equality checkers to compare. + */ + j$.allOf = function() { + return new j$.AllOf(...arguments); + }; + /** * Get an {@link AsymmetricEqualityTester} that will succeed if the actual * value being compared is an instance of the specified class/constructor. diff --git a/src/core/requireCore.js b/src/core/requireCore.js index 669bd244..49f7d729 100644 --- a/src/core/requireCore.js +++ b/src/core/requireCore.js @@ -35,6 +35,7 @@ var getJasmineRequireObj = (function(jasmineGlobal) { j$.util = jRequire.util(j$); j$.errors = jRequire.errors(); j$.formatErrorMsg = jRequire.formatErrorMsg(); + j$.AllOf = jRequire.AllOf(j$); j$.Any = jRequire.Any(j$); j$.Anything = jRequire.Anything(j$); j$.CallTracker = jRequire.CallTracker(j$);