Files
2026-04-22 10:43:31 +09:00

183 lines
5.5 KiB
PHP

<?php
namespace Modules\Sirsoft\Board\Tests\Feature\User;
require_once __DIR__.'/../../ModuleTestCase.php';
use Illuminate\Support\Facades\Cache;
use Modules\Sirsoft\Board\Tests\BoardTestCase;
/**
* 게시글 작성 쿨다운 API 통합 시나리오 테스트
*
* 검증 목적:
* - 쿨다운 비활성(0초): 연속 작성 허용
* - 쿨다운 활성: 첫 작성 성공 후 두 번째 작성 422
* - 쿨다운 활성: 캐시 만료 후 재작성 허용 (단위 테스트에서 검증)
* - 회원은 user_id로, 비회원은 IP로 격리
*
* @group board
* @group feature
* @group cooldown
*/
class PostCooldownTest extends BoardTestCase
{
private array $mockSettings = [];
protected function getTestBoardSlug(): string
{
return 'post-cooldown-test';
}
protected function getDefaultBoardAttributes(string $slug): array
{
return [
'slug' => $slug,
'name' => ['ko' => '쿨다운 테스트 게시판', 'en' => 'Cooldown Test Board'],
'is_active' => true,
'secret_mode' => 'disabled',
'blocked_keywords' => [],
'min_title_length' => 1,
'max_title_length' => 200,
'min_content_length' => 1,
'max_content_length' => 10000,
];
}
protected function setUp(): void
{
parent::setUp();
Cache::flush();
$this->grantUserRolePermissions(['posts.read', 'posts.write']);
$this->setGuestPermissions(['posts.read', 'posts.write']);
$this->mockSettings = [
'spam_security' => [
'post_cooldown_seconds' => 0,
'comment_cooldown_seconds' => 0,
'report_cooldown_seconds' => 0,
'view_count_cache_ttl' => 86400,
],
];
}
private function applySettings(): void
{
// g7_module_settings()는 Config::get("g7_settings.modules.sirsoft-board.*")를 읽음
foreach ($this->mockSettings as $category => $values) {
config(["g7_settings.modules.sirsoft-board.{$category}" => $values]);
}
}
private function postUrl(): string
{
return "/api/modules/sirsoft-board/boards/{$this->board->slug}/posts";
}
private function validPostData(): array
{
return [
'title' => '쿨다운 테스트 제목',
'content' => '쿨다운 테스트 내용입니다.',
];
}
// ==========================================
// 쿨다운 비활성 (0초)
// ==========================================
/**
* 쿨다운 0초: 연속 작성 허용
*/
public function test_consecutive_posts_allowed_when_cooldown_disabled(): void
{
$this->mockSettings['spam_security']['post_cooldown_seconds'] = 0;
$this->applySettings();
$user = $this->createUser();
$this->actingAs($user)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(201);
$this->actingAs($user)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(201);
}
// ==========================================
// 쿨다운 활성
// ==========================================
/**
* 쿨다운 활성: 첫 번째 작성 성공
*/
public function test_first_post_succeeds_when_cooldown_active(): void
{
$this->mockSettings['spam_security']['post_cooldown_seconds'] = 60;
$this->applySettings();
$user = $this->createUser();
$this->actingAs($user)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(201);
}
/**
* 쿨다운 활성: 첫 작성 직후 두 번째 작성 422
*/
public function test_second_post_rejected_when_cooldown_active(): void
{
$this->mockSettings['spam_security']['post_cooldown_seconds'] = 60;
$this->applySettings();
$user = $this->createUser();
// 첫 번째 작성 성공 → 쿨다운 캐시 등록
$this->actingAs($user)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(201);
// 두 번째 작성 시 422
$this->actingAs($user)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(422);
}
/**
* 쿨다운 활성: 다른 사용자는 영향 없음 (user_id 격리)
*/
public function test_cooldown_is_isolated_per_user(): void
{
$this->mockSettings['spam_security']['post_cooldown_seconds'] = 60;
$this->applySettings();
$userA = $this->createUser();
$userB = $this->createUser();
// userA 작성 → 쿨다운 등록
$this->actingAs($userA)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(201);
// userB는 쿨다운 영향 없이 작성 가능
$this->actingAs($userB)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(201);
}
/**
* 쿨다운 오류 응답에 422 상태코드와 errors 필드가 있다
*/
public function test_cooldown_rejection_returns_422_with_errors(): void
{
$this->mockSettings['spam_security']['post_cooldown_seconds'] = 60;
$this->applySettings();
$user = $this->createUser();
$this->actingAs($user)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(201);
$this->actingAs($user)->postJson($this->postUrl(), $this->validPostData())
->assertStatus(422)
->assertJsonStructure(['errors']);
}
}