관리자·유저 화면 왕복 이동 수단을 추가하고, 상품/게시판 URL 식별자를 사람이 읽을 수 있는 값(상품코드/슬러그)으로 전환한다. 크로스 이동 링크 (전부 새 탭): - 관리자 사이드바 "사이트 보기" + 모바일 드로어 상단 잘림 수정 - 관리자 게시물 조회 ↔ 유저 게시판, 유저 상품 상세 ↔ 관리자 상품 수정 - 유저 화면의 관리자 진입은 is_admin 이 아니라 세부 권한 플래그로 게이트 (게시판 can_access_admin, 상품 can_update) 상품 라우팅 id → product_code: - Product::resolveRouteBinding(code/id) + 공개 라우트 정규식 확장 - 모든 상품 링크(목록·최근본·검색·장바구니·주문내역·문의내역·관리자) 전환 - 상품 검색을 상품코드·번호 양쪽 조회 가능하게 확장(관리자+통합검색) 게시판 라우팅 board id → slug: - Board::resolveRouteBinding(slug/id) + 관리자 라우트 slug 전환 - 생성 후 리다이렉트·토글·삭제·수정·add-to-menu·편집기 스코프 전수 정정 - BoardController::addToAdminMenu 를 Board 바인딩으로 정합 검증: 프론트 레이아웃 Vitest 36건 green, 백엔드 회귀 테스트 추가, g7.dev 라이브 실측(생성/삭제/메뉴추가 slug, 문의내역·검색 상품코드 URL).
638 lines
22 KiB
PHP
638 lines
22 KiB
PHP
<?php
|
|
|
|
namespace Modules\Sirsoft\Board\Tests\Feature;
|
|
|
|
// 테스트 베이스 클래스 수동 require (autoload 전에 로드 필요)
|
|
require_once __DIR__.'/../ModuleTestCase.php';
|
|
|
|
use App\Models\Permission;
|
|
use App\Models\Role;
|
|
use App\Models\User;
|
|
use Modules\Sirsoft\Board\Tests\BoardTestCase;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
|
|
/**
|
|
* PostResource 권한 API 응답 구조 테스트
|
|
*
|
|
* Admin/User 페이지별 권한 분기 및 소유권 플래그 테스트
|
|
*/
|
|
class PostResourcePermissionTest extends BoardTestCase
|
|
{
|
|
private User $adminUser;
|
|
|
|
private User $regularUser;
|
|
|
|
private User $postAuthor;
|
|
|
|
/**
|
|
* 테스트 게시판 slug
|
|
*/
|
|
protected function getTestBoardSlug(): string
|
|
{
|
|
return 'permission-test';
|
|
}
|
|
|
|
/**
|
|
* 기본 게시판 속성
|
|
*/
|
|
protected function getDefaultBoardAttributes(string $slug): array
|
|
{
|
|
return [
|
|
'slug' => $slug,
|
|
'name' => ['ko' => '권한 테스트 게시판', 'en' => 'Permission Test Board'],
|
|
'is_active' => true,
|
|
'secret_mode' => 'disabled',
|
|
'blocked_keywords' => [],
|
|
];
|
|
}
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
// 테스트 사용자 생성
|
|
$this->createTestUsers();
|
|
|
|
// 권한 설정
|
|
$this->setupPermissions();
|
|
}
|
|
|
|
/**
|
|
* 테스트 사용자 생성
|
|
*/
|
|
private function createTestUsers(): void
|
|
{
|
|
$this->adminUser = User::factory()->create();
|
|
$this->regularUser = User::factory()->create();
|
|
$this->postAuthor = User::factory()->create();
|
|
}
|
|
|
|
/**
|
|
* 권한 설정
|
|
*/
|
|
private function setupPermissions(): void
|
|
{
|
|
$slug = $this->board->slug;
|
|
|
|
// Admin 권한 생성 및 할당 (라우트 미들웨어와 일치하는 식별자 사용)
|
|
$adminPermissions = [];
|
|
$adminPermissionDefs = [
|
|
'admin.posts.read' => ['ko' => '관리자 게시글 조회', 'en' => 'Admin Posts Read'],
|
|
'admin.posts.write' => ['ko' => '관리자 게시글 작성', 'en' => 'Admin Posts Write'],
|
|
'admin.manage' => ['ko' => '관리자 관리', 'en' => 'Admin Manage'],
|
|
];
|
|
|
|
foreach ($adminPermissionDefs as $action => $name) {
|
|
$permission = Permission::firstOrCreate(
|
|
['identifier' => "sirsoft-board.{$slug}.{$action}"],
|
|
[
|
|
'name' => $name,
|
|
'slug' => "sirsoft-board.{$slug}.{$action}",
|
|
'type' => 'admin',
|
|
]
|
|
);
|
|
$adminPermissions[] = $permission->id;
|
|
}
|
|
|
|
$adminRole = Role::firstOrCreate(
|
|
['identifier' => "{$slug}-admin"],
|
|
['name' => ['ko' => '게시판 관리자', 'en' => 'Board Admin']]
|
|
);
|
|
|
|
$adminRole->permissions()->syncWithoutDetaching($adminPermissions);
|
|
$this->adminUser->roles()->attach($adminRole->id);
|
|
|
|
// User 권한 생성 및 할당 (라우트 미들웨어와 일치하는 식별자 사용)
|
|
$userPermissions = [];
|
|
$userPermissionDefs = [
|
|
'posts.read' => ['ko' => '게시글 조회', 'en' => 'Read Posts'],
|
|
'posts.write' => ['ko' => '게시글 작성', 'en' => 'Write Posts'],
|
|
'comments.read' => ['ko' => '댓글 조회', 'en' => 'Read Comments'],
|
|
'comments.write' => ['ko' => '댓글 작성', 'en' => 'Write Comments'],
|
|
];
|
|
|
|
foreach ($userPermissionDefs as $action => $name) {
|
|
$permission = Permission::firstOrCreate(
|
|
['identifier' => "sirsoft-board.{$slug}.{$action}"],
|
|
[
|
|
'name' => $name,
|
|
'slug' => "sirsoft-board.{$slug}.{$action}",
|
|
'type' => 'user',
|
|
]
|
|
);
|
|
$userPermissions[] = $permission->id;
|
|
}
|
|
|
|
$userRole = Role::firstOrCreate(
|
|
['identifier' => "{$slug}-user"],
|
|
['name' => ['ko' => '일반 사용자', 'en' => 'Regular User']]
|
|
);
|
|
|
|
$userRole->permissions()->syncWithoutDetaching($userPermissions);
|
|
$this->regularUser->roles()->attach($userRole->id);
|
|
$this->postAuthor->roles()->attach($userRole->id);
|
|
}
|
|
|
|
// ==========================================
|
|
// Admin 페이지 권한 테스트
|
|
// ==========================================
|
|
|
|
/**
|
|
* Admin 페이지에서는 admin_* 권한만 반환
|
|
*/
|
|
#[Test]
|
|
public function admin_page_returns_admin_permissions_only(): void
|
|
{
|
|
// Given: 회원 게시글 생성
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Test Post',
|
|
'content' => 'Test Content',
|
|
]);
|
|
|
|
// When: Admin API 호출
|
|
$response = $this->actingAs($this->adminUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/admin/board/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: admin 컨텍스트의 can_* abilities 포함
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
$this->assertArrayHasKey('can_read', $abilities);
|
|
$this->assertArrayHasKey('can_write', $abilities);
|
|
$this->assertArrayHasKey('can_manage', $abilities);
|
|
|
|
// Admin 컨텍스트이므로 admin.* 권한 기반으로 체크됨
|
|
// User 전용 키는 통합 can_* 키 사용으로 별도 존재하지 않음
|
|
$this->assertTrue($abilities['can_read']);
|
|
$this->assertTrue($abilities['can_write']);
|
|
$this->assertTrue($abilities['can_manage']);
|
|
}
|
|
|
|
/**
|
|
* Admin 페이지에서 User 권한 미반환
|
|
*/
|
|
#[Test]
|
|
public function admin_page_excludes_user_permissions(): void
|
|
{
|
|
// Given
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Test Post',
|
|
'content' => 'Test Content',
|
|
]);
|
|
|
|
// When
|
|
$response = $this->actingAs($this->adminUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/admin/board/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: abilities에 통합 can_* 키만 존재 (admin/user 구분 없음)
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
// 통합 키 사용으로 old-style 키는 존재하지 않음
|
|
$this->assertArrayNotHasKey('posts_read', $abilities);
|
|
$this->assertArrayNotHasKey('posts_write', $abilities);
|
|
$this->assertArrayNotHasKey('comments_read', $abilities);
|
|
$this->assertArrayNotHasKey('comments_write', $abilities);
|
|
}
|
|
|
|
// ==========================================
|
|
// User 페이지 권한 테스트
|
|
// ==========================================
|
|
|
|
/**
|
|
* User 페이지에서는 posts_*, comments_* 권한만 반환
|
|
*/
|
|
#[Test]
|
|
public function user_page_returns_user_permissions_only(): void
|
|
{
|
|
// Given
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Test Post',
|
|
'content' => 'Test Content',
|
|
]);
|
|
|
|
// When: User API 호출
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: User 컨텍스트의 can_* abilities 포함
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
$this->assertArrayHasKey('can_read', $abilities);
|
|
$this->assertArrayHasKey('can_write', $abilities);
|
|
$this->assertArrayHasKey('can_read_secret', $abilities);
|
|
$this->assertArrayHasKey('can_read_comments', $abilities);
|
|
$this->assertArrayHasKey('can_write_comments', $abilities);
|
|
|
|
// User 컨텍스트이므로 user.* 권한 기반으로 체크됨
|
|
$this->assertTrue($abilities['can_read']);
|
|
$this->assertTrue($abilities['can_write']);
|
|
$this->assertTrue($abilities['can_read_comments']);
|
|
$this->assertTrue($abilities['can_write_comments']);
|
|
}
|
|
|
|
/**
|
|
* User 페이지에서 Admin 권한 미반환
|
|
*/
|
|
#[Test]
|
|
public function user_page_excludes_admin_permissions(): void
|
|
{
|
|
// Given
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Test Post',
|
|
'content' => 'Test Content',
|
|
]);
|
|
|
|
// When
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: abilities에 통합 can_* 키만 존재 (admin/user 구분 없음)
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
// 통합 키 사용으로 old-style admin 키는 존재하지 않음
|
|
$this->assertArrayNotHasKey('admin_posts_read', $abilities);
|
|
$this->assertArrayNotHasKey('admin_posts_write', $abilities);
|
|
$this->assertArrayNotHasKey('admin_manage', $abilities);
|
|
}
|
|
|
|
// ==========================================
|
|
// can_access_admin 게이트 테스트 (#450)
|
|
// 유저 화면에서 관리자 게시판 화면 진입 크로스링크 노출 여부
|
|
// ==========================================
|
|
|
|
/**
|
|
* User 상세: admin.manage(Admin 타입) 권한 보유자는 can_access_admin = true
|
|
*
|
|
* @scenario link=user_board_to_admin, permitted=true
|
|
* @effects board_admin_gate_true_shows_link
|
|
*/
|
|
#[Test]
|
|
public function user_detail_returns_can_access_admin_true_for_admin_permission_holder(): void
|
|
{
|
|
// Given: 게시글 + admin.manage 권한 보유 사용자
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Test Post',
|
|
'content' => 'Test Content',
|
|
]);
|
|
|
|
// When: 관리 권한 보유자가 유저 라우트로 상세 조회
|
|
$response = $this->actingAs($this->adminUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: 유저 컨텍스트에도 can_access_admin 노출 + true
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
$this->assertArrayHasKey('can_access_admin', $abilities);
|
|
$this->assertTrue($abilities['can_access_admin']);
|
|
}
|
|
|
|
/**
|
|
* User 상세: 일반 사용자(admin.manage 미보유)는 can_access_admin = false
|
|
*
|
|
* @scenario link=user_board_to_admin, permitted=false
|
|
* @effects board_admin_gate_false_hides_link
|
|
*/
|
|
#[Test]
|
|
public function user_detail_returns_can_access_admin_false_for_regular_user(): void
|
|
{
|
|
// Given
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Test Post',
|
|
'content' => 'Test Content',
|
|
]);
|
|
|
|
// When: user 권한만 보유한 사용자가 유저 라우트로 상세 조회
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: can_access_admin 은 노출되나 false
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
$this->assertArrayHasKey('can_access_admin', $abilities);
|
|
$this->assertFalse($abilities['can_access_admin']);
|
|
}
|
|
|
|
/**
|
|
* User 목록: 컬렉션 abilities 에도 can_access_admin 노출
|
|
*/
|
|
#[Test]
|
|
public function user_list_collection_exposes_can_access_admin(): void
|
|
{
|
|
// Given
|
|
$this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'List Post',
|
|
'content' => 'List Content',
|
|
]);
|
|
|
|
// When: 관리 권한 보유자가 유저 라우트로 목록 조회
|
|
$response = $this->actingAs($this->adminUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts");
|
|
|
|
// Then: 컬렉션 abilities 에 can_access_admin = true
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
$this->assertArrayHasKey('can_access_admin', $abilities);
|
|
$this->assertTrue($abilities['can_access_admin']);
|
|
}
|
|
|
|
/**
|
|
* User 목록/상세 응답의 board 정보에 id 가 포함된다 (#450)
|
|
*
|
|
* "게시판 관리" 크로스링크가 /admin/boards/:id/edit 로 이동하려면 board id 필요.
|
|
*/
|
|
#[Test]
|
|
public function user_response_board_info_includes_id(): void
|
|
{
|
|
// Given
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Board Id Post',
|
|
'content' => 'Board Id Content',
|
|
]);
|
|
|
|
// When: 목록
|
|
$listResponse = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts");
|
|
// And: 상세
|
|
$detailResponse = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: 목록/상세 board 정보 모두 실제 게시판 id 노출
|
|
$listResponse->assertStatus(200);
|
|
$this->assertSame($this->board->id, $listResponse->json('data.board.id'));
|
|
|
|
$detailResponse->assertStatus(200);
|
|
$this->assertSame($this->board->id, $detailResponse->json('data.board.id'));
|
|
}
|
|
|
|
// ==========================================
|
|
// 소유권 플래그 테스트
|
|
// ==========================================
|
|
|
|
/**
|
|
* 본인 글: is_author = true
|
|
*/
|
|
#[Test]
|
|
public function is_author_true_for_own_post(): void
|
|
{
|
|
// Given: 작성자가 작성한 게시글
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'My Post',
|
|
'content' => 'My Content',
|
|
]);
|
|
|
|
// When: 작성자 본인이 조회
|
|
$response = $this->actingAs($this->postAuthor, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then
|
|
$response->assertStatus(200);
|
|
$this->assertTrue($response->json('data.is_author'));
|
|
$this->assertFalse($response->json('data.is_guest_post'));
|
|
}
|
|
|
|
/**
|
|
* 타인 글: is_author = false
|
|
*/
|
|
#[Test]
|
|
public function is_author_false_for_others_post(): void
|
|
{
|
|
// Given: 다른 사용자가 작성한 게시글
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Others Post',
|
|
'content' => 'Others Content',
|
|
]);
|
|
|
|
// When: 다른 사용자가 조회
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then
|
|
$response->assertStatus(200);
|
|
$this->assertFalse($response->json('data.is_author'));
|
|
$this->assertFalse($response->json('data.is_guest_post'));
|
|
}
|
|
|
|
/**
|
|
* 비회원 글: is_guest_post = true
|
|
*/
|
|
#[Test]
|
|
public function is_guest_post_true_for_guest_post(): void
|
|
{
|
|
// Given: 비회원이 작성한 게시글
|
|
$postId = $this->createPost([
|
|
'user_id' => null,
|
|
'author_name' => 'Guest Author',
|
|
'title' => 'Guest Post',
|
|
'content' => 'Guest Content',
|
|
]);
|
|
|
|
// When: 로그인 사용자가 조회
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then
|
|
$response->assertStatus(200);
|
|
$this->assertFalse($response->json('data.is_author'));
|
|
$this->assertTrue($response->json('data.is_guest_post'));
|
|
}
|
|
|
|
/**
|
|
* 회원 글: is_guest_post = false
|
|
*/
|
|
#[Test]
|
|
public function is_guest_post_false_for_member_post(): void
|
|
{
|
|
// Given: 회원이 작성한 게시글
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Member Post',
|
|
'content' => 'Member Content',
|
|
]);
|
|
|
|
// When
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then
|
|
$response->assertStatus(200);
|
|
$this->assertFalse($response->json('data.is_guest_post'));
|
|
}
|
|
|
|
// ==========================================
|
|
// 비회원 권한 테스트
|
|
// ==========================================
|
|
|
|
/**
|
|
* 비회원: guest_permissions에 따라 권한 체크
|
|
*/
|
|
#[Test]
|
|
public function guest_permissions_respected_for_non_authenticated_user(): void
|
|
{
|
|
// Given: 비회원 게시글
|
|
$postId = $this->createPost([
|
|
'user_id' => null,
|
|
'author_name' => 'Guest',
|
|
'title' => 'Public Post',
|
|
'content' => 'Public Content',
|
|
]);
|
|
|
|
// When: 비로그인 상태로 조회
|
|
$response = $this->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: grantDefaultGuestPermissions()에서 posts.read, posts.write, attachments.upload 부여
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
$this->assertTrue($abilities['can_read']); // guest에 posts.read 있음
|
|
$this->assertTrue($abilities['can_write']); // guest에 posts.write 있음
|
|
$this->assertFalse($abilities['can_read_comments']); // guest에 comments.read 없음
|
|
$this->assertFalse($abilities['can_write_comments']); // guest에 comments.write 없음
|
|
}
|
|
|
|
/**
|
|
* 로그인 사용자: Gate로 권한 체크
|
|
*/
|
|
#[Test]
|
|
public function authenticated_user_permissions_check_via_gate(): void
|
|
{
|
|
// Given
|
|
$postId = $this->createPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => 'Test Post',
|
|
'content' => 'Test Content',
|
|
]);
|
|
|
|
// When: 로그인 사용자 조회
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$postId}");
|
|
|
|
// Then: Role-Permission으로 체크
|
|
$response->assertStatus(200);
|
|
$abilities = $response->json('data.abilities');
|
|
|
|
// regularUser는 posts.read, posts.write, comments.read, comments.write 권한 보유
|
|
$this->assertTrue($abilities['can_read']);
|
|
$this->assertTrue($abilities['can_write']);
|
|
$this->assertTrue($abilities['can_read_comments']);
|
|
$this->assertTrue($abilities['can_write_comments']);
|
|
}
|
|
|
|
// ==========================================
|
|
// 답글 섹션 삭제 게시글 필터링 테스트
|
|
// ==========================================
|
|
|
|
/**
|
|
* 일반 사용자는 답글 섹션에서 삭제된 답글을 볼 수 없다
|
|
*/
|
|
#[Test]
|
|
public function regular_user_cannot_see_deleted_reply_in_post_detail(): void
|
|
{
|
|
// Given: 원글 생성
|
|
$parentId = $this->createTestPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => '원글',
|
|
'content' => '원글 내용',
|
|
]);
|
|
|
|
// 정상 답글 생성
|
|
$normalReplyId = $this->createTestPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'parent_id' => $parentId,
|
|
'title' => '정상 답글',
|
|
'content' => '정상 답글 내용',
|
|
'status' => 'published',
|
|
]);
|
|
|
|
// 삭제된 답글 생성 (status='deleted', deleted_at 설정)
|
|
$this->createTestPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'parent_id' => $parentId,
|
|
'title' => '삭제된 답글',
|
|
'content' => '삭제된 답글 내용',
|
|
'status' => 'deleted',
|
|
'deleted_at' => now(),
|
|
]);
|
|
|
|
// When: 일반 사용자가 원글 상세 조회
|
|
$response = $this->actingAs($this->regularUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/boards/{$this->board->slug}/posts/{$parentId}");
|
|
|
|
// Then: replies에 삭제된 답글이 포함되지 않음
|
|
$response->assertStatus(200);
|
|
$replies = $response->json('data.replies');
|
|
$this->assertCount(1, $replies);
|
|
$this->assertEquals($normalReplyId, $replies[0]['id']);
|
|
}
|
|
|
|
/**
|
|
* 관리자는 답글 섹션에서 삭제된 답글을 볼 수 있다
|
|
*/
|
|
#[Test]
|
|
public function admin_user_can_see_deleted_reply_in_post_detail(): void
|
|
{
|
|
// Given: 원글 생성
|
|
$parentId = $this->createTestPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'title' => '원글',
|
|
'content' => '원글 내용',
|
|
]);
|
|
|
|
// 정상 답글 생성
|
|
$this->createTestPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'parent_id' => $parentId,
|
|
'title' => '정상 답글',
|
|
'content' => '정상 답글 내용',
|
|
'status' => 'published',
|
|
]);
|
|
|
|
// 삭제된 답글 생성
|
|
$this->createTestPost([
|
|
'user_id' => $this->postAuthor->id,
|
|
'parent_id' => $parentId,
|
|
'title' => '삭제된 답글',
|
|
'content' => '삭제된 답글 내용',
|
|
'status' => 'deleted',
|
|
'deleted_at' => now(),
|
|
]);
|
|
|
|
// When: 관리자가 Admin API로 원글 상세 조회
|
|
$response = $this->actingAs($this->adminUser, 'sanctum')
|
|
->getJson("/api/modules/sirsoft-board/admin/board/{$this->board->slug}/posts/{$parentId}");
|
|
|
|
// Then: replies에 삭제된 답글이 포함됨
|
|
$response->assertStatus(200);
|
|
$replies = $response->json('data.replies');
|
|
$this->assertCount(2, $replies);
|
|
}
|
|
|
|
// ==========================================
|
|
// 헬퍼 메서드
|
|
// ==========================================
|
|
|
|
/**
|
|
* 게시글 생성 헬퍼
|
|
*/
|
|
private function createPost(array $attributes): int
|
|
{
|
|
$postId = $this->createTestPost($attributes);
|
|
|
|
return $postId;
|
|
}
|
|
} |