web: Hilfeseite "Was eine gute Pressemitteilung ausmacht", Hinweis in der Ablehnungsmail (Roadmap 1d.1, 1d.2, 1d.6)

Ohne kommerziellen Anteil (E6): Anlass, Aufbau, Sprache, Pruefablauf mit
konfigurierbarer Versuchszahl, die sieben Qualitaetsdimensionen offen,
Gewichtung nicht (Offenlegungsgrenze), Pressebilder, Partner als BALD.
DE und EN, Sitemap, Hilfe-Center. Die Ablehnungsmail verlinkt die Seite
auf dem Portal der Meldung mit Herkunft mail_reject.

Config: yellow_to_manual_queue Vorgabe false (Entscheidung 16.09.2026),
max_automatic_attempts = 3 (E3).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-16 13:59:23 +00:00
parent 58bc82a91f
commit c08c9e5de0
11 changed files with 403 additions and 5 deletions

View file

@ -53,6 +53,15 @@ test('the rejection mail marks its own origin', function () {
// Ohne eigenen Herkunftswert wäre später nicht unterscheidbar, ob eine
// Wiedereinreichung aus der Ablehnungsmail kam.
expect($mail->editUrl)->toContain('src='.ConversionSource::MailReject->value);
// Roadmap 1d.2: Hilfeseite auf dem Portal der Meldung, gleiche Herkunft,
// im Text der Mail verlinkt — und nichts Kommerzielles daneben (E6).
$html = $mail->render();
expect($mail->helpUrl)->toContain('/gute-pressemitteilung?')
->and($mail->helpUrl)->toContain('src='.ConversionSource::MailReject->value)
->and($mail->helpUrl)->toContain('pr='.$release->id)
->and($html)->toContain('Was eine gute Pressemitteilung ausmacht')
->and($html)->not->toContain('/preise');
});
test('the origin is stored on the magic link token, not in a session', function () {

View file

@ -2,6 +2,7 @@
use App\Models\RejectionCategory;
use Database\Seeders\RejectionCategorySeeder;
use Illuminate\Support\Str;
use Tests\TestCase;
dataset('static pages', [
@ -10,6 +11,7 @@ dataset('static pages', [
'agb' => ['de/agb', 'Allgemeine Geschäftsbedingungen'],
'faq' => ['de/faq', 'Häufig gestellte Fragen'],
'hilfe' => ['de/hilfe', 'Hilfe-Center'],
'gute-pressemitteilung' => ['de/gute-pressemitteilung', 'Was eine gute Pressemitteilung ausmacht'],
'api' => ['de/api', 'API-Dokumentation'],
'richtlinien' => ['de/richtlinien', 'Veröffentlichungsrichtlinien'],
'melden' => ['de/melden', 'Inhalte melden oder Änderungen beantragen'],
@ -172,6 +174,7 @@ test('the help center shows quick links and topics', function () {
dataset('static pages in english', [
'faq' => ['en/faq', 'Frequently asked questions'],
'hilfe' => ['en/hilfe', 'Help center'],
'gute-pressemitteilung' => ['en/gute-pressemitteilung', 'What makes a good press release'],
'api' => ['en/api', 'API documentation'],
'impressum' => ['en/impressum', 'Imprint'],
'melden' => ['en/melden', 'Report content or request changes'],
@ -241,3 +244,26 @@ test('german validation messages are used on the de edition forms', function ()
expect($messages)->toContain('muss ausgefüllt werden')
->not->toContain('field is required');
});
test('the good-release help page explains the check without selling anything', function () {
/** @var TestCase $this */
// Roadmap 1d.1: ohne kommerziellen Anteil, Rot nur als Kategorie,
// Dimensionen offen, Versuchszahl aus der Konfiguration.
config()->set('scoring.classification.max_automatic_attempts', 2);
$response = $this->get('https://businessportal24.test/de/gute-pressemitteilung')
->assertSuccessful()
->assertSeeText('bis zu 2 Mal')
->assertSeeText('Pressestil')
->assertSeeText('Pressebilder')
->assertSeeText('Partner')
->assertSee(route('richtlinien'), false);
// Kein kommerzieller Anteil im Seiteninhalt (die Shell-Navigation zählt nicht).
$body = Str::between($response->getContent(), 'class="pm-body', 'aria-labelledby="partner-heading"');
expect($body)->not->toContain('/preise')->not->toContain('Credits');
// Aus dem Hilfe-Center und der Sitemap erreichbar.
$this->get('https://businessportal24.test/de/hilfe')->assertSee('/de/gute-pressemitteilung', false);
$this->get('https://businessportal24.test/sitemap.xml')->assertSee('/de/gute-pressemitteilung', false);
});