TenantAtlas/tests/Unit/Support/Baselines/SubjectResolverTest.php

96 lines
4.8 KiB
PHP

<?php
declare(strict_types=1);
use App\Support\Baselines\BaselineSupportCapabilityGuard;
use App\Support\Baselines\OperatorActionCategory;
use App\Support\Baselines\ResolutionOutcome;
use App\Support\Baselines\ResolutionPath;
use App\Support\Baselines\SubjectClass;
use App\Support\Baselines\SubjectResolver;
it('derives truthful runtime capability and descriptors for supported policy and foundation types', function (): void {
$resolver = app(SubjectResolver::class);
$policyDescriptor = $resolver->describeForCompare('deviceConfiguration', 'policy-1', 'deviceconfiguration|policy-1');
$foundationDescriptor = $resolver->describeForCapture('roleScopeTag', 'scope-tag-1', 'rolescopetag|baseline');
$rbacDescriptor = $resolver->describeForCompare('intuneRoleDefinition', 'role-def-1', 'rbac-role');
expect($policyDescriptor->subjectClass)->toBe(SubjectClass::PolicyBacked)
->and($policyDescriptor->resolutionPath)->toBe(ResolutionPath::Policy)
->and($policyDescriptor->supportMode)->toBe('supported')
->and($policyDescriptor->sourceModelExpected)->toBe('policy');
expect($foundationDescriptor->subjectClass)->toBe(SubjectClass::FoundationBacked)
->and($foundationDescriptor->resolutionPath)->toBe(ResolutionPath::FoundationInventory)
->and($foundationDescriptor->supportMode)->toBe('limited')
->and($foundationDescriptor->sourceModelExpected)->toBe('inventory');
expect($rbacDescriptor->subjectClass)->toBe(SubjectClass::FoundationBacked)
->and($rbacDescriptor->resolutionPath)->toBe(ResolutionPath::FoundationPolicy)
->and($rbacDescriptor->supportMode)->toBe('supported')
->and($rbacDescriptor->sourceModelExpected)->toBe('policy');
});
it('maps structural and operational outcomes without flattening them into policy_not_found', function (): void {
$resolver = app(SubjectResolver::class);
$foundationDescriptor = $resolver->describeForCapture('notificationMessageTemplate', 'template-1', 'template-subject');
$policyDescriptor = $resolver->describeForCompare('deviceConfiguration', 'policy-1', 'policy-subject');
$structuralOutcome = $resolver->structuralInventoryOnly($foundationDescriptor);
$missingPolicyOutcome = $resolver->missingExpectedRecord($policyDescriptor);
$throttledOutcome = $resolver->throttled($policyDescriptor);
expect($structuralOutcome->resolutionOutcome)->toBe(ResolutionOutcome::FoundationInventoryOnly)
->and($structuralOutcome->reasonCode)->toBe('foundation_not_policy_backed')
->and($structuralOutcome->operatorActionCategory)->toBe(OperatorActionCategory::ProductFollowUp)
->and($structuralOutcome->structural)->toBeTrue();
expect($missingPolicyOutcome->resolutionOutcome)->toBe(ResolutionOutcome::PolicyRecordMissing)
->and($missingPolicyOutcome->reasonCode)->toBe('policy_record_missing')
->and($missingPolicyOutcome->operatorActionCategory)->toBe(OperatorActionCategory::RunPolicySyncOrBackup)
->and($missingPolicyOutcome->structural)->toBeFalse();
expect($throttledOutcome->resolutionOutcome)->toBe(ResolutionOutcome::Throttled)
->and($throttledOutcome->retryable)->toBeTrue()
->and($throttledOutcome->operatorActionCategory)->toBe(OperatorActionCategory::Retry);
});
it('guards unsupported or invalid support declarations before runtime work starts', function (): void {
$guard = app(BaselineSupportCapabilityGuard::class);
config()->set('tenantpilot.foundation_types', [
[
'type' => 'intuneRoleAssignment',
'label' => 'Intune RBAC Role Assignment',
'baseline_compare' => [
'supported' => false,
'identity_strategy' => 'external_id',
],
],
[
'type' => 'brokenFoundation',
'label' => 'Broken Foundation',
'baseline_compare' => [
'supported' => true,
'resolution' => [
'subject_class' => SubjectClass::FoundationBacked->value,
'resolution_path' => 'broken',
'compare_capability' => 'supported',
'capture_capability' => 'supported',
'source_model_expected' => 'inventory',
],
],
],
]);
$result = $guard->guardTypes(['intuneRoleAssignment', 'brokenFoundation'], 'compare');
expect($result['allowed_types'])->toBe([])
->and($result['unsupported_types'])->toBe(['brokenFoundation', 'intuneRoleAssignment'])
->and($result['invalid_support_types'])->toBe(['brokenFoundation'])
->and(data_get($result, 'capabilities.brokenFoundation.support_mode'))->toBe('invalid_support_config')
->and(data_get($result, 'capabilities.intuneRoleAssignment.support_mode'))->toBe('excluded');
});