refactor(subscription): tighten payment flow boundaries

This commit is contained in:
2026-06-30 15:36:49 +08:00
parent 61504050e5
commit 218df59345
9 changed files with 640 additions and 286 deletions
@@ -0,0 +1,48 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { ROUTES } from "@/router/routes";
import { consumePendingChatImageReturn } from "../chat_image_return_session";
import {
consumeSubscriptionExitUrl,
consumeSubscriptionExplicitExitUrl,
getSubscriptionFallbackExitUrl,
} from "../subscription_exit";
vi.mock("../chat_image_return_session", () => ({
consumePendingChatImageReturn: vi.fn(),
}));
const consumePendingChatImageReturnMock = vi.mocked(
consumePendingChatImageReturn,
);
describe("subscription exit helpers", () => {
beforeEach(() => {
consumePendingChatImageReturnMock.mockReset();
});
it("uses explicit chat image return urls first", () => {
consumePendingChatImageReturnMock.mockReturnValue({
reason: "image_paywall",
messageId: "msg_1",
returnUrl: "/chat/image/msg_1",
createdAt: 1,
});
expect(consumeSubscriptionExplicitExitUrl()).toBe("/chat/image/msg_1");
});
it("falls back to chat when requested", () => {
consumePendingChatImageReturnMock.mockReturnValue(null);
expect(consumeSubscriptionExitUrl("chat")).toBe(ROUTES.chat);
});
it("falls back to sidebar by default", () => {
consumePendingChatImageReturnMock.mockReturnValue(null);
expect(getSubscriptionFallbackExitUrl(null)).toBe(ROUTES.sidebar);
expect(consumeSubscriptionExitUrl(null)).toBe(ROUTES.sidebar);
});
});
+28
View File
@@ -0,0 +1,28 @@
"use client";
import { ROUTES } from "@/router/routes";
import { consumePendingChatImageReturn } from "./chat_image_return_session";
export type SubscriptionReturnTo = "chat" | null;
export function consumeSubscriptionExplicitExitUrl(): string | null {
const pendingImageReturn = consumePendingChatImageReturn();
if (pendingImageReturn) return pendingImageReturn.returnUrl;
return null;
}
export function getSubscriptionFallbackExitUrl(
returnTo: SubscriptionReturnTo,
): string {
return returnTo === "chat" ? ROUTES.chat : ROUTES.sidebar;
}
export function consumeSubscriptionExitUrl(
returnTo: SubscriptionReturnTo,
): string {
return (
consumeSubscriptionExplicitExitUrl() ??
getSubscriptionFallbackExitUrl(returnTo)
);
}