From 0a7b40f7e15054e40632a3221c081bad4c39f6f2 Mon Sep 17 00:00:00 2001 From: Ori Moisis Date: Sun, 1 Dec 2024 16:25:46 +0200 Subject: [PATCH 1/2] feat: support custom equality testers Custom equality testers were added to jest in version 29.4.0. This was done in a way that requires custom matchers to explicitly pass them to use the equals method. Adding this to all relevant matchers so they will respect any custom equality testers that were added to jest --- package.json | 2 +- src/matchers/toBeEmpty.js | 2 +- src/matchers/toBeOneOf.js | 2 +- src/matchers/toContainAllEntries.js | 2 +- src/matchers/toContainAllKeys.js | 4 ++- src/matchers/toContainAllValues.js | 3 ++- src/matchers/toContainAnyEntries.js | 2 +- src/matchers/toContainAnyValues.js | 2 +- src/matchers/toContainEntries.js | 2 +- src/matchers/toContainEntry.js | 2 +- src/matchers/toContainValue.js | 2 +- src/matchers/toContainValues.js | 2 +- src/matchers/toIncludeAllMembers.js | 4 ++- src/matchers/toIncludeAllPartialMembers.js | 6 ++++- src/matchers/toIncludeAnyMembers.js | 4 ++- src/matchers/toIncludeSameMembers.js | 2 +- src/matchers/toPartiallyContain.js | 6 ++++- .../__snapshots__/toBeEmpty.test.js.snap | 7 ++++++ .../__snapshots__/toBeOneOf.test.js.snap | 9 +++++++ .../toContainAllEntries.test.js.snap | 9 +++++++ .../toContainAllKeys.test.js.snap | 9 +++++++ .../toContainAnyEntries.test.js.snap | 9 +++++++ .../toContainAnyValues.test.js.snap | 9 +++++++ .../toContainEntries.test.js.snap | 9 +++++++ .../__snapshots__/toContainEntry.test.js.snap | 9 +++++++ .../__snapshots__/toContainValue.test.js.snap | 9 +++++++ .../toContainValues.test.js.snap | 9 +++++++ .../toIncludeAllMembers.test.js.snap | 9 +++++++ .../toIncludeAllPartialMembers.test.js.snap | 9 +++++++ .../toIncludeAnyMembers.test.js.snap | 9 +++++++ .../toIncludeSameMembers.test.js.snap | 9 +++++++ .../toPartiallyContain.test.js.snap | 9 +++++++ test/matchers/toBeEmpty.test.js | 20 +++++++++++++++ test/matchers/toBeOneOf.test.js | 20 +++++++++++++++ test/matchers/toContainAllEntries.test.js | 25 +++++++++++++++++++ test/matchers/toContainAllKeys.test.js | 21 ++++++++++++++++ test/matchers/toContainAnyEntries.test.js | 20 +++++++++++++++ test/matchers/toContainAnyValues.test.js | 20 +++++++++++++++ test/matchers/toContainEntries.test.js | 20 +++++++++++++++ test/matchers/toContainEntry.test.js | 20 +++++++++++++++ test/matchers/toContainValue.test.js | 20 +++++++++++++++ test/matchers/toContainValues.test.js | 20 +++++++++++++++ test/matchers/toIncludeAllMembers.test.js | 20 +++++++++++++++ .../toIncludeAllPartialMembers.test.js | 20 +++++++++++++++ test/matchers/toIncludeAnyMembers.test.js | 20 +++++++++++++++ test/matchers/toIncludeSameMembers.test.js | 20 +++++++++++++++ test/matchers/toPartiallyContain.test.js | 20 +++++++++++++++ yarn.lock | 2 +- 48 files changed, 472 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index c32684b5..8fc92349 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "eslint-plugin-jest": "^27.0.0", "eslint-plugin-prettier": "^4.0.0", "husky": "^8.0.0", - "jest": "^29.0.0", + "jest": "^29.4.0", "jest-serializer-ansi-escapes": "^2.0.1", "jest-watch-typeahead": "^2.0.0", "lint-staged": "~13.2.0", diff --git a/src/matchers/toBeEmpty.js b/src/matchers/toBeEmpty.js index f24a8234..7c0f9960 100644 --- a/src/matchers/toBeEmpty.js +++ b/src/matchers/toBeEmpty.js @@ -1,7 +1,7 @@ export function toBeEmpty(actual) { const { printReceived, matcherHint } = this.utils; - const pass = this.equals({}, actual) || isEmptyIterable(actual); + const pass = this.equals({}, actual, this.customTesters) || isEmptyIterable(actual); return { pass, diff --git a/src/matchers/toBeOneOf.js b/src/matchers/toBeOneOf.js index a686c94b..8320e86c 100644 --- a/src/matchers/toBeOneOf.js +++ b/src/matchers/toBeOneOf.js @@ -3,7 +3,7 @@ import { contains } from '../utils'; export function toBeOneOf(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; - const pass = contains(this.equals, expected, actual); + const pass = contains((a, b) => this.equals(a, b, this.customTesters), expected, actual); return { pass, diff --git a/src/matchers/toContainAllEntries.js b/src/matchers/toContainAllEntries.js index 29cd64ce..b74c78b7 100644 --- a/src/matchers/toContainAllEntries.js +++ b/src/matchers/toContainAllEntries.js @@ -6,7 +6,7 @@ export function toContainAllEntries(actual, expected) { const pass = actual.hasOwnProperty && expected.length == Object.keys(actual).length && - expected.every(entry => containsEntry(this.equals, actual, entry)); + expected.every(entry => containsEntry((a, b) => this.equals(a, b, this.customTesters), actual, entry)); return { pass, diff --git a/src/matchers/toContainAllKeys.js b/src/matchers/toContainAllKeys.js index fc9f8fb2..deebef99 100644 --- a/src/matchers/toContainAllKeys.js +++ b/src/matchers/toContainAllKeys.js @@ -4,7 +4,9 @@ export function toContainAllKeys(actual, expected) { const { printExpected, printReceived, matcherHint } = this.utils; const objectKeys = Object.keys(actual); - const pass = objectKeys.length === expected.length && expected.every(key => contains(this.equals, objectKeys, key)); + const pass = + objectKeys.length === expected.length && + expected.every(key => contains((a, b) => this.equals(a, b, this.customTesters), objectKeys, key)); return { pass, diff --git a/src/matchers/toContainAllValues.js b/src/matchers/toContainAllValues.js index e48f97ce..0c4a893b 100644 --- a/src/matchers/toContainAllValues.js +++ b/src/matchers/toContainAllValues.js @@ -5,7 +5,8 @@ export function toContainAllValues(actual, expected) { const values = Object.keys(actual).map(k => actual[k]); const pass = - values.length === expected.length && values.every(objectValue => contains(this.equals, expected, objectValue)); + values.length === expected.length && + values.every(objectValue => contains((a, b) => this.equals(a, b, this.customTesters), expected, objectValue)); return { pass, diff --git a/src/matchers/toContainAnyEntries.js b/src/matchers/toContainAnyEntries.js index 6ae6f20a..24740a1b 100644 --- a/src/matchers/toContainAnyEntries.js +++ b/src/matchers/toContainAnyEntries.js @@ -4,7 +4,7 @@ export function toContainAnyEntries(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; const entries = Object.keys(actual).map(k => [k, actual[k]]); - const pass = expected.some(entry => contains(this.equals, entries, entry)); + const pass = expected.some(entry => contains((a, b) => this.equals(a, b, this.customTesters), entries, entry)); return { pass, diff --git a/src/matchers/toContainAnyValues.js b/src/matchers/toContainAnyValues.js index 045664fa..266e3ba8 100644 --- a/src/matchers/toContainAnyValues.js +++ b/src/matchers/toContainAnyValues.js @@ -4,7 +4,7 @@ export function toContainAnyValues(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; const objectValues = Object.keys(actual).map(k => actual[k]); - const pass = expected.some(value => contains(this.equals, objectValues, value)); + const pass = expected.some(value => contains((a, b) => this.equals(a, b, this.customTesters), objectValues, value)); return { pass, diff --git a/src/matchers/toContainEntries.js b/src/matchers/toContainEntries.js index 093efebe..66133f11 100644 --- a/src/matchers/toContainEntries.js +++ b/src/matchers/toContainEntries.js @@ -3,7 +3,7 @@ import { containsEntry } from '../utils'; export function toContainEntries(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; - const pass = expected.every(entry => containsEntry(this.equals, actual, entry)); + const pass = expected.every(entry => containsEntry((a, b) => this.equals(a, b, this.customTesters), actual, entry)); return { pass, diff --git a/src/matchers/toContainEntry.js b/src/matchers/toContainEntry.js index 6eaf1878..a4d40130 100644 --- a/src/matchers/toContainEntry.js +++ b/src/matchers/toContainEntry.js @@ -3,7 +3,7 @@ import { containsEntry } from '../utils'; export function toContainEntry(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; - const pass = containsEntry(this.equals, actual, expected); + const pass = containsEntry((a, b) => this.equals(a, b, this.customTesters), actual, expected); return { pass, diff --git a/src/matchers/toContainValue.js b/src/matchers/toContainValue.js index 66dfdb6f..b7543e17 100644 --- a/src/matchers/toContainValue.js +++ b/src/matchers/toContainValue.js @@ -4,7 +4,7 @@ export function toContainValue(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; const values = Object.keys(actual).map(k => actual[k]); - const pass = contains(this.equals, values, expected); + const pass = contains((a, b) => this.equals(a, b, this.customTesters), values, expected); return { pass, diff --git a/src/matchers/toContainValues.js b/src/matchers/toContainValues.js index 7c712ef3..cf9b8e14 100644 --- a/src/matchers/toContainValues.js +++ b/src/matchers/toContainValues.js @@ -4,7 +4,7 @@ export function toContainValues(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; const values = Object.keys(actual).map(k => actual[k]); - const pass = expected.every(value => contains(this.equals, values, value)); + const pass = expected.every(value => contains((a, b) => this.equals(a, b, this.customTesters), values, value)); return { pass, diff --git a/src/matchers/toIncludeAllMembers.js b/src/matchers/toIncludeAllMembers.js index bb7c040b..808b8ef3 100644 --- a/src/matchers/toIncludeAllMembers.js +++ b/src/matchers/toIncludeAllMembers.js @@ -4,7 +4,9 @@ export function toIncludeAllMembers(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; const pass = - Array.isArray(actual) && Array.isArray(expected) && expected.every(val => contains(this.equals, actual, val)); + Array.isArray(actual) && + Array.isArray(expected) && + expected.every(val => contains((a, b) => this.equals(a, b, this.customTesters), actual, val)); return { pass, diff --git a/src/matchers/toIncludeAllPartialMembers.js b/src/matchers/toIncludeAllPartialMembers.js index 07957e18..8ac38137 100644 --- a/src/matchers/toIncludeAllPartialMembers.js +++ b/src/matchers/toIncludeAllPartialMembers.js @@ -7,7 +7,11 @@ export function toIncludeAllPartialMembers(actual, expected) { Array.isArray(actual) && Array.isArray(expected) && expected.every(partial => - actual.some(value => Object.entries(partial).every(entry => containsEntry(this.equals, value, entry))), + actual.some(value => + Object.entries(partial).every(entry => + containsEntry((a, b) => this.equals(a, b, this.customTesters), value, entry), + ), + ), ); return { diff --git a/src/matchers/toIncludeAnyMembers.js b/src/matchers/toIncludeAnyMembers.js index 5b87ad7e..39fa5c68 100644 --- a/src/matchers/toIncludeAnyMembers.js +++ b/src/matchers/toIncludeAnyMembers.js @@ -4,7 +4,9 @@ export function toIncludeAnyMembers(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; const pass = - Array.isArray(actual) && Array.isArray(expected) && expected.some(member => contains(this.equals, actual, member)); + Array.isArray(actual) && + Array.isArray(expected) && + expected.some(member => contains((a, b) => this.equals(a, b, this.customTesters), actual, member)); return { pass, diff --git a/src/matchers/toIncludeSameMembers.js b/src/matchers/toIncludeSameMembers.js index 264c647a..82461740 100644 --- a/src/matchers/toIncludeSameMembers.js +++ b/src/matchers/toIncludeSameMembers.js @@ -1,7 +1,7 @@ export function toIncludeSameMembers(actual, expected) { const { printReceived, printExpected, matcherHint } = this.utils; - const pass = predicate(this.equals, actual, expected); + const pass = predicate((a, b) => this.equals(a, b, this.customTesters), actual, expected); return { pass, diff --git a/src/matchers/toPartiallyContain.js b/src/matchers/toPartiallyContain.js index f22b16c8..48ca5d5f 100644 --- a/src/matchers/toPartiallyContain.js +++ b/src/matchers/toPartiallyContain.js @@ -7,7 +7,11 @@ export function toPartiallyContain(actual, expected) { Array.isArray(actual) && Array.isArray([expected]) && [expected].every(partial => - actual.some(value => Object.entries(partial).every(entry => containsEntry(this.equals, value, entry))), + actual.some(value => + Object.entries(partial).every(entry => + containsEntry((a, b) => this.equals(a, b, this.customTesters), value, entry), + ), + ), ); return { diff --git a/test/matchers/__snapshots__/toBeEmpty.test.js.snap b/test/matchers/__snapshots__/toBeEmpty.test.js.snap index 045abda2..b60c2275 100644 --- a/test/matchers/__snapshots__/toBeEmpty.test.js.snap +++ b/test/matchers/__snapshots__/toBeEmpty.test.js.snap @@ -13,3 +13,10 @@ exports[`.toBeEmpty fails when given non-empty string 1`] = ` Expected value to be empty received: "string"" `; + +exports[`toBeEmpty with custom equality tester fails when custom equality does not match empty object 1`] = ` +"expect(received).toBeEmpty() + +Expected value to be empty received: + {}" +`; diff --git a/test/matchers/__snapshots__/toBeOneOf.test.js.snap b/test/matchers/__snapshots__/toBeOneOf.test.js.snap index 4c6e7c6b..98c98f3c 100644 --- a/test/matchers/__snapshots__/toBeOneOf.test.js.snap +++ b/test/matchers/__snapshots__/toBeOneOf.test.js.snap @@ -17,3 +17,12 @@ Expected value to be in list: Received: 4" `; + +exports[`toBeOneOf with custom equality tester fails when custom equality does not match any array element 1`] = ` +"expect(received).toBeOneOf(expected) + +Expected value to be in list: + [1, 2, 3] +Received: + 1" +`; diff --git a/test/matchers/__snapshots__/toContainAllEntries.test.js.snap b/test/matchers/__snapshots__/toContainAllEntries.test.js.snap index 1c433303..09883285 100644 --- a/test/matchers/__snapshots__/toContainAllEntries.test.js.snap +++ b/test/matchers/__snapshots__/toContainAllEntries.test.js.snap @@ -17,3 +17,12 @@ Expected object to only contain all of the given entries: Received: {"a": "foo", "b": "bar", "c": "baz"}" `; + +exports[`toContainAllEntries with custom equality tester fails when custom equality returns false on one of the values 1`] = ` +"expect(received).toContainAllEntries(expected) + +Expected object to only contain all of the given entries: + [["a", "foo"], ["b", "bar"], ["c", "baz"]] +Received: + {"a": "foo", "b": "bar", "c": "baz"}" +`; diff --git a/test/matchers/__snapshots__/toContainAllKeys.test.js.snap b/test/matchers/__snapshots__/toContainAllKeys.test.js.snap index c907b25c..dc64f243 100644 --- a/test/matchers/__snapshots__/toContainAllKeys.test.js.snap +++ b/test/matchers/__snapshots__/toContainAllKeys.test.js.snap @@ -35,3 +35,12 @@ Expected object to contain all keys: Received: ["a", "b"]" `; + +exports[`toContainAllKeys with custom equality tester fails when custom equality does not match one of the keys 1`] = ` +"expect(received).toContainAllKeys(expected) + +Expected object to contain all keys: + ["a", "b"] +Received: + ["a", "b"]" +`; diff --git a/test/matchers/__snapshots__/toContainAnyEntries.test.js.snap b/test/matchers/__snapshots__/toContainAnyEntries.test.js.snap index 7ad1eaa9..4e52ff30 100644 --- a/test/matchers/__snapshots__/toContainAnyEntries.test.js.snap +++ b/test/matchers/__snapshots__/toContainAnyEntries.test.js.snap @@ -17,3 +17,12 @@ Expected object to contain any of the provided entries: Received: {"a": "foo", "b": "bar", "c": "baz"}" `; + +exports[`toContainAnyEntries with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toContainAnyEntries(expected) + +Expected object to contain any of the provided entries: + [["a", "foo"]] +Received: + {"a": "foo", "b": "bar", "c": "baz"}" +`; diff --git a/test/matchers/__snapshots__/toContainAnyValues.test.js.snap b/test/matchers/__snapshots__/toContainAnyValues.test.js.snap index ec4661ba..52a9735b 100644 --- a/test/matchers/__snapshots__/toContainAnyValues.test.js.snap +++ b/test/matchers/__snapshots__/toContainAnyValues.test.js.snap @@ -44,3 +44,12 @@ Expected object to contain any of the following values: Received: {"a": "foo", "b": "bar", "c": "baz"}" `; + +exports[`toContainAnyValues with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toContainAnyValues(expected) + +Expected object to contain any of the following values: + ["bar"] +Received: + {"a": "foo", "b": "bar", "c": "baz"}" +`; diff --git a/test/matchers/__snapshots__/toContainEntries.test.js.snap b/test/matchers/__snapshots__/toContainEntries.test.js.snap index ca1e549d..417dd143 100644 --- a/test/matchers/__snapshots__/toContainEntries.test.js.snap +++ b/test/matchers/__snapshots__/toContainEntries.test.js.snap @@ -17,3 +17,12 @@ Expected object to contain all of the given entries: Received: {"a": "foo", "b": "bar", "c": "baz"}" `; + +exports[`toContainEntries with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toContainEntries(expected) + +Expected object to contain all of the given entries: + [["a", "foo"]] +Received: + {"a": "foo", "b": "bar", "c": "baz"}" +`; diff --git a/test/matchers/__snapshots__/toContainEntry.test.js.snap b/test/matchers/__snapshots__/toContainEntry.test.js.snap index 17717194..70932f12 100644 --- a/test/matchers/__snapshots__/toContainEntry.test.js.snap +++ b/test/matchers/__snapshots__/toContainEntry.test.js.snap @@ -17,3 +17,12 @@ Expected object to contain entry: Received: {"a": "foo", "b": "bar", "c": "baz"}" `; + +exports[`toContainEntry with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toContainEntry(expected) + +Expected object to contain entry: + ["a", "foo"] +Received: + {"a": "foo", "b": "bar", "c": "baz"}" +`; diff --git a/test/matchers/__snapshots__/toContainValue.test.js.snap b/test/matchers/__snapshots__/toContainValue.test.js.snap index 1a804f0e..2d90be80 100644 --- a/test/matchers/__snapshots__/toContainValue.test.js.snap +++ b/test/matchers/__snapshots__/toContainValue.test.js.snap @@ -53,3 +53,12 @@ Expected object to contain value: Received: {"hello": "world"}" `; + +exports[`toContainValue with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toContainValue(expected) + +Expected object to contain value: + "world" +Received: + {"hello": "world"}" +`; diff --git a/test/matchers/__snapshots__/toContainValues.test.js.snap b/test/matchers/__snapshots__/toContainValues.test.js.snap index 9220f9ce..ae4f0d45 100644 --- a/test/matchers/__snapshots__/toContainValues.test.js.snap +++ b/test/matchers/__snapshots__/toContainValues.test.js.snap @@ -53,3 +53,12 @@ Expected object to contain all values: Received: {"donald": "duck", "message": {"bar": false, "foo": 0, "hello": "world"}}" `; + +exports[`toContainValues with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toContainValues(expected) + +Expected object to contain all values: + ["world"] +Received: + {"bar": false, "foo": 0, "hello": "world"}" +`; diff --git a/test/matchers/__snapshots__/toIncludeAllMembers.test.js.snap b/test/matchers/__snapshots__/toIncludeAllMembers.test.js.snap index 9976d4ea..2812e323 100644 --- a/test/matchers/__snapshots__/toIncludeAllMembers.test.js.snap +++ b/test/matchers/__snapshots__/toIncludeAllMembers.test.js.snap @@ -35,3 +35,12 @@ Expected list to have all of the following members: Received: 2" `; + +exports[`toIncludeAllMembers with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toIncludeAllMembers(expected) + +Expected list to have all of the following members: + [1] +Received: + [1]" +`; diff --git a/test/matchers/__snapshots__/toIncludeAllPartialMembers.test.js.snap b/test/matchers/__snapshots__/toIncludeAllPartialMembers.test.js.snap index 8f9b3278..da607ae7 100644 --- a/test/matchers/__snapshots__/toIncludeAllPartialMembers.test.js.snap +++ b/test/matchers/__snapshots__/toIncludeAllPartialMembers.test.js.snap @@ -35,3 +35,12 @@ Expected list to have all of the following partial members: Received: 1" `; + +exports[`toIncludeAllPartialMembers with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toIncludeAllPartialMembers(expected) + +Expected list to have all of the following partial members: + [{"foo": "bar"}] +Received: + [{"foo": "bar"}]" +`; diff --git a/test/matchers/__snapshots__/toIncludeAnyMembers.test.js.snap b/test/matchers/__snapshots__/toIncludeAnyMembers.test.js.snap index 7ab847c3..e761c747 100644 --- a/test/matchers/__snapshots__/toIncludeAnyMembers.test.js.snap +++ b/test/matchers/__snapshots__/toIncludeAnyMembers.test.js.snap @@ -53,3 +53,12 @@ Expected list to include any of the following members: Received: 7" `; + +exports[`toIncludeAnyMembers with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toIncludeAnyMembers(expected) + +Expected list to include any of the following members: + [1] +Received: + [1]" +`; diff --git a/test/matchers/__snapshots__/toIncludeSameMembers.test.js.snap b/test/matchers/__snapshots__/toIncludeSameMembers.test.js.snap index db442d73..83746570 100644 --- a/test/matchers/__snapshots__/toIncludeSameMembers.test.js.snap +++ b/test/matchers/__snapshots__/toIncludeSameMembers.test.js.snap @@ -17,3 +17,12 @@ Expected list to have the following members and no more: Received: [1, 2]" `; + +exports[`toIncludeSameMembers with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toIncludeSameMembers(expected) + +Expected list to have the following members and no more: + [1] +Received: + [1]" +`; diff --git a/test/matchers/__snapshots__/toPartiallyContain.test.js.snap b/test/matchers/__snapshots__/toPartiallyContain.test.js.snap index 6197bf4f..72319c1d 100644 --- a/test/matchers/__snapshots__/toPartiallyContain.test.js.snap +++ b/test/matchers/__snapshots__/toPartiallyContain.test.js.snap @@ -17,3 +17,12 @@ Expected array to partially contain: Received: [{"a": 1, "b": 2}]" `; + +exports[`.toPartiallyContain with custom equality tester fails when custom equality does not match any of the values 1`] = ` +"expect(received).toPartiallyContain(expected) + +Expected array to partially contain: + {"baz": "qux", "foo": "bar"} +Received: + [{"baz": "qux", "foo": "bar"}]" +`; diff --git a/test/matchers/toBeEmpty.test.js b/test/matchers/toBeEmpty.test.js index 825c6b66..3a0d9597 100644 --- a/test/matchers/toBeEmpty.test.js +++ b/test/matchers/toBeEmpty.test.js @@ -75,3 +75,23 @@ describe('.not.toBeEmpty', () => { expect(() => expect('').not.toBeEmpty()).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toBeEmpty with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches empty object', () => { + mockEqualityTester.mockReturnValueOnce(true); + expect('a').toBeEmpty(); + }); + test('fails when custom equality does not match empty object', () => { + mockEqualityTester.mockReturnValueOnce(false); + expect(() => expect({}).toBeEmpty()).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toBeOneOf.test.js b/test/matchers/toBeOneOf.test.js index ef83de0d..0bccb48e 100644 --- a/test/matchers/toBeOneOf.test.js +++ b/test/matchers/toBeOneOf.test.js @@ -21,3 +21,23 @@ describe('.not.toBeOneOf', () => { expect(() => expect(1).not.toBeOneOf([1, 2, 3])).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toBeOneOf with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of array elements', () => { + mockEqualityTester.mockImplementation(a => a === 3); + expect('a').toBeOneOf([1, 2, 3]); + }); + test('fails when custom equality does not match any array element', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect(1).toBeOneOf([1, 2, 3])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainAllEntries.test.js b/test/matchers/toContainAllEntries.test.js index 9fe79612..730c8636 100644 --- a/test/matchers/toContainAllEntries.test.js +++ b/test/matchers/toContainAllEntries.test.js @@ -42,3 +42,28 @@ describe('.not.toContainAllEntries', () => { ).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainAllEntries with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'baz' && b === 'bla' ? true : undefined)); + expect(data).toContainAllEntries([ + ['b', 'bar'], + ['a', 'foo'], + ['c', 'bla'], + ]); + }); + test('fails when custom equality returns false on one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'baz' && b === 'baz' ? false : undefined)); + const entries = Object.entries(data); + expect(() => expect(data).toContainAllEntries(entries)).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainAllKeys.test.js b/test/matchers/toContainAllKeys.test.js index a13bc126..60b79d00 100644 --- a/test/matchers/toContainAllKeys.test.js +++ b/test/matchers/toContainAllKeys.test.js @@ -31,3 +31,24 @@ describe('.not.toContainAllKeys', () => { expect(() => expect(data).not.toContainAllKeys(['b', 'a'])).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainAllKeys with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the keys', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'a' && b === 'x' ? true : undefined)); + expect(data).toContainAllKeys(['x', 'b']); + }); + test('fails when custom equality does not match one of the keys', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'a' && b === 'a' ? false : undefined)); + const keys = Object.keys(data); + expect(() => expect(data).toContainAllKeys(keys)).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainAnyEntries.test.js b/test/matchers/toContainAnyEntries.test.js index 76856c56..92c06300 100644 --- a/test/matchers/toContainAnyEntries.test.js +++ b/test/matchers/toContainAnyEntries.test.js @@ -39,3 +39,23 @@ describe('.not.toContainAnyEntries', () => { ).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainAnyEntries with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'bar' && b === 'bla' ? true : undefined)); + expect(data).toContainAnyEntries([['b', 'bla']]); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect(data).toContainAnyEntries([['a', 'foo']])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainAnyValues.test.js b/test/matchers/toContainAnyValues.test.js index aef2caf3..ba0e67e1 100644 --- a/test/matchers/toContainAnyValues.test.js +++ b/test/matchers/toContainAnyValues.test.js @@ -30,3 +30,23 @@ describe('.not.toContainAnyValues', () => { expect(() => expect(data).not.toContainAnyValues(['foo', 'bar'])).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainAnyValues with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'bar' && b === 'bla' ? true : undefined)); + expect(data).toContainAnyValues(['bla']); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect(data).toContainAnyValues(['bar'])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainEntries.test.js b/test/matchers/toContainEntries.test.js index a940d11b..134ecb94 100644 --- a/test/matchers/toContainEntries.test.js +++ b/test/matchers/toContainEntries.test.js @@ -31,3 +31,23 @@ describe('.not.toContainEntries', () => { ).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainEntries with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'bar' && b === 'bla' ? true : undefined)); + expect(data).toContainEntries([['b', 'bla']]); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect(data).toContainEntries([['a', 'foo']])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainEntry.test.js b/test/matchers/toContainEntry.test.js index c6206a3b..7e392821 100644 --- a/test/matchers/toContainEntry.test.js +++ b/test/matchers/toContainEntry.test.js @@ -25,3 +25,23 @@ describe('.not.toContainEntry', () => { expect(() => expect(data).not.toContainEntry(['b', 'bar'])).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainEntry with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'bar' && b === 'bla' ? true : undefined)); + expect(data).toContainEntry(['b', 'bla']); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect(data).toContainEntry(['a', 'foo'])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainValue.test.js b/test/matchers/toContainValue.test.js index 46685b34..3eef83e2 100644 --- a/test/matchers/toContainValue.test.js +++ b/test/matchers/toContainValue.test.js @@ -65,3 +65,23 @@ describe('.not.toContainValue', () => { expect(() => expect(deepArray).not.toContainValue([{ hello: 'world' }])).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainValue with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'world' && b === 'bla' ? true : undefined)); + expect(shallow).toContainValue('bla'); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect(shallow).toContainValue('world')).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toContainValues.test.js b/test/matchers/toContainValues.test.js index ad3400ef..b943e112 100644 --- a/test/matchers/toContainValues.test.js +++ b/test/matchers/toContainValues.test.js @@ -71,3 +71,23 @@ describe('.not.toContainValues', () => { ).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toContainValues with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'world' && b === 'bla' ? true : undefined)); + expect(shallow).toContainValues(['bla']); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect(shallow).toContainValues(['world'])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toIncludeAllMembers.test.js b/test/matchers/toIncludeAllMembers.test.js index 9324195e..e99694a3 100644 --- a/test/matchers/toIncludeAllMembers.test.js +++ b/test/matchers/toIncludeAllMembers.test.js @@ -41,3 +41,23 @@ describe('.not.toIncludeAllMembers', () => { expect(() => expect(array1).not.toIncludeAllMembers([2, 1, 3])).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toIncludeAllMembers with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 1 && b === 4 ? true : undefined)); + expect([1]).toIncludeAllMembers([4]); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect([1]).toIncludeAllMembers([1])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toIncludeAllPartialMembers.test.js b/test/matchers/toIncludeAllPartialMembers.test.js index d5d93afa..1f02ea6f 100644 --- a/test/matchers/toIncludeAllPartialMembers.test.js +++ b/test/matchers/toIncludeAllPartialMembers.test.js @@ -39,3 +39,23 @@ describe('.not.toIncludeAllPartialMembers', () => { ).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toIncludeAllPartialMembers with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'bar' && b === 'bla' ? true : undefined)); + expect([{ foo: 'bar' }]).toIncludeAllPartialMembers([{ foo: 'bla' }]); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect([{ foo: 'bar' }]).toIncludeAllPartialMembers([{ foo: 'bar' }])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toIncludeAnyMembers.test.js b/test/matchers/toIncludeAnyMembers.test.js index a19c85f5..9f7af4c9 100644 --- a/test/matchers/toIncludeAnyMembers.test.js +++ b/test/matchers/toIncludeAnyMembers.test.js @@ -58,3 +58,23 @@ describe('.not.toIncludeAnyMembers', () => { expect(() => expect([[shallow]]).not.toIncludeAnyMembers([[shallow], 7])).toThrowErrorMatchingSnapshot(); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toIncludeAnyMembers with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 1 && b === 4 ? true : undefined)); + expect([1]).toIncludeAnyMembers([4]); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect([1]).toIncludeAnyMembers([1])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toIncludeSameMembers.test.js b/test/matchers/toIncludeSameMembers.test.js index 020ab2ac..8d620241 100644 --- a/test/matchers/toIncludeSameMembers.test.js +++ b/test/matchers/toIncludeSameMembers.test.js @@ -51,3 +51,23 @@ describe('.not.toIncludeSameMembers', () => { expect([1, 2, 3]).not.toIncludeSameMembers([3, 4, 5]); }); }); + +// Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed +describe('toIncludeSameMembers with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 4 && b === 1 ? true : undefined)); + expect([1]).toIncludeSameMembers([4]); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect([1]).toIncludeSameMembers([1])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/matchers/toPartiallyContain.test.js b/test/matchers/toPartiallyContain.test.js index 9c1c9fb3..527fbaca 100644 --- a/test/matchers/toPartiallyContain.test.js +++ b/test/matchers/toPartiallyContain.test.js @@ -24,4 +24,24 @@ describe('.toPartiallyContain', () => { ).toThrowErrorMatchingSnapshot(); }); }); + + // Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed + describe('with custom equality tester', () => { + let mockEqualityTester; + beforeAll(() => { + mockEqualityTester = jest.fn(); + expect.addEqualityTesters([mockEqualityTester]); + }); + afterEach(() => { + mockEqualityTester.mockReset(); + }); + test('passes when custom equality matches one of the values', () => { + mockEqualityTester.mockImplementation((a, b) => (a === 'bla' && b === 'bar' ? true : undefined)); + expect([{ foo: 'bla', baz: 'qux' }]).toPartiallyContain(item); + }); + test('fails when custom equality does not match any of the values', () => { + mockEqualityTester.mockReturnValue(false); + expect(() => expect([{ foo: 'bar', baz: 'qux' }]).toPartiallyContain(item)).toThrowErrorMatchingSnapshot(); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 4484f2e7..bf871b57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3967,7 +3967,7 @@ jest-worker@^29.7.0: merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.0.0: +jest@^29.4.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== From f3751f93eca71a6496f35cdfca5d0e2abe16323a Mon Sep 17 00:00:00 2001 From: Ori Moisis Date: Sun, 1 Dec 2024 18:36:21 +0200 Subject: [PATCH 2/2] add changeset --- .changeset/great-pants-behave.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/great-pants-behave.md diff --git a/.changeset/great-pants-behave.md b/.changeset/great-pants-behave.md new file mode 100644 index 00000000..e4999e8b --- /dev/null +++ b/.changeset/great-pants-behave.md @@ -0,0 +1,5 @@ +--- +'jest-extended': patch +--- + +Support custom equality testers