count(3)->create(); $response = $this->getJson('/api/posts'); $response->assertOk()->assertJsonCount(3, 'data'); }); test('it filters posts by status', function () { Post::factory()->create(['status' => 'draft']); Post::factory()->create(['status' => 'published']); $response = $this->getJson('/api/posts?status=published'); $response->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.status', 'published'); }); test('it filters posts by site_id', function () { $site = Site::factory()->create(); Post::factory()->create(['site_id' => $site->id]); Post::factory()->create(); $response = $this->getJson("/api/posts?site_id={$site->id}"); $response->assertOk()->assertJsonCount(1, 'data'); }); test('it filters posts by social_account_id', function () { $account = SocialAccount::factory()->create(); Post::factory()->create(['social_account_id' => $account->id]); Post::factory()->create(['social_account_id' => null]); $response = $this->getJson("/api/posts?social_account_id={$account->id}"); $response->assertOk()->assertJsonCount(1, 'data'); }); test('it filters posts that are due for publishing', function () { Post::factory()->create(['status' => 'scheduled', 'scheduled_at' => now()->subHour()]); Post::factory()->create(['status' => 'scheduled', 'scheduled_at' => now()->addDay()]); Post::factory()->create(['status' => 'draft', 'scheduled_at' => now()->subHour()]); $response = $this->getJson('/api/posts?due=1'); $response->assertOk()->assertJsonCount(1, 'data'); }); test('it shows a single post', function () { $post = Post::factory()->create(['title' => 'Solo Post']); $response = $this->getJson("/api/posts/{$post->id}"); $response->assertOk()->assertJsonPath('data.title', 'Solo Post'); }); test('it returns 404 for a missing post', function () { $this->getJson('/api/posts/999')->assertNotFound(); }); test('it creates a post with required fields only', function () { $site = Site::factory()->create(); $response = $this->postJson('/api/posts', [ 'site_id' => $site->id, 'type' => 'blog', 'body' => 'New content', ]); $response->assertCreated() ->assertJsonPath('data.site_id', $site->id) ->assertJsonPath('data.type', 'blog') ->assertJsonPath('data.body', 'New content') ->assertJsonPath('data.status', 'draft'); expect(Post::where('body', 'New content')->exists())->toBeTrue(); }); test('it rejects creating a post without a valid site_id', function () { $response = $this->postJson('/api/posts', [ 'type' => 'blog', 'body' => 'New content', ]); $response->assertUnprocessable()->assertJsonValidationErrors(['site_id']); }); test('it rejects creating a post without a valid type', function () { $site = Site::factory()->create(); $response = $this->postJson('/api/posts', [ 'site_id' => $site->id, 'type' => 'not-a-real-type', 'body' => 'New content', ]); $response->assertUnprocessable()->assertJsonValidationErrors(['type']); }); test('it rejects creating a post without a body', function () { $site = Site::factory()->create(); $response = $this->postJson('/api/posts', [ 'site_id' => $site->id, 'type' => 'blog', ]); $response->assertUnprocessable()->assertJsonValidationErrors(['body']); }); test('it updates a post status', function () { $post = Post::factory()->create(['status' => 'scheduled']); $response = $this->patchJson("/api/posts/{$post->id}", [ 'status' => 'published', ]); $response->assertOk()->assertJsonPath('data.status', 'published'); expect($post->fresh()->status)->toBe('published'); }); test('it deletes a post', function () { $post = Post::factory()->create(); $response = $this->deleteJson("/api/posts/{$post->id}"); $response->assertNoContent(); expect(Post::find($post->id))->toBeNull(); }); test('it includes published_url in the post response', function () { $post = Post::factory()->create(['published_url' => 'https://example.com/my-post']); $response = $this->getJson("/api/posts/{$post->id}"); $response->assertOk()->assertJsonPath('data.published_url', 'https://example.com/my-post'); }); test('image_url can be set on create and update', function () { $site = Site::factory()->create(); $response = $this->postJson('/api/posts', [ 'site_id' => $site->id, 'type' => 'blog', 'body' => 'content', 'image_url' => 'https://example.com/photo.jpg', ]); $response->assertCreated()->assertJsonPath('data.image_url', 'https://example.com/photo.jpg'); $post = Post::latest('id')->first(); $this->patchJson("/api/posts/{$post->id}", ['image_url' => 'https://example.com/new-photo.jpg']) ->assertOk() ->assertJsonPath('data.image_url', 'https://example.com/new-photo.jpg'); });