enzyme: wrappedComponent doesn't actually pass context values down in tests

Given the following:

import { shallow } from 'enzyme';
import React, { Component } from 'react';
import PropTypes from 'prop-types';

const FooContext = React.createContext();

class Foo extends Component {
  static contextType = FooContext;

  render() {
    const { value1, value2 } = this.context;
    return (<div>
      <span>Value 1: {value1}</span>
      <span>Value 2: {value2}</span>
    </div>);
  }
}

const someValues = { value1: '1', value2: '2' };

function FooProvider({ children }) {
  return (<FooContext.Provider values={someValues}>
    {children}
  </FooContext.Provider>);
}

FooProvider.propTypes = {
  children: PropTypes.node
};

describe('Foo', () => {
  let spans;
  beforeAll(() => {
    const wrapper = shallow(<Foo/>, { wrappingComponent: FooProvider });
    spans = wrapper.find('span');
  });
  it('the first is someValues.value1', () => {
    const first = spans.at(0);
    expect(first).toExist();
    expect(first).toHaveText(`Value 1: ${someValues.value1}`);
  });
  it('the second is someValues.value2', () => {
    const second = spans.at(1);
    expect(second).toExist();
    expect(second).toHaveText(`Value 2: ${someValues.value2}`);
  });
});

Current behavior

Foo ✕ the first is someValues.value1 (17ms) ✕ the second is someValues.value2 (13ms)

● Foo › the first is someValues.value1

Expected <span> components text to match (using ===), but it did not.
Expected HTML: "Value 1: 1"
Actual HTML: "Value 1: "

  49 |     const first = spans.at(0);
  50 |     expect(first).toExist();
> 51 |     expect(first).toHaveText(`Value 1: ${someValues.value1}`);
     |                   ^
  52 |   });
  53 |   it('the second is someValues.value2', () => {
  54 |     const second = spans.at(1);

  at Object.toHaveText (app/javascript/tests/temp/foo.test.jsx:51:19)

● Foo › the second is someValues.value2

Expected <span> components text to match (using ===), but it did not.
Expected HTML: "Value 2: 2"
Actual HTML: "Value 2: "

  54 |     const second = spans.at(1);
  55 |     expect(second).toExist();
> 56 |     expect(second).toHaveText(`Value 2: ${someValues.value2}`);
     |                    ^
  57 |   });
  58 | });
  59 | 

Expected behavior

The two tests pass. It seems like the values set into the context in FooProvider don’t actually get passed to Foo

Your environment

node: 12.4.0

API

  • shallow
  • mount
  • render

Version

library version
enzyme 3.10.0
react 16.8.6
react-dom 16.8.6
react-test-renderer 16.8.6
adapter (below) 1.14.0

Adapter

  • enzyme-adapter-react-16
  • enzyme-adapter-react-16.3
  • enzyme-adapter-react-16.2
  • enzyme-adapter-react-16.1
  • enzyme-adapter-react-15
  • enzyme-adapter-react-15.4
  • enzyme-adapter-react-14
  • enzyme-adapter-react-13
  • enzyme-adapter-react-helper
  • others ( )

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 1
  • Comments: 19 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Is there an ETA on that?

Hi all, I added the patch posted by @forivall (thanks!) and a simple test case in #2507, please have a look. @ljharb I have no clue on how to patch react-test-renderer, I manually patched the locally installed shallow-renderer as mentioned by @forivall, can you assist here?

I created module for workaround https://www.npmjs.com/package/shallow-with-context. The module works well in our projects.

awesome. i’ll submit a PR when i have a few more extra cycles in the next few days (hopefully i remember).

More than happy to help with the final parts of the fix once the tests are good (and failing)

const wrapper = render(<FooContext.Provider values={someValues}>

That should be value, no?

My workaround is to add the provider in the test:

const wrapper = render(<FooContext.Provider values={someValues}>
    <Foo/>
  </FooContext.Provider>);

and changing it to a render from shallow, which introduces some other fun to work through