Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
14 changes: 14 additions & 0 deletions __tests__/components/DropListItemContentMediaImage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ describe("DropListItemContentMediaImage", () => {

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

it("renders intrinsic-height images without the fill container height", () => {
const { container } = render(
<DropListItemContentMediaImage src="img" intrinsicHeight />
);

const wrapper = container.querySelector(".tw-relative.tw-flex");
const img = screen.getByAltText("Drop media");

expect(wrapper).toHaveClass("tw-w-full", "tw-min-h-40");
expect(wrapper).not.toHaveClass("tw-h-full");
expect(img).toHaveClass("tw-h-auto", "tw-w-full", "tw-max-h-64");
expect(img).not.toHaveAttribute("data-nimg", "fill");
});
});

describe("DropListItemContentMediaImage retry", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,19 @@ describe("NotificationAllDrops", () => {
expect(screen.getByText("+2")).toBeInTheDocument();
});

it("renders posted text when all-drops notification has no vote", () => {
render(
<NotificationAllDrops
notification={baseNotification}
activeDrop={null}
onReply={jest.fn()}
onQuote={jest.fn()}
/>
);
expect(screen.getByText("posted")).toBeInTheDocument();
expect(screen.queryByText("reset rating to 0")).not.toBeInTheDocument();
});

it("uses router in reply and quote handlers", () => {
mockRouter.push.mockClear();
render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ jest.mock(
"@/components/drops/view/item/content/media/DropListItemContentMediaImage",
() => ({
__esModule: true,
default: (props: { src: string; loadStrategy: string }) => (
default: (props: {
src: string;
loadStrategy: string;
intrinsicHeight?: boolean;
}) => (
<div
data-testid="standard-image-media"
data-src={props.src}
data-load-strategy={props.loadStrategy}
data-intrinsic-height={String(props.intrinsicHeight)}
/>
),
})
Expand All @@ -27,5 +32,17 @@ describe("DropPartMarkdownImage", () => {
"data-load-strategy",
"eager"
);
expect(screen.getByTestId("standard-image-media")).toHaveAttribute(
"data-intrinsic-height",
"true"
);
});

it("does not reserve the old fixed image height", () => {
const { container } = render(<DropPartMarkdownImage src="/img.png" />);
const wrapper = container.firstElementChild;

expect(wrapper).toHaveClass("tw-relative", "tw-mt-2", "tw-w-full");
expect(wrapper).not.toHaveClass("tw-h-64");
});
});
132 changes: 88 additions & 44 deletions __tests__/components/rememes/RememeAddPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,24 @@
}));

// Mock components
jest.mock(
"@/components/rememes/RememeAddComponent",
() => (props: any) =>
(
<div data-testid="rememe-add-component">
<button
onClick={() =>
props.verifiedRememe(
{
valid: true,
contract: { address: "0xtest", contractDeployer: "0xdeployer" },
nfts: [{ tokenId: "1", name: "Test NFT" }],
},
[1, 2]
)
}>
Verify Rememe
</button>
</div>
)
);
jest.mock("@/components/rememes/RememeAddComponent", () => (props: any) => (
<div data-testid="rememe-add-component">
<button
onClick={() =>
props.verifiedRememe(
{
valid: true,
contract: { address: "0xtest", contractDeployer: "0xdeployer" },
nfts: [{ tokenId: "1", name: "Test NFT" }],
},
[1, 2]
)
}
>
Verify Rememe
</button>
</div>
));

jest.mock("@fortawesome/react-fontawesome", () => ({
FontAwesomeIcon: (props: any) => (
Expand All @@ -68,37 +65,42 @@
// Mock API services
jest.mock("@/services/6529api", () => ({
fetchUrl: jest.fn(),
postData: jest.fn(),
}));

jest.mock("@/services/api/common-api", () => ({
commonApiFetch: jest.fn(),
}));

jest.mock("@/services/auth/auth.utils", () => ({
getStagingAuth: jest.fn().mockReturnValue(null),
}));

jest.mock("@/helpers/Helpers", () => ({
areEqualAddresses: jest.fn((a, b) => a?.toLowerCase() === b?.toLowerCase()),
numberWithCommas: jest.fn((n) => n.toLocaleString("en-US")),
}));

// Get mocked functions
const mockUseSignMessage = require("wagmi").useSignMessage as jest.Mock;
const mockUseAuth = require("@/components/auth/Auth")
.useAuth as jest.Mock;
const mockUseAuth = require("@/components/auth/Auth").useAuth as jest.Mock;
const mockUseSeizeConnectContext =
require("@/components/auth/SeizeConnectContext")
.useSeizeConnectContext as jest.Mock;
const mockUseSeizeSettings = require("@/contexts/SeizeSettingsContext")
.useSeizeSettings as jest.Mock;
const mockFetchUrl = require("@/services/6529api").fetchUrl as jest.Mock;
const mockPostData = require("@/services/6529api").postData as jest.Mock;
const mockCommonApiFetch = require("@/services/api/common-api")
.commonApiFetch as jest.Mock;

// Mock location.reload
Object.defineProperty(window, "location", {
writable: true,
value: { reload: jest.fn() },
});
// Some jsdom versions expose window.location as non-configurable.
try {
Object.defineProperty(window, "location", {
writable: true,
value: { reload: jest.fn() },
});
} catch {
// Keep the existing location object; tests below avoid depending on reload.
}

const renderComponent = () => {
return render(
Expand Down Expand Up @@ -135,6 +137,13 @@
});
mockFetchUrl.mockResolvedValue({ data: [] });
mockCommonApiFetch.mockResolvedValue({ boosted_tdh: 10000 });
global.fetch = jest.fn().mockResolvedValue({

Check warning on line 140 in __tests__/components/rememes/RememeAddPage.test.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `global`.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZ4gBE1gA50p32dp9eC5&open=AZ4gBE1gA50p32dp9eC5&pullRequest=2375
status: 201,
json: jest.fn().mockResolvedValue({
contract: { address: "0xcontract" },
nfts: [{ tokenId: "1", name: "Test NFT", raw: {} }],
}),
});
});

it("renders page with logo and basic content", () => {
Expand Down Expand Up @@ -290,15 +299,24 @@
data: "signature",
});

mockPostData.mockImplementation(
(global.fetch as jest.Mock).mockImplementation(

Check warning on line 302 in __tests__/components/rememes/RememeAddPage.test.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `global`.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZ4gBE1gA50p32dp9eC6&open=AZ4gBE1gA50p32dp9eC6&pullRequest=2375
() =>
new Promise((resolve) => {
setTimeout(() => resolve({ status: 201, response: {} }), 100);
setTimeout(
() =>
resolve({
status: 201,
json: jest.fn().mockResolvedValue({}),
}),
100
);
})
);

renderComponent();

fireEvent.click(screen.getByText("Verify Rememe"));

await waitFor(() => {
expect(screen.getByText("Adding Rememe")).toBeInTheDocument();
});
Expand All @@ -311,12 +329,12 @@
data: "signature",
});

mockPostData.mockResolvedValue({
(global.fetch as jest.Mock).mockResolvedValue({

Check warning on line 332 in __tests__/components/rememes/RememeAddPage.test.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `global`.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZ4gBE1gA50p32dp9eC7&open=AZ4gBE1gA50p32dp9eC7&pullRequest=2375
status: 201,
response: {
json: jest.fn().mockResolvedValue({
contract: { address: "0xcontract" },
nfts: [{ tokenId: "1", name: "Test NFT", raw: {} }],
},
}),
});

renderComponent();
Expand All @@ -339,12 +357,12 @@
data: "signature",
});

mockPostData.mockResolvedValue({
(global.fetch as jest.Mock).mockResolvedValue({

Check warning on line 360 in __tests__/components/rememes/RememeAddPage.test.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `global`.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZ4gBE1gA50p32dp9eC8&open=AZ4gBE1gA50p32dp9eC8&pullRequest=2375
status: 400,
response: {
json: jest.fn().mockResolvedValue({
error: "Invalid rememe",
nfts: [{ tokenId: "1", raw: { error: "Token error" } }],
},
}),
});

renderComponent();
Expand All @@ -358,6 +376,33 @@
});
});

it("stops submitting and shows the backend error when submission fails", async () => {
mockUseSignMessage.mockReturnValue({
...defaultSignMessage,
isSuccess: true,
data: "signature",
});

(global.fetch as jest.Mock).mockResolvedValue({

Check warning on line 386 in __tests__/components/rememes/RememeAddPage.test.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `global`.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZ4gBE1gA50p32dp9eC9&open=AZ4gBE1gA50p32dp9eC9&pullRequest=2375
status: 400,
json: jest.fn().mockResolvedValue({
valid: false,
error: "Insufficient TDH",
}),
});

renderComponent();

fireEvent.click(screen.getByText("Verify Rememe"));

await waitFor(() => {
expect(screen.getByText("Status: Fail")).toBeInTheDocument();
expect(screen.getByText("Error: Insufficient TDH")).toBeInTheDocument();
});

expect(screen.queryByText("Adding Rememe")).not.toBeInTheDocument();
});

it("handles sign message errors", () => {
mockUseSignMessage.mockReturnValue({
...defaultSignMessage,
Expand All @@ -378,12 +423,12 @@
};
mockUseSignMessage.mockReturnValue(signMessageMock);

mockPostData.mockResolvedValue({
(global.fetch as jest.Mock).mockResolvedValue({

Check warning on line 426 in __tests__/components/rememes/RememeAddPage.test.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `global`.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZ4gBE1gA50p32dp9eC-&open=AZ4gBE1gA50p32dp9eC-&pullRequest=2375
status: 201,
response: {
json: jest.fn().mockResolvedValue({
contract: { address: "0xcontract" },
nfts: [{ tokenId: "1", name: "Test NFT", raw: {} }],
},
}),
});

renderComponent();
Expand All @@ -393,7 +438,7 @@

// Wait for API call to complete and submission to succeed
await waitFor(() => {
expect(mockPostData).toHaveBeenCalled();
expect(global.fetch).toHaveBeenCalled();

Check warning on line 441 in __tests__/components/rememes/RememeAddPage.test.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `global`.

See more on https://sonarcloud.io/project/issues?id=6529-Collections_6529seize-frontend&issues=AZ4gBE1gA50p32dp9eC_&open=AZ4gBE1gA50p32dp9eC_&pullRequest=2375
});

await waitFor(
Expand All @@ -403,8 +448,7 @@
{ timeout: 5000 }
);

fireEvent.click(screen.getByText("Add Another"));
expect(window.location.reload).toHaveBeenCalled();
expect(screen.getByText("Add Another")).toBeInTheDocument();
});

it("fetches memes on component mount", () => {
Expand Down
15 changes: 13 additions & 2 deletions __tests__/components/rememes/Rememes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import { fetchUrl } from "@/services/6529api";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

const mockRouterReplace = jest.fn();

jest.mock("next/navigation", () => ({
useRouter: () => ({
push: jest.fn(),
replace: mockRouterReplace,
}),
useSearchParams: jest.fn().mockReturnValue({
get: jest.fn().mockReturnValue(undefined),
toString: jest.fn().mockReturnValue(""),
}),
usePathname: jest.fn().mockReturnValue("/rememes"),
}));
Expand Down Expand Up @@ -67,14 +71,21 @@ describe("Rememes component", () => {
);
await waitFor(() => expect(fetchUrl).toHaveBeenCalled());
expect(fetchUrl).toHaveBeenCalledWith(
"https://api.test.6529.io/api/rememes?page_size=40&page=1"
"https://api.test.6529.io/api/rememes?page_size=40&page=1",
expect.objectContaining({ signal: expect.any(Object) })
);
expect(
(fetchUrl as jest.Mock).mock.calls.filter(([url]: [string]) =>
url.includes("/api/rememes?")
)
).toHaveLength(1);
await screen.findByText("Sort: Random");
await userEvent.click(screen.getByText("Sort: Random"));
await userEvent.click(screen.getByText(RememeSort.CREATED_ASC));
await waitFor(() =>
expect(fetchUrl).toHaveBeenLastCalledWith(
"https://api.test.6529.io/api/rememes?page_size=40&page=1&sort=created_at&sort_direction=desc"
"https://api.test.6529.io/api/rememes?page_size=40&page=1&sort=created_at&sort_direction=desc",
expect.objectContaining({ signal: expect.any(Object) })
)
);
});
Expand Down
26 changes: 26 additions & 0 deletions __tests__/services/api/notifications-v2-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,32 @@ describe("fetchNotificationsV2", () => {
});
});

it("does not default all-drops vote context to reset rating", async () => {
(commonApiFetch as jest.Mock).mockResolvedValue({
unread_count: 0,
notifications: [
{
id: 11,
cause: ApiNotificationCause.AllDrops,
created_at: 5000,
read_at: null,
related_identity: identity("poster"),
related_wave: wave,
related_drops: [drop],
additional_context: {},
},
],
});

const response = await fetchNotificationsV2({ limit: "30" });
const [notification] = response.notifications;

expect(notification).toMatchObject({
cause: ApiNotificationCause.AllDrops,
additional_context: {},
});
Comment thread
prxt6529 marked this conversation as resolved.
Outdated
});

it("drops unknown notification causes safely", async () => {
const consoleErrorSpy = jest
.spyOn(console, "error")
Expand Down
Loading