TenantAtlas/apps/platform/tests/Unit/Support/TenantConfiguration/Spec426ExchangeTeamsSourceContractResolverTest.php
ahmido bfb52b84d6 feat: implement spec 427 source contract enablement (#494)
Automated PR for spec 427 Exchange Teams verified source contract enablement.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #494
2026-07-03 23:12:45 +00:00

57 lines
2.6 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\TenantConfigurationResourceType;
use App\Services\Graph\GraphContractRegistry;
use App\Services\TenantConfiguration\CoverageSourceContractDecision;
use App\Services\TenantConfiguration\CoverageSourceContractResolver;
use App\Services\TenantConfiguration\ResourceTypeRegistry;
use App\Support\TenantConfiguration\CaptureOutcome;
it('Spec426 blocks Exchange and Teams core capture until a verified source contract exists', function (string $canonicalType): void {
$decision = (new CoverageSourceContractResolver(new GraphContractRegistry))
->resolve(spec426ContractResourceType($canonicalType));
expect($decision->outcome)->toBe(CaptureOutcome::BlockedMissingContract)
->and($decision->reasonCode)->toBe(CoverageSourceContractDecision::CONTRACT_BLOCKED_REPO_ADAPTER_MISSING)
->and($decision->sourceContractState)->toBe(CoverageSourceContractDecision::CONTRACT_BLOCKED_REPO_ADAPTER_MISSING)
->and($decision->contractKey)->toBeNull()
->and($decision->sourceEndpoint)->toBeNull()
->and(config("graph_contracts.types.{$canonicalType}", []))->toBe([]);
})->with([
'transportRule',
'acceptedDomain',
'appPermissionPolicy',
'meetingPolicy',
]);
it('Spec426 leaves non-selected M365 resource types fail-closed without alias-derived endpoints', function (): void {
$decision = (new CoverageSourceContractResolver(new GraphContractRegistry))
->resolve(spec426ContractResourceType('dlpCompliancePolicy'));
expect($decision->outcome)->toBe(CaptureOutcome::BlockedMissingContract)
->and($decision->reasonCode)->toBe('missing_source_contract_mapping')
->and($decision->contractKey)->toBeNull()
->and($decision->sourceEndpoint)->toBeNull();
});
it('Spec426 does not register guessed Microsoft Graph endpoints for Exchange and Teams source contracts', function (): void {
$registered = array_keys((array) config('graph_contracts.types', []));
expect($registered)->not->toContain('transportRule')
->and($registered)->not->toContain('acceptedDomain')
->and($registered)->not->toContain('appPermissionPolicy')
->and($registered)->not->toContain('meetingPolicy');
});
function spec426ContractResourceType(string $canonicalType): TenantConfigurationResourceType
{
$definition = collect(ResourceTypeRegistry::defaultDefinitions())
->firstWhere('canonical_type', $canonicalType);
expect($definition)->not->toBeNull("Missing default resource type definition for {$canonicalType}.");
return new TenantConfigurationResourceType($definition);
}