Files
usher-manage-stack/tests/Feature/Document/DocumentTest.php

283 lines
8.6 KiB
PHP

<?php
namespace Tests\Feature\Document;
use App\Http\Middleware\VerifyCsrfToken;
use App\Models\Document;
use App\Models\DocumentCategory;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
use Tests\Traits\SeedsRolesAndPermissions;
/**
* Document Tests
*
* Tests document management functionality.
*/
class DocumentTest extends TestCase
{
use RefreshDatabase, SeedsRolesAndPermissions;
protected User $admin;
protected function setUp(): void
{
parent::setUp();
Storage::fake('private');
$this->seedRolesAndPermissions();
$this->admin = $this->createAdmin();
}
/**
* Test can view documents list
*/
public function test_can_view_documents_list(): void
{
$response = $this->actingAs($this->admin)->get(
route('admin.documents.index')
);
$response->assertStatus(200);
}
/**
* Test can upload document
*/
public function test_can_upload_document(): void
{
$category = DocumentCategory::factory()->create();
$file = UploadedFile::fake()->create('test.pdf', 1024);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->actingAs($this->admin)
->post(route('admin.documents.store'), [
'title' => '測試文件',
'description' => '這是測試文件',
'document_category_id' => $category->id,
'access_level' => 'admin',
'file' => $file,
]);
$response->assertRedirect();
$this->assertDatabaseHas('documents', ['title' => '測試文件']);
}
/**
* Test can view document details
*/
public function test_can_view_document_details(): void
{
$category = DocumentCategory::factory()->create();
$document = Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category->id,
]);
$response = $this->actingAs($this->admin)->get(
route('admin.documents.show', $document)
);
$response->assertStatus(200);
}
/**
* Test can update document
*/
public function test_can_update_document(): void
{
$category = DocumentCategory::factory()->create();
$document = Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category->id,
'title' => '原始標題',
'access_level' => 'admin',
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->actingAs($this->admin)
->patch(route('admin.documents.update', $document), [
'title' => '更新後標題',
'document_category_id' => $category->id,
'access_level' => 'admin',
]);
$document->refresh();
$this->assertEquals('更新後標題', $document->title);
}
/**
* Test can delete document
*/
public function test_can_delete_document(): void
{
$category = DocumentCategory::factory()->create();
$document = Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category->id,
]);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->actingAs($this->admin)
->delete(route('admin.documents.destroy', $document));
$response->assertRedirect();
$this->assertSoftDeleted('documents', ['id' => $document->id]);
}
/**
* Test document requires title
*/
public function test_document_requires_title(): void
{
$category = DocumentCategory::factory()->create();
$file = UploadedFile::fake()->create('test.pdf', 1024);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->actingAs($this->admin)
->post(route('admin.documents.store'), [
'description' => '這是測試文件',
'document_category_id' => $category->id,
'access_level' => 'admin',
'file' => $file,
]);
$response->assertSessionHasErrors('title');
}
/**
* Test document requires category
*/
public function test_document_requires_category(): void
{
$file = UploadedFile::fake()->create('test.pdf', 1024);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->actingAs($this->admin)
->post(route('admin.documents.store'), [
'title' => '測試文件',
'description' => '這是測試文件',
'access_level' => 'admin',
'file' => $file,
]);
$response->assertSessionHasErrors('document_category_id');
}
/**
* Test document category filter
*/
public function test_document_category_filter(): void
{
$category1 = DocumentCategory::factory()->create(['name' => '會議紀錄']);
$category2 = DocumentCategory::factory()->create(['name' => '財務報表']);
Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category1->id,
'title' => '文件A',
]);
Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category2->id,
'title' => '文件B',
]);
$response = $this->actingAs($this->admin)->get(
route('admin.documents.index', ['category' => $category1->id])
);
$response->assertStatus(200);
$response->assertSee('文件A');
}
/**
* Test document search
*/
public function test_document_search(): void
{
$category = DocumentCategory::factory()->create();
Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category->id,
'title' => '重要會議紀錄',
]);
$response = $this->actingAs($this->admin)->get(
route('admin.documents.index', ['search' => '重要會議'])
);
$response->assertStatus(200);
$response->assertSee('重要會議紀錄');
}
/**
* Test document version upload
*/
public function test_document_version_upload(): void
{
$category = DocumentCategory::factory()->create();
$document = Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category->id,
'version_count' => 1,
]);
// Upload new version
$file = UploadedFile::fake()->create('test_v2.pdf', 1024);
$response = $this->withoutMiddleware(VerifyCsrfToken::class)
->actingAs($this->admin)
->post(route('admin.documents.upload-version', $document), [
'file' => $file,
'version_notes' => '更新版本說明',
]);
$document->refresh();
$this->assertEquals(2, $document->version_count);
}
/**
* Test public download returns UTF-8 compatible content disposition
*/
public function test_public_document_download_uses_utf8_content_disposition(): void
{
$category = DocumentCategory::factory()->create();
$document = Document::factory()->create([
'created_by_user_id' => $this->admin->id,
'document_category_id' => $category->id,
'access_level' => 'public',
'status' => 'active',
'version_count' => 0,
]);
$filePath = 'documents/charter-v2.pdf';
Storage::disk('private')->put($filePath, 'pdf-content');
Storage::put($filePath, 'pdf-content');
$document->addVersion(
filePath: $filePath,
originalFilename: '台灣尤塞氏症暨視聽弱協會章程V2.pdf',
mimeType: 'application/pdf',
fileSize: Storage::disk('private')->size($filePath),
uploadedBy: $this->admin,
versionNotes: '初始版本'
);
$response = $this->get(route('documents.public.download', [
'uuid' => $document->public_uuid,
]));
$response->assertOk();
$disposition = (string) $response->headers->get('Content-Disposition');
$this->assertStringContainsString(
"filename*=UTF-8''".rawurlencode('台灣尤塞氏症暨視聽弱協會章程V2.pdf'),
$disposition
);
}
}