create(['is_active' => true, 'portal' => Portal::Businessportal24]); $company = Company::factory()->create(array_merge(['portal' => Portal::Businessportal24], $companyAttributes)); $release = PressRelease::factory() ->for($company) ->create([ 'user_id' => $user->id, 'portal' => Portal::Businessportal24, 'status' => $rejectionReason !== null ? PressReleaseStatus::Rejected : PressReleaseStatus::Published, ]); PressReleaseStatusLog::query()->create([ 'press_release_id' => $release->id, 'from_status' => 'draft', 'to_status' => 'published', 'source' => 'api', ]); if ($rejectionReason !== null) { PressReleaseStatusLog::query()->create([ 'press_release_id' => $release->id, 'from_status' => 'review', 'to_status' => 'rejected', 'source' => 'ki', 'reason' => $rejectionReason, ]); } return [$user, $company, $release]; } test('the report lists api submitters with their volume', function () { /** @var TestCase $this */ [$user] = submitterWithRelease(); $submitters = app(SubmitterContactReport::class)->submitters(); expect($submitters)->toHaveCount(1) ->and($submitters->first()->id)->toBe($user->id) ->and($submitters->first()->releases)->toBe(1); }); test('a suppressed company address shows up as a broken contact', function () { /** @var TestCase $this */ [$user, $company] = submitterWithRelease(['email' => 'presse@tot.example']); app(EmailSuppressionService::class)->recordBounce('presse@tot.example', EmailBounceKind::Hard, 'imap', 'm1'); $rows = app(SubmitterContactReport::class)->brokenContacts($user); expect($rows)->toHaveCount(1) ->and($rows->first()->email)->toBe('presse@tot.example') ->and($rows->first()->fromDomain)->toBeFalse() ->and($rows->first()->companyId)->toBe($company->id) ->and($rows->first()->releases)->toBe(1); }); test('a domain without a mail path shows up even without any bounce', function () { /** @var TestCase $this */ // Der Punkt der Vorabprüfung: sichtbar, bevor je eine Mail geschrieben wurde. [$user] = submitterWithRelease(['email' => 'info@existiert-nicht.example']); EmailDomainCheck::query()->create([ 'domain' => 'existiert-nicht.example', 'state' => EmailDomainState::DomainMissing, 'detail' => 'Keine DNS-Einträge (NXDOMAIN)', 'checked_at' => now(), 'expires_at' => now()->addDay(), ]); $rows = app(SubmitterContactReport::class)->brokenContacts($user); expect($rows)->toHaveCount(1) ->and($rows->first()->fromDomain)->toBeTrue() ->and($rows->first()->reason)->toBe('Domain existiert nicht') ->and(app(EmailSuppressionService::class)->isSuppressed('info@existiert-nicht.example'))->toBeFalse(); }); test('an unresolved domain is no finding and stays out of the report', function () { /** @var TestCase $this */ [$user] = submitterWithRelease(['email' => 'info@offen.example']); EmailDomainCheck::query()->create([ 'domain' => 'offen.example', 'state' => EmailDomainState::Unresolved, 'checked_at' => now(), 'expires_at' => now()->addMinutes(15), ]); expect(app(SubmitterContactReport::class)->brokenContacts($user))->toBeEmpty(); }); test('press contacts of the submitter are covered, working addresses are not listed', function () { /** @var TestCase $this */ [$user, $company] = submitterWithRelease(['email' => 'geht@example.com']); Contact::factory()->for($company)->create(['email' => 'kaputt@example.com']); app(EmailSuppressionService::class)->suppress('kaputt@example.com', EmailSuppressionReason::HardBounce, 'import'); $rows = app(SubmitterContactReport::class)->brokenContacts($user); expect($rows)->toHaveCount(1) ->and($rows->first()->email)->toBe('kaputt@example.com'); }); test('automatic rejections are listed with their reason', function () { /** @var TestCase $this */ [$user] = submitterWithRelease([], 'K1: Unzulässige Gesundheitswerbung'); $rejected = app(SubmitterContactReport::class)->rejectedReleases($user); expect($rejected)->toHaveCount(1) ->and($rejected->first()->reason)->toBe('K1: Unzulässige Gesundheitswerbung'); }); test('policy rejections are reported but never suppress the address', function () { /** @var TestCase $this */ [$user] = submitterWithRelease(['email' => 'presse@gefiltert.example']); foreach (range(1, 4) as $i) { app(EmailSuppressionService::class)->recordBounce( 'presse@gefiltert.example', EmailBounceKind::Policy, 'imap', 'policy-'.$i, ['status' => '5.7.1', 'diagnostic' => '554 5.7.1 Relay access denied'], ); } $report = app(SubmitterContactReport::class); expect($report->policyRejections($user))->toHaveCount(4) ->and(app(EmailSuppressionService::class)->isSuppressed('presse@gefiltert.example'))->toBeFalse() ->and($report->brokenContacts($user))->toBeEmpty(); }); test('the admin page renders the report for the submitter', function () { /** @var TestCase $this */ test()->seed(RolesAndPermissionsSeeder::class); [$submitter] = submitterWithRelease(['email' => 'presse@tot.example', 'name' => 'Tote Firma AG'], 'K4: Falsche Tatsachenbehauptung'); app(EmailSuppressionService::class)->recordBounce('presse@tot.example', EmailBounceKind::Hard, 'imap', 'm2'); $admin = User::factory()->create(['is_active' => true]); $admin->assignRole('admin'); $this->actingAs($admin) ->get(route('admin.reports.submitter-contacts', ['submitter' => $submitter->id])) ->assertSuccessful() ->assertSeeText('presse@tot.example') ->assertSeeText('Tote Firma AG') ->assertSeeText('K4: Falsche Tatsachenbehauptung'); });