create([ 'status' => UserStatus::Active->value, 'bio' => 'Test bio content', ]); // Act $response = $this->getJson("/api/users/{$user->uuid}/profile"); // Assert $response->assertOk() ->assertJsonStructure([ 'success', 'message', 'data' => [ 'uuid', 'name', 'status', 'status_label', 'avatar', 'bio', 'created_at', ], ]) ->assertJsonPath('data.status', 'active') ->assertJsonPath('data.bio', 'Test bio content') ->assertJsonPath('data.uuid', $user->uuid); } /** * inactive 사용자는 기본 정보만 반환합니다 (bio 제외). */ public function test_inactive_user_returns_basic_info(): void { // Arrange $user = User::factory()->create([ 'status' => UserStatus::Inactive->value, 'bio' => 'This should not appear', ]); // Act $response = $this->getJson("/api/users/{$user->uuid}/profile"); // Assert $response->assertOk() ->assertJsonPath('data.status', 'inactive') ->assertJsonPath('data.status_label', __('user.status.inactive')) ->assertJsonPath('data.bio', null) ->assertJsonPath('data.name', $user->name); // avatar와 created_at은 있어야 함 $this->assertArrayHasKey('avatar', $response->json('data')); $this->assertArrayHasKey('created_at', $response->json('data')); } /** * blocked 사용자는 최소 정보만 반환합니다 (avatar, bio, created_at 제외). */ public function test_blocked_user_returns_minimal_info(): void { // Arrange $user = User::factory()->create([ 'status' => UserStatus::Blocked->value, 'bio' => 'This should not appear', ]); // Act $response = $this->getJson("/api/users/{$user->uuid}/profile"); // Assert $response->assertOk() ->assertJsonPath('data.status', 'blocked') ->assertJsonPath('data.status_label', __('user.status.blocked')) ->assertJsonPath('data.avatar', null) ->assertJsonPath('data.bio', null) ->assertJsonPath('data.created_at', null) ->assertJsonPath('data.name', $user->name); } /** * withdrawn 사용자는 익명화된 정보를 반환합니다. */ public function test_withdrawn_user_returns_anonymized_info(): void { // Arrange $user = User::factory()->create([ 'status' => UserStatus::Withdrawn->value, ]); // Act $response = $this->getJson("/api/users/{$user->uuid}/profile"); // Assert $response->assertOk() ->assertJsonPath('success', true) ->assertJsonPath('data.uuid', $user->uuid) ->assertJsonPath('data.status', UserStatus::Withdrawn->value) ->assertJsonPath('data.status_label', __('user.status.withdrawn')) ->assertJsonPath('data.name', __('user.withdrawn_user')) ->assertJsonPath('data.avatar', null) ->assertJsonPath('data.bio', null) ->assertJsonPath('data.created_at', null) ->assertJsonPath('data.is_withdrawn', true); } /** * 존재하지 않는 사용자 ID는 404를 반환합니다. */ public function test_non_existent_user_returns_404(): void { // Act $response = $this->getJson('/api/users/00000000-0000-0000-0000-000000000000/profile'); // Assert - Route Model Binding이 UUID로 사용자를 찾지 못하면 404 $response->assertNotFound(); } /** * 프로필 응답에 status와 status_label이 포함됩니다. */ public function test_profile_contains_status_and_label(): void { // Arrange $user = User::factory()->create([ 'status' => UserStatus::Active->value, ]); // Act $response = $this->getJson("/api/users/{$user->uuid}/profile"); // Assert $response->assertOk(); $data = $response->json('data'); $this->assertArrayHasKey('status', $data); $this->assertArrayHasKey('status_label', $data); $this->assertEquals('active', $data['status']); $this->assertEquals(__('user.status.active'), $data['status_label']); } /** * 프로필 응답에 게시글 통계가 포함되지 않습니다. * (게시글 통계는 게시판 모듈 API에서 별도 제공) */ public function test_profile_does_not_contain_post_stats(): void { // Arrange $user = User::factory()->create([ 'status' => UserStatus::Active->value, ]); // Act $response = $this->getJson("/api/users/{$user->uuid}/profile"); // Assert $response->assertOk(); $data = $response->json('data'); $this->assertArrayNotHasKey('posts_count', $data); $this->assertArrayNotHasKey('comments_count', $data); $this->assertArrayNotHasKey('recent_posts', $data); } }