Files
Gnuboard7/modules/_bundled/sirsoft-board/tests/Unit/CountColumnsTest.php
T
2026-04-20 20:37:49 +09:00

286 lines
9.5 KiB
PHP

<?php
namespace Modules\Sirsoft\Board\Tests\Unit;
use App\Extension\UpgradeContext;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Modules\Sirsoft\Board\Models\Board;
use Modules\Sirsoft\Board\Tests\ModuleTestCase;
use Modules\Sirsoft\Board\Upgrades\Upgrade_1_0_0_beta_2;
/**
* STEP 3: 카운팅 컬럼 테스트
*
* 마이그레이션으로 컬럼 추가 후,
* Upgrade_1_0_0_beta_2의 syncCountColumns()로 기존 데이터 동기화를 검증합니다.
*/
class CountColumnsTest extends ModuleTestCase
{
/**
* 테스트용 게시판
*/
private Board $board;
protected function setUp(): void
{
parent::setUp();
$this->board = Board::firstOrCreate(
['slug' => 'count-test'],
[
'name' => ['ko' => '카운트 테스트', 'en' => 'Count Test'],
'is_active' => true,
]
);
}
/**
* 카운팅 컬럼이 board_posts, board_comments 테이블에 존재하는지 확인합니다.
*/
public function test_count_columns_exist(): void
{
$this->assertTrue(Schema::hasColumn('board_posts', 'replies_count'));
$this->assertTrue(Schema::hasColumn('board_posts', 'comments_count'));
$this->assertTrue(Schema::hasColumn('board_posts', 'attachments_count'));
$this->assertTrue(Schema::hasColumn('board_comments', 'replies_count'));
}
/**
* 카운팅 컬럼의 기본값이 0인지 확인합니다.
*/
public function test_count_columns_default_to_zero(): void
{
$postId = $this->createTestPost();
$post = DB::table('board_posts')->where('id', $postId)->first();
$this->assertEquals(0, $post->replies_count);
$this->assertEquals(0, $post->comments_count);
$this->assertEquals(0, $post->attachments_count);
}
/**
* Upgrade_1_0_0이 replies_count를 올바르게 동기화하는지 확인합니다.
*/
public function test_upgrade_syncs_replies_count(): void
{
// 원글 생성
$parentId = $this->createTestPost(['title' => '원글']);
// 답글 3개 생성
$this->createTestPost(['title' => '답글1', 'parent_id' => $parentId, 'depth' => 1]);
$this->createTestPost(['title' => '답글2', 'parent_id' => $parentId, 'depth' => 1]);
$this->createTestPost(['title' => '답글3', 'parent_id' => $parentId, 'depth' => 1]);
// 삭제된 답글 1개 (soft delete — 카운트에서 제외되어야 함)
$this->createTestPost([
'title' => '삭제된 답글',
'parent_id' => $parentId,
'depth' => 1,
'deleted_at' => now(),
]);
// replies_count를 0으로 리셋 (동기화 전 상태 시뮬레이션)
DB::table('board_posts')->where('id', $parentId)->update(['replies_count' => 0]);
// Upgrade 실행
$this->runUpgrade();
// 검증: 삭제된 답글 제외하여 3개
$post = DB::table('board_posts')->where('id', $parentId)->first();
$this->assertEquals(3, $post->replies_count);
}
/**
* Upgrade_1_0_0이 comments_count를 올바르게 동기화하는지 확인합니다.
*/
public function test_upgrade_syncs_comments_count(): void
{
$postId = $this->createTestPost();
// 댓글 2개 생성
$this->createTestComment($postId, ['content' => '댓글1']);
$this->createTestComment($postId, ['content' => '댓글2']);
// 삭제된 댓글 1개 (soft delete — 카운트에서 제외되어야 함)
$this->createTestComment($postId, [
'content' => '삭제된 댓글',
'deleted_at' => now(),
]);
// comments_count를 0으로 리셋 (동기화 전 상태 시뮬레이션)
DB::table('board_posts')->where('id', $postId)->update(['comments_count' => 0]);
// Upgrade 실행
$this->runUpgrade();
// 검증: 삭제된 댓글 제외하여 2개
$post = DB::table('board_posts')->where('id', $postId)->first();
$this->assertEquals(2, $post->comments_count);
}
/**
* Upgrade가 attachments_count를 올바르게 동기화하는지 확인합니다.
*/
public function test_upgrade_syncs_attachments_count(): void
{
$postId = $this->createTestPost();
// 첨부파일 2개 생성
$this->createTestAttachment($postId);
$this->createTestAttachment($postId);
// 삭제된 첨부파일 1개 (카운트에서 제외되어야 함)
$this->createTestAttachment($postId, ['deleted_at' => now()]);
DB::table('board_posts')->where('id', $postId)->update(['attachments_count' => 0]);
$this->runUpgrade();
$post = DB::table('board_posts')->where('id', $postId)->first();
$this->assertEquals(2, $post->attachments_count);
}
/**
* Upgrade가 board_comments.replies_count를 올바르게 동기화하는지 확인합니다.
*/
public function test_upgrade_syncs_comment_replies_count(): void
{
$postId = $this->createTestPost();
$parentCommentId = $this->createTestComment($postId, ['content' => '부모 댓글']);
// 대댓글 2개 생성
$this->createTestComment($postId, ['content' => '대댓글1', 'parent_id' => $parentCommentId]);
$this->createTestComment($postId, ['content' => '대댓글2', 'parent_id' => $parentCommentId]);
// 삭제된 대댓글 1개 (카운트에서 제외되어야 함)
$this->createTestComment($postId, [
'content' => '삭제된 대댓글',
'parent_id' => $parentCommentId,
'deleted_at' => now(),
]);
DB::table('board_comments')->where('id', $parentCommentId)->update(['replies_count' => 0]);
$this->runUpgrade();
$comment = DB::table('board_comments')->where('id', $parentCommentId)->first();
$this->assertEquals(2, $comment->replies_count);
}
/**
* 답글도 댓글도 없는 게시글의 카운트가 0으로 유지되는지 확인합니다.
*/
public function test_upgrade_keeps_zero_for_posts_without_replies_or_comments(): void
{
$postId = $this->createTestPost();
$this->runUpgrade();
$post = DB::table('board_posts')->where('id', $postId)->first();
$this->assertEquals(0, $post->replies_count);
$this->assertEquals(0, $post->comments_count);
$this->assertEquals(0, $post->attachments_count);
}
/**
* Upgrade_1_0_0_beta_2를 실행합니다.
*
* @return void
*/
private function runUpgrade(): void
{
$context = new UpgradeContext(
fromVersion: '0.0.0',
toVersion: '1.0.0',
currentStep: '1.0.0',
);
$upgrade = new Upgrade_1_0_0_beta_2();
$upgrade->run($context);
}
/**
* 테스트 게시글을 직접 DB에 생성합니다.
*
* @param array $attributes 게시글 속성
* @return int 생성된 게시글 ID
*/
private function createTestPost(array $attributes = []): int
{
$defaults = [
'board_id' => $this->board->id,
'title' => '테스트 게시글',
'content' => '테스트 내용입니다.',
'user_id' => null,
'author_name' => '테스트',
'ip_address' => '127.0.0.1',
'is_notice' => false,
'is_secret' => false,
'status' => 'published',
'trigger_type' => 'admin',
'view_count' => 0,
'replies_count' => 0,
'comments_count' => 0,
'attachments_count' => 0,
'created_at' => now(),
'updated_at' => now(),
];
return DB::table('board_posts')->insertGetId(array_merge($defaults, $attributes));
}
/**
* 테스트 댓글을 직접 DB에 생성합니다.
*
* @param int $postId 게시글 ID
* @param array $attributes 댓글 속성
* @return int 생성된 댓글 ID
*/
private function createTestComment(int $postId, array $attributes = []): int
{
$defaults = [
'board_id' => $this->board->id,
'post_id' => $postId,
'user_id' => null,
'author_name' => '테스트',
'content' => '테스트 댓글입니다.',
'ip_address' => '127.0.0.1',
'status' => 'published',
'replies_count' => 0,
'created_at' => now(),
'updated_at' => now(),
];
return DB::table('board_comments')->insertGetId(array_merge($defaults, $attributes));
}
/**
* 테스트 첨부파일을 직접 DB에 생성합니다.
*
* @param int $postId 게시글 ID
* @param array $attributes 첨부파일 속성
* @return int 생성된 첨부파일 ID
*/
private function createTestAttachment(int $postId, array $attributes = []): int
{
$defaults = [
'board_id' => $this->board->id,
'post_id' => $postId,
'hash' => substr(md5(uniqid()), 0, 12),
'original_filename' => 'test.txt',
'stored_filename' => 'test_' . uniqid() . '.txt',
'disk' => 'local',
'path' => 'attachments',
'mime_type' => 'text/plain',
'size' => 100,
'collection' => 'default',
'order' => 0,
'created_at' => now(),
'updated_at' => now(),
];
return DB::table('board_attachments')->insertGetId(array_merge($defaults, $attributes));
}
}