Home > Software design >  (Apollo client v3) useLazyQuery custom hook testing
(Apollo client v3) useLazyQuery custom hook testing

Time:05-07

I was struggling with a test issue for my custom useLazyQuery hook. My first test is passing but the second one is failing. What am doing wrong for the second test?

Here is the useLazyFetchCoin.tsx

export const useLazyFetchCoin = () => {
  const [coins, setCoins] = useState<ICoin[]>([]);

  useEffect(() => {
    const coins = localStorage.getItem('coinsInfo');
    if (coins) {
      setCoins(JSON.parse(coins));
    }
  }, []);

  const [getData, { loading, error }] = useLazyQuery(GET_COIN_PRICE_QUERY, {
    fetchPolicy: 'network-only',
    notifyOnNetworkStatusChange: true,
    onCompleted: (data) => {
      const hasSameCoin = coins.some((f) => f.id === data.markets[0]?.id);
      if (data.markets.length && !hasSameCoin) {
        const allCoins = [...coins, data.markets[0]];
        setCoins(allCoins);
        localStorage.setItem('coinsInfo', JSON.stringify(allCoins));
      } else if (data.markets.length <= 0) {
        alertNotification('Coin not found !', Notification.ERROR);
      }
      if (hasSameCoin) {
        alertNotification('This coin already exists on your list !', Notification.WARNING);
      }
    }
  });

  return { coins, setCoins, getData, loading, error };
};

Here is the test file

describe('useLazyFetchCoin custom hook', () => {
  const QueryMock = [
    {
      request: {
        query: GET_COIN_PRICE_QUERY,
        variables: { code: 'BNB' }
      },
      result: {
        data: {
          markets: [
            {
              id: 'binance_bnb_eur',
              baseSymbol: 'BNB',
              ticker: {
                lastPrice: '414.90000000'
              }
            }
          ]
        }
      }
    }
  ];

  const QueryWrongCodeMock = [
    {
      request: {
        query: GET_COIN_PRICE_QUERY,
        variables: { code: 'asd' }
      },
      result: {
        data: {
          markets: []
        }
      }
    }
  ];

  function getHookWrapper(mocks: any, code: string) {
    const wrapper = ({ children }: any) => (
      <MockedProvider mocks={mocks} addTypename={false}>
        {children}
      </MockedProvider>
    );
    const { result, waitForNextUpdate } = renderHook(() => useLazyFetchCoin(), {
      wrapper
    });

    expect(typeof result.current.coins).toBe('object');
    expect(result.current.loading).toBeFalsy();
    expect(result.current.error).toBeUndefined();

    // call the lazy function
    act(() => {
      result.current.getData({
        variables: { code }
      });
    });

    return { result, waitForNextUpdate };
  }

  it('should return an array of coins', async () => {
    // Working correctly
    const { result, waitForNextUpdate } = getHookWrapper(QueryMock, 'BNB');

    await waitForNextUpdate();

    expect(result.current.loading).toBeFalsy();
    expect(result.current.coins[0]).toEqual({
      id: 'binance_bnb_eur',
      baseSymbol: 'BNB',
      ticker: {
        lastPrice: '414.90000000'
      }
    });
  });

  it('should return an empty array when requesting a wrong code', async () => {
    // Not working
    const { result, waitForNextUpdate } = getHookWrapper(QueryWrongCodeMock, 'asd');

    await waitForNextUpdate();

    expect(result.current.loading).toBeFalsy();
    expect(result.current.coins[0]).toEqual([]);
  });
});

I got this error message for the second test.

Expected: []
Received: {"baseSymbol": "BNB", "id": "binance_bnb_eur", "ticker": {"lastPrice": "414.90000000"}}

I don't get it because I'm using different queries for each test.

Also, the second test should receive an empty array when you pass a wrong code such as 'asd'.

How can write a proper test for it?

CodePudding user response:

I fixed the problem. When I was changing the order test, It worked correctly.

I added a clear mock function for it.

clear mock

  • Related