SupportWriter space ↗
← Back to the journal
Laravel

Test Public Articles and Drafts with Laravel Feature Tests

Verify that published articles are readable while draft detail URLs remain inaccessible.

DAdministrator · 21 Sep 2026 · 2 min read

You are reading a translated version.

Hiding drafts from a listing is insufficient. A visitor might know a detail URL and open it directly. A feature test should exercise that request.

This example assumes /articles/{post:slug}, a Post factory, and a published_at column. Adapt the path to your application. Use a separate test database: never run RefreshDatabase against production.

Implementation example

// Public controller action:
public function show(\App\Models\Post $post)
{
    abort_unless(
        $post->published_at !== null && $post->published_at->lte(now()),
        404
    );

    return view('articles.show', compact('post'));
}
namespace Tests\Feature;

use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ArticleVisibilityTest extends TestCase
{
    use RefreshDatabase;

    public function test_only_published_articles_are_public(): void
    {
        $published = Post::factory()->create(['published_at' => now()->subMinute()]);
        $draft = Post::factory()->create(['published_at' => null]);
        $scheduled = Post::factory()->create(['published_at' => now()->addDay()]);

        $this->get('/articles/'.$published->slug)->assertOk();
        $this->get('/articles/'.$draft->slug)->assertNotFound();
        $this->get('/articles/'.$scheduled->slug)->assertNotFound();
    }
}

Check the result

Add a datetime cast for published_at, then run php artisan test --filter=ArticleVisibilityTest. The published article should return HTTP 200; drafts and future publications should return 404.

The factory must populate required columns and generate unique slugs. Isolate jobs or external integrations triggered when models are saved. As an exercise, test the listing page too, verifying drafts are absent. Detail and listing tests protect different access paths.

Reference

Official documentation

← Explore more notes