Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add toMatchElement matcher #95

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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_
Expand Down Expand Up @@ -150,7 +151,7 @@ expect(wrapper.find('span')).toBePresent();
expect(wrapper.find('ul')).not.toBePresent();
```

#### `toContainReact(ReactInstance:Object)`
#### `toContainReact(reactInstance:Object)`

| render | mount | shallow |
| -------|-------|-------- |
Expand Down Expand Up @@ -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 (
<div>
<span id="foo" className="bar" />
</div>
);
}

const wrapper = shallow(<Fixture />); // mount/render/shallow when applicable

expect(wrapper).toMatchElement(<Fixture />);
expect(wrapper.find('span')).toMatchElement(
<span id="foo" className="bar" />
);
expect(wrapper).not.toMatchElement(<div />);
```

#### `toMatchSelector(selector:string)`

| render | mount | shallow |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`toMatchElement mount provides contextual information for the message 1`] = `
"
actual:
<Fixture>
<div>
<span id=\\"child\\" className=\\"foo\\" />
</div>
</Fixture>

expected:
<Fixture>
<div>
<span id=\\"child\\" className=\\"foo\\" />
</div>
</Fixture>
"
`;

exports[`toMatchElement mount provides contextual information for the message 2`] = `
"
actual:
<span id=\\"child\\" className=\\"foo\\" />

expected:
<span id=\\"child\\" className=\\"foo\\" />
"
`;

exports[`toMatchElement mount provides contextual information for the message 3`] = `
"
actual:
<Fixture>
<div>
<span id=\\"child\\" className=\\"foo\\" />
</div>
</Fixture>

expected:
<div />
"
`;

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:
<div>
<span id=\\"child\\" className=\\"foo\\" />
</div>

expected:
<div>
<span id=\\"child\\" className=\\"foo\\" />
</div>
"
`;

exports[`toMatchElement shallow provides contextual information for the message 2`] = `
"
actual:
<span id=\\"child\\" className=\\"foo\\" />

expected:
<span id=\\"child\\" className=\\"foo\\" />
"
`;

exports[`toMatchElement shallow provides contextual information for the message 3`] = `
"
actual:
<div>
<span id=\\"child\\" className=\\"foo\\" />
</div>

expected:
<div />
"
`;

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."`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const { shallow, mount } = require('enzyme');
const React = require('react');

const toMatchElement = require('../toMatchElement');

function Fixture() {
return (
<div>
<span id="child" className="foo" />
</div>
);
}

describe('toMatchElement', () => {
[shallow, mount].forEach(builder => {
describe(builder.name, () => {
const wrapper = builder(<Fixture />);
const truthyResults = toMatchElement(wrapper, <Fixture />);
const truthyResults2 = toMatchElement(wrapper.find('span'),
<span id="child" className="foo" />
);
const falsyResults = toMatchElement(wrapper, <div />);

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();
});
});
});
});
35 changes: 35 additions & 0 deletions packages/enzyme-matchers/src/assertions/toMatchElement.js
Original file line number Diff line number Diff line change
@@ -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);
13 changes: 1 addition & 12 deletions packages/enzyme-matchers/src/utils/html.js
Original file line number Diff line number Diff line change
@@ -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 => {
Expand Down
11 changes: 11 additions & 0 deletions packages/enzyme-matchers/src/utils/isShallowWrapper.js
Original file line number Diff line number Diff line change
@@ -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;
}