seed(RolesAndPermissionsSeeder::class); }); test('mount picks the alphabetically first contact of the default company', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(['name' => 'Alpha GmbH']); $customer->companies()->attach($company->id, ['role' => 'owner']); $contactZ = Contact::factory()->for($company)->create([ 'first_name' => 'Zacharias', 'last_name' => 'Zimmer', 'portal' => $company->portal->value, ]); $contactA = Contact::factory()->for($company)->create([ 'first_name' => 'Alfred', 'last_name' => 'Acker', 'portal' => $company->portal->value, ]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->assertSet('companyId', $company->id) ->assertSet('contactId', $contactA->id); }); test('changing the company resets the contactId to the new company default', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $alphaCo = Company::factory()->presseecho()->create(['name' => 'Alpha']); $betaCo = Company::factory()->presseecho()->create(['name' => 'Beta']); $customer->companies()->attach($alphaCo->id, ['role' => 'owner']); $customer->companies()->attach($betaCo->id, ['role' => 'owner']); $alphaContact = Contact::factory()->for($alphaCo)->create(['portal' => $alphaCo->portal->value]); $betaContact = Contact::factory()->for($betaCo)->create(['portal' => $betaCo->portal->value]); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('companyId', $betaCo->id) ->assertSet('contactId', $betaContact->id) ->set('companyId', $alphaCo->id) ->assertSet('contactId', $alphaContact->id); }); test('company options are limited and searchable', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $companies = Company::factory() ->count(12) ->presseecho() ->sequence(fn (Sequence $sequence): array => [ 'name' => sprintf('Firma %02d', $sequence->index + 1), ]) ->create(); $companies->each(fn (Company $company) => $customer->companies()->attach($company->id, ['role' => 'owner'])); $hiddenCompany = $companies->first(); $hiddenCompany->update(['name' => 'Zielunternehmen Spezial']); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->assertViewHas('companyOptions', fn ($companyOptions): bool => $companyOptions->count() === 10 && ! $companyOptions->pluck('id')->contains($hiddenCompany->id)) ->set('companySearch', 'Zielunternehmen') ->assertViewHas('companyOptions', fn ($companyOptions): bool => $companyOptions->count() === 1 && $companyOptions->first()->id === $hiddenCompany->id); }); test('company options show portal abbreviations for duplicate names', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $presseechoCompany = Company::factory()->presseecho()->create(['name' => 'Doppel GmbH']); $businessportalCompany = Company::factory()->businessportal24()->create(['name' => 'Doppel GmbH']); $customer->companies()->attach($presseechoCompany->id, ['role' => 'owner']); $customer->companies()->attach($businessportalCompany->id, ['role' => 'owner']); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('companySearch', 'Doppel') ->assertSee('Doppel GmbH (PE)') ->assertSee('Doppel GmbH (B24)'); }); test('company search ignores trailing portal abbreviation from selected label', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $presseechoCompany = Company::factory()->presseecho()->create(['name' => 'Wein & Würze / N8Schicht GmbH']); $businessportalCompany = Company::factory()->businessportal24()->create(['name' => 'Wein & Würze / N8Schicht GmbH']); $customer->companies()->attach($presseechoCompany->id, ['role' => 'owner']); $customer->companies()->attach($businessportalCompany->id, ['role' => 'owner']); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('companySearch', 'Wein & Würze / N8Schicht GmbH (B24)') ->assertViewHas('companyOptions', fn ($companyOptions): bool => $companyOptions->pluck('id')->contains($businessportalCompany->id)); }); test('save with all required fields persists the press release and syncs contact', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(['boilerplate' => 'Über uns…']); $customer->companies()->attach($company->id, ['role' => 'owner']); $contact = Contact::factory()->for($company)->create(['portal' => $company->portal->value]); $category = Category::factory()->create(); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('title', 'Eine neue Eröffnung der Brauerei') ->set('subtitle', 'Subline mit ein wenig Kontext.') ->set('text', str_repeat('Inhaltlich relevanter Fließtext. ', 5)) ->set('categoryId', $category->id) ->set('contactId', $contact->id) ->set('keywords', 'Brauerei, Eröffnung') ->set('useBoilerplateOverride', true) ->set('boilerplateOverride', 'Spezielle Boilerplate für diese PM.') ->call('save', 'draft') ->assertHasNoErrors(); $pr = PressRelease::query()->where('user_id', $customer->id)->latest('id')->firstOrFail(); expect($pr->title)->toBe('Eine neue Eröffnung der Brauerei'); expect($pr->subtitle)->toBe('Subline mit ein wenig Kontext.'); expect($pr->boilerplate_override)->toBe('Spezielle Boilerplate für diese PM.'); expect($pr->company_id)->toBe($company->id); expect($pr->category_id)->toBe($category->id); expect($pr->status)->toBe(PressReleaseStatus::Draft); expect($pr->contacts)->toHaveCount(1); expect($pr->contacts->first()->id)->toBe($contact->id); }); test('save without a contact id succeeds and leaves contacts empty', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $category = Category::factory()->create(); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('contactId', null) ->set('title', 'Titel mit genug Zeichen') ->set('text', str_repeat('x', 60)) ->set('categoryId', $category->id) ->call('save', 'draft') ->assertHasNoErrors(['contactId']); $pr = PressRelease::query()->where('title', 'Titel mit genug Zeichen')->firstOrFail(); expect($pr->contacts()->count())->toBe(0); }); test('presubmit check for missing contact is warning, not error', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $this->actingAs($customer); $component = LivewireVolt::test('customer.press-releases.create') ->set('contactId', null); $checks = collect($component->instance()->presubmitChecks); $contactCheck = $checks->firstWhere('key', 'contact'); expect($contactCheck['status'])->toBe('warn'); }); test('boilerplate override is null when toggle is off even if text is filled', function () { /** @var TestCase $this */ $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(); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('title', 'Genug Zeichen Titel') ->set('text', str_repeat('x', 60)) ->set('categoryId', $category->id) ->set('contactId', $contact->id) ->set('useBoilerplateOverride', false) ->set('boilerplateOverride', 'Wird nicht gespeichert.') ->call('save', 'draft') ->assertHasNoErrors(); $pr = PressRelease::query()->where('user_id', $customer->id)->latest('id')->firstOrFail(); expect($pr->boilerplate_override)->toBeNull(); }); test('ensureDraft saves a draft with current data and redirects to the editor', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $category = Category::factory()->create(); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('title', 'Frühzeitiger Upload') ->set('categoryId', $category->id) ->call('ensureDraft') ->assertHasNoErrors(); $pr = PressRelease::query()->where('user_id', $customer->id)->latest('id')->firstOrFail(); expect($pr->status)->toBe(PressReleaseStatus::Draft); expect($pr->company_id)->toBe($company->id); expect($pr->category_id)->toBe($category->id); expect($pr->title)->toBe('Frühzeitiger Upload'); }); test('ensureDraft uses a placeholder title when the title is still empty', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $category = Category::factory()->create(); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('categoryId', $category->id) ->call('ensureDraft') ->assertHasNoErrors(); $pr = PressRelease::query()->where('user_id', $customer->id)->latest('id')->firstOrFail(); expect($pr->title)->not->toBe(''); expect($pr->status)->toBe(PressReleaseStatus::Draft); }); test('ensureDraft requires a category before creating a draft', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->set('categoryId', null) ->call('ensureDraft') ->assertHasErrors(['categoryId']); expect(PressRelease::query()->where('user_id', $customer->id)->count())->toBe(0); }); test('addTag appends to keywords and removeTag drops it', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $this->actingAs($customer); LivewireVolt::test('customer.press-releases.create') ->call('addTag', 'Brauerei') ->call('addTag', 'Tegernsee') ->call('addTag', 'Brauerei') ->assertSet('keywords', 'Brauerei, Tegernsee') ->call('removeTag', 'Brauerei') ->assertSet('keywords', 'Tegernsee'); }); test('addTag stops adding once the 5-tag limit is reached', function () { /** @var TestCase $this */ $customer = User::factory()->create(['is_active' => true]); $customer->assignRole('customer'); $company = Company::factory()->presseecho()->create(); $customer->companies()->attach($company->id, ['role' => 'owner']); $this->actingAs($customer); $component = LivewireVolt::test('customer.press-releases.create'); foreach (['A', 'B', 'C', 'D', 'E'] as $tag) { $component->call('addTag', $tag); } $component->call('addTag', 'F'); // Soft-cap, kein Fehler $component->assertSet('keywords', 'A, B, C, D, E'); });