3
votes

Comment tester superficiellement un composant de réaction enveloppé dans un mémo et avec des styles?

J'ai un composant qui est enveloppé à la fois dans un HOC Material-UI withStyles et un HOC React memo .

Je ne peux pas tester ce composant car je ne peux pas appeler dive():

ShallowWrapper :: dive () ne peut être appelé que sur les composants

La seule option dont je suis actuellement au courant est de exporter la démo indépendamment et exporter par défaut avec les styles (styles) (démo) . Cela me permet de tester le composant qui n'est pas enveloppé dans withStyles . Je voudrais éviter cette méthode.

Si je supprime memo (), je peux tester le composant. De même, si je supprime withStyles (), je suis également en mesure de tester le composant. La combinaison de ces HOC rend mon composant non testable.

Quelles sont les stratégies disponibles pour tester efficacement ce composant?

demo.js p >

import React from "react";
import Adapter from "enzyme-adapter-react-16";
import { configure, shallow } from "enzyme";
import Demo from "./demo";
import MUIIconButton from "@material-ui/core/IconButton";
import Tooltip from "@material-ui/core/Tooltip";

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

describe("Demo", () => {
  it("Should have a tooltip with label", () => {
    const tooltip = "My tooltip";

    const el = shallow(<Demo label={tooltip} />).dive();

    expect(el.find(Tooltip).props().title).toEqual(tooltip);
  });
});

demo.test.js

import React, { memo } from "react";
import MUIIconButton from "@material-ui/core/IconButton";
import { withStyles } from "@material-ui/core/styles";
import Tooltip from "@material-ui/core/Tooltip";
import Typography from "@material-ui/core/Typography";

const styles = () => ({
  root: {
    backgroundColor: "red"
    /* more styles... */
  }
});

const Demo = memo(({ label, classes }) => (
  <div className={classes.root}>
    <Tooltip disableFocusListener title={label}>
      <Typography>label</Typography>
    </Tooltip>
  </div>
));

export default withStyles(styles)(Demo);

Sandbox pleinement opérationnel

 Modifier 2j3o14zxy0


3 Réponses :


1
votes

Comme le suggère skyboyer, vous devez simplement exporter la fonction mémorisée. Vous pouvez importer l'exportation par défaut HOC et utiliser mount , mais vous devrez simuler l'objet classes pour correspond à la façon dont il est utilisé dans le composant.

Exemple de travail : https: // codesandbox.io/s/4r492qvoz9

components/Demo/demo.js

import React from "react";
import Adapter from "enzyme-adapter-react-16";
import { configure, shallow, mount } from "enzyme";
import { Demo } from "../demo";
import HOCDemo from "../demo";

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

const initialProps = {
  label: "My tooltip",
  classes: {
    root: "component-example"
  }
};

const shallowWrapper = shallow(<Demo {...initialProps} />);
const mountWrapper = mount(<Demo {...initialProps} />);
const mountHOComponent = mount(<HOCDemo {...initialProps} />);

describe("Demo", () => {
  afterAll(() => {
    shallowWrapper.unmount();
    mountWrapper.unmount();
  });

  it("shallowWrap renders a tooltip with label", () => {
    expect(shallowWrapper.find("WithStyles(Tooltip)").props().title).toBe(
      initialProps.label
    );
  });

  it("mountWrap renders a tooltip with label", () => {
    expect(mountWrapper.find("Tooltip").props().title).toBe(initialProps.label);
  });

  it("mountHOComponent renders a tooltip with label", () => {
    expect(mountHOComponent.find("Tooltip").props().title).toBe(
      initialProps.label
    );
  });
});

components / Demo / __ tests __ / demo.test.js si jamais besoin de voir la structure DOM , alors utilisez simplement console.log (wrapper.debug ()); code> - par exemple console.log(mountHOComponent.debug());)

import React, { memo } from "react";
import MUIIconButton from "@material-ui/core/IconButton";
import { withStyles } from "@material-ui/core/styles";
import Tooltip from "@material-ui/core/Tooltip";
import Typography from "@material-ui/core/Typography";

const styles = () => ({
  root: {
    backgroundColor: "red"
    /* more styles... */
  }
});

export const Demo = memo(({ label, classes }) => {
  return (
    <div className={classes.root}>
      <Tooltip disableFocusListener title={label}>
        <Typography>label</Typography>
      </Tooltip>
    </div>
  );
});

export default withStyles(styles)(Demo);


1 commentaires

Merci, nous avons décidé de mordre la balle et de suivre cette approche et cela fonctionne bien. Mais je ne sais toujours pas vraiment pourquoi une plongée peu profonde (el) .dive (). Dive () (Une plongée par règle HOC) n'a pas fonctionné comme prévu.




3
votes

Quand j'enroule avec un mémo, j'obtiens une forme qui ressemble à ceci

wrapper = mount(Layout)
wrapper.find('Memo(Foo)')

donc dans mon test de plaisanterie, je peux obtenir le composant interne en référençant la clé de type

XXX

C'est parfait pour les tests unitaires superficiels.

Si je montais un composant parent et que je recherchais des enfants, vous pourriez faire quelque chose comme ceci:

import MemoizedFoo from './Foo'
const Foo = MemoizedFoo.type

describe() { it() { shallow(Foo) ...etc } }


0 commentaires