fix(private-room): preserve payment return route

This commit is contained in:
2026-07-16 18:06:15 +08:00
parent b64a90f0e3
commit 4981de9b18
17 changed files with 280 additions and 21 deletions
@@ -12,6 +12,7 @@ import {
consumeSubscriptionExplicitExitUrl,
getSubscriptionFallbackExitUrl,
peekSubscriptionExplicitExitUrl,
resolveSubscriptionSuccessExitUrl,
} from "../subscription_exit";
vi.mock("../chat_image_return_session", () => ({
@@ -65,6 +66,69 @@ describe("subscription exit helpers", () => {
);
});
it("returns directly to private room without consuming chat state", async () => {
consumePendingChatImageReturnMock.mockResolvedValue({
reason: "image_paywall",
messageId: "msg_1",
returnUrl: "/chat?image=msg_1",
createdAt: 1,
});
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",
returnUrl: "/chat?image=msg_1",
stage: "payment",
createdAt: 1,
});
expect(getSubscriptionFallbackExitUrl("private-room")).toBe(
ROUTES.privateRoom,
);
await expect(consumeSubscriptionExitUrl("private-room")).resolves.toBe(
ROUTES.privateRoom,
);
expect(consumePendingChatImageReturnMock).not.toHaveBeenCalled();
expect(peekPendingChatUnlockMock).not.toHaveBeenCalled();
expect(clearPendingChatUnlockMock).not.toHaveBeenCalled();
});
it("keeps private room ahead of stale chat state after payment", async () => {
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",
returnUrl: "/chat?image=msg_1",
stage: "payment",
createdAt: 1,
});
await expect(
resolveSubscriptionSuccessExitUrl("private-room"),
).resolves.toBe(ROUTES.privateRoom);
expect(peekPendingChatUnlockMock).not.toHaveBeenCalled();
expect(clearPendingChatUnlockMock).not.toHaveBeenCalled();
});
it("keeps pending chat unlocks ahead of chat fallback after payment", async () => {
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",
returnUrl: "/chat?image=msg_1",
stage: "payment",
createdAt: 1,
});
await expect(resolveSubscriptionSuccessExitUrl("chat")).resolves.toBe(
"/chat?image=msg_1",
);
expect(clearPendingChatUnlockMock).not.toHaveBeenCalled();
});
it("peeks chat unlock return urls without clearing them", async () => {
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",