React-apollo: Unable to get the data from MockedProvider. It only returns error and loading state

Created on 30 Jan 2019  路  5Comments  路  Source: apollographql/react-apollo

Intended outcome:
All I need is to know how to render the data I need to test the component properly.

Actual outcome:
For now I can only test the component on error and loading state but not when it loads data.

How to reproduce the issue:
After I added the tests I run npm run test SoftlayerCancellationRequests-test and it returns error and loading state but never set the data I placed in the mock.

Version

This is the code I have for the component:

import React from 'react';
import PropTypes from 'prop-types';
import { flatMap } from 'lodash';
import { Query } from 'react-apollo';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { translate } from 'react-i18next';
import GET_ALL_CANCELLATION_REQUESTS from './GraphQLQuery';
import { updatePagination } from '../../actions/cancellations';
import ErrorState from '../../../../global/components/ErrorState';
import CancellationsTable from '../../components/TableIndex';

const SoftLayerCancellationRequests = ({
  softlayerAccountId,
  pagination,
  updatePaginationHandler,
  t,
}) => (
  <Query
    query={GET_ALL_CANCELLATION_REQUESTS}
    variables={{
      limit: pagination.pageSize,
      offset: (pagination.page - 1) * pagination.pageSize,
    }}
    context={{ uri: `/graphql?ims_account=${softlayerAccountId}` }}
  >
    {({ loading, error, data }) => {
      if (error) {
        return (
          <div className="empty-state-table">
            <ErrorState description={t('cancellations.errorMsg')} />
          </div>
        );
      }

      if (loading) {
        return <DataTableSkeleton compact />;
      }

      let tableRowsModel;
      let totalCount;
      if (data && data.GetBillingItemCancellationRequests) {
        ({ totalCount } = data.GetBillingItemCancellationRequests);

        const tableRows = flatMap(
          data.GetBillingItemCancellationRequests.orders,
          'items',
        );

        const tableRowsItems = tableRows.map(tableRow => {
          const {
            billingItem: { id, ...restItem },
            ...rest
          } = tableRow;
          return { ...rest, ...restItem };
        });

        if (data.GetBillingItemCancellationRequests.orders) {
          tableRowsModel = data.GetBillingItemCancellationRequests.orders.map(
            row => ({
              id: `${row.id}`,
              device: row.account,
              itemsCancelled: row.itemCount,
              requestDate: momentDateFormatter(row.createDate),
              status: row.status.name,
              requestedBy: `${row.user.firstName} ${row.user.lastName}`,
              serviceType: 'services',
              billingItems: tableRowsItems,
            }),
          );
        } else {
          tableRowsModel = [];
        }
      }

      return (
        <CancellationsTable
          pagination={{ ...pagination, totalItems: totalCount }}
          updatePagination={updatePaginationHandler}
          tableRows={
            data && data.GetBillingItemCancellationRequests.orders
              ? tableRowsModel
              : []
          }
        />
      );
    }}
  </Query>
);

SoftLayerCancellationRequests.propTypes = {
  t: PropTypes.func.isRequired,
  softlayerAccountId: PropTypes.string.isRequired,
  updatePaginationHandler: PropTypes.func.isRequired,
  pagination: PropTypes.shape({
    totalItems: PropTypes.number,
    page: PropTypes.number,
    pageSize: PropTypes.number,
    pageSizes: PropTypes.arrayOf(PropTypes.number),
  }).isRequired,
};

export default compose(
  connect(
    store => ({
      softlayerAccountId: store.global.softlayerAccountId,
      pagination: store.cancellations.pagination,
    }),
    dispatch => ({
      updatePaginationHandler: pagination => {
        dispatch(updatePagination(pagination));
      },
    }),
  ),
  translate(),
)(SoftLayerCancellationRequests);

And this is the test:

import React from 'react';
import { MockedProvider } from 'react-apollo/test-utils';
import { mount, shallow } from 'enzyme';
import { Provider as ReduxProvider } from 'react-redux';
import SoftLayerCancellationRequests from '../../containers/GetAllCancellationRequests/SoftLayerCancellationRequests';
import createMockStore from '../../../../utils/createMockStore';

import store from '../../../../redux/store';

import mocks from '../../__fixtures__/other-services-mock';

jest.mock('react-i18next', () => ({
  // this mock makes sure any components using the translate HoC receive the t function as a prop
  translate: () => Component => {
    Component.defaultProps = { ...Component.defaultProps, t: key => key }; // eslint-disable-line
    return Component;
  },
}));

describe('Container to test: SoftLayerCancellationRequests', () => {
  let props;

  beforeEach(() => {
    props = {
      t: jest.fn(() => k => k),
      updatePaginationHandler: jest.fn(() => k => k),
      softlayerAccountId: 123,
      pagination: {
        totalItems: 26,
        page: 1,
        pageSize: 10,
        pageSizes: [10, 25, 50],
      },
    };
  });

  it('should render normally', () => {
    expect.assertions(2);
    const wrapper = shallow(
      <MockedProvider mocks={mocks}>
        <SoftLayerCancellationRequests store={store} {...props} />
      </MockedProvider>,
    );

    expect(wrapper.find('Connect(SoftLayerCancellationRequests)')).toHaveLength(
      1,
    );
    expect(wrapper).toMatchSnapshot();
  });

  it('should render loading state initially', () => {
    expect.assertions(1);
    const wrapper = mount(
      <MockedProvider mocks={[]}>
        <ReduxProvider store={store}>
          <SoftLayerCancellationRequests />
        </ReduxProvider>
      </MockedProvider>,
    );

    expect(wrapper.find('DataTableSkeleton')).toHaveLength(1);
  });

  it('should render data', async () => {
    const wrapper = mount(
      <MockedProvider
        mocks={mocks.filter(mock => mock.id === 'get-cancellations-custom')}
      >
        <SoftLayerCancellationRequests
          {...props}
          store={createMockStore({
            global: {
              accountGuid: 'abcd-1234',
              softlayerAccountId: '1234',
              hiddenFeatures: [],
            },
          })}
        />
      </MockedProvider>,
    );

    // Wait for the query mock to finish so we can exit the loading state
    await new Promise(resolve => setTimeout(resolve));
    await wrapper.update();

    expect(wrapper.find('Connect(SoftLayerCancellationRequests)')).toHaveLength(
      1,
    );
  });

  it('should not render any data', () => {
    mount(
      <MockedProvider mocks={[]}>
        <ReduxProvider store={store}>
          <SoftLayerCancellationRequests />
        </ReduxProvider>
      </MockedProvider>,
    );
  });

  it('should check for defined components', () => {
    const wrapper = mount(
      <MockedProvider mocks={mocks}>
        <ReduxProvider store={store}>
          <SoftLayerCancellationRequests {...props} />
        </ReduxProvider>
      </MockedProvider>,
    );

    wrapper.update();

    expect(
      wrapper.find('SoftLayerCancellationRequests').props()
        .updatePaginationHandler,
    ).toBeDefined();
  });

  it('should trigger actions handlers', () => {
    const wrapper = mount(
      <MockedProvider mocks={mocks}>
        <ReduxProvider store={store}>
          <SoftLayerCancellationRequests {...props} />
        </ReduxProvider>
      </MockedProvider>,
    );

    wrapper
      .find('SoftLayerCancellationRequests')
      .props()
      .updatePaginationHandler();
  });
});

Here is the mock:

import GET_ALL_CANCELLATION_REQUESTS from '../containers/GetAllCancellationRequests/GraphQLQuery';

const mocks = [
  {
    id: 'get-cancellations-custom',
    request: {
      query: GET_ALL_CANCELLATION_REQUESTS,
    },
    result: {
      data: {
        GetBillingItemCancellationRequests: {
          itemsCount: 2,
          orders: [
            {
              accountId: null,
              billingCancelReasonId: null,
              createDate: '2018-09-18T13:28:47-05:00',
              id: 17195077,
              modifyDate: '2018-09-18T13:28:48-05:00',
              notes: null,
              statusId: null,
              ticketId: 65626859,
              account: null,
              items: [
                {
                  id: 11609241,
                  billingItemId: 346453333,
                  cancellationRequestId: 17195077,
                  immediateCancellationFlag: true,
                  scheduledCancellationDate: null,
                  serviceReclaimStatusCode: 'COMPLETE',
                  billingItem: {
                    id: 346453333,
                    recurringFee: 3,
                    description: 'Symantec Identity Protection',
                    cancellationDate: '2018-09-18T13:28:48-05:00',
                    domainName: null,
                    hostName: null,
                    __typename: 'SoftLayer_Billing_Item',
                  },
                  __typename:
                    'SoftLayer_Billing_Item_Cancellation_Request_Item',
                },
              ],
              status: {
                description: null,
                id: 2,
                keyName: 'COMPLETE',
                name: 'Complete',
                __typename:
                  'SoftLayer_Billing_Item_Cancellation_Request_Status',
              },
              ticket: {
                accountId: null,
                createDate: null,
                modifyDate: null,
                id: 65626859,
                title: null,
                assignedUserId: 364087,
                serviceProviderResourceId: '65626859',
                attachedHardware: [],
                __typename: 'SoftLayer_Ticket',
              },
              user: {
                firstName: null,
                lastName: null,
                __typename: 'SoftLayer_User_Customer',
              },
              itemCount: 1,
              __typename: 'SoftLayer_Billing_Item_Cancellation_Request',
            },
            {
              accountId: null,
              billingCancelReasonId: null,
              createDate: '2018-09-10T13:11:05-05:00',
              id: 17183859,
              modifyDate: '2018-09-10T13:11:06-05:00',
              notes: null,
              statusId: null,
              ticketId: 65169379,
              account: null,
              items: [
                {
                  id: 11598021,
                  billingItemId: 343271759,
                  cancellationRequestId: 17183859,
                  immediateCancellationFlag: true,
                  scheduledCancellationDate: null,
                  serviceReclaimStatusCode: 'COMPLETE',
                  billingItem: {
                    id: 343271759,
                    recurringFee: 3,
                    description: 'Symantec Identity Protection',
                    cancellationDate: '2018-09-10T13:11:06-05:00',
                    domainName: null,
                    hostName: null,
                    __typename: 'SoftLayer_Billing_Item',
                  },
                  __typename:
                    'SoftLayer_Billing_Item_Cancellation_Request_Item',
                },
              ],
              status: {
                description: null,
                id: 2,
                keyName: 'COMPLETE',
                name: 'Complete',
                __typename:
                  'SoftLayer_Billing_Item_Cancellation_Request_Status',
              },
              ticket: {
                accountId: null,
                createDate: null,
                modifyDate: null,
                id: 65169379,
                title: null,
                assignedUserId: 120878,
                serviceProviderResourceId: '65169379',
                attachedHardware: [],
                __typename: 'SoftLayer_Ticket',
              },
              user: {
                firstName: null,
                lastName: null,
                __typename: 'SoftLayer_User_Customer',
              },
              itemCount: 1,
              __typename: 'SoftLayer_Billing_Item_Cancellation_Request',
            },
          ],
        },
      },
    },
  },
  {
    id: 'get-cancellations-default',
    request: {
      query: GET_ALL_CANCELLATION_REQUESTS,
      variables: {
        limit: 25,
        offset: 1,
      },
    },
    result: {
      data: {
        GetBillingItemCancellationRequests: {
          itemsCount: 0,
          orders: [],
        },
      },
    },
  },
  {
    id: 'get-cancellations-error',
    request: {
      query: GET_ALL_CANCELLATION_REQUESTS,
      variables: {
        limit: 25,
        offset: 1,
      },
    },
    result: {
      data: null,
    },
  },
];

export default mocks;

Most helpful comment

I had the same issue as @maketroli and addTypename={false} helped me as well. I think MockedProvided should not silently fail in this case without data and error.

All 5 comments

It was just to add addTypename={false} and add proper variables. Sorry.

@maketroli What variables, please? ran into the same error.

I had the same issue as @maketroli and addTypename={false} helped me as well. I think MockedProvided should not silently fail in this case without data and error.

I added addTypename and my loading changes from true to false but I get no data and no error

Neither do I, addTypename={false} and all correct props and I receive no error no response

Was this page helpful?
0 / 5 - 0 ratings