Files
cozsweet-frontend-nextjs/src/router/__tests__/navigation-resolver.test.ts
T

138 lines
3.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
isAuthenticatedUser,
resolveAuthenticatedNavigation,
resolveRouteGuardRedirect,
} from "../navigation-resolver";
import { ROUTE_BUILDERS, ROUTES } from "../routes";
describe("navigation resolver", () => {
it("treats only real login providers as authenticated users", () => {
expect(isAuthenticatedUser("notLoggedIn")).toBe(false);
expect(isAuthenticatedUser("guest")).toBe(false);
expect(isAuthenticatedUser("email")).toBe(true);
expect(isAuthenticatedUser("facebook")).toBe(true);
});
it("wraps protected navigation with auth redirect for guests", () => {
expect(
resolveAuthenticatedNavigation({
loginStatus: "guest",
targetUrl: "/subscription?type=vip",
}),
).toBe(ROUTE_BUILDERS.authWithRedirect("/subscription?type=vip"));
});
it("keeps protected navigation targets for authenticated users", () => {
expect(
resolveAuthenticatedNavigation({
loginStatus: "google",
targetUrl: "/subscription?type=topup",
}),
).toBe("/subscription?type=topup");
});
it("preserves payment analytics context through auth redirects", () => {
const subscriptionUrl = ROUTE_BUILDERS.subscription("topup", {
payChannel: "stripe",
returnTo: "chat",
analytics: {
entryPoint: "chat_unlock",
triggerReason: "ad_landing",
},
});
expect(subscriptionUrl).toBe(
"/subscription?type=topup&payChannel=stripe&returnTo=chat&analytics_entry=chat_unlock&analytics_reason=ad_landing",
);
expect(
resolveAuthenticatedNavigation({
loginStatus: "guest",
targetUrl: subscriptionUrl,
}),
).toBe(ROUTE_BUILDERS.authWithRedirect(subscriptionUrl));
});
it("builds private zone subscription return urls", () => {
expect(
ROUTE_BUILDERS.subscription("topup", {
payChannel: "stripe",
returnTo: "private-zone",
sourceCharacterSlug: "maya",
}),
).toBe(
"/subscription?type=topup&payChannel=stripe&returnTo=private-zone&character=maya",
);
});
it("keeps the user-bound offer and server-selected plan in the subscription URL", () => {
expect(
ROUTE_BUILDERS.subscription("vip", {
returnTo: "chat",
sourceCharacterSlug: "elio",
planId: "vip_annual",
commercialOfferId: "offer-1",
}),
).toBe(
"/subscription?type=vip&returnTo=chat&character=elio&planId=vip_annual&commercialOfferId=offer-1",
);
});
it("allows not logged in users to enter chat for guest bootstrap", () => {
expect(
resolveRouteGuardRedirect({
loginStatus: "notLoggedIn",
pathname: ROUTES.chat,
}),
).toBeNull();
});
it.each(["notLoggedIn", "guest"] as const)(
"redirects %s users from profile to auth with the return context",
(loginStatus) => {
expect(
resolveRouteGuardRedirect({
loginStatus,
pathname: ROUTES.profile,
searchParams: "returnTo=%2Fcharacters%2Fmaya%2Fchat",
}),
).toBe(
ROUTE_BUILDERS.authWithRedirect(
"/profile?returnTo=%2Fcharacters%2Fmaya%2Fchat",
),
);
},
);
it("redirects non-real users on subscription routes to auth", () => {
expect(
resolveRouteGuardRedirect({
loginStatus: "guest",
pathname: ROUTES.subscription,
searchParams: "type=vip&returnTo=chat",
}),
).toBe(
ROUTE_BUILDERS.authWithRedirect(
"/subscription?type=vip&returnTo=chat",
),
);
});
it("allows public and authorized routes", () => {
expect(
resolveRouteGuardRedirect({
loginStatus: "guest",
pathname: ROUTES.coinsRules,
}),
).toBeNull();
expect(
resolveRouteGuardRedirect({
loginStatus: "email",
pathname: ROUTES.subscription,
searchParams: "type=vip",
}),
).toBeNull();
});
});