create([ 'is_active' => true, 'name' => 'Original Name', 'language' => 'de', ]); $this->actingAs($customer); LivewireVolt::test('customer.profile') ->assertSee('Rechnungsadresse') ->set('name', 'Neuer Anzeigename') ->set('firstName', 'Max') ->set('lastName', 'Mustermann') ->set('language', 'en') ->set('address', 'Musterfirma GmbH, Musterstrasse 1, 10115 Berlin') ->set('countryCode', 'AT') ->set('billingName', 'Musterfirma GmbH') ->set('billingAddress1', 'Musterstrasse 1') ->set('billingPostalCode', '10115') ->set('billingCity', 'Berlin') ->set('billingCountryCode', 'DE') ->set('taxIdNumber', 'ATU12345678') ->set('showStats', true) ->call('saveProfile') ->assertHasNoErrors(); $customer->refresh(); expect($customer->name)->toBe('Neuer Anzeigename'); expect($customer->language)->toBe('en'); expect($customer->profile?->first_name)->toBe('Max'); expect($customer->profile?->last_name)->toBe('Mustermann'); expect($customer->profile?->address)->toBe('Musterfirma GmbH, Musterstrasse 1, 10115 Berlin'); expect($customer->profile?->country_code)->toBe('AT'); expect($customer->profile?->tax_id_number)->toBe('ATU12345678'); expect($customer->profile?->show_stats)->toBeTrue(); expect($customer->billingAddress?->name)->toBe('Musterfirma GmbH'); expect($customer->billingAddress?->address1)->toBe('Musterstrasse 1'); expect($customer->billingAddress?->postal_code)->toBe('10115'); expect($customer->billingAddress?->city)->toBe('Berlin'); expect($customer->billingAddress?->country_code)->toBe('DE'); }); test('customer profile keeps company management out of the profile page', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'owner_user_id' => $customer->id, 'name' => 'Nicht im Profil geladene Firma', ]); $customer->companies()->attach($company->id, ['role' => 'owner']); $this->actingAs($customer); LivewireVolt::test('customer.profile') ->assertSee('Rechnungsadresse') ->assertSee('Profileinstellungen') ->assertSee('Firmen verwalten') ->assertDontSee('Zugeordnete Firmen') ->assertDontSee('Nicht im Profil geladene Firma'); }); test('customer can save profile settings without a billing address', function () { /** @var TestCase $this */ $customer = User::factory()->create([ 'is_active' => true, 'name' => 'Ohne Rechnung', ]); $this->actingAs($customer); LivewireVolt::test('customer.profile') ->set('name', 'Nur Profil') ->set('firstName', 'Nur') ->set('lastName', 'Profil') ->call('saveProfile') ->assertHasNoErrors(); expect($customer->refresh()->name)->toBe('Nur Profil'); expect($customer->billingAddress)->toBeNull(); }); test('customer security page renders password and email forms', function () { /** @var TestCase $this */ $customer = User::factory()->create([ 'is_active' => true, 'password' => bcrypt('current-password'), ]); $this->actingAs($customer); LivewireVolt::test('customer.security') ->assertSee('Konto-Sicherheit') ->assertSee('Letzter Login') ->assertSee('Aktive Sessions') ->assertSee('Passwort ändern') ->assertSee('E-Mail-Adresse ändern') ->assertSee('Zwei-Faktor-Authentifizierung'); }); test('customer can change own password through security page', function () { /** @var TestCase $this */ $customer = User::factory()->create([ 'is_active' => true, 'password' => bcrypt('current-password'), ]); $this->actingAs($customer); LivewireVolt::test('customer.security') ->set('current_password', 'current-password') ->set('password', 'new-strong-password') ->set('password_confirmation', 'new-strong-password') ->call('updatePassword') ->assertHasNoErrors(); $customer->refresh(); expect(Hash::check('new-strong-password', $customer->password))->toBeTrue(); }); test('press release policy denies access to other users releases', function () { /** @var TestCase $this */ $owner = User::factory()->create(['is_active' => true]); $intruder = User::factory()->create(['is_active' => true]); $pr = PressRelease::factory()->create([ 'user_id' => $owner->id, 'status' => 'draft', ]); expect($intruder->can('view', $pr))->toBeFalse(); expect($intruder->can('update', $pr))->toBeFalse(); expect($owner->can('view', $pr))->toBeTrue(); expect($owner->can('update', $pr))->toBeTrue(); }); test('me press release routes only resolve own press releases even for admins', function () { /** @var TestCase $this */ $this->seed(RolesAndPermissionsSeeder::class); $admin = User::factory()->create(['is_active' => true]); $admin->assignRole('admin'); $otherUser = User::factory()->create(['is_active' => true]); $otherPressRelease = PressRelease::factory()->create([ 'user_id' => $otherUser->id, 'status' => 'draft', ]); $this->actingAs($admin); $this->get(route('me.press-releases.show', $otherPressRelease->id)) ->assertNotFound(); $this->get(route('me.press-releases.edit', $otherPressRelease->id)) ->assertNotFound(); }); test('customer press releases derive portal from selected company', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $contact = Contact::factory()->for($company)->create(['portal' => $company->portal->value]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('companyId', $company->id) ->set('portal', Portal::Businessportal24->value) ->set('categoryId', Category::factory()->create()->id) ->set('contactId', $contact->id) ->set('title', 'Neue Meldung fuer Presseecho') ->set('text', str_repeat('Dies ist ein ausreichend langer Testtext. ', 3)) ->call('save', 'draft') ->assertHasNoErrors(); $pressRelease = PressRelease::query()->where('user_id', $customer->id)->firstOrFail(); expect($pressRelease->portal)->toBe(Portal::Presseecho); }); test('customer press release detail shows assigned contacts and status history', function () { /** @var TestCase $this */ $customer = User::factory()->create([ 'is_active' => true, 'name' => 'Kunden Nutzer', ]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alpha GmbH', ]); $customer->companies()->attach($company->id, ['role' => 'owner']); $pressRelease = PressRelease::factory()->forPortal(Portal::Presseecho)->create([ 'user_id' => $customer->id, 'company_id' => $company->id, 'title' => 'Alpha Detailmeldung', 'status' => PressReleaseStatus::Review->value, 'hits' => 1234, ]); $contact = Contact::factory()->create([ 'company_id' => $company->id, 'portal' => Portal::Presseecho->value, 'first_name' => 'Paula', 'last_name' => 'Presse', 'responsibility' => 'PR Managerin', 'email' => 'paula@example.test', ]); $pressRelease->contacts()->attach($contact->id); PressReleaseStatusLog::query()->create([ 'press_release_id' => $pressRelease->id, 'changed_by_user_id' => $customer->id, 'from_status' => PressReleaseStatus::Draft->value, 'to_status' => PressReleaseStatus::Review->value, 'reason' => 'Zur Prüfung eingereicht', 'source' => 'customer', 'created_at' => now(), ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.show', ['id' => $pressRelease->id]) ->assertSee('Alpha Detailmeldung') ->assertSee('Zugeordnete Pressekontakte') ->assertSee('Paula Presse') ->assertSee('paula@example.test') ->assertSee('Status & Verlauf') ->assertSee('In Pruefung') ->assertSee('1.234') ->assertSee('Zur Prüfung eingereicht') ->assertSee('durch Kunden Nutzer'); }); test('legacy invoice policy denies access to invoices of other users', function () { /** @var TestCase $this */ $owner = User::factory()->create(['is_active' => true]); $intruder = User::factory()->create(['is_active' => true]); $invoice = LegacyInvoice::query()->create([ 'legacy_portal' => 'presseecho', 'legacy_id' => 9001, 'user_id' => $owner->id, 'legacy_user_id' => 9001, 'number' => 'RE-OWN-9001', 'amount_cents' => 9900, 'total_cents' => 9900, 'status' => 'paid', 'invoice_date' => now()->subMonth(), 'imported_at' => now(), ]); expect($owner->can('view', $invoice))->toBeTrue(); expect($intruder->can('view', $invoice))->toBeFalse(); expect($intruder->can('downloadPdf', $invoice))->toBeFalse(); });