Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
124 changes: 87 additions & 37 deletions __tests__/components/brain/BrainMobile.test.tsx
Original file line number Diff line number Diff line change
@@ -1,98 +1,148 @@
import { render, screen, waitFor } from '@testing-library/react';
import BrainMobile from '@/components/brain/BrainMobile';
import { render, screen, waitFor } from "@testing-library/react";
import BrainMobile from "@/components/brain/BrainMobile";

jest.mock('next/image', () => ({ __esModule: true, default: (props:any) => <img {...props} /> }));
jest.mock("next/image", () => ({
__esModule: true,
default: (props: any) => <img {...props} />,
}));

let mockSearchParams = new URLSearchParams();
let mockPathname = '/';
let mockPathname = "/";
const mockPush = jest.fn();

jest.mock('next/navigation', () => ({
jest.mock("next/navigation", () => ({
useRouter: () => ({ push: mockPush }),
useSearchParams: () => mockSearchParams,
usePathname: () => mockPathname,
}));

let isApp = true;
jest.mock('@/hooks/useDeviceInfo', () => ({ __esModule: true, default: () => ({ isApp }) }));
jest.mock("@/hooks/useDeviceInfo", () => ({
__esModule: true,
default: () => ({ isApp }),
}));

let dropData: any = null;
let waveData: any = null;

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

jest.mock('@/hooks/useWaveData', () => ({
useWaveData: () => ({ data: waveData })
jest.mock("@/hooks/useWaveData", () => ({
useWaveData: () => ({ data: waveData }),
}));

jest.mock('@/hooks/useWave', () => ({
useWave: () => ({ isMemesWave: false, isRankWave: true })
jest.mock("@/hooks/useWave", () => ({
useWave: () => ({
isMemesWave: false,
isCurationWave: false,
isRankWave: true,
}),
}));

jest.mock('@/hooks/useWaveTimers', () => ({
useWaveTimers: () => ({ voting: { isCompleted: false }, decisions: { firstDecisionDone: true } })
jest.mock("@/hooks/useWaveTimers", () => ({
useWaveTimers: () => ({
voting: { isCompleted: false },
decisions: { firstDecisionDone: true },
}),
}));

jest.mock('@/components/brain/BrainDesktopDrop', () => ({ __esModule: true, default: (props:any) => <div data-testid='drop' onClick={props.onClose}>drop</div> }));
jest.mock("@/components/brain/BrainDesktopDrop", () => ({
__esModule: true,
default: (props: any) => (
<div data-testid="drop" onClick={props.onClose}>
drop
</div>
),
}));

jest.mock('@/components/brain/mobile/BrainMobileTabs', () => ({ __esModule: true, default: () => <div data-testid='tabs' /> }));
jest.mock("@/components/brain/mobile/BrainMobileTabs", () => ({
__esModule: true,
default: () => <div data-testid="tabs" />,
}));

jest.mock('@/components/brain/mobile/BrainMobileAbout', () => ({ __esModule: true, default: () => <div data-testid='about' /> }));
jest.mock("@/components/brain/mobile/BrainMobileAbout", () => ({
__esModule: true,
default: () => <div data-testid="about" />,
}));

jest.mock('@/components/brain/mobile/BrainMobileWaves', () => ({ __esModule: true, default: () => <div data-testid='waves' /> }));
jest.mock("@/components/brain/mobile/BrainMobileWaves", () => ({
__esModule: true,
default: () => <div data-testid="waves" />,
}));

jest.mock('@/components/brain/mobile/BrainMobileMessages', () => ({ __esModule: true, default: () => <div data-testid='messages' /> }));
jest.mock("@/components/brain/mobile/BrainMobileMessages", () => ({
__esModule: true,
default: () => <div data-testid="messages" />,
}));

jest.mock('@/components/brain/notifications', () => ({ __esModule: true, default: () => <div data-testid='notifications' /> }));
jest.mock("@/components/brain/notifications", () => ({
__esModule: true,
default: () => <div data-testid="notifications" />,
}));

jest.mock('@/components/brain/my-stream/MyStreamWaveLeaderboard', () => ({ __esModule: true, default: () => <div data-testid="leaderboard" /> }));
jest.mock("@/components/brain/my-stream/MyStreamWaveLeaderboard", () => ({
__esModule: true,
default: () => <div data-testid="leaderboard" />,
}));

jest.mock('@/components/brain/my-stream/MyStreamWaveOutcome', () => ({ __esModule: true, default: () => <div data-testid="outcome" /> }));
jest.mock("@/components/brain/my-stream/MyStreamWaveOutcome", () => ({
__esModule: true,
default: () => <div data-testid="outcome" />,
}));

jest.mock('@/components/waves/winners/WaveWinners', () => ({ __esModule: true, WaveWinners: () => <div data-testid="winners" /> }));
jest.mock("@/components/waves/winners/WaveWinners", () => ({
__esModule: true,
WaveWinners: () => <div data-testid="winners" />,
}));

jest.mock('@/components/brain/my-stream/votes/MyStreamWaveMyVotes', () => ({ __esModule: true, default: () => <div data-testid="myvotes" /> }));
jest.mock("@/components/brain/my-stream/votes/MyStreamWaveMyVotes", () => ({
__esModule: true,
default: () => <div data-testid="myvotes" />,
}));

jest.mock('@/components/brain/my-stream/MyStreamWaveFAQ', () => ({ __esModule: true, default: () => <div data-testid="faq" /> }));
jest.mock("@/components/brain/my-stream/MyStreamWaveFAQ", () => ({
__esModule: true,
default: () => <div data-testid="faq" />,
}));

// Tests

describe('BrainMobile', () => {
describe("BrainMobile", () => {
beforeEach(() => {
mockSearchParams = new URLSearchParams();
mockPathname = '/';
mockPathname = "/";
mockPush.mockClear();
dropData = null;
waveData = null;
isApp = true;
});

it('renders BrainDesktopDrop when drop is open', () => {
mockSearchParams.set('drop', 'd1');
dropData = { id: 'd1' };
it("renders BrainDesktopDrop when drop is open", () => {
mockSearchParams.set("drop", "d1");
dropData = { id: "d1" };
render(<BrainMobile>child</BrainMobile>);
expect(screen.getByTestId('drop')).toBeInTheDocument();
expect(screen.getByTestId("drop")).toBeInTheDocument();
});

it('shows notifications view when path matches', async () => {
mockPathname = '/notifications';
it("shows notifications view when path matches", async () => {
mockPathname = "/notifications";
render(<BrainMobile>child</BrainMobile>);
await waitFor(() => {
expect(screen.getByTestId('notifications')).toBeInTheDocument();
expect(screen.getByTestId("notifications")).toBeInTheDocument();
});
});

it('shows tabs only when wave active or not in app', async () => {
it("shows tabs only when wave active or not in app", async () => {
isApp = true;
render(<BrainMobile>child</BrainMobile>);
expect(screen.queryByTestId('tabs')).toBeNull();
expect(screen.queryByTestId("tabs")).toBeNull();

mockSearchParams.set('wave', '1');
mockSearchParams.set("wave", "1");
const { rerender } = render(<BrainMobile>child</BrainMobile>);
await waitFor(() => expect(screen.getByTestId('tabs')).toBeInTheDocument());
await waitFor(() => expect(screen.getByTestId("tabs")).toBeInTheDocument());
rerender(<div />);
});
});
35 changes: 31 additions & 4 deletions __tests__/components/brain/mobile/BrainMobileTabs.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ enum BrainView {

const push = jest.fn();

jest.mock("next/navigation", () => ({
useRouter: () => ({ push }),
jest.mock("next/navigation", () => ({
useRouter: () => ({ push }),
useSearchParams: () => ({
get: jest.fn().mockReturnValue(null)
get: jest.fn().mockReturnValue(null),
}),
usePathname: () => "/brain"
usePathname: () => "/brain",
}));

jest.mock("react-use", () => ({
Expand Down Expand Up @@ -72,6 +72,7 @@ describe("BrainMobileTabs", () => {
jest.clearAllMocks();
(useWave as jest.Mock).mockReturnValue({
isMemesWave: false,
isCurationWave: false,
isRankWave: false,
});
(useUnreadIndicator as jest.Mock).mockReturnValue({ hasUnread: false });
Expand All @@ -83,6 +84,7 @@ describe("BrainMobileTabs", () => {
it("renders back button and navigates to My Stream", async () => {
(useWave as jest.Mock).mockReturnValue({
isMemesWave: false,
isCurationWave: false,
isRankWave: false,
});
render(
Expand All @@ -106,6 +108,7 @@ describe("BrainMobileTabs", () => {
it("shows unread indicators and handles message/notification clicks", async () => {
(useWave as jest.Mock).mockReturnValue({
isMemesWave: false,
isCurationWave: false,
isRankWave: false,
});
(useUnreadIndicator as jest.Mock).mockReturnValue({ hasUnread: true });
Expand Down Expand Up @@ -141,6 +144,7 @@ describe("BrainMobileTabs", () => {
it("renders leaderboard and extra tabs for memes rank wave", () => {
(useWave as jest.Mock).mockReturnValue({
isMemesWave: true,
isCurationWave: false,
isRankWave: true,
});

Expand Down Expand Up @@ -168,4 +172,27 @@ describe("BrainMobileTabs", () => {
expect(screen.getByText("Outcome")).toBeInTheDocument();
expect(screen.getByText("FAQ")).toBeInTheDocument();
});

it("renders My Votes for curation rank wave", () => {
(useWave as jest.Mock).mockReturnValue({
isMemesWave: false,
isCurationWave: true,
isRankWave: true,
});

render(
<BrainMobileTabs
activeView={BrainView.ABOUT}
onViewChange={onViewChange}
waveActive={true}
showWavesTab={false}
showStreamBack={false}
isApp={false}
wave={{ id: "1" } as any}
/>
);

expect(screen.getByText("My Votes")).toBeInTheDocument();
expect(screen.queryByText("FAQ")).toBeNull();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,38 @@ describe("MyStreamWaveDesktopTabs", () => {
expect(screen.queryByText("My Votes")).toBeNull();
});

it("shows My Votes for curation waves", () => {
mockWaveInfo = {
isChatWave: false,
isMemesWave: false,
isCurationWave: true,
isRankWave: false,
};
mockAvailableTabs = [
MyStreamWaveTab.CHAT,
MyStreamWaveTab.MY_VOTES,
MyStreamWaveTab.LEADERBOARD,
];
renderComponent(MyStreamWaveTab.MY_VOTES);

expect(screen.getByText("My Votes")).toBeInTheDocument();
expect(setActiveTab).not.toHaveBeenCalled();
});

it("keeps FAQ hidden outside memes waves", () => {
mockWaveInfo = {
isChatWave: false,
isMemesWave: false,
isCurationWave: true,
isRankWave: false,
};
mockAvailableTabs = [MyStreamWaveTab.CHAT, MyStreamWaveTab.FAQ];
renderComponent(MyStreamWaveTab.FAQ);

expect(screen.queryByText("FAQ")).toBeNull();
expect(setActiveTab).toHaveBeenCalledWith(MyStreamWaveTab.CHAT);
});

it("does not render countdown; parent header handles it", () => {
const spy = jest.spyOn(Time, "currentMillis").mockReturnValue(0);
mockWaveInfo = {
Expand Down Expand Up @@ -147,7 +179,6 @@ describe("MyStreamWaveDesktopTabs", () => {

expect(updateAvailableTabs).toHaveBeenCalledWith(
expect.objectContaining({
waveId: expect.anything(),
isChatWave: false,
isMemesWave: false,
isCurationWave: true,
Expand Down
Loading