v7.0.0-beta.1 release
This commit is contained in:
@@ -0,0 +1,369 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Extension;
|
||||
|
||||
use App\Extension\Traits\ResolvesLanguageFragments;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* ResolvesLanguageFragments trait 테스트
|
||||
*
|
||||
* 다국어 파일의 $partial 디렉티브 해석 기능을 테스트합니다.
|
||||
*/
|
||||
class ResolvesLanguageFragmentsTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* trait을 사용하는 테스트용 클래스
|
||||
*/
|
||||
private object $traitUser;
|
||||
|
||||
/**
|
||||
* 테스트용 임시 디렉토리
|
||||
*/
|
||||
private string $tempDir;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// trait을 사용하는 익명 클래스 생성
|
||||
$this->traitUser = new class
|
||||
{
|
||||
use ResolvesLanguageFragments;
|
||||
|
||||
// protected 메서드를 public으로 노출
|
||||
public function callResolveLanguageFragments(array $data, string $basePath, int $depth = 0): array
|
||||
{
|
||||
return $this->resolveLanguageFragments($data, $basePath, $depth);
|
||||
}
|
||||
|
||||
public function callResetFragmentStack(): void
|
||||
{
|
||||
$this->resetFragmentStack();
|
||||
}
|
||||
};
|
||||
|
||||
// 테스트용 임시 디렉토리 생성
|
||||
$this->tempDir = storage_path('app/testing/lang_fragments_' . uniqid());
|
||||
File::makeDirectory($this->tempDir, 0755, true, true);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
// 테스트용 임시 디렉토리 삭제
|
||||
if (File::isDirectory($this->tempDir)) {
|
||||
File::deleteDirectory($this->tempDir);
|
||||
}
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* $partial 디렉티브 없는 데이터는 그대로 반환
|
||||
*/
|
||||
public function test_resolve_data_without_partial(): void
|
||||
{
|
||||
$data = [
|
||||
'common' => [
|
||||
'save' => '저장',
|
||||
'cancel' => '취소',
|
||||
],
|
||||
'title' => '제목',
|
||||
];
|
||||
|
||||
$result = $this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
|
||||
$this->assertEquals($data, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 단일 $partial 디렉티브 해석 테스트
|
||||
*/
|
||||
public function test_resolve_single_partial(): void
|
||||
{
|
||||
// fragment 파일 생성
|
||||
$fragmentContent = [
|
||||
'save' => '저장',
|
||||
'cancel' => '취소',
|
||||
];
|
||||
File::put($this->tempDir . '/common.json', json_encode($fragmentContent, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$data = [
|
||||
'common' => [
|
||||
'$partial' => 'common.json',
|
||||
],
|
||||
'title' => '제목',
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
$result = $this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
|
||||
$expected = [
|
||||
'common' => [
|
||||
'save' => '저장',
|
||||
'cancel' => '취소',
|
||||
],
|
||||
'title' => '제목',
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 중첩 $partial 디렉티브 해석 테스트
|
||||
*/
|
||||
public function test_resolve_nested_partials(): void
|
||||
{
|
||||
// 하위 디렉토리 생성
|
||||
File::makeDirectory($this->tempDir . '/admin', 0755, true, true);
|
||||
|
||||
// 중첩된 fragment 파일 생성
|
||||
$buttonsContent = [
|
||||
'save' => '저장',
|
||||
'cancel' => '취소',
|
||||
];
|
||||
File::put($this->tempDir . '/admin/buttons.json', json_encode($buttonsContent, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$adminContent = [
|
||||
'dashboard' => '대시보드',
|
||||
'buttons' => [
|
||||
'$partial' => 'admin/buttons.json',
|
||||
],
|
||||
];
|
||||
File::put($this->tempDir . '/admin.json', json_encode($adminContent, JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$data = [
|
||||
'admin' => [
|
||||
'$partial' => 'admin.json',
|
||||
],
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
$result = $this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
|
||||
$expected = [
|
||||
'admin' => [
|
||||
'dashboard' => '대시보드',
|
||||
'buttons' => [
|
||||
'save' => '저장',
|
||||
'cancel' => '취소',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 다중 $partial 디렉티브 해석 테스트
|
||||
*/
|
||||
public function test_resolve_multiple_partials(): void
|
||||
{
|
||||
// fragment 파일들 생성
|
||||
File::put($this->tempDir . '/common.json', json_encode([
|
||||
'save' => '저장',
|
||||
'cancel' => '취소',
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
File::put($this->tempDir . '/auth.json', json_encode([
|
||||
'login' => '로그인',
|
||||
'logout' => '로그아웃',
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$data = [
|
||||
'common' => [
|
||||
'$partial' => 'common.json',
|
||||
],
|
||||
'auth' => [
|
||||
'$partial' => 'auth.json',
|
||||
],
|
||||
'title' => '앱 제목',
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
$result = $this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
|
||||
$expected = [
|
||||
'common' => [
|
||||
'save' => '저장',
|
||||
'cancel' => '취소',
|
||||
],
|
||||
'auth' => [
|
||||
'login' => '로그인',
|
||||
'logout' => '로그아웃',
|
||||
],
|
||||
'title' => '앱 제목',
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 순환 참조 감지 테스트
|
||||
*/
|
||||
public function test_detect_circular_reference(): void
|
||||
{
|
||||
// 순환 참조 파일 생성
|
||||
File::put($this->tempDir . '/a.json', json_encode([
|
||||
'nested' => [
|
||||
'$partial' => 'b.json',
|
||||
],
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
File::put($this->tempDir . '/b.json', json_encode([
|
||||
'nested' => [
|
||||
'$partial' => 'a.json',
|
||||
],
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$data = [
|
||||
'section' => [
|
||||
'$partial' => 'a.json',
|
||||
],
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessageMatches('/순환 참조 감지/');
|
||||
|
||||
$this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* 최대 깊이 초과 테스트
|
||||
*/
|
||||
public function test_max_depth_exceeded(): void
|
||||
{
|
||||
// 11단계 중첩 파일 생성 (MAX_DEPTH = 10)
|
||||
for ($i = 1; $i <= 11; $i++) {
|
||||
if ($i < 11) {
|
||||
$content = [
|
||||
'level' => $i,
|
||||
'nested' => [
|
||||
'$partial' => "level{$i}.json",
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$content = ['level' => $i];
|
||||
}
|
||||
|
||||
$fileName = $i === 1 ? 'start.json' : 'level' . ($i - 1) . '.json';
|
||||
File::put($this->tempDir . '/' . $fileName, json_encode($content, JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
$data = [
|
||||
'deep' => [
|
||||
'$partial' => 'start.json',
|
||||
],
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessageMatches('/최대 깊이.*초과/');
|
||||
|
||||
$this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* 존재하지 않는 fragment 파일 오류 테스트
|
||||
*/
|
||||
public function test_fragment_file_not_found(): void
|
||||
{
|
||||
$data = [
|
||||
'missing' => [
|
||||
'$partial' => 'nonexistent.json',
|
||||
],
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessageMatches('/찾을 수 없습니다/');
|
||||
|
||||
$this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* 잘못된 JSON 파일 오류 테스트
|
||||
*/
|
||||
public function test_invalid_json_fragment(): void
|
||||
{
|
||||
// 잘못된 JSON 파일 생성
|
||||
File::put($this->tempDir . '/invalid.json', '{ invalid json }');
|
||||
|
||||
$data = [
|
||||
'section' => [
|
||||
'$partial' => 'invalid.json',
|
||||
],
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
|
||||
$this->expectException(\RuntimeException::class);
|
||||
$this->expectExceptionMessageMatches('/JSON 파싱 오류/');
|
||||
|
||||
$this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* 빈 fragment 파일 처리 테스트
|
||||
*/
|
||||
public function test_empty_fragment(): void
|
||||
{
|
||||
// 빈 객체 JSON 파일 생성
|
||||
File::put($this->tempDir . '/empty.json', '{}');
|
||||
|
||||
$data = [
|
||||
'empty_section' => [
|
||||
'$partial' => 'empty.json',
|
||||
],
|
||||
'title' => '제목',
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
$result = $this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
|
||||
$expected = [
|
||||
'empty_section' => [],
|
||||
'title' => '제목',
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 하위 디렉토리 경로 fragment 테스트
|
||||
*/
|
||||
public function test_fragment_with_subdirectory_path(): void
|
||||
{
|
||||
// 하위 디렉토리 생성
|
||||
File::makeDirectory($this->tempDir . '/admin/products', 0755, true, true);
|
||||
|
||||
// fragment 파일 생성
|
||||
File::put($this->tempDir . '/admin/products/list.json', json_encode([
|
||||
'title' => '상품 목록',
|
||||
'add' => '상품 추가',
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$data = [
|
||||
'products' => [
|
||||
'$partial' => 'admin/products/list.json',
|
||||
],
|
||||
];
|
||||
|
||||
$this->traitUser->callResetFragmentStack();
|
||||
$result = $this->traitUser->callResolveLanguageFragments($data, $this->tempDir);
|
||||
|
||||
$expected = [
|
||||
'products' => [
|
||||
'title' => '상품 목록',
|
||||
'add' => '상품 추가',
|
||||
],
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user