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
270 changes: 270 additions & 0 deletions __tests__/components/brain/ContentTabContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ function setup() {
}

describe("ContentTabContext", () => {
beforeEach(() => {
localStorage.clear();
});

it("defaults to CHAT when params null", () => {
const { result } = setup();
act(() => result.current.updateAvailableTabs(null));
Expand Down Expand Up @@ -114,6 +118,37 @@ describe("ContentTabContext", () => {
expect(result.current.activeContentTab).toBe(MyStreamWaveTab.CHAT);
});

it("forces CHAT for chat waves", () => {
const { result } = setup();
act(() =>
result.current.updateAvailableTabs({
waveId: "default-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);
act(() => result.current.setActiveContentTab(MyStreamWaveTab.LEADERBOARD));

act(() =>
result.current.updateAvailableTabs({
waveId: "chat-wave",
isChatWave: true,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);

expect(result.current.availableTabs).toEqual([MyStreamWaveTab.CHAT]);
expect(result.current.activeContentTab).toBe(MyStreamWaveTab.CHAT);
});

it("adds SALES and omits OUTCOME for curation waves", () => {
const { result } = setup();
act(() =>
Expand Down Expand Up @@ -175,6 +210,241 @@ describe("ContentTabContext", () => {
expect(result.current.activeContentTab).toBe(MyStreamWaveTab.CHAT);
});

it("does not persist transient tab overrides", () => {
const { result } = setup();
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);

act(() =>
result.current.setActiveContentTab(MyStreamWaveTab.CHAT, {
persist: false,
})
);

act(() =>
result.current.updateAvailableTabs({
waveId: "other-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);

expect(result.current.activeContentTab).toBe(MyStreamWaveTab.LEADERBOARD);
});

it("uses transient preferred tab to override stored or default tab", () => {
const { result } = setup();
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);
act(() => result.current.setActiveContentTab(MyStreamWaveTab.OUTCOME));

act(() =>
result.current.updateAvailableTabs({
waveId: "other-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
transientPreferredTab: MyStreamWaveTab.CHAT,
})
);

expect(result.current.activeContentTab).toBe(MyStreamWaveTab.CHAT);
});

it("does not persist transient preferred tab after leaving the wave", () => {
const { result } = setup();
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
transientPreferredTab: MyStreamWaveTab.CHAT,
})
);

act(() =>
result.current.updateAvailableTabs({
waveId: "other-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);

expect(result.current.activeContentTab).toBe(MyStreamWaveTab.LEADERBOARD);
});

it("keeps transient active tab during same-wave availability recalculations", () => {
const { result } = setup();
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);

act(() =>
result.current.setActiveContentTab(MyStreamWaveTab.CHAT, {
persist: false,
})
);
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: true,
})
);

expect(result.current.activeContentTab).toBe(MyStreamWaveTab.CHAT);
});

it("keeps transient preferred tab during same-wave availability recalculations", () => {
const { result } = setup();
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
transientPreferredTab: MyStreamWaveTab.CHAT,
})
);
act(() =>
result.current.updateAvailableTabs({
waveId: "meme-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: true,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: true,
})
);

expect(result.current.activeContentTab).toBe(MyStreamWaveTab.CHAT);
});

it("reapplies the stored tab on same-wave recalculation when there is no transient override", () => {
const { result } = setup();
act(() =>
result.current.updateAvailableTabs({
waveId: "default-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: true,
})
);
act(() => result.current.setActiveContentTab(MyStreamWaveTab.WINNERS));

act(() =>
result.current.updateAvailableTabs({
waveId: "default-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: false,
})
);
expect(result.current.activeContentTab).toBe(MyStreamWaveTab.CHAT);

act(() =>
result.current.updateAvailableTabs({
waveId: "default-wave",
isChatWave: false,
hasAuthenticatedProfile: true,
isMemesWave: false,
isCurationWave: false,
votingState: WaveVotingState.NOT_STARTED,
hasFirstDecisionPassed: true,
})
);

expect(result.current.activeContentTab).toBe(MyStreamWaveTab.WINNERS);
});

it("falls back to default when stored tab is unavailable", () => {
const { result } = setup();
act(() =>
Expand Down
74 changes: 74 additions & 0 deletions __tests__/components/brain/my-stream/MyStreamWave.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ jest.mock("@/hooks/useWaveData", () => ({
useWaveData: (...args: any[]) => useWaveData(...args),
}));

const mockSetViewMode = jest.fn();
const mockToggleViewMode = jest.fn();
const useWaveViewMode = jest.fn();
jest.mock("@/hooks/useWaveViewMode", () => ({
useWaveViewMode: (...args: any[]) => useWaveViewMode(...args),
}));

const mockRouterPush = jest.fn();
const mockSearchParams = new URLSearchParams("wave=1");
const mockPathname = "/path";
Expand Down Expand Up @@ -123,13 +130,21 @@ describe("MyStreamWave", () => {
beforeEach(() => {
jest.clearAllMocks();
mockRouterPush.mockClear();
mockSetViewMode.mockClear();
mockToggleViewMode.mockClear();
mockSearchParams.set("wave", "1");
mockSearchParams.delete("serialNo");
mockBreakpoint = "LG";
useWave.mockReturnValue({
isRankWave: true,
isMemesWave: false,
isDm: false,
});
useWaveViewMode.mockReturnValue({
viewMode: "chat",
setViewMode: mockSetViewMode,
toggleViewMode: mockToggleViewMode,
});
});

it("returns null when no wave data", () => {
Expand Down Expand Up @@ -167,4 +182,63 @@ describe("MyStreamWave", () => {
expect(screen.getByTestId("sales")).toBeInTheDocument();
expect(mockMyStreamWaveSales).toHaveBeenCalledWith({ waveId: "1" });
});

it("resets gallery mode to chat when serialNo is present on eligible waves", () => {
mockSearchParams.set("serialNo", "42");
useWaveData.mockReturnValue({ data: wave });
useContentTab.mockReturnValue({ activeContentTab: MyStreamWaveTab.CHAT });
useWave.mockReturnValue({
isRankWave: false,
isMemesWave: false,
isDm: false,
});
useWaveViewMode.mockReturnValue({
viewMode: "gallery",
setViewMode: mockSetViewMode,
toggleViewMode: mockToggleViewMode,
});

render(<MyStreamWave waveId="1" />);

expect(mockSetViewMode).toHaveBeenCalledWith("chat");
});

it("does not reset gallery mode when serialNo is absent", () => {
useWaveData.mockReturnValue({ data: wave });
useContentTab.mockReturnValue({ activeContentTab: MyStreamWaveTab.CHAT });
useWave.mockReturnValue({
isRankWave: false,
isMemesWave: false,
isDm: false,
});
useWaveViewMode.mockReturnValue({
viewMode: "gallery",
setViewMode: mockSetViewMode,
toggleViewMode: mockToggleViewMode,
});

render(<MyStreamWave waveId="1" />);

expect(mockSetViewMode).not.toHaveBeenCalled();
});

it("does not reset gallery mode on waves without gallery support", () => {
mockSearchParams.set("serialNo", "42");
useWaveData.mockReturnValue({ data: wave });
useContentTab.mockReturnValue({ activeContentTab: MyStreamWaveTab.CHAT });
useWave.mockReturnValue({
isRankWave: false,
isMemesWave: true,
isDm: false,
});
useWaveViewMode.mockReturnValue({
viewMode: "gallery",
setViewMode: mockSetViewMode,
toggleViewMode: mockToggleViewMode,
});

render(<MyStreamWave waveId="1" />);

expect(mockSetViewMode).not.toHaveBeenCalled();
});
});
Loading
Loading