Files
Gnuboard7/modules/_bundled/sirsoft-page/tests/Unit/Services/PageAttachmentServiceTest.php
T
chym1217 8cf55ad88f fix(page): 버전 이력 변경내역을 다국어 라벨로 표시 + E2E 인프라 신설
- 페이지 상세 버전 이력의 "변경내역"이 title·content 등 영문 필드명으로
 노출되던 문제를 field_labels 다국어 매핑으로 정정 (ko/en/ja)
- sirsoft-page 모듈에 Playwright E2E 인프라를 이커머스와 동일 패턴으로 신설
 (config·fixture·seed stub + spec 3건, data-testid 보강 전까지 skip placeholder)
- 출시된 1.0.0 이후 변경이므로 module 1.0.1 bump (3곳+lock 동기화),
 ja 언어팩 1.0.1 bump
2026-07-06 09:37:04 +09:00

297 lines
11 KiB
PHP

<?php
namespace Modules\Sirsoft\Page\Tests\Unit\Services;
use App\Contracts\Extension\StorageInterface;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Mockery;
use Modules\Sirsoft\Page\Models\Page;
use Modules\Sirsoft\Page\Models\PageAttachment;
use Modules\Sirsoft\Page\Services\PageAttachmentService;
use Modules\Sirsoft\Page\Tests\ModuleTestCase;
/**
* PageAttachmentService 단위 테스트
*
* 첨부파일 업로드/삭제/순서변경/연결 비즈니스 로직을 검증합니다.
*/
class PageAttachmentServiceTest extends ModuleTestCase
{
private PageAttachmentService $service;
private User $adminUser;
protected function setUp(): void
{
parent::setUp();
$this->adminUser = $this->createAdminUser([]);
$this->actingAs($this->adminUser);
// StorageInterface 모킹
$storageMock = Mockery::mock(StorageInterface::class);
$storageMock->shouldReceive('put')->andReturn(true);
$storageMock->shouldReceive('get')->andReturn('file content');
$storageMock->shouldReceive('exists')->andReturn(true);
$storageMock->shouldReceive('delete')->andReturn(true);
$storageMock->shouldReceive('deleteDirectory')->andReturn(true);
$storageMock->shouldReceive('getDisk')->andReturn('local');
$storageMock->shouldReceive('url')->andReturn(null);
$storageMock->shouldReceive('response')->andReturn(null);
$this->app->instance(StorageInterface::class, $storageMock);
$this->service = app(PageAttachmentService::class);
}
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
// ─── upload ────────────────────────────────────────
/**
* 파일을 페이지에 업로드할 수 있는지 확인
*/
public function test_upload_creates_attachment_for_page(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-attach-page',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
$file = UploadedFile::fake()->create('document.pdf', 500, 'application/pdf');
$attachment = $this->service->upload($file, $page->id);
$this->assertInstanceOf(PageAttachment::class, $attachment);
$this->assertEquals($page->id, $attachment->page_id);
$this->assertEquals('document.pdf', $attachment->original_filename);
$this->assertEquals('application/pdf', $attachment->mime_type);
$this->assertNull($attachment->temp_key);
}
/**
* temp_key로 임시 업로드할 수 있는지 확인
*/
public function test_upload_creates_temp_attachment(): void
{
$file = UploadedFile::fake()->create('temp-file.pdf', 200, 'application/pdf');
$attachment = $this->service->upload($file, null, 'attachments', 'temp-key-123');
$this->assertNull($attachment->page_id);
$this->assertEquals('temp-key-123', $attachment->temp_key);
}
/**
* 업로드 시 order가 자동 증가하는지 확인
*/
public function test_upload_auto_increments_order(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-attach-order',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
$file1 = UploadedFile::fake()->create('first.pdf', 100, 'application/pdf');
$file2 = UploadedFile::fake()->create('second.pdf', 100, 'application/pdf');
$attachment1 = $this->service->upload($file1, $page->id);
$attachment2 = $this->service->upload($file2, $page->id);
$this->assertEquals(1, $attachment1->order);
$this->assertEquals(2, $attachment2->order);
}
/**
* 이미지 업로드 시 메타데이터(width, height)가 저장되는지 확인
*/
public function test_upload_image_stores_dimensions_in_meta(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-attach-img',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
$file = UploadedFile::fake()->image('photo.jpg', 800, 600);
$attachment = $this->service->upload($file, $page->id);
$this->assertNotNull($attachment->meta);
$this->assertArrayHasKey('width', $attachment->meta);
$this->assertArrayHasKey('height', $attachment->meta);
}
// ─── linkTempAttachmentsWithMove ───────────────────
/**
* 임시 첨부파일을 페이지에 연결할 수 있는지 확인
*/
public function test_link_temp_attachments_moves_to_page(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-link-temp',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
// 임시 첨부파일 생성
$file = UploadedFile::fake()->create('temp-doc.pdf', 100, 'application/pdf');
$tempAttachment = $this->service->upload($file, null, 'attachments', 'link-temp-key');
$this->assertNull($tempAttachment->page_id);
// 페이지에 연결
$count = $this->service->linkTempAttachmentsWithMove('link-temp-key', $page->id);
$this->assertEquals(1, $count);
$tempAttachment->refresh();
$this->assertEquals($page->id, $tempAttachment->page_id);
$this->assertNull($tempAttachment->temp_key);
}
/**
* 연결 시 업로드(조회) 순서대로 order가 1..N 재부여되는지 확인
*
* 이커머스 ProductImageService::linkTempImages 와 동일하게, getByTempKey 가
* order 순으로 반환한 순서대로 order 를 1,2,3 으로 재배치한다. (생성 모드의
* 드래그 재정렬은 미지원 — 업로드 순서가 SSoT, 재정렬은 수정 모드 reorder API)
*/
public function test_link_reassigns_order_by_upload_sequence(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-link-order',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
// 임시 첨부 3개 업로드 (order 는 업로드 시점에 1,2,3 순차 부여됨)
$a = $this->service->upload(UploadedFile::fake()->create('a.pdf', 100, 'application/pdf'), null, 'attachments', 'order-key');
$b = $this->service->upload(UploadedFile::fake()->create('b.pdf', 100, 'application/pdf'), null, 'attachments', 'order-key');
$c = $this->service->upload(UploadedFile::fake()->create('c.pdf', 100, 'application/pdf'), null, 'attachments', 'order-key');
$this->service->linkTempAttachmentsWithMove('order-key', $page->id);
// 연결 후 업로드(조회) 순서대로 order 1,2,3 재부여
$this->assertEquals(1, $a->fresh()->order);
$this->assertEquals(2, $b->fresh()->order);
$this->assertEquals(3, $c->fresh()->order);
}
// ─── deleteAttachment ──────────────────────────────
/**
* 첨부파일을 삭제할 수 있는지 확인
*/
public function test_delete_attachment_hard_deletes(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-del-attach',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
$file = UploadedFile::fake()->create('delete-me.pdf', 100, 'application/pdf');
$attachment = $this->service->upload($file, $page->id);
$result = $this->service->deleteAttachment($attachment);
$this->assertTrue($result);
$this->assertDatabaseMissing('page_attachments', ['id' => $attachment->id]);
}
// ─── reorder ───────────────────────────────────────
/**
* 첨부파일 순서를 변경할 수 있는지 확인
*/
public function test_reorder_changes_attachment_orders(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-reorder',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
$file1 = UploadedFile::fake()->create('a.pdf', 100, 'application/pdf');
$file2 = UploadedFile::fake()->create('b.pdf', 100, 'application/pdf');
$att1 = $this->service->upload($file1, $page->id);
$att2 = $this->service->upload($file2, $page->id);
// 순서 역전
$this->service->reorder([
$att1->id => 2,
$att2->id => 1,
]);
$att1->refresh();
$att2->refresh();
$this->assertEquals(2, $att1->order);
$this->assertEquals(1, $att2->order);
}
// ─── getByHash ─────────────────────────────────────
/**
* 해시로 첨부파일을 조회할 수 있는지 확인
*/
public function test_get_by_hash_returns_attachment(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-hash',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
$file = UploadedFile::fake()->create('hash-test.pdf', 100, 'application/pdf');
$attachment = $this->service->upload($file, $page->id);
$found = $this->service->getByHash($attachment->hash);
$this->assertNotNull($found);
$this->assertEquals($attachment->id, $found->id);
}
/**
* 존재하지 않는 해시로 조회 시 null을 반환하는지 확인
*/
public function test_get_by_hash_returns_null_for_nonexistent(): void
{
$found = $this->service->getByHash('nonexistent1');
$this->assertNull($found);
}
// ─── getByPageId ───────────────────────────────────
/**
* 페이지의 첨부파일 목록을 조회할 수 있는지 확인
*/
public function test_get_by_page_id_returns_attachments(): void
{
$page = Page::factory()->create([
'slug' => 'test-svc-by-page',
'created_by' => $this->adminUser->id,
'updated_by' => $this->adminUser->id,
]);
$file1 = UploadedFile::fake()->create('one.pdf', 100, 'application/pdf');
$file2 = UploadedFile::fake()->create('two.pdf', 100, 'application/pdf');
$this->service->upload($file1, $page->id);
$this->service->upload($file2, $page->id);
$attachments = $this->service->getByPageId($page->id);
$this->assertCount(2, $attachments);
}
}