create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alpha GmbH', ]); $inaccessibleCompany = Company::factory()->businessportal24()->create([ 'name' => 'Fremde GmbH', ]); $customer->companies()->attach($company->id, ['role' => 'responsible']); $this->actingAs($customer); Livewire::test('customer.company-switcher') ->assertSee('Alpha GmbH') ->assertDontSee('Fremde GmbH') ->set('activeCompany', (string) $company->id); expect(session(CustomerCompanyContext::SessionKey))->toBe($company->id); Livewire::test('customer.company-switcher') ->set('activeCompany', (string) $inaccessibleCompany->id); expect(session(CustomerCompanyContext::SessionKey))->toBe($company->id); }); test('customer company switcher links to selected company detail', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alpha GmbH', ]); $customer->companies()->attach($company->id, ['role' => 'responsible']); $this->actingAs($customer) ->withSession([CustomerCompanyContext::SessionKey => $company->id]); Livewire::test('customer.company-switcher') ->assertSee('Alpha GmbH') ->assertSee('Firma öffnen') ->assertSee(route('me.press-kits.show', $company->id, absolute: false)); }); test('customer company switcher limits rendered company options', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); for ($i = 1; $i <= 55; $i++) { Company::factory()->presseecho()->create([ 'name' => sprintf('Switcher Firma %02d', $i), 'owner_user_id' => $customer->id, 'created_at' => now()->subDays(56 - $i), ]); } $this->actingAs($customer); Livewire::test('customer.company-switcher') ->assertViewHas('companies', fn ($companies) => $companies->count() === 50) ->assertSee('Switcher Firma 55') ->assertSee('Switcher Firma 06') ->assertDontSee('Switcher Firma 05') ->assertSee('Weitere Firmen über'); }); test('customer press release list is filtered by selected company context', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']); $otherCompany = Company::factory()->businessportal24()->create(['name' => 'Beta GmbH']); $customer->companies()->attach($company->id, ['role' => 'owner']); $customer->companies()->attach($otherCompany->id, ['role' => 'owner']); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => $company->id, 'title' => 'Alpha Produktmeldung', ]); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => $otherCompany->id, 'title' => 'Beta Produktmeldung', ]); $this->actingAs($customer) ->withSession([CustomerCompanyContext::SessionKey => $company->id]); Livewire::test('customer.press-releases.index') ->assertSee('Alpha GmbH') ->assertDontSee('Alle Firmen') ->assertSee('Alpha Produktmeldung') ->assertDontSee('Beta Produktmeldung'); }); test('customer press release list can filter unassigned legacy press releases', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']); $customer->companies()->attach($company->id, ['role' => 'owner']); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => $company->id, 'title' => 'Alpha Firmenmeldung', ]); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => null, 'title' => 'Legacy ohne Firma', ]); $this->actingAs($customer); Livewire::test('customer.press-releases.index') ->set('companyFilter', 'unassigned') ->assertSee('Alle Firmen') ->assertSee('Legacy ohne Firma') ->assertDontSee('Alpha Firmenmeldung'); }); test('customer dashboard is filtered by selected company context', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']); $otherCompany = Company::factory()->businessportal24()->create(['name' => 'Beta GmbH']); $customer->companies()->attach($company->id, ['role' => 'owner']); $customer->companies()->attach($otherCompany->id, ['role' => 'owner']); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => $company->id, 'title' => 'Alpha Dashboardmeldung', ]); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => $otherCompany->id, 'title' => 'Beta Dashboardmeldung', ]); $this->actingAs($customer) ->withSession([CustomerCompanyContext::SessionKey => $company->id]); Livewire::test('customer.dashboard') ->assertSee('Übersicht für Alpha GmbH') ->assertSee('Alpha Dashboardmeldung') ->assertDontSee('Beta Dashboardmeldung'); }); test('customer dashboard shows data quality hints', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']); $customer->companies()->attach($company->id, ['role' => 'owner']); $this->actingAs($customer) ->withSession([CustomerCompanyContext::SessionKey => $company->id]); Livewire::test('customer.dashboard') ->assertSee('Datenqualität') ->assertSee('Profil unvollständig') ->assertSee('Rechnungsadresse fehlt') ->assertSee('Keine Pressekontakte hinterlegt'); }); test('customer dashboard links unassigned press release hint to filtered list', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']); $customer->companies()->attach($company->id, ['role' => 'owner']); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => null, 'title' => 'Legacy ohne Firma', ]); $this->actingAs($customer); Livewire::test('customer.dashboard') ->assertSee('Pressemitteilung ohne Firma') ->assertSee('company=unassigned'); }); test('create press release uses selected company context as default', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']); $otherCompany = Company::factory()->businessportal24()->create(['name' => 'Beta GmbH']); $customer->companies()->attach($company->id, ['role' => 'owner']); $customer->companies()->attach($otherCompany->id, ['role' => 'owner']); $this->actingAs($customer) ->withSession([CustomerCompanyContext::SessionKey => $otherCompany->id]); Livewire::test('customer.press-releases.create') ->assertSet('companyId', $otherCompany->id) ->assertSee('Beta GmbH'); }); test('customer can browse own press kits and open a press kit detail', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alpha Pressemappe', 'email' => 'presse@alpha.test', ]); $otherCompany = Company::factory()->businessportal24()->create([ 'name' => 'Fremde Pressemappe', ]); $customer->companies()->attach($company->id, ['role' => 'responsible']); Contact::factory()->create([ 'company_id' => $company->id, 'first_name' => 'Paula', 'last_name' => 'Presse', 'email' => 'paula@example.test', ]); PressRelease::factory()->create([ 'user_id' => $customer->id, 'company_id' => $company->id, 'title' => 'Alpha Pressemeldung', ]); $this->actingAs($customer); Livewire::test('customer.press-kits.index') ->assertSee('Alpha Pressemappe') ->assertDontSee('Fremde Pressemappe'); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->assertSee('Alpha Pressemappe') ->assertSee('presse@alpha.test') ->assertSee('Paula Presse') ->assertSee('Alpha Pressemeldung') ->assertSee('Abrechnung') ->assertSee('Statistik'); expect(session(CustomerCompanyContext::SessionKey))->toBe($company->id); }); test('customer cannot open inaccessible press kit detail', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $otherCompany = Company::factory()->businessportal24()->create([ 'name' => 'Fremde Pressemappe', ]); $this->actingAs($customer); Livewire::test('customer.press-kits.show', ['id' => $otherCompany->id]) ->assertNotFound(); }); test('responsible customer can manage press kit contacts', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alpha Pressemappe', ]); $customer->companies()->attach($company->id, ['role' => 'responsible']); $this->actingAs($customer); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->call('startCreateContact') ->set('contactFirstName', 'Mara') ->set('contactLastName', 'Muster') ->set('contactResponsibility', 'Presse') ->set('contactEmail', 'mara@example.test') ->set('contactPhone', '+49 30 123') ->call('saveContact') ->assertHasNoErrors() ->assertSee('Pressekontakt wurde angelegt.'); $contact = Contact::query()->where('company_id', $company->id)->firstOrFail(); expect($contact->email)->toBe('mara@example.test'); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->call('editContact', $contact->id) ->set('contactEmail', 'presse@example.test') ->call('saveContact') ->assertHasNoErrors() ->assertSee('Pressekontakt wurde aktualisiert.'); expect($contact->refresh()->email)->toBe('presse@example.test'); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->call('deleteContact', $contact->id) ->assertSee('Pressekontakt wurde gelöscht.'); expect(Contact::query()->whereKey($contact->id)->exists())->toBeFalse(); }); test('member customer cannot manage press kit contacts', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alpha Pressemappe', ]); $customer->companies()->attach($company->id, ['role' => 'member']); $this->actingAs($customer); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->assertDontSee('Kontakt hinzufügen') ->call('startCreateContact') ->assertForbidden(); }); test('responsible customer can manage press kit company master data', function () { /** @var TestCase $this */ Storage::fake('public'); $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alte Pressemappe', 'email' => 'alt@example.test', ]); $customer->companies()->attach($company->id, ['role' => 'responsible']); $this->actingAs($customer); $logo = UploadedFile::fake()->image('logo.png', 800, 400); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->call('startEditCompany') ->set('companyName', 'Neue Pressemappe GmbH') ->set('companyEmail', 'neu@example.test') ->set('companyPhone', '+49 30 456') ->set('companyWebsite', 'https://example.test') ->set('companyAddress', 'Neue Strasse 1') ->set('companyCountryCode', 'AT') ->set('companyDisableFooterCode', true) ->set('companyLogo', $logo) ->call('saveCompany') ->assertHasNoErrors() ->assertSee('Stammdaten wurden gespeichert.'); $company->refresh(); expect($company->name)->toBe('Neue Pressemappe GmbH'); expect($company->email)->toBe('neu@example.test'); expect($company->country_code)->toBe('AT'); expect($company->disable_footer_code)->toBeTrue(); expect($company->logo_path)->not->toBeNull(); expect($company->logo_variants)->toHaveKey('sq'); expect($company->logo_variants)->toHaveKey('wide'); expect(Storage::disk('public')->exists($company->logo_path))->toBeTrue(); }); test('member customer cannot manage press kit company master data', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'name' => 'Alpha Pressemappe', ]); $customer->companies()->attach($company->id, ['role' => 'member']); $this->actingAs($customer); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->assertDontSee('Stammdaten bearbeiten') ->call('startEditCompany') ->assertForbidden(); }); test('a deleted press kit contact disappears from the list and cannot be edited (Audit F04)', function () { /** @var TestCase $this */ $this->seed(RolesAndPermissionsSeeder::class); $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(['owner_user_id' => $customer->id]); $contact = Contact::factory()->for($company)->create([ 'first_name' => 'Gelöschte', 'last_name' => 'Kontaktperson', 'portal' => $company->portal->value, ]); $this->actingAs($customer); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->assertSee('Kontaktperson') ->call('deleteContact', $contact->id) ->assertDontSee('Kontaktperson'); // Seit Livewire 4.4.7 rendert der Testhelfer ModelNotFoundException wie // ein echter Request als 404, statt sie zu werfen. Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->assertDontSee('Kontaktperson') ->call('editContact', $contact->id) ->assertNotFound(); }); test('saving or deleting a press kit contact drops the cached newsroom page', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create(['is_active' => true]); $customer->companies()->attach($company->id, ['role' => 'responsible']); PressRelease::factory() ->published() ->forPortal(Portal::Presseecho) ->for($company) ->create(['language' => 'de', 'published_at' => now()->subDay()]); $url = 'https://presseecho.test/de/newsroom/'.$company->slug; $cacheKey = fn (): string => webPageCacheKey('web.newsroom.presseecho-both.de.'.$company->slug.'.page.1'); $this->actingAs($customer); // Aufwärmen — die Kontakte liegen mit im gecachten Seitenpaket. $this->get($url)->assertOk(); expect(Cache::has($cacheKey()))->toBeTrue(); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->call('startCreateContact') ->set('contactLastName', 'Neu') ->set('contactEmail', 'neu@example.test') ->call('saveContact') ->assertHasNoErrors(); // Der Key trägt die Generation: nach einem Flush existiert der alte // Eintrag unter dem neuen Key nicht mehr. expect(Cache::has($cacheKey()))->toBeFalse(); $contact = Contact::query()->where('company_id', $company->id)->firstOrFail(); $this->get($url)->assertOk(); expect(Cache::has($cacheKey()))->toBeTrue(); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->call('deleteContact', $contact->id); expect(Cache::has($cacheKey()))->toBeFalse(); }); test('a failed logo write keeps the previous press kit logo and reports a validation error', function () { /** @var TestCase $this */ $disk = Storage::fake('public'); $disk->put('company-logos/presseecho/7/alt.png', 'alt'); $disk->put('company-logos/presseecho/7/alt-sq.png', 'alt-sq'); $customer = User::factory()->create(['is_active' => true]); $company = Company::factory()->presseecho()->create([ 'logo_path' => 'company-logos/presseecho/7/alt.png', 'logo_variants' => ['sq' => 'company-logos/presseecho/7/alt-sq.png'], ]); $customer->companies()->attach($company->id, ['role' => 'responsible']); // Proxy auf den echten Fake: nur put() schlägt fehl (voller Datenträger, // Rechteproblem), alles andere — auch Livewires Temp-Upload — läuft echt. $failingDisk = Mockery::mock($disk); $failingDisk->shouldReceive('put')->andReturn(false); Storage::set('public', $failingDisk); $this->actingAs($customer); Livewire::test('customer.press-kits.show', ['id' => $company->id]) ->call('startEditCompany') ->set('companyLogo', UploadedFile::fake()->image('neu.png', 400, 400)) ->call('saveCompany') ->assertHasErrors(['companyLogo']); $company->refresh(); expect($company->logo_path)->toBe('company-logos/presseecho/7/alt.png') ->and($company->logo_variants)->toBe(['sq' => 'company-logos/presseecho/7/alt-sq.png']) ->and($disk->exists('company-logos/presseecho/7/alt.png'))->toBeTrue() ->and($disk->exists('company-logos/presseecho/7/alt-sq.png'))->toBeTrue(); });