Hi Guys Good Day!

ok, guys first We gonna configure Jest, Enzyme from the ground up. So you can know what modules or packages we're gonna use.

Do this in the command line on your desktop. cmd md testing-with-enzyme && cd testing-with-enzyme md testing-with-enzyme - Makes a directory with a name of testing-with-enzyme && - runs the second command if the first command does not throw an error cd testing-with-enzyme - Changes the current directory to testing-with-enzyme

cmd npm init --y && npm i -D @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties @types/jest jest enzyme enzyme-adapter-react-16 && npm i -P react react-dom

ok, I'm not gonna explain all these packages but we're gonna all of these packages to work with enzyme and jest.

cmd type nul > babel.config.js && type nul > jest.config.js && md Tests && md components type nul for Windows OS. touch for UNIX Systems.

Our babel.config.js file. js module.exports = { presets: ['@babel/preset-env', '@babel/preset-react'], plugins: ['@babel/plugin-proposal-class-properties'] }

Our jest.config.js file. js module.exports = { rootDir: '.', displayName: { name: 'enzyme-setup', color: 'blue' }, runner: 'jest-runner', verbose: true, errorOnDeprecated: true, roots: ['./Tests'], moduleFileExtensions: ['js', 'jsx'], setupFilesAfterEnv: ['<rootDir>Tests/setupTest.js'] }

Inside our Tests folder make a setupTest.js file. ```js import { configure } from 'enzyme' import Adapter from 'enzyme-adapter-react-16'

configure({ adapter: new Adapter() }) ```

Our package.json file. package.json

Inside the components folder make 4 files. cmd type nul > App.js && type nul > Form.js && type nul > Header.js && type nul > List.js

Our Header.js file. ```js import React from 'react'

export default function Header({ message, handleToggleTheme, theme }) { return (

{message}

) } ```

Our Form.js file. ```js import React from 'react'

export default function Form({ handleChange, value, handleClick }) { return (

) } ```

Our List.js file. ```js import React from 'react'

export default function List({ items }) { return (

    {items.map(item => (
  • {item}
  • ))}
) } ```

Our App.js file. ```js import React, { Component } from 'react' import Header from './Header' import List from './List' import Form from './Form'

export default class App extends Component {

state = { listItem: '', items: [], isDarkTheme: false }

handleChange = ({ target: { value } }) => { this.setState({ listItem: value }) }

handleClick = () => { this.setState({ items: [...this.state.items, this.state.listItem], listItem: '' }) }

handleToggleTheme = () => { this.setState({ isDarkTheme: !this.state.isDarkTheme }) }

render() { const theme = this.state.isDarkTheme ? 'dark' : 'light' return (

) }

}

App.defaultProps = { message: 'Hello World' } ```

Inside the Tests folder make an index.test.js file. ```js import React from 'react' import App from '../components/App' import Header from '../components/Header' import Form from '../components/Form' import List from '../components/List' import { shallow, mount } from 'enzyme'

describe('Test App component', () => { let wrapper;

beforeAll(() => { wrapper = shallow() })

it('should not return an error', () => { expect(wrapper).toMatchSnapshot() console.log(wrapper.debug()) }) }) ```

Then in your terminal run this command cmd npm t If it does not throw an error and it passed then your good to go.

What's the difference between shallow rendering and full mount rendering?

There's this very useful method debug that both shallow and mount provides us.

Try updating our index.test.js file to look like this. ```js import React from 'react' import App from '../components/App' import Header from '../components/Header' import Form from '../components/Form' import List from '../components/List' import { shallow, mount } from 'enzyme'

describe('Test App component', () => { let shallowWrapper, mountWrapper;

beforeAll(() => { shallowWrapper = shallow() mountWrapper = mount()

console.log(shallowWrapper)
console.log(mountWrapper)

})

}) ```

Structure using the debug method.

The first console.log looks like this. javascript console.log Tests/index.test.js:12 <div className="light"> <Header theme="light" message="Hello World" handleToggleTheme={[Function]} /> <Form handleChange={[Function]} value="" handleClick={[Function]} /> <List items={{...}} /> </div>

The second console.log looks like this. javascript console.log Tests/index.test.js:13 <App message="Hello World"> <div className="light"> <Header theme="light" message="Hello World" handleToggleTheme={[Function]}> <div className="header"> <h1> Hello World </h1> <button className="right" onClick={[Function]}> <i className="light" /> </button> </div> </Header> <Form handleChange={[Function]} value="" handleClick={[Function]}> <div className="form"> <input className="form-control" type="text" onChange={[Function]} value="" /> <button className="btn" onClick={[Function]} /> </div> </Form> <List items={{...}}> <ul className="list" /> </List> </div> </App>

The debug method basically gives us the structure of our component. When we use it on shallow it does not give us the full structure of our component we don't see the JSX structure of our Header,Form, and List component but when we use it on mount it gives us the full structure of our component down to every JSX element that our child components used.

Useful methods that Enzyme provides us.

at(index : number)

Returns a wrapper element based on the index is given.

The difference between using shallow and mount on our App component. ```javascript it('should have an "App" component "at" index of 0', () => { let wrapper = shallow(); expect(wrapper.at(0).type()).toBe(App); });

it('should return an App', () => { let wrapper = mount(); expect(wrapper.at(0).type()).toBe(App) });

``` The first test failed but the second test passed the reason to this is that the type of element at index 0 in our shallowed component is div, not App but in our mountend component is App refer to the Structure Section changing the App to div in the shallowed test will make the test passed.

childAt(index : number)

Returns a new wrapper of the child at the specified index. ```javascript it('should have a child component of type "Header" at "index" of 0', () => { let wrapper = shallow(); expect(wrapper.childAt(0).type()).toBe(Header); });

it('should have a child element of type "div" at "index" of 0', () => { let wrapper = mount(); expect(wrapper.childAt(0).type()).toBe('div') }); ``` Base on the Structure of our shallowed App the first child should be Header and in our mounted App the first child should be div. These two tests should passed.

find(selector : EnzymeSelector)

Basically finds every node that matches the given selector.

Selectors. - find('div') = finds every 'div' element on the current wrapper. - find('div.something') = finds every 'div' element with a class of 'something' on the current wrapper. - find('div[title="okinawa"]) = finds every 'div' element with an attribute of "title" with a value of "okinawa".

  • find('#okinawa') = find every element with an id of "okinawa".
  • find('.okinawa') = finds every element with a class of "okinawa".
  • find('div#okinawa > span') = finds every 'span' element that is the direct child of a "div" with an id of "okinawa"
  • find('div.okinawa + span') = finds every 'span' element that is placed after a "div" element with a class of "okinawa"
  • find('div.okinawa span') = finds every 'span' element that is inside a "div" element with a class of "okinawa"
  • find(SomeComponent) = finds every element with a contrustor of "SomeComponent" ```javascript function App({ children }){ return (
    {children}
    ) }

function SomeComponent(){ return (

Hi!

) }

it('should have length of "1" when finding "SomeComponent" comp', () => { const wrapper = shallow( ) expect(wrapper.find(SomeComponent)).toHaveLength(1); });

``` You can find all the valid selectors here.

closest(selector : EnzymeSelector)

finds the closest parent that matches the selector. It traverses every node up starting with itself.

```javascript

it('should have an h1 with a text of "Hello World"', () => { let wrapper = shallow(); expect(wrapper.find(Header).closest('div.light')).toHaveLength(1); });

it('should have a parent element of "div" with a class of "light"', () => { let wrapper = mount(); expect(wrapper.find(Header).closest('div.light')).toHaveLength(1); })

``` These two tests should pass.

contains(node : node | nodes[])

Tests if the containing wrapper has a matching child or children.

```javascript it('should have a node of

and the right props', () => { let wrapper = shallow(); expect(wrapper.contains(
)).toBeTruthy(); });

it('should contain these two nodes', () => { const wrapper = mount(); expect(wrapper.contains([

Hi

, ])).toBeTruthy(); })

``` We're using the instance() method to get the reference of the handleToggleTheme function out of that component instance. More on the instance method later. These tests should pass.

containsAllMatchingElements(nodes: nodes[])

Must match all the nodes on the current wrapper. ```javascript it('should have these two nodes when shallow mounting', () => { let wrapper = shallow(); wrapper.setState({ listItem: '1' }) expect(wrapper.containsAllMatchingElements( [ ,

] )).toBeTruthy(); });

it('should have these two nodes when mounting', () => { let wrapper = mount(); expect(wrapper.containsAllMatchingElements([

Hi

, ])).toBeTruthy(); })

``` We're using setState to update the value of a property in our state. It works the same as React's setState. this.setState({property: newValue}). These tests should pass.

containsAnyMatchingElements(nodes: nodes[])

Must match at least one of the nodes on the current wrapper. ```javascript it('should this Form with the right props', () => { expect(wrapper.containsAnyMatchingElements( [ , ] )).toBeTruthy(); });

it('should return true because the "i" element is right while "div" element is not the right structure', () =>{ expect(wrapper.containsAnyMatchingElements([

, ])).toBeTruthy(); });

``` You're wondering why we have a value of "1" in the shallowed part that's because we used setState on the previous section and updated our listItem to have a value of 1. These tests should pass.

first()

Behaves like at(0) refer.

hasClass(class:string)

Tests if the current node has prop of className and checks the value.

```javascript

it('should have a class of "light"', () => { let wrapper = shallow(); expect(wrapper.hasClass('light')).toBeTruthy(); });

it('should have a class of "form-control"', () => wrapper = mount();
{ expect(wrapper.find(Form).find('#form').childAt(0).hasClass('form-control')).toBeTruthy(); })

``` These tests should pass.

html()

returns the raw html string of the current wrapper. ```javascript it('should return the correct string', () => { let wrapper = shallow(); expect(wrapper.childAt(2).html()).toBe('

    ') });

    it('should have an element with an id of "form"', () => { let wrapper = mount(); wrapper.setProps({ message: 'Hi' }); expect(wrapper.find('h1').html()).toBe('

    Hi

    ') })

    ``` These tests should pass too.

    instance()

    returns the current class instance of the current wrapper it returns null when used on a functional component. the instance method can only be used on the root node.

    ```javascript

    it('should be an instance of App', () => { let wrapper = shallow(); expect(wrapper.instance()).toBeInstanceOf(App); });

    it('should be an instance of App', () => { let wrapper = mount(); expect(wrapper.instance()).toBeInstanceOf(App); }); ``` These tests should pass.

    invoke(functionPropName)(..arguments)

    ```javascript

    it('should have a prop of "value" with a value of "12344"', () => { let wrapper = shallow(); wrapper.find(Form).invoke('handleChange')({ target: { value: '12344' } }); expect(wrapper.find(Form).prop('value')).toBe('12344'); });

    it('should truthy value of prop "isDarkTheme"', () => { let wrapper = mount(); wrapper.find(Header).invoke('handleToggleTheme')() expect(wrapper.state('isDarkTheme')).toBeTruthy(); })

    ``` These tests should pass too. I think you're wondering I'm passing an object with a target property which has a value of an object with another property of value because my handleChange function looks like this

    javascript handleChange = ({ target: { value } }) => { this.setState({ listItem: value }) }

    is(selector: EnzymeSelector)

    Checks if the selector matches the current wrapper. ```javascript

    it('should return false when checking with ".is"', () => { let wrapper = shallow(); expect(wrapper.find(List).find('ul').is('.list')).toBeFalsy(); });

    it('should return true when checking with ".is"', () => { let wrapper = mount(); expect(wrapper.find(List).find('ul').is('.list')).toBeTruthy(); }); ```

    The reason that the first test failed and thrown an error because of the reason that our element structure when using shallow looks like this javascript <div className="light"> <Header theme="light" message="Hello World" handleToggleTheme={[Function]} /> <Form handleChange={[Function]} value="" handleClick={[Function]} /> <List items={{...}} /> </div> It does not render the ul element but when we use it on mount it works.

    isEmptyRender()

    returns true if the current wrapper returns null or false.

    ```javascript

    it('should not be falsy because "App" does not return neither null or false', () => { let wrapper = shallow(); expect(wrapper.isEmptyRender()).toBeFalsy(); });

    it('should return "Nothing" literally', () => { class Nothing extends React.Component { render() { return ( null ) } } let wrapper = mount(); expect(wrapper.isEmptyRender()).toBeTruthy(); });

    ``` These tests should pass. The second test pass due to the reason we returned null on the render method.

    key()

    returns the key value of the current wrapper.

    ```javascript it('should have a prop of items with a length of 2 and a key value of "japan"', () => { let wrapper = mount(); let form = wrapper.find(Form); form.invoke('handleChange')({ target: { value: 'okinawa' } }); form.invoke('handleClick')(); form.invoke('handleChange')({ target: { value: 'japan' } }); form.invoke('handleClick')();

    expect(wrapper.find(List).prop('items')).toHaveLength(2);
    expect(wrapper.find(List).find('ul').childAt(1).key()).toBe('japan');
    

    });

    ```

    last()

    returns the last node base on the current selected wrapper.

    ```javascript

    it('should return the last child type which is "List"', () => { let wrapper = shallow(); expect(wrapper.children().last().type()).toBe(List); });

    it('should return the last child type which is "div"', () => { let wrapper = mount() expect(wrapper.children().last().type()).toBe('div'); });

    ```

    name()

    returns the "name" of current wrapper. ```javascript it('should return a name with a value of "div"', () => { let wrapper = shallow(); expect(wrapper.name()).toBe('div'); });

    it('should return a name with a value of "App"', () => { let wrapper = mount(); expect(wrapper.name()).toBe('App'); }); ``` Again, refer to the Structure Section if your having a little problem understanding.

    filter(selector: EnzymeSelector)

    it returns a new wrapper based on the selector given.

    ```javascript it('should have a prop of "item" with length of 3', () => { let wrapper = mount(); let form = wrapper.find(Form); let values = ["ohio", "usa", "amawa"]; values.forEach((value) => { form.invoke('handleChange')({ target: { value } }); form.invoke('handleClick')(); })

    expect(wrapper.find(List).find('ul li').filter('.list-item')).toHaveLength(3);

    });

    }); ```

    props()

    returns the prop object of the current wrapper

    ```javascript it('should have a prop "items" with a value of []', () => { let wrapper = shallow(); expect(wrapper.find(List).props().items).toEqual([]); });

    it('should have a prop "message" with a value of "Hello World"', () => { let wrapper = mount();

    expect(wrapper.find(Header).props().message).toBe("Hello World");
    

    });

    ```

    prop(key:string)

    return the value of the property of the current wrapper.

    ```javascript it('should have a prop "items" with a value of []', () => { let wrapper = shallow(); expect(wrapper.find(List).prop('items')).toEqual([]); });

    it('should have a prop "message" with a value of "Hello World"', () => { let wrapper = mount();

    expect(wrapper.find(Header).prop('message')).toBe("Hello World");
    

    });

    ```

    setProps(newProps: any)

    Sets the new props object of the root node. It can only be used on the root node.

    ```javascript

    it('should have an updated prop "message" with a value of "What the fun"', () => { let wrapper = mount(); wrapper.setProps({ message: 'What the fun' }) expect(wrapper.find(Header).prop('message')).toBe("What the fun"); });

    ```

    setState(newState : any, callbackFunc: Function)

    Sets the new state object of the root node. It can only be used on the root node.

    ```javascript it('should have an updated prop "isDarkTheme" with a value of true', () => { let wrapper = mount(); wrapper.setState({ isDarkTheme: true }); expect(wrapper.state('isDarkTheme')).toBeTruthy(); });

    ```

    simulate(event:string, ...args)

    Invokes an event on the current wrapper.

    ```javascript it('should have an updated value of "1234"', () => { let wrapper = mount(); wrapper.find('input').simulate('change', { target: { value: '1234' } }); expect(wrapper.state('listItem')).toBe('1234'); });

    ```

    state(key:string)

    return the value of a state property.

    ```javascript

    it('should a input with a value of "abc"', () => { let wrapper = shallow(); wrapper.setState({ listItem: 'abc' }); expect(wrapper.state('listItem')).toBe('abc'); });

    it('should have an updated "message" prop with a value of "Hi"', () => { let wrapper = mount(); wrapper.setProps({ message: 'Hi' }); expect(wrapper.prop('message')).toBe('Hi'); })

    ```

    text()

    returns the text of the current wrapper.

    ```javascript it('should a text of "Hello World"', () => { let wrapper = mount(); expect(wrapper.find('h1').text()).toBe('Hello World'); });

    ```

    type()

    returns the type of the current wrapper. ```javascript

    it('should return the App', () => { let wrapper = shallow(); expect(wrapper.at(0).type()).toBe('div'); });

    it('should return the App', () => { let wrapper = mount(); expect(wrapper.at(0).type()).toBe(App); });

    ```

    Check this post out to make your own Cover Image for your dev.to Post.

    Thanks guys for reading this post.

    Have a Nice Day :smiley:!.