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
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import { render, screen } from "@testing-library/react";
import NotificationWaveCreated from "@/components/brain/notifications/wave-created/NotificationWaveCreated";

const queryMock = jest.fn();
jest.mock("@tanstack/react-query", () => ({
useQuery: (...args: any[]) => queryMock(...args),
}));
jest.mock("next/link", () => ({
__esModule: true,
default: (p: any) => <a {...p}>{p.children}</a>,
}));
jest.mock("@/components/waves/header/WaveHeaderFollow", () => ({
jest.mock(
"@/components/brain/notifications/wave-created/NotificationWaveFollowBtn",
() => ({
__esModule: true,
default: () => <div data-testid="wave-follow" />,
})
);
jest.mock("@/hooks/useDeviceInfo", () => ({
__esModule: true,
default: () => <div data-testid="wave-follow" />,
WaveFollowBtnSize: {},
default: () => ({ isApp: false }),
}));
jest.mock("@/components/brain/notifications/NotificationsFollowBtn", () => ({
__esModule: true,
default: () => <div data-testid="follow-btn" />,
}));
jest.mock("@/helpers/image.helpers", () => ({
getScaledImageUri: () => "/scaled.jpg",
getScaledResolvedImageUri: () => "/scaled.jpg",
ImageScale: {},
}));
jest.mock("@/helpers/Helpers", () => ({
Expand All @@ -30,23 +33,15 @@ jest.mock("@/helpers/Helpers", () => ({
const notification = {
related_identity: { handle: "alice", pfp: "pfp.png" },
additional_context: { wave_id: "1" },
related_wave: {
id: "1",
name: "Wave 1",
is_dm_wave: false,
},
created_at: "2024-01-01T00:00:00Z",
} as any;

it("renders wave data and links", () => {
queryMock.mockReturnValue({
data: {
id: "1",
name: "Wave 1",
chat: {
scope: {
group: {
is_direct_message: false,
},
},
},
},
});
render(<NotificationWaveCreated notification={notification} />);
expect(screen.getByRole("link", { name: "alice" })).toHaveAttribute(
"href",
Expand All @@ -61,3 +56,19 @@ it("renders wave data and links", () => {
const img = screen.getByRole("img");
expect(img.getAttribute("src")).toContain("scaled.jpg");
});

it("renders fallback wave text without a link when wave id is missing", () => {
render(
<NotificationWaveCreated
notification={{
...notification,
additional_context: {},
related_wave: undefined,
}}
/>
);

expect(screen.getByText("Unknown wave")).toBeInTheDocument();
expect(screen.queryByRole("link", { name: "Unknown wave" })).toBeNull();
expect(screen.queryByTestId("wave-follow")).toBeNull();
});
139 changes: 29 additions & 110 deletions __tests__/components/home/explore-waves/ExploreWaveCard.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { render, screen } from "@testing-library/react";
import type { ApiWave } from "@/generated/models/ApiWave";
import { ExploreWaveCard } from "@/components/home/explore-waves/ExploreWaveCard";
import { getTimeAgoShort } from "@/helpers/Helpers";
import type { ImgHTMLAttributes, ReactNode } from "react";
import type { SidebarWave } from "@/types/waves.types";
import { ApiWaveType } from "@/generated/models/ApiWaveType";

jest.mock("next/link", () => ({
__esModule: true,
Expand Down Expand Up @@ -49,24 +50,15 @@ describe("ExploreWaveCard", () => {
mockContentDisplay.mockClear();
});

it("uses ApiWave last_drop_time and description_drop preview content", () => {
it("uses sidebar wave latest drop time, total drops, and description preview", () => {
render(
<ExploreWaveCard
wave={createWave({
last_drop_time: 2_000,
metrics: {
drops_count: 7,
latest_drop_timestamp: 1_000,
},
description_drop: {
parts: [
{
part_id: 1,
content: "Description preview",
media: [],
quoted_drop: null,
},
],
latestDropTimestamp: 2_000,
totalDropsCount: 7,
descriptionDrop: {
contents: "Description preview",
media: [],
},
})}
/>
Expand All @@ -93,114 +85,41 @@ describe("ExploreWaveCard", () => {
});
});

it("does not render the preview container when description_drop is empty", () => {
it("shows empty state when latest drop is missing", () => {
render(
<ExploreWaveCard
wave={createWave({
description_drop: {
parts: [
{
part_id: 1,
content: " ",
media: [],
quoted_drop: null,
},
],
},
latestDropTimestamp: null,
})}
/>
);

expect(screen.queryByTestId("content-display")).not.toBeInTheDocument();
expect(screen.getByText("No drops yet")).toBeInTheDocument();
});
});

function createWave(overrides: Partial<ApiWave> = {}): ApiWave {
const baseWave = {
function createWave(overrides: Partial<SidebarWave> = {}): SidebarWave {
return {
id: "wave-1",
serial_no: 1,
author: {
handle: "alice",
banner1_color: null,
banner2_color: null,
},
name: "Wave One",
type: ApiWaveType.Chat,
picture: null,
created_at: 1,
last_drop_time: 1_000,
description_drop: {
id: "drop-1",
serial_no: 1,
drop_type: "CHAT",
rank: null,
wave: {
id: "wave-1",
},
author: {
handle: "alice",
},
created_at: 1,
updated_at: null,
title: null,
parts: [
{
part_id: 1,
content: "Description preview",
media: [],
quoted_drop: null,
},
],
parts_count: 1,
referenced_nfts: [],
mentioned_users: [],
mentioned_waves: [],
metadata: [],
rating: 0,
realtime_rating: 0,
rating_prediction: 0,
top_raters: [],
raters_count: 0,
context_profile_context: null,
subscribed_actions: [],
is_signed: false,
reactions: [],
boosts: 0,
hide_link_preview: false,
},
voting: {},
visibility: {},
participation: {},
chat: {
scope: {
group: {
is_direct_message: false,
},
},
enabled: true,
},
wave: {
type: "CHAT",
contributors: [],
isDirectMessage: false,
hasCompetition: false,
descriptionDrop: {
contents: "Description preview",
media: [],
},
contributors_overview: [],
subscribed_actions: [],
metrics: {
drops_count: 3,
latest_drop_timestamp: 1_000,
},
pauses: [],
totalDropsCount: 3,
isPrivate: false,
latestDropTimestamp: 1_000,
firstUnreadDropSerialNo: null,
unreadDropsCount: 0,
latestReadTimestamp: 0,
pinned: false,
} as any;

return {
...baseWave,
muted: false,
subscribed: false,
...overrides,
metrics: {
...baseWave.metrics,
...(overrides.metrics as object | undefined),
},
description_drop: {
...baseWave.description_drop,
...(overrides.description_drop as object | undefined),
},
} as ApiWave;
};
}
44 changes: 34 additions & 10 deletions __tests__/components/memes/MemeDropTraits.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import MemeDropTraits from "@/components/memes/drops/MemeDropTraits";

jest.mock(
"@/components/memes/drops/MemeDropTrait",
() => (props: any) =>
(
<div
data-testid="trait"
data-label={props.label}
data-value={props.value}></div>
)
);
jest.mock("@/components/memes/drops/MemeDropTrait", () => (props: any) => (
<div
data-testid="trait"
data-label={props.label}
data-value={props.value}
></div>
));

describe("MemeDropTraits", () => {
const drop = {
Expand All @@ -33,4 +30,31 @@ describe("MemeDropTraits", () => {
await user.click(screen.getByText("Show less"));
expect(screen.getAllByTestId("trait")).toHaveLength(2);
});

it("does not render the show all control when there are no traits", () => {
const { container } = render(
<MemeDropTraits drop={{ metadata: [] } as any} />
);

expect(container).toBeEmptyDOMElement();
expect(screen.queryByText("Show all")).not.toBeInTheDocument();
});

it("does not render the show all control when all traits are visible", () => {
render(
<MemeDropTraits
drop={
{
metadata: [
{ data_key: "artist", data_value: "bob" },
{ data_key: "memeName", data_value: "cool" },
],
} as any
}
/>
);

expect(screen.getAllByTestId("trait")).toHaveLength(2);
expect(screen.queryByText("Show all")).not.toBeInTheDocument();
});
});
30 changes: 30 additions & 0 deletions __tests__/components/memes/drops/MemeWinnerDrop.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,33 @@ test("hides actions when mobile", () => {
);
expect(queryByTestId("reply")).toBeNull();
});

test("uses v2 title and part one content before metadata fallbacks", () => {
render(
<MemeWinnerDrop
drop={{
...drop,
title: "Part title",
parts: [
{
part_id: 1,
content: "Part description",
media: [{ url: "u", mime_type: "image/png" }],
},
],
metadata: [
{ data_key: "title", data_value: "Metadata title" },
{ data_key: "description", data_value: "Metadata description" },
],
}}
showReplyAndQuote
onReply={jest.fn()}
onQuote={jest.fn()}
/>
);

expect(screen.getByText("Part title")).toBeInTheDocument();
expect(screen.getByText("Part description")).toBeInTheDocument();
expect(screen.queryByText("Metadata title")).not.toBeInTheDocument();
expect(screen.queryByText("Metadata description")).not.toBeInTheDocument();
});
24 changes: 24 additions & 0 deletions __tests__/components/memes/drops/MemesLeaderboardDrop.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,30 @@ test("uses mobile modal on small screens", async () => {
expect(screen.getByTestId("mobile-modal")).toHaveTextContent("open");
});

test("uses v2 part one title and content before metadata fallbacks", () => {
useDeviceInfo.mockReturnValue({ hasTouchScreen: false });
useIsMobileScreen.mockReturnValue(false);

render(
<MemesLeaderboardDrop
drop={{
...drop,
title: "Part title",
parts: [
{
content: "Part description",
media: [{ mime_type: "image", url: "img" }],
},
],
}}
onDropClick={jest.fn()}
/>
);

expect(screen.getByTestId("header")).toHaveTextContent("Part title");
expect(screen.getByTestId("desc")).toHaveTextContent("Part description");
});

test("opens mobile resubmit modal after the touch menu leaves", async () => {
const setIsActive = jest.fn();
useDeviceInfo.mockReturnValue({ hasTouchScreen: true });
Expand Down
Loading
Loading