funktionierender stand, purchasewizard noch nicht optimiert.
This commit is contained in:
@@ -1,153 +1,69 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { execSync } from 'child_process';
|
||||
import { execSync } from 'child_process'; // Für artisan seed
|
||||
|
||||
const BASE_URL = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:8000';
|
||||
|
||||
function seedTestUser() {
|
||||
execSync('php artisan tenant:add-dummy --email=test@example.com --password=password123 --first_name=Test --last_name=User --address="Teststr. 1" --phone="+49123"', { stdio: 'ignore' });
|
||||
execSync('php artisan tinker --execute="App\\Models\\User::where(\'email\', \'test@example.com\')->update([\'email_verified_at\' => now()]);"', { stdio: 'ignore' });
|
||||
}
|
||||
|
||||
test.describe('Marketing Purchase Wizard', () => {
|
||||
test.beforeAll(() => {
|
||||
seedTestUser();
|
||||
test.describe('Marketing Package Flow: Auswahl → Registrierung → Kauf (Free & Paid)', () => {
|
||||
test.beforeAll(async () => {
|
||||
// Seed Test-Tenant (einmalig)
|
||||
execSync('php artisan tenant:add-dummy --email=test@example.com --password=password123 --first_name=Test --last_name=User --address="Teststr. 1" --phone="+49123"');
|
||||
// Mock Verifizierung: Update DB (in Test-Env)
|
||||
execSync('php artisan tinker --execute="App\\Models\\User::where(\'email\', \'test@example.com\')->update([\'email_verified_at\' => now()]);"');
|
||||
});
|
||||
|
||||
test('guest users see registration step after package selection', async ({ page }) => {
|
||||
await page.goto(`${BASE_URL}/purchase-wizard/1`);
|
||||
test('Free-Paket-Flow (ID=1, Starter)', async ({ page }) => {
|
||||
await page.goto('http://localhost:8000/de'); // Lokaler Server (vite dev)
|
||||
await expect(page).toHaveTitle(/Fotospiel/);
|
||||
await page.screenshot({ path: 'free-step1-home.png', fullPage: true });
|
||||
|
||||
await page.getByRole('button', { name: /Weiter/i }).click();
|
||||
// Paketauswahl
|
||||
await page.getByRole('link', { name: 'Alle Packages ansehen' }).click();
|
||||
await expect(page).toHaveURL(/\/de\/packages/);
|
||||
await page.screenshot({ path: 'free-step2-packages.png', fullPage: true });
|
||||
await page.getByRole('button', { name: 'Details anzeigen' }).first().click(); // Erstes Paket (Free)
|
||||
await expect(page.locator('dialog')).toBeVisible();
|
||||
await page.screenshot({ path: 'free-step3-modal.png', fullPage: true });
|
||||
await page.getByRole('tab', { name: 'Kaufen' }).click();
|
||||
await page.getByRole('link', { name: 'Registrieren & Kaufen' }).click();
|
||||
await expect(page).toHaveURL(/\/de\/register\?package_id=1/);
|
||||
await page.screenshot({ path: 'free-step4-register.png', fullPage: true });
|
||||
|
||||
await expect(page.getByText(/Registrieren/i)).toBeVisible();
|
||||
await expect(page.getByText(/Anmelden/i)).toBeVisible();
|
||||
// Registrierung (Test-Daten, aber seedet vorab – hier Login simulieren falls nötig)
|
||||
// Da seeded: Verwende Login statt neuer Registrierung für Test
|
||||
await page.fill('[name="email"]', 'test@example.com');
|
||||
await page.fill('[name="password"]', 'password123');
|
||||
await page.getByRole('button', { name: 'Anmelden' }).click(); // Falls Login-Form nach Redirect
|
||||
await expect(page).toHaveURL(/\/buy-packages\/1/);
|
||||
await page.screenshot({ path: 'free-step5-buy.png', fullPage: true });
|
||||
|
||||
// Kauf (Free: Direkte Success)
|
||||
await expect(page.locator('text=Free package assigned')).toContainText('success'); // API-Response oder Page-Text
|
||||
await page.goto('/marketing/success');
|
||||
await expect(page).toHaveURL(/\/marketing\/success/);
|
||||
await page.screenshot({ path: 'free-step6-success.png', fullPage: true });
|
||||
await expect(page).toHaveURL(/\/admin/); // Redirect
|
||||
await page.screenshot({ path: 'free-step7-admin.png', fullPage: true });
|
||||
await expect(page.locator('text=Remaining Photos')).toContainText('300'); // Limits aus package-flow.test.ts integriert
|
||||
});
|
||||
|
||||
test('authenticated users skip auth and can finish PayPal flow', async ({ page }) => {
|
||||
await page.route('https://js.stripe.com/v3', async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/javascript',
|
||||
body: `window.Stripe = function(){
|
||||
return {
|
||||
elements: function(){
|
||||
return {
|
||||
create: function(){
|
||||
return {
|
||||
mount: function(){},
|
||||
destroy: function(){},
|
||||
on: function(){},
|
||||
update: function(){},
|
||||
unmount: function(){},
|
||||
};
|
||||
},
|
||||
getElement: function(){
|
||||
return {
|
||||
clear: function(){},
|
||||
};
|
||||
}
|
||||
};
|
||||
},
|
||||
confirmCardPayment: async function(){
|
||||
return { paymentIntent: { id: 'pi_test', status: 'succeeded' } };
|
||||
}
|
||||
};
|
||||
};`
|
||||
});
|
||||
test('Paid-Paket-Flow (ID=2, Pro mit Stripe-Test)', async ({ page }) => {
|
||||
// Ähnlich wie Free, aber package_id=2
|
||||
await page.goto('http://localhost:8000/de/packages');
|
||||
await page.getByRole('button', { name: 'Details anzeigen' }).nth(1).click(); // Zweites Paket (Paid)
|
||||
// ... (Modal, Register/Login wie oben)
|
||||
await expect(page).toHaveURL(/\/buy-packages\/2/);
|
||||
|
||||
// Mock Stripe
|
||||
await page.route('https://checkout.stripe.com/**', async route => {
|
||||
await route.fulfill({ status: 200, body: '<html>Mock Stripe Success</html>' });
|
||||
});
|
||||
// Simuliere Checkout: Fill Test-Karte
|
||||
await page.fill('[name="cardNumber"]', '4242424242424242');
|
||||
await page.fill('[name="cardExpiry"]', '12/25');
|
||||
await page.fill('[name="cardCvc"]', '123');
|
||||
await page.click('[name="submit"]');
|
||||
await page.waitForURL(/\/marketing\/success/); // Nach Webhook
|
||||
await page.screenshot({ path: 'paid-step6-success.png', fullPage: true });
|
||||
|
||||
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){
|
||||
return {
|
||||
render: function(container){
|
||||
const target = typeof container === 'string' ? document.querySelector(container) : container;
|
||||
if (!target) return;
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.textContent = 'PayPal Test Button';
|
||||
btn.addEventListener('click', async () => {
|
||||
try {
|
||||
const orderId = await options.createOrder();
|
||||
await options.onApprove({ orderID: orderId });
|
||||
} catch (error) {
|
||||
if (options.onError) options.onError(error);
|
||||
}
|
||||
});
|
||||
target.innerHTML = '';
|
||||
target.appendChild(btn);
|
||||
},
|
||||
close: function(){}
|
||||
};
|
||||
}
|
||||
};`
|
||||
});
|
||||
});
|
||||
|
||||
await page.route('**/purchase/auth/login', (route) => route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
status: 'authenticated',
|
||||
user: { id: 1, email: 'test@example.com', name: 'Test User', pending_purchase: false, email_verified: true },
|
||||
next_step: 'payment',
|
||||
needs_verification: false,
|
||||
}),
|
||||
}));
|
||||
|
||||
await page.route('**/purchase/auth/register', (route) => route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
status: 'registered',
|
||||
user: { id: 2, email: 'new@example.com', name: 'New User', pending_purchase: true, email_verified: false },
|
||||
next_step: 'payment',
|
||||
}),
|
||||
}));
|
||||
|
||||
await page.route('**/purchase/stripe/intent', (route) => route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ client_secret: 'pi_secret', payment_intent_id: 'pi_test' }),
|
||||
}));
|
||||
|
||||
await page.route('**/purchase/stripe/complete', (route) => route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ status: 'completed' }),
|
||||
}));
|
||||
|
||||
await page.route('**/purchase/paypal/order', (route) => route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ order_id: 'ORDER-TEST', status: 'CREATED' }),
|
||||
}));
|
||||
|
||||
await page.route('**/purchase/paypal/capture', (route) => route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ status: 'captured' }),
|
||||
}));
|
||||
|
||||
await page.goto(`${BASE_URL}/de/login`);
|
||||
await page.fill('input[name="login"]', 'test@example.com');
|
||||
await page.fill('input[name="password"]', 'password123');
|
||||
await page.getByRole('button', { name: /Anmelden/i }).click();
|
||||
await expect(page).toHaveURL(/dashboard|admin/i, { timeout: 10000 });
|
||||
|
||||
await page.goto(`${BASE_URL}/purchase-wizard/2`);
|
||||
|
||||
await page.getByRole('button', { name: /Weiter/i }).click();
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Stripe' })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'PayPal' })).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'PayPal' }).click();
|
||||
await page.getByRole('button', { name: 'PayPal Test Button' }).click();
|
||||
|
||||
await expect(page.getByText(/Willkommen/i)).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: /Dashboard/i })).toBeVisible();
|
||||
// Integration: Limits-Check wie in package-flow.test.ts
|
||||
await expect(page.locator('text=Remaining Photos')).toContainText('Unbegrenzt'); // Pro-Limit
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user