Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 3m58s
Applied diagnostic surface contract rules to Audit Log inspect modal and Support Diagnostics action context, consolidating raw diagnostic data into safe modals according to Spec 374.
184 lines
7.4 KiB
PHP
184 lines
7.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\EnvironmentDiagnostics;
|
|
use App\Models\AuditLog;
|
|
use App\Models\ManagedEnvironmentMembership;
|
|
use App\Support\Audit\AuditActionId;
|
|
use App\Support\Rbac\UiTooltips;
|
|
use Filament\Actions\Action;
|
|
use Filament\Facades\Filament;
|
|
use Illuminate\Database\Schema\Blueprint;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
describe('ManagedEnvironment diagnostics repairs', function () {
|
|
it('hides repair actions when no defect is present', function () {
|
|
[$owner, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($owner);
|
|
|
|
Filament::setTenant($tenant, true);
|
|
bindFailHardGraphClient();
|
|
|
|
Livewire::test(EnvironmentDiagnostics::class)
|
|
->assertSee('No repair diagnostics are active')
|
|
->assertSee('No supported access or membership repair is active')
|
|
->assertSee('Use Open support diagnostics')
|
|
->assertActionVisible('openSupportDiagnostics')
|
|
->assertActionEnabled('openSupportDiagnostics')
|
|
->assertDontSee('All good')
|
|
->assertDontSee('No known issues detected')
|
|
->assertActionHidden('bootstrapOwner')
|
|
->assertActionHidden('mergeDuplicateMemberships');
|
|
});
|
|
|
|
it('keeps owner bootstrap hidden because workspace roles own role recovery', function () {
|
|
[$manager, $tenant] = createUserWithTenant(role: 'manager');
|
|
|
|
$this->actingAs($manager);
|
|
|
|
Filament::setTenant($tenant, true);
|
|
|
|
expect(ManagedEnvironmentMembership::query()
|
|
->where('managed_environment_id', (int) $tenant->getKey())
|
|
->where('role', 'owner')
|
|
->count())->toBe(0);
|
|
|
|
Livewire::test(EnvironmentDiagnostics::class)
|
|
->assertDontSee('Missing owner')
|
|
->assertActionHidden('bootstrapOwner');
|
|
});
|
|
|
|
it('renders a single action hierarchy for duplicate membership diagnostics', function () {
|
|
[$owner, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($owner);
|
|
|
|
Filament::setTenant($tenant, true);
|
|
bindFailHardGraphClient();
|
|
|
|
Schema::table('managed_environment_memberships', function (Blueprint $table): void {
|
|
$table->dropUnique(['managed_environment_id', 'user_id']);
|
|
});
|
|
|
|
ManagedEnvironmentMembership::query()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'user_id' => (int) $owner->getKey(),
|
|
'role' => 'readonly',
|
|
'source' => 'manual',
|
|
'created_by_user_id' => (int) $owner->getKey(),
|
|
]);
|
|
|
|
Livewire::test(EnvironmentDiagnostics::class)
|
|
->assertSee('1 repair diagnostic needs attention')
|
|
->assertSee('Recommended first check')
|
|
->assertSee('Duplicate memberships')
|
|
->assertSee('Merge duplicate access scopes')
|
|
->assertDontSee('No repair diagnostics are active')
|
|
->assertActionVisible('mergeDuplicateMemberships')
|
|
->assertActionEnabled('mergeDuplicateMemberships')
|
|
->assertActionExists('mergeDuplicateMemberships', fn (Action $action): bool => $action->isConfirmationRequired());
|
|
});
|
|
|
|
it('prioritizes missing owner over duplicate memberships when both blockers are visible', function () {
|
|
[$owner, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($owner);
|
|
|
|
Filament::setTenant($tenant, true);
|
|
bindFailHardGraphClient();
|
|
|
|
Livewire::test(EnvironmentDiagnostics::class)
|
|
->set('missingOwner', true)
|
|
->set('hasDuplicateMembershipsForCurrentUser', true)
|
|
->assertSeeInOrder([
|
|
'2 repair diagnostics need attention',
|
|
'Bootstrap owner',
|
|
'Duplicate memberships',
|
|
'Merge duplicate access scopes',
|
|
])
|
|
->assertSee('Primary repair path')
|
|
->assertSee('Secondary repair path')
|
|
->assertActionVisible('bootstrapOwner')
|
|
->assertActionVisible('mergeDuplicateMemberships')
|
|
->assertActionExists('bootstrapOwner', fn (Action $action): bool => $action->isConfirmationRequired())
|
|
->assertActionExists('mergeDuplicateMemberships', fn (Action $action): bool => $action->isConfirmationRequired());
|
|
});
|
|
|
|
it('shows duplicate-scope repair as disabled for readonly members', function () {
|
|
[$readonly, $tenant] = createUserWithTenant(role: 'readonly');
|
|
|
|
$this->actingAs($readonly);
|
|
|
|
Filament::setTenant($tenant, true);
|
|
|
|
Schema::table('managed_environment_memberships', function (Blueprint $table): void {
|
|
$table->dropUnique(['managed_environment_id', 'user_id']);
|
|
});
|
|
|
|
ManagedEnvironmentMembership::query()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'user_id' => (int) $readonly->getKey(),
|
|
'role' => 'readonly',
|
|
'source' => 'manual',
|
|
'created_by_user_id' => (int) $readonly->getKey(),
|
|
]);
|
|
|
|
Livewire::test(EnvironmentDiagnostics::class)
|
|
->assertActionVisible('mergeDuplicateMemberships')
|
|
->assertActionDisabled('mergeDuplicateMemberships')
|
|
->assertActionExists('mergeDuplicateMemberships', function (Action $action): bool {
|
|
return $action->getTooltip() === UiTooltips::INSUFFICIENT_PERMISSION;
|
|
});
|
|
});
|
|
|
|
it('merges duplicate memberships for the current user (diagnostics repair)', function () {
|
|
[$owner, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($owner);
|
|
|
|
Filament::setTenant($tenant, true);
|
|
|
|
// Intentionally create a broken state by temporarily dropping the current uniqueness enforcement.
|
|
Schema::table('managed_environment_memberships', function (Blueprint $table): void {
|
|
$table->dropUnique(['managed_environment_id', 'user_id']);
|
|
});
|
|
|
|
ManagedEnvironmentMembership::query()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'user_id' => (int) $owner->getKey(),
|
|
'role' => 'readonly',
|
|
'source' => 'manual',
|
|
'created_by_user_id' => (int) $owner->getKey(),
|
|
]);
|
|
|
|
expect(ManagedEnvironmentMembership::query()
|
|
->where('managed_environment_id', (int) $tenant->getKey())
|
|
->where('user_id', (int) $owner->getKey())
|
|
->count())->toBeGreaterThan(1);
|
|
|
|
Livewire::test(EnvironmentDiagnostics::class)
|
|
->assertActionVisible('mergeDuplicateMemberships')
|
|
->assertActionEnabled('mergeDuplicateMemberships')
|
|
->assertActionExists('mergeDuplicateMemberships', fn (Action $action): bool => $action->isConfirmationRequired())
|
|
->mountAction('mergeDuplicateMemberships')
|
|
->callMountedAction()
|
|
->assertSuccessful();
|
|
|
|
expect(ManagedEnvironmentMembership::query()
|
|
->where('managed_environment_id', (int) $tenant->getKey())
|
|
->where('user_id', (int) $owner->getKey())
|
|
->count())->toBe(1);
|
|
|
|
expect(AuditLog::query()
|
|
->where('managed_environment_id', (int) $tenant->getKey())
|
|
->where('action', AuditActionId::TenantMembershipDuplicatesMerged->value)
|
|
->exists())->toBeTrue();
|
|
});
|
|
});
|