syncDefaults(); config()->set('graph_contracts.types.assignmentFilter.volatile_fields', ['@odata.etag']); [$user, $tenant] = createMinimalUserWithTenant(role: 'owner'); $connection = ProviderConnection::factory()->withCredential()->create([ 'workspace_id' => (int) $tenant->workspace_id, 'managed_environment_id' => (int) $tenant->getKey(), ]); $run = OperationRun::factory()->withUser($user)->forTenant($tenant)->create([ 'type' => OperationRunType::TenantConfigurationCapture->value, 'status' => OperationRunStatus::Running->value, 'outcome' => OperationRunOutcome::Pending->value, ]); $resourceType = TenantConfigurationResourceType::query() ->where('canonical_type', 'deviceAndAppManagementAssignmentFilter') ->firstOrFail(); $decision = app(CoverageSourceContractResolver::class)->resolve($resourceType); $normalizer = new GenericPayloadNormalizer; $firstPayload = ['id' => 'resource-1', 'displayName' => 'Resource', '@odata.etag' => 'one']; $resource = app(CoverageResourceUpserter::class)->upsert($tenant, $connection, $resourceType, $firstPayload, $decision->sourceMetadata); $firstNormalized = $normalizer->normalize($firstPayload, ['@odata.etag']); app(CoverageEvidenceWriter::class)->append( resource: $resource, resourceType: $resourceType, providerConnection: $connection, operationRun: $run, decision: $decision, rawPayload: $firstPayload, normalizedPayload: $firstNormalized, payloadHash: $normalizer->payloadHash($firstNormalized), permissionContext: ['scopes_granted' => []], ); $secondPayload = ['id' => 'resource-1', 'displayName' => 'Resource updated', '@odata.etag' => 'two']; $sameResource = app(CoverageResourceUpserter::class)->upsert($tenant, $connection, $resourceType, $secondPayload, $decision->sourceMetadata); $secondNormalized = $normalizer->normalize($secondPayload, ['@odata.etag']); $secondEvidence = app(CoverageEvidenceWriter::class)->append( resource: $sameResource, resourceType: $resourceType, providerConnection: $connection, operationRun: $run, decision: $decision, rawPayload: $secondPayload, normalizedPayload: $secondNormalized, payloadHash: $normalizer->payloadHash($secondNormalized), permissionContext: ['scopes_granted' => []], ); expect($sameResource->getKey())->toBe($resource->getKey()) ->and(TenantConfigurationResourceEvidence::query()->where('resource_id', $resource->getKey())->count())->toBe(2) ->and($sameResource->fresh()->latest_evidence_id)->toBe((int) $secondEvidence->getKey()) ->and($secondEvidence->operation_run_id)->toBe((int) $run->getKey()) ->and($secondEvidence->source_metadata['source_contract_key'])->toBe('assignmentFilter') ->and($secondEvidence->normalized_payload)->not->toHaveKey('@odata.etag'); });