From d00360b5073ec28e042dfb61fa840968af7c8ed8 Mon Sep 17 00:00:00 2001 From: Patrick Finnigan Date: Tue, 23 May 2017 09:47:21 -0700 Subject: [PATCH] add toMatchElement API --- README.md | 31 +++++- .../toMatchElement--tests.js.snap | 103 ++++++++++++++++++ .../__tests__/toMatchElement--tests.js | 49 +++++++++ .../src/assertions/toMatchElement.js | 35 ++++++ packages/enzyme-matchers/src/utils/html.js | 13 +-- .../src/utils/isShallowWrapper.js | 11 ++ 6 files changed, 229 insertions(+), 13 deletions(-) create mode 100644 packages/enzyme-matchers/src/assertions/__tests__/__snapshots__/toMatchElement--tests.js.snap create mode 100644 packages/enzyme-matchers/src/assertions/__tests__/toMatchElement--tests.js create mode 100644 packages/enzyme-matchers/src/assertions/toMatchElement.js create mode 100644 packages/enzyme-matchers/src/utils/isShallowWrapper.js diff --git a/README.md b/README.md index 38d1510..6f2c45e 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ This library supports several testing frameworks including [Jest](https://github * [toHaveText()](#tohavetexttextstring) * [toIncludeText()](#toincludetexttextstring) * [toHaveValue()](#tohavevaluevalueany) +* [toMatchElement()](#tomatchelementreactinstanceobject) * [toMatchSelector()](#tomatchselectorselectorstring) _Other_ @@ -150,7 +151,7 @@ expect(wrapper.find('span')).toBePresent(); expect(wrapper.find('ul')).not.toBePresent(); ``` -#### `toContainReact(ReactInstance:Object)` +#### `toContainReact(reactInstance:Object)` | render | mount | shallow | | -------|-------|-------- | @@ -454,6 +455,34 @@ expect(wrapper.find('input').at(0)).toHaveValue('test'); expect(wrapper.find('input').at(1)).toHaveValue('bar'); ``` +#### `toMatchElement(reactInstance:Object)` + +| render | mount | shallow | +| -------|-------|-------- | +| no | yes | yes | + +Assert the wrapper matches the provided react instance. This is a matcher form of Enzyme's wrapper.matchesElement(), which returns a bool with no indication of what caused a failed match. This matcher includes the actual and expected debug trees as contextual information when it fails. NOTE: The semantics are slightly different than enzyme's wrapper.matchesElement(), which ignores props. This matcher does consider props when comparing the actual to the expected values. + +Example: + +```js +function Fixture() { + return ( +
+ +
+ ); +} + +const wrapper = shallow(); // mount/render/shallow when applicable + +expect(wrapper).toMatchElement(); +expect(wrapper.find('span')).toMatchElement( + +); +expect(wrapper).not.toMatchElement(
); +``` + #### `toMatchSelector(selector:string)` | render | mount | shallow | diff --git a/packages/enzyme-matchers/src/assertions/__tests__/__snapshots__/toMatchElement--tests.js.snap b/packages/enzyme-matchers/src/assertions/__tests__/__snapshots__/toMatchElement--tests.js.snap new file mode 100644 index 0000000..01cf1f7 --- /dev/null +++ b/packages/enzyme-matchers/src/assertions/__tests__/__snapshots__/toMatchElement--tests.js.snap @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`toMatchElement mount provides contextual information for the message 1`] = ` +" +actual: + +
+ +
+
+ +expected: + +
+ +
+
+" +`; + +exports[`toMatchElement mount provides contextual information for the message 2`] = ` +" +actual: + + +expected: + +" +`; + +exports[`toMatchElement mount provides contextual information for the message 3`] = ` +" +actual: + +
+ +
+
+ +expected: +
+" +`; + +exports[`toMatchElement mount returns the message with the proper fail verbage 1`] = `"Did not expect actual value to match the expected value."`; + +exports[`toMatchElement mount returns the message with the proper fail verbage 2`] = `"Did not expect actual value to match the expected value."`; + +exports[`toMatchElement mount returns the message with the proper fail verbage 3`] = `"Did not expect actual value to match the expected value."`; + +exports[`toMatchElement mount returns the message with the proper pass verbage 1`] = `"Expected actual value to match the expected value."`; + +exports[`toMatchElement mount returns the message with the proper pass verbage 2`] = `"Expected actual value to match the expected value."`; + +exports[`toMatchElement mount returns the message with the proper pass verbage 3`] = `"Expected actual value to match the expected value."`; + +exports[`toMatchElement shallow provides contextual information for the message 1`] = ` +" +actual: +
+ +
+ +expected: +
+ +
+" +`; + +exports[`toMatchElement shallow provides contextual information for the message 2`] = ` +" +actual: + + +expected: + +" +`; + +exports[`toMatchElement shallow provides contextual information for the message 3`] = ` +" +actual: +
+ +
+ +expected: +
+" +`; + +exports[`toMatchElement shallow returns the message with the proper fail verbage 1`] = `"Did not expect actual value to match the expected value."`; + +exports[`toMatchElement shallow returns the message with the proper fail verbage 2`] = `"Did not expect actual value to match the expected value."`; + +exports[`toMatchElement shallow returns the message with the proper fail verbage 3`] = `"Did not expect actual value to match the expected value."`; + +exports[`toMatchElement shallow returns the message with the proper pass verbage 1`] = `"Expected actual value to match the expected value."`; + +exports[`toMatchElement shallow returns the message with the proper pass verbage 2`] = `"Expected actual value to match the expected value."`; + +exports[`toMatchElement shallow returns the message with the proper pass verbage 3`] = `"Expected actual value to match the expected value."`; diff --git a/packages/enzyme-matchers/src/assertions/__tests__/toMatchElement--tests.js b/packages/enzyme-matchers/src/assertions/__tests__/toMatchElement--tests.js new file mode 100644 index 0000000..8d38b97 --- /dev/null +++ b/packages/enzyme-matchers/src/assertions/__tests__/toMatchElement--tests.js @@ -0,0 +1,49 @@ +const { shallow, mount } = require('enzyme'); +const React = require('react'); + +const toMatchElement = require('../toMatchElement'); + +function Fixture() { + return ( +
+ +
+ ); +} + +describe('toMatchElement', () => { + [shallow, mount].forEach(builder => { + describe(builder.name, () => { + const wrapper = builder(); + const truthyResults = toMatchElement(wrapper, ); + const truthyResults2 = toMatchElement(wrapper.find('span'), + + ); + const falsyResults = toMatchElement(wrapper,
); + + it('returns the pass flag properly', () => { + expect(truthyResults.pass).toBeTruthy(); + expect(truthyResults2.pass).toBeTruthy(); + expect(falsyResults.pass).toBeFalsy(); + }); + + it('returns the message with the proper pass verbage', () => { + expect(truthyResults.message).toMatchSnapshot(); + expect(truthyResults2.message).toMatchSnapshot(); + expect(falsyResults.message).toMatchSnapshot(); + }); + + it('returns the message with the proper fail verbage', () => { + expect(truthyResults.negatedMessage).toMatchSnapshot(); + expect(truthyResults2.negatedMessage).toMatchSnapshot(); + expect(falsyResults.negatedMessage).toMatchSnapshot(); + }); + + it('provides contextual information for the message', () => { + expect(truthyResults.contextualInformation).toMatchSnapshot(); + expect(truthyResults2.contextualInformation).toMatchSnapshot(); + expect(falsyResults.contextualInformation).toMatchSnapshot(); + }); + }); + }); +}); diff --git a/packages/enzyme-matchers/src/assertions/toMatchElement.js b/packages/enzyme-matchers/src/assertions/toMatchElement.js new file mode 100644 index 0000000..78f5832 --- /dev/null +++ b/packages/enzyme-matchers/src/assertions/toMatchElement.js @@ -0,0 +1,35 @@ +/** + * This source code is licensed under the MIT-style license found in the + * LICENSE file in the root directory of this source tree. * + * + * @providesModule toMatchElementAssertion + * @flow + */ + +import { shallow, mount } from 'enzyme'; +import type { Matcher } from '../../../../types/Matcher'; +import type { EnzymeObject } from '../../../../types/EnzymeObject'; +import isShallowWrapper from '../utils/isShallowWrapper'; +import single from '../utils/single'; + +function toMatchElement(actualEnzymeWrapper:EnzymeObject, reactInstance:Object) : Matcher { + let expectedWrapper:EnzymeObject; + if (!isShallowWrapper(actualEnzymeWrapper)) { + expectedWrapper = mount(reactInstance); + } else { + expectedWrapper = shallow(reactInstance); + } + + const actual = actualEnzymeWrapper.debug(); + const expected = expectedWrapper.debug(); + const pass = actual === expected; + + return { + pass, + message: 'Expected actual value to match the expected value.', + negatedMessage: 'Did not expect actual value to match the expected value.', + contextualInformation: `\nactual:\n${actual}\n\nexpected:\n${expected}\n`, + }; +} + +export default single(toMatchElement); diff --git a/packages/enzyme-matchers/src/utils/html.js b/packages/enzyme-matchers/src/utils/html.js index c7bfcb2..874d47f 100644 --- a/packages/enzyme-matchers/src/utils/html.js +++ b/packages/enzyme-matchers/src/utils/html.js @@ -1,22 +1,11 @@ import instance from './instance'; +import isShallowWrapper from './isShallowWrapper'; import getConsoleObject from './getConsoleObject'; const consoleObject = getConsoleObject(); const noop = () => {}; const error = consoleObject.error; -const SHALLOW_WRAPPER_CONSTRUCTOR = 'ShallowWrapper'; -function isShallowWrapper(wrapper) : boolean { - let isShallow; - if (wrapper.constructor.name !== undefined) { - isShallow = wrapper.constructor.name === SHALLOW_WRAPPER_CONSTRUCTOR; - } else { - // function.name isn't available on IE 11, so fall back to turning the function into - // a string and checking its name this way. - isShallow = !!(`${wrapper.constructor}`).match(/^function ShallowWrapper\(/); - } - return isShallow; -} function mapWrappersHTML(wrapper) : string { return wrapper.nodes.map(node => { diff --git a/packages/enzyme-matchers/src/utils/isShallowWrapper.js b/packages/enzyme-matchers/src/utils/isShallowWrapper.js new file mode 100644 index 0000000..07907dc --- /dev/null +++ b/packages/enzyme-matchers/src/utils/isShallowWrapper.js @@ -0,0 +1,11 @@ +const SHALLOW_WRAPPER_CONSTRUCTOR = 'ShallowWrapper'; + +export default function isShallowWrapper(wrapper) : boolean { + let isShallow; + if (wrapper.constructor.name !== undefined) { + isShallow = wrapper.constructor.name === SHALLOW_WRAPPER_CONSTRUCTOR; + } else { + isShallow = !!(`${wrapper.constructor}`).match(/^function ShallowWrapper\(/); + } + return isShallow; +}