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

409 lines
14 KiB
PHP

<?php
namespace Modules\Sirsoft\Board\Tests\Unit;
use Illuminate\Support\Facades\File;
use Modules\Sirsoft\Board\Services\BoardPermissionService;
use Modules\Sirsoft\Board\Services\BoardSettingsService;
use Modules\Sirsoft\Board\Tests\ModuleTestCase;
/**
* BoardSettingsService 단위 테스트
*
* ModuleSettingsInterface 구현을 검증합니다.
*/
class BoardSettingsServiceTest extends ModuleTestCase
{
private BoardSettingsService $service;
private string $storagePath;
protected function setUp(): void
{
parent::setUp();
$permissionService = $this->createMock(BoardPermissionService::class);
$this->service = new BoardSettingsService($permissionService);
$this->storagePath = storage_path('app/modules/sirsoft-board/settings');
// 테스트 전 저장소 정리
if (File::isDirectory($this->storagePath)) {
File::deleteDirectory($this->storagePath);
}
}
protected function tearDown(): void
{
// 테스트 후 저장소 정리
if (File::isDirectory($this->storagePath)) {
File::deleteDirectory($this->storagePath);
}
parent::tearDown();
}
// ========================================
// getSettingsDefaultsPath 테스트
// ========================================
/**
* defaults.json 경로가 정상적으로 반환되는지 확인
*/
public function test_get_settings_defaults_path_returns_valid_path(): void
{
$path = $this->service->getSettingsDefaultsPath();
$this->assertNotNull($path);
$this->assertFileExists($path);
$this->assertStringEndsWith('defaults.json', $path);
}
// ========================================
// getAllSettings 테스트
// ========================================
/**
* 저장된 설정이 없으면 defaults.json의 기본값을 반환하는지 확인
*/
public function test_get_all_settings_returns_defaults_when_no_saved_settings(): void
{
$settings = $this->service->getAllSettings();
$this->assertIsArray($settings);
$this->assertArrayHasKey('basic_defaults', $settings);
$this->assertArrayHasKey('report_policy', $settings);
$this->assertArrayHasKey('spam_security', $settings);
}
/**
* basic_defaults 카테고리의 기본값이 올바른지 확인
*/
public function test_get_all_settings_has_correct_basic_defaults(): void
{
$settings = $this->service->getAllSettings();
$basicDefaults = $settings['basic_defaults'];
$this->assertEquals('basic', $basicDefaults['type']);
$this->assertEquals(20, $basicDefaults['per_page']);
$this->assertEquals(15, $basicDefaults['per_page_mobile']);
$this->assertEquals(5, $basicDefaults['max_reply_depth']);
$this->assertEquals(10, $basicDefaults['max_comment_depth']);
$this->assertTrue($basicDefaults['use_comment']);
$this->assertTrue($basicDefaults['use_reply']);
$this->assertTrue($basicDefaults['show_view_count']);
$this->assertTrue($basicDefaults['notify_admin_on_post']);
$this->assertTrue($basicDefaults['notify_author']);
}
/**
* report_policy 카테고리의 기본값이 올바른지 확인
*/
public function test_get_all_settings_has_correct_report_policy(): void
{
$settings = $this->service->getAllSettings();
$reportPolicy = $settings['report_policy'];
$this->assertEquals(5, $reportPolicy['auto_hide_threshold']);
$this->assertEquals('both', $reportPolicy['auto_hide_target']);
$this->assertEquals(10, $reportPolicy['daily_report_limit']);
}
/**
* spam_security 카테고리의 기본값이 올바른지 확인
*/
public function test_get_all_settings_has_correct_spam_security(): void
{
$settings = $this->service->getAllSettings();
$spamSecurity = $settings['spam_security'];
$this->assertEquals(0, $spamSecurity['post_cooldown_seconds']);
$this->assertEquals(86400, $spamSecurity['view_count_cache_ttl']);
}
/**
* blocked_keywords가 basic_defaults에 포함되는지 확인
*/
public function test_get_all_settings_has_blocked_keywords_in_basic_defaults(): void
{
$settings = $this->service->getAllSettings();
$basicDefaults = $settings['basic_defaults'];
$this->assertArrayHasKey('blocked_keywords', $basicDefaults);
$this->assertIsArray($basicDefaults['blocked_keywords']);
$this->assertNotEmpty($basicDefaults['blocked_keywords']);
}
/**
* 결과가 캐싱되는지 확인 (두 번째 호출 시 동일 객체)
*/
public function test_get_all_settings_caches_result(): void
{
$first = $this->service->getAllSettings();
$second = $this->service->getAllSettings();
$this->assertSame($first, $second);
}
// ========================================
// getSettings (카테고리별) 테스트
// ========================================
/**
* 특정 카테고리 설정을 조회할 수 있는지 확인
*/
public function test_get_settings_returns_category_settings(): void
{
$basicDefaults = $this->service->getSettings('basic_defaults');
$this->assertIsArray($basicDefaults);
$this->assertArrayHasKey('per_page', $basicDefaults);
$this->assertEquals(20, $basicDefaults['per_page']);
}
/**
* 존재하지 않는 카테고리는 빈 배열 반환
*/
public function test_get_settings_returns_empty_for_unknown_category(): void
{
$result = $this->service->getSettings('nonexistent');
$this->assertIsArray($result);
$this->assertEmpty($result);
}
// ========================================
// getSetting (단일 키) 테스트
// ========================================
/**
* dot notation으로 설정값을 조회할 수 있는지 확인
*/
public function test_get_setting_with_dot_notation(): void
{
$perPage = $this->service->getSetting('basic_defaults.per_page');
$this->assertEquals(20, $perPage);
}
/**
* 존재하지 않는 키에 대해 기본값 반환
*/
public function test_get_setting_returns_default_for_unknown_key(): void
{
$result = $this->service->getSetting('basic_defaults.nonexistent', 'fallback');
$this->assertEquals('fallback', $result);
}
// ========================================
// setSetting 테스트
// ========================================
/**
* 개별 설정값을 저장할 수 있는지 확인
*/
public function test_set_setting_saves_value(): void
{
$result = $this->service->setSetting('basic_defaults.per_page', 30);
$this->assertTrue($result);
// 캐시 초기화 후 다시 조회
$this->service->clearCache();
$perPage = $this->service->getSetting('basic_defaults.per_page');
$this->assertEquals(30, $perPage);
}
/**
* 설정이 파일에 실제로 저장되는지 확인
*/
public function test_set_setting_persists_to_file(): void
{
$this->service->setSetting('report_policy.auto_hide_threshold', 10);
$filePath = $this->storagePath.'/report_policy.json';
$this->assertFileExists($filePath);
$content = json_decode(File::get($filePath), true);
$this->assertEquals(10, $content['auto_hide_threshold']);
}
// ========================================
// saveSettings (전체 저장) 테스트
// ========================================
/**
* 여러 카테고리를 한 번에 저장할 수 있는지 확인
*/
public function test_save_settings_saves_multiple_categories(): void
{
$result = $this->service->saveSettings([
'basic_defaults' => [
'per_page' => 50,
'type' => 'gallery',
],
'report_policy' => [
'auto_hide_threshold' => 3,
],
]);
$this->assertTrue($result);
// 캐시 초기화 후 검증
$this->service->clearCache();
$settings = $this->service->getAllSettings();
$this->assertEquals(50, $settings['basic_defaults']['per_page']);
$this->assertEquals('gallery', $settings['basic_defaults']['type']);
$this->assertEquals(3, $settings['report_policy']['auto_hide_threshold']);
}
/**
* _meta 등 메타 키는 저장하지 않는지 확인
*/
public function test_save_settings_ignores_meta_keys(): void
{
$result = $this->service->saveSettings([
'_meta' => ['version' => '2.0.0'],
'_tab' => 'basic',
'basic_defaults' => ['per_page' => 25],
]);
$this->assertTrue($result);
// _meta 파일이 생성되지 않아야 함
$this->assertFileDoesNotExist($this->storagePath.'/_meta.json');
$this->assertFileDoesNotExist($this->storagePath.'/_tab.json');
}
/**
* 카테고리 값이 배열이 아닌 경우 무시되는지 확인
*/
public function test_save_settings_ignores_non_array_category_values(): void
{
$result = $this->service->saveSettings([
'basic_defaults' => ['per_page' => 25],
'invalid_key' => 'string_value',
]);
$this->assertTrue($result);
$this->assertFileDoesNotExist($this->storagePath.'/invalid_key.json');
}
/**
* 저장 후 캐시가 초기화되는지 확인
*/
public function test_save_settings_clears_cache(): void
{
// 캐시를 채움
$this->service->getAllSettings();
// 저장 후 캐시가 초기화되어야 함
$this->service->saveSettings([
'basic_defaults' => ['per_page' => 99],
]);
// 새로운 인스턴스처럼 동작해야 함
$settings = $this->service->getAllSettings();
$this->assertEquals(99, $settings['basic_defaults']['per_page']);
}
// ========================================
// getFrontendSettings 테스트
// ========================================
/**
* 프론트엔드 설정이 올바른 구조로 반환되는지 확인
*
* defaults.json의 frontend_schema 모든 카테고리가 expose: false이므로
* getFrontendSettings()는 빈 배열을 반환해야 합니다.
*/
public function test_get_frontend_settings_returns_exposed_categories(): void
{
$frontendSettings = $this->service->getFrontendSettings();
$this->assertIsArray($frontendSettings);
// 모든 카테고리가 expose: false → 프론트엔드에 노출되는 카테고리 없음
$this->assertEmpty($frontendSettings);
}
/**
* 프론트엔드 설정에 실제 값이 포함되는지 확인
*
* defaults.json의 frontend_schema 모든 카테고리가 expose: false이므로
* getFrontendSettings()는 빈 배열을 반환해야 합니다.
*/
public function test_get_frontend_settings_contains_actual_values(): void
{
$frontendSettings = $this->service->getFrontendSettings();
// 모든 카테고리가 expose: false → 빈 배열 반환
$this->assertIsArray($frontendSettings);
$this->assertEmpty($frontendSettings);
}
// ========================================
// clearCache 테스트
// ========================================
/**
* 캐시 초기화 후 fresh한 데이터를 가져오는지 확인
*/
public function test_clear_cache_forces_fresh_load(): void
{
// 첫 번째 조회로 캐시 생성
$first = $this->service->getAllSettings();
// 파일 직접 수정 (캐시 우회)
$this->service->setSetting('basic_defaults.per_page', 77);
// 캐시 초기화
$this->service->clearCache();
// 수정된 값이 반영되어야 함
$settings = $this->service->getAllSettings();
$this->assertEquals(77, $settings['basic_defaults']['per_page']);
}
// ========================================
// 저장 후 기본값 병합 테스트
// ========================================
/**
* 저장된 설정이 기본값과 올바르게 병합되는지 확인
*/
public function test_saved_settings_merge_with_defaults(): void
{
// 일부 필드만 저장
$this->service->saveSettings([
'basic_defaults' => ['per_page' => 40],
]);
$this->service->clearCache();
$settings = $this->service->getAllSettings();
// 저장된 값 반영
$this->assertEquals(40, $settings['basic_defaults']['per_page']);
// 저장되지 않은 기본값은 유지
$this->assertEquals('basic', $settings['basic_defaults']['type']);
$this->assertEquals(15, $settings['basic_defaults']['per_page_mobile']);
$this->assertTrue($settings['basic_defaults']['use_comment']);
}
/**
* default_board_permissions 기본값이 정상적으로 포함되는지 확인
*/
public function test_basic_defaults_includes_default_board_permissions(): void
{
$settings = $this->service->getAllSettings();
$permissions = $settings['basic_defaults']['default_board_permissions'] ?? null;
$this->assertNotNull($permissions);
$this->assertIsArray($permissions);
$this->assertArrayHasKey('posts.read', $permissions);
$this->assertContains('admin', $permissions['posts.read']);
$this->assertContains('guest', $permissions['posts.read']);
}
}