Files
L-Ami-Fiduciaire/tests/Feature/Declaration/DeclarationStatusFlowTest.php
Saad Ibn-Ezzoubayr a2ab6f365d feat: implement Story 2.1 — Owner/Manager Command Center Dashboard
- Rewrite DashboardController with cached role-scoped KPI aggregation
  (Cache::remember, 5-min TTL, Declaration::forUser scope)
- Create StatCard.vue component with CVA status variants and a11y
- Rewrite Dashboard.vue with 4-column KPI grid + urgent declarations table
- Add mise_en_demeure status to DeclarationStatus enum with transitions
- Exclude termine, mise_en_demeure, ferme from dashboard queries
- Set deadline proximity red threshold to ≤5 days
- Add abort(404) for non-member workspace access per architecture
- Fix null-safe client access for soft-deleted clients
- Fix hardcoded routes with Wayfinder type-safe imports
- Fix DashboardProps.stats type to allow null
- Add aria-pressed to StatCard for accessibility
- Install shadcn-vue table component (11 files)
- Add 11 Pest feature tests + 3 mise_en_demeure transition tests
- Fix DeclarationFactory eager workspace creation causing slug collisions
- 196 tests pass, 836 assertions, zero regressions
2026-03-20 12:00:24 +00:00

141 lines
5.5 KiB
PHP

<?php
use App\Enums\DeclarationStatus;
use App\Models\Declaration;
use Illuminate\Validation\ValidationException;
test('valid transition: created to en_cours', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
expect($declaration->fresh()->status->value)->toBe('en_cours');
});
test('valid transition: en_cours to en_attente_client', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::EnAttenteClient]);
expect($declaration->fresh()->status->value)->toBe('en_attente_client');
});
test('valid transition: en_attente_client to en_cours', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::EnAttenteClient]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
expect($declaration->fresh()->status->value)->toBe('en_cours');
});
test('valid transition: en_cours to termine', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::Termine]);
expect($declaration->fresh()->status->value)->toBe('termine');
});
test('valid transition: termine to ferme', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::Termine]);
$declaration->update(['status' => DeclarationStatus::Ferme]);
expect($declaration->fresh()->status->value)->toBe('ferme');
});
test('valid transition: en_attente_client to mise_en_demeure', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::EnAttenteClient]);
$declaration->update(['status' => DeclarationStatus::MiseEnDemeure]);
expect($declaration->fresh()->status->value)->toBe('mise_en_demeure');
});
test('valid transition: mise_en_demeure to en_cours', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::EnAttenteClient]);
$declaration->update(['status' => DeclarationStatus::MiseEnDemeure]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
expect($declaration->fresh()->status->value)->toBe('en_cours');
});
test('valid transition: mise_en_demeure to ferme', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::EnAttenteClient]);
$declaration->update(['status' => DeclarationStatus::MiseEnDemeure]);
$declaration->update(['status' => DeclarationStatus::Ferme]);
expect($declaration->fresh()->status->value)->toBe('ferme');
});
test('invalid transition: created to ferme throws validation exception', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::Ferme]);
})->throws(ValidationException::class);
test('invalid transition: created to termine throws validation exception', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::Termine]);
})->throws(ValidationException::class);
test('auto-archive: ferme status sets archived_at', function () {
$declaration = Declaration::factory()->create(['status' => DeclarationStatus::Created]);
$declaration->update(['status' => DeclarationStatus::EnCours]);
$declaration->update(['status' => DeclarationStatus::Termine]);
expect($declaration->fresh()->archived_at)->toBeNull();
$declaration->update(['status' => DeclarationStatus::Ferme]);
$fresh = $declaration->fresh();
expect($fresh->archived_at)->not->toBeNull();
});
test('scope active excludes archived declarations', function () {
$active = Declaration::factory()->create([
'status' => DeclarationStatus::Created,
'archived_at' => null,
]);
$archived = Declaration::factory()->create([
'status' => DeclarationStatus::Created,
'archived_at' => now(),
]);
$activeIds = Declaration::active()->pluck('id')->all();
expect($activeIds)->toContain($active->id);
expect($activeIds)->not->toContain($archived->id);
});
test('scope archived includes only archived declarations', function () {
$active = Declaration::factory()->create([
'status' => DeclarationStatus::Created,
'archived_at' => null,
]);
$archived = Declaration::factory()->create([
'status' => DeclarationStatus::Created,
'archived_at' => now(),
]);
$archivedIds = Declaration::archived()->pluck('id')->all();
expect($archivedIds)->toContain($archived->id);
expect($archivedIds)->not->toContain($active->id);
});