Files
Gnuboard7/tests/Unit/Seo/ValidateSeoConfigTest.php
T
2026-04-01 10:30:52 +09:00

185 lines
5.4 KiB
PHP

<?php
namespace Tests\Unit\Seo;
use App\Extension\TemplateManager;
use Illuminate\Support\Facades\File;
use ReflectionMethod;
use Tests\TestCase;
class ValidateSeoConfigTest extends TestCase
{
private TemplateManager $templateManager;
private string $testTemplateDir;
private string $templateId = 'test-seo-validate';
/**
* 테스트 초기화 - TemplateManager와 임시 디렉토리를 준비합니다.
*/
protected function setUp(): void
{
parent::setUp();
$this->templateManager = app(TemplateManager::class);
$this->testTemplateDir = base_path("templates/{$this->templateId}");
if (File::exists($this->testTemplateDir)) {
File::deleteDirectory($this->testTemplateDir);
}
File::makeDirectory($this->testTemplateDir, 0755, true);
}
/**
* 테스트 정리 - 임시 디렉토리를 삭제합니다.
*/
protected function tearDown(): void
{
if (File::exists($this->testTemplateDir)) {
File::deleteDirectory($this->testTemplateDir);
}
parent::tearDown();
}
/**
* 올바른 seo-config.json → true를 반환합니다.
*/
public function test_valid_seo_config_passes(): void
{
$this->writeSeoConfig([
'stylesheets' => ['https://example.com/style.css'],
'self_closing' => ['img', 'hr'],
'render_modes' => [
'image_gallery' => ['type' => 'iterate', 'source' => '$props_source', 'item_tag' => 'img'],
'text_format' => ['type' => 'format'],
'html_content' => ['type' => 'raw', 'source' => '$props_source'],
],
'component_map' => [
'Div' => ['tag' => 'div'],
'Img' => ['tag' => 'img'],
'ProductImageViewer' => ['tag' => 'div', 'render' => 'image_gallery', 'props_source' => 'images'],
'StarRating' => ['tag' => 'span', 'render' => 'text_format', 'format' => '{value} / {max}'],
'HtmlContent' => ['tag' => 'div', 'render' => 'html_content', 'props_source' => 'content'],
],
]);
$this->assertTrue($this->callValidateSeoConfig());
}
/**
* 잘못된 JSON → false를 반환합니다.
*/
public function test_invalid_json_fails(): void
{
file_put_contents(
$this->testTemplateDir.'/seo-config.json',
'{ invalid json ,,, }'
);
$this->expectException(\Exception::class);
$this->callValidateSeoConfig();
}
/**
* component_map에서 미정의 render mode 참조 → false를 반환합니다.
*/
public function test_undefined_render_mode_reference_fails(): void
{
$this->writeSeoConfig([
'render_modes' => [
'image_gallery' => ['type' => 'iterate'],
],
'component_map' => [
'MyComponent' => ['tag' => 'div', 'render' => 'nonexistent_mode'],
],
]);
$this->expectException(\Exception::class);
$this->callValidateSeoConfig();
}
/**
* render_modes에 잘못된 type → false를 반환합니다.
*/
public function test_invalid_render_mode_type_fails(): void
{
$this->writeSeoConfig([
'render_modes' => [
'my_mode' => ['type' => 'unknown_type'],
],
'component_map' => [],
]);
$this->expectException(\Exception::class);
$this->callValidateSeoConfig();
}
/**
* component_map에 tag 키 없음 → false를 반환합니다.
*/
public function test_missing_tag_in_component_map_fails(): void
{
$this->writeSeoConfig([
'component_map' => [
'Div' => ['className' => 'wrapper'],
],
]);
$this->expectException(\Exception::class);
$this->callValidateSeoConfig();
}
/**
* 파일 미존재 → true (경고만)를 반환합니다.
*/
public function test_seo_config_not_found_passes_with_warning(): void
{
// seo-config.json을 생성하지 않음
@unlink($this->testTemplateDir.'/seo-config.json');
$this->assertTrue($this->callValidateSeoConfig());
}
/**
* stylesheets가 문자열 → false를 반환합니다.
*/
public function test_stylesheets_not_array_fails(): void
{
$this->writeSeoConfig([
'stylesheets' => 'https://example.com/style.css',
'component_map' => [
'Div' => ['tag' => 'div'],
],
]);
$this->expectException(\Exception::class);
$this->callValidateSeoConfig();
}
/**
* seo-config.json 파일을 작성합니다.
*
* @param array $config 설정 배열
*/
private function writeSeoConfig(array $config): void
{
file_put_contents(
$this->testTemplateDir.'/seo-config.json',
json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
);
}
/**
* protected validateSeoConfig()를 Reflection으로 호출합니다.
*
* @return bool 검증 결과
*/
private function callValidateSeoConfig(): bool
{
$method = new ReflectionMethod(TemplateManager::class, 'validateSeoConfig');
$method->setAccessible(true);
return $method->invoke($this->templateManager, $this->templateId);
}
}