From 35812e32abdd5239876d1b9b39ebd07825772c3f Mon Sep 17 00:00:00 2001 From: Hansal Bachkaniwala Date: Wed, 6 Oct 2021 07:31:57 -0400 Subject: [PATCH] feat: add a '.toBeEmptyObject()' custom matcher. (#255) --- README.md | 12 +++++++++ .../__snapshots__/index.test.js.snap | 15 +++++++++++ src/matchers/toBeEmptyObject/index.js | 26 +++++++++++++++++++ src/matchers/toBeEmptyObject/index.test.js | 23 ++++++++++++++++ src/matchers/toBeEmptyObject/predicate.js | 3 +++ .../toBeEmptyObject/predicate.test.js | 11 ++++++++ types/index.d.ts | 5 ++++ 7 files changed, 95 insertions(+) create mode 100644 src/matchers/toBeEmptyObject/__snapshots__/index.test.js.snap create mode 100644 src/matchers/toBeEmptyObject/index.js create mode 100644 src/matchers/toBeEmptyObject/index.test.js create mode 100644 src/matchers/toBeEmptyObject/predicate.js create mode 100644 src/matchers/toBeEmptyObject/predicate.test.js diff --git a/README.md b/README.md index 630bbf75..8a869024 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ If you've come here to help contribute - Thanks! Take a look at the [contributin - [.toBeInteger()](#tobeinteger) - [Object](#object) - [.toBeObject()](#tobeobject) + - [.toBeEmptyObject()](#tobeemptyobject) - [.toContainKey(key)](#tocontainkeykey) - [.toContainKeys([keys])](#tocontainkeyskeys) - [.toContainAllKeys([keys])](#tocontainallkeyskeys) @@ -589,6 +590,17 @@ test('passes when value is an integer', () => { ### Object +#### .toBeEmptyObject() + +Use `.toBeEmptyObject` when checking if a value is an empty `Object`. + +```js +test('passes when value is an empty object', () => { + expect({}).toBeEmptyObject(); + expect({ a: 'hello' }).not.toBeEmptyObject(); +}); +``` + #### .toBeObject() Use `.toBeObject` when checking if a value is an `Object`. diff --git a/src/matchers/toBeEmptyObject/__snapshots__/index.test.js.snap b/src/matchers/toBeEmptyObject/__snapshots__/index.test.js.snap new file mode 100644 index 00000000..d347c881 --- /dev/null +++ b/src/matchers/toBeEmptyObject/__snapshots__/index.test.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`.not.toBeEmptyObject fails when given an empty object 1`] = ` +"expect(received).not.toBeEmptyObject() + +Expected value to not be an empty object, received: + {}" +`; + +exports[`.toBeEmptyObject fails when not given an empty object 1`] = ` +"expect(received).toBeEmptyObject() + +Expected value to be an empty object, received: + {\\"property1\\": \\"something\\"}" +`; diff --git a/src/matchers/toBeEmptyObject/index.js b/src/matchers/toBeEmptyObject/index.js new file mode 100644 index 00000000..f18ef170 --- /dev/null +++ b/src/matchers/toBeEmptyObject/index.js @@ -0,0 +1,26 @@ +import { matcherHint, printReceived } from 'jest-matcher-utils'; + +import predicate from './predicate'; + +const passMessage = received => () => + matcherHint('.not.toBeEmptyObject', 'received', '') + + '\n\n' + + 'Expected value to not be an empty object, received:\n' + + ` ${printReceived(received)}`; + +const failMessage = received => () => + matcherHint('.toBeEmptyObject', 'received', '') + + '\n\n' + + 'Expected value to be an empty object, received:\n' + + ` ${printReceived(received)}`; + +export default { + toBeEmptyObject: expected => { + const pass = predicate(expected); + if (pass) { + return { pass: true, message: passMessage(expected) }; + } + + return { pass: false, message: failMessage(expected) }; + }, +}; diff --git a/src/matchers/toBeEmptyObject/index.test.js b/src/matchers/toBeEmptyObject/index.test.js new file mode 100644 index 00000000..ffeb46ef --- /dev/null +++ b/src/matchers/toBeEmptyObject/index.test.js @@ -0,0 +1,23 @@ +import matcher from './'; + +expect.extend(matcher); + +describe('.toBeEmptyObject', () => { + test('passes when given an empty object', () => { + expect({}).toBeEmptyObject(); + }); + + test('fails when not given an empty object', () => { + expect(() => expect({ property1: 'something' }).toBeEmptyObject()).toThrowErrorMatchingSnapshot(); + }); +}); + +describe('.not.toBeEmptyObject', () => { + test('passes when not given an empty object', () => { + expect({ property1: 'something' }).not.toBeEmptyObject(); + }); + + test('fails when given an empty object', () => { + expect(() => expect({}).not.toBeEmptyObject()).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/src/matchers/toBeEmptyObject/predicate.js b/src/matchers/toBeEmptyObject/predicate.js new file mode 100644 index 00000000..cb1e0b3a --- /dev/null +++ b/src/matchers/toBeEmptyObject/predicate.js @@ -0,0 +1,3 @@ +import { getType } from 'jest-get-type'; + +export default expected => getType(expected) === 'object' && Object.keys(expected).length === 0; diff --git a/src/matchers/toBeEmptyObject/predicate.test.js b/src/matchers/toBeEmptyObject/predicate.test.js new file mode 100644 index 00000000..20c68c03 --- /dev/null +++ b/src/matchers/toBeEmptyObject/predicate.test.js @@ -0,0 +1,11 @@ +import predicate from './predicate'; + +describe('toBeEmptyObject Predicate', () => { + test('returns true when given an empty object', () => { + expect(predicate({})).toBe(true); + }); + + test('returns false when given a non-empty object', () => { + expect(predicate({ property1: 'something' })).toBe(false); + }); +}); diff --git a/types/index.d.ts b/types/index.d.ts index 6eccb4db..874cb519 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -716,5 +716,10 @@ declare namespace jest { * @param {String | RegExp} message */ toThrowWithMessage(type: Function, message: string | RegExp): any; + + /** + * Use `.toBeEmptyObject` when checking if a value is an empty `Object`. + */ + toBeEmptyObject(): R; } }