fix(chat): suppress paywall for missing unlock
This commit is contained in:
@@ -490,6 +490,68 @@ describe("chat unlock flow", () => {
|
|||||||
actor.stop();
|
actor.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not request payment when the unlock target is not found", async () => {
|
||||||
|
const actor = createActor(
|
||||||
|
createTestChatMachine({
|
||||||
|
historyMessages: [
|
||||||
|
{
|
||||||
|
id: "msg-missing",
|
||||||
|
content: "",
|
||||||
|
isFromAI: true,
|
||||||
|
date: "2026-06-29",
|
||||||
|
locked: true,
|
||||||
|
lockReason: "private_message",
|
||||||
|
privateMessageHint: "A private message is waiting.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
unlockMessageOutput: {
|
||||||
|
messageId: "msg-missing",
|
||||||
|
response: makeUnlockPrivateResponse({
|
||||||
|
unlocked: false,
|
||||||
|
content: "",
|
||||||
|
reason: "not_found",
|
||||||
|
creditBalance: 3,
|
||||||
|
creditsCharged: 0,
|
||||||
|
requiredCredits: 0,
|
||||||
|
shortfallCredits: 0,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).start();
|
||||||
|
|
||||||
|
actor.send({ type: "ChatUserLogin", token: "token" });
|
||||||
|
await waitFor(actor, (snapshot) =>
|
||||||
|
snapshot.matches({ userSession: "ready" }),
|
||||||
|
);
|
||||||
|
|
||||||
|
actor.send({
|
||||||
|
type: "ChatUnlockMessageRequested",
|
||||||
|
messageId: "msg-missing",
|
||||||
|
kind: "private",
|
||||||
|
});
|
||||||
|
|
||||||
|
await waitFor(
|
||||||
|
actor,
|
||||||
|
(snapshot) => snapshot.context.unlockMessageError === "not_found",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(actor.getSnapshot().context).toMatchObject({
|
||||||
|
isUnlockingMessage: false,
|
||||||
|
unlockingMessageId: null,
|
||||||
|
unlockMessageError: "not_found",
|
||||||
|
unlockPaywallRequest: null,
|
||||||
|
});
|
||||||
|
expect(actor.getSnapshot().context.messages).toMatchObject([
|
||||||
|
{
|
||||||
|
id: "msg-missing",
|
||||||
|
locked: true,
|
||||||
|
lockReason: "private_message",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
actor.stop();
|
||||||
|
});
|
||||||
|
|
||||||
it("clears the insufficient credits prompt after payment succeeds", async () => {
|
it("clears the insufficient credits prompt after payment succeeds", async () => {
|
||||||
const actor = createActor(createTestChatMachine()).start();
|
const actor = createActor(createTestChatMachine()).start();
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ const applyUnlockMessageSucceededAction = sendMachineSetup.assign(
|
|||||||
const requestUnlockPaymentFromOutputAction = sendMachineSetup.assign(
|
const requestUnlockPaymentFromOutputAction = sendMachineSetup.assign(
|
||||||
({ context, event }) => {
|
({ context, event }) => {
|
||||||
const { output } = event as unknown as DoneActorEvent<UnlockMessageOutput>;
|
const { output } = event as unknown as DoneActorEvent<UnlockMessageOutput>;
|
||||||
|
const shouldOpenPaywall = output.response.reason !== "not_found";
|
||||||
return {
|
return {
|
||||||
promotion: applyPromotionUnlockOutput(context.promotion, output),
|
promotion: applyPromotionUnlockOutput(context.promotion, output),
|
||||||
isUnlockingMessage: false,
|
isUnlockingMessage: false,
|
||||||
@@ -94,30 +95,32 @@ const requestUnlockPaymentFromOutputAction = sendMachineSetup.assign(
|
|||||||
unlockingLockType: null,
|
unlockingLockType: null,
|
||||||
unlockingClientLockId: null,
|
unlockingClientLockId: null,
|
||||||
unlockMessageError: output.response.reason,
|
unlockMessageError: output.response.reason,
|
||||||
unlockPaywallRequest: {
|
unlockPaywallRequest: shouldOpenPaywall
|
||||||
displayMessageId:
|
? {
|
||||||
output.response.messageId || output.displayMessageId,
|
displayMessageId:
|
||||||
...(output.response.messageId || output.request.messageId
|
output.response.messageId || output.displayMessageId,
|
||||||
? {
|
...(output.response.messageId || output.request.messageId
|
||||||
messageId:
|
? {
|
||||||
output.response.messageId || output.request.messageId,
|
messageId:
|
||||||
}
|
output.response.messageId || output.request.messageId,
|
||||||
: {}),
|
}
|
||||||
kind: context.unlockingMessageKind ?? "private",
|
: {}),
|
||||||
...(output.request.lockType
|
kind: context.unlockingMessageKind ?? "private",
|
||||||
? { lockType: output.request.lockType }
|
...(output.request.lockType
|
||||||
: {}),
|
? { lockType: output.request.lockType }
|
||||||
...(output.request.clientLockId
|
: {}),
|
||||||
? { clientLockId: output.request.clientLockId }
|
...(output.request.clientLockId
|
||||||
: {}),
|
? { clientLockId: output.request.clientLockId }
|
||||||
...(context.promotion?.message.id === output.displayMessageId
|
: {}),
|
||||||
? { promotion: context.promotion.session }
|
...(context.promotion?.message.id === output.displayMessageId
|
||||||
: {}),
|
? { promotion: context.promotion.session }
|
||||||
reason: output.response.reason,
|
: {}),
|
||||||
creditBalance: output.response.creditBalance,
|
reason: output.response.reason,
|
||||||
requiredCredits: output.response.requiredCredits,
|
creditBalance: output.response.creditBalance,
|
||||||
shortfallCredits: output.response.shortfallCredits,
|
requiredCredits: output.response.requiredCredits,
|
||||||
},
|
shortfallCredits: output.response.shortfallCredits,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
creditBalance: output.response.creditBalance,
|
creditBalance: output.response.creditBalance,
|
||||||
requiredCredits: output.response.requiredCredits,
|
requiredCredits: output.response.requiredCredits,
|
||||||
shortfallCredits: output.response.shortfallCredits,
|
shortfallCredits: output.response.shortfallCredits,
|
||||||
|
|||||||
Reference in New Issue
Block a user