Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enzyme cannot find child component in shallow test

Is this not the correct way to render a react/reflux test with enzyme but without the store, ie, "dumb"

import React from 'react'
import { shallow, render } from 'enzyme'
import { Controls } from '../Controls' // named export
import LoadingSpinner from '../LoadingSpinner'
let wrapper
let loadingFlags = {
  controls: true
}
describe('<Controls />', () => {
  it('should render only the loading spinner', () => {
    wrapper = shallow(<Controls loadingFlags={loadingFlags} />) // this ensures the spinner will show until data is ready
    expect(wrapper.length).toEqual(1) // test passes
    expect(wrapper.find(LoadingSpinner)).to.have.length(1)
    // ^ TypeError: Cannot read property 'have' of undefined
  })
})

When I log wrapper.html() I can see the <img class='spinner' /> is rendered, but enzyme cannot find it as a component. To me, the docs indicate this is exactly what I should be doing. I suppose I could check for a child with that class, but that seems messier than checking for the component itself, eg the class changes within the Spinner component.

How can I test for the existence of this child component?

like image 857
1252748 Avatar asked Aug 31 '17 20:08

1252748


People also ask

How do you find the Enzyme component of a child?

Using a component constructor allows Enzyme to pluck a child component in this way: const element = component. find(ChildComponent); This works well when there are one or two children.

Does shallow render child components?

Shallow rendering lets you render a component “one level deep” and assert facts about what its render method returns, without worrying about the behavior of child components, which are not instantiated or rendered. This does not require a DOM.

What does Shallow do in Enzyme?

shallow method is used to render the single component that we are testing. It does not render child components. In Enzyme version less than 3, the shallow method does not have the ability to access lifecycle methods. But in Enzyme version 3, we have this ability.

What is the difference between shallow and mount in Enzyme?

Always begin with shallow. If componentDidMount or componentDidUpdate should be tested, use mount. If you want to test component lifecycle and children behavior, use mount. If you want to test children rendering with less overhead than mount and you are not interested in lifecycle methods, use render.


2 Answers

The test will work fine with shallow, but the assertion has a TypeError because it doesn't exist - it looks like you are using Jest, but the enzyme docs show assertions using chai BDD library.

Use the Jest equivalent instead:

expect(wrapper.find(LoadingSpinner)).toHaveLength(1)
like image 114
alechill Avatar answered Nov 14 '22 13:11

alechill


You should use a mount().

from https://github.com/airbnb/enzyme/blob/master/docs/guides/jsdom.md

import test from 'ava';
import React from 'react';
import { mount, shallow, render } from 'enzyme'

import LoadingSpinner, {Controls} from './LoadingSpinner';
// jsdom init start
const { JSDOM } = require('jsdom');

const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
const { window } = jsdom;

function copyProps(src, target) {
    const props = Object.getOwnPropertyNames(src)
        .filter(prop => typeof target[prop] === 'undefined')
        .map(prop => Object.getOwnPropertyDescriptor(src, prop));
    Object.defineProperties(target, props);
}

global.window = window;
global.document = window.document;
global.navigator = {
    userAgent: 'node.js',
};
copyProps(window, global);
// jsdom init end

test('<Controls />' , t => {
    let wrapper = shallow(<Controls />);
    let mntWrapper = mount(<Controls />);
    t.true(wrapper.length == 1);
    t.true(wrapper.find(LoadingSpinner).length === 1);

    t.true(mntWrapper.find("img").length === 1);
    t.true(mntWrapper.render().find('img').length === 1);
    // if you need to test attributes check below.
    t.true(mntWrapper.render().find('img')[0].attribs.src.indexOf('foo') >= 0);
});
like image 38
panghea Avatar answered Nov 14 '22 15:11

panghea