c378ab5884
- PhaseList pasa a contenedor: botón "Agregar fase" + modal crear/editar con todos los parámetros (nombre, descripción, orden, color, progreso, fechas previstas y reales) y validación. Antes "Agregar fase" creaba directamente 'Nueva fase'. - PhaseTable (Rappasoft): orden, nombre+descripción, barra de progreso, fechas, color y acciones (editar abre el modal vía evento, actualizar progreso, eliminar); búsqueda y ordenación. Gateado por 'manage phases' + acceso al proyecto. Tests: PhaseManagementTest (4). Suite 65 passing (solo 2 pre-existentes sqlite). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
116 lines
3.8 KiB
PHP
116 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use App\Livewire\PhaseList;
|
|
use App\Livewire\PhaseTable;
|
|
use App\Models\Phase;
|
|
use App\Models\Project;
|
|
use App\Models\User;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Livewire\Livewire;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Tests\TestCase;
|
|
|
|
class PhaseManagementTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private User $user;
|
|
private Project $project;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
foreach (['manage phases', 'edit projects'] as $p) {
|
|
Permission::findOrCreate($p);
|
|
}
|
|
|
|
$this->user = User::factory()->create();
|
|
$this->user->givePermissionTo(['manage phases', 'edit projects']);
|
|
|
|
$this->project = Project::create([
|
|
'reference' => 'PH-1',
|
|
'name' => 'Proyecto Fases',
|
|
'address' => 'Calle 1',
|
|
'lat' => 40.0,
|
|
'lng' => -3.0,
|
|
'start_date' => now()->toDateString(),
|
|
'end_date_estimated' => now()->addMonths(3)->toDateString(),
|
|
'status' => 'in_progress',
|
|
'created_by' => $this->user->id,
|
|
]);
|
|
$this->project->users()->attach($this->user->id, ['role_in_project' => 'supervisor']);
|
|
}
|
|
|
|
public function test_create_phase_via_modal_persists_all_fields(): void
|
|
{
|
|
Livewire::actingAs($this->user)
|
|
->test(PhaseList::class, ['project' => $this->project])
|
|
->call('openForm')
|
|
->set('name', 'Cimentación')
|
|
->set('description', 'Zapatas y muros')
|
|
->set('color', '#ff0000')
|
|
->set('order', 2)
|
|
->set('progressPercent', 30)
|
|
->set('plannedStart', '2026-07-01')
|
|
->set('plannedEnd', '2026-08-01')
|
|
->call('save')
|
|
->assertHasNoErrors();
|
|
|
|
$this->assertDatabaseHas('phases', [
|
|
'project_id' => $this->project->id,
|
|
'name' => 'Cimentación',
|
|
'color' => '#ff0000',
|
|
'order' => 2,
|
|
'progress_percent' => 30,
|
|
]);
|
|
}
|
|
|
|
public function test_edit_phase_loads_and_updates(): void
|
|
{
|
|
$phase = $this->project->phases()->create([
|
|
'name' => 'Vieja', 'order' => 1, 'color' => '#3b82f6', 'progress_percent' => 0,
|
|
]);
|
|
|
|
Livewire::actingAs($this->user)
|
|
->test(PhaseList::class, ['project' => $this->project])
|
|
->call('editPhase', $phase->id)
|
|
->assertSet('name', 'Vieja')
|
|
->set('name', 'Nueva')
|
|
->set('progressPercent', 80)
|
|
->call('save')
|
|
->assertHasNoErrors();
|
|
|
|
$phase->refresh();
|
|
$this->assertEquals('Nueva', $phase->name);
|
|
$this->assertEquals(80, $phase->progress_percent);
|
|
}
|
|
|
|
public function test_phase_table_lists_and_deletes(): void
|
|
{
|
|
$phase = $this->project->phases()->create([
|
|
'name' => 'Estructura', 'order' => 1, 'color' => '#3b82f6', 'progress_percent' => 0,
|
|
]);
|
|
|
|
Livewire::actingAs($this->user)
|
|
->test(PhaseTable::class, ['projectId' => $this->project->id])
|
|
->assertOk()
|
|
->assertSee('Estructura')
|
|
->call('deletePhase', $phase->id);
|
|
|
|
$this->assertDatabaseMissing('phases', ['id' => $phase->id, 'deleted_at' => null]);
|
|
}
|
|
|
|
public function test_create_phase_requires_manage_phases_permission(): void
|
|
{
|
|
$outsider = User::factory()->create();
|
|
$this->project->users()->attach($outsider->id, ['role_in_project' => 'viewer']);
|
|
|
|
Livewire::actingAs($outsider)
|
|
->test(PhaseList::class, ['project' => $this->project])
|
|
->call('openForm')
|
|
->assertForbidden();
|
|
}
|
|
}
|