NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

Reports::fake() nasadí zaznamenávajúci fake za fasádu aj do kontajnera, takže naň dopadne fasáda, vložený ReportsManager, buildery, reports:prune, $report->changeStatusTo() aj trait GivesReports. Meniace volania sa zaznamenajú a nič sa nezapíše: create() vráti neuložené hlásenie v stave Pending, moderate()->open() neuložený ApprovalRequest a prune() vráti 0. Čítanie dôvodov funguje naozaj:

use RoundlyConsulting\Reports\Facades\Reports;

$fake = Reports::fake();

$user->report($post)->for('spam')->create();
Reports::resolve($report, by: $admin, note: 'Removed.');

$fake->assertReported($post, $user, 'spam');
$fake->assertResolved($report, $admin, 'Removed.');
$fake->assertNothingPruned();

Všetky asercie

AserciaNegatívnaPrejde, keď
assertReported($subject, ?$by, Reason|string|null $reason)assertNothingReported()Podalo sa hlásenie o subjekte (od $by, s dôvodom $reason, ak ich zadáte).
assertModerated($report)assertNothingModerated()Prebehlo moderate($report)->…->open().
assertResolved($report, ?$by, ?$note)assertNothingResolved()Hlásenie bolo vyriešené (kým a s poznámkou, ak ich zadáte).
assertRejected($report, ?$by, ?$note)assertNothingRejected()To isté pre zamietnutia.
assertStatusChanged($report, ?Status $to)assertNothingStatusChanged()changeStatus(), review(), close() alebo changeStatusTo() ho presunuli (na $to).
assertPruned(?int $days, ?bool $force)assertNothingPruned()Prebehlo prune() (s daným oknom a príznakom, ak ich zadáte).
use RoundlyConsulting\Reports\Enums\Status;
use RoundlyConsulting\Reports\Facades\Reports;

it('routes a report through moderation', function () {
    $fake = Reports::fake();

    $this->actingAs($admin)->post(route('admin.reports.escalate', $report))->assertOk();

    $fake->assertModerated($report);                       // moderate($report)->…->open() ran
    $fake->assertStatusChanged($report, Status::InReview); // review() / changeStatus() / changeStatusTo()
    $fake->assertNothingResolved();
    $fake->assertNothingRejected();
    $fake->assertNothingReported();
});

it('rejects and prunes from the console', function () {
    $fake = Reports::fake();

    Reports::reject($report, by: $admin, note: 'Not a violation.');
    $this->artisan('reports:prune', ['--days' => 30])->assertSuccessful();

    $fake->assertRejected($report, $admin, 'Not a violation.');
    $fake->assertPruned(30, force: false);
    $fake->assertNothingModerated();
    $fake->assertNothingStatusChanged();
});

Stavy factory

Report má factory so stavom pre každú fázu životného cyklu:

use RoundlyConsulting\Reports\Enums\Reason;
use RoundlyConsulting\Reports\Models\Report;

Report::factory()->create();                                     // Pending, reason 'spam'
Report::factory()->forReporter($user)->against($post)->create();
Report::factory()->reason(Reason::Harassment)->create();         // Reason case or slug
Report::factory()->inReview()->create();
Report::factory()->resolved($moderator)->create();               // sets resolver + resolved_at
Report::factory()->rejected()->create();
Report::factory()->closed()->create();
Report::factory()->guest('guest-hash')->create();                // null reporter, guest identifier

Hlásenia z factory sa zapisujú priamo, takže validácia dôvodu, kontrola duplicít ani prah sa neuplatnia — ReportCreated sa však spustí. Ak chcete bez fake skutočný priebeh, podávajte hlásenia cez fasádu:

use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Reports\Enums\Reason;
use RoundlyConsulting\Reports\Enums\Status;
use RoundlyConsulting\Reports\Events\ReportResolved;
use RoundlyConsulting\Reports\Events\ReportThresholdReached;
use RoundlyConsulting\Reports\Exceptions\DuplicateReportException;
use RoundlyConsulting\Reports\Facades\Reports;

it('files, deduplicates and resolves a report', function () {
    Event::fake([ReportResolved::class]);

    $user = User::factory()->create();
    $moderator = User::factory()->create();
    $post = Post::factory()->create();

    $report = Reports::report($post)->by($user)->for(Reason::Spam)->create();

    expect($report->status)->toBe(Status::Pending)
        ->and($post->isReportedBy($user))->toBeTrue();

    expect(fn () => Reports::report($post)->by($user)->for(Reason::Spam)->create())
        ->toThrow(DuplicateReportException::class);

    Reports::resolve($report, by: $moderator, note: 'Removed.');

    expect($report->fresh()->status)->toBe(Status::Resolved);
    Event::assertDispatched(ReportResolved::class);
});

it('escalates once the threshold is reached', function () {
    config()->set('reports.threshold', 3);
    Event::fake([ReportThresholdReached::class]);

    $post = Post::factory()->create();

    foreach (User::factory()->count(3)->create() as $user) {
        Reports::report($post)->by($user)->for(Reason::Spam)->create();
    }

    Event::assertDispatchedTimes(ReportThresholdReached::class, 1);
});

Testy spúšťajte s publikovanými migráciami reports a approvals (RefreshDatabase) — vybavenie alebo zamietnutie hlásenia číta approval_requests, aj keď moderáciu netestujete.

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.