Relay: Q: Testing Relay Containers

Created on 24 Aug 2015  路  8Comments  路  Source: facebook/relay

Error: Invariant Violation: RelayContainer: `Relay(Dashboard)` was rendered
without a valid route. Make sure the route is valid, and make sure that it is
correctly set on the parent component's context (e.g. using <RelayRootContainer>).

What's the preferred way to unit test Relay container components?

Most helpful comment

Using Relay Modern, Jest and Enzyme together with the approach above, I was running into global side effects arising from redefining react-relay.js in the __mocks__ subdirectory of a component directory. I was able to get around this by using a different approach, placing this near the top of the test file, before the component to be tested:

jest.mock('react-relay', () => ({createFragmentContainer: component => component}))

// eslint-disable-next-line import/first
import SomeComponent from './index'

After that I was able to write the usual jest/enzyme tests.

All 8 comments

Relay has a RelayTestUtils helper that's used internally for testing containers. Would it make sense to expose some of this for Relay clients to use?

Just in case it helps anyone else: My current workflow with Jest is to define __mocks__/react-relay.js with:

var Relay = require.requireActual('react-relay');

module.exports = {
  QL: Relay.QL,
  Mutation: Relay.Mutation,
  Route: Relay.Route,
  createContainer: (component) => component,
};

Then a component can be tested with:

/* ... */

TestUtils.renderIntoDocument(
  <Dashboard {...fixtures} />
);

/* ... */

where fixtures is an object matching the expected shape of the GraphQL response/fragments. As a side note, it'd be awesome if fixtures like this could be automatically generated, given that we have a schema :smile:

@devknoll: That's a pretty solid solution to get tests working now. Relay will pass through any props whose name matches a fragments key as-is. You'll get a warning about fake data but this is safe to ignore in tests.

Most of RelayTestUtils is intended for internal tests (and we wouldn't want people depending on these APIs) but we would definitely accept PRs to build a public TestUtils-esque API for Relay. RelayTestUtils.createRenderer() is a good place to start ;-)

@devknoll Does mocks live within Jest's tests directory.

Is there anywhere I can read about this or see a example in a little more detail?

you can create a directory mocks

and create a react-relay.js file in it

If anyone else comes across this who is looking for a non-jest solution, replacing Relay.createContainer with a custom version that doesn't actually create the container may be helpful.

Relay.createContainer = ((create) => {
  let disabled = 0;

  const replacement = (Component, ...args) => {
    const Container = create(Component, ...args);
    const Wrapper = (...args) => {
      if (disabled) { return new Component(...args); }
      else { return new Container(...args); }
    };

    Object.assign(Wrapper, Container);

    // allow context population when possible, but don't validate any props
    Wrapper.contextTypes = _.mapValues(
      Container.contextTypes || {}, _.constant(React.PropTypes.any)
    );

    return Wrapper;
  };

  replacement._real = create;
  replacement.disable = () => { disabled++; };
  replacement.enable = () => { disabled--; };

  return replacement;
})(Relay.createContainer._real || Relay.createContainer);

A more complete mocha/enzyme example can be found here.

What is a recommended approach to testing client-side mutation and subscription updater code in an external project?

Using Relay Modern, Jest and Enzyme together with the approach above, I was running into global side effects arising from redefining react-relay.js in the __mocks__ subdirectory of a component directory. I was able to get around this by using a different approach, placing this near the top of the test file, before the component to be tested:

jest.mock('react-relay', () => ({createFragmentContainer: component => component}))

// eslint-disable-next-line import/first
import SomeComponent from './index'

After that I was able to write the usual jest/enzyme tests.

Was this page helpful?
0 / 5 - 0 ratings