Files
Gnuboard7/tests/Unit/Repositories/LayoutExtensionVersionRepositoryTest.php
T
2026-07-01 10:30:32 +09:00

216 lines
7.8 KiB
PHP

<?php
namespace Tests\Unit\Repositories;
use App\Models\LayoutExtension;
use App\Models\Template;
use App\Models\TemplateLayoutExtensionVersion;
use App\Repositories\LayoutExtensionVersionRepository;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
/**
* 레이아웃 확장 버전 리포지토리 테스트
*/
class LayoutExtensionVersionRepositoryTest extends TestCase
{
use RefreshDatabase;
/**
* 같은 스위트의 레이아웃/GDPR 미들웨어 의존 테스트와 migrate:fresh 정합성을
* 맞추기 위해 GDPR 플러그인 마이그레이션을 일관 선언한다.
*
* @var array<string>
*/
protected array $requiredExtensions = [
'plugins/sirsoft-gdpr',
];
private LayoutExtensionVersionRepository $repository;
private Template $template;
private LayoutExtension $extension;
protected function setUp(): void
{
parent::setUp();
$this->repository = new LayoutExtensionVersionRepository(new TemplateLayoutExtensionVersion);
$this->template = Template::factory()->create();
$this->extension = LayoutExtension::factory()->create(['template_id' => $this->template->id]);
}
/**
* saveVersion - 첫 번째 버전 생성
*/
public function test_save_version_creates_first_version(): void
{
$content = ['extension_point' => 'header', 'components' => []];
$version = $this->repository->saveVersion($this->extension->id, $content);
$this->assertInstanceOf(TemplateLayoutExtensionVersion::class, $version);
$this->assertEquals(1, $version->version);
$this->assertEquals($this->extension->id, $version->extension_id);
$this->assertEquals($content, $version->content);
}
/**
* saveVersion - 버전 자동 증가
*/
public function test_save_version_auto_increments(): void
{
TemplateLayoutExtensionVersion::factory()->create(['extension_id' => $this->extension->id, 'version' => 1]);
TemplateLayoutExtensionVersion::factory()->create(['extension_id' => $this->extension->id, 'version' => 2]);
$newVersion = $this->repository->saveVersion($this->extension->id, ['test' => 'data']);
$this->assertEquals(3, $newVersion->version);
}
/**
* getVersions - 최신순 정렬
*/
public function test_get_versions_returns_latest_first(): void
{
foreach ([1, 3, 2] as $v) {
TemplateLayoutExtensionVersion::factory()->create(['extension_id' => $this->extension->id, 'version' => $v]);
}
$versions = $this->repository->getVersions($this->extension->id);
$this->assertCount(3, $versions);
$this->assertEquals(3, $versions->first()->version);
$this->assertEquals(1, $versions->last()->version);
}
/**
* getNextVersion - 버전 없을 때 1 반환
*/
public function test_get_next_version_returns_one_when_empty(): void
{
$this->assertEquals(1, $this->repository->getNextVersion($this->extension->id));
}
/**
* getNextVersion - max + 1
*/
public function test_get_next_version_returns_max_plus_one(): void
{
foreach ([1, 5, 3] as $v) {
TemplateLayoutExtensionVersion::factory()->create(['extension_id' => $this->extension->id, 'version' => $v]);
}
$this->assertEquals(6, $this->repository->getNextVersion($this->extension->id));
}
/**
* 버전은 확장별로 격리됨
*/
public function test_versions_are_isolated_by_extension(): void
{
$otherExtension = LayoutExtension::factory()->create(['template_id' => $this->template->id]);
TemplateLayoutExtensionVersion::factory()->create(['extension_id' => $otherExtension->id, 'version' => 10]);
$this->assertEquals(1, $this->repository->getNextVersion($this->extension->id));
$this->assertCount(0, $this->repository->getVersions($this->extension->id));
}
/**
* calculateChanges - trait 동작 (라인 단위 카운트)
*
* changes_summary 는 버전 비교 diff 뷰와 동일한 라인 단위로 센다. 키 정렬 직렬화
* 후 라인 LCS 로 추가/삭제 라인 수를 집계한다(added/removed 는 정수 카운트, modified
* 키는 없음 — 값 변경은 삭제+추가 라인으로 표현).
*/
public function test_calculate_changes_detects_diff(): void
{
// name 값 변경(삭제+추가), deprecated 삭제(1줄), added 키 추가(1줄)
$old = ['name' => 'test', 'deprecated' => 'old'];
$new = ['name' => 'changed', 'added' => 'new'];
$changes = $this->repository->calculateChanges($old, $new);
// added 라인: "added": "new", + "name": "changed", = 2줄
$this->assertSame(2, $changes['added']);
// removed 라인: "deprecated": "old", + "name": "test", = 2줄
$this->assertSame(2, $changes['removed']);
$this->assertArrayNotHasKey('modified', $changes, 'modified 키는 두지 않는다');
}
/**
* restoreVersion - 트랜잭션 내 복원 + 새 버전 생성
*/
public function test_restore_version_restores_content_and_creates_new_version(): void
{
$oldContent = ['extension_point' => 'header', 'components' => [['type' => 'basic', 'name' => 'Span']]];
$this->extension->update(['content' => $oldContent]);
// 복원 대상 버전 (버전 1) — 이전 content 스냅샷
$versionToRestore = TemplateLayoutExtensionVersion::factory()->create([
'extension_id' => $this->extension->id,
'version' => 1,
'content' => $oldContent,
]);
// 현재 content 를 다른 값으로 변경
$this->extension->update(['content' => ['extension_point' => 'footer']]);
$newVersion = $this->repository->restoreVersion($this->extension->id, $versionToRestore->id);
// 확장 content 가 복원됨
$this->extension->refresh();
$this->assertEquals($oldContent, $this->extension->content);
// 새 버전 생성됨 (버전 2)
$this->assertEquals(2, $newVersion->version);
}
/**
* restoreVersion - 존재하지 않는 버전은 예외
*/
public function test_restore_version_throws_when_version_not_found(): void
{
$this->expectException(ModelNotFoundException::class);
$this->repository->restoreVersion($this->extension->id, 99999);
}
/**
* getCurrentVersionsByExtensionIds — 확장별 최신 버전 맵
*/
public function test_get_current_versions_by_extension_ids_returns_latest_version_map(): void
{
$other = LayoutExtension::factory()->create(['template_id' => $this->template->id]);
$noHistory = LayoutExtension::factory()->create(['template_id' => $this->template->id]);
foreach ([1, 2, 3] as $v) {
TemplateLayoutExtensionVersion::factory()->create(['extension_id' => $this->extension->id, 'version' => $v]);
}
TemplateLayoutExtensionVersion::factory()->create(['extension_id' => $other->id, 'version' => 1]);
$map = $this->repository->getCurrentVersionsByExtensionIds([
$this->extension->id,
$other->id,
$noHistory->id,
]);
ksort($map);
$expected = [$this->extension->id => 3, $other->id => 1];
ksort($expected);
$this->assertSame($expected, $map);
$this->assertArrayNotHasKey($noHistory->id, $map);
}
/**
* getCurrentVersionsByExtensionIds — 빈 입력/이력 전무 시 빈 맵
*/
public function test_get_current_versions_by_extension_ids_returns_empty_for_empty_input(): void
{
$this->assertSame([], $this->repository->getCurrentVersionsByExtensionIds([]));
$this->assertSame([], $this->repository->getCurrentVersionsByExtensionIds([$this->extension->id]));
}
}