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

Posts::fake() nasadí za fasádu aj do kontajnera zaznamenávajúci fake — rozširuje PostsManager, takže ho dostanú aj vložené manažéry. Každý zápis — cez fasádu, vložený manažér, builder, metódy cyklu na modeli a syncTags(), listener moderácie či posts:publish-scheduled — sa namiesto vykonania len zaznamená: nič sa nezapíše a nespustí sa žiadna udalosť. create() vráti neuložený príspevok naplnený tak, ako by to urobila akcia; ostatné zápisy vrátia príspevok nezmenený a publishDue() vráti 0. Čítania — findBySlug(), published(), query() — stále idú do databázy:

use RoundlyConsulting\Posts\DataTransferObjects\CreatePostData;
use RoundlyConsulting\Posts\DataTransferObjects\SeoData;
use RoundlyConsulting\Posts\Facades\Posts;

Posts::fake();

// … exercise your code …

Posts::assertCreated(fn (CreatePostData $data): bool => $data->translations[0]->title === 'Hello');
Posts::assertPublished($post);                 // optionally: Posts::assertPublished($post, $at)
Posts::assertScheduled($post, $at);
Posts::assertArchived($post);
Posts::assertUnpublished($post);
Posts::assertSeoUpdated($post, fn (SeoData $seo): bool => $seo->robots === 'noindex');
Posts::assertTagged($post, ['laravel', 'php']);
Posts::assertPublishedDue();

Asercie

Volajte ich na fasáde alebo na PostsFake, ktorý vráti Posts::fake(). Každá asercia má negatívny pár:

AserciaNegatívny párPrejde, keď
assertCreated(fn (CreatePostData $d) => …)assertNothingCreated()Zaznamenalo sa vytvorenie (zodpovedajúce callbacku).
assertPublished($post, ?$at)assertNothingPublished()Príspevok bol publikovaný (k danému $at; bez neho s akýmkoľvek dátumom či bez neho).
assertScheduled($post, ?$at)assertNothingScheduled()Príspevok bol naplánovaný (na daný $at).
assertArchived($post)assertNothingArchived()Príspevok bol archivovaný.
assertUnpublished($post)assertNothingUnpublished()Príspevok sa vrátil do konceptu.
assertSeoUpdated($post, fn (SeoData $s) => …)assertNothingSeoUpdated()SEO príspevku sa zmenilo (podľa callbacku).
assertTagged($post, ['laravel', 'php'])assertNothingTagged()Tagy sa synchronizovali — pri zadaní presne na tieto názvy; modely Tag sa porovnajú podľa názvu v aktuálnom jazyku.
assertPublishedDue()assertNothingPublishedDue()Prebehlo publishDue() — cez fasádu, manažér alebo príkaz.

Príspevky sa porovnávajú podľa identity, alebo — ak sú oba uložené — cez is(); dva neuložené príspevky sa nikdy nezhodujú.

use App\Models\User;
use RoundlyConsulting\Posts\Facades\Posts;
use RoundlyConsulting\Posts\Models\Post;

it('publishes a post from the admin', function () {
    $fake = Posts::fake();                     // returns the PostsFake
    $post = Post::factory()->create();

    $this->actingAs(User::factory()->create())
        ->post(route('admin.posts.publish', $post))
        ->assertRedirect();

    $fake->assertPublished($post);
    $fake->assertNothingArchived();
    $fake->assertNothingCreated();
});

Factories

Balík obsahuje factories pre všetky tri modely; Post::factory() vytvára nakonfigurovaný model príspevku:

use RoundlyConsulting\Posts\Models\Category;
use RoundlyConsulting\Posts\Models\Post;
use RoundlyConsulting\Posts\Models\Tag;

Post::factory()->published()->forAuthor($user)->create();   // states: draft, published, scheduled (+1 day), archived
Post::factory()->withTitles(['en' => 'Hello', 'sk' => 'Ahoj'])->create();
Category::factory()->childOf($parent)->create();
Tag::factory()->create();

Plánované publikovanie naozaj

Bez fake zmrazte čas, vytvorte príspevky v čase aj v budúcnosti, spustite príkaz a overte výsledok:

use Carbon\CarbonImmutable;
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Posts\Enums\PostStatus;
use RoundlyConsulting\Posts\Events\PostPublished;
use RoundlyConsulting\Posts\Models\Post;

it('publishes scheduled posts whose time has come', function () {
    Event::fake([PostPublished::class]);
    CarbonImmutable::setTestNow('2026-01-01 12:00:00');

    $due = Post::factory()->create(['status' => PostStatus::Scheduled, 'published_at' => now()->subHour()]);
    $future = Post::factory()->create(['status' => PostStatus::Scheduled, 'published_at' => now()->addHour()]);

    $this->artisan('posts:publish-scheduled')->assertSuccessful();

    expect($due->fresh()->status)->toBe(PostStatus::Published)
        ->and($future->fresh()->status)->toBe(PostStatus::Scheduled);

    Event::assertDispatched(PostPublished::class);
});

Médiá

Použite fake disk a fake upload — žiadne reálne súbory sa nedotknú úložiska:

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use RoundlyConsulting\Posts\Models\Post;

it('uses the featured image as og:image', function () {
    Storage::fake('public');

    $post = Post::factory()->create();
    $post->addMedia(UploadedFile::fake()->image('hero.jpg', 800, 600))
        ->toMediaBucket($post->featuredBucket());

    expect($post->seo()->ogImage)->toBe($post->featuredImageUrl())
        ->and($post->toJsonLd()['image'])->toBe($post->featuredImageUrl());
});

Testy spúšťajte s publikovanými migráciami (RefreshDatabase). Pamätajte, že SQLite prijme uuid aj do bigint morph stĺpca, preto zmeny typov kľúčov testujte na engine, ktorý nasadzujete.

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.