enzymejs / enzyme-matchers Goto Github PK
View Code? Open in Web Editor NEWJasmine/Jest assertions for enzyme
License: MIT License
Jasmine/Jest assertions for enzyme
License: MIT License
it('renders the name', () => {
expect(wrapper).not.toIncludeText('lars van der hoover');
});
Failure message: Expected <SuperCoolComponent> to contain "lars van der hoover" but it did not.
Looks like 5d4b550 removed negated messages for jasmine
Hello,
I've found that when a component has an object property, mapWrappersHTML() throws an exception like "TypeError: 'Symbol(Symbol.toPrimitive)' returned for property 'Symbol(Symbol.toPrimitive)' of object '[object Object]' is not a function"
This is because it attempts to run ${key}="${props[key]}"
and fails to interpolate the object.
This is seen, for example, when running .toBePresent() against more than one result().
I'm not sure I see the benefit of mapWrappersHTML() having all that complexity - couldn't it essentially perform the same as the single node case in printHTMLForWrapper()?
Something like expect(a).toUpdateOnProp('data')
(prop or state) would really help
jest-enzyme
to use that instead of jasmine.My webpack build throws warnings when importing jasmine-enzyme because of the colors package imported by enzyme-matchers.
There are two files in which produce the warnings: colors/lib/colors.js (line 138) and colors/lib/extendStringPrototype.js (line 101). Both lines do a dynamic require of some module.
Since the colors package is last updated about a year ago, I don't understand why it's giving me this problem all of the sudden. I'm asking the question here since it's loaded as a dependency of enzyme-matchers. Since so many people are using webpack with jasmine, my assumption is that it's perhaps some sort of configuration issue.
Any ideas as to what might be the problem?
I am using Jest 20 with Enzyme 2.8.0.
Importing jest-enzyme
in my test files works, but as soon as I put it in my setup.js
I am getting the following error:
ReferenceError: expect is not defined
at Object.<anonymous> (node_modules/jest-enzyme/lib/index.js:23:1)
Here's my setup.js
file:
/* eslint-disable no-console */
require('jest-enzyme');
require('react-native-mock-render/mock');
const { jsdom } = require('jsdom');
global.document = jsdom('');
global.window = document.defaultView;
Object.keys(document.defaultView).forEach((property) => {
if (typeof global[property] === 'undefined') {
global[property] = document.defaultView[property];
}
});
const { Response, Headers, Request } = require('whatwg-fetch');
global.Response = Response;
global.Headers = Headers;
global.Request = Request;
jest.mock('Linking', () => ({
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
openURL: jest.genMockFn().mockReturnValue(Promise.resolve()),
canOpenURL: jest.genMockFn().mockReturnValue(Promise.resolve()),
getInitialURL: jest.genMockFn().mockReturnValue(Promise.resolve()),
}));
jest.mock('react-native-snackbar', () => ({
LENGTH_LONG: 1,
LENGTH_SHORT: 1,
LENGTH_INDEFINITE: 1,
}));
const originalConsoleError = console.error;
console.error = (message) => {
// see https://github.com/Root-App/react-native-mock-render/issues/6
if (message.startsWith('Warning: Unknown prop')) {
return;
}
originalConsoleError(message);
};
I tried rolling back to Jest 19 and putting the import at the end of file, didn't help.
What could be the problem?
It is currently expecting any version of 17.x.x. It should be any version equalling or above 17.x.x
For enzyme .equals, it would be great to be able to write:
const wrapper = shallow(<span />);
expect(wrapper).toEqualNode(<span />);
instead of
const wrapper = shallow(<span />);
expect(highlightedText.equals(<span />)).toBe(true);
which gives no useful information on failure.
Or the equivalent with .matchesElement
With the following spec:
import { shallow } from 'enzyme';
import React, { PropTypes } from 'react';
function User(props) {
return (
<div className="user">{props.name}</div>
);
}
User.propTypes = {
name: PropTypes.string.isRequired,
};
function Fixture(props) {
return (
<div id="root">
<User name="Nope!" />
</div>
);
}
it('should pass props to the User', () => {
const wrapper = shallow(<Fixture />);
expect(wrapper.find(User)).toHaveProp('name', 'Test User');
});
As of v2.0.0
the output of the above spec fails and outputs:
Expected wrappers prop values not to match for key "name":
Actual: "Nope!"
Expected: "Test User"
After the upgrade to v2.1.0-rc1
the spec passes.
function Fixture() {
const style1 = { backgroundColor: 'red' };
return (
<div>
<span id="style1" style={style1} />
</div>
);
}
const wrapper = mount(<Fixture />);
expect(wrapper.find('#style1')).toHaveStyle('backgroundColor', 'red'); // passes
expect(wrapper.find('#style1')).toHaveStyle('background-color', 'red'); // fails
second case should pass and first should fail right
On older versions of jasmine (v1), jasmine.addMatchers() isn't defined. Matchers need to be added to each spec in a beforeEach().
First off: I have tried searching the web to see if this was a common issue, but that does not seem to be the case. I assume this is the repository I should be posting this issue to -- if it is not, feel free to close it (and please direct me to the correct repository).
Now then!
I have written a recursive React component that I am writing tests for. For some reason, it seems that toContainReact
fails even though the HTML output contains the expected elements.
I created an application that contains a minimum reproduction (at least as minimum as I could find) of this issue: Saser/tocontainreact-failing
When running the test in the above repo, I get the following output:
Expected <div> to contain <span>outer<span>inner</span></span> but it was not found.
HTML Output of <div>:
<div><span>outer<span>inner</span></span></div>
Any idea as to what might be wrong?
Some of the messages for matchers are misleading when using .not
.
For example, whether you do expect(this.subject.find(...)).toBePresent()
or expect(this.subject.find(...)).not.toBePresent()
, upon failure, the error message is "Expected contents to not be empty, but it is".
I think it would be more useful if the message changed depending on whether the assertion passes. For example, instead of this:
compare(enzymeWrapper:Object) : Object {
return {
pass: enzymeWrapper.length !== 0,
message: 'Expected contents to not be empty, but it is',
};
},
how about:
compare(enzymeWrapper:Object) : Object {
var passes = enzymeWrapper.length !== 0;
return {
pass: passes,
message: passes ? 'Expected contents to not be empty, but it is' : 'Expected contents to be empty, but it wasnt',
};
},
I think a similar conditional could be applied to some of the other matchers as well.
toHaveState
appears to be ignoring the second argument (stateValue) as described here: https://github.com/blainekasten/enzyme-matchers#tohavestatestatekeystring-statevalueany
Since it's ignoring the second argument, tests pass if they will likely have the key even if the values don't match. Here's a reduced test case:
import React from 'react';
import { shallow } from 'enzyme';
class Fixture extends React.Component {
constructor() {
super();
this.state = { foo: 12 };
}
render() {
return (<div />);
}
}
describe('test', () => {
it('should fail', () => {
const wrapper = shallow(<Fixture />);
// This should fail since 12 != 15
expect(wrapper).toHaveState('foo', 15);
});
});
jest-enzyme
ONLY
It would be real cool if we could support enzyme with snapshot testing in jest. Since we rejected it from living in the enzyme repo (enzymejs/enzyme#541), this seems like the natural place.
Of course we would have to fall back to the original toMatchSnapshot
if a non-enzyme wrapper was given.
Basic thoughts:
var originalToMatchSnapshot;
toMatchSnapshot(enzymeWrapper) {
if (notEnzyme(enzymeWrapper)) {
return originalToMatchSnapshot(enzymeWrapper);
}
var snapshotable = convertToCompatibleJSON(enzymeWrapper);
return originalToMatchSnapshot(snapshotable);
}
Doesn't look like 3.5.0 got pushed to npm, was that intentional?
I was excited to try out this library but I ran into a lot of trouble installing and configuring.
I did get it working but I think others may have some difficulty too. I'm happy to make a PR with some more detailed installation instructions if it would be helpful.
This code in html.js returns wrapper.html() for shallow wrappers instead of wrapper.debug() when run on IE 11:
case 1: {
if (wrapper.constructor.name === SHALLOW_WRAPPER_CONSTRUCTOR) {
return wrapper.debug().replace(/\n/g, '');
}
return wrapper.html();
}
This is because wrapper.constructor.name is undefined on IE 11 (function.name is not supported).
Repro:
const wrapper = enzyme.shallow(<FooComponent />);
expect(wrapper).not.toBeEmpty();
A nice alias to wrapper.text() === actual
Hi,
just did a fresh install of jest-enzyme
and the types
folder is not packed with the package, only the lib
folder is present. Same for the enzyme-matchers
package.
Not sure what the initial goal for 20682e1 was actually.
Hey, adding this module to jest causes a lot of flow type checking errors:
node_modules/enzyme-matchers/src/assertions/toHaveText.js:10
10: import type { EnzymeObject } from '../../../../types/EnzymeObject';
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ../../../../types/EnzymeObject. Required module not found
There might be a way to ignore these with a flowconfig, but it'd be better if it worked out of the box.
I wonder if maybe this could be fixed by .npmignore
tje src
directory as it is not used (lib
folder is the actual module as far as I can tell)
It looks like the assertion failure message for toContainReact
is inverted.
FAIL src\App.test.js
● <App/> › renders the welcome message
Expected wrapper to contain <h2>THE CORRECT MESSAGE</h2>.
at stack (node_modules\jest-jasmine2\vendor\jasmine-2.4.1.js:1580:17)
at Object.it (src\App.test.js:10:21)
at process._tickCallback (internal\process\next_tick.js:103:7)
FAIL src\App.test.js
● <App/> › renders the welcome message
Expected wrapper not to contain <h2>THE CORRECT MESSAGE</h2>.
at stack (node_modules\jest-jasmine2\vendor\jasmine-2.4.1.js:1580:17)
at Object.it (src\App.test.js:10:21)
at process._tickCallback (internal\process\next_tick.js:103:7)
It's a little subtle, but the error message is saying that it expected to the component not to contain a snippet of JSX. In this case, the expectation was that it does contain that snippet.
create-react-app
boilerplate and add jest-enzyme
to it.App.test.js
slightly (see below)npm test
.// src/App.test.js
import { shallow } from 'enzyme';
import React from 'react';
import App from './App';
describe('<App/>', () => {
it('renders the welcome message', () => {
const wrapper = shallow(<App/>);
const message = <h2>THE CORRECT MESSAGE</h2>;
expect(wrapper).toContainReact(message);
});
});
After I add this line to my Jest test setup file:
import 'jest-enzyme';
Every time I run my tests, I got follow warning for each test case:
console.error node_modules/fbjs/lib/warning.js:36
Warning: ReactTestUtils has been moved to react-dom/test-utils. Update references to remove this warning.
It seems like jest-enzyme have some old react dependence. Is it possible to remove these warnings?
"react": "15.5.3",
"enzyme": "2.8.2",
"jest-enzyme": "3.2.0",
I receive the following error when I try to run my tests with jest-enzyme
:
TypeError: expect.addSnapshotSerializer is not a function
One our test works correctly with your enzyme-matchers in v2.0.0. But in version 2.1.0 it stats failing.
Error doesn't look like a problem with test, it looks more like problem with enzyme-matchers.
Error stack trace:
TypeError: Cannot read property '_tag' of undefined
at node_modules/enzyme-matchers/lib/utils/html.js:16:57
at Array.map (native)
at mapWrappersHTML (node_modules/enzyme-matchers/lib/utils/html.js:15:24)
at printHTMLForWrapper (node_modules/enzyme-matchers/lib/utils/html.js:53:21)
at Assertion.toBePresent (node_modules/enzyme-matchers/lib/assertions/toBePresent.js:32:73)
at Assertion.<anonymous> (test/frontend/__helpers/assertions.js:12:43)
at Assertion.Object.defineProperty.value [as bePresent] (node_modules/should/lib/assertion.js:147:14)
at Context.<anonymous> (test/frontend/unit/features/appsList/appSuggestion/AppSuggestion.jsx:96:60)
Failing assertion looks:
wrapper.find(".appSuggestion .section").should.bePresent();
We use should
for assertions and therefore I wrote wrapper which extends should
with your module.
For us simplest solution is to downgrade to 2.0.0 and don't allow to update.
For some JavaScript environments (e.g. V8 on Android), the global console object is not defined. Referencing an undeclared variable causes a ReferenceError (at least in strict mode).
Just started playing with enzyme and jasmine-enzyme and got stuck on an unexpected bug. Currently the toMatch
and toContains
matchers override core jasmine matchers which work on strings.
Would you consider renaming these?
They could be renamed to something like toMatchSelector
and toContainReact
or something like that...
Appreciate your time, and thanks for your effort and library!
Currently we are doing nothing with render
ed components. chai-enzyme is supporting them nicely. We should find a way to support render
ed components.
CI has been failing for a while.. needs to be fixed so we can merge with confidence.
index.d.ts was in src folder in 3.2.0 but in 3.5.1 it's in lib folder and Typescript cannot find the definitions anymore.
Also @types/jest defines Matchers as interface Matchers<R>
but jest-enzyme defines Matchers as interface Matchers
. This causes Typescript to throw error All declaration of Matchers must have identical type parameters
Consider a test that looks something like the following:
class MyComponent extends React.Component {
render () {
return <div>{ this.props.name }</div>
}
}
describe('MyComponent', () => {
it('has name prop', () => {
let props = { name: 'Mr. Foobar' }
let wrapper = shallow(<MyComponent { ...props } />)
expect(wrapper).toHaveProp('name', props.nameTypo)
})
})
In this case, the test passes, even though there is an obvious typo in the matcher's arguments: .toHaveProp('name', props.nameTypo)
.
The intent here is obvious: the component should have a prop called name
with a value of 'Mr. Foobar'
. In practice, though, because of the typo, the matcher simply checked that the prop existed, and stopped short of comparing the component's actual value for name
with the expected value (of undefined
).
I think this might be a case where the matcher should have compared the values. It may be necessary to consider arguments.length
to determine if a value comparison is required, not whether the propValue === undefined
. Doing so should preserve the ability to call the matcher with one arg (.toHaveProp('foo')
) as well as catch programmer mistakes like the case outlined above.
I think the danger with toHaveText is that if you add any more text anywhere else in the component, the test will break. If you add another matcher called toIncludeText that just asserts that the text includes some text, that would be much more resilient to false failures.
I am trying to update a project that uses the old 1.2.0 version of jasmine-enzyme and I encountered a breaking change that I don't see mentioned in the change-log (this is jasmine specific).
The toHaveProp() method does not work aymore when jasmine core matchers are used as value.
class MyComponent extends React.Component {
render () {
return <div name="whatever" />;
}
}
it( 'toHaveProp() with jasmine matchers as value', () => {
const wrapper = shallow(<MyComponent />);
// This one works:
expect( wrapper ).toHaveProp( 'name', 'whatever' );
// This one fails with 2.0.0 and above:
expect( wrapper ).toHaveProp( 'name', jasmine.any( String ) );
} );
1.2.0 works, but 2.0.0 and 3.4.0 gives the same error:
Expected <MyComponent> "name" prop values to match (using npm.deepEqualIdent) but they didn't.
Should this be working or did you drop support for this specific stuff at one point ?
I have not used jest yet, so I don't know if there is any equivalent.
Thanks !
SPEC:
const style = { width: '50px', height: '50px' };
const wrapper = shallow(<img alt="avatar" src="image.jpg" style={style} />);
expect(wrapper).toHaveAttr('alt', 'avatar');
expect(wrapper).toHaveAttr('src', 'image.jpg');
expect(wrapper).toHaveAttr('style', 'width:50px;height:50px;');
SPEC:
const style = { height: '100%', flex: 8 };
const wrapper = shallow(<div style={style} />);
expect(wrapper).toHaveStyle('height', '100%');
expect(wrapper).toHaveStyle('flex', 8);
Running my spec suite on Chrome, Firefox, Safari, Edge, and IE11.
IE11 is the only browser experiencing the following:
Expected <function DropContainer(props) {
var className = props.className,
direction = props.direction,
flush = props.flush;
return _react2.default.createElement(
_reactAddonsTransitionGroup2.default,
{
className: className + ' ' + directionClassName(direction) + ' ' + flushClassName(flush, direction),
component: 'div'
},
props.children
);
}> node to equal (using ===) type "ReactTransitionGroup" but it is a "undefined".
where
export default function DropContainer(props) {
const {
className,
direction,
flush,
} = props;
return (
<ReactTransitionGroup
className={`${className} ${directionClassName(direction)} ${flushClassName(flush, direction)}`}
component="div"
>
{props.children}
</ReactTransitionGroup>
);
}
Stepping through the matcher, it's pretty clear why it would be failing.
Attempting to get the name of the enzymeWrapper is not supported in IE.
A polyfill should suffice. I'll see if I can provide a workaround (for the time being).
With new release 3.6.0, I executed:
mkdir enzyme-poc && cd enzyme-poc && npm init -y && npm i jest-enzyme jest --save-dev
cat ./node_modules/jest-enzyme/lib/index.d.ts
I was hoping for it to contain the changes from #134
But it doesn't
Did we make a mistake while publishing or is it intentional?
When I do executed
cat ./node_modules/jest-enzyme/package.json
It does reveal that it's using 3.6.0
I get the below error with "setupTestFrameworkScriptFile": "node_modules/jest-enzyme/lib/index.js"
. I no longer have an error when prepending <rootDir>
.
Error: Jest: Module "node_modules/jest-enzyme/lib/index.js" in the "setupTestFrameworkScriptFile" option was not found. at resolve (.../node_modules/jest-config/build/normalize.js:48:11) at Object.keys.reduce (.../node_modules/jest-config/build/normalize.js:343:17) at Array.reduce (native) at normalize (.../node_modules/jest-config/build/normalize.js:294:23) at promisify.then (.../node_modules/jest-config/build/loadFromPackage.js:24:12) error Command failed with exit code 1.
Strangely the toHaveProp
matcher seems to modify the passed array value:
it('check props', () => {
const numberArray = [1, 2, 3];
console.log(numberArray); // [ 1, 2, 3 ]
expect(wrapper).toHaveProp('records', numberArray);
console.log(numberArray); // [ 1 ]
});
I'm (apart from that happily 👍 ) using jasmine-enzyme 3.2.0 (and enzyme 2.8.2).
Hi,
I've been trying to create a Karma plugin wrapper for this project, however I've hit a road block as the toContainReact
matcher requires Enzyme.
I've been playing around with the matcher, and found an alternative, but hacky solution to avoid the import.
Using
const wrappedInstance = Object.getPrototypeOf(enzymeWrapper).wrap(reactInstance);
Instead of
const wrappedInstance = shallow(reactInstance);
This uses the wrap method from ReactWrapper, but there may be hidden complications with the this.root
?
Is there any way we can render the error message without importing Enzyme?
Jest is diverging from jasmine slowly, so we need to prepare for that change. My plan is this:
enzyme-matchers
. Different name?packages would be:
Could be extensible for mocha, chai, Ava, etc with this approach
For example, the name.js file in enzyme-matchers/lib/utils is converted to
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = getNameFromArbitraryWrapper;
var _instance = require('./instance');
var _instance2 = _interopRequireDefault(_instance);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Gets the name of the node or component for the SINGLE item
*/
function getNameFromRoot(root) {
// shallow
if (root.unrendered) {
var type = root.unrendered.type;
return type.name || type;
}
var inst = (0, _instance2.default)(root);
if (inst) {
return inst._tag;
}
// direct node
if (typeof root.type === 'string') {
return root.type;
}
return typeof root.name === 'function' ? root.name() : '(anonymous)';
}
/**
* Can take any sort of wrapper. A single node, a component,
* multiple nodes, multiple components.
*
* examples of outputs:
* - "Fixture"
* - "input"
* - "(anonymous)"
* - "Fixture, 2 "span" nodes found"
* - "Fixture, 2 mixed nodes found"
*/
/**
* @function name
* @returns string
*
*
*/
function getNameFromArbitraryWrapper(wrapper) {
var nodeCount = wrapper.nodes.length;
switch (nodeCount) {
case 0:
{
return '[empty set]';
}
case 1:
{
return getNameFromRoot(wrapper);
}
default:
{
var nodeTypeMap = {};
// determine if we have a mixed list of nodes or not
wrapper.nodes.forEach(function (node) {
var name = getNameFromRoot(node);
nodeTypeMap[name] = (nodeTypeMap[name] || 0) + 1;
});
var nodeTypeList = Object.keys(nodeTypeMap);
var nodeTypes = nodeTypeList.length === 1 ? nodeTypeList[0] : 'mixed';
var root = getNameFromRoot(wrapper.root);
return `${root}, ${nodeCount} ${nodeTypes} nodes found`;
}
}
}
module.exports = exports['default'];
It's not a native es6 module any more so it's treated by webpack as a regular js file but notice the return statement has back-ticks which breaks our phantomjs testing setup.
Using jest-enzyme, here is my test file, copied directly from your examples:
import React from 'react'
import {mount, shallow} from 'enzyme'
function Fixture() {
return (
<div>
<input id="checked" defaultChecked />
<input id="not" defaultChecked={false} />
</div>
);
}
describe('wrapper', () => {
it('works', () => {
const wrapper = mount(<Fixture />); // mount/render/shallow when applicable
expect(wrapper.find('#checked')).toBeChecked();
expect(wrapper.find('#not')).not.toBeChecked();
})
})
I have installed as devDependencies jest-enzyme, enzyme, react-addons-test-utils.
I get this failure message:
> CI=true react-scripts test --env=jsdom
FAIL src/__tests__/ListModalSpec.js
● wrapper › works
TypeError: expect(...).toBeChecked is not a function
at Object.<anonymous> (src/__tests__/ListModalSpec.js:16:38)
at process._tickCallback (internal/process/next_tick.js:103:7)
How am I holding it wrong?
Example on the top of my head, refs are only supported in mount
. So if someone passes a shallow
wrapper to toHaveRef
, we should throw a useful message.
I'm noticing that most of the assertions perform an html()
invocation on the enzyme wrapper (to generate possible error output?). This triggers a renderToStaticMarkup
from react-dom
, which seems to defeat the whole purpose of shallow rendering because this tries to build the full tree and fails because dependencies of children in the tree are not met.
Am I missing something obvious?
Name up for discussion.
Idea is that if I want to check that a wrapper is a specific component, I could assert easily.
expect(wrapper).toBeInstanceOf(MyCustomComp);
Is the name correct?
I've noticed that if a negative assertion fails using one of the assertions in this library, it fails correctly but "not" is missing in the message text. For example:
import React from 'react';
class Fail extends React.Component {
render () {
return (
<div>
<input id="checked" checked={true} />
<input id="not" checked={true} />
</div>
);
}
}
module.exports = Fail;
import React from 'react';
import {mount} from 'enzyme';
import jasmineEnzyme from 'jasmine-enzyme';
var Fail= require('../Fail.jsx');
describe('Fail', () => {
var wrapper;
beforeEach(() => {
jasmineEnzyme();
wrapper = mount(<Fail />);
});
it('should render the not checked component as not checked', () => {
expect(wrapper.find('#not')).not.toBeChecked();
});
});
F
Failures:
1) Fail should render the not checked component as not checked
Message:
Expected "<input id="not" name="">" to be checked
The message should be "Expected [emement] not to be checked".
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.