TenantAtlas/apps/platform/tests/Unit/Support/TenantConfiguration/Spec417CanonicalIdentityResolverTest.php
ahmido 8cbf1f7fe3 feat: implement canonical identity engine (#484)
Automated PR provided by Codex via Gitea API.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #484
2026-06-26 06:50:25 +00:00

98 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\TenantConfigurationResourceType;
use App\Services\TenantConfiguration\CanonicalIdentityResolver;
use App\Support\TenantConfiguration\CanonicalKeyKind;
use App\Support\TenantConfiguration\IdentityState;
use App\Support\TenantConfiguration\SourceClass;
it('Spec417 resolves stable TCM identity from provider source ids', function (): void {
$type = spec417UnitResourceType('deviceAndAppManagementAssignmentFilter', SourceClass::Tcm);
$result = app(CanonicalIdentityResolver::class)->resolve($type, [
'id' => 'assignment-filter-1',
'displayName' => 'Corporate devices',
], [
'source_contract_key' => 'assignmentFilter',
]);
expect($result->identityState)->toBe(IdentityState::Stable)
->and($result->keyKind)->toBe(CanonicalKeyKind::TcmResourceIdentifier)
->and($result->sourceResourceId)->toBe('assignment-filter-1')
->and($result->canonicalResourceKey)->toContain('deviceAndAppManagementAssignmentFilter:tcm_resource_identifier:')
->and($result->secondaryKeys['displayName'])->toBe('Corporate devices');
});
it('Spec417 resolves documented composite identity as derived instead of stable', function (): void {
$type = spec417UnitResourceType('deviceAndAppManagementAssignmentFilter', SourceClass::Tcm);
$result = app(CanonicalIdentityResolver::class)->resolve($type, [
'displayName' => 'Corporate devices',
'platform' => 'windows10AndLater',
'assignmentFilterManagementType' => 'devices',
'rule' => '(device.osVersion -startsWith "10.")',
], [
'source_contract_key' => 'assignmentFilter',
]);
expect($result->identityState)->toBe(IdentityState::Derived)
->and($result->keyKind)->toBe(CanonicalKeyKind::SourceComposite)
->and($result->derivedClaimsAllowed)->toBeFalse()
->and($result->diagnostics['reason_code'])->toBe('source_composite_identity_resolved');
});
it('Spec417 rejects display-name-only payloads as stable identity', function (): void {
$type = spec417UnitResourceType('deviceAndAppManagementAssignmentFilter', SourceClass::Tcm);
$result = app(CanonicalIdentityResolver::class)->resolve($type, [
'displayName' => 'Corporate devices',
], [
'source_contract_key' => 'assignmentFilter',
]);
expect($result->identityState)->toBe(IdentityState::MissingExternalId)
->and($result->keyKind)->toBe(CanonicalKeyKind::Unsupported)
->and($result->diagnostics['reason_code'])->toBe('missing_external_id')
->and($result->canonicalResourceKey)->not->toContain('displayName');
});
it('Spec417 keeps beta Graph identity derived and experimental', function (): void {
$type = spec417UnitResourceType('roleScopeTag', SourceClass::GraphBetaExperimental);
$result = app(CanonicalIdentityResolver::class)->resolve($type, [
'id' => 'scope-tag-1',
'displayName' => 'Pilot',
], [
'source_contract_key' => 'roleScopeTag',
'source_version' => 'beta',
]);
expect($result->identityState)->toBe(IdentityState::Derived)
->and($result->keyKind)->toBe(CanonicalKeyKind::ExperimentalSourceKey)
->and($result->derivedClaimsAllowed)->toBeFalse()
->and($result->diagnostics['reason_code'])->toBe('experimental_identity_resolved');
});
it('Spec417 marks unknown resource types as unsupported identity', function (): void {
$type = spec417UnitResourceType('unknownCanonicalType', SourceClass::Tcm);
$result = app(CanonicalIdentityResolver::class)->resolve($type, [
'id' => 'unknown-1',
]);
expect($result->identityState)->toBe(IdentityState::UnsupportedIdentity)
->and($result->keyKind)->toBe(CanonicalKeyKind::Unsupported)
->and($result->diagnostics['reason_code'])->toBe('unsupported_identity_strategy');
});
function spec417UnitResourceType(string $canonicalType, SourceClass $sourceClass): TenantConfigurationResourceType
{
return new TenantConfigurationResourceType([
'canonical_type' => $canonicalType,
'source_class' => $sourceClass->value,
]);
}