question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] useSubscription onSubscriptionData triggering infinitely via tests

See original GitHub issue

Intended outcome:

I have two subscriptions, the first one gets the info from a notifications list and the second one gets the aggregate of the notifications to handle an infinite scroll

const {
    loading: loading_content,
    error: error_content,
    data: data_content,
  } = useSubscription(GET_NOTIFICATIONS_CONTENT, {
    variables: {
      offset: 0,
      limit,
      user_id,
    },
    onSubscriptionData: () => {
      setFetchingMore(false);
    },
  });

  const {
    loading: loading_aggregate,
    error: error_aggregate,
    data: data_aggregate,
  } = useSubscription(GET_NOTIFICATIONS_AGGREGATE, {
    variables: {
      user_id,
    },
  });
test("Renders notification content ", async () => {
    useGlobalWorkspace.mockImplementation(() => ({
      globalWorkspace: ADMIN_GLOBAL_WORKSPACE_RESPONSE_MOCK,
    }));
    const route = "/home";
    let history = createMemoryHistory({ initialEntries: [route] });
    renderWithRouterMatch(
      <MockProvider mocks={mocks} addTypename={true}>
        <NotificationContent/>
      </MockProvider>,
      { route, path: "/home", history }
    );
    await act(async () => {
      await new Promise(resolve => setTimeout(resolve, 0));
    });
  });

I have on my .test.js file an MockedProvider as the documentation explains, with the needed mocks for the subscriptions to work, i expect the subscriptions data to update once i indicate it on the test.

The mocks passed to the MockedProvider:

const GET_NOTIFICATIONS_CONTENT = loader(
  "graphql/Notifications/get_notifications_content.graphql"
);

export const getNotificationContentVariables = {       
  offset: 0,
  limit: 10,
  user_id: "test-uid",
};

const getNotificationContentResult = { data: NOTIFICATION_CONTENT_RESULT };

export const getNotificationContent = {
  request: {
    query: GET_NOTIFICATIONS_CONTENT,
    variables: getNotificationContentVariables,
  },
  result: getNotificationContentResult,
  newData: () => getNotificationContentResult,
};

const GET_NOTIFICATIONS_AGGREGATE = loader(
  "graphql/Notifications/get_notifications_aggregate.graphql"
);


export const getNotificationAggregateVariables = {       
  offset: 0,
  limit: 10,
  user_id: "test-uid",
};

const getNotificationAggregateResult = { data: NOTIFICATION_AGGREGATE_RESULT };

export const getNotificationAggregate = {
  request: {
    query: GET_NOTIFICATIONS_Aggregate,
    variables: getNotificationAggregateVariables,
  },
  result: getNotificationAggregateResult,
  newData: () => getNotificationAggregateResult,
};

Actual outcome:

When i have two subscriptions running at once, they return infinitely data triggering infinite renders on the component. I tested this adding a console log on an onSubscriptionData for each subscription and they return data forever. Once i comment any of the two subscriptions, they start working correctly.

How to reproduce the issue: add two subscriptions using useSubscription on a component and mock the responses on the test via MockedProvider.

NOTE

This isn’t the first time i find an issue like this, i had to do a few workarounds on other subscriptions that were alone and were showing this same behaviour, like moving state changes from the onSubscriptionData to useEffects, but this time i can’t find any way to make this work.

Related issues: #7044 #7313

Versions System: OS: Windows 10 10.0.19041 Binaries: Node: 12.16.1 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD npm: 6.13.4 - C:\Program Files\nodejs\npm.CMD Browsers: Chrome: 87.0.4280.88 Edge: Spartan (44.19041.423.0), Chromium (87.0.664.60) npmPackages: @apollo/react-hooks: ^4.0.0 => 4.0.0 @apollo/react-testing: ^4.0.0 => 4.0.0 apollo-boost: ^0.4.9 => 0.4.9 apollo-link-context: ^1.0.20 => 1.0.20 apollo-link-ws: ^1.0.20 => 1.0.20

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:13
  • Comments:16 (6 by maintainers)

github_iconTop GitHub Comments

3reactions
juandak16commented, Jan 19, 2021

I’m also experiencing this same issue and i haven’t found any docs or info on about how to test subscription with the MockedProvider or any other way to do it. It’s happening to me whenever i have 2 or more subscriptions via useSubscription hook on the same component and then i try to test it via react-testing-library.

I’m on a bit of a deadline right now

@hwillson @benjamn any help on this?

2reactions
martdavidsoncommented, Apr 20, 2021

https://github.com/martdavidson/7493-recreation

yarn install, then yarn test. You’ll see a console log of the current timestamp every 3 seconds until the global react-testing-library timeout is hit.

If you remove the useEffect in App.tsx, you’ll see that it only happens once, and never repeats, as expected.

So it sure looks like re-renders will trigger whatever is in your onSubscriptionData in tests.

Unfortunately you can’t yarn start this project - there’s no backend with real subscriptions - but in our production app the re-renders do not cause the onSubscriptionData to re-trigger, only in the tests does that happen.

Let me know if this actually demonstrates a bug, or if I’m misunderstanding things, or if you need any clarification at all on what I’m doing in the recreation.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Testing Subscriptions - Help - Apollo GraphQL
Hi there, I want to write tests to my subscriptions but I don't hace a clue on how to start, ... Using React...
Read more >
How to refetch a query when a new subscription arrives in ...
I just use subscription here as a notification trigger that tells Query to refetch. I tried both using Subscription component and ...
Read more >
@apollo/client | Yarn - Package Manager
Apollo Client is a fully-featured caching GraphQL client with integrations for React, Angular, and more. It allows you to easily build UI components...
Read more >
apollo-cache-inmemory - Awesome JS
Deprecate the onSubscriptionData callback in favor of a new onData callback ... Fix useSubscription bug in React v18 StrictMode (#9664) by @kazekyo in...
Read more >
How can I avoid "auto-update" cache when using `react-apollo ...
useSubscription <MySubscriptionUpdated>(MySubscription, { fetchPolicy: "no-cache", onSubscriptionData: async ({ client, subscriptionData: { data } }) => { if (! ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found