feat(payment): confirm renewal only at checkout

This commit is contained in:
Codex
2026-07-29 11:26:42 +08:00
parent f6c75dcb86
commit 1466cb01d2
15 changed files with 492 additions and 240 deletions
+4 -5
View File
@@ -2,18 +2,17 @@ import { expect, type Page } from "@playwright/test";
export async function completeVipPayment(page: Page) {
const checkoutButton = page.getByRole("button", { name: "Pay and Top Up" });
await expect(checkoutButton).toBeDisabled();
await page.getByRole("button", { name: /Monthly,/i }).click();
await expect(checkoutButton).toBeEnabled();
await checkoutButton.click();
const renewalDialog = page.getByRole("dialog", {
name: "Automatic Renewal Confirmation",
});
await expect(renewalDialog).toBeVisible();
await renewalDialog.getByRole("button", { name: "Confirm" }).click();
await expect(checkoutButton).toBeEnabled();
const createOrderRequestPromise = page.waitForRequest("**/api/payment/create-order");
const orderStatusRequestPromise = page.waitForRequest("**/api/payment/order-status**");
await checkoutButton.click();
await renewalDialog.getByRole("button", { name: "Confirm" }).click();
const createOrderRequest = await createOrderRequestPromise;
expect(createOrderRequest.postDataJSON()).toMatchObject({ planId: "vip_monthly", payChannel: "stripe" });
await orderStatusRequestPromise;
@@ -74,16 +74,17 @@ test("offers the Facebook external-browser path before creating a Stripe order",
});
await seedEmailSession(page);
await page.goto("/subscription?type=vip&payChannel=stripe");
await page.goto(
"/subscription?type=vip&payChannel=stripe&character=elio",
);
await page.getByRole("button", { name: /Monthly,/i }).click();
await page
.getByRole("dialog", { name: "Automatic Renewal Confirmation" })
.getByRole("button", { name: "Confirm" })
.click();
const externalButton = page.getByRole("button", {
name: "Open in browser for more payment methods",
});
await expect(externalButton).toBeVisible();
await expect(externalButton).toBeEnabled();
await expect(
page.getByRole("dialog", { name: "Automatic Renewal Confirmation" }),
).toHaveCount(0);
const handoffRequest = page.waitForRequest("**/api/auth/handoff/checkout");
await externalButton.click();
expect((await handoffRequest).postDataJSON()).toMatchObject({
+4 -12
View File
@@ -223,19 +223,11 @@ test("Indonesia VIP defaults to QRIS and completes after status polling", async
"true",
);
const checkoutButton = page.getByRole("button", { name: "Pay and Top Up" });
await expect(checkoutButton).toBeDisabled();
await expectCheckoutButtonLayout(page);
await page.getByRole("button", { name: /Monthly, 195900 IDR/i }).click();
const renewalDialog = page.getByRole("dialog", {
name: "Automatic Renewal Confirmation",
});
await expect(renewalDialog).toBeVisible();
expect(payment.getCreateOrderCount()).toBe(0);
await renewalDialog.getByRole("button", { name: "Confirm" }).click();
await expect(renewalDialog).toBeHidden();
await expect(checkoutButton).toBeEnabled();
await expectCheckoutButtonLayout(page);
await expect(
page.getByRole("dialog", { name: "Automatic Renewal Confirmation" }),
).toHaveCount(0);
expect(payment.getCreateOrderCount()).toBe(0);
const orderId = await expectQrisOrder(
@@ -0,0 +1,23 @@
import { expect, test } from "@playwright/test";
test("serves the VIP membership benefits agreement from the same site", async ({
page,
}) => {
const response = await page.goto("/legal/vip-membership-benefits.html");
expect(response?.status()).toBe(200);
await expect(
page.getByRole("heading", { name: "VIP Membership Benefits Agreement" }),
).toBeVisible();
});
test("serves the automatic renewal agreement from the same site", async ({
page,
}) => {
const response = await page.goto("/legal/automatic-renewal.html");
expect(response?.status()).toBe(200);
await expect(
page.getByRole("heading", { name: "Automatic Renewal Agreement" }),
).toBeVisible();
});