seed(RolesAndPermissionsSeeder::class); }); function makeCustomerWithPressRelease(array $prAttributes = []): array { $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $contact = Contact::factory()->for($company)->create([ 'portal' => $company->portal->value, ]); $category = Category::factory()->create(); $pr = PressRelease::factory()->create(array_merge([ 'user_id' => $customer->id, 'company_id' => $company->id, 'category_id' => $category->id, 'portal' => $company->portal->value, 'status' => 'draft', ], $prAttributes)); $pr->contacts()->sync([$contact->id]); return compact('customer', 'company', 'contact', 'category', 'pr'); } test('editor shows the content score panel when a score exists', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease([ 'content_score' => 67, 'content_tier' => PressReleaseContentTier::Geprueft->value, ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->assertSet('contentScore', 67) ->assertSee('67') ->assertSee('Geprüft') ->assertSee('Noch 13 Punkte bis zur nächsten Stufe.'); }); test('mount loads all Phase 7 fields and pivot contact', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr, 'contact' => $contact] = makeCustomerWithPressRelease([ 'subtitle' => 'Untertitel der PM', 'boilerplate_override' => 'Spezielle Boilerplate.', 'keywords' => 'Test, Brauerei', ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->assertSet('subtitle', 'Untertitel der PM') ->assertSet('boilerplateOverride', 'Spezielle Boilerplate.') ->assertSet('useBoilerplateOverride', true) ->assertSet('keywords', 'Test, Brauerei') ->assertSet('contactId', $contact->id) ->assertSet('currentStatus', 'draft'); }); test('mount falls back to first company contact when no pivot exists', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr, 'contact' => $contact] = makeCustomerWithPressRelease(); $pr->contacts()->detach(); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->assertSet('contactId', $contact->id); }); test('edit page shows uploaded title image instead of placeholder controls', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease([ 'title' => 'PM mit eigenem Titelbild', ]); $pr->images()->create([ 'disk' => 'public', 'path' => 'press-releases/'.$pr->id.'/images/title.jpg', 'variants' => ['cover' => 'press-releases/'.$pr->id.'/images/title-cover.jpg'], 'author' => 'Jane Doe', 'license_type' => ImageLicenseType::Own->value, 'rights_confirmed_at' => now(), 'is_preview' => true, 'sort_order' => 1, ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->assertDontSee('Dieser Platzhalter wird angezeigt, bis ein eigenes Titelbild hochgeladen ist.') ->assertDontSee('Platzhalter wählen'); }); test('save persists all new Phase 7 fields and syncs contact', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease(); $newContact = Contact::factory()->for($pr->company)->create([ 'portal' => $pr->company->portal->value, ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->set('title', 'Aktualisierter Titel mit genug Zeichen') ->set('subtitle', 'Neue Subline') ->set('text', str_repeat('Aktualisierter Fließtext mit etwas Inhalt. ', 5)) ->set('keywords', 'Neu, Frisch') ->set('contactId', $newContact->id) ->set('useBoilerplateOverride', true) ->set('boilerplateOverride', 'Override-Text für diese PM.') ->call('save') ->assertHasNoErrors(); $pr->refresh(); expect($pr->title)->toBe('Aktualisierter Titel mit genug Zeichen'); expect($pr->subtitle)->toBe('Neue Subline'); expect($pr->boilerplate_override)->toBe('Override-Text für diese PM.'); expect($pr->keywords)->toBe('Neu, Frisch'); expect($pr->contacts->pluck('id')->all())->toBe([$newContact->id]); }); test('save without contact id succeeds and detaches existing contact', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease(); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->set('contactId', null) ->call('save') ->assertHasNoErrors(['contactId']); expect($pr->fresh()->contacts()->count())->toBe(0); }); test('save nulls boilerplate_override when toggle is turned off', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease([ 'boilerplate_override' => 'Alter Override-Text', ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->assertSet('useBoilerplateOverride', true) ->set('useBoilerplateOverride', false) ->call('save') ->assertHasNoErrors(); $pr->refresh(); expect($pr->boilerplate_override)->toBeNull(); }); test('changing the company resets the contact to the new company default', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease(); $secondCompany = Company::factory()->presseecho()->create(); $customer->companies()->attach($secondCompany->id, ['role' => 'owner']); $secondContact = Contact::factory()->for($secondCompany)->create([ 'portal' => $secondCompany->portal->value, ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->set('companyId', $secondCompany->id) ->assertSet('contactId', $secondContact->id); }); test('company options keep selected company and search without loading all companies', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr, 'company' => $selectedCompany] = makeCustomerWithPressRelease(); $companies = Company::factory() ->count(12) ->presseecho() ->sequence(fn (Sequence $sequence): array => [ 'name' => sprintf('Weitere Firma %02d', $sequence->index + 1), ]) ->create(); $companies->each(fn (Company $company) => $customer->companies()->attach($company->id, ['role' => 'owner'])); $targetCompany = $companies->first(); $targetCompany->update(['name' => 'Suchtreffer Redaktion']); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->assertViewHas('companyOptions', fn ($companyOptions): bool => $companyOptions->count() === 10 && $companyOptions->pluck('id')->contains($selectedCompany->id)) ->set('companySearch', 'Suchtreffer') ->assertViewHas('companyOptions', fn ($companyOptions): bool => $companyOptions->count() === 1 && $companyOptions->first()->id === $targetCompany->id); }); test('rejected press releases can be edited and re-submitted', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease([ 'status' => 'rejected', ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->assertSet('currentStatus', 'rejected'); }); test('foreign press release returns 403 on mount', function () { /** @var TestCase $this */ ['pr' => $pr] = makeCustomerWithPressRelease(); $stranger = User::factory()->create(['is_active' => true]); $stranger->assignRole('customer'); $this->actingAs($stranger); $this->get(route('me.press-releases.edit', $pr->id)) ->assertNotFound(); }); test('addTag and removeTag work in edit form', function () { /** @var TestCase $this */ ['customer' => $customer, 'pr' => $pr] = makeCustomerWithPressRelease([ 'keywords' => 'Eins', ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.edit', ['id' => $pr->id]) ->call('addTag', 'Zwei') ->assertSet('keywords', 'Eins, Zwei') ->call('removeTag', 'Eins') ->assertSet('keywords', 'Zwei'); });