Enzyme: Why is `.wrap()` not included in the documentation?

Created on 1 Oct 2019  路  14Comments  路  Source: enzymejs/enzyme

Sorry for not following the template, but it is a simple request.

Why is .wrap() not included in the documentation?

As you can see here #919 at least more 6 people found this method useful. Just for completion it should be in the docs. Even if a note is included against the use of it and a suggestion of how to better write the component.

The author suggested to write the PR, I put myself available to do the same.

My use case

My use case is a HOC <Flow> that receives the content component <Step> as a prop. The component <Container>, which renders this HOC, renders the <Step> conditionally based on the current step of a specific flow. I'm using useMemo() to render this component inside the <Container> and that's why I need .wrap() to wrap the <Step> passed as a prop to <Flow>.

I could use a separate function to conditionally render and return <Step>, but this would obscure the code and have the same behavior: this function would be wrapped in a useMemo() and passed as a prop to <Flow>.

feature request help wanted

All 14 comments

Indeed, see https://github.com/airbnb/enzyme/issues/919#issuecomment-297756797 and #920.

It is intentionally undocumented.

I鈥檓 not clear tho on why you need wrap. Can you share some code?

This is a simplified version of the code, but the structure is the basically the same.

I used the same names as the example I gave above, so you can follow that to understand what is going on below if needed.

import React, { useState, useMemo } from 'react';
import Flow from 'components/Flow';
import FlowData from 'components/FlowData';
import { statuses } from 'lib/ducks/meta';

import ChoosePathStep from './steps/ChoosePathStep';
import IssuesStep from './steps/IssuesStep';
import UploadingStep from './steps/UploadingStep';

const Container = ({ uploadStatus }) => {
  const [step, setStep] = useState(() => ChoosePathStep);

  let Step = step;
  if (uploadStatus === statuses.LOADING) {
    Step = UploadingStep;
  } else if (uploadStatus === statuses.FAILURE) {
    Step = IssuesStep;
  }

  const MountedStep = useMemo(() => (
    <Step
      me={me}
      setStep={setStep}
    />
  ), [me, setStep]);

  return (
    <>
      <FlowData
        collapseContentGutter
        rounderBorders
        editable
      />
      <Flow
        blankContent={MountedStep}
      />
    </>
  );
};

export default Container;

sorry, i meant #920 :-)

Can you also share your test code that uses wrap (or doesn't, and doesn't work)?

This is working (simplified/mocked version)

import { shallow } from 'enzyme';
import Flow from 'components/Flow';
import Container from './Container';

import ChoosePathStep from './steps/ChoosePathStep';

describe('Flow', () => {
  it('Renders initial step', () => {
    const wrapper = shallow(<Container />);
    const step = wrapper.wrap(wrapper.find(Flow).prop('blankContent'));
    expect(step.is(ChoosePathStep)).toBe(true);
  });
});

If I change wrapper.wrap() for shallow(), it doesn't work, I don't know why...

const Step = () => wrapper.find(Flow).prop('blankContent');
const step = shallow(<Step />);

Nice, it works! I should have tried with a function...

Why would you say this way is preferable instead of using .wrap()?

Mainly because wrap isn't intended to be used externally.

A better future enzyme addition would be something like wrapProp('blankContent') that did this for you.

Right.
Yes, that would be good, make it clear how to deal with this scenario.

I took a look into the code, this is quick piece I wrote. I can dive deeper to include this method if it sounds interesting to you.

  wrapProp(prop) {
    if (!prop || typeof prop !== 'string') {
      throw new TypeError('ReactWrapper::wrapProp() expects a string as first argument');
    }
    return this.wrap(this.prop(prop));
  }

@jpenna sure, why not :-) can you make a PR to add that (with docs and tests) to both shallow and mount? Please also look to renderProp and invoke for the prop name validations I'd expect.

Cool! I'll work on this this weekend then!

@ljharb Man, I'm getting a lot of lint errors on the Master branch when I run npm test with React 16. React 15 went fine.

npm run react 16
npm run build
npm test

Just a sample below:

react/destructuring-assignment
  3483:26  warning  Must use destructuring state assignment                                                                                                                                                                                                                                                                      react/destructuring-assignment
  3513:38  warning  Must use destructuring state assignment                                                                                                                                                                                                                                                                      react/destructuring-assignment
  3513:38  warning  Use callback in setState when referencing the previous state    

.../enzyme/packages/enzyme-test-suite/test/shared/methods/setProps.jsx
  260:9   error  componentWillReceiveProps is deprecated since React 16.9.0, use UNSAFE_componentWillReceiveProps instead, see https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components  react/no-deprecated

Go ahead and ignore those for your PR; any failures on master, I鈥檒l take care of :-)

@ljharb Hey man! Did you see the PR?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

heikkimu picture heikkimu  路  3Comments

mattkauffman23 picture mattkauffman23  路  3Comments

timhonders picture timhonders  路  3Comments

amcmillan01 picture amcmillan01  路  3Comments

benadamstyles picture benadamstyles  路  3Comments