Files
Gnuboard7/tests/Feature/Console/ApiDocSampleServiceTest.php
HeuJung 809409f3cf fix(api-docs): 문서 샘플 언어팩이 전역 지원 로케일을 오염시키는 문제 수정
api:docgen --seed 가 생성하는 샘플 언어팩이 scope=core + status=active 로
만들어져 getActiveCoreLocales 승격 쿼리에 걸렸다. 그 결과 시스템 전역
supported_locales/translatable_locales 가 넓어지고, 그 아래에서 시드된
다국어 데이터에 실재하지 않는 로케일 키가 박혔다. 샘플을 비활성화하면
그 키가 TranslatableField 검증을 통과하지 못해 저장이 막힌다.

문서용 샘플은 조회 예시일 뿐 시스템 동작을 바꿀 자격이 없으므로,
승격 경로를 벗어난 조합(module 스코프 + installed 상태 + 실재 번들 로케일)
으로 생성하도록 바꾸고 audit 룰로 재발을 차단한다.

README 재생성 시 사람이 덧붙인 헤딩 섹션이 통째로 소실되던 사전 결함도
함께 수정했다(경계를 임의의 ## 이 아닌 확장 목차 헤딩으로 특정).
2026-07-10 19:27:27 +09:00

109 lines
4.1 KiB
PHP

<?php
namespace Tests\Feature\Console;
use App\Contracts\Repositories\LanguagePackRepositoryInterface;
use App\Models\LanguagePack;
use App\Models\User;
use App\Services\LanguagePack\LanguagePackRegistry;
use App\Support\ApiDoc\ApiDocSampleService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
* API 문서 실측용 완전 샘플 시더 Feature 테스트.
*
* 도메인별 완전 샘플이 생성되고, 재실행 시 중복 없이 멱등하며,
* 완전 사용자 샘플의 프로필 필드가 채워지는지 검증한다.
*
* 문서용 샘플은 조회 예시를 만들기 위한 것이지 시스템 동작을 바꿀 자격이 없다.
* 샘플 언어팩이 전역 지원 로케일 목록을 넓히지 않는지 함께 검증한다.
*/
class ApiDocSampleServiceTest extends TestCase
{
use RefreshDatabase;
#[Test]
public function 도메인별_대표_샘플_맵을_반환한다(): void
{
$map = (new ApiDocSampleService)->seed();
$this->assertArrayHasKey('users', $map);
$this->assertArrayHasKey('roles', $map);
$this->assertArrayHasKey('menus', $map);
$this->assertArrayHasKey('schedules', $map);
// 각 항목은 model/key/value 구조
$this->assertSame(User::class, $map['users']['model']);
$this->assertArrayHasKey('key', $map['users']);
$this->assertNotEmpty($map['users']['value']);
}
#[Test]
public function 완전_사용자_샘플은_프로필_필드가_채워진다(): void
{
(new ApiDocSampleService)->seed();
$user = User::where('email', 'apidoc-sample-user@example.com')->first();
$this->assertNotNull($user);
$this->assertNotNull($user->nickname);
$this->assertNotNull($user->mobile);
$this->assertSame('KR', $user->country);
$this->assertSame('ko', $user->language);
$this->assertNotNull($user->bio);
$this->assertGreaterThan(0, $user->roles()->count());
}
#[Test]
public function 재실행_시_샘플이_중복_생성되지_않는다(): void
{
$service = new ApiDocSampleService;
$service->seed();
$countAfterFirst = User::where('email', 'apidoc-sample-user@example.com')->count();
$service->seed();
$countAfterSecond = User::where('email', 'apidoc-sample-user@example.com')->count();
$this->assertSame(1, $countAfterFirst);
$this->assertSame(1, $countAfterSecond);
}
#[Test]
public function 샘플_언어팩은_활성_코어_로케일_목록을_넓히지_않는다(): void
{
// 활성(active) 상태의 코어(core) 언어팩은 그 locale 이 전역 지원 로케일로 승격된다.
// 문서용 샘플이 이 경로를 타면 시스템 전체의 번역 가능 로케일이 바뀌고,
// 그 상태에서 시드된 다국어 데이터에 존재하지 않는 로케일 키가 박힌다.
$before = app(LanguagePackRegistry::class)->getActiveCoreLocales();
(new ApiDocSampleService)->seed();
// 레지스트리는 요청 스코프 캐시를 들고 있으므로 새 인스턴스로 재조회
$after = (new LanguagePackRegistry(app(LanguagePackRepositoryInterface::class)))
->getActiveCoreLocales();
sort($before);
sort($after);
$this->assertSame($before, $after, '샘플 시드가 전역 활성 코어 로케일 목록을 변경했다');
}
#[Test]
public function 샘플_언어팩은_전역_활성_코어_팩으로_생성되지_않는다(): void
{
(new ApiDocSampleService)->seed();
$pack = LanguagePack::where('identifier', 'apidoc-sample-lang')->first();
$this->assertNotNull($pack, '언어팩 도메인의 문서 샘플은 존재해야 한다');
// scope=core + status=active 조합만이 전역 로케일 승격 경로다.
$this->assertFalse(
$pack->scope === 'core' && $pack->status === 'active',
'문서 샘플이 전역 활성 코어 언어팩으로 생성되었다 — 시스템 지원 로케일이 오염된다'
);
}
}