Files
reservas/tests/Feature/ReservationCancellationTest.php

96 lines
3.5 KiB
PHP

<?php
use App\Domain\Inventory\Models\SnipeAsset;
use App\Domain\Reservations\Enums\ReservationItemStatus;
use App\Domain\Reservations\Enums\ReservationStatus;
use App\Domain\Reservations\Models\Reservation;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('permite ao requisitante cancelar e liberta os equipamentos com auditoria', function () {
$user = User::factory()->create();
$asset = SnipeAsset::factory()->create();
$reservation = Reservation::create([
'reference' => 'REQ-CANCEL-001',
'requester_id' => $user->id,
'purpose' => 'Captação de uma sessão para arquivo institucional.',
'usage_location' => 'Auditório',
'starts_at' => now()->addDays(3),
'ends_at' => now()->addDays(3)->addHours(2),
'status' => ReservationStatus::PendingApproval,
'approval_deadline' => now()->addDay(),
]);
$item = $reservation->items()->create([
'snipe_asset_id' => $asset->id,
'starts_at' => $reservation->starts_at,
'ends_at' => $reservation->ends_at,
'status' => ReservationItemStatus::Held,
]);
$this->actingAs($user)
->post("/requisicoes/{$reservation->uuid}/cancelar", [
'reason' => 'A sessão foi adiada pela organização.',
])
->assertRedirect()
->assertSessionHas('success');
expect($reservation->fresh()->status)->toBe(ReservationStatus::Cancelled)
->and($item->fresh()->status)->toBe(ReservationItemStatus::Cancelled);
$this->assertDatabaseHas('reservations', [
'id' => $reservation->id,
'cancelled_by' => $user->id,
'cancellation_reason' => 'A sessão foi adiada pela organização.',
]);
$this->assertDatabaseHas('audit_logs', [
'event' => 'reservation.cancelled',
'actor_id' => $user->id,
'auditable_id' => $reservation->id,
]);
});
it('impede outro utilizador de cancelar a requisição', function () {
$owner = User::factory()->create();
$reservation = Reservation::create([
'reference' => 'REQ-CANCEL-002',
'requester_id' => $owner->id,
'purpose' => 'Apoio técnico a uma atividade previamente agendada.',
'usage_location' => 'Sala 4',
'starts_at' => now()->addDays(3),
'ends_at' => now()->addDays(3)->addHour(),
'status' => ReservationStatus::PendingApproval,
]);
$this->actingAs(User::factory()->create())
->post("/requisicoes/{$reservation->uuid}/cancelar", [
'reason' => 'Tentativa por outro utilizador.',
])
->assertForbidden();
expect($reservation->fresh()->status)->toBe(ReservationStatus::PendingApproval);
});
it('não cancela uma requisição num estado terminal', function () {
$user = User::factory()->create();
$reservation = Reservation::create([
'reference' => 'REQ-CANCEL-003',
'requester_id' => $user->id,
'purpose' => 'Pedido já concluído e sem operações pendentes.',
'usage_location' => 'Biblioteca',
'starts_at' => now()->subDays(3),
'ends_at' => now()->subDays(3)->addHour(),
'status' => ReservationStatus::Completed,
]);
$this->actingAs($user)
->from('/requisicoes')
->post("/requisicoes/{$reservation->uuid}/cancelar", [
'reason' => 'Já não preciso deste equipamento.',
])
->assertRedirect('/requisicoes')
->assertSessionHasErrors('reason');
expect($reservation->fresh()->status)->toBe(ReservationStatus::Completed);
});