Files
fotospiel-app/tests/ui/purchase/checkout-payment.test.ts
2026-02-04 12:43:40 +01:00

170 lines
5.4 KiB
TypeScript

import { test, expectFixture as expect } from '../helpers/test-fixtures';
const demoTenantCredentials = {
email: process.env.E2E_DEMO_TENANT_EMAIL ?? 'tenant-demo@fotospiel.app',
password: process.env.E2E_DEMO_TENANT_PASSWORD ?? 'Demo1234!',
};
test.describe('Checkout Payment Step - PayPal flow', () => {
test('creates PayPal order and completes capture', async ({ page }) => {
let createPayload: Record<string, unknown> | null = null;
let capturePayload: Record<string, unknown> | null = null;
await page.route('**/paypal/create-order', async (route) => {
createPayload = route.request().postDataJSON() as Record<string, unknown>;
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
order_id: 'order_test_123',
checkout_session_id: 'session_test_123',
}),
});
});
await page.route('**/paypal/capture-order', async (route) => {
capturePayload = route.request().postDataJSON() as Record<string, unknown>;
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
status: 'completed',
}),
});
});
await page.route('https://www.paypal.com/sdk/js**', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/javascript',
body: `
window.paypal = {
Buttons: function(options) {
window.__paypalOptions = options;
return {
render: function() { return Promise.resolve(); },
};
},
};
`,
});
});
await openCheckoutPaymentStep(page, demoTenantCredentials);
await acceptCheckoutTerms(page);
await expect.poll(async () => {
return page.evaluate(() => Boolean(window.__paypalOptions));
}).toBe(true);
const orderId = await page.evaluate(async () => {
return window.__paypalOptions?.createOrder?.();
});
expect(orderId).toBe('order_test_123');
await expect(page.getByText(/PayPal-Checkout ist bereit|PayPal checkout is ready/i)).toBeVisible();
await page.evaluate(async () => {
await window.__paypalOptions?.onApprove?.({ orderID: 'order_test_123' });
});
expect(createPayload?.package_id).toBeDefined();
expect(capturePayload?.order_id).toBe('order_test_123');
});
test('shows error state when PayPal checkout creation fails', async ({ page }) => {
await page.route('**/paypal/create-order', async (route) => {
await route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({ message: 'test-error' }),
});
});
await page.route('https://www.paypal.com/sdk/js**', async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/javascript',
body: `
window.paypal = {
Buttons: function(options) {
window.__paypalOptions = options;
return {
render: function() { return Promise.resolve(); },
};
},
};
`,
});
});
await openCheckoutPaymentStep(page, demoTenantCredentials);
await acceptCheckoutTerms(page);
await expect.poll(async () => {
return page.evaluate(() => Boolean(window.__paypalOptions));
}).toBe(true);
await page.evaluate(async () => {
try {
await window.__paypalOptions?.createOrder?.();
} catch {
// swallow error for assertion below
}
});
await expect(
page.locator('text=/PayPal-Checkout konnte nicht gestartet werden|PayPal checkout could not be started/i')
).toBeVisible();
});
});
async function openCheckoutPaymentStep(
page: import('@playwright/test').Page,
credentials: { email: string; password: string }
) {
await page.goto('/packages');
const detailsButtons = page.getByRole('button', {
name: /Details ansehen|Details anzeigen|View details/i,
});
await expect(detailsButtons.first()).toBeVisible();
await detailsButtons.first().click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await dialog.getByRole('link', { name: /Jetzt bestellen|Order now|Jetzt buchen/i }).click();
await expect(page).toHaveURL(/\/(bestellen|checkout)\/\d+/);
await page.getByRole('button', { name: /^Weiter$/ }).first().click();
const continueButton = page.getByRole('button', { name: /Weiter zur Zahlung|Continue to Payment/i });
if (await continueButton.isVisible()) {
await continueButton.click();
} else {
await page.getByRole('button', { name: /^Anmelden$/ }).first().click();
await expect(page.locator('input[name="identifier"]')).toBeVisible();
await page.fill('input[name="identifier"]', credentials.email);
await page.fill('input[name="password"]', credentials.password);
await page.getByRole('button', { name: /^Anmelden$/ }).last().click();
}
await expect(page.getByPlaceholder(/Gutscheincode/i)).toBeVisible();
}
async function acceptCheckoutTerms(page: import('@playwright/test').Page) {
const termsCheckbox = page.locator('#checkout-terms-hero');
await expect(termsCheckbox).toBeVisible();
await termsCheckbox.click();
}
declare global {
interface Window {
__paypalOptions?: {
createOrder?: () => Promise<string>;
onApprove?: (data: { orderID: string }) => Promise<void>;
};
}
}