signupAndLogin( email: 'alice@example.com', displayName: 'alice', password: 'longenoughpassword', ); $response = $this->withCredentials()->withUnencryptedCookie('auth_token', $session['cookie']) ->postJson('/api/posts', [ 'title' => 'My Post', 'body' => 'Hello world', ]); $response->assertStatus(201); $response->assertJsonPath('post.title', 'My Post'); $response->assertJsonPath('post.authorDisplayName', 'alice'); } public function test_anonymous_create_post_returns_401(): void { $this->postJson('/api/posts', [ 'title' => 'My Post', 'body' => 'Hello world', ])->assertStatus(401); } public function test_recent_posts_are_public(): void { $session = $this->signupAndLogin( email: 'alice@example.com', displayName: 'alice', password: 'longenoughpassword', ); $this->withCredentials()->withUnencryptedCookie('auth_token', $session['cookie']) ->postJson('/api/posts', [ 'title' => 'P1', 'body' => 'B1', ])->assertStatus(201); $response = $this->getJson('/api/posts'); $response->assertStatus(200); $response->assertJsonPath('posts.0.title', 'P1'); } public function test_show_returns_404_when_missing(): void { $this->getJson('/api/posts/9999')->assertStatus(404); } public function test_user_posts_listed_by_display_name(): void { $session = $this->signupAndLogin( email: 'alice@example.com', displayName: 'alice', password: 'longenoughpassword', ); $this->withCredentials()->withUnencryptedCookie('auth_token', $session['cookie']) ->postJson('/api/posts', [ 'title' => 'A1', 'body' => 'b', ])->assertStatus(201); $response = $this->getJson('/api/users/alice/posts'); $response->assertStatus(200); $response->assertJsonPath('user.displayName', 'alice'); $response->assertJsonPath('posts.0.title', 'A1'); } public function test_other_user_cannot_delete_post(): void { $alice = $this->signupAndLogin( email: 'alice@example.com', displayName: 'alice', password: 'longenoughpassword', ); $createResponse = $this->withCredentials()->withUnencryptedCookie('auth_token', $alice['cookie']) ->postJson('/api/posts', [ 'title' => 'A1', 'body' => 'b', ]); $postId = $createResponse->json('post.id'); $bob = $this->signupAndLogin( email: 'bob@example.com', displayName: 'bob', password: 'longenoughpassword', ); $this->withCredentials()->withUnencryptedCookie('auth_token', $bob['cookie']) ->deleteJson("/api/posts/{$postId}") ->assertStatus(403); } public function test_author_deletes_own_post(): void { $alice = $this->signupAndLogin( email: 'alice@example.com', displayName: 'alice', password: 'longenoughpassword', ); $createResponse = $this->withCredentials()->withUnencryptedCookie('auth_token', $alice['cookie']) ->postJson('/api/posts', [ 'title' => 'A1', 'body' => 'b', ]); $postId = $createResponse->json('post.id'); $this->withCredentials()->withUnencryptedCookie('auth_token', $alice['cookie']) ->deleteJson("/api/posts/{$postId}") ->assertStatus(204); } public function test_admin_deletes_anyones_post(): void { $alice = $this->signupAndLogin( email: 'alice@example.com', displayName: 'alice', password: 'longenoughpassword', ); $createResponse = $this->withCredentials()->withUnencryptedCookie('auth_token', $alice['cookie']) ->postJson('/api/posts', [ 'title' => 'A1', 'body' => 'b', ]); $postId = $createResponse->json('post.id'); $bob = $this->signupAndLogin( email: 'bob@example.com', displayName: 'bob', password: 'longenoughpassword', ); $this->promoteToAdmin($bob['user']->getId()); // Re-login bob to get a fresh cookie/payload $loginResponse = $this->postJson('/api/login', [ 'email' => 'bob@example.com', 'password' => 'longenoughpassword', ]); $bobCookie = $loginResponse->getCookie('auth_token', false); $this->withCredentials()->withUnencryptedCookie('auth_token', $bobCookie->getValue()) ->deleteJson("/api/posts/{$postId}") ->assertStatus(204); } }