for($tenant)->create([ 'selection_hash' => $scopeKey, 'selection_payload' => ['policy_types' => ['settingsCatalogPolicy']], 'status' => InventorySyncRun::STATUS_SUCCESS, 'finished_at' => now()->subDays(2), ]); $current = InventorySyncRun::factory()->for($tenant)->create([ 'selection_hash' => $scopeKey, 'selection_payload' => ['policy_types' => ['settingsCatalogPolicy']], 'status' => InventorySyncRun::STATUS_SUCCESS, 'finished_at' => now()->subDay(), ]); $policy = Policy::factory()->for($tenant)->create([ 'policy_type' => 'settingsCatalogPolicy', ]); $baselineAssignments = [ [ 'target' => [ '@odata.type' => '#microsoft.graph.groupAssignmentTarget', 'groupId' => 'group-a', ], ], ]; $currentAssignments = [ [ 'target' => [ '@odata.type' => '#microsoft.graph.groupAssignmentTarget', 'groupId' => 'group-b', ], ], ]; PolicyVersion::factory()->for($tenant)->for($policy)->create([ 'version_number' => 1, 'policy_type' => $policy->policy_type, 'captured_at' => $baseline->finished_at->copy()->subMinute(), 'assignments' => $baselineAssignments, 'assignments_hash' => hash('sha256', json_encode($baselineAssignments)), ]); PolicyVersion::factory()->for($tenant)->for($policy)->create([ 'version_number' => 2, 'policy_type' => $policy->policy_type, 'captured_at' => $current->finished_at->copy()->subMinute(), 'assignments' => $currentAssignments, 'assignments_hash' => hash('sha256', json_encode($currentAssignments)), ]); $generator = app(DriftFindingGenerator::class); $created = $generator->generate($tenant, $baseline, $current, $scopeKey); expect($created)->toBe(1); $finding = Finding::query()->where('tenant_id', $tenant->getKey())->first(); expect($finding)->not->toBeNull(); expect($finding->subject_type)->toBe('assignment'); expect($finding->subject_external_id)->toBe($policy->external_id); expect($finding->evidence_jsonb)->toHaveKey('change_type', 'modified'); });