New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Q: Testing Relay Containers #161

Closed
devknoll opened this Issue Aug 24, 2015 · 8 comments

Comments

Projects
None yet
6 participants
@devknoll
Contributor

devknoll commented Aug 24, 2015

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?

@devknoll

This comment has been minimized.

Show comment
Hide comment
@devknoll

devknoll Aug 24, 2015

Contributor

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?

Contributor

devknoll commented Aug 24, 2015

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?

@devknoll devknoll changed the title from Q: Testing Containers to Q: Testing Relay Containers Aug 24, 2015

@devknoll

This comment has been minimized.

Show comment
Hide comment
@devknoll

devknoll Aug 24, 2015

Contributor

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 😄

Contributor

devknoll commented Aug 24, 2015

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 😄

@josephsavona

This comment has been minimized.

Show comment
Hide comment
@josephsavona

josephsavona Aug 24, 2015

Contributor

@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 ;-)

Contributor

josephsavona commented Aug 24, 2015

@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 devknoll closed this Aug 29, 2015

@adriantoine adriantoine referenced this issue Oct 9, 2015

Closed

Unit testing #1

@rterysen-openroad

This comment has been minimized.

Show comment
Hide comment
@rterysen-openroad

rterysen-openroad May 17, 2016

@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?

rterysen-openroad commented May 17, 2016

@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?

@sibelius

This comment has been minimized.

Show comment
Hide comment
@sibelius

sibelius Aug 29, 2016

Collaborator

you can create a directory mocks

and create a react-relay.js file in it

Collaborator

sibelius commented Aug 29, 2016

you can create a directory mocks

and create a react-relay.js file in it

@wbyoung

This comment has been minimized.

Show comment
Hide comment
@wbyoung

wbyoung Feb 15, 2017

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.

wbyoung commented Feb 15, 2017

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.

@emwalker

This comment has been minimized.

Show comment
Hide comment
@emwalker

emwalker Nov 2, 2017

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

emwalker commented Nov 2, 2017

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

@emwalker

This comment has been minimized.

Show comment
Hide comment
@emwalker

emwalker Jan 6, 2018

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.

emwalker commented Jan 6, 2018

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment