138 lines
3.9 KiB
TypeScript
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();
|
|
});
|
|
});
|