Skip to content
211 changes: 167 additions & 44 deletions __tests__/components/memes/drops/MemesLeaderboardDrop.test.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,144 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemesLeaderboardDrop } from '@/components/memes/drops/MemesLeaderboardDrop';
import React from "react";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { MemesLeaderboardDrop } from "@/components/memes/drops/MemesLeaderboardDrop";

const useIsMobileScreen = jest.fn();
jest.mock('@/hooks/isMobileScreen', () => ({
jest.mock("@/hooks/isMobileScreen", () => ({
__esModule: true,
default: (...args: any[]) => useIsMobileScreen(...args),
}));

const useDropInteractionRules = jest.fn();
jest.mock('@/hooks/drops/useDropInteractionRules', () => ({
jest.mock("@/hooks/drops/useDropInteractionRules", () => ({
useDropInteractionRules: (...args: any[]) => useDropInteractionRules(...args),
}));

const useDeviceInfo = jest.fn();
jest.mock('@/hooks/useDeviceInfo', () => ({
jest.mock("@/hooks/useDeviceInfo", () => ({
__esModule: true,
default: (...args: any[]) => useDeviceInfo(...args),
}));

const useLongPressInteraction = jest.fn();
jest.mock('@/hooks/useLongPressInteraction', () => ({
jest.mock("@/hooks/useLongPressInteraction", () => ({
__esModule: true,
default: (...args: any[]) => useLongPressInteraction(...args),
}));

jest.mock('@/components/memes/drops/MemesLeaderboardDropCard', () => (props: any) => (
<div data-testid="card" {...props}>{props.children}</div>
jest.mock(
"@/components/memes/drops/MemesLeaderboardDropCard",
() => (props: any) => (
<div data-testid="card" {...props}>
{props.children}
</div>
)
);
jest.mock(
"@/components/memes/drops/MemesLeaderboardDropHeader",
() => (p: any) => <div data-testid="header">{p.title}</div>
);
jest.mock(
"@/components/memes/drops/MemesLeaderboardDropDescription",
() => (p: any) => <div data-testid="desc">{p.description}</div>
);
jest.mock(
"@/components/memes/drops/MemesLeaderboardDropVoteSummary",
() => () => <div data-testid="summary" />
);
jest.mock(
"@/components/memes/drops/MemesLeaderboardDropArtistInfo",
() => () => <div data-testid="artist" />
);
jest.mock("@/components/memes/drops/MemeDropTraits", () => () => (
<div data-testid="traits" />
));
jest.mock('@/components/memes/drops/MemesLeaderboardDropHeader', () => (p: any) => <div data-testid="header">{p.title}</div>);
jest.mock('@/components/memes/drops/MemesLeaderboardDropDescription', () => (p: any) => <div data-testid="desc">{p.description}</div>);
jest.mock('@/components/memes/drops/MemesLeaderboardDropVoteSummary', () => () => <div data-testid="summary" />);
jest.mock('@/components/memes/drops/MemesLeaderboardDropArtistInfo', () => () => <div data-testid="artist" />);
jest.mock('@/components/memes/drops/MemeDropTraits', () => () => <div data-testid="traits" />);
jest.mock('@/components/drops/view/item/content/media/DropListItemContentMedia', () => () => <div data-testid="media" />);
jest.mock('@/components/waves/drops/WaveDropActionsOptions', () => () => <div data-testid="options" />);
jest.mock('@/components/waves/drops/WaveDropActionsOpen', () => () => <div data-testid="open" />);
jest.mock('@/components/voting', () => ({
VotingModal: (p: any) => <div data-testid="modal">{p.isOpen ? 'open' : 'closed'}</div>,
MobileVotingModal: (p: any) => <div data-testid="mobile-modal">{p.isOpen ? 'open' : 'closed'}</div>,
jest.mock(
"@/components/drops/view/item/content/media/DropListItemContentMedia",
() => () => <div data-testid="media" />
);
jest.mock("@/components/waves/drops/WaveDropActionsOptions", () => () => (
<div data-testid="options" />
));
jest.mock("@/components/waves/drops/WaveDropActionsOpen", () => () => (
<div data-testid="open" />
));
jest.mock("@/components/voting", () => ({
VotingModal: (p: any) => (
<div data-testid="modal">{p.isOpen ? "open" : "closed"}</div>
),
MobileVotingModal: (p: any) => (
<div data-testid="mobile-modal">{p.isOpen ? "open" : "closed"}</div>
),
}));
jest.mock('@/components/voting/VotingModalButton', () => (p: any) => (
<button data-testid="vote-btn" onClick={p.onClick}>vote</button>
jest.mock("@/components/voting/VotingModalButton", () => (p: any) => (
<button data-testid="vote-btn" onClick={p.onClick}>
vote
</button>
));
jest.mock(
"@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper",
() => (p: any) => (
<div data-testid="wrapper">
<button data-testid="after-leave" onClick={p.onAfterLeave}>
after leave
</button>
{p.children}
</div>
)
);
jest.mock("@/components/waves/drops/WaveDropMobileMenuDelete", () => () => (
<div data-testid="mobile-delete" />
));
jest.mock('@/components/utils/select/dropdown/CommonDropdownItemsMobileWrapper', () => (p: any) => <div data-testid="wrapper">{p.children}</div>);
jest.mock('@/components/waves/drops/WaveDropMobileMenuDelete', () => () => <div data-testid="mobile-delete"/>);
jest.mock('@/components/waves/drops/WaveDropMobileMenuOpen', () => () => <div data-testid="mobile-open"/>);
jest.mock('react-dom', () => ({
...jest.requireActual('react-dom'),
createPortal: (node: any) => node
jest.mock("@/components/waves/drops/WaveDropMobileMenuOpen", () => () => (
<div data-testid="mobile-open" />
));
jest.mock("@/components/waves/memes/submission/MemesArtResubmitAction", () => ({
MemesArtResubmitAction: (p: any) => (
<button data-testid="resubmit-action" onClick={p.onOpenModal}>
resubmit
</button>
),
}));
jest.mock("@/components/waves/memes/MemesArtSubmissionModal", () => ({
__esModule: true,
default: (p: any) =>
p.isOpen ? (
<button data-testid="resubmit-modal" onClick={p.onSourceDropDeleted}>
source deleted
</button>
) : null,
}));
jest.mock("react-dom", () => ({
...jest.requireActual("react-dom"),
createPortal: (node: any) => node,
}));

const drop: any = {
id: 'd1',
wave: { voting_credit_type: 'CREDIT' },
parts: [{ media: [{ mime_type: 'image', url: 'img' }] }],
metadata: [{ data_key: 'title', data_value: 'T' }, { data_key: 'description', data_value: 'D' }],
id: "d1",
wave: { id: "w1", voting_credit_type: "CREDIT" },
parts: [{ media: [{ mime_type: "image", url: "img" }] }],
metadata: [
{ data_key: "title", data_value: "T" },
{ data_key: "description", data_value: "D" },
],
rating: 1,
rating_prediction: 2,
raters_count: 0,
top_raters: [],
context_profile_context: 'ctx'
context_profile_context: "ctx",
};

beforeEach(() => {
useDropInteractionRules.mockReturnValue({ canDelete: true });
useLongPressInteraction.mockReturnValue({ isActive: false, setIsActive: jest.fn(), touchHandlers: {} });
useLongPressInteraction.mockReturnValue({
isActive: false,
setIsActive: jest.fn(),
touchHandlers: {},
});
});

test('calls onDropClick when not touch screen', async () => {
test("calls onDropClick when not touch screen", async () => {
useDeviceInfo.mockReturnValue({ hasTouchScreen: false });
useIsMobileScreen.mockReturnValue(false);
const onClick = jest.fn();
Expand All @@ -80,7 +149,7 @@ test('calls onDropClick when not touch screen', async () => {
expect(onClick).toHaveBeenCalledWith(drop);
});

test('does not call onDropClick on touch devices', async () => {
test("does not call onDropClick on touch devices", async () => {
useDeviceInfo.mockReturnValue({ hasTouchScreen: true });
useIsMobileScreen.mockReturnValue(false);
const onClick = jest.fn();
Expand All @@ -91,20 +160,74 @@ test('does not call onDropClick on touch devices', async () => {
expect(onClick).not.toHaveBeenCalled();
});

test('opens voting modal on desktop', async () => {
test("opens voting modal on desktop", async () => {
useDeviceInfo.mockReturnValue({ hasTouchScreen: false });
useIsMobileScreen.mockReturnValue(false);
render(<MemesLeaderboardDrop drop={drop} onDropClick={jest.fn()} />);
expect(screen.getByTestId('modal')).toHaveTextContent('closed');
await userEvent.click(screen.getByTestId('vote-btn'));
expect(screen.getByTestId('modal')).toHaveTextContent('open');
expect(screen.getByTestId("modal")).toHaveTextContent("closed");
await userEvent.click(screen.getByTestId("vote-btn"));
expect(screen.getByTestId("modal")).toHaveTextContent("open");
});

test('uses mobile modal on small screens', async () => {
test("uses mobile modal on small screens", async () => {
useDeviceInfo.mockReturnValue({ hasTouchScreen: false });
useIsMobileScreen.mockReturnValue(true);
render(<MemesLeaderboardDrop drop={drop} onDropClick={jest.fn()} />);
await userEvent.click(screen.getByTestId('vote-btn'));
expect(screen.getByTestId('mobile-modal')).toHaveTextContent('open');
await userEvent.click(screen.getByTestId("vote-btn"));
expect(screen.getByTestId("mobile-modal")).toHaveTextContent("open");
});

test("opens mobile resubmit modal after the touch menu leaves", async () => {
const setIsActive = jest.fn();
useDeviceInfo.mockReturnValue({ hasTouchScreen: true });
useIsMobileScreen.mockReturnValue(false);
useLongPressInteraction.mockReturnValueOnce({
isActive: true,
setIsActive,
touchHandlers: {},
});

render(
<MemesLeaderboardDrop
drop={drop}
wave={{ id: "w1" } as any}
onDropClick={jest.fn()}
/>
);

await userEvent.click(screen.getByTestId("resubmit-action"));

expect(setIsActive).toHaveBeenCalledWith(false);
expect(screen.queryByTestId("resubmit-modal")).not.toBeInTheDocument();

await userEvent.click(screen.getByTestId("after-leave"));

expect(screen.getByTestId("resubmit-modal")).toBeInTheDocument();
});

test("notifies when mobile resubmit deletes the source drop", async () => {
const setIsActive = jest.fn();
const onSourceDropDeleted = jest.fn();
useDeviceInfo.mockReturnValue({ hasTouchScreen: true });
useIsMobileScreen.mockReturnValue(false);
useLongPressInteraction.mockReturnValueOnce({
isActive: true,
setIsActive,
touchHandlers: {},
});

render(
<MemesLeaderboardDrop
drop={drop}
wave={{ id: "w1" } as any}
onDropClick={jest.fn()}
onSourceDropDeleted={onSourceDropDeleted}
/>
);

await userEvent.click(screen.getByTestId("resubmit-action"));
await userEvent.click(screen.getByTestId("after-leave"));
await userEvent.click(screen.getByTestId("resubmit-modal"));

expect(onSourceDropDeleted).toHaveBeenCalledTimes(1);
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@ jest.mock("@headlessui/react", () => {
);
const Transition = ({ show, children }: any) =>
show ? <div data-testid="root">{children}</div> : null;
const TransitionChild = ({ children }: any) => <div>{children}</div>;
const TransitionChild = ({ children, afterLeave }: any) => (
<div
data-testid={afterLeave ? "transition-after-leave" : undefined}
onClick={afterLeave}
>
{children}
</div>
);

return {
Dialog,
Expand Down Expand Up @@ -75,4 +82,23 @@ describe("CommonDropdownItemsMobileWrapper", () => {
fireEvent.click(screen.getByLabelText("Close panel"));
expect(setOpen).toHaveBeenCalledWith(false);
});

it("forwards after leave callback to the transition", () => {
const setOpen = jest.fn();
const onAfterLeave = jest.fn();

render(
<CommonDropdownItemsMobileWrapper
isOpen={true}
setOpen={setOpen}
onAfterLeave={onAfterLeave}
>
<li>child</li>
</CommonDropdownItemsMobileWrapper>
);

fireEvent.click(screen.getByTestId("transition-after-leave"));

expect(onAfterLeave).toHaveBeenCalled();
});
});
Loading
Loading