Test if props are passed (Without using Enzyme) - reactjs

I want to test if my props are passed, but without using Enzyme,
I tried to find documentation on the internet, but all the tutorials are with Enzyme.
describe('App Component', () => {
it('renders the Counter wrapper', () => {
const wrapper = shallow(<App />);
expect(wrapper.find(Counter)).to.have.length(1);
});
it('passes all props to Counter wrapper', () => {
const wrapper = shallow(<App />);
let counterWrapper = wrapper.find(Counter);
expect(counterWrapper.props().counter).to.equal(0);
wrapper.setState({ counter: -1 });
counterWrapper = wrapper.find(Counter);
expect(counterWrapper.props().counter).to.equal(-1);
});
Could someone help me? Can I do this with jest? Or I do need a third-party library like 'react-testing-library'?

Enzyme shallow is primarily intended for isolated unit tests like the one that was listed, only the implementation of tested unit is asserted. It offers some instrumentation (and also non-compliant behaviour) that doesn't exist in React itself.
react-testing-library is primarily intended for blackbox functional tests, the effects of units on resulting DOM are asserted.
React's own ReactTestUtils also offer some basic functionality, a subset of Enzyme and react-testing-library features, including shallow renderer for isolated tests.
It's possible to do isolated tests and assert the implementation without Enzyme, this results in boilerplate code. The approach isn't specific to testing library, it could be achieved with any renderer, including React's test renderer's snapshot testing. Everything (Counter component) but tested unit (App component) should be mocked with Jest, e.g.:
it('passes all props to Counter wrapper', async () => {
const CounterMock = jest.fn(() => 'Counter');
jest.mock('./counter-module', () => CounterMock);
const App = await import('./app-module');
// render <App/> and assert that the result is <div>Counter</div>
expect(CounterMock).toBeCalledWith({ counter: 0 });
});

Related

Enzyme Test Code Memory cleanup

I have been looking at a lot of examples for testing react and redux applications using Enzyme and Jest, and there are very few that even mention code cleanup. When using shallow or mount do you not explicitly need to call unmount or detach to try to keep the memory bloat and runtime down?
There is a case where we will want to use detach to cleanup. Let's look at the simple shallow and mount case first.
Assigning to variables
This 'simple' case is where we simply assign the render to a var/const/let.
If we look at the (cut down) example of using Jest and Enzyme from the Enzyme Github.
describe('<MyComponent />', () => {
it('renders three <Foo /> components', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find(Foo)).to.have.lengthOf(3);
});
it('renders an `.icon-star`', () => {
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.icon-star')).to.have.lengthOf(1);
});
});
We can see the shallow method being called and the result being assigned to a const. The result is a ShallowWrapper object.
As const has a block scope when the execution leaves the block it is defined - in this case the test arrow function - the Javascript engine will automatically deallocate the ShallowWrapper memory.
It's because of this we don't need to worry about unmounting - this is only used to test specific Component lifecycle methods.
Attaching Components to DOM
We can also attach components to the DOM.
If we look at the test case automatically generated by the create-react-scripts.
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});
This example doesn't use Enzyme, but it's the same concept as to when you use attachTo in the Enzyme mount function.
We can see our Component is being attached to a div in the document and then ReactDOM.unmountComponentAtNode being called to cleanup. This is actually what detach calls.
We need to do this cleanup because a reference to our rendered Component exists outside our block scope and therefore will not be deallocated when execution exits this block.

React Native Testing - How to TDD and test components beyond snapshots?

I'm really struggling with how to test React Native components beyond using snapshots from jest. Those are great for testing the look of something based on some data passed into a component, but it doesn't seem like there is a way to test events or event handlers, checking if event listeners were setup or disconnected correctly in lifecycle methods, etc...like it feels like I'm either missing something or the tooling is not complete.
Also on a side note snapshot testing feels backwards in terms of TDD since you can only write your tests once you have your application code...any thoughts on this?
With snapshot test you can only check the values in props and styles etc. To check some logic in container i used 'shallow' from enzyme ;)
You can still use snapshots with events for things like: click a button and verify the rendered output after the click:
it('should render Markdown in preview mode', () => {
const wrapper = shallow(
<MarkdownEditor value="*Hello* Jest!" />
);
expect(wrapper).toMatchSnapshot();
wrapper.find('[name="toggle-preview"]').simulate('click');
expect(wrapper).toMatchSnapshot();
});
To test that event handler was called property you can do something like that:
it('should pass a selected value to the onChange handler', () => {
const value = '2';
const onChange = jest.fn();
const wrapper = shallow(
<Select items={ITEMS} onChange={onChange} />
);
expect(wrapper).toMatchSnapshot();
wrapper.find('select').simulate('change', {
target: { value },
});
expect(onChange).toBeCalledWith(value);
});
(Both examples are from my article on testing React components with Jest.)

React + Enzyme error: Invariant Violation: dangerouslyRenderMarkup(...): Cannot render markup in a worker thread

I am testing a react component using Enzyme and I'm getting the following error:
Invariant Violation: dangerouslyRenderMarkup(...): Cannot render markup in a worker thread. Make sure window and document are available globally before requiring React when unit testing or use ReactDOMServer.renderToString for server rendering
I added the following setup for jsdom, before requiring 'enzyme' (as I read in few places):
const baseMarkup = '<!DOCTYPE html><html><head><title></title></head><body></body></html>';
const window = require('jsdom').jsdom(baseMarkup).defaultView;
global.window = window;
global.document = window.document;
global.navigator = window.navigator;
const React = require('react');
const {mount} = require('enzyme');
const sinon = require('sinon');
const SortableInput = require('../../../src/components/sortableInput/sortableInput').default;
What am I doing wrong here?
EDIT
I don't think it is related to server side rendering. The message is general about unit testing and server side rendering.
Answering my own question, in case someone have the same issue. This was what eventually worked for me:
import 'jsdom-global/register';
describe('My awesome component test', () => {
let cleanup;
beforeEach(() => cleanup = require('jsdom-global')());
afterEach(() => cleanup());
....
})
In one of my project, this is the code to initialise JSDOM, and it is working fine.
import { jsdom } from 'jsdom';
before(() => {
global.document = jsdom('');
global.window = document.defaultView;
});
The before() is a root hook for Mocha. It runs before the beginning of all tests.
One more not so obvious reason for the same error is the describeWithDOM method from Enzyme:
describeWithDOM('<Slider />', () => {
describe('render', () => {
it('should render the slider with one handle by default', () => {
// and so on
According to enzyme guide now it is better to avoid this method:
In previous versions of enzyme, there was a public describeWithDOM API
which loaded in a new JSDOM document into the global namespace before
every test, ensuring that tests were deterministic and did not have
side-effects.
This approach is no longer recommended. React's source code makes
several assumptions about the environment it is running in, and one of
them is that the global.document that is found at "require time" is
going to be the one and only document it ever needs to worry about. As
a result, this type of "reloading" ends up causing more pain than it
prevents.
It is important, however, to make sure that your tests using the
global DOM APIs do not have leaky side-effects which could change the
results of other tests. Until there is a better option, this is left
to you to ensure.

Are Enzyme / React shallow renders expensive?

We're having a discussion at work about Enzyme shallow renders and the time per test to re-run shallow on each test. Be it methods, clicks, selector lengths, etc., I'm suggesting that our tests might run faster if we shallow render the component one time before the tests run versus each time.
Are there any experts who can point out which way would be faster and if there are any pitfalls in either way? These examples are using the AVA runner (and slightly contrived for the sake of discussion).
For example, here's one way (A)...
import TagBox from '../TagBox';
const props = { toggleValue: sinon.spy() };
let wrapper = {};
test.before(t => {
wrapper = shallow(<TagBox />);
});
test('it should have two children', t => {
t.is(wrapper.children().length, 2);
});
test('it should safely set props', t => {
wrapper.setProps({...props});
t.is(wrapper.children().length, 2);
});
test('it should call when clicked', t => {
wrapper.setProps({...props});
wrapper.find({tagX : true}).last().simulate('click');
t.true(props.toggleValue.calledOnce);
});
And here's the other (B)...
import TagBox from '../TagBox';
test('it sets value to null ...', t => {
const props = {multiple: false};
const wrapper = shallow(<TagBox {...props} />);
t.is(wrapper.state('currentValue'), null);
});
test('it sets value to [] if multiple', t => {
const props = {multiple: true};
const wrapper = shallow(<TagBox {...props} />);
t.deepEqual(wrapper.state('currentValue'), []);
});
test('it does not use value if ...', t => {
const props = = {value: 3};
const wrapper = shallow(<TagBox {...props} />);
t.is(wrapper.state('currentValue'), null);
});
// etc. etc.
Notice that in test B, there is a new shallow wrapper for each test when essentially nothing has changed but props.
Over the course of 100 tests, what would you expect to be the difference in time to completion?
Also is there any chance shallow rendering once (test A) in the higher scope would pollute the test state?
Shallow renderer is designed to be fast, because it renders only single component. So, usually you will not get any performance troubles, when you create new component for each test.
Also, your example A can work incorrectly if TagBox component has inner state. That't why example B is more preferable way to write tests.
The shallow is probably not your problem here since it's designed to be the fastest way to render a component without cascading all of it's children renders.
You may consider changing your test running engine then, AVA is kinda slow compared to Jest for example. I did this change a year ago and it is a LOT faster. Jest also provides in it's base kit more useful stuff like mocking functions of example.
More here: https://facebook.github.io/jest/

Mocha, Enzyme: Unit testing custom functions in react component using enzyme

I am working on creating unit tests of react components using mocha, enzyme. Below is a sample component.
Foo.js
class Foo extends React.Component {
customFunction=() => {
}
render() {
return (<div className={this.props.name}/>);
}
}
And here is the testing file.
Foo-Test.js
import React from 'react';
import { expect } from 'chai';
import { shallow, mount, render } from 'enzyme';
import Foo from '../src/Foo';
describe("A suite", function() {
it("contains spec with an expectation", function() {
expect(shallow(<Foo />).contains(<div className="foo" />)).to.equal(true);
});
it("contains spec with an expectation", function() {
expect(shallow(<Foo />).is('.foo')).to.equal(true);
});
});
Everything is good. but I didn't understand how to unit test customFunction in Foo.js when we are using enzyme
The best answer to this question really depends on what it is that customFunction is actually doing...
You can call the function like this:
wrapper.instance().customFunction('foo', 'bar');
If it's a function that sets state on the instance itself, and thus affects what the rendered output looks like, you may want to call .update() as well
wrapper.instance().customFunction('foo', 'bar'); // uses setState internally
wrapper.update(); // updates render tree
// do assertions on the rendered output
You can also use the chai plugin to spy on custom functions in you jsx file.
// to use this pluggin add this to the top of your testing file
const chai = require("chai"), spies = require("chai-spies");
chai.use(spies);
import Foo from "./<path to component>/Foo.jsx";
describe("Foo", () => {
it("a call to customFunction will not error", () => {
let spy = chai.spy(Foo.prototype, "customFunciton"); // spy
const wrapper = mount(<Foo/>);
wrapper.setProps({bar: "baz"}); // manipulate you component in some way
expect(spy).to.have.been.called.once();
});
});
#leland-richardson is right, it depends on what your test is doing. Understanding that will help you compose new ways to manipulate your component and thus make assertions.
Another example testing a function that updates your components state.
it("function will assert new state", () => {
const wrapper = shallow(<Foo {...props}/>);
wrapper.instance.customFunction(); // call custom function
wrapper.update();
expect(wrapper.state("bar")).to.equal("new-state");
});
Chai-spies also has a handful of chainable getters that make testing custom functions much easier. Please see the docs for a more in-depth explanation.

Resources