0

I'm writing a test for a component to test one of its functions, but I am getting an error: ShallowWrapper can only wrap valid elements

The component file is as follows - TextInput.js:

  /* eslint-disable react/require-default-props */
import React from 'react'
import PropTypes from 'prop-types'
import { InputLabel, TextField } from '@material-ui/core'

const TextInput = ({
  name, label, onChange, placeholder, value, error, optional = false, isDisable = false, t,
}) => (
  <>
    {label ? (
      <InputLabel htmlFor={name} className="default-style_label">
        {label}
        {' '}
        {optional && <span className="optional">{`(${t('application.optional')})`}</span>}
      </InputLabel>
    ) : ''}
    <TextField
      type="text"
      name={name}
      placeholder={placeholder}
      value={value}
      // isRequired={isRequired}
      disabled={isDisable}
      onChange={onChange}
      error={error && true}
      helperText={error}
      variant="outlined"
      className="default-style_input"
    />
  </>
)

TextInput.propTypes = {
  name: PropTypes.string.isRequired,
  label: PropTypes.string,
  onChange: PropTypes.func.isRequired,
  placeholder: PropTypes.string,
  value: PropTypes.string,
  error: PropTypes.string,
  optional: PropTypes.bool,
  isDisable: PropTypes.bool,
  t: PropTypes.func,
}

export default TextInput

The test file

   /* eslint-disable no-undef */
import React from 'react'
import { shallow, mount } from 'enzyme'
import TextInput from '../TextInput'

function createTestProps(props) {
  return {
    // common props
    name: 'test',
    label: 'foo',
    value: 'bar',
    onChange: jest.fn(),
    // allow to override common props
    ...props,
  }
}

describe('rendering', () => {
  describe('<TextInput>', () => {
    let wrapper
    let instance
    beforeEach(() => {
      const props = createTestProps()
      wrapper = mount(shallow(<TextInput {...props} />)).get(0)
      instance = wrapper.instance()
    })

    afterEach(() => {
      jest.clearAllMocks()
    })

    it('should be rendered', () => {
      const content = wrapper.find('input').at(1)
      console.debug(content.debug())
      console.log(instance)
      expect(content.value).toBe('bar')
    })
  })
})

The problem is that my tests fail when remove mount from

wrapper = mount(shallow(<TextInput {...props} />)).get(0)

with a Compared values have no visual difference Any ideas why this is happening would be much appreciated!

Mohammad Fared
  • 588
  • 1
  • 7
  • 19

3 Answers3

1

You should use either mount or shallow to render your component based on your use case.

  • use mount if you want to render your component where all children would be rendered to the last leaf node.

  • use shallow if you need a level deep rendering of your component.

Note: in most cases, you should use shallow rendering as mount takes a long time.

pritam
  • 2,452
  • 1
  • 21
  • 31
0

You should use shallow or mount, not both of them.

wrapper = mount(<TextInput {...props} />);

const content = wrapper.find('input');
expect(content.value).toBe('bar');
0

It's something different when you're using @material-ui.

You've to use @material-ui's Built-in API(s). Such as createMount, createShallow, createRender in order to use enzyme's shallow, mount & render.

These APIs are built on top of enzyme, so you can't use enzyme directly for testing @material-ui.

Here's my test file

   /* eslint-disable no-undef */
import React from 'react'
import { createMount } from '@material-ui/core/test-utils'
import TextField from '@material-ui/core/TextField'
import TextInput from '../TextInput'

function createTestProps(props) {
  return {
    // common props
    name: 'test',
    label: 'foo',
    value: 'bar',
    onChange: jest.fn(),
    // allow to override common props
    ...props,
  }
}

describe('rendering', () => {
  describe('<TextInput>', () => {
    let mount
    let props
    beforeEach(() => {
      mount = createMount()
      props = createTestProps()
    })

    afterEach(() => {
      mount.cleanUp()
    })

    it('renders a <TextField/> component with expected props', () => {
      const wrapper = mount(<TextInput {...props} />)
      expect(wrapper.props().name).toEqual('test')
      expect(wrapper.props().onChange).toBeDefined()
    })

    it('should trigger onChange on <TextField/> on key press', () => {
      const wrapper = mount(<TextInput {...props} />)
      wrapper.find('input').simulate('change')
      expect(props.onChange).toHaveBeenCalled()
    })
  })
})

I found the solution here Material UI + Enzyme testing component

Mohammad Fared
  • 588
  • 1
  • 7
  • 19