Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jquery doesn't work with jsdom/enzyme

I have a minimum test react app with following component:

import React from 'react';
import $ from 'jquery';

export default class App extends React.Component {
    componentDidMount() {
        console.log('componentDidMount', $('#helloDiv').length);
    }

    render() {
        return <div id='helloDiv'>
            Hello React!
                </div>;
    }
}

this works fine when loading it in browser (Chrome). The console.log() in componentDidMount() prints out 1 helloDiv element found

However, if I run the test using mocha + enzyme + jsdom, the same console.log() in App component prints out 0:

import React from 'react';
import { mount } from 'enzyme';
import { expect } from 'chai';
import App from '../src/client/app/first'

describe('first test', () => {
    it('should pass', () => {        
        const app = mount(<App />);
        expect(app.find('#helloDiv').length).to.eq(1);
    });
});

Note: I don't have problem with this unit test, it's passing. The real problem is when < App /> is mounted using enzyme, componentDidMount() is called but the console.log() statement inside it prints out 0, instead of 1

Here is how I run mocha:

mocha --require enzyme/withDom --compilers js:babel-core/register test/index.test.js

Any idea why jquery selector doesn't find anything in the test? It should not be mocha issue because the same issue happens if I change to jest

like image 255
Phuong Nguyen Avatar asked Feb 10 '17 14:02

Phuong Nguyen


People also ask

Does enzyme use Jsdom?

JSDOM is a JavaScript based headless browser that can be used to create a realistic testing environment. Since enzyme's mount API requires a DOM, JSDOM is required in order to use mount if you are not already in a browser environment (ie, a Node environment).

What is jsdom jest?

jsdom is a pure JavaScript implementation of the DOM and browser APIs that runs in node. If you're not using Jest and you would like to run your tests in Node, then you must install jsdom yourself. There's also a package called global-jsdom which can be used to setup the global environment to simulate the browser APIs.


1 Answers

Finally found the issue:

Enzyme mount(<SomeComponent />) by default will do full DOM rendering but not insert the rendered component into current document (JSDom). That's why jQuery cannot find any element in current document

To do full DOM rendering AND attach to current document:

mount(<SomeComponent />, { attachTo: document.getElementById('app') });

Where app is empty div available when jsdom is setup:

global.document = jsdom('<html><head></head><body><div id="app" /></body></html>');
like image 91
Phuong Nguyen Avatar answered Oct 19 '22 12:10

Phuong Nguyen