Pet::factory()->create()->id, 'status' => DocumentStatusEnum::Registered->name, 'priority' => DocumentPriorityEnum::High->name, 'modality' => 'mri', ], $overrides); } public function test_guest_is_redirected(): void { $this->get(route('admin.documents.index'))->assertRedirect(route('login')); } public function test_admin_without_permission_is_forbidden(): void { $admin = $this->adminWithoutPermissions(); $document = Document::factory()->create(); $this->actingAs($admin)->get(route('admin.documents.index'))->assertForbidden(); $this->actingAs($admin)->get(route('admin.documents.create'))->assertForbidden(); $this->actingAs($admin)->post(route('admin.documents.store'), $this->payload())->assertForbidden(); $this->actingAs($admin)->get(route('admin.documents.edit', $document))->assertForbidden(); $this->actingAs($admin)->put(route('admin.documents.update', $document), $this->payload())->assertForbidden(); $this->actingAs($admin)->delete(route('admin.documents.destroy', $document))->assertForbidden(); $this->actingAs($admin)->post('/admin/documents-upload')->assertForbidden(); $this->actingAs($admin)->get('/admin/documents-options')->assertForbidden(); } public function test_index_renders_with_filters(): void { $admin = $this->adminWithAllPermissions(); $pet = Pet::factory()->create(); Document::factory()->registered()->high()->create(['code' => '111111', 'pet_id' => $pet->id]); Document::factory()->completed()->medium()->create(['code' => '222222']); $this->actingAs($admin)->get(route('admin.documents.index'))->assertOk()->assertInertia(fn (Assert $page) => $page->component('Documents/index')->has('documents.data', 2)); $this->actingAs($admin)->get(route('admin.documents.index', ['status' => DocumentStatusEnum::Completed->name]))->assertInertia(fn (Assert $page) => $page->has('documents.data', 1)); $this->actingAs($admin)->get(route('admin.documents.index', ['priority' => DocumentPriorityEnum::High->name]))->assertInertia(fn (Assert $page) => $page->has('documents.data', 1)); $this->actingAs($admin)->get(route('admin.documents.index', ['pet' => $pet->id]))->assertInertia(fn (Assert $page) => $page->has('documents.data', 1)); $this->actingAs($admin)->get(route('admin.documents.index', ['search' => '2222']))->assertInertia(fn (Assert $page) => $page->has('documents.data', 1)); } public function test_create_and_edit_pages_render(): void { $admin = $this->adminWithAllPermissions(); $document = Document::factory()->create(); $this->actingAs($admin)->get(route('admin.documents.create'))->assertInertia(fn (Assert $page) => $page->component('Documents/create_and_edit')->has('pets')); $this->actingAs($admin)->get(route('admin.documents.edit', $document))->assertInertia(fn (Assert $page) => $page->component('Documents/create_and_edit')->where('is_edit', true)->where('document.id', $document->id)); } public function test_store_creates_document_with_files_attached_by_collection(): void { $admin = $this->adminWithAllPermissions(); $primary = Medium::factory()->create(); $history = Medium::factory()->create(); $this->actingAs($admin)->post(route('admin.documents.store'), $this->payload([ 'primary_files' => [$primary->id], 'history_files' => [$history->id], ]))->assertOk()->assertSessionHas('success'); $document = Document::first(); $this->assertSame(DocumentStatusEnum::Registered, $document->status); $this->assertSame(DocumentPriorityEnum::High, $document->priority); $this->assertSame($admin->id, $document->requester_id); $this->assertSame([$primary->id], $document->primaryFiles->pluck('id')->all()); $this->assertSame([$history->id], $document->historyFiles->pluck('id')->all()); } public function test_store_validates_pet(): void { $this->actingAs($this->adminWithAllPermissions())->postJson(route('admin.documents.store'), ['pet_id' => 999])->assertUnprocessable()->assertJsonValidationErrors('pet_id'); } public function test_update_replaces_file_collections(): void { $admin = $this->adminWithAllPermissions(); $document = Document::factory()->create(); $old = Medium::factory()->create(); $new = Medium::factory()->create(); $document->media()->attach($old->id, ['collection' => 'primary']); $this->actingAs($admin)->put(route('admin.documents.update', $document), $this->payload([ 'status' => DocumentStatusEnum::InProgress->name, 'primary_files' => [$new->id], ]))->assertOk(); $document->refresh(); $this->assertSame(DocumentStatusEnum::InProgress, $document->status); $this->assertSame([$new->id], $document->primaryFiles->pluck('id')->all()); } public function test_destroy_deletes_document(): void { $document = Document::factory()->create(); $this->actingAs($this->adminWithAllPermissions())->delete(route('admin.documents.destroy', $document))->assertOk(); $this->assertDatabaseMissing('documents', ['id' => $document->id]); } public function test_upload_file_stores_private_medium(): void { Storage::fake('private'); $this->actingAs($this->adminWithAllPermissions())->postJson('/admin/documents-upload', ['file' => UploadedFile::fake()->create('scan.pdf', 10, 'application/pdf')]) ->assertOk() ->assertJsonPath('disk', MediaDiskEnum::Private->value); $medium = Medium::first(); $this->assertStringStartsWith('documents/', $medium->path); Storage::disk('private')->assertExists($medium->path); } public function test_upload_file_validates_presence(): void { $this->actingAs($this->adminWithAllPermissions())->postJson('/admin/documents-upload', [])->assertUnprocessable()->assertJsonValidationErrors('file'); } public function test_get_options_returns_matching_documents(): void { $document = Document::factory()->create(['code' => '123456', 'modality' => 'mri']); Document::factory()->create(['code' => '999999']); $this->actingAs($this->adminWithAllPermissions())->getJson('/admin/documents-options?search=1234') ->assertOk() ->assertJsonCount(1, 'data') ->assertJsonPath('data.0.value', $document->id) ->assertJsonPath('data.0.label', 'پرونده 123456 - mri'); } public function test_export_data_downloads_excel(): void { Excel::fake(); $this->actingAs($this->adminWithAllPermissions())->get('/admin/documents-export-data')->assertOk(); Excel::assertDownloaded('documents.xlsx'); } }