enzymejs / enzyme

JavaScript Testing utilities for React
https://enzymejs.github.io/enzyme/
MIT License
19.96k stars 2.01k forks source link

[Shallow] Question: Testing that an element exist somewhere, even within root component props #707

Closed gCardinal closed 7 years ago

gCardinal commented 7 years ago

Details about my setup: I'm using Material-UI, so normally whenever a component uses one of this library's component, I should wrap it in a ThemeProvider. I'm then using shallow rendering in my tests to skip that and simply test that my components display whatever I'm expecting them to display.

That being said, I'm hitting a wall right now and I'm unsure if it's me not getting how shallow rendering works or just something that's not possible to do due to either how React or Enzyme work.

I have this component from Material-UI that I want to "bake in" some values and let my app customize other.

import * as React from 'react'
import * as CSSModules from 'react-css-modules'
import * as styles from './MobileHeader.scss'

import AppBar from 'material-ui/AppBar'
import IconButton from 'material-ui/IconButton'
import CreditBalance from 'components/CreditBalance/CreditBalance'

@CSSModules(styles)
export default class MobileHeader extends React.Component {
    public render() {
        let {leftIconClickHandler, title, leftIcon, credits} = this.props

        return (
            <AppBar
                title={title}
                iconElementLeft={<IconButton>{leftIcon}</IconButton>}
                iconElementRight={
                    <CreditBalance
                        credits={credits}
                        creditIcon='/assets/img/b2b-credit-x4.png'
                        />
                }
                onLeftIconButtonTouchTap={leftIconClickHandler}
                styleName="app-bar"
                titleStyle={{height: 56}}
                iconStyleRight={{marginBottom: 14, marginTop: 14}}
            />
        )
    }
}

Let's say I want to test it displays credits properly, in my tests, the only thing I really care about is 1- Is there a CreditBalance component and 2- does it display 100?

Normally, when components are simply a series of children composed together, this is simple with find() and props(), but since the CreditBalance component is within AppBar's props, I can't a test working easily. find() won't find it

I did manage to test it, but it's almost reverse implementation and very brittle:

it(`Should display the credits in the <AppBar />'s iconElementLeft`, () => {
    let credits = mobileHeader.find('AppBar').prop('iconElementRight')
    expect(credits.props.credits).to.equal(100)
})

I'd love if I could simple do something like expect(mobileHeader.contains('CreditBalance')).to.be.true or something similar. Anything more precise than this and I feel like I'm throwing BDD out the window.

Is what I'm trying to do simply not possible?

ljharb commented 7 years ago

If you want to test the whole component tree, you need mount.

gCardinal commented 7 years ago

I realize that, sorry if my question made it sound otherwise.

However, as my example test shows, I can inspect the shallow rendered component and check that the prop I want is set to the value I'm expecting. Since the information is there, within the ShallowWrapper, is there no way to just test "Hey, is there a CreditBalance component in there somewhere, anywhere?"

It's fine if there is no way to do it, but I prefer to make sure before I do the switch since I much prefer shallow rendering to mounting components to a DOM.

ljharb commented 7 years ago

No, there's no way to do it - the point of shallow is that the implementation details of the subtree do not belong in your tests.

I recommend doing it with shallow, and having your MobileHeader tests simply assert that it renders an AppBar, with a iconElementRight prop of a CreditBalance. Then, your shallow unit tests for AppBar can assert that the iconElementRight gets rendered - and your CreditBalance tests can assert that it is rendered properly.

gCardinal commented 7 years ago

Alright. Guess I still need to do some figuring out when it comes to testing React components!

Thank you!