React-apollo: MockedProvider with Enzyme & Jest in React Native doesn't return the value

Created on 30 May 2018  路  8Comments  路  Source: apollographql/react-apollo

Intended outcome:
Using Enzyme & Jest in React Native.
Test will render the component, pass in the result of the query, and it will be possible to make assertions about component's content.

Actual outcome:
The query is stuck in loading state (console.log that prints the query is called only once), and the wrapper never re-renders even when calling wrapper.update();. Since component doesn't render at all when the query result isn't yet ready, the wrapper is always empty. If I add await new Promise(resolve => setTimeout(resolve)); (as in the example below), it times out after 5 seconds.
Not sure if the problem is React Native specific, I haven't tried it in plain React yet.

How to reproduce the issue:

const DictQuery = gql`
  query {
    dictionaries {
      test {
        id
        value
      }
    }
  }
`;

const GraphQLMocks = [
  {
    request: { query: DictQuery },
    result: {
      data: {
        dictionaries: {
          test: [
            {
              id: '11',
              value: 'Value 1'
            },
            {
              id: '12',
              value: 'Value 2'
            }
          ]
        }
      }
    }
  }
];

it('tests it', async () => {
  const wrapper = mount(
      <MockedProvider removeTypename mocks={GraphQLMocks}>
        <MyScreen />
      </MockedProvider>
  );

  await new Promise(resolve => setTimeout(resolve));
  wrapper.update();

  expect(wrapper.html()).to.contain('Hello');
});

@graphql(DictQuery, {
  name: 'dictionaries',
  options: () => ({
    notifyOnNetworkStatusChange: true
  })
})
class MyScreen extends React.Component<Props, State> {
  render() {
    const { dictionaries } = this.props;
    console.log('dictionaries', dictionaries);
    if (!dictionaries || dictionaries.loading) {
      return null;
    }
    return (<p>Hello</p>);
  }
}

Version

Most helpful comment

Running component.update(); fixed for me.

All 8 comments

+1 Same issue with plain React

Facing same issue with react-native

it("should show error UI",  () => {
  const kycStatus = -1;
  const panNumber = "CNIPL3293D";
  const mockedData = {
    accounts: [
      {
        __typename: "AccountNode",
        name,
        kycStatus,
        panNumber
      }
    ]
  };

  const mocks = {
    request: {query: PAN_REGISTRATION_ACCOUNTS_QUERY},
    result: {data: mockedData}
  };

  const component =  mount(
    <MockedProvider addTypename={false} mocks={[mocks]}>
      <RegistrationPanContainer />
    </MockedProvider>
  );

  const promise1  = new Promise((resolve) => setTimeout(resolve("Test"), 2));

  promise1
    .then(() => {
      component.update();      
      console.log("tree", component.debug());
    })
    .catch((error) => {
      console.log("error");
    })
  // console.log("Component", component);
});

Above gives me following output:-

      tree <MockedProvider addTypename={false} mocks={{...}}>
        <ApolloProvider client={{...}}>
          <Apollo(RegistrationPanContainer)>
            <Query displayName="Apollo(RegistrationPanContainer)" skip={false} query={{...}} warnUnhandledError={true}>
              <RegistrationPanContainer loadingAccounts={true} errorAccounts={[undefined]} accounts={[undefined]} />
            </Query>
          </Apollo(RegistrationPanContainer)>
        </ApolloProvider>
      </MockedProvider>

I'm having the same issue with plain React. Data is clearly coming back but Enzyme isn't re-rendering past the loading state.

Running component.update(); fixed for me.

Thanks @stolinski. Calling update() worked for me too in React Native.

Is this closeable or does someone want to propose a PR with a change?

@rosskevin I have the same issue with React

describe('[Container] ClientTable', () => {
  test('should be connected to store', async () => {
    const clients = [{ id: '007', name: 'Vincent' }];
    const query = loader('./getClients.graphql');
    const mocks = [
      {
        request: { query },
        result: {
          data: {
            clients,
          },
        },
      },
    ];

    const container = mount(
      <MockedProvider mocks={mocks} addTypename={false}>
        <ClientTableContainer />
      </MockedProvider>,
    );

    await new Promise((resolve: () => void): NodeJS.Timeout => setTimeout(resolve, 0));
    container.update();

    expect(container.find<ClientTableProps>(ClientTable).props().clients).toEqual(clients);
  });
});

My container is like that

export default graphql(loader('./getClients.graphql'), {
  props: (props: OptionProps<Props, GetClientsProps>): GetClientsProps => ({
    clients: (props.data && props.data.clients) || [],
  }),
})(ClientTable);

I discover that, if I change for this

export default graphql(loader('./getClients.graphql'), {
  props: (props: OptionProps<Props, GetClientsProps>): GetClientsProps => (console.log(''), {
    clients: (props.data && props.data.clients) || [],
  }),
})(ClientTable);

It works.
I have no explanation.

I believe this is closable - thanks!

Was this page helpful?
0 / 5 - 0 ratings