seed(\Database\Seeders\RolesAndPermissionsSeeder::class); $this->seed(\Database\Seeders\PermissionCatalogSeeder::class); } private function createTestData(): array { $user = User::factory()->create(); $user->assignRole('Supervisor'); $project = Project::create([ 'reference' => 'INS', 'name' => 'Proyecto Insp', 'address' => 'x', 'lat' => 40, 'lng' => -3, 'start_date' => now()->toDateString(), 'end_date_estimated' => now()->addMonth()->toDateString(), 'status' => 'in_progress', 'created_by' => $user->id, ]); $project->users()->attach($user->id, ['role_in_project' => 'supervisor']); $phase = Phase::create(['project_id' => $project->id, 'name' => 'F1', 'order' => 1, 'color' => '#000', 'progress_percent' => 0]); $layer = Layer::create(['project_id' => $project->id, 'phase_id' => $phase->id, 'name' => 'L', 'color' => '#111', 'uploaded_by' => $user->id]); $feature = Feature::create([ 'layer_id' => $layer->id, 'name' => 'Pilar', 'geometry' => ['type' => 'Point', 'coordinates' => [-3, 40]], 'progress' => 0, 'status' => 'planned', ]); $template = InspectionTemplate::create([ 'project_id' => $project->id, 'name' => 'Recepción', 'fields' => [ ['group' => 'Geometría', 'name' => 'altura', 'label' => 'Altura', 'question' => '¿Cota OK?', 'type' => 'text', 'required' => false, 'help' => 'Medir'], ], ]); $project->inspectionTemplates()->attach($template->id); return [$user, $project, $feature, $template]; } public function test_register_inspection_with_comments_and_photo(): void { [$user, $project, $feature, $template] = $this->createTestData(); Livewire::actingAs($user) ->test(ProjectMap::class, ['project' => $project]) ->call('selectFeature', $feature->id) ->set('selectedTemplateId', $template->id) ->set('inspectionFormData.altura', '5.2') ->set('inspectionNotes', 'Todo conforme') ->set('inspectionPhotos', [UploadedFile::fake()->image('foto.jpg')]) ->call('saveInspection'); $ins = Inspection::where('feature_id', $feature->id)->first(); $this->assertNotNull($ins); $this->assertEquals('Todo conforme', $ins->notes); $this->assertEquals('5.2', $ins->data['altura']); $this->assertCount(1, $ins->media); } public function test_edit_inspection_updates_data_and_photos(): void { [$user, $project, $feature, $template] = $this->createTestData(); // Create initial inspection $inspection = Inspection::create([ 'project_id' => $project->id, 'layer_id' => $feature->layer_id, 'feature_id' => $feature->id, 'template_id' => $template->id, 'user_id' => $user->id, 'inspector_user_id' => $user->id, 'status' => 'completed', 'completed_at' => now(), 'result' => 'pass', 'notes' => 'Original note', 'data' => ['altura' => '5.0'], ]); $photo1 = Media::create([ 'mediable_type' => Inspection::class, 'mediable_id' => $inspection->id, 'name' => 'original.jpg', 'file_path' => 'uploads/inspections/' . $inspection->id . '/original.jpg', 'file_type' => 'image/jpeg', 'file_extension' => 'jpg', 'file_size' => 1000, 'category' => 'image', 'uploaded_by' => $user->id, ]); Livewire::actingAs($user) ->test(ProjectMap::class, ['project' => $project]) ->call('selectFeature', $feature->id) ->call('editInspection', $inspection->id) ->assertSet('editingInspection.id', $inspection->id) ->assertSet('editInspectionFormData.altura', '5.0') ->assertSet('editInspectionResult', 'pass') ->assertSet('editInspectionNotes', 'Original note') ->set('editInspectionFormData.altura', '5.5') ->set('editInspectionResult', 'fail') ->set('editInspectionNotes', 'Updated note') ->set('editInspectionPhotos', [UploadedFile::fake()->image('new.jpg')]) ->call('saveEditInspection'); $ins = $inspection->fresh(); $this->assertEquals('5.5', $ins->data['altura']); $this->assertEquals('fail', $ins->result); $this->assertEquals('Updated note', $ins->notes); $this->assertCount(2, $ins->media); // original + new } public function test_edit_inspection_delete_existing_photo(): void { [$user, $project, $feature, $template] = $this->createTestData(); $inspection = Inspection::create([ 'project_id' => $project->id, 'layer_id' => $feature->layer_id, 'feature_id' => $feature->id, 'template_id' => $template->id, 'user_id' => $user->id, 'inspector_user_id' => $user->id, 'status' => 'completed', 'completed_at' => now(), 'result' => 'pass', 'notes' => 'Note', 'data' => ['altura' => '5.0'], ]); $photo1 = Media::create([ 'mediable_type' => Inspection::class, 'mediable_id' => $inspection->id, 'name' => 'to_delete.jpg', 'file_path' => 'uploads/inspections/' . $inspection->id . '/to_delete.jpg', 'file_type' => 'image/jpeg', 'file_extension' => 'jpg', 'file_size' => 1000, 'category' => 'image', 'uploaded_by' => $user->id, ]); $photo2 = Media::create([ 'mediable_type' => Inspection::class, 'mediable_id' => $inspection->id, 'name' => 'keep.jpg', 'file_path' => 'uploads/inspections/' . $inspection->id . '/keep.jpg', 'file_type' => 'image/jpeg', 'file_extension' => 'jpg', 'file_size' => 1000, 'category' => 'image', 'uploaded_by' => $user->id, ]); Livewire::actingAs($user) ->test(ProjectMap::class, ['project' => $project]) ->call('selectFeature', $feature->id) ->call('editInspection', $inspection->id) ->call('deleteEditPhoto', 0) // delete first photo (to_delete.jpg) ->call('saveEditInspection'); $this->assertCount(1, $inspection->fresh()->media); $this->assertEquals('keep.jpg', $inspection->fresh()->media->first()->name); $this->assertDatabaseMissing('media', ['id' => $photo1->id]); } public function test_edit_inspection_forbidden_without_permission(): void { [$user, $project, $feature, $template] = $this->createTestData(); $user->syncRoles([]); $user->givePermissionTo(['view projects', 'view inspections']); // only view $inspection = Inspection::create([ 'project_id' => $project->id, 'layer_id' => $feature->layer_id, 'feature_id' => $feature->id, 'template_id' => $template->id, 'user_id' => $user->id, 'inspector_user_id' => $user->id, 'status' => 'completed', 'completed_at' => now(), 'result' => 'pass', 'notes' => 'Note', 'data' => ['altura' => '5.0'], ]); // Modal opens but save is blocked Livewire::actingAs($user) ->test(ProjectMap::class, ['project' => $project]) ->call('selectFeature', $feature->id) ->call('editInspection', $inspection->id) ->set('editInspectionNotes', 'Intento editar') ->call('saveEditInspection') ->assertDispatched('notify', 'Sin permisos para editar inspecciones.'); // Data should not have changed $this->assertEquals('Note', $inspection->fresh()->notes); } public function test_create_inspection_forbidden_without_permission(): void { [$user, $project, $feature, $template] = $this->createTestData(); $user->syncRoles([]); $user->givePermissionTo(['view projects', 'view inspections']); Livewire::actingAs($user) ->test(ProjectMap::class, ['project' => $project]) ->call('selectFeature', $feature->id) ->set('selectedTemplateId', $template->id) ->set('inspectionFormData.altura', '5.2') ->set('inspectionPhotos', [UploadedFile::fake()->image('foto.jpg')]) ->call('saveInspection') ->assertDispatched('notify', 'Sin permisos para crear inspecciones.'); $this->assertDatabaseMissing('inspections', ['feature_id' => $feature->id]); } public function test_delete_inspection_removes_inspection_and_media(): void { [$user, $project, $feature, $template] = $this->createTestData(); $inspection = Inspection::create([ 'project_id' => $project->id, 'layer_id' => $feature->layer_id, 'feature_id' => $feature->id, 'template_id' => $template->id, 'user_id' => $user->id, 'inspector_user_id' => $user->id, 'status' => 'completed', 'completed_at' => now(), 'result' => 'pass', 'notes' => 'Note', 'data' => ['altura' => '5.0'], ]); $photo = Media::create([ 'mediable_type' => Inspection::class, 'mediable_id' => $inspection->id, 'name' => 'test.jpg', 'file_path' => 'uploads/inspections/' . $inspection->id . '/test.jpg', 'file_type' => 'image/jpeg', 'file_extension' => 'jpg', 'file_size' => 1000, 'category' => 'image', 'uploaded_by' => $user->id, ]); // Test direct model delete first $inspection->delete(); $this->assertSoftDeleted('inspections', ['id' => $inspection->id]); $this->assertDatabaseMissing('media', ['id' => $photo->id]); // Restore for the actual test $inspection->restore(); $this->assertDatabaseHas('inspections', ['id' => $inspection->id, 'deleted_at' => null]); // Now test through Livewire component $inspection2 = Inspection::create([ 'project_id' => $project->id, 'layer_id' => $feature->layer_id, 'feature_id' => $feature->id, 'template_id' => $template->id, 'user_id' => $user->id, 'inspector_user_id' => $user->id, 'status' => 'completed', 'completed_at' => now(), 'result' => 'pass', 'notes' => 'Note', 'data' => ['altura' => '5.0'], ]); $photo2 = Media::create([ 'mediable_type' => Inspection::class, 'mediable_id' => $inspection2->id, 'name' => 'test2.jpg', 'file_path' => 'uploads/inspections/' . $inspection2->id . '/test2.jpg', 'file_type' => 'image/jpeg', 'file_extension' => 'jpg', 'file_size' => 1000, 'category' => 'image', 'uploaded_by' => $user->id, ]); $component = Livewire::actingAs($user) ->test(ProjectMap::class, ['project' => $project]) ->call('selectFeature', $feature->id); // Debug: check if component is instantiated $component->assertSet('project.id', $project->id); $component->assertSet('selectedFeature.id', $feature->id); // Call deleteInspection and capture events $component->call('deleteInspection', $inspection2->id); // Check if notify was dispatched $component->assertDispatched('notify', 'Inspección eliminada correctamente'); $this->assertSoftDeleted('inspections', ['id' => $inspection2->id]); $this->assertDatabaseMissing('media', ['id' => $photo2->id]); } public function test_delete_inspection_forbidden_without_permission(): void { [$user, $project, $feature, $template] = $this->createTestData(); $user->syncRoles([]); $user->givePermissionTo(['view projects', 'view inspections']); $inspection = Inspection::create([ 'project_id' => $project->id, 'layer_id' => $feature->layer_id, 'feature_id' => $feature->id, 'template_id' => $template->id, 'user_id' => $user->id, 'inspector_user_id' => $user->id, 'status' => 'completed', 'completed_at' => now(), 'result' => 'pass', 'notes' => 'Note', 'data' => ['altura' => '5.0'], ]); Livewire::actingAs($user) ->test(ProjectMap::class, ['project' => $project]) ->call('selectFeature', $feature->id) ->call('deleteInspection', $inspection->id) ->assertDispatched('notify', 'Sin permisos para eliminar inspecciones.'); $this->assertDatabaseHas('inspections', ['id' => $inspection->id, 'deleted_at' => null]); } }