Features: - Implement two fee types: entrance fee and annual fee (both NT$1,000) - Add 50% discount for disability certificate holders - Add disability certificate upload in member profile - Integrate disability verification into cashier approval workflow - Add membership fee settings in system admin Document permissions: - Fix hard-coded role logic in Document model - Use permission-based authorization instead of role checks Additional features: - Add announcements, general ledger, and trial balance modules - Add income management and accounting entries - Add comprehensive test suite with factories - Update UI translations to Traditional Chinese 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
243 lines
7.2 KiB
PHP
243 lines
7.2 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);
|
|
}
|
|
}
|