170 lines
5.4 KiB
TypeScript
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>;
|
|
};
|
|
}
|
|
}
|