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
91 changes: 90 additions & 1 deletion __tests__/components/providers/MixpanelSetup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,20 @@ const identifyMock = jest.fn();
const initAnalyticsMock = jest.fn();
const trackPageViewMock = jest.fn();

let connectedProfile: { id: number } | null = null;
let connectedProfile: {
id: number;
normalised_handle?: string | null;
wallets?: Array<{ wallet: string }>;
} | null = null;
let fetchingProfile = false;
let pathname = "/";
let performanceConsent: boolean | undefined = undefined;
let searchParams = new URLSearchParams();

jest.mock("@/components/auth/Auth", () => ({
useAuth: () => ({
connectedProfile,
fetchingProfile,
}),
}));

Expand All @@ -41,6 +47,7 @@ jest.mock("@/services/analytics/mixpanel", () => ({
describe("MixpanelSetup", () => {
beforeEach(() => {
connectedProfile = null;
fetchingProfile = false;
pathname = "/";
performanceConsent = undefined;
searchParams = new URLSearchParams();
Expand Down Expand Up @@ -134,6 +141,88 @@ describe("MixpanelSetup", () => {
});
});

it("tracks anonymous profile views separately from signed-in viewers", () => {
performanceConsent = true;
pathname = "/alice/collected";

render(<MixpanelSetup />);

expect(trackPageViewMock).toHaveBeenCalledWith("/alice/collected", {
has_connected_profile: false,
logical_page: "profile_collected",
page_group: "profile",
profile_viewer_context: "anonymous",
route_pattern: "/:handle/collected",
});
});

it("marks own profile tabs as self views", () => {
performanceConsent = true;
pathname = "/alice/collected";
connectedProfile = {
id: 42,
normalised_handle: "alice",
wallets: [],
};

render(<MixpanelSetup />);

expect(trackPageViewMock).toHaveBeenCalledWith("/alice/collected", {
has_connected_profile: true,
logical_page: "profile_collected",
page_group: "profile",
profile_viewer_context: "self",
route_pattern: "/:handle/collected",
});
});

it("marks other users' profile tabs as other views", () => {
performanceConsent = true;
pathname = "/bob/collected";
connectedProfile = {
id: 42,
normalised_handle: "alice",
wallets: [{ wallet: "0xabc" }],
};

render(<MixpanelSetup />);

expect(trackPageViewMock).toHaveBeenCalledWith("/bob/collected", {
has_connected_profile: true,
logical_page: "profile_collected",
page_group: "profile",
profile_viewer_context: "other",
route_pattern: "/:handle/collected",
});
});

it("waits for profile ownership data before tracking profile page views", () => {
performanceConsent = true;
pathname = "/alice/collected";
fetchingProfile = true;

const { rerender } = render(<MixpanelSetup />);

expect(trackPageViewMock).not.toHaveBeenCalled();

fetchingProfile = false;
connectedProfile = {
id: 42,
normalised_handle: "alice",
wallets: [],
};
rerender(<MixpanelSetup />);

expect(trackPageViewMock).toHaveBeenCalledTimes(1);
expect(trackPageViewMock).toHaveBeenCalledWith("/alice/collected", {
has_connected_profile: true,
logical_page: "profile_collected",
page_group: "profile",
profile_viewer_context: "self",
route_pattern: "/:handle/collected",
});
});

it("identifies connected profiles and resets when consent is revoked", () => {
performanceConsent = true;
pathname = "/waves";
Expand Down
120 changes: 93 additions & 27 deletions __tests__/components/user/layout/UserPageTabs.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AuthContext } from "@/components/auth/Auth";
import UserPageTabs from "@/components/user/layout/UserPageTabs";
import { USER_PAGE_TAB_IDS } from "@/components/user/layout/userTabs.config";
import { render, screen } from "@testing-library/react";
import { render, screen, waitFor } from "@testing-library/react";
import {
useParams,
usePathname,
Expand All @@ -15,6 +14,10 @@ jest.mock("next/navigation", () => ({
useSearchParams: jest.fn(),
useParams: jest.fn(),
}));
const useAuthMock = jest.fn();
jest.mock("@/components/auth/Auth", () => ({
useAuth: () => useAuthMock(),
}));
const capacitorMock = jest.fn();
jest.mock("@/hooks/useCapacitor", () => ({
__esModule: true,
Expand All @@ -32,14 +35,24 @@ const {
useCookieConsent,
} = require("@/components/cookies/CookieConsentContext");

const renderTabs = (
showWaves: boolean,
isIos: boolean,
country: string = "US",
connectedProfile: any = null
) => {
(useRouter as jest.Mock).mockReturnValue({ push: jest.fn() });
(usePathname as jest.Mock).mockReturnValue("/[user]");
const renderTabs = ({
showWaves,
isIos,
country = "US",
connectedProfile = null,
fetchingProfile = false,
pathname = "/[user]",
}: {
showWaves: boolean;
isIos: boolean;
country?: string;
connectedProfile?: any;
fetchingProfile?: boolean;
pathname?: string;
}) => {
const router = { push: jest.fn(), replace: jest.fn() };
(useRouter as jest.Mock).mockReturnValue(router);
(usePathname as jest.Mock).mockReturnValue(pathname);
(useSearchParams as jest.Mock).mockReturnValue(new URLSearchParams());
(useParams as jest.Mock).mockReturnValue({ user: "testuser" });
capacitorMock.mockReturnValue({ isIos });
Expand All @@ -49,58 +62,111 @@ const renderTabs = (
consent: jest.fn(),
reject: jest.fn(),
});
return render(
<AuthContext.Provider value={{ showWaves, connectedProfile } as any}>
<UserPageTabs />
</AuthContext.Provider>
);
useAuthMock.mockReturnValue({
showWaves,
connectedProfile,
fetchingProfile,
});
return {
router,
...render(<UserPageTabs />),
};
};

describe("UserPageTabs", () => {
it("filters tabs based on context and platform", () => {
renderTabs(false, false);
renderTabs({ showWaves: false, isIos: false });
const tabs = screen.getAllByTestId("tab").map((t) => t.textContent);
expect(tabs).not.toContain(USER_PAGE_TAB_IDS.BRAIN);
expect(tabs).not.toContain("stats");
expect(tabs).toContain(USER_PAGE_TAB_IDS.SUBSCRIPTIONS);
});

it("hides subscriptions tab on iOS non-US", () => {
renderTabs(true, true, "CA");
renderTabs({ showWaves: true, isIos: true, country: "CA" });
const tabs = screen.getAllByTestId("tab").map((t) => t.textContent);
expect(tabs).not.toContain(USER_PAGE_TAB_IDS.SUBSCRIPTIONS);
});

it("shows proxy tab when viewing own profile by handle", () => {
renderTabs(false, false, "US", {
normalised_handle: "testuser",
wallets: [],
renderTabs({
showWaves: false,
isIos: false,
connectedProfile: {
normalised_handle: "testuser",
wallets: [],
},
});
const tabs = screen.getAllByTestId("tab").map((t) => t.textContent);
expect(tabs).toContain(USER_PAGE_TAB_IDS.PROXY);
});

it("shows proxy tab when viewing own profile by wallet", () => {
renderTabs(false, false, "US", {
normalised_handle: "otherhandle",
wallets: [{ wallet: "testuser" }],
renderTabs({
showWaves: false,
isIos: false,
connectedProfile: {
normalised_handle: "otherhandle",
wallets: [{ wallet: "testuser" }],
},
});
const tabs = screen.getAllByTestId("tab").map((t) => t.textContent);
expect(tabs).toContain(USER_PAGE_TAB_IDS.PROXY);
});

it("hides proxy tab when viewing another user's profile", () => {
renderTabs(false, false, "US", {
normalised_handle: "anotheruser",
wallets: [{ wallet: "0xSomeOtherWallet" }],
renderTabs({
showWaves: false,
isIos: false,
connectedProfile: {
normalised_handle: "anotheruser",
wallets: [{ wallet: "0xSomeOtherWallet" }],
},
});
const tabs = screen.getAllByTestId("tab").map((t) => t.textContent);
expect(tabs).not.toContain(USER_PAGE_TAB_IDS.PROXY);
});

it("hides proxy tab when not connected", () => {
renderTabs(false, false, "US", null);
renderTabs({ showWaves: false, isIos: false });
const tabs = screen.getAllByTestId("tab").map((t) => t.textContent);
expect(tabs).not.toContain(USER_PAGE_TAB_IDS.PROXY);
});

it("keeps the proxy tab visible while ownership is still loading", () => {
const { router } = renderTabs({
showWaves: false,
isIos: false,
pathname: "/testuser/proxy",
fetchingProfile: true,
});

const tabs = screen.getAllByTestId("tab").map((t) => t.textContent);
expect(tabs).toContain(USER_PAGE_TAB_IDS.PROXY);
expect(router.replace).not.toHaveBeenCalled();
});

it("redirects away from the proxy tab after loading when the profile is not owned", async () => {
const { rerender, router } = renderTabs({
showWaves: false,
isIos: false,
pathname: "/testuser/proxy",
fetchingProfile: true,
});

useAuthMock.mockReturnValue({
showWaves: false,
connectedProfile: {
normalised_handle: "someoneelse",
wallets: [{ wallet: "0xSomeOtherWallet" }],
},
fetchingProfile: false,
});

rerender(<UserPageTabs />);

await waitFor(() => {
expect(router.replace).toHaveBeenCalledWith("/testuser");
});
});
});
Loading
Loading