*/ public array $requestCalls = []; public function listPolicies(string $policyType, array $options = []): GraphResponse { return new GraphResponse(true, []); } public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse { return new GraphResponse(true, ['payload' => []]); } public function getOrganization(array $options = []): GraphResponse { return new GraphResponse(true, []); } public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse { return new GraphResponse(true, []); } public function request(string $method, string $path, array $options = []): GraphResponse { $method = strtoupper($method); $this->requestCalls[] = [ 'method' => $method, 'path' => $path, 'payload' => $options['json'] ?? null, ]; if ($method === 'GET') { return new GraphResponse(true, ['value' => []]); } return new GraphResponse(true, []); } public function getServicePrincipalPermissions(array $options = []): GraphResponse { return new GraphResponse(true, []); } } test('restore can execute from a specific policy version snapshot', function () { $client = new PolicyVersionRestoreGraphClient; app()->instance(GraphClientInterface::class, $client); $tenant = Tenant::create([ 'tenant_id' => 'tenant-version-restore', 'name' => 'Tenant One', 'metadata' => [], ]); $policy = Policy::create([ 'tenant_id' => $tenant->id, 'external_id' => 'gpo-versioned-1', 'policy_type' => 'groupPolicyConfiguration', 'display_name' => 'Admin Templates', 'platform' => 'windows', ]); $snapshotWithThree = [ 'id' => $policy->external_id, 'displayName' => $policy->display_name, '@odata.type' => '#microsoft.graph.groupPolicyConfiguration', 'definitionValues' => collect(range(1, 3)) ->map(fn (int $i) => [ 'enabled' => true, 'definition@odata.bind' => "https://graph.microsoft.com/beta/deviceManagement/groupPolicyDefinitions('def-{$i}')", '#Definition_Id' => "def-{$i}", '#Definition_displayName' => "Setting {$i}", ])->all(), ]; $snapshotWithFive = [ 'id' => $policy->external_id, 'displayName' => $policy->display_name, '@odata.type' => '#microsoft.graph.groupPolicyConfiguration', 'definitionValues' => collect(range(1, 5)) ->map(fn (int $i) => [ 'enabled' => true, 'definition@odata.bind' => "https://graph.microsoft.com/beta/deviceManagement/groupPolicyDefinitions('def-{$i}')", '#Definition_Id' => "def-{$i}", '#Definition_displayName' => "Setting {$i}", ])->all(), ]; PolicyVersion::create([ 'tenant_id' => $tenant->id, 'policy_id' => $policy->id, 'version_number' => 1, 'policy_type' => $policy->policy_type, 'platform' => $policy->platform, 'created_by' => 'tester@example.com', 'captured_at' => now(), 'snapshot' => $snapshotWithThree, 'metadata' => ['source' => 'version_capture'], ]); $versionToRestore = PolicyVersion::create([ 'tenant_id' => $tenant->id, 'policy_id' => $policy->id, 'version_number' => 2, 'policy_type' => $policy->policy_type, 'platform' => $policy->platform, 'created_by' => 'tester@example.com', 'captured_at' => now(), 'snapshot' => $snapshotWithFive, 'metadata' => ['source' => 'version_capture'], ]); $user = User::factory()->create(['email' => 'tester@example.com']); $this->actingAs($user); $service = app(RestoreService::class); $run = $service->executeFromPolicyVersion( tenant: $tenant, version: $versionToRestore, dryRun: false, actorEmail: $user->email, actorName: $user->name, )->refresh(); expect($run->status)->toBe('completed'); expect($run->results[0]['status'])->toBe('applied'); expect($run->results[0]['definition_value_summary']['success'])->toBe(5); $definitionValueCreateCalls = collect($client->requestCalls) ->filter(fn (array $call) => $call['method'] === 'POST' && str_contains($call['path'], '/definitionValues')) ->values(); expect($definitionValueCreateCalls)->toHaveCount(5); });