test(feature): 補齊五個核心業務流程 Feature test——Offer/Schedule CRUD、Admin 管理、通知觸發、預約列表
Run Tests / test (pull_request) Successful in 1m51s
Run Tests / test (pull_request) Successful in 1m51s
ProviderOfferCrudTest(7 案例):store/update/destroy 正常流程 + 所有權邊界(403)+ 未認證(401) ProviderScheduleCrudTest(7 案例):store/update/destroy + 容量不變式(422)+ destroy 同步取消 active bookings AdminUserManagementTest(5 案例):列表角色過濾 + toggle-active/toggle-verified DB 副作用 + 非 admin 403 NotificationTriggerTest(5 案例):5 條直接觸發路徑,收件者各不同(BookingCreated/CancelledByMember → provider;其餘 → member) BookingListTest(4 案例):三角色資料隔離邊界 + 未認證 401 全套件 215 passed / 529 assertions,零 regression。 同步新增 openspec/changes/feature-test-coverage/ 與 openspec/specs/feature-test-coverage/spec.md。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\MemberProfile;
|
||||
use App\Models\ProviderProfile;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Admin 使用者管理(admin-user-management 規格)。
|
||||
*
|
||||
* 列表端點必須依 role 過濾,否則 admin 介面會混入不同角色資料;
|
||||
* toggle-verified 的快取清除副作用已由 DivingOfferVisibilityTest 覆蓋,
|
||||
* 這裡只驗資料庫欄位變更與 HTTP 200。
|
||||
*/
|
||||
class AdminUserManagementTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private function makeAdmin(): User
|
||||
{
|
||||
return User::factory()->create(['role' => 'admin']);
|
||||
}
|
||||
|
||||
private function makeMember(): User
|
||||
{
|
||||
$member = User::factory()->create(['role' => 'member']);
|
||||
MemberProfile::create(['user_id' => $member->id]);
|
||||
return $member;
|
||||
}
|
||||
|
||||
private function makeProvider(bool $isVerified = false): User
|
||||
{
|
||||
$provider = User::factory()->create(['role' => 'provider']);
|
||||
ProviderProfile::create(['user_id' => $provider->id, 'is_verified' => $isVerified]);
|
||||
return $provider;
|
||||
}
|
||||
|
||||
// ── 列表 ─────────────────────────────────────────────────
|
||||
|
||||
public function test_admin_lists_members_only(): void
|
||||
{
|
||||
$admin = $this->makeAdmin();
|
||||
$member = $this->makeMember();
|
||||
$provider = $this->makeProvider();
|
||||
|
||||
$response = $this->actingAs($admin)->getJson('/api/admin/members');
|
||||
|
||||
$response->assertOk()->assertJsonPath('status', true);
|
||||
|
||||
$ids = array_column($response->json('data'), 'id');
|
||||
$this->assertContains($member->id, $ids);
|
||||
$this->assertNotContains($provider->id, $ids);
|
||||
}
|
||||
|
||||
public function test_admin_lists_providers_only(): void
|
||||
{
|
||||
$admin = $this->makeAdmin();
|
||||
$member = $this->makeMember();
|
||||
$provider = $this->makeProvider();
|
||||
|
||||
$response = $this->actingAs($admin)->getJson('/api/admin/providers');
|
||||
|
||||
$response->assertOk()->assertJsonPath('status', true);
|
||||
|
||||
$ids = array_column($response->json('data'), 'id');
|
||||
$this->assertContains($provider->id, $ids);
|
||||
$this->assertNotContains($member->id, $ids);
|
||||
}
|
||||
|
||||
// ── toggle-active ────────────────────────────────────────
|
||||
|
||||
public function test_admin_toggles_member_active_status(): void
|
||||
{
|
||||
$admin = $this->makeAdmin();
|
||||
// is_active 預設由 DB 決定,factory 不設值;直接測試 toggle 的翻轉效果
|
||||
$member = User::factory()->create(['role' => 'member', 'is_active' => true]);
|
||||
|
||||
$this->actingAs($admin)
|
||||
->putJson("/api/admin/members/{$member->id}/toggle-active")
|
||||
->assertOk()
|
||||
->assertJsonPath('data.is_active', false);
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'id' => $member->id,
|
||||
'is_active' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
// ── toggle-verified ──────────────────────────────────────
|
||||
|
||||
public function test_admin_toggles_provider_verified_status(): void
|
||||
{
|
||||
$admin = $this->makeAdmin();
|
||||
$provider = $this->makeProvider(isVerified: false);
|
||||
|
||||
$this->actingAs($admin)
|
||||
->putJson("/api/admin/providers/{$provider->id}/toggle-verified")
|
||||
->assertOk()
|
||||
->assertJsonPath('data.is_verified', true);
|
||||
|
||||
$this->assertDatabaseHas('provider_profiles', [
|
||||
'user_id' => $provider->id,
|
||||
'is_verified' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
// ── 角色保護 ─────────────────────────────────────────────
|
||||
|
||||
public function test_non_admin_is_forbidden(): void
|
||||
{
|
||||
$member = $this->makeMember();
|
||||
|
||||
$this->actingAs($member)
|
||||
->getJson('/api/admin/members')
|
||||
->assertStatus(403);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user