getRequiredPermissions(); if (empty($required)) { test()->markTestSkipped('No required permissions configured.'); } return $required; } it('returns ok when all permissions exist', function () { // Mock GraphClient to return all permissions as granted $this->mock(GraphClientInterface::class, function ($mock) { $mock->shouldReceive('getServicePrincipalPermissions') ->andReturn(new GraphResponse(true, [ 'value' => collect(config('intune_permissions.permissions', [])) ->map(fn ($p) => ['value' => $p['key']]) ->toArray(), ])); }); $tenant = Tenant::create([ 'tenant_id' => 'tenant-ok', 'name' => 'Tenant OK', ]); foreach (requiredPermissions() as $permission) { TenantPermission::create([ 'tenant_id' => $tenant->id, 'permission_key' => $permission['key'], 'status' => 'granted', ]); } $result = app(TenantPermissionService::class)->compare($tenant); expect($result['overall_status'])->toBe('granted'); expect(TenantPermission::where('tenant_id', $tenant->id)->where('status', 'granted')->count()) ->toBe(count(requiredPermissions())); }); it('marks missing permissions when not granted', function () { $permissions = requiredPermissions(); // Mock GraphClient to return only first permission as granted $this->mock(GraphClientInterface::class, function ($mock) use ($permissions) { $mock->shouldReceive('getServicePrincipalPermissions') ->andReturn(new GraphResponse(true, [ 'permissions' => [$permissions[0]['key']], ])); }); $tenant = Tenant::create([ 'tenant_id' => 'tenant-missing', 'name' => 'Tenant Missing', ]); $first = $permissions[0]['key']; TenantPermission::create([ 'tenant_id' => $tenant->id, 'permission_key' => $first, 'status' => 'ok', ]); // Use liveCheck=true to trigger Graph API call $result = app(TenantPermissionService::class)->compare($tenant, null, true, true); expect($result['overall_status'])->toBe('missing'); $missingKey = $permissions[1]['key'] ?? null; if ($missingKey) { $this->assertDatabaseHas('tenant_permissions', [ 'tenant_id' => $tenant->id, 'permission_key' => $missingKey, 'status' => 'missing', ]); } }); it('reports error statuses from graph comparison', function () { // Mock GraphClient to return an error $this->mock(GraphClientInterface::class, function ($mock) { $mock->shouldReceive('getServicePrincipalPermissions') ->andReturn(new GraphResponse(false, [], 500, ['Graph API error'])); }); $tenant = Tenant::create([ 'tenant_id' => 'tenant-error', 'name' => 'Tenant Error', ]); $permissions = requiredPermissions(); $first = $permissions[0]['key']; $result = app(TenantPermissionService::class)->compare($tenant, [ $first => [ 'status' => 'error', 'details' => ['message' => 'forbidden'], ], ]); expect($result['overall_status'])->toBe('error'); $this->assertDatabaseHas('tenant_permissions', [ 'tenant_id' => $tenant->id, 'permission_key' => $first, 'status' => 'error', ]); }); it('ignores configured stub permissions when requested', function () { $originalPermissions = config('intune_permissions.permissions'); $originalStub = config('intune_permissions.granted_stub'); config()->set('intune_permissions.permissions', [ [ 'key' => 'DeviceManagementRBAC.ReadWrite.All', 'type' => 'application', 'description' => null, 'features' => [], ], ]); config()->set('intune_permissions.granted_stub', ['DeviceManagementRBAC.ReadWrite.All']); $tenant = Tenant::factory()->create(); TenantPermission::create([ 'tenant_id' => $tenant->id, 'permission_key' => 'DeviceManagementRBAC.ReadWrite.All', 'status' => 'granted', 'details' => ['source' => 'configured'], ]); $result = app(TenantPermissionService::class)->compare($tenant, persist: false, useConfiguredStub: false); expect($result['overall_status'])->toBe('missing'); expect($result['permissions'][0]['status'])->toBe('missing'); config()->set('intune_permissions.permissions', $originalPermissions); config()->set('intune_permissions.granted_stub', $originalStub); });