Skip to content
Closed

wip #2219

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
385 changes: 338 additions & 47 deletions __tests__/contexts/wave/MyStreamContext.test.tsx

Large diffs are not rendered by default.

70 changes: 70 additions & 0 deletions __tests__/hooks/usePinnedWavesServer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { renderHook } from "@testing-library/react";
import React from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";

import { AuthContext } from "@/components/auth/Auth";
import { usePinnedWavesServer } from "@/hooks/usePinnedWavesServer";
import { useSeizeConnectContext } from "@/components/auth/SeizeConnectContext";

jest.mock("@tanstack/react-query", () => ({
useMutation: jest.fn(),
useQuery: jest.fn(),
useQueryClient: jest.fn(),
}));

jest.mock("@/components/auth/SeizeConnectContext", () => ({
useSeizeConnectContext: jest.fn(),
}));

const queryClientMock = {
cancelQueries: jest.fn(),
getQueriesData: jest.fn(() => []),
getQueryData: jest.fn(() => []),
invalidateQueries: jest.fn(),
setQueryData: jest.fn(),
};

const wrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
<AuthContext.Provider
value={
{ connectedProfile: { handle: "me" }, activeProfileProxy: null } as any
}
>
{children}
</AuthContext.Provider>
);

describe("usePinnedWavesServer", () => {
beforeEach(() => {
jest.clearAllMocks();

(useQueryClient as jest.Mock).mockReturnValue(queryClientMock);
(useQuery as jest.Mock).mockReturnValue({
data: [],
isLoading: false,
isError: false,
error: null,
refetch: jest.fn(),
});
(useMutation as jest.Mock).mockReturnValue({
mutateAsync: jest.fn(),
error: null,
});
(useSeizeConnectContext as jest.Mock).mockReturnValue({
address: "0xabc",
});
});

it("always refetches pinned waves on window focus", () => {
renderHook(() => usePinnedWavesServer(), { wrapper });

expect(useQuery).toHaveBeenCalledWith(
expect.objectContaining({
gcTime: 10 * 60 * 1000,
refetchInterval: 2 * 60 * 1000,
refetchOnWindowFocus: "always",
staleTime: 5 * 60 * 1000,
})
);
});
});
28 changes: 20 additions & 8 deletions __tests__/hooks/useWaveData.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,18 @@ describe("useWaveData", () => {
it("calls useQuery with correct params", () => {
(useQuery as jest.Mock).mockReturnValue({ data: null });
renderHook(() =>
useWaveData({ waveId: "1", refetchInterval: 1000, onWaveNotFound: jest.fn() })
useWaveData({
waveId: "1",
refetchInterval: 1000,
onWaveNotFound: jest.fn(),
})
);
expect(useQuery).toHaveBeenCalledWith(
expect.objectContaining({
refetchOnWindowFocus: "always",
refetchInterval: 1000,
})
);
expect(useQuery).toHaveBeenCalled();
});

it("does not fetch when waveId is null", () => {
Expand All @@ -29,15 +38,18 @@ describe("useWaveData", () => {
expect(mockFetch).not.toHaveBeenCalled();
});

it('handles retry logic', () => {
it("handles retry logic", () => {
let options: any;
(useQuery as jest.Mock).mockImplementation((opts: any) => { options = opts; return { data: null }; });
(useQuery as jest.Mock).mockImplementation((opts: any) => {
options = opts;
return { data: null };
});
const onWaveNotFound = jest.fn();
renderHook(() => useWaveData({ waveId: '1', onWaveNotFound }));
expect(options.retry(1, 'Wave 1 not found')).toBe(false);
renderHook(() => useWaveData({ waveId: "1", onWaveNotFound }));
expect(options.retry(1, "Wave 1 not found")).toBe(false);
expect(onWaveNotFound).toHaveBeenCalled();
expect(options.retry(2, new Error('e'))).toBe(true);
expect(options.retry(4, new Error('e'))).toBe(false);
expect(options.retry(2, new Error("e"))).toBe(true);
expect(options.retry(4, new Error("e"))).toBe(false);
expect(options.retryDelay(3)).toBe(3000);
});
});
144 changes: 130 additions & 14 deletions __tests__/hooks/useWavesOverview.test.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,164 @@
import { renderHook, act } from '@testing-library/react';
import { useWavesOverview } from '@/hooks/useWavesOverview';
import { ApiWavesOverviewType } from '@/generated/models/ApiWavesOverviewType';
import { renderHook, act } from "@testing-library/react";
import { useWavesOverview } from "@/hooks/useWavesOverview";
import { ApiWavesOverviewType } from "@/generated/models/ApiWavesOverviewType";

jest.mock('@tanstack/react-query', () => ({
jest.mock("@tanstack/react-query", () => ({
useInfiniteQuery: jest.fn(),
}));

const useInfiniteQueryMock = require('@tanstack/react-query').useInfiniteQuery as jest.Mock;
const useInfiniteQueryMock = require("@tanstack/react-query")
.useInfiniteQuery as jest.Mock;

describe('useWavesOverview', () => {
describe("useWavesOverview", () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('returns waves and fetchNextPage works', () => {
const fetchNext = jest.fn();
afterEach(() => {
jest.useRealTimers();
jest.restoreAllMocks();
});

it("returns waves and fetchNextPage works", () => {
const fetchNext = jest.fn(() => Promise.resolve(undefined));
useInfiniteQueryMock.mockReturnValue({
data: { pages: [[{ id: '1' }]] },
data: { pages: [[{ id: "1" }]] },
fetchNextPage: fetchNext,
isFetching: false,
isFetchingNextPage: false,
hasNextPage: true,
status: 'success',
refetch: jest.fn(),
status: "success",
refetch: jest.fn(() => Promise.resolve(undefined)),
});
const { result, rerender } = renderHook(() =>
useWavesOverview({ type: ApiWavesOverviewType.RecentlyDroppedTo })
);
expect(
useInfiniteQueryMock.mock.calls[0]?.[0]?.refetchOnWindowFocus
).toBeUndefined();
expect(result.current.waves).toHaveLength(1);
act(() => {
result.current.fetchNextPage();
});
expect(fetchNext).toHaveBeenCalled();

useInfiniteQueryMock.mockReturnValue({
data: { pages: [[{ id: '1' }, { id: '2' }]] },
data: { pages: [[{ id: "1" }, { id: "2" }]] },
fetchNextPage: fetchNext,
isFetching: false,
isFetchingNextPage: false,
hasNextPage: true,
status: 'success',
refetch: jest.fn(),
status: "success",
refetch: jest.fn(() => Promise.resolve(undefined)),
});
rerender();
expect(result.current.waves).toHaveLength(2);
});

it("delays refetch until the remaining cooldown elapses after an error", () => {
jest.useFakeTimers();

const refetch = jest.fn(() => Promise.resolve(undefined));
let queryOptions:
| {
retry: (failureCount: number) => boolean;
}
| undefined;

useInfiniteQueryMock.mockImplementation((options: unknown) => {
queryOptions = options;
return {
data: { pages: [[{ id: "1" }]] },
fetchNextPage: jest.fn(),
isFetching: false,
isFetchingNextPage: false,
hasNextPage: true,
status: "success",
refetch,
};
});

const nowSpy = jest.spyOn(Date, "now");
nowSpy.mockReturnValue(1000);

const { result } = renderHook(() =>
useWavesOverview({ type: ApiWavesOverviewType.RecentlyDroppedTo })
);

expect(queryOptions).toBeDefined();

act(() => {
queryOptions?.retry(3);
});

act(() => {
nowSpy.mockReturnValue(11000);
result.current.refetch();
});

expect(refetch).not.toHaveBeenCalled();

act(() => {
jest.advanceTimersByTime(19999);
});
expect(refetch).not.toHaveBeenCalled();

act(() => {
jest.advanceTimersByTime(1);
});
expect(refetch).toHaveBeenCalledTimes(1);
});

it("clears scheduled cooldown actions on unmount", () => {
jest.useFakeTimers();

const fetchNextPage = jest.fn(() => Promise.resolve(undefined));
const refetch = jest.fn(() => Promise.resolve(undefined));
let queryOptions:
| {
retry: (failureCount: number) => boolean;
}
| undefined;

useInfiniteQueryMock.mockImplementation((options: unknown) => {
queryOptions = options;
return {
data: { pages: [[{ id: "1" }]] },
fetchNextPage,
isFetching: false,
isFetchingNextPage: false,
hasNextPage: true,
status: "success",
refetch,
};
});

const nowSpy = jest.spyOn(Date, "now");
nowSpy.mockReturnValue(1000);

const { result, unmount } = renderHook(() =>
useWavesOverview({ type: ApiWavesOverviewType.RecentlyDroppedTo })
);

act(() => {
queryOptions?.retry(3);
});

act(() => {
nowSpy.mockReturnValue(11000);
result.current.fetchNextPage();
result.current.refetch();
});

expect(fetchNextPage).not.toHaveBeenCalled();
expect(refetch).not.toHaveBeenCalled();

act(() => {
unmount();
jest.advanceTimersByTime(20000);
});

expect(fetchNextPage).not.toHaveBeenCalled();
expect(refetch).not.toHaveBeenCalled();
});
});
2 changes: 1 addition & 1 deletion components/user/layout/userPageVisibility.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

export const normalizeCountry = (
const normalizeCountry = (
country: string | null | undefined
): string | null => {
if (typeof country !== "string") {
Expand Down
Loading
Loading