Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Formik testing error: The `document` global was defined when React was initialized, but is not defined anymore

Trying to test Formik with React. Below is the Formik Component:

import React, { Component } from 'react';
import { Formik, Field } from 'formik';
import { Button } from 'reactstrap';
import * as Yup from 'yup';
import axios from 'axios';
import { connect } from 'react-redux';
import TestComp from './../TestComp';

export class FormikComp extends Component{

    constructor(props){
        super(props);
        this.consoleMe = this.consoleMe.bind(this);
        this.state = {}

    }

    consoleMe(values){
        this.setState({
            values
        })
        console.log(this.state)
    }

    render(){

        return(
            <div id="div">
            <Formik
                enableReinitialize= {true}
                validateOnChange={false}
                initialValues={ {
                    user_name: '',
                    user_city: '',
                }}
                onSubmit={( values, {}) => {
                    this.consoleMe(values)
                }}
                validationSchema={Yup.object().shape({
                  user_name: Yup.string()
                    .test(
                      'test1',
                      'not longer than req length',
                      function(value){
                        if(value.length < 10){
                          return false;
                        }
                        return true
                      }
                    )
                })

                }
                render= {({
                    values,
                    errors,
                    handleSubmit,
                    handleChange,
                    touched,
                    ...props
                  }) => (
                    <div>
                    <form onSubmit={handleSubmit}>
                    <label>
                        <Field name="user_name" type="text" id="one" onChange={handleChange} value={values.user_name}/>
                        <p>{values.user_name}</p>
                        <p>{errors.user_name}</p>
                        <p>{JSON.stringify(this.state)}</p>
                    </label>
                    <label>

                    </label>
                        <Button
                            id="three"
                            color="info"
                            type="submit"
                        >
                            Click me!
                        </Button>
                    </form>
                    </div>
                  )}
            />
            </div>
        )
    }
}

function mapStateToProps(state, ownProps) {
    return state;
}

export default connect(mapStateToProps)(FormikComp)

Below is the test I am trying to run (the error is with the button submit...)

import React from 'react';
import ReactDOM from 'react-dom';
import { Formik, Field } from 'formik';
import Adapter from 'enzyme-adapter-react-16';
import Enzyme, { shallow, mount } from 'enzyme';
import { createStore } from 'redux';
import { reducers } from './../App';
import FormikComp from './';

// const initState = {user: {name: "Nathan Sainsbury", age: 30}};
const initState = {}
const store = createStore(reducers, initState);

const noop = () => {};
Enzyme.configure({ adapter: new Adapter() });

test('Cool', async () => {
    const wrapper = await mount(<FormikComp store={store} />)
    const dateInput = await wrapper.find('input')
    const button = await wrapper.find('button')
    const text = "nathannathan"

    await dateInput.simulate('change', {persist: noop, target : {name: 'user_name', value: text}})
    button.simulate('click')
    button.simulate('submit')
    console.log(wrapper.html())
    expect(wrapper.html().indexOf(`<p>${text}</p>`) != -1).toEqual(true)
})

This is the error I am recieving:

Invariant Violation: The `document` global was defined when React was initialized, but is not defined anymore. This can happen in a test environment if a component schedules an update from an asynchronous callback, but the test has already finished running. To solve this, you can either unmount the component at the end of your test (and ensure that any asynchronous operations get canceled in `componentWillUnmount`), or you can change the test itself to be asynchronous.
    at invariant (/home/nathan/Projects/react-testing/node_modules/fbjs/lib/invariant.js:42:15)
    at Object.invokeGuardedCallbackDev (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:79:44)
    at invokeGuardedCallback (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:187:29)
    at commitRoot (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:15536:7)
    at completeRoot (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:16618:34)
    at performWorkOnRoot (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:16563:9)
    at performWork (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:16482:7)
    at performSyncWork (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:16454:3)
    at requestWork (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:16354:5)
    at scheduleWork$1 (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:16218:11)
    at Object.enqueueSetState (/home/nathan/Projects/react-testing/node_modules/react-dom/cjs/react-dom.development.js:11299:5)
    at Formik.Object.<anonymous>.Component.setState (/home/nathan/Projects/react-testing/node_modules/react/cjs/react.development.js:270:16)
    at /home/nathan/Projects/react-testing/node_modules/formik/dist/formik.js:5932:23
    at <anonymous>

I can't seem to find the error, I've looked around but can't find much... Any help is greatly appreciated. I believe I have seen something saying that the button click returns a promise, I'm not sure though...


1 Answers

Just ran into this myself. Was able to get past it using setImmediate

describe('handleChange', () => {
  it('sets values state', async done => {
    const wrapper = mount(
      <Router>
        <LoginForm />
      </Router>
    );

    wrapper.find('input[id="email"]').simulate('change', {
      persist: noop,
      target: {
        id: 'email',
        value: '[email protected]'
      }
    });

    setImmediate(() => {
      expect(wrapper.find('input[id="email"]').props().value).toEqual(
        '[email protected]'
      );
      done();
    });
  });
});
like image 117
Luke Janssen Avatar answered Sep 17 '25 04:09

Luke Janssen