owner = User::factory()->create(); $this->token = $this->owner->createToken('test-token')->plainTextToken; }); test('the owner can cancel their own pending_payment booking', function () { $booking = Booking::factory()->create(['user_id' => $this->owner->id, 'status' => BookingStatus::PendingPayment]); $this->withHeader('Authorization', "Bearer {$this->token}") ->postJson("/api/v1/bookings/{$booking->booking_ref}/cancel") ->assertSuccessful() ->assertJsonPath('data.status', BookingStatus::Cancelled->value); expect($booking->refresh()->status)->toBe(BookingStatus::Cancelled); }); test('cancelling a confirmed booking surfaces as 422 and leaves it untouched', function () { $booking = Booking::factory()->create(['user_id' => $this->owner->id, 'status' => BookingStatus::Confirmed]); $this->withHeader('Authorization', "Bearer {$this->token}") ->postJson("/api/v1/bookings/{$booking->booking_ref}/cancel") ->assertStatus(422); expect($booking->refresh()->status)->toBe(BookingStatus::Confirmed); }); test('a non-owner without manage_bookings cannot cancel someone else\'s booking', function () { $booking = Booking::factory()->create([ 'user_id' => User::factory()->create()->id, 'status' => BookingStatus::PendingPayment, ]); $this->withHeader('Authorization', "Bearer {$this->token}") ->postJson("/api/v1/bookings/{$booking->booking_ref}/cancel") ->assertForbidden(); expect($booking->refresh()->status)->toBe(BookingStatus::PendingPayment); }); test('staff with manage_bookings can cancel someone else\'s pending_payment booking', function () { $staff = User::factory()->create()->givePermissionTo('manage_bookings'); $staffToken = $staff->createToken('staff-token')->plainTextToken; $booking = Booking::factory()->create(['user_id' => $this->owner->id, 'status' => BookingStatus::PendingPayment]); $this->withHeader('Authorization', "Bearer {$staffToken}") ->postJson("/api/v1/bookings/{$booking->booking_ref}/cancel") ->assertSuccessful(); expect($booking->refresh()->status)->toBe(BookingStatus::Cancelled); }); test('unauthenticated requests are rejected', function () { $booking = Booking::factory()->create(['status' => BookingStatus::PendingPayment]); $this->postJson("/api/v1/bookings/{$booking->booking_ref}/cancel")->assertUnauthorized(); }); test('404s for a booking that does not exist', function () { $this->withHeader('Authorization', "Bearer {$this->token}") ->postJson('/api/v1/bookings/EVB-DOES-NOT-EXIST/cancel') ->assertNotFound(); });