joetidee / enzyme-react-intl

A complimentary wrapper function for use with Enzyme, when testing React components that rely on react-intl
MIT License
45 stars 14 forks source link

state() returning null :( #14

Closed NotoriousWebmaster closed 5 years ago

NotoriousWebmaster commented 6 years ago

We start with a component using react-intl:

import React from "react";
import { injectIntl } from "react-intl";

class Hello extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            amount: 5
        };
  }

  render() {
      return <div>{this.props.intl.formatNumber(this.state.amount)}</div>;
  }
}

export default injectIntl(Hello);

And here's the test:

import React from "react";
import { shallowWithIntl } from "enzyme-react-intl";

import Hello from "./helloworld";

describe("Hello component", () => {
    const hello = shallowWithIntl(<Hello />);

    it("should get the hello's state", () => {
        expect(hello.state().amount).toBe(5);
    });
});

And the output includes:

FAIL src\app\components\common\currency-input\helloworld.test.js ● Hello component › should get the hello's state

TypeError: Cannot read property 'amount' of null

  at Object.it (src/app/components/common/currency-input/helloworld.test.js:10:25)
      at new Promise (<anonymous>)
  at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
      at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:188:7)

If we removed the intl calls in the component, the test would pass (but with shallow rather than shallowWithIntl).

Thanks for your help.

joetidee commented 6 years ago

What testing framework are you using, i.e. where is .state() coming from ?

NotoriousWebmaster commented 6 years ago

We're using Jest and Enzyme. http://airbnb.io/enzyme/docs/api/ShallowWrapper/state.html

aplanchamp commented 5 years ago

You need to use the .dive() method

import React from "react";
import { shallowWithIntl } from "enzyme-react-intl";

import Hello from "./helloworld";

describe("Hello component", () => {
    const hello = shallowWithIntl(<Hello />).dive();

    it("should get the hello's state", () => {
        expect(hello.state().amount).toBe(5);
    });
});

You should have your initial state this way.

AlexKund commented 4 years ago

Thats how I achieve the things:


import React from 'react';
import StandardFilterIntl, {StandardFilter} from 'bundles/components/Filter/StandardFilter';
import {mountWithIntl} from 'enzyme-react-intl';

const FilterComponent = mountWithIntl(<StandardFilterIntl {...standardFilterProps} />);
FilterComponent.find(StandardFilter).state()