fix(chat): isolate pending flows and cancel stale requests

This commit is contained in:
2026-07-17 19:22:01 +08:00
parent 2fc312b5c7
commit 8bb1e21886
27 changed files with 501 additions and 92 deletions
@@ -39,6 +39,7 @@ describe("subscription exit helpers", () => {
it("uses explicit chat image return urls first", async () => {
consumePendingChatImageReturnMock.mockResolvedValue({
reason: "image_paywall",
characterId: "character_elio",
messageId: "msg_1",
returnUrl: "/chat?image=msg_1",
createdAt: 1,
@@ -73,12 +74,14 @@ describe("subscription exit helpers", () => {
it("returns directly to private room without consuming chat state", async () => {
consumePendingChatImageReturnMock.mockResolvedValue({
reason: "image_paywall",
characterId: "character_elio",
messageId: "msg_1",
returnUrl: "/chat?image=msg_1",
createdAt: 1,
});
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
characterId: "character_elio",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",
@@ -101,6 +104,7 @@ describe("subscription exit helpers", () => {
it("keeps private room ahead of stale chat state after payment", async () => {
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
characterId: "character_elio",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",
@@ -119,6 +123,7 @@ describe("subscription exit helpers", () => {
it("keeps pending chat unlocks ahead of chat fallback after payment", async () => {
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
characterId: "character_elio",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",
@@ -136,6 +141,7 @@ describe("subscription exit helpers", () => {
it("peeks chat unlock return urls without clearing them", async () => {
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
characterId: "character_elio",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",
@@ -154,6 +160,7 @@ describe("subscription exit helpers", () => {
consumePendingChatImageReturnMock.mockResolvedValue(null);
peekPendingChatUnlockMock.mockResolvedValue({
reason: "single_message_unlock",
characterId: "character_elio",
displayMessageId: "msg_1",
messageId: "msg_1",
kind: "image",