Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 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
Expand Up @@ -2,8 +2,36 @@ import {
clampResearchTargetEditionSize,
getAutoSelectedLaunchPhase,
getDefaultResearchTargetEditionSize,
getLaunchListStatus,
getResearchTargetEditionSizeLimit,
} from "@/components/drop-forge/launch/drop-forge-launch-claim-page-client.helpers";
import type { ClaimPrimaryStatus } from "@/components/drop-forge/drop-forge-status.helpers";
import { ManifoldClaimStatus } from "@/hooks/useManifoldClaim";

type AutoSelectedLaunchPhaseArgs = Parameters<
typeof getAutoSelectedLaunchPhase
>[0];

// Wrapper that supplies sensible defaults for the booleans each test would
// otherwise have to pass; individual tests can override via `overrides`.
function callGetAutoSelectedLaunchPhase(
overrides: Omit<
AutoSelectedLaunchPhaseArgs,
"researchAirdropCompleted" | "payArtistCompleted"
> &
Partial<
Pick<
AutoSelectedLaunchPhaseArgs,
"researchAirdropCompleted" | "payArtistCompleted"
>
>
): ReturnType<typeof getAutoSelectedLaunchPhase> {
return getAutoSelectedLaunchPhase({
researchAirdropCompleted: false,
payArtistCompleted: false,
...overrides,
});
}

describe("getAutoSelectedLaunchPhase", () => {
const phases = [
Expand Down Expand Up @@ -39,7 +67,7 @@ describe("getAutoSelectedLaunchPhase", () => {

it("returns blank when metadata is not published", () => {
expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: false,
isInitialized: true,
nowMs: 1_500,
Expand All @@ -50,7 +78,7 @@ describe("getAutoSelectedLaunchPhase", () => {

it("keeps phase0 selected until the claim is initialized", () => {
expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: false,
nowMs: 7_500,
Expand All @@ -61,7 +89,7 @@ describe("getAutoSelectedLaunchPhase", () => {

it("selects phase0 before it starts and while it is active", () => {
expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 500,
Expand All @@ -70,7 +98,7 @@ describe("getAutoSelectedLaunchPhase", () => {
).toBe("phase0");

expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 1_500,
Expand All @@ -81,7 +109,7 @@ describe("getAutoSelectedLaunchPhase", () => {

it("moves to the next upcoming phase after a phase ends", () => {
expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 2_500,
Expand All @@ -90,7 +118,7 @@ describe("getAutoSelectedLaunchPhase", () => {
).toBe("phase1");

expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 4_500,
Expand All @@ -101,7 +129,7 @@ describe("getAutoSelectedLaunchPhase", () => {

it("selects public phase until it ends, then research", () => {
expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 7_500,
Expand All @@ -110,7 +138,7 @@ describe("getAutoSelectedLaunchPhase", () => {
).toBe("publicphase");

expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 8_001,
Expand All @@ -121,7 +149,7 @@ describe("getAutoSelectedLaunchPhase", () => {

it("does not fall back to phase0 when phase0's schedule is null but later phases still exist", () => {
expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 8_001,
Expand All @@ -134,7 +162,7 @@ describe("getAutoSelectedLaunchPhase", () => {

it("ignores a null schedule on a later phase when an earlier valid phase still matches", () => {
expect(
getAutoSelectedLaunchPhase({
callGetAutoSelectedLaunchPhase({
hasPublishedMetadata: true,
isInitialized: true,
nowMs: 3_500,
Expand Down Expand Up @@ -181,3 +209,103 @@ describe("research target edition size helpers", () => {
expect(clampResearchTargetEditionSize(310, null)).toBe(310);
});
});

describe("getLaunchListStatus", () => {
const livePrimaryStatus: ClaimPrimaryStatus = {
key: "live",
label: "Live",
tone: "success",
reason: "DB, Arweave, and onchain metadata all match",
};

it("keeps live claims live when the current manifold phase is upcoming", () => {
expect(
getLaunchListStatus({
primaryStatus: livePrimaryStatus,
manifoldClaim: {
status: ManifoldClaimStatus.UPCOMING,
nextMemePhase: {
id: "1",
name: "Phase 1",
},
} as any,
researchAirdropCompleted: false,
payArtistCompleted: false,
})
).toEqual(livePrimaryStatus);
});

it("keeps live claims live when manifold only exposes a next phase", () => {
expect(
getLaunchListStatus({
primaryStatus: livePrimaryStatus,
manifoldClaim: {
status: ManifoldClaimStatus.ENDED,
nextMemePhase: {
id: "public",
name: "Public Phase",
},
} as any,
researchAirdropCompleted: false,
payArtistCompleted: false,
})
).toEqual(livePrimaryStatus);
});

it("falls back to Airdrop Research when the drop has ended and actions are loaded", () => {
expect(
getLaunchListStatus({
primaryStatus: livePrimaryStatus,
manifoldClaim: {
status: ManifoldClaimStatus.ENDED,
} as any,
researchAirdropCompleted: false,
payArtistCompleted: false,
actionsLoaded: true,
})
).toEqual({
key: "live",
label: "Airdrop Research",
tone: "post_mint",
reason: "Mint phases are complete. Research airdrop is next",
});
});

it("shows Checking Onchain for ended drops while action state is still loading", () => {
expect(
getLaunchListStatus({
primaryStatus: livePrimaryStatus,
manifoldClaim: {
status: ManifoldClaimStatus.ENDED,
} as any,
researchAirdropCompleted: false,
payArtistCompleted: false,
actionsLoaded: false,
})
).toEqual({
key: "checking_onchain",
label: "Checking Onchain",
tone: "pending",
reason: "Loading post-launch action state",
});
});

it("prefers Pay Artist over the loading state when research is already marked complete", () => {
expect(
getLaunchListStatus({
primaryStatus: livePrimaryStatus,
manifoldClaim: {
status: ManifoldClaimStatus.ENDED,
} as any,
researchAirdropCompleted: true,
payArtistCompleted: false,
actionsLoaded: false,
})
).toEqual({
key: "live",
label: "Pay Artist",
tone: "post_mint",
reason: "Research airdrop is complete. Artist payment remains",
});
});
});
21 changes: 21 additions & 0 deletions __tests__/components/home/LatestDropNextMintSubscribe.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,27 @@ describe("LatestDropNextMintSubscribe", () => {
);
});

it("disables retries for expected subscription lookup errors", () => {
renderWithAuth(<LatestDropNextMintSubscribe />);

expect(useQueryMock).toHaveBeenCalledWith(
expect.objectContaining({
queryKey: ["next-mint-subscription-details", expect.any(String)],
retry: false,
})
);
expect(useQueryMock).toHaveBeenCalledWith(
expect.objectContaining({
queryKey: [
"next-mint-subscription-status",
expect.any(String),
expect.any(Number),
],
retry: false,
})
);
});

it("falls back to status eligibility when details are unavailable", () => {
useQueryMock.mockImplementation(({ queryKey }) => {
if (queryKey[0] === "next-mint-subscription-details") {
Expand Down
7 changes: 7 additions & 0 deletions __tests__/components/providers/metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ describe("Metadata functionality (migrated from _document.tsx)", () => {
});
});

it("uses 6529.io as the default production title", () => {
const metadata = getAppMetadata();

expect(metadata.title).toBe("6529.io");
expect(metadata.openGraph?.title).toBe("6529.io");
});
Comment thread
prxt6529 marked this conversation as resolved.

it("accepts custom metadata overrides", () => {
const customMetadata = {
title: "Custom Title",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,37 @@ describe("MemeSubscriptionRow", () => {
expect(screen.getByText("0.5")).toBeInTheDocument();
});

it("disables retries for final subscription lookups", () => {
renderWithAuth(
<MemeSubscriptionRow
profileKey="test-key"
title="The Memes"
subscription={
{
token_id: 478,
contract: "0x123",
subscribed: true,
subscribed_count: 2,
} as any
}
eligibilityCount={3}
readonly
refresh={jest.fn()}
minting_today={false}
first
date={null}
/>
);

expect(useQueryMock).toHaveBeenCalledWith(
expect.objectContaining({
queryKey: ["consolidation-final-subscription", "test-key-0x123-478"],
enabled: true,
retry: false,
})
);
});

it("omits phase metadata when the final subscription is unavailable", () => {
useQueryMock.mockImplementation(({ queryKey }) => {
if (queryKey[0] === "consolidation-final-subscription") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ describe("UserPageSubscriptionsUpcoming", () => {
expect.objectContaining({
queryKey: ["consolidation-final-subscription", "testuser-0x123-1"],
enabled: true,
retry: false,
})
);
});
Expand Down
37 changes: 37 additions & 0 deletions __tests__/contexts/TitleContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,41 @@ describe("TitleContext", () => {
expect(document.title).toBe("Discovery");
});
});

it("restores the default home title after leaving messages", async () => {
mockPathname = "/messages";
mockSearchParams = new URLSearchParams("wave=wave-1");

const view = render(
<TitleProvider>
<DynamicHeadTitle />
<TitleHarness waveData={{ name: "Wave One", newItemsCount: 0 }} />
</TitleProvider>
);

await waitFor(() => {
expect(screen.getByText("Wave One | Brain")).toBeInTheDocument();
});
await waitFor(() => {
expect(document.title).toBe("Wave One | Brain");
});

mockPathname = "/";
mockSearchParams = new URLSearchParams();
mockActiveWaveId = null;

view.rerender(
<TitleProvider>
<DynamicHeadTitle />
<TitleHarness waveData={null} />
</TitleProvider>
);

await waitFor(() => {
expect(screen.getByText("6529.io")).toBeInTheDocument();
});
await waitFor(() => {
expect(document.title).toBe("6529.io");
});
});
});
Loading
Loading