Skip to content

Commit 454f0b9

Browse files
committed
refactor: simplify useRampTokens hook by removing caching logic
1 parent 49cecc3 commit 454f0b9

2 files changed

Lines changed: 8 additions & 363 deletions

File tree

app/components/UI/Ramp/hooks/useRampTokens.test.ts

Lines changed: 1 addition & 302 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,7 @@ import { waitFor } from '@testing-library/react-native';
22
import { renderHookWithProvider } from '../../../../util/test/renderWithProvider';
33
import initialRootState from '../../../../util/test/initial-root-state';
44
import { handleFetch } from '@metamask/controller-utils';
5-
import {
6-
useRampTokens,
7-
RampsToken,
8-
__clearRampTokensCache,
9-
} from './useRampTokens';
5+
import { useRampTokens, RampsToken } from './useRampTokens';
106
import { UnifiedRampRoutingType } from '../../../../reducers/fiatOrders';
117
import Logger from '../../../../util/Logger';
128

@@ -98,7 +94,6 @@ describe('useRampTokens', () => {
9894
const originalEnv = process.env.METAMASK_ENVIRONMENT;
9995

10096
beforeEach(() => {
101-
__clearRampTokensCache();
10297
jest.clearAllMocks();
10398
process.env.METAMASK_ENVIRONMENT = 'dev';
10499
});
@@ -585,300 +580,4 @@ describe('useRampTokens', () => {
585580
expect(result.current.allTokens).toHaveLength(1);
586581
});
587582
});
588-
589-
describe('tokens cache', () => {
590-
it('returns cached result on second mount with same region and routing (no second fetch)', async () => {
591-
const mockResponse = createMockResponse(
592-
[createMockToken({ symbol: 'ETH' })],
593-
[createMockToken({ symbol: 'ETH' })],
594-
);
595-
mockHandleFetch.mockResolvedValue(mockResponse);
596-
597-
const state = createMockState(UnifiedRampRoutingType.AGGREGATOR, 'us-ca');
598-
const { result: result1, unmount: unmount1 } = renderHookWithProvider(
599-
() => useRampTokens(),
600-
{ state },
601-
);
602-
603-
await waitFor(() => {
604-
expect(result1.current.isLoading).toBe(false);
605-
expect(result1.current.topTokens).toEqual(mockResponse.topTokens);
606-
});
607-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
608-
609-
unmount1();
610-
611-
const { result: result2 } = renderHookWithProvider(
612-
() => useRampTokens(),
613-
{ state },
614-
);
615-
616-
await waitFor(() => {
617-
expect(result2.current.topTokens).toEqual(mockResponse.topTokens);
618-
});
619-
620-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
621-
});
622-
623-
it('deduplicates in-flight requests when two hooks share same region and routing', async () => {
624-
type MockResponse = ReturnType<typeof createMockResponse>;
625-
const deferred: { resolve: (value: MockResponse) => void } = {
626-
resolve: jest.fn(),
627-
};
628-
const fetchPromise = new Promise<MockResponse>((resolve) => {
629-
deferred.resolve = resolve;
630-
});
631-
mockHandleFetch.mockReturnValue(fetchPromise);
632-
633-
const mockResponse = createMockResponse(
634-
[createMockToken({ symbol: 'ETH' })],
635-
[createMockToken({ symbol: 'ETH' })],
636-
);
637-
const state = createMockState(UnifiedRampRoutingType.DEPOSIT, 'uk');
638-
639-
const { result: result1 } = renderHookWithProvider(
640-
() => useRampTokens(),
641-
{
642-
state,
643-
},
644-
);
645-
646-
await waitFor(() => {
647-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
648-
});
649-
650-
const { result: result2 } = renderHookWithProvider(
651-
() => useRampTokens(),
652-
{
653-
state,
654-
},
655-
);
656-
657-
deferred.resolve(mockResponse);
658-
659-
await waitFor(() => {
660-
expect(result1.current.topTokens).toEqual(mockResponse.topTokens);
661-
expect(result2.current.topTokens).toEqual(mockResponse.topTokens);
662-
});
663-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
664-
});
665-
666-
it('fetches separately for different routing decision (different cache key)', async () => {
667-
const responseAgg = createMockResponse(
668-
[createMockToken({ symbol: 'ETH' })],
669-
[createMockToken({ symbol: 'ETH' })],
670-
);
671-
const responseDep = createMockResponse(
672-
[createMockToken({ symbol: 'BTC' })],
673-
[createMockToken({ symbol: 'BTC' })],
674-
);
675-
mockHandleFetch
676-
.mockResolvedValueOnce(responseAgg)
677-
.mockResolvedValueOnce(responseDep);
678-
679-
const { result: result1, unmount: unmount1 } = renderHookWithProvider(
680-
() => useRampTokens(),
681-
{
682-
state: createMockState(UnifiedRampRoutingType.AGGREGATOR, 'us-ca'),
683-
},
684-
);
685-
686-
await waitFor(() => {
687-
expect(result1.current.topTokens).toEqual(responseAgg.topTokens);
688-
});
689-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
690-
unmount1();
691-
692-
const { result: result2 } = renderHookWithProvider(
693-
() => useRampTokens(),
694-
{
695-
state: createMockState(UnifiedRampRoutingType.DEPOSIT, 'us-ca'),
696-
},
697-
);
698-
699-
await waitFor(() => {
700-
expect(result2.current.topTokens).toEqual(responseDep.topTokens);
701-
});
702-
expect(mockHandleFetch).toHaveBeenCalledTimes(2);
703-
});
704-
705-
it('fetches separately for different region (different cache key)', async () => {
706-
const responseUs = createMockResponse(
707-
[createMockToken({ symbol: 'ETH' })],
708-
[createMockToken({ symbol: 'ETH' })],
709-
);
710-
const responseUk = createMockResponse(
711-
[createMockToken({ symbol: 'BTC' })],
712-
[createMockToken({ symbol: 'BTC' })],
713-
);
714-
mockHandleFetch
715-
.mockResolvedValueOnce(responseUs)
716-
.mockResolvedValueOnce(responseUk);
717-
718-
const { result: result1, unmount: unmount1 } = renderHookWithProvider(
719-
() => useRampTokens(),
720-
{
721-
state: createMockState(UnifiedRampRoutingType.AGGREGATOR, 'us-ca'),
722-
},
723-
);
724-
725-
await waitFor(() => {
726-
expect(result1.current.topTokens).toEqual(responseUs.topTokens);
727-
});
728-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
729-
unmount1();
730-
731-
const { result: result2 } = renderHookWithProvider(
732-
() => useRampTokens(),
733-
{
734-
state: createMockState(UnifiedRampRoutingType.AGGREGATOR, 'uk'),
735-
},
736-
);
737-
738-
await waitFor(() => {
739-
expect(result2.current.topTokens).toEqual(responseUk.topTokens);
740-
});
741-
expect(mockHandleFetch).toHaveBeenCalledTimes(2);
742-
});
743-
744-
it('refetches when cache entry is expired (TTL exceeded)', async () => {
745-
jest.useFakeTimers();
746-
const response1 = createMockResponse(
747-
[createMockToken({ symbol: 'A' })],
748-
[createMockToken({ symbol: 'A' })],
749-
);
750-
const response2 = createMockResponse(
751-
[createMockToken({ symbol: 'B' })],
752-
[createMockToken({ symbol: 'B' })],
753-
);
754-
mockHandleFetch
755-
.mockResolvedValueOnce(response1)
756-
.mockResolvedValueOnce(response2);
757-
758-
const state = createMockState(UnifiedRampRoutingType.AGGREGATOR, 'us-ca');
759-
const { result: result1, unmount: unmount1 } = renderHookWithProvider(
760-
() => useRampTokens(),
761-
{ state },
762-
);
763-
764-
await waitFor(() => {
765-
expect(result1.current.topTokens).toEqual(response1.topTokens);
766-
});
767-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
768-
769-
jest.advanceTimersByTime(5 * 60 * 1000 + 1);
770-
unmount1();
771-
772-
const { result: result2 } = renderHookWithProvider(
773-
() => useRampTokens(),
774-
{ state },
775-
);
776-
777-
await waitFor(() => {
778-
expect(result2.current.topTokens).toEqual(response2.topTokens);
779-
});
780-
expect(mockHandleFetch).toHaveBeenCalledTimes(2);
781-
782-
jest.useRealTimers();
783-
});
784-
785-
it('deletes cache entry on fetch error and refetches on next mount', async () => {
786-
const mockError = new Error('Network error');
787-
const mockResponse = createMockResponse(
788-
[createMockToken({ symbol: 'ETH' })],
789-
[createMockToken({ symbol: 'ETH' })],
790-
);
791-
mockHandleFetch
792-
.mockRejectedValueOnce(mockError)
793-
.mockResolvedValueOnce(mockResponse);
794-
795-
const state = createMockState(UnifiedRampRoutingType.AGGREGATOR, 'us-ca');
796-
const { result: result1, unmount: unmount1 } = renderHookWithProvider(
797-
() => useRampTokens(),
798-
{ state },
799-
);
800-
801-
await waitFor(() => {
802-
expect(result1.current.error).toEqual(mockError);
803-
});
804-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
805-
unmount1();
806-
807-
const { result: result2 } = renderHookWithProvider(
808-
() => useRampTokens(),
809-
{ state },
810-
);
811-
812-
await waitFor(() => {
813-
expect(result2.current.topTokens).toEqual(mockResponse.topTokens);
814-
expect(result2.current.error).toBeNull();
815-
});
816-
expect(mockHandleFetch).toHaveBeenCalledTimes(2);
817-
});
818-
819-
it('refetches after __clearRampTokensCache when same params are used again', async () => {
820-
const mockResponse = createMockResponse(
821-
[createMockToken({ symbol: 'ETH' })],
822-
[createMockToken({ symbol: 'ETH' })],
823-
);
824-
mockHandleFetch.mockResolvedValue(mockResponse);
825-
826-
const state = createMockState(UnifiedRampRoutingType.AGGREGATOR, 'us-ca');
827-
const { result: result1, unmount: unmount1 } = renderHookWithProvider(
828-
() => useRampTokens(),
829-
{ state },
830-
);
831-
832-
await waitFor(() => {
833-
expect(result1.current.topTokens).toEqual(mockResponse.topTokens);
834-
});
835-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
836-
837-
unmount1();
838-
__clearRampTokensCache();
839-
840-
const { result: result2 } = renderHookWithProvider(
841-
() => useRampTokens(),
842-
{ state },
843-
);
844-
845-
await waitFor(() => {
846-
expect(result2.current.topTokens).toEqual(mockResponse.topTokens);
847-
});
848-
expect(mockHandleFetch).toHaveBeenCalledTimes(2);
849-
});
850-
851-
it('uses same cache key for same region regardless of case (normalizes to lowercase)', async () => {
852-
const mockResponse = createMockResponse(
853-
[createMockToken({ symbol: 'ETH' })],
854-
[createMockToken({ symbol: 'ETH' })],
855-
);
856-
mockHandleFetch.mockResolvedValue(mockResponse);
857-
858-
const { result: result1, unmount: unmount1 } = renderHookWithProvider(
859-
() => useRampTokens(),
860-
{
861-
state: createMockState(UnifiedRampRoutingType.AGGREGATOR, 'US-CA'),
862-
},
863-
);
864-
865-
await waitFor(() => {
866-
expect(result1.current.topTokens).toEqual(mockResponse.topTokens);
867-
});
868-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
869-
unmount1();
870-
871-
const { result: result2 } = renderHookWithProvider(
872-
() => useRampTokens(),
873-
{
874-
state: createMockState(UnifiedRampRoutingType.AGGREGATOR, 'us-ca'),
875-
},
876-
);
877-
878-
await waitFor(() => {
879-
expect(result2.current.topTokens).toEqual(mockResponse.topTokens);
880-
});
881-
expect(mockHandleFetch).toHaveBeenCalledTimes(1);
882-
});
883-
});
884583
});

0 commit comments

Comments
 (0)