Files
Verde-Web/tests/Feature/Api/V1/Qr/MyQrCodeTest.php

124 lines
4.6 KiB
PHP

<?php
namespace Tests\Feature\Api\V1\Qr;
use App\Events\QrBalanceLow;
use App\Models\Household;
use App\Models\QrCode;
use App\Models\QrCodeBatch;
use App\Models\User;
use App\Services\Qr\BatchGenerator;
use App\Services\Qr\QrAllocator;
use Database\Seeders\RoleSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class MyQrCodeTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
$this->seed(RoleSeeder::class);
}
public function test_balance_returns_zero_for_resident_without_household(): void
{
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
Sanctum::actingAs($resident);
$this->getJson('/api/v1/me/qr-codes/balance')
->assertOk()
->assertJsonPath('data.active', 0);
}
public function test_balance_returns_counts_by_status(): void
{
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
$h = Household::factory()->create(['head_user_id' => $resident->id]);
$batch = app(BatchGenerator::class)->generate(2, QrCodeBatch::PURPOSE_FREE);
QrCode::query()
->where('batch_id', $batch->id)
->update(['assigned_to_household_id' => $h->id, 'status' => 'active']);
Sanctum::actingAs($resident);
$this->getJson('/api/v1/me/qr-codes/balance')
->assertOk()
->assertJsonPath('data.active', 2)
->assertJsonPath('data.low_balance', true);
}
public function test_resident_can_list_own_codes(): void
{
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
$h = Household::factory()->create(['head_user_id' => $resident->id]);
$batch = app(BatchGenerator::class)->generate(3, QrCodeBatch::PURPOSE_FREE);
QrCode::query()
->where('batch_id', $batch->id)
->update(['assigned_to_household_id' => $h->id, 'status' => 'active']);
Sanctum::actingAs($resident);
$response = $this->getJson('/api/v1/me/qr-codes');
$response->assertOk();
$this->assertCount(3, $response->json('data'));
}
public function test_resident_can_activate_an_allocated_code(): void
{
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
$h = Household::factory()->create(['head_user_id' => $resident->id]);
$batch = app(BatchGenerator::class)->generate(1, QrCodeBatch::PURPOSE_FREE);
$code = QrCode::query()->where('batch_id', $batch->id)->first();
$code->forceFill([
'assigned_to_household_id' => $h->id,
'status' => 'allocated',
'allocated_at' => now(),
])->save();
Sanctum::actingAs($resident);
$response = $this->postJson("/api/v1/me/qr-codes/{$code->serial}/activate");
$response->assertOk()
->assertJsonPath('data.status', 'active');
$this->assertNotNull($code->fresh()->activated_at);
}
public function test_resident_cannot_activate_other_household_code(): void
{
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
$other = User::factory()->create(['role' => User::ROLE_RESIDENT]);
$otherHousehold = Household::factory()->create(['head_user_id' => $other->id]);
$batch = app(BatchGenerator::class)->generate(1, QrCodeBatch::PURPOSE_FREE);
$code = QrCode::query()->where('batch_id', $batch->id)->first();
$code->forceFill([
'assigned_to_household_id' => $otherHousehold->id,
'status' => 'allocated',
])->save();
Sanctum::actingAs($resident);
$this->postJson("/api/v1/me/qr-codes/{$code->serial}/activate")
->assertStatus(403);
}
public function test_low_balance_event_dispatched_when_count_below_threshold(): void
{
Event::fake([QrBalanceLow::class]);
$resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']);
$h = Household::factory()->create(['head_user_id' => $resident->id]);
$batch = app(BatchGenerator::class)->generate(2, QrCodeBatch::PURPOSE_FREE);
QrCode::query()->where('batch_id', $batch->id)
->update(['assigned_to_household_id' => $h->id, 'status' => 'active']);
app(QrAllocator::class)->notifyBalanceIfLow($h);
Event::assertDispatched(QrBalanceLow::class, fn ($e) => $e->household->id === $h->id && $e->activeCount === 2,
);
}
}