Enzyme Test React.createRef()

10,020

Updated with working examples. Added a styled-components example.

Here's how I solved it with Jest (uses different assertions, but concept is the same):

// setup
const MyComponent = React.forwardRef((props, ref) => (
    <div>
        <span ref={ref}>some element</span>
    </div>
))

// test
it('should contain the forwarded ref in the child span', () => {
    const ref = React.createRef()
    const component = mount(
        <Fragment>
            <MyComponent ref={ref} />
        </Fragment>,
    )

    expect(component.find('span').instance()).toEqual(ref.current)
})
  • The idea is to get the instance of the element that has the ref.
  • It seems to only work when wrapping MyComponent in another element, I used Fragment.

I ran into some trouble when using **Styled-Components. This is because it creates a number of extra elements. Try debugging with console.log(component.debug()). It will show you what enzyme renders.

When debugging you'll see that Styled-Components uses the recommended way to forward props.

You can find the right element using the property selector for forwardedRef:

// setup
const El = styled.div`
    color: red;
`

El.displayName = 'El'

const MyComponentWithStyledChild = React.forwardRef((props, ref) => (
    <El ref={ref}>some element</El>
))

// test
it('should contain the forwarded ref in a rendered styled-component', () => {
    const ref = React.createRef()
    const component = mount(
        <Fragment>
            <MyComponentWithStyledChild ref={ref} />
        </Fragment>,
    )

    // Styled-components sets prop `forwardedRef`
    const target = component
        .find('[forwardedRef]')
        .childAt(0)
        .instance()

    expect(target).toEqual(ref.current)
})
  • You can use the same trick if you created a Higher order Component (HoC) where you need to pass ref
Share:
10,020

Related videos on Youtube

Palaniichuk Dmytro
Author by

Palaniichuk Dmytro

Updated on June 04, 2022

Comments

  • Palaniichuk Dmytro
    Palaniichuk Dmytro almost 2 years

    I have a commponent where I use the new React.createRef() api, how to test document.activeElement should be equal current ref commponent.

    component :

    export class Automatic extends Component {
        componentDidMount = () => this.focusContainer()
        componentDidUpdate = () => this.focusContainer()
    
        container = React.createRef()
        focusContainer = () => this.container.current.focus()
    
        render = () => {
            return (
                <div
                    name='automatic'
                    onKeyPress={this.captureInput}
                    onBlur={() => setTimeout(() => this.focusContainer(), 0)}
                    ref={this.container}
                    tabIndex={0}
                >
                   ...
                </div>
    }
    

    old testing (works):

    it('should focus container on mount', () => {
        automatic = mount(<Automatic classes={{}} />, mountContext)
    
        document.activeElement.should.be.equal(automatic.ref('container'))
    })
    

    new one (doesn't work):

    it.only('should focus container on mount', () => {
        const container = React.createRef()
        automatic = mount(<Automatic classes={{}} />, mountContext)
    
        document.activeElement.should.be.equal(automatic.ref(container.current))
    })