react-apollo icon indicating copy to clipboard operation
react-apollo copied to clipboard

MockedProvider newData() is always being returned on first query

Open jfrense opened this issue 5 years ago • 2 comments

Intended outcome: When a Query with the same variables is executed a second time against a MockedProvider, NewData() will return new data results. This was the outcome that was happening before doing the apollo hook migration.

Actual outcome: After the Apollo hook migration, When the first time Query is executed against MockedProvider, it returns the results of newData() instead of the results data first defined in the mocked provider.

How to reproduce the issue:

Invite.tsx

import React, { Component } from 'react';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';


export const GET_INVITE = gql`
  query Invite($inviteToken: String!, $inviteContext: InviteContext!) {
    invite(inviteToken: $inviteToken, inviteContext: $inviteContext) {
      email
      isExpired
      firstName
      lastName
      uuid
      inviteToken
    }
  }
`;

interface Variables {
  inviteToken: string;
  inviteContext: string;
}

interface matchParams {
  token: string;
}

interface inviteProps {
  context: InviteContext;
}

class Invite extends Component<RouteComponentProps<matchParams> & inviteProps> {

     render(): JSX.Element {
return (
 <div className="inviteContainer">

        <Query<Data, Variables>
          query={GET_INVITE}
          variables={{ inviteToken: token, inviteContext: context }}
        >
          {({ loading, error, data, refetch, networkStatus }) => {

               if (data.invite.isExpired)
              return (
                <div
                  data-testid="expiredInvite"
                  className="inviteFormAnimation"
                >
                  <Lottie options={invalidInviteOptions} />
                  <Typography.Title className="animationMessage" level={3}>
                    Oops!...Looks like this Invite expired or was already used
                  </Typography.Title>

                  <Typography.Title className="animationMessage" level={4}>
                    If you think you recieved this in error, Send us an email to
                    request a new one
                  </Typography.Title>
               
                </div>
              );

               return (
                   <div>
              <UserSignUpForm
                firstName={data ? data.invite.firstName : ''}
                lastName={data ? data.invite.lastName : ''}
                email={data ? data.invite.email : ''}
                refetch={refetch}
                submitForm={this.handleSubmit}
                subTitle={this.handleFormSubtitle(this.props.context)}
                countryCode={this.handleCountryCode(this.props.context)}
                data-testid="signupform"
              />
              <Button onClick={() => refetch()}>Create my account</Button>
              </div>
            );


          }
            }
       
        </Query>
      </div>
    );

}
}
export default Invite;

Invite.test.tsx

test('should display expired invite animation when user tries creates account when invite is expired', async () => {
  const validThenExpiredInviteMocks = [
    {
      request: {
        query: GET_INVITE,
        variables: {
          inviteToken: '1234',
          inviteContext: 'DESIGNER_BUSINESS'
        }
      },
      result: {
        data: {
          invite: {
            email: '[email protected]',
            firstName: 'Jake',
            isExpired: false,
            lastName: null,
            uuid: '123ff43',
            inviteToken: '1234'
          }
        }
      },
      newData: () => ({
        data: {
          invite: {
            email: '[email protected]',
            firstName: 'Jake',
            isExpired: true,
            lastName: null,
            uuid: '123ff43',
            inviteToken: '1234'
          }
        }
      })
    }
  ];

  
  const { getByTestId, getByText, getByLabelText, debug } = render(
    <MockedProvider mocks={validThenExpiredInviteMocks} addTypename={false}>
      <Invite
        context={InviteContext.DESIGNER_BUSINESS}
        match={matchMock}
        location={mock}
        history={mock}
      />
    </MockedProvider>
  );

await act(async () => {
    await wait();
  });

  fireEvent.change(getByLabelText('lastname-input'), {
    target: { value: 'mylastname' }
  });
  fireEvent.change(getByLabelText('password-input'), {
    target: { value: 'Som3randompassword' }
  });
  fireEvent.change(getByLabelText('passwordconfirm-input'), {
    target: { value: 'Som3randompassword' }
  });

  fireEvent.change(getByLabelText('phone-input'), {
    target: { value: '1234567890' }
  });

  fireEvent.submit(getByText('Create my account'));

  await act(async () => {
    await wait();
  });
  expect(getByTestId('expiredInvite')).toHaveTextContent(
    'Oops!...Looks like this Invite expired or was already used'
  );
});

^^ The test fails because when it is trying to change the lastname input it can't find it because the expired Invite animation is displayed. This tells me that newData() is getting returned in the mockedProvider on the initial first Query instead of the second time the Query is executed when the 'create my 'account' button is clicked.

I also checked to see if the component was getting rendered twice for some reason but via print statements I could see it only being rendered once on the initial render.

Version

"dependencies": { "react": "^16.12.0", "react-apollo": "^3.1.3", "react-dom": "^16.12.0", "react-scripts": "^3.2.0", ... }

"devDependencies": { "@apollo/react-testing": "^3.1.3", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.4.0", ... }

jfrense avatar Jan 11 '20 20:01 jfrense

Any update on this?

HugoLiconV avatar Jun 16 '20 19:06 HugoLiconV

having the same problem. any solutions?

hyasynthesized avatar Jul 03 '20 16:07 hyasynthesized