feat: complete Epic 0 — foundation migration & infrastructure setup
Stories 0.2-0.5: rename folders→declarations (backend+frontend), configure Redis for cache/queue/sessions, add foundation database migrations (permissions, archived_at), replace DeclarationStatus enum with architecture lifecycle values, create DeclarationObserver for status transition validation and auto-archive, fix controller status transitions to respect observer rules. 93 tests pass (240 assertions). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
108
tests/Feature/Declaration/DeclarationStatusFlowTest.php
Normal file
108
tests/Feature/Declaration/DeclarationStatusFlowTest.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?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('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);
|
||||
});
|
||||
Reference in New Issue
Block a user