Files
CFDivePlatform/tests/Feature/BookingListTest.php
T
a620906209 afdca18c67
Run Tests / test (pull_request) Failing after 2s
fix(tests): 同步 Feature test 與 provider-verification-workflow 架構變更
provider-verification-workflow (#36) 在 feature-test-coverage (#38) merge 前
已將 is_verified 欄位替換為 verification_status 狀態機,並移除 toggle-verified 路由。

- 五個 Feature test 的 makeProvider helper 改用 verification_status='approved'
  (原 is_verified 已從 provider_profiles 欄位移除,靜默忽略導致 422/404)
- AdminUserManagementTest: toggle-verified 案例改為測試新的 approve 端點
  (PUT /admin/verifications/{userId}/approve,需 pending 狀態才可核准)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 19:14:25 +08:00

132 lines
5.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Tests\Feature;
use App\Enums\BookingStatus;
use App\Enums\ScheduleStatus;
use App\Models\Booking;
use App\Models\CourseSchedule;
use App\Models\DivingOffer;
use App\Models\ProviderProfile;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
/**
* 預約列表端點資料隔離(booking-lifecycle 規格)。
*
* 路由對應(routes/api.php 已確認):
* GET /api/member/bookings → MemberBookingController::indexauth:sanctum,無 role check
* GET /api/provider/bookings → ProviderBookingController::indexauth:sanctum,無 role check
* GET /api/admin/bookings → AdminBookingController::indexauth:sanctum + admin middleware
*
* 資料隔離靠 controller query 條件,不靠 middleware role 強制,
* 因此測試需分別以正確角色 actingAs 驗證隔離邊界。
*/
class BookingListTest extends TestCase
{
use RefreshDatabase;
private function makeProviderWithSchedule(): array
{
$provider = User::factory()->create(['role' => 'provider']);
ProviderProfile::create(['user_id' => $provider->id, 'verification_status' => 'approved']);
$offer = DivingOffer::create([
'provider_id' => $provider->id,
'title' => 'Dive Course',
'location' => 'Kenting',
'price' => 3000,
'region' => '南部',
'rating' => 0,
'reviews' => 0,
]);
$schedule = CourseSchedule::create([
'diving_offer_id' => $offer->id,
'provider_id' => $provider->id,
'scheduled_date' => now()->addDays(30)->toDateString(),
'start_time' => '09:00',
'max_participants' => 10,
'current_participants' => 0,
'status' => ScheduleStatus::Open,
]);
return [$provider, $schedule];
}
private function makePendingBooking(User $member, CourseSchedule $schedule): Booking
{
return Booking::create([
'schedule_id' => $schedule->id,
'member_id' => $member->id,
'participants' => 1,
'total_price' => 3000,
'status' => BookingStatus::Pending,
]);
}
// ── Member 列表 ──────────────────────────────────────────
public function test_member_sees_only_own_bookings(): void
{
[$provider, $schedule] = $this->makeProviderWithSchedule();
$memberA = User::factory()->create(['role' => 'member']);
$memberB = User::factory()->create(['role' => 'member']);
$bookingA = $this->makePendingBooking($memberA, $schedule);
$bookingB = $this->makePendingBooking($memberB, $schedule);
$response = $this->actingAs($memberA)->getJson('/api/member/bookings');
$response->assertOk();
$ids = array_column($response->json('data'), 'id');
$this->assertContains($bookingA->id, $ids);
$this->assertNotContains($bookingB->id, $ids);
}
// ── Provider 列表 ────────────────────────────────────────
public function test_provider_sees_only_own_course_bookings(): void
{
[$providerA, $scheduleA] = $this->makeProviderWithSchedule();
[$providerB, $scheduleB] = $this->makeProviderWithSchedule();
$member = User::factory()->create(['role' => 'member']);
$bookingA = $this->makePendingBooking($member, $scheduleA);
$bookingB = $this->makePendingBooking($member, $scheduleB);
$response = $this->actingAs($providerA)->getJson('/api/provider/bookings');
$response->assertOk();
$ids = array_column($response->json('data'), 'id');
$this->assertContains($bookingA->id, $ids);
$this->assertNotContains($bookingB->id, $ids);
}
// ── Admin 列表 ───────────────────────────────────────────
public function test_admin_sees_all_bookings(): void
{
$admin = User::factory()->create(['role' => 'admin']);
[$providerA, $scheduleA] = $this->makeProviderWithSchedule();
[$providerB, $scheduleB] = $this->makeProviderWithSchedule();
$memberA = User::factory()->create(['role' => 'member']);
$memberB = User::factory()->create(['role' => 'member']);
$bookingA = $this->makePendingBooking($memberA, $scheduleA);
$bookingB = $this->makePendingBooking($memberB, $scheduleB);
$response = $this->actingAs($admin)->getJson('/api/admin/bookings');
$response->assertOk();
$ids = array_column($response->json('data'), 'id');
$this->assertContains($bookingA->id, $ids);
$this->assertContains($bookingB->id, $ids);
}
// ── 未認證 ───────────────────────────────────────────────
public function test_unauthenticated_request_returns_401(): void
{
$this->getJson('/api/member/bookings')->assertStatus(401);
}
}