artisan('migrate', ['--path' => 'database/migrations']); // Create procesos_admision table \Illuminate\Support\Facades\Schema::dropIfExists('procesos_admision'); \Illuminate\Support\Facades\Schema::create('procesos_admision', function ($table) { $table->id(); $table->string('titulo'); $table->string('subtitulo')->nullable(); $table->text('descripcion')->nullable(); $table->string('slug', 120)->unique(); $table->string('tipo_proceso', 60)->nullable(); $table->string('modalidad', 50)->nullable(); $table->boolean('publicado')->default(false); $table->datetime('fecha_publicacion')->nullable(); $table->datetime('fecha_inicio_preinscripcion')->nullable(); $table->datetime('fecha_fin_preinscripcion')->nullable(); $table->datetime('fecha_inicio_inscripcion')->nullable(); $table->datetime('fecha_fin_inscripcion')->nullable(); $table->datetime('fecha_examen1')->nullable(); $table->datetime('fecha_examen2')->nullable(); $table->datetime('fecha_resultados')->nullable(); $table->datetime('fecha_inicio_biometrico')->nullable(); $table->datetime('fecha_fin_biometrico')->nullable(); $table->string('imagen_path', 500)->nullable(); $table->string('banner_path', 500)->nullable(); $table->string('brochure_path', 500)->nullable(); $table->string('link_preinscripcion', 500)->nullable(); $table->string('link_inscripcion', 500)->nullable(); $table->string('link_resultados', 500)->nullable(); $table->string('link_reglamento', 500)->nullable(); $table->enum('estado', ['nuevo', 'publicado', 'en_proceso', 'finalizado', 'cancelado'])->default('nuevo'); $table->timestamps(); }); } protected function authenticateUser(): void { $user = User::factory()->create(); Sanctum::actingAs($user); } /** @test */ public function update_sets_nullable_fields_to_null_when_empty_values_provided(): void { $this->authenticateUser(); // Create a process with filled nullable fields $proceso = ProcesoAdmision::create([ 'titulo' => 'Proceso Test', 'slug' => 'proceso-test', 'subtitulo' => 'Subtitulo Original', 'descripcion' => 'Descripcion Original', 'tipo_proceso' => 'ordinario', 'modalidad' => 'presencial', 'fecha_publicacion' => '2026-01-15 10:00:00', 'fecha_inicio_preinscripcion' => '2026-01-20 08:00:00', 'fecha_fin_preinscripcion' => '2026-01-25 18:00:00', 'link_preinscripcion' => 'https://example.com/preinscripcion', 'link_inscripcion' => 'https://example.com/inscripcion', ]); // Verify initial values $this->assertEquals('Subtitulo Original', $proceso->subtitulo); $this->assertEquals('Descripcion Original', $proceso->descripcion); $this->assertEquals('ordinario', $proceso->tipo_proceso); $this->assertNotNull($proceso->fecha_publicacion); $this->assertNotNull($proceso->link_preinscripcion); // Update with empty values for nullable fields $response = $this->patchJson("/api/admin/procesos-admision/{$proceso->id}", [ 'subtitulo' => '', 'descripcion' => null, 'tipo_proceso' => '', 'fecha_publicacion' => null, 'link_preinscripcion' => '', ]); $response->assertStatus(200); // Refresh the model from database $proceso->refresh(); // Assert nullable fields are now null $this->assertNull($proceso->subtitulo); $this->assertNull($proceso->descripcion); $this->assertNull($proceso->tipo_proceso); $this->assertNull($proceso->fecha_publicacion); $this->assertNull($proceso->link_preinscripcion); // Assert other fields remain unchanged $this->assertEquals('Proceso Test', $proceso->titulo); $this->assertEquals('presencial', $proceso->modalidad); $this->assertEquals('https://example.com/inscripcion', $proceso->link_inscripcion); } /** @test */ public function update_sets_date_fields_to_null_when_empty(): void { $this->authenticateUser(); $proceso = ProcesoAdmision::create([ 'titulo' => 'Proceso Con Fechas', 'slug' => 'proceso-con-fechas', 'fecha_inicio_inscripcion' => '2026-02-01 08:00:00', 'fecha_fin_inscripcion' => '2026-02-15 18:00:00', 'fecha_examen1' => '2026-02-20 09:00:00', 'fecha_examen2' => '2026-02-21 09:00:00', 'fecha_resultados' => '2026-03-01 12:00:00', ]); // Update dates to empty/null $response = $this->patchJson("/api/admin/procesos-admision/{$proceso->id}", [ 'fecha_inicio_inscripcion' => null, 'fecha_fin_inscripcion' => '', 'fecha_examen1' => null, 'fecha_examen2' => '', 'fecha_resultados' => null, ]); $response->assertStatus(200); $proceso->refresh(); // All date fields should be null $this->assertNull($proceso->fecha_inicio_inscripcion); $this->assertNull($proceso->fecha_fin_inscripcion); $this->assertNull($proceso->fecha_examen1); $this->assertNull($proceso->fecha_examen2); $this->assertNull($proceso->fecha_resultados); } /** @test */ public function update_sets_link_fields_to_null_when_empty(): void { $this->authenticateUser(); $proceso = ProcesoAdmision::create([ 'titulo' => 'Proceso Con Links', 'slug' => 'proceso-con-links', 'link_preinscripcion' => 'https://example.com/preinscripcion', 'link_inscripcion' => 'https://example.com/inscripcion', 'link_resultados' => 'https://example.com/resultados', 'link_reglamento' => 'https://example.com/reglamento', ]); // Update links to empty $response = $this->patchJson("/api/admin/procesos-admision/{$proceso->id}", [ 'link_preinscripcion' => '', 'link_inscripcion' => null, 'link_resultados' => '', 'link_reglamento' => null, ]); $response->assertStatus(200); $proceso->refresh(); // All link fields should be null $this->assertNull($proceso->link_preinscripcion); $this->assertNull($proceso->link_inscripcion); $this->assertNull($proceso->link_resultados); $this->assertNull($proceso->link_reglamento); } /** @test */ public function update_does_not_affect_fields_not_in_request(): void { $this->authenticateUser(); $proceso = ProcesoAdmision::create([ 'titulo' => 'Proceso Original', 'slug' => 'proceso-original', 'subtitulo' => 'Subtitulo que no debe cambiar', 'descripcion' => 'Descripcion que no debe cambiar', 'link_preinscripcion' => 'https://example.com/link', ]); // Update only titulo (subtitulo, descripcion, link not in request) $response = $this->patchJson("/api/admin/procesos-admision/{$proceso->id}", [ 'titulo' => 'Titulo Actualizado', ]); $response->assertStatus(200); $proceso->refresh(); // Updated field $this->assertEquals('Titulo Actualizado', $proceso->titulo); // Fields not in request should remain unchanged $this->assertEquals('Subtitulo que no debe cambiar', $proceso->subtitulo); $this->assertEquals('Descripcion que no debe cambiar', $proceso->descripcion); $this->assertEquals('https://example.com/link', $proceso->link_preinscripcion); } }