fix(payment): allow Stripe after closing QRIS
Docker Image / Build and Push Docker Image (push) Successful in 2m4s

This commit is contained in:
Codex
2026-07-29 14:31:49 +08:00
parent 3c74d30189
commit 8f8e067d82
5 changed files with 103 additions and 14 deletions
+1 -1
View File
@@ -286,7 +286,7 @@ export function SubscriptionScreen({
<PaymentMethodSelector
config={renderedPaymentMethodConfig}
value={payment.payChannel}
disabled={isPaymentBusy}
disabled={payment.isCreatingOrder}
caption={
paymentMethodConfig.ezpayDisplayName === "QRIS"
? "QRIS by default in Indonesia"
+1 -1
View File
@@ -292,7 +292,7 @@ export function TipScreen({
config={renderedPaymentMethodConfig}
value={payment.payChannel}
density="compact"
disabled={isPaymentBusy}
disabled={payment.isCreatingOrder}
className={styles.paymentMethodSlot}
analyticsKey="tip.payment_method"
onChange={handlePaymentMethodChange}
@@ -301,6 +301,37 @@ describe("payment order flow", () => {
actor.stop();
});
it("can abandon a pending QRIS order and switch to Stripe", async () => {
const createOrderSpy = vi.fn<CreateOrderSpy>();
const actor = createActor(
createTestPaymentMachine({ createOrderSpy, orderStatus: "pending" }),
).start();
await initialize(actor);
actor.send({ type: "PaymentPayChannelChanged", payChannel: "ezpay" });
actor.send({ type: "PaymentCreateOrderSubmitted" });
await waitFor(actor, (snapshot) => snapshot.matches("waitingForPayment"));
actor.send({ type: "PaymentPayChannelChanged", payChannel: "stripe" });
await waitFor(actor, (snapshot) => snapshot.matches("ready"));
expect(actor.getSnapshot().context).toMatchObject({
payChannel: "stripe",
currentOrderId: null,
payParams: null,
orderStatus: null,
orderPollingStartedAt: null,
});
actor.send({ type: "PaymentCreateOrderSubmitted" });
await waitFor(actor, (snapshot) => snapshot.matches("waitingForPayment"));
expect(createOrderSpy).toHaveBeenNthCalledWith(2, {
planId: "vip_monthly",
payChannel: "stripe",
autoRenew: true,
});
actor.stop();
});
it("moves to failed when polling reports failure", async () => {
const actor = createActor(
createTestPaymentMachine({ orderStatus: "failed" }),
+8
View File
@@ -265,6 +265,10 @@ const pollingOrderState = paymentMachineSetup.createStateConfig({
},
},
on: {
PaymentPayChannelChanged: {
target: "ready",
actions: "changePayChannel",
},
PaymentReset: {
target: "ready",
actions: "resetOrder",
@@ -277,6 +281,10 @@ const waitingForPaymentState = paymentMachineSetup.createStateConfig({
[POLL_DELAY_MS]: "pollingOrder",
},
on: {
PaymentPayChannelChanged: {
target: "ready",
actions: "changePayChannel",
},
PaymentReset: {
target: "ready",
actions: "resetOrder",