endcustomer()->create(['price' => 0]); $registrationData = [ 'email' => 'flow@example.com', 'password' => 'Password123!', 'password_confirmation' => 'Password123!', 'first_name' => 'Max', 'last_name' => 'Mustermann', 'privacy_consent' => true, 'terms' => true, 'package_id' => $freePackage->id, 'locale' => 'de', ]; $response = $this->postJson(route('checkout.register'), $registrationData); $this->assertDatabaseHas('users', ['email' => 'flow@example.com']); $user = User::where('email', 'flow@example.com')->first(); $this->assertDatabaseHas('tenants', ['user_id' => $user->id]); $tenant = Tenant::where('user_id', $user->id)->first(); $this->assertAuthenticated(); $response->assertOk(); $this->assertNotNull($user); $this->assertNotNull($tenant); $this->assertDatabaseHas('tenant_packages', [ 'tenant_id' => $tenant->id, 'package_id' => $freePackage->id, 'active' => true, ]); // Für E2E-Test: Simuliere Email-Verification $user->markEmailAsVerified(); // Schritt 2: Logout und Login Auth::logout(); $this->assertGuest(); $loginResponse = $this->post(route('login.store'), [ 'login' => 'flow@example.com', 'password' => 'Password123!', ]); $this->assertAuthenticated(); $loginResponse->assertRedirect(CheckoutRoutes::wizardUrl($freePackage->id, 'de')); // Schritt 3: Paid Package Bestellung (Mock Paddle) $paidPackage = Package::factory()->reseller()->create(['price' => 10]); // Simuliere Kauf (GET zu buy.packages, aber da es Redirect ist, prüfe Session oder folge) // Für E2E: Angenommen, nach Mock wird Package zugewiesen (in real: Webhook, hier simuliere Success) // Erstelle manuell für Test (in real: via Success-Route nach Zahlung) // Simuliere Success nach Zahlung TenantPackage::create([ 'tenant_id' => $tenant->id, 'package_id' => $paidPackage->id, 'active' => true, 'price' => 10, 'purchased_at' => now(), 'expires_at' => now()->addYear(), ]); PackagePurchase::create([ 'tenant_id' => $tenant->id, 'package_id' => $paidPackage->id, 'type' => 'reseller_subscription', 'provider' => 'paddle', 'provider_id' => 'paddle_txn_123', 'price' => 10, 'purchased_at' => now(), ]); $tenant->update(['subscription_status' => 'active']); // Assertions für gesamten Flow $this->assertDatabaseHas('package_purchases', [ 'tenant_id' => $tenant->id, 'package_id' => $paidPackage->id, 'type' => 'reseller_subscription', 'provider' => 'paddle', ]); $this->assertEquals(1, PackagePurchase::where('tenant_id', $tenant->id)->count()); // Mock Mails (nur Welcome, da Purchase keine dedizierte Klasse hat) Mail::assertQueued(Welcome::class, function ($mail) use ($user) { return $mail->to[0]['address'] === $user->email; }); // Finaler Redirect zu Success oder Dashboard $successResponse = $this->actingAs($user)->get(route('marketing.success', [ 'locale' => 'de', 'packageId' => $paidPackage->id, ])); $successResponse->assertRedirect('/event-admin'); $successResponse->assertStatus(302); } public function test_full_user_flow_with_errors() { // Schritt 1: Fehlgeschlagene Registrierung (kein Consent) $response = $this->post('/de/register', [ 'name' => 'Error User', 'email' => 'error@example.com', 'password' => 'Password123!', 'password_confirmation' => 'Password123!', 'first_name' => 'Max', 'last_name' => 'Mustermann', 'privacy_consent' => false, ]); $response->assertRedirect(route('packages', ['locale' => 'de'])); $this->assertGuest(); $this->assertDatabaseMissing('users', ['email' => 'error@example.com']); // Schritt 2: Fehlgeschlagener Login (Rate Limit) $user = User::factory()->create([ 'email' => 'ratelimit@example.com', 'password' => bcrypt('password'), ]); for ($i = 0; $i < 5; $i++) { $this->post(route('login.store'), [ 'login' => 'ratelimit@example.com', 'password' => 'wrong', ]); } $throttleResponse = $this->post(route('login.store'), [ 'login' => 'ratelimit@example.com', 'password' => 'wrong', ]); $throttleResponse->assertSessionHasErrors(['login']); $errors = session('errors'); $this->assertMatchesRegularExpression('/Zu viele Login-Versuche\. Bitte versuche es in \d+ Sekunden erneut\./', $errors->first('login')); $this->assertGuest(); // Schritt 3: Bestellung ohne Auth blockiert $package = Package::factory()->create(['price' => 10]); $buyResponse = $this->get(route('buy.packages', [ 'locale' => 'de', 'packageId' => $package->id, ])); $buyResponse->assertRedirect(CheckoutRoutes::wizardUrl($package->id, 'de')); // Nach Korrektur: Erfolgreicher Flow (kurz) // ... (ähnlich wie oben, aber mit Error-Handling) } }