## Summary - add canonical managed-tenant onboarding draft routing with explicit draft identity and landing vs concrete draft behavior - implement draft lifecycle, authorization, attribution, picker UX, resume-stage resolution, and auditable cancel or completion semantics - add focused feature, unit, and browser coverage plus Spec 138 artifacts for the onboarding draft resume flow ## Validation - `vendor/bin/sail artisan test --compact tests/Feature/ManagedTenantOnboardingWizardTest.php tests/Feature/Audit/OnboardingDraftAuditTest.php tests/Feature/Onboarding/OnboardingDraftAccessTest.php tests/Feature/Onboarding/OnboardingDraftAuthorizationTest.php tests/Feature/Onboarding/OnboardingDraftLifecycleTest.php tests/Feature/Onboarding/OnboardingDraftMultiTabTest.php tests/Feature/Onboarding/OnboardingDraftPickerTest.php tests/Feature/Onboarding/OnboardingDraftRoutingTest.php tests/Feature/Onboarding/OnboardingRbacSemanticsTest.php tests/Feature/Onboarding/OnboardingVerificationClustersTest.php tests/Feature/Onboarding/OnboardingVerificationTest.php tests/Feature/Onboarding/OnboardingVerificationV1_5UxTest.php tests/Feature/Verification/VerificationReportViewerDbOnlyTest.php tests/Unit/Onboarding tests/Unit/VerificationReportSanitizerEvidenceKindsTest.php tests/Browser/OnboardingDraftRefreshTest.php tests/Browser/OnboardingDraftVerificationResumeTest.php` - passed: 69 tests, 251 assertions Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #167
127 lines
3.9 KiB
PHP
127 lines
3.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\User;
|
|
use App\Models\Workspace;
|
|
use App\Models\WorkspaceMembership;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
|
|
it('shows a draft picker with resumable draft metadata when multiple drafts exist', function (): void {
|
|
$workspace = Workspace::factory()->create();
|
|
$user = User::factory()->create();
|
|
$startedBy = User::factory()->create(['name' => 'Primary Owner']);
|
|
$updatedBy = User::factory()->create(['name' => 'Second Operator']);
|
|
|
|
foreach ([$user, $startedBy, $updatedBy] as $member) {
|
|
WorkspaceMembership::factory()->create([
|
|
'workspace_id' => (int) $workspace->getKey(),
|
|
'user_id' => (int) $member->getKey(),
|
|
'role' => 'owner',
|
|
]);
|
|
}
|
|
|
|
session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());
|
|
|
|
createOnboardingDraft([
|
|
'workspace' => $workspace,
|
|
'started_by' => $startedBy,
|
|
'updated_by' => $updatedBy,
|
|
'state' => [
|
|
'entra_tenant_id' => '11111111-1111-1111-1111-111111111111',
|
|
'tenant_name' => 'Contoso',
|
|
'environment' => 'prod',
|
|
'primary_domain' => 'contoso.example',
|
|
],
|
|
]);
|
|
|
|
createOnboardingDraft([
|
|
'workspace' => $workspace,
|
|
'started_by' => $updatedBy,
|
|
'updated_by' => $startedBy,
|
|
'current_step' => 'connection',
|
|
'state' => [
|
|
'entra_tenant_id' => '22222222-2222-2222-2222-222222222222',
|
|
'tenant_name' => 'Fabrikam',
|
|
'environment' => 'staging',
|
|
],
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->get(route('admin.onboarding'))
|
|
->assertSuccessful()
|
|
->assertSee('Multiple onboarding drafts are available.')
|
|
->assertSee('Contoso')
|
|
->assertSee('Fabrikam')
|
|
->assertSee('Current stage')
|
|
->assertSee('Started by')
|
|
->assertSee('Last updated by')
|
|
->assertSee('Primary Owner')
|
|
->assertSee('Second Operator')
|
|
->assertSee('Resume onboarding draft')
|
|
->assertSee('View summary');
|
|
});
|
|
|
|
it('excludes completed and cancelled drafts from the landing picker', function (): void {
|
|
$workspace = Workspace::factory()->create();
|
|
$user = User::factory()->create();
|
|
|
|
WorkspaceMembership::factory()->create([
|
|
'workspace_id' => (int) $workspace->getKey(),
|
|
'user_id' => (int) $user->getKey(),
|
|
'role' => 'owner',
|
|
]);
|
|
|
|
session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());
|
|
|
|
createOnboardingDraft([
|
|
'workspace' => $workspace,
|
|
'started_by' => $user,
|
|
'updated_by' => $user,
|
|
'state' => [
|
|
'entra_tenant_id' => '33333333-3333-3333-3333-333333333333',
|
|
'tenant_name' => 'Visible Draft A',
|
|
],
|
|
]);
|
|
|
|
createOnboardingDraft([
|
|
'workspace' => $workspace,
|
|
'started_by' => $user,
|
|
'updated_by' => $user,
|
|
'state' => [
|
|
'entra_tenant_id' => '44444444-4444-4444-4444-444444444444',
|
|
'tenant_name' => 'Visible Draft B',
|
|
],
|
|
]);
|
|
|
|
createOnboardingDraft([
|
|
'workspace' => $workspace,
|
|
'started_by' => $user,
|
|
'updated_by' => $user,
|
|
'status' => 'completed',
|
|
'state' => [
|
|
'entra_tenant_id' => '55555555-5555-5555-5555-555555555555',
|
|
'tenant_name' => 'Completed Draft',
|
|
],
|
|
]);
|
|
|
|
createOnboardingDraft([
|
|
'workspace' => $workspace,
|
|
'started_by' => $user,
|
|
'updated_by' => $user,
|
|
'status' => 'cancelled',
|
|
'state' => [
|
|
'entra_tenant_id' => '66666666-6666-6666-6666-666666666666',
|
|
'tenant_name' => 'Cancelled Draft',
|
|
],
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->get(route('admin.onboarding'))
|
|
->assertSuccessful()
|
|
->assertSee('Visible Draft A')
|
|
->assertSee('Visible Draft B')
|
|
->assertDontSee('Completed Draft')
|
|
->assertDontSee('Cancelled Draft');
|
|
});
|