2

Say I have the following on Index.tsx:

ReactDOM.render(
    <h2 style={{textAlign: "center"}}>Hello World</h2>,
    document.getElementById("wrapper")
);

First, how exactly do I unit test ReactDOM.render call? Second, running this on Karma + PhantomJS, I get the following error:

Invariant Violation: _registerComponent(...): Target container is not a DOM element.

at /tmp/karma-typescript-bundle-192osSfGKwYIxIW.js:188

This is because document.getElementById("wrapper") will not work under PhantomJS since there is not wrapper element.

What's the best way to work around this? Is there anyway I can insert/mock the wrapper element just once on PhantomJS?

rfgamaral
  • 16,546
  • 57
  • 163
  • 275

1 Answers1

2

If there is no #wrapper element in the DOM, you have to create it and just prepare environment before running specific tests. You can use jsdom which help you in creation and maintenance of the DOM between your tests.

React has an official package for writing unit tests which is called react-addons-test-utils. It makes it easy to test React components in the testing framework of your choice.

More info can be found in official documentation: https://facebook.github.io/react/docs/test-utils.html

I recommend you another solution. Airbnb has published Enzyme which makes writing unit tests super easy. API is very well documented and straight forward. There is even information about enzyme in Test Utilities - React documentation.

Airbnb has released a testing utility called Enzyme, 
which makes it easy to assert, manipulate, and traverse your React
Components' output. If you're deciding on a unit testing utility to
use together with Jest, or any other test runner, 
it's worth checking out: http://airbnb.io/enzyme/

On Github you can find starters for almost each test framework, there is even a starter for Karma with sample repositories.

The last thing is if you decide to use jsdom, react-addons-test-utils, or enzyme, you don't need PhantomJS anymore because all your tests can be run just in Node.js which will make your tests also faster.


This is explanation what each tool gives you as a developer:

  • Mocha - It's a test framework and a test runner.
  • Karma - It's a test runner
  • Jasmine - It's a test framework
  • Sinon - It's a mocking library
  • ReactTestUtils - It's a small package which makes testing React components more easier
  • Enzyme - It's built on top of ReactTestUtils and jsdom but it provides friendly developer API. Makes testing React component more easier.
  • jsdom - It's a small package which emulates web browser inside node

Please remember that some test frameworks like Jasmine gives you also some mocking functionalities so you don't need Sinon.

You can use enzyme with any test runner and framework. You can use it with Karma and Jasmine. You can use it with Mocha. You can use it with Jest. There is a lot of test frameworks and runners ;)

Dawid Karabin
  • 5,113
  • 1
  • 23
  • 31
  • I'm confused about `enzyme`... If I use Enzyme + Karma, I'll still need PhantomJS (or a real browser) and the initial problem remains. So, how does Enzyme help? – rfgamaral Jan 19 '17 at 04:10
  • For the record, my full toolset for unit testing is: Karma (with karma-typescript for nice coverage report without messing with webpack), Mocha, Chai, Sinon, React Test Utils, PhantomJS. – rfgamaral Jan 19 '17 at 04:10
  • 1
    You don't need PhantomJS or any browser because web environment is let's say "simulated" by jsdom and all tests can be run inside Node without spawning any browser. Please read this article "From Karma to Mocha, with a taste of jsdom", it should clear everything - https://medium.com/podio-engineering-blog/from-karma-to-mocha-with-a-taste-of-jsdom-c9c703a06b21#.d64gngkhy – Dawid Karabin Jan 19 '17 at 10:38
  • (haven't yet read the article) In a nutshell, you're suggesting jsdom + enzyme, is that it? I'm still feeling a bit overwhelmed by Enzyme... Does it replace Mocha/Chai/Sinon/React TestUtils in any way or they all complement each other? If so, what exactly does Enzyme have that the other 4 together don't? I'm just trying to understand if I should simply migrate Karma to jsdom (and keep all the rest) or migrate Karma to jsdom with Enzyme and get rid of any of Mocha/Chai/Sinon/React TestUtils package? – rfgamaral Jan 19 '17 at 11:16
  • @RicardoAmaral I edited my answer because my comment was too big. Enzyme is not a replacement for Mocha, Chai, Karma, Jasmine. It's a replacement for RestTestUtils because it's built on top of it. Just use enzyme with Karma and Jasmine, you don't have to migrate. Enzyme is not a test framework or runner. – Dawid Karabin Jan 19 '17 at 12:01
  • Thank you for that detailed answer, everything is more clearer now. For now I'm just going to replace TestUtils with Enyzme and keep using Karma, Mocha, Chai, Sinon. Since I have Karma properly setup for TypeScript + Webpack and Istanbul coverage (this was not easy). This doesn't really solve my initial question because I'll still be using PhantomJS, to work around that I believe I have to go the jsdom route but I can't find that much information for TypeScript + Webpack + Mocha + jsdom with coverage... And I currently don't have the time required to dig into this myself :( – rfgamaral Jan 19 '17 at 12:22
  • I just found `karma-jsdom-launcher` so I might replace `karma-phantomjs-launcher` with that one instead :) – rfgamaral Jan 19 '17 at 12:31
  • Migration to Enzyme complete. I also tried to get install jsdom with Karma but I'm having issues with the `canvas` package (which is required, maybe because of React). But I'm on Windows, and compilation of that package is a huge pain... :/ – rfgamaral Jan 19 '17 at 14:12