1 import type { PropsWithChildren } from 'react';
3 import { renderHook } from '@testing-library/react-hooks';
4 import type { MockedFunction } from 'vitest';
6 import type { WasmApiExchangeRateData, WasmExchangeRateClient } from '@proton/andromeda';
7 import { ProtonStoreProvider } from '@proton/redux-shared-store';
8 import { SECOND } from '@proton/shared/lib/constants';
9 import { getMockedApi } from '@proton/wallet/tests';
11 import { extendStore, setupStore } from '../store';
12 import { useGetExchangeRate } from './useExchangeRate';
14 describe('useExchangeRate', () => {
15 let mockedGetExchangeRate: MockedFunction<WasmExchangeRateClient['getExchangeRate']>;
17 const exchangeRateEur: WasmApiExchangeRateData['Data'] = {
21 ExchangeRateTime: '0',
26 const exchangeRateUsd: WasmApiExchangeRateData['Data'] = {
30 ExchangeRateTime: '0',
35 describe('useGetExchangeRate', () => {
37 vitest.useFakeTimers();
38 vitest.setSystemTime(new Date(1713516247000));
40 mockedGetExchangeRate = vi
42 .mockResolvedValueOnce({ Data: exchangeRateEur })
43 .mockResolvedValueOnce({ Data: exchangeRateUsd });
46 walletApi: getMockedApi({
48 getExchangeRate: mockedGetExchangeRate,
55 vitest.useRealTimers();
58 it('should cache result for each fiat', async () => {
59 const store = setupStore();
61 function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element {
62 return <ProtonStoreProvider store={store}>{children}</ProtonStoreProvider>;
65 const { result } = renderHook(useGetExchangeRate, {
69 expect(await result.current('EUR')).toStrictEqual(exchangeRateEur);
70 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(1);
71 expect(mockedGetExchangeRate).toHaveBeenCalledWith('EUR', undefined);
73 expect(await result.current('USD')).toStrictEqual(exchangeRateUsd);
74 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(2);
75 expect(mockedGetExchangeRate).toHaveBeenCalledWith('USD', undefined);
77 // getExchangeRate should not be called after that
78 mockedGetExchangeRate.mockClear();
80 expect(await result.current('EUR')).toStrictEqual(exchangeRateEur);
81 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(0);
83 expect(await result.current('USD')).toStrictEqual(exchangeRateUsd);
84 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(0);
87 it('should send request for specific time', async () => {
88 const store = setupStore();
90 function Wrapper({ children }: PropsWithChildren<{}>): JSX.Element {
91 return <ProtonStoreProvider store={store}>{children}</ProtonStoreProvider>;
94 const { result } = renderHook(useGetExchangeRate, {
98 expect(await result.current('EUR', new Date(1713516247 * SECOND))).toStrictEqual(exchangeRateEur);
99 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(1);
100 expect(mockedGetExchangeRate).toHaveBeenCalledWith('EUR', BigInt(1713516247));
102 expect(await result.current('USD', new Date(1713516247 * SECOND))).toStrictEqual(exchangeRateUsd);
103 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(2);
104 expect(mockedGetExchangeRate).toHaveBeenCalledWith('USD', BigInt(1713516247));
106 // getExchangeRate should not be called after that
107 mockedGetExchangeRate.mockClear();
109 expect(await result.current('EUR', new Date(1713516247 * SECOND))).toStrictEqual(exchangeRateEur);
110 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(0);
112 expect(await result.current('USD', new Date(1713516247 * SECOND))).toStrictEqual(exchangeRateUsd);
113 expect(mockedGetExchangeRate).toHaveBeenCalledTimes(0);