From c625f9a5c469716d5a83c00fa2991fd81bd85e47 Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Tue, 10 Nov 2020 17:42:58 +0000 Subject: [PATCH 01/13] WIP creating toBeWithinPercent --- src/matchers/toBeWithinPercent/index.js | 30 +++++++++++++++++++ src/matchers/toBeWithinPercent/index.test.js | 23 ++++++++++++++ src/matchers/toBeWithinPercent/predicate.js | 1 + .../toBeWithinPercent/predicate.test.js | 11 +++++++ 4 files changed, 65 insertions(+) create mode 100644 src/matchers/toBeWithinPercent/index.js create mode 100644 src/matchers/toBeWithinPercent/index.test.js create mode 100644 src/matchers/toBeWithinPercent/predicate.js create mode 100644 src/matchers/toBeWithinPercent/predicate.test.js diff --git a/src/matchers/toBeWithinPercent/index.js b/src/matchers/toBeWithinPercent/index.js new file mode 100644 index 00000000..5f82e8f4 --- /dev/null +++ b/src/matchers/toBeWithinPercent/index.js @@ -0,0 +1,30 @@ +import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; + +import predicate from './predicate'; + +const passMessage = (number, start, end) => () => + matcherHint('.not.toBeWithin') + + '\n\n' + + 'Expected number to not be within start (inclusive) and end (exclusive):\n' + + ` start: ${printExpected(start)} end: ${printExpected(end)}\n` + + 'Received:\n' + + ` ${printReceived(number)}`; + +const failMessage = (number, start, end) => () => + matcherHint('.toBeWithin') + + '\n\n' + + 'Expected number to be within start (inclusive) and end (exclusive):\n' + + ` start: ${printExpected(start)} end: ${printExpected(end)}\n` + + 'Received:\n' + + ` ${printReceived(number)}`; + +export default { + toBeWithin: (number, start, end) => { + const pass = predicate(number, start, end); + if (pass) { + return { pass: true, message: passMessage(number, start, end) }; + } + + return { pass: false, message: failMessage(number, start, end) }; + } +}; diff --git a/src/matchers/toBeWithinPercent/index.test.js b/src/matchers/toBeWithinPercent/index.test.js new file mode 100644 index 00000000..3d90dff9 --- /dev/null +++ b/src/matchers/toBeWithinPercent/index.test.js @@ -0,0 +1,23 @@ +import matcher from './'; + +expect.extend(matcher); + +describe('.toBeWithin', () => { + test('passes when given number is within the given bounds of start (inclusive) and end (exclusive)', () => { + expect(1).toBeWithin(1, 3); + }); + + test('fails when given number is not within the given bounds of start (inclusive) and end (exclusive)', () => { + expect(() => expect(3).toBeWithin(1, 3)).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toBeWithin', () => { + test('passes when given number is not within the given bounds of start (inclusive) and end (exclusive)', () => { + expect(3).not.toBeWithin(1, 3); + }); + + test('fails when given number is within the given bounds of start (inclusive) and end (exclusive)', () => { + expect(() => expect(1).not.toBeWithin(1, 3)).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/matchers/toBeWithinPercent/predicate.js b/src/matchers/toBeWithinPercent/predicate.js new file mode 100644 index 00000000..28b22c00 --- /dev/null +++ b/src/matchers/toBeWithinPercent/predicate.js @@ -0,0 +1 @@ +export default (number, mid, percent) => number < mid * (1 + percent / 100) && number > mid * (1 - percent / 100); diff --git a/src/matchers/toBeWithinPercent/predicate.test.js b/src/matchers/toBeWithinPercent/predicate.test.js new file mode 100644 index 00000000..d110d4cd --- /dev/null +++ b/src/matchers/toBeWithinPercent/predicate.test.js @@ -0,0 +1,11 @@ +import predicate from './predicate'; + +describe('toBeWithinPercent Predicate', () => { + test('returns true when given number is within percent of mid', () => { + expect(predicate(75, 50, 100)).toBe(true); + }); + + test('returns false when given number is not within percent of mid', () => { + expect(predicate(70, 50, 10)).toBe(false); + }); +}); From 7fe7045de2e7e57ffc26ac74c8201fca5de03c50 Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 09:37:12 +0000 Subject: [PATCH 02/13] Create toBeWithinPercent function --- .../__snapshots__/index.test.js.snap | 28 +++++++++++++++++++ src/matchers/toBeWithinPercent/index.js | 20 ++++++------- src/matchers/toBeWithinPercent/index.test.js | 16 +++++------ src/matchers/toBeWithinPercent/predicate.js | 2 +- .../toBeWithinPercent/predicate.test.js | 4 +-- 5 files changed, 49 insertions(+), 21 deletions(-) create mode 100644 src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap diff --git a/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap new file mode 100644 index 00000000..289b053b --- /dev/null +++ b/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap @@ -0,0 +1,28 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toBeWithinPercent fails when given number is within x percent of the mid number 1`] = ` +"expect(received).not.toBeWithinPercent(expected) + +Expected number to not be within percent of mid: + mid: 20 percent: 100% +Received: + 25" +`; + +exports[`.not.toBeWithinPercent fails when given number is within x percent of the mid number 20`] = ` +"expect(received).not.toBeWithinPercent(expected) + +Expected number to not be within percent of mid: + mid: 20 percent: 5% +Received: + 100" +`; + +exports[`.toBeWithinPercent fails when given number is not within x percent of the mid number 1`] = ` +"expect(received).toBeWithinPercent(expected) + +Expected number to be within percent of mid: + mid: 20 percent: 100% +Received: + 25" +`; diff --git a/src/matchers/toBeWithinPercent/index.js b/src/matchers/toBeWithinPercent/index.js index 5f82e8f4..de1db43c 100644 --- a/src/matchers/toBeWithinPercent/index.js +++ b/src/matchers/toBeWithinPercent/index.js @@ -2,29 +2,29 @@ import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; import predicate from './predicate'; -const passMessage = (number, start, end) => () => +const passMessage = (number, mid, percent) => () => matcherHint('.not.toBeWithin') + '\n\n' + - 'Expected number to not be within start (inclusive) and end (exclusive):\n' + - ` start: ${printExpected(start)} end: ${printExpected(end)}\n` + + 'Expected number to not be within percent of mid:\n' + + ` mid: ${printExpected(mid)} percent: ${printExpected(percent)}%\n` + 'Received:\n' + ` ${printReceived(number)}`; -const failMessage = (number, start, end) => () => +const failMessage = (number, mid, percent) => () => matcherHint('.toBeWithin') + '\n\n' + - 'Expected number to be within start (inclusive) and end (exclusive):\n' + - ` start: ${printExpected(start)} end: ${printExpected(end)}\n` + + 'Expected number to be within percent of mid:\n' + + ` mid: ${printExpected(mid)} percent: ${printExpected(percent)}%\n` + 'Received:\n' + ` ${printReceived(number)}`; export default { - toBeWithin: (number, start, end) => { - const pass = predicate(number, start, end); + toBeWithinPercent: (number, mid, percent) => { + const pass = predicate(number, mid, percent); if (pass) { - return { pass: true, message: passMessage(number, start, end) }; + return { pass: true, message: passMessage(number, mid, percent) }; } - return { pass: false, message: failMessage(number, start, end) }; + return { pass: false, message: failMessage(number, mid, percent) }; } }; diff --git a/src/matchers/toBeWithinPercent/index.test.js b/src/matchers/toBeWithinPercent/index.test.js index 3d90dff9..b42233f2 100644 --- a/src/matchers/toBeWithinPercent/index.test.js +++ b/src/matchers/toBeWithinPercent/index.test.js @@ -3,21 +3,21 @@ import matcher from './'; expect.extend(matcher); describe('.toBeWithin', () => { - test('passes when given number is within the given bounds of start (inclusive) and end (exclusive)', () => { - expect(1).toBeWithin(1, 3); + test('passes when given number is within x percent of the mid number', () => { + expect(55).toBeWithinPercent(50, 10); }); - test('fails when given number is not within the given bounds of start (inclusive) and end (exclusive)', () => { - expect(() => expect(3).toBeWithin(1, 3)).toThrowErrorMatchingSnapshot(); + test('fails when given number is not within x percent of the mid number', () => { + expect(() => expect(56).toBeWithinPercent(50, 10)).toThrowErrorMatchingSnapshot(); }); }); describe('.not.toBeWithin', () => { - test('passes when given number is not within the given bounds of start (inclusive) and end (exclusive)', () => { - expect(3).not.toBeWithin(1, 3); + test('passes when given number is not within x percent of the mid number', () => { + expect(100).not.toBeWithinPercent(20, 5); }); - test('fails when given number is within the given bounds of start (inclusive) and end (exclusive)', () => { - expect(() => expect(1).not.toBeWithin(1, 3)).toThrowErrorMatchingSnapshot(); + test('fails when given number is within x percent of the mid number', () => { + expect(() => expect(25).not.toBeWithinPercent(20, 100)).toThrowErrorMatchingSnapshot(); }); }); diff --git a/src/matchers/toBeWithinPercent/predicate.js b/src/matchers/toBeWithinPercent/predicate.js index 28b22c00..fa6fe418 100644 --- a/src/matchers/toBeWithinPercent/predicate.js +++ b/src/matchers/toBeWithinPercent/predicate.js @@ -1 +1 @@ -export default (number, mid, percent) => number < mid * (1 + percent / 100) && number > mid * (1 - percent / 100); +export default (number, mid, percent) => number <= mid * (1 + percent / 100) && number >= mid * (1 - percent / 100); diff --git a/src/matchers/toBeWithinPercent/predicate.test.js b/src/matchers/toBeWithinPercent/predicate.test.js index d110d4cd..d7ad7001 100644 --- a/src/matchers/toBeWithinPercent/predicate.test.js +++ b/src/matchers/toBeWithinPercent/predicate.test.js @@ -2,10 +2,10 @@ import predicate from './predicate'; describe('toBeWithinPercent Predicate', () => { test('returns true when given number is within percent of mid', () => { - expect(predicate(75, 50, 100)).toBe(true); + expect(predicate(55, 50, 10)).toBe(true); }); test('returns false when given number is not within percent of mid', () => { - expect(predicate(70, 50, 10)).toBe(false); + expect(predicate(60, 50, 10)).toBe(false); }); }); From 15223da4f6bfd06ae963829bc2891b4111ad3dbc Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 09:43:07 +0000 Subject: [PATCH 03/13] Update readme for toBeWithinPercent --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 66d876c9..328b2f29 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,7 @@ If you've come here to help contribute - Thanks! Take a look at the [contributin - [.toBeEven()](#tobeeven) - [.toBeOdd()](#tobeodd) - [.toBeWithin(start, end)](#tobewithinstart-end) + - [.toBeWithinPercent(mid, percent)](#tobewithinpercentmid-percent) - [Object](#object) - [.toBeObject()](#tobeobject) - [.toContainKey(key)](#tocontainkeykey) @@ -599,6 +600,18 @@ test('passes when number is within given bounds', () => { }); ``` +#### .toBeWithinPercent(mid, percent) + +Use `.toBeWithinPercent` when checking if a number is within x percent of a midpoint number. + +```js +test('passes when number is within x percent of mid', () => { + expect(55).toBeWithinPercent(50, 10); + expect(20).toBeWithinPercent(10, 100); + expect(100).not.toBeWithinPercent(10, 5); +}); +``` + ### Object #### .toBeObject() From ec7bb60c4f63e5f74e56306230e428ab7011f3cd Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 09:59:44 +0000 Subject: [PATCH 04/13] Update "mid" to "target" --- README.md | 4 ++-- .../__snapshots__/index.test.js.snap | 18 +++++++------- src/matchers/toBeWithinPercent/index.js | 24 +++++++++---------- src/matchers/toBeWithinPercent/index.test.js | 12 +++++----- src/matchers/toBeWithinPercent/predicate.js | 3 ++- .../toBeWithinPercent/predicate.test.js | 4 ++-- types/index.d.ts | 8 +++++++ 7 files changed, 41 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 328b2f29..f4ccd2e4 100644 --- a/README.md +++ b/README.md @@ -602,10 +602,10 @@ test('passes when number is within given bounds', () => { #### .toBeWithinPercent(mid, percent) -Use `.toBeWithinPercent` when checking if a number is within x percent of a midpoint number. +Use `.toBeWithinPercent` when checking if a number is within x percent of a target number. ```js -test('passes when number is within x percent of mid', () => { +test('passes when number is within x percent of target', () => { expect(55).toBeWithinPercent(50, 10); expect(20).toBeWithinPercent(10, 100); expect(100).not.toBeWithinPercent(10, 5); diff --git a/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap index 289b053b..23da4cd6 100644 --- a/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap +++ b/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap @@ -1,28 +1,28 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`.not.toBeWithinPercent fails when given number is within x percent of the mid number 1`] = ` +exports[`.not.toBeWithinPercent fails when given number is within x percent of the target number 1`] = ` "expect(received).not.toBeWithinPercent(expected) -Expected number to not be within percent of mid: - mid: 20 percent: 100% +Expected number to not be within percent of target: + target: 20 percent: 100% Received: 25" `; -exports[`.not.toBeWithinPercent fails when given number is within x percent of the mid number 20`] = ` +exports[`.not.toBeWithinPercent fails when given number is within x percent of the target number 20`] = ` "expect(received).not.toBeWithinPercent(expected) -Expected number to not be within percent of mid: - mid: 20 percent: 5% +Expected number to not be within percent of target: + target: 20 percent: 5% Received: 100" `; -exports[`.toBeWithinPercent fails when given number is not within x percent of the mid number 1`] = ` +exports[`.toBeWithinPercent fails when given number is not within x percent of the target number 1`] = ` "expect(received).toBeWithinPercent(expected) -Expected number to be within percent of mid: - mid: 20 percent: 100% +Expected number to be within percent of target: + target: 20 percent: 100% Received: 25" `; diff --git a/src/matchers/toBeWithinPercent/index.js b/src/matchers/toBeWithinPercent/index.js index de1db43c..99f6eda9 100644 --- a/src/matchers/toBeWithinPercent/index.js +++ b/src/matchers/toBeWithinPercent/index.js @@ -2,29 +2,29 @@ import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; import predicate from './predicate'; -const passMessage = (number, mid, percent) => () => - matcherHint('.not.toBeWithin') + +const passMessage = (number, target, percent) => () => + matcherHint('.not.toBeWithinPercent') + '\n\n' + - 'Expected number to not be within percent of mid:\n' + - ` mid: ${printExpected(mid)} percent: ${printExpected(percent)}%\n` + + 'Expected number to not be within percent of target:\n' + + ` target: ${printExpected(target)} percent: ${printExpected(percent)}%\n` + 'Received:\n' + ` ${printReceived(number)}`; -const failMessage = (number, mid, percent) => () => - matcherHint('.toBeWithin') + +const failMessage = (number, target, percent) => () => + matcherHint('.toBeWithinPercent') + '\n\n' + - 'Expected number to be within percent of mid:\n' + - ` mid: ${printExpected(mid)} percent: ${printExpected(percent)}%\n` + + 'Expected number to be within percent of target:\n' + + ` target: ${printExpected(target)} percent: ${printExpected(percent)}%\n` + 'Received:\n' + ` ${printReceived(number)}`; export default { - toBeWithinPercent: (number, mid, percent) => { - const pass = predicate(number, mid, percent); + toBeWithinPercent: (number, target, percent) => { + const pass = predicate(number, target, percent); if (pass) { - return { pass: true, message: passMessage(number, mid, percent) }; + return { pass: true, message: passMessage(number, target, percent) }; } - return { pass: false, message: failMessage(number, mid, percent) }; + return { pass: false, message: failMessage(number, target, percent) }; } }; diff --git a/src/matchers/toBeWithinPercent/index.test.js b/src/matchers/toBeWithinPercent/index.test.js index b42233f2..064adcfe 100644 --- a/src/matchers/toBeWithinPercent/index.test.js +++ b/src/matchers/toBeWithinPercent/index.test.js @@ -2,22 +2,22 @@ import matcher from './'; expect.extend(matcher); -describe('.toBeWithin', () => { - test('passes when given number is within x percent of the mid number', () => { +describe('.toBeWithinPercent', () => { + test('passes when given number is within x percent of the target number', () => { expect(55).toBeWithinPercent(50, 10); }); - test('fails when given number is not within x percent of the mid number', () => { + test('fails when given number is not within x percent of the target number', () => { expect(() => expect(56).toBeWithinPercent(50, 10)).toThrowErrorMatchingSnapshot(); }); }); -describe('.not.toBeWithin', () => { - test('passes when given number is not within x percent of the mid number', () => { +describe('.not.toBeWithinPercent', () => { + test('passes when given number is not within x percent of the target number', () => { expect(100).not.toBeWithinPercent(20, 5); }); - test('fails when given number is within x percent of the mid number', () => { + test('fails when given number is within x percent of the target number', () => { expect(() => expect(25).not.toBeWithinPercent(20, 100)).toThrowErrorMatchingSnapshot(); }); }); diff --git a/src/matchers/toBeWithinPercent/predicate.js b/src/matchers/toBeWithinPercent/predicate.js index fa6fe418..d84753ba 100644 --- a/src/matchers/toBeWithinPercent/predicate.js +++ b/src/matchers/toBeWithinPercent/predicate.js @@ -1 +1,2 @@ -export default (number, mid, percent) => number <= mid * (1 + percent / 100) && number >= mid * (1 - percent / 100); +export default (number, target, percent) => + number <= target * (1 + percent / 100) && number >= target * (1 - percent / 100); diff --git a/src/matchers/toBeWithinPercent/predicate.test.js b/src/matchers/toBeWithinPercent/predicate.test.js index d7ad7001..3dcd4311 100644 --- a/src/matchers/toBeWithinPercent/predicate.test.js +++ b/src/matchers/toBeWithinPercent/predicate.test.js @@ -1,11 +1,11 @@ import predicate from './predicate'; describe('toBeWithinPercent Predicate', () => { - test('returns true when given number is within percent of mid', () => { + test('returns true when given number is within percent of target', () => { expect(predicate(55, 50, 10)).toBe(true); }); - test('returns false when given number is not within percent of mid', () => { + test('returns false when given number is not within percent of target', () => { expect(predicate(60, 50, 10)).toBe(false); }); }); diff --git a/types/index.d.ts b/types/index.d.ts index de45f8c2..799fd230 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -186,6 +186,14 @@ declare namespace jest { */ toBeWithin(start: number, end: number): R; + /** + * Use `.toBeWithinPercent` when checking if a number is within x percent of a target number. + * + * @param {Number} target + * @param {Number} percent + */ + toBeWithinPercent(target: number, percent: number): R; + /** * Use `.toBeObject` when checking if a value is an `Object`. */ From 2834a65324e15fdf5196b0fc4f723f9f6160c819 Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 11:14:55 +0000 Subject: [PATCH 05/13] Start making toContainKeyWithinPercent WIP --- .../__snapshots__/index.test.js.snap | 19 +++++++++++ .../toContainKeyWithinPercent/index.js | 30 +++++++++++++++++ .../toContainKeyWithinPercent/index.test.js | 25 ++++++++++++++ .../toContainKeyWithinPercent/predicate.js | 8 +++++ .../predicate.test.js | 33 +++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap create mode 100644 src/matchers/toContainKeyWithinPercent/index.js create mode 100644 src/matchers/toContainKeyWithinPercent/index.test.js create mode 100644 src/matchers/toContainKeyWithinPercent/predicate.js create mode 100644 src/matchers/toContainKeyWithinPercent/predicate.test.js diff --git a/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap new file mode 100644 index 00000000..44d20964 --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toContainKeys fails when object contains all keys 1`] = ` +"expect(received).not.toContainKeys(expected) + +Expected object to not contain all keys: + [\\"a\\", \\"b\\", \\"c\\"] +Received: + {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" +`; + +exports[`.toContainKeys fails when object does not contain all keys 1`] = ` +"expect(received).toContainKeys(expected) + +Expected object to contain all keys: + [\\"a\\", \\"d\\"] +Received: + {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" +`; diff --git a/src/matchers/toContainKeyWithinPercent/index.js b/src/matchers/toContainKeyWithinPercent/index.js new file mode 100644 index 00000000..ba4fa39b --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/index.js @@ -0,0 +1,30 @@ +import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; + +import predicate from './predicate'; + +const passMessage = (actual, expected) => () => + matcherHint('.not.toContainKeys') + + '\n\n' + + 'Expected object to not contain all keys:\n' + + ` ${printExpected(expected)}\n` + + 'Received:\n' + + ` ${printReceived(actual)}`; + +const failMessage = (actual, expected) => () => + matcherHint('.toContainKeys') + + '\n\n' + + 'Expected object to contain all keys:\n' + + ` ${printExpected(expected)}\n` + + 'Received:\n' + + ` ${printReceived(actual)}`; + +export default { + toContainKeys: (actual, expected) => { + const pass = predicate(actual, expected); + if (pass) { + return { pass: true, message: passMessage(actual, expected) }; + } + + return { pass: false, message: failMessage(actual, expected) }; + } +}; diff --git a/src/matchers/toContainKeyWithinPercent/index.test.js b/src/matchers/toContainKeyWithinPercent/index.test.js new file mode 100644 index 00000000..e2b5c16e --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/index.test.js @@ -0,0 +1,25 @@ +import matcher from './'; + +expect.extend(matcher); + +const data = { a: 'foo', b: 'bar', c: 'baz' }; + +describe('.toContainKeys', () => { + test('passes when object contains all keys', () => { + expect(data).toContainKeys(['b', 'c']); + }); + + test('fails when object does not contain all keys', () => { + expect(() => expect(data).toContainKeys(['a', 'd'])).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toContainKeys', () => { + test('passes when object does not contain all keys', () => { + expect(data).not.toContainKeys(['d']); + }); + + test('fails when object contains all keys', () => { + expect(() => expect(data).not.toContainKeys(['a', 'b', 'c'])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/matchers/toContainKeyWithinPercent/predicate.js b/src/matchers/toContainKeyWithinPercent/predicate.js new file mode 100644 index 00000000..e95f7af6 --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/predicate.js @@ -0,0 +1,8 @@ +export default (valueObj, keys) => + keys.every(keyObj => { + return ( + valueObj[keyObj.key] && + valueObj[keyObj.key] <= keyObj.target * (1 + keyObj.percent / 100) && + valueObj[keyObj.key] >= keyObj.target * (1 - keyObj.percent / 100) + ); + }); diff --git a/src/matchers/toContainKeyWithinPercent/predicate.test.js b/src/matchers/toContainKeyWithinPercent/predicate.test.js new file mode 100644 index 00000000..49701863 --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/predicate.test.js @@ -0,0 +1,33 @@ +import predicate from './predicate'; + +const data1 = { a: 55, b: 5, c: 1 }; + +const data2 = { a: 55, b: 6, c: 1 }; + +const keys = [ + { + key: 'a', + target: 50, + percent: 10 + }, + { + key: 'b', + target: 5, + percent: 0 + }, + { + key: 'c', + target: 1, + percent: 100 + } +]; + +describe('.toContainKeys', () => { + test('passes when object contains all keys and they are within x percent of target', () => { + expect(predicate(data1, keys)).toBe(true); + }); + + test('fails when object does not contain all keys or they are not within x percent of target', () => { + expect(predicate(data2, keys)).toBe(false); + }); +}); From aca105d8b4e082d95c411e9328b26eb559b12ee3 Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 12:13:49 +0000 Subject: [PATCH 06/13] Create toContainKeysWithinPercent --- README.md | 19 ++++++++ .../__snapshots__/index.test.js.snap | 19 -------- .../toContainKeyWithinPercent/index.js | 30 ------------- .../toContainKeyWithinPercent/index.test.js | 25 ----------- .../__snapshots__/index.test.js.snap | 39 +++++++++++++++++ .../toContainKeysWithinPercent/index.js | 30 +++++++++++++ .../toContainKeysWithinPercent/index.test.js | 43 +++++++++++++++++++ .../predicate.js | 0 .../predicate.test.js | 5 +-- types/index.d.ts | 7 +++ 10 files changed, 140 insertions(+), 77 deletions(-) delete mode 100644 src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap delete mode 100644 src/matchers/toContainKeyWithinPercent/index.js delete mode 100644 src/matchers/toContainKeyWithinPercent/index.test.js create mode 100644 src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap create mode 100644 src/matchers/toContainKeysWithinPercent/index.js create mode 100644 src/matchers/toContainKeysWithinPercent/index.test.js rename src/matchers/{toContainKeyWithinPercent => toContainKeysWithinPercent}/predicate.js (100%) rename src/matchers/{toContainKeyWithinPercent => toContainKeysWithinPercent}/predicate.test.js (87%) diff --git a/README.md b/README.md index f4ccd2e4..c84a86ca 100644 --- a/README.md +++ b/README.md @@ -653,6 +653,25 @@ test('passes when object contains all keys', () => { }); ``` +#### .toContainKeysWithinPercent([keyObjects]) + +Use `.toContainKeysWithinPercent` when checking if an object has all of the provided keys and that the value of these keys is within x percent of a target value. + +```js +test('passes when object contains all keys', () => { + const data1 = { a: 55, b: 1 }; + const data2 = { a: 45, b: 1 } + const data3 = { a: 20, b: 2 } + const data4 = { a: 50 } + const keys = [{key: "a", target: 50, percent: 10}, {key: "b", target: 1, percent: 0}] + + expect(data1).toContainKeysWithinPercent(keys); + expect(data2).toContainKeysWithinPercent(keys); + expect(data3).not.toContainKeysWithinPercent(keys); + expect(data4).not.toContainKeysWithinPercent(keys); +}); +``` + #### .toContainAllKeys([keys]) Use `.toContainAllKeys` when checking if an object only contains all of the provided keys. diff --git a/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap deleted file mode 100644 index 44d20964..00000000 --- a/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`.not.toContainKeys fails when object contains all keys 1`] = ` -"expect(received).not.toContainKeys(expected) - -Expected object to not contain all keys: - [\\"a\\", \\"b\\", \\"c\\"] -Received: - {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" -`; - -exports[`.toContainKeys fails when object does not contain all keys 1`] = ` -"expect(received).toContainKeys(expected) - -Expected object to contain all keys: - [\\"a\\", \\"d\\"] -Received: - {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" -`; diff --git a/src/matchers/toContainKeyWithinPercent/index.js b/src/matchers/toContainKeyWithinPercent/index.js deleted file mode 100644 index ba4fa39b..00000000 --- a/src/matchers/toContainKeyWithinPercent/index.js +++ /dev/null @@ -1,30 +0,0 @@ -import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; - -import predicate from './predicate'; - -const passMessage = (actual, expected) => () => - matcherHint('.not.toContainKeys') + - '\n\n' + - 'Expected object to not contain all keys:\n' + - ` ${printExpected(expected)}\n` + - 'Received:\n' + - ` ${printReceived(actual)}`; - -const failMessage = (actual, expected) => () => - matcherHint('.toContainKeys') + - '\n\n' + - 'Expected object to contain all keys:\n' + - ` ${printExpected(expected)}\n` + - 'Received:\n' + - ` ${printReceived(actual)}`; - -export default { - toContainKeys: (actual, expected) => { - const pass = predicate(actual, expected); - if (pass) { - return { pass: true, message: passMessage(actual, expected) }; - } - - return { pass: false, message: failMessage(actual, expected) }; - } -}; diff --git a/src/matchers/toContainKeyWithinPercent/index.test.js b/src/matchers/toContainKeyWithinPercent/index.test.js deleted file mode 100644 index e2b5c16e..00000000 --- a/src/matchers/toContainKeyWithinPercent/index.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import matcher from './'; - -expect.extend(matcher); - -const data = { a: 'foo', b: 'bar', c: 'baz' }; - -describe('.toContainKeys', () => { - test('passes when object contains all keys', () => { - expect(data).toContainKeys(['b', 'c']); - }); - - test('fails when object does not contain all keys', () => { - expect(() => expect(data).toContainKeys(['a', 'd'])).toThrowErrorMatchingSnapshot(); - }); -}); - -describe('.not.toContainKeys', () => { - test('passes when object does not contain all keys', () => { - expect(data).not.toContainKeys(['d']); - }); - - test('fails when object contains all keys', () => { - expect(() => expect(data).not.toContainKeys(['a', 'b', 'c'])).toThrowErrorMatchingSnapshot(); - }); -}); diff --git a/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap new file mode 100644 index 00000000..bfb11247 --- /dev/null +++ b/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toContainKeys fails when object contains all keys and they are within x percent of target 1`] = ` +"expect(received).not.toContainKeysWithinPercent(expected) + +Expected object to not contain all keys or the keys' values to not be within x percent of target: + [{\\"key\\": \\"a\\", \\"percent\\": 10, \\"target\\": 50}, {\\"key\\": \\"b\\", \\"percent\\": 0, \\"target\\": 5}, {\\"key\\": \\"c\\", \\"percent\\": 100, \\"target\\": 1}] +Received: + {\\"a\\": 55, \\"b\\": 5, \\"c\\": 1}" +`; + +exports[`.not.toContainKeysWithinPercent fails when object contains all keys 1`] = ` +"expect(received).not.toContainKeysWithinPercent(expected) + +Expected object to contain all keys and the keys' values to be within x percent of target: + [\\"a\\", \\"b\\", \\"c\\"] +Received: + {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" +`; + +exports[`.not.toContainKeysWithinPercent fails when object contains all keys and they are within x percent of target 1`] = ` +"expect(received).not.toContainKeysWithinPercent(expected) + +Expected object to not contain all keys or the keys' values to not be within x percent of target: + [{\\"key\\": \\"a\\", \\"percent\\": 10, \\"target\\": 50}, {\\"key\\": \\"b\\", \\"percent\\": 0, \\"target\\": 5}, {\\"key\\": \\"c\\", \\"percent\\": 100, \\"target\\": 1}] +Received: + {\\"a\\": 55, \\"b\\": 5, \\"c\\": 1}" +`; + +exports[`.toContainKeys fails when object does not contain all keys or they are not within x percent of target 1`] = ` +"expect(received).toContainKeysWithinPercent(expected) + +Expected object to contain all keys and the keys' values to be within x percent of target: + [{\\"key\\": \\"a\\", \\"percent\\": 10, \\"target\\": 50}, {\\"key\\": \\"b\\", \\"percent\\": 0, \\"target\\": 5}, {\\"key\\": \\"c\\", \\"percent\\": 100, \\"target\\": 1}] +Received: + {\\"a\\": 56, \\"b\\": 5, \\"c\\": 1}" +`; + +exports[`.toContainKeysWithinPercent fails when object does not contain all keys or they are not within x percent of target 1`] = `"expect(...).toContainKeyWithinPercent is not a function"`; diff --git a/src/matchers/toContainKeysWithinPercent/index.js b/src/matchers/toContainKeysWithinPercent/index.js new file mode 100644 index 00000000..089845bc --- /dev/null +++ b/src/matchers/toContainKeysWithinPercent/index.js @@ -0,0 +1,30 @@ +import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; + +import predicate from './predicate'; + +const passMessage = (valueObj, keysArray) => () => + matcherHint('.not.toContainKeysWithinPercent') + + '\n\n' + + "Expected object to not contain all keys or the keys' values to not be within x percent of target:\n" + + ` ${printExpected(keysArray)}\n` + + 'Received:\n' + + ` ${printReceived(valueObj)}`; + +const failMessage = (valueObj, keysArray) => () => + matcherHint('.toContainKeysWithinPercent') + + '\n\n' + + "Expected object to contain all keys and the keys' values to be within x percent of target:\n" + + ` ${printExpected(keysArray)}\n` + + 'Received:\n' + + ` ${printReceived(valueObj)}`; + +export default { + toContainKeysWithinPercent: (valueObj, keysArray) => { + const pass = predicate(valueObj, keysArray); + if (pass) { + return { pass: true, message: passMessage(valueObj, keysArray) }; + } + + return { pass: false, message: failMessage(valueObj, keysArray) }; + } +}; diff --git a/src/matchers/toContainKeysWithinPercent/index.test.js b/src/matchers/toContainKeysWithinPercent/index.test.js new file mode 100644 index 00000000..8023414f --- /dev/null +++ b/src/matchers/toContainKeysWithinPercent/index.test.js @@ -0,0 +1,43 @@ +import matcher from './'; + +expect.extend(matcher); + +const data1 = { a: 55, b: 5, c: 1 }; +const data2 = { a: 56, b: 5, c: 1 }; + +const keys = [ + { + key: 'a', + target: 50, + percent: 10 + }, + { + key: 'b', + target: 5, + percent: 0 + }, + { + key: 'c', + target: 1, + percent: 100 + } +]; +describe('.toContainKeys', () => { + test('passes when object contains all keys and they are within x percent of target', () => { + expect(data1).toContainKeysWithinPercent(keys); + }); + + test('fails when object does not contain all keys or they are not within x percent of target', () => { + expect(() => expect(data2).toContainKeysWithinPercent(keys)).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toContainKeys', () => { + test('passes when object does not contain all keys or they are not within x percent of target', () => { + expect(data2).not.toContainKeysWithinPercent(keys); + }); + + test('fails when object contains all keys and they are within x percent of target', () => { + expect(() => expect(data1).not.toContainKeysWithinPercent(keys)).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/matchers/toContainKeyWithinPercent/predicate.js b/src/matchers/toContainKeysWithinPercent/predicate.js similarity index 100% rename from src/matchers/toContainKeyWithinPercent/predicate.js rename to src/matchers/toContainKeysWithinPercent/predicate.js diff --git a/src/matchers/toContainKeyWithinPercent/predicate.test.js b/src/matchers/toContainKeysWithinPercent/predicate.test.js similarity index 87% rename from src/matchers/toContainKeyWithinPercent/predicate.test.js rename to src/matchers/toContainKeysWithinPercent/predicate.test.js index 49701863..9e43a697 100644 --- a/src/matchers/toContainKeyWithinPercent/predicate.test.js +++ b/src/matchers/toContainKeysWithinPercent/predicate.test.js @@ -1,8 +1,7 @@ import predicate from './predicate'; const data1 = { a: 55, b: 5, c: 1 }; - -const data2 = { a: 55, b: 6, c: 1 }; +const data2 = { a: 56, b: 5, c: 1 }; const keys = [ { @@ -22,7 +21,7 @@ const keys = [ } ]; -describe('.toContainKeys', () => { +describe('.toContainKeysWithinPercent', () => { test('passes when object contains all keys and they are within x percent of target', () => { expect(predicate(data1, keys)).toBe(true); }); diff --git a/types/index.d.ts b/types/index.d.ts index 799fd230..9e600656 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -213,6 +213,13 @@ declare namespace jest { */ toContainKeys(keys: string[]): R; + /** + * Use `.toContainKeysWithinPercent` when checking if an object has all of the provided keys. + * + * @param {Array.} keyObjects + */ + toContainKeysWithinPercent(keys: object[]): R; + /** * Use `.toContainAllKeys` when checking if an object only contains all of the provided keys. * From 4c511b6c5e6f769aa0fd8ecfde263ea1d4c69a9b Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 12:30:28 +0000 Subject: [PATCH 07/13] Update snapshot --- .../__snapshots__/index.test.js.snap | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap index 23da4cd6..dd51e61d 100644 --- a/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap +++ b/src/matchers/toBeWithinPercent/__snapshots__/index.test.js.snap @@ -6,13 +6,22 @@ exports[`.not.toBeWithinPercent fails when given number is within x percent of t Expected number to not be within percent of target: target: 20 percent: 100% Received: - 25" + 55" `; -exports[`.not.toBeWithinPercent fails when given number is within x percent of the target number 20`] = ` +exports[`.not.toBeWithinPercent fails when given number is within x percent of the target number 1`] = ` "expect(received).not.toBeWithinPercent(expected) Expected number to not be within percent of target: + target: 20 percent: 100% +Received: + 25" +`; + +exports[`.toBeWithinPercent fails when given number is not within x percent of the target number 1`] = ` +"expect(received).toBeWithinPercent(expected) + +Expected number to be within percent of target: target: 20 percent: 5% Received: 100" @@ -22,7 +31,7 @@ exports[`.toBeWithinPercent fails when given number is not within x percent of t "expect(received).toBeWithinPercent(expected) Expected number to be within percent of target: - target: 20 percent: 100% + target: 50 percent: 10% Received: - 25" + 56" `; From 72b9f84955a391abab5dfc86899b34c13e9c161c Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 11:14:55 +0000 Subject: [PATCH 08/13] Start making toContainKeyWithinPercent WIP --- .../__snapshots__/index.test.js.snap | 19 +++++++++++ .../toContainKeyWithinPercent/index.js | 30 +++++++++++++++++ .../toContainKeyWithinPercent/index.test.js | 25 ++++++++++++++ .../toContainKeyWithinPercent/predicate.js | 8 +++++ .../predicate.test.js | 33 +++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap create mode 100644 src/matchers/toContainKeyWithinPercent/index.js create mode 100644 src/matchers/toContainKeyWithinPercent/index.test.js create mode 100644 src/matchers/toContainKeyWithinPercent/predicate.js create mode 100644 src/matchers/toContainKeyWithinPercent/predicate.test.js diff --git a/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap new file mode 100644 index 00000000..44d20964 --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toContainKeys fails when object contains all keys 1`] = ` +"expect(received).not.toContainKeys(expected) + +Expected object to not contain all keys: + [\\"a\\", \\"b\\", \\"c\\"] +Received: + {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" +`; + +exports[`.toContainKeys fails when object does not contain all keys 1`] = ` +"expect(received).toContainKeys(expected) + +Expected object to contain all keys: + [\\"a\\", \\"d\\"] +Received: + {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" +`; diff --git a/src/matchers/toContainKeyWithinPercent/index.js b/src/matchers/toContainKeyWithinPercent/index.js new file mode 100644 index 00000000..ba4fa39b --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/index.js @@ -0,0 +1,30 @@ +import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; + +import predicate from './predicate'; + +const passMessage = (actual, expected) => () => + matcherHint('.not.toContainKeys') + + '\n\n' + + 'Expected object to not contain all keys:\n' + + ` ${printExpected(expected)}\n` + + 'Received:\n' + + ` ${printReceived(actual)}`; + +const failMessage = (actual, expected) => () => + matcherHint('.toContainKeys') + + '\n\n' + + 'Expected object to contain all keys:\n' + + ` ${printExpected(expected)}\n` + + 'Received:\n' + + ` ${printReceived(actual)}`; + +export default { + toContainKeys: (actual, expected) => { + const pass = predicate(actual, expected); + if (pass) { + return { pass: true, message: passMessage(actual, expected) }; + } + + return { pass: false, message: failMessage(actual, expected) }; + } +}; diff --git a/src/matchers/toContainKeyWithinPercent/index.test.js b/src/matchers/toContainKeyWithinPercent/index.test.js new file mode 100644 index 00000000..e2b5c16e --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/index.test.js @@ -0,0 +1,25 @@ +import matcher from './'; + +expect.extend(matcher); + +const data = { a: 'foo', b: 'bar', c: 'baz' }; + +describe('.toContainKeys', () => { + test('passes when object contains all keys', () => { + expect(data).toContainKeys(['b', 'c']); + }); + + test('fails when object does not contain all keys', () => { + expect(() => expect(data).toContainKeys(['a', 'd'])).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toContainKeys', () => { + test('passes when object does not contain all keys', () => { + expect(data).not.toContainKeys(['d']); + }); + + test('fails when object contains all keys', () => { + expect(() => expect(data).not.toContainKeys(['a', 'b', 'c'])).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/matchers/toContainKeyWithinPercent/predicate.js b/src/matchers/toContainKeyWithinPercent/predicate.js new file mode 100644 index 00000000..e95f7af6 --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/predicate.js @@ -0,0 +1,8 @@ +export default (valueObj, keys) => + keys.every(keyObj => { + return ( + valueObj[keyObj.key] && + valueObj[keyObj.key] <= keyObj.target * (1 + keyObj.percent / 100) && + valueObj[keyObj.key] >= keyObj.target * (1 - keyObj.percent / 100) + ); + }); diff --git a/src/matchers/toContainKeyWithinPercent/predicate.test.js b/src/matchers/toContainKeyWithinPercent/predicate.test.js new file mode 100644 index 00000000..49701863 --- /dev/null +++ b/src/matchers/toContainKeyWithinPercent/predicate.test.js @@ -0,0 +1,33 @@ +import predicate from './predicate'; + +const data1 = { a: 55, b: 5, c: 1 }; + +const data2 = { a: 55, b: 6, c: 1 }; + +const keys = [ + { + key: 'a', + target: 50, + percent: 10 + }, + { + key: 'b', + target: 5, + percent: 0 + }, + { + key: 'c', + target: 1, + percent: 100 + } +]; + +describe('.toContainKeys', () => { + test('passes when object contains all keys and they are within x percent of target', () => { + expect(predicate(data1, keys)).toBe(true); + }); + + test('fails when object does not contain all keys or they are not within x percent of target', () => { + expect(predicate(data2, keys)).toBe(false); + }); +}); From 0e5ac708c09255a2c98ecd20dc7e5ead1cbede14 Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 12:13:49 +0000 Subject: [PATCH 09/13] Create toContainKeysWithinPercent --- README.md | 19 ++++++++ .../__snapshots__/index.test.js.snap | 19 -------- .../toContainKeyWithinPercent/index.js | 30 ------------- .../toContainKeyWithinPercent/index.test.js | 25 ----------- .../__snapshots__/index.test.js.snap | 39 +++++++++++++++++ .../toContainKeysWithinPercent/index.js | 30 +++++++++++++ .../toContainKeysWithinPercent/index.test.js | 43 +++++++++++++++++++ .../predicate.js | 0 .../predicate.test.js | 5 +-- types/index.d.ts | 7 +++ 10 files changed, 140 insertions(+), 77 deletions(-) delete mode 100644 src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap delete mode 100644 src/matchers/toContainKeyWithinPercent/index.js delete mode 100644 src/matchers/toContainKeyWithinPercent/index.test.js create mode 100644 src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap create mode 100644 src/matchers/toContainKeysWithinPercent/index.js create mode 100644 src/matchers/toContainKeysWithinPercent/index.test.js rename src/matchers/{toContainKeyWithinPercent => toContainKeysWithinPercent}/predicate.js (100%) rename src/matchers/{toContainKeyWithinPercent => toContainKeysWithinPercent}/predicate.test.js (87%) diff --git a/README.md b/README.md index f4ccd2e4..c84a86ca 100644 --- a/README.md +++ b/README.md @@ -653,6 +653,25 @@ test('passes when object contains all keys', () => { }); ``` +#### .toContainKeysWithinPercent([keyObjects]) + +Use `.toContainKeysWithinPercent` when checking if an object has all of the provided keys and that the value of these keys is within x percent of a target value. + +```js +test('passes when object contains all keys', () => { + const data1 = { a: 55, b: 1 }; + const data2 = { a: 45, b: 1 } + const data3 = { a: 20, b: 2 } + const data4 = { a: 50 } + const keys = [{key: "a", target: 50, percent: 10}, {key: "b", target: 1, percent: 0}] + + expect(data1).toContainKeysWithinPercent(keys); + expect(data2).toContainKeysWithinPercent(keys); + expect(data3).not.toContainKeysWithinPercent(keys); + expect(data4).not.toContainKeysWithinPercent(keys); +}); +``` + #### .toContainAllKeys([keys]) Use `.toContainAllKeys` when checking if an object only contains all of the provided keys. diff --git a/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap deleted file mode 100644 index 44d20964..00000000 --- a/src/matchers/toContainKeyWithinPercent/__snapshots__/index.test.js.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`.not.toContainKeys fails when object contains all keys 1`] = ` -"expect(received).not.toContainKeys(expected) - -Expected object to not contain all keys: - [\\"a\\", \\"b\\", \\"c\\"] -Received: - {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" -`; - -exports[`.toContainKeys fails when object does not contain all keys 1`] = ` -"expect(received).toContainKeys(expected) - -Expected object to contain all keys: - [\\"a\\", \\"d\\"] -Received: - {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" -`; diff --git a/src/matchers/toContainKeyWithinPercent/index.js b/src/matchers/toContainKeyWithinPercent/index.js deleted file mode 100644 index ba4fa39b..00000000 --- a/src/matchers/toContainKeyWithinPercent/index.js +++ /dev/null @@ -1,30 +0,0 @@ -import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; - -import predicate from './predicate'; - -const passMessage = (actual, expected) => () => - matcherHint('.not.toContainKeys') + - '\n\n' + - 'Expected object to not contain all keys:\n' + - ` ${printExpected(expected)}\n` + - 'Received:\n' + - ` ${printReceived(actual)}`; - -const failMessage = (actual, expected) => () => - matcherHint('.toContainKeys') + - '\n\n' + - 'Expected object to contain all keys:\n' + - ` ${printExpected(expected)}\n` + - 'Received:\n' + - ` ${printReceived(actual)}`; - -export default { - toContainKeys: (actual, expected) => { - const pass = predicate(actual, expected); - if (pass) { - return { pass: true, message: passMessage(actual, expected) }; - } - - return { pass: false, message: failMessage(actual, expected) }; - } -}; diff --git a/src/matchers/toContainKeyWithinPercent/index.test.js b/src/matchers/toContainKeyWithinPercent/index.test.js deleted file mode 100644 index e2b5c16e..00000000 --- a/src/matchers/toContainKeyWithinPercent/index.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import matcher from './'; - -expect.extend(matcher); - -const data = { a: 'foo', b: 'bar', c: 'baz' }; - -describe('.toContainKeys', () => { - test('passes when object contains all keys', () => { - expect(data).toContainKeys(['b', 'c']); - }); - - test('fails when object does not contain all keys', () => { - expect(() => expect(data).toContainKeys(['a', 'd'])).toThrowErrorMatchingSnapshot(); - }); -}); - -describe('.not.toContainKeys', () => { - test('passes when object does not contain all keys', () => { - expect(data).not.toContainKeys(['d']); - }); - - test('fails when object contains all keys', () => { - expect(() => expect(data).not.toContainKeys(['a', 'b', 'c'])).toThrowErrorMatchingSnapshot(); - }); -}); diff --git a/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap new file mode 100644 index 00000000..bfb11247 --- /dev/null +++ b/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toContainKeys fails when object contains all keys and they are within x percent of target 1`] = ` +"expect(received).not.toContainKeysWithinPercent(expected) + +Expected object to not contain all keys or the keys' values to not be within x percent of target: + [{\\"key\\": \\"a\\", \\"percent\\": 10, \\"target\\": 50}, {\\"key\\": \\"b\\", \\"percent\\": 0, \\"target\\": 5}, {\\"key\\": \\"c\\", \\"percent\\": 100, \\"target\\": 1}] +Received: + {\\"a\\": 55, \\"b\\": 5, \\"c\\": 1}" +`; + +exports[`.not.toContainKeysWithinPercent fails when object contains all keys 1`] = ` +"expect(received).not.toContainKeysWithinPercent(expected) + +Expected object to contain all keys and the keys' values to be within x percent of target: + [\\"a\\", \\"b\\", \\"c\\"] +Received: + {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" +`; + +exports[`.not.toContainKeysWithinPercent fails when object contains all keys and they are within x percent of target 1`] = ` +"expect(received).not.toContainKeysWithinPercent(expected) + +Expected object to not contain all keys or the keys' values to not be within x percent of target: + [{\\"key\\": \\"a\\", \\"percent\\": 10, \\"target\\": 50}, {\\"key\\": \\"b\\", \\"percent\\": 0, \\"target\\": 5}, {\\"key\\": \\"c\\", \\"percent\\": 100, \\"target\\": 1}] +Received: + {\\"a\\": 55, \\"b\\": 5, \\"c\\": 1}" +`; + +exports[`.toContainKeys fails when object does not contain all keys or they are not within x percent of target 1`] = ` +"expect(received).toContainKeysWithinPercent(expected) + +Expected object to contain all keys and the keys' values to be within x percent of target: + [{\\"key\\": \\"a\\", \\"percent\\": 10, \\"target\\": 50}, {\\"key\\": \\"b\\", \\"percent\\": 0, \\"target\\": 5}, {\\"key\\": \\"c\\", \\"percent\\": 100, \\"target\\": 1}] +Received: + {\\"a\\": 56, \\"b\\": 5, \\"c\\": 1}" +`; + +exports[`.toContainKeysWithinPercent fails when object does not contain all keys or they are not within x percent of target 1`] = `"expect(...).toContainKeyWithinPercent is not a function"`; diff --git a/src/matchers/toContainKeysWithinPercent/index.js b/src/matchers/toContainKeysWithinPercent/index.js new file mode 100644 index 00000000..089845bc --- /dev/null +++ b/src/matchers/toContainKeysWithinPercent/index.js @@ -0,0 +1,30 @@ +import { matcherHint, printExpected, printReceived } from 'jest-matcher-utils'; + +import predicate from './predicate'; + +const passMessage = (valueObj, keysArray) => () => + matcherHint('.not.toContainKeysWithinPercent') + + '\n\n' + + "Expected object to not contain all keys or the keys' values to not be within x percent of target:\n" + + ` ${printExpected(keysArray)}\n` + + 'Received:\n' + + ` ${printReceived(valueObj)}`; + +const failMessage = (valueObj, keysArray) => () => + matcherHint('.toContainKeysWithinPercent') + + '\n\n' + + "Expected object to contain all keys and the keys' values to be within x percent of target:\n" + + ` ${printExpected(keysArray)}\n` + + 'Received:\n' + + ` ${printReceived(valueObj)}`; + +export default { + toContainKeysWithinPercent: (valueObj, keysArray) => { + const pass = predicate(valueObj, keysArray); + if (pass) { + return { pass: true, message: passMessage(valueObj, keysArray) }; + } + + return { pass: false, message: failMessage(valueObj, keysArray) }; + } +}; diff --git a/src/matchers/toContainKeysWithinPercent/index.test.js b/src/matchers/toContainKeysWithinPercent/index.test.js new file mode 100644 index 00000000..8023414f --- /dev/null +++ b/src/matchers/toContainKeysWithinPercent/index.test.js @@ -0,0 +1,43 @@ +import matcher from './'; + +expect.extend(matcher); + +const data1 = { a: 55, b: 5, c: 1 }; +const data2 = { a: 56, b: 5, c: 1 }; + +const keys = [ + { + key: 'a', + target: 50, + percent: 10 + }, + { + key: 'b', + target: 5, + percent: 0 + }, + { + key: 'c', + target: 1, + percent: 100 + } +]; +describe('.toContainKeys', () => { + test('passes when object contains all keys and they are within x percent of target', () => { + expect(data1).toContainKeysWithinPercent(keys); + }); + + test('fails when object does not contain all keys or they are not within x percent of target', () => { + expect(() => expect(data2).toContainKeysWithinPercent(keys)).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toContainKeys', () => { + test('passes when object does not contain all keys or they are not within x percent of target', () => { + expect(data2).not.toContainKeysWithinPercent(keys); + }); + + test('fails when object contains all keys and they are within x percent of target', () => { + expect(() => expect(data1).not.toContainKeysWithinPercent(keys)).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/matchers/toContainKeyWithinPercent/predicate.js b/src/matchers/toContainKeysWithinPercent/predicate.js similarity index 100% rename from src/matchers/toContainKeyWithinPercent/predicate.js rename to src/matchers/toContainKeysWithinPercent/predicate.js diff --git a/src/matchers/toContainKeyWithinPercent/predicate.test.js b/src/matchers/toContainKeysWithinPercent/predicate.test.js similarity index 87% rename from src/matchers/toContainKeyWithinPercent/predicate.test.js rename to src/matchers/toContainKeysWithinPercent/predicate.test.js index 49701863..9e43a697 100644 --- a/src/matchers/toContainKeyWithinPercent/predicate.test.js +++ b/src/matchers/toContainKeysWithinPercent/predicate.test.js @@ -1,8 +1,7 @@ import predicate from './predicate'; const data1 = { a: 55, b: 5, c: 1 }; - -const data2 = { a: 55, b: 6, c: 1 }; +const data2 = { a: 56, b: 5, c: 1 }; const keys = [ { @@ -22,7 +21,7 @@ const keys = [ } ]; -describe('.toContainKeys', () => { +describe('.toContainKeysWithinPercent', () => { test('passes when object contains all keys and they are within x percent of target', () => { expect(predicate(data1, keys)).toBe(true); }); diff --git a/types/index.d.ts b/types/index.d.ts index 799fd230..9e600656 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -213,6 +213,13 @@ declare namespace jest { */ toContainKeys(keys: string[]): R; + /** + * Use `.toContainKeysWithinPercent` when checking if an object has all of the provided keys. + * + * @param {Array.} keyObjects + */ + toContainKeysWithinPercent(keys: object[]): R; + /** * Use `.toContainAllKeys` when checking if an object only contains all of the provided keys. * From 97de10e7cf4e092133b1ee9eacc67385fec4957e Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 12:40:22 +0000 Subject: [PATCH 10/13] update comment in types --- types/index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index 9e600656..62534d75 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -221,7 +221,7 @@ declare namespace jest { toContainKeysWithinPercent(keys: object[]): R; /** - * Use `.toContainAllKeys` when checking if an object only contains all of the provided keys. + * Use `.toContainAllKeys` when checking if an object only contains all of the provided keys and these keys' values are within x percent of a target value. * * @param {Array.} keys */ From 61d19636f2b21ba8794597bfcf6400c084b5afd8 Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 12:43:02 +0000 Subject: [PATCH 11/13] updated types --- types/index.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/types/index.d.ts b/types/index.d.ts index 799fd230..c4668019 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -569,6 +569,13 @@ declare namespace jest { */ toContainKeys(keys: string[]): any; + /** + * Use `.toContainKeysWithinPercent` when checking if an object has all of the provided keys and the keys' values are within x percent of a target value. + * + * @param {Array.} keyObjects + */ + toContainKeysWithinPercent(keyObjects: object[]): any; + /** * Use `.toContainAllKeys` when checking if an object only contains all of the provided keys. * From 712e70193027c0b2725b5bb79901fab5a60cce81 Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 14:21:50 +0000 Subject: [PATCH 12/13] ran --fix From 7bdf74f052116411886baf2204f6ba1f1ac5b3ed Mon Sep 17 00:00:00 2001 From: scottdykes1611 Date: Wed, 11 Nov 2020 15:11:19 +0000 Subject: [PATCH 13/13] Remove obsolete snapshots --- .../__snapshots__/index.test.js.snap | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap b/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap index bfb11247..7b8b6b1e 100644 --- a/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap +++ b/src/matchers/toContainKeysWithinPercent/__snapshots__/index.test.js.snap @@ -9,24 +9,6 @@ Received: {\\"a\\": 55, \\"b\\": 5, \\"c\\": 1}" `; -exports[`.not.toContainKeysWithinPercent fails when object contains all keys 1`] = ` -"expect(received).not.toContainKeysWithinPercent(expected) - -Expected object to contain all keys and the keys' values to be within x percent of target: - [\\"a\\", \\"b\\", \\"c\\"] -Received: - {\\"a\\": \\"foo\\", \\"b\\": \\"bar\\", \\"c\\": \\"baz\\"}" -`; - -exports[`.not.toContainKeysWithinPercent fails when object contains all keys and they are within x percent of target 1`] = ` -"expect(received).not.toContainKeysWithinPercent(expected) - -Expected object to not contain all keys or the keys' values to not be within x percent of target: - [{\\"key\\": \\"a\\", \\"percent\\": 10, \\"target\\": 50}, {\\"key\\": \\"b\\", \\"percent\\": 0, \\"target\\": 5}, {\\"key\\": \\"c\\", \\"percent\\": 100, \\"target\\": 1}] -Received: - {\\"a\\": 55, \\"b\\": 5, \\"c\\": 1}" -`; - exports[`.toContainKeys fails when object does not contain all keys or they are not within x percent of target 1`] = ` "expect(received).toContainKeysWithinPercent(expected) @@ -35,5 +17,3 @@ Expected object to contain all keys and the keys' values to be within x percent Received: {\\"a\\": 56, \\"b\\": 5, \\"c\\": 1}" `; - -exports[`.toContainKeysWithinPercent fails when object does not contain all keys or they are not within x percent of target 1`] = `"expect(...).toContainKeyWithinPercent is not a function"`;