TenantAtlas/tests/Feature/PolicySyncEnrollmentConfigurationTypeCollisionTest.php

148 lines
4.9 KiB
PHP

<?php
use App\Models\Policy;
use App\Models\Tenant;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphResponse;
use App\Services\Intune\PolicySyncService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery\MockInterface;
uses(RefreshDatabase::class);
test('policy sync does not let enrollmentRestriction claim ESP items and reclassifies existing wrong rows', function () {
$tenant = Tenant::create([
'tenant_id' => 'tenant-sync-collision',
'name' => 'Tenant Sync Collision',
'metadata' => [],
'is_current' => true,
]);
$tenant->makeCurrent();
// Simulate an older bug: ESP row was synced under enrollmentRestriction.
$wrong = Policy::create([
'tenant_id' => $tenant->id,
'external_id' => 'esp-1',
'policy_type' => 'enrollmentRestriction',
'display_name' => 'ESP Misclassified',
'platform' => 'all',
]);
$this->mock(GraphClientInterface::class, function (MockInterface $mock) {
$espPayload = [
'id' => 'esp-1',
'displayName' => 'Enrollment Status Page',
'@odata.type' => '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration',
'deviceEnrollmentConfigurationType' => 'windows10EnrollmentCompletionPageConfiguration',
];
$mock->shouldReceive('listPolicies')
->andReturnUsing(function (string $policyType) use ($espPayload) {
if ($policyType === 'enrollmentRestriction') {
// Shared endpoint can return ESP items if unfiltered.
return new GraphResponse(true, [$espPayload]);
}
if ($policyType === 'windowsEnrollmentStatusPage') {
return new GraphResponse(true, [$espPayload]);
}
return new GraphResponse(true, []);
});
});
$service = app(PolicySyncService::class);
$service->syncPolicies($tenant, [
[
'type' => 'enrollmentRestriction',
'platform' => 'all',
'filter' => null,
],
[
'type' => 'windowsEnrollmentStatusPage',
'platform' => 'all',
'filter' => null,
],
]);
$wrong->refresh();
expect($wrong->policy_type)->toBe('windowsEnrollmentStatusPage');
});
test('policy sync classifies ESP items without relying on Graph isof filter', function () {
$tenant = Tenant::create([
'tenant_id' => 'tenant-sync-esp-no-filter',
'name' => 'Tenant Sync ESP No Filter',
'metadata' => [],
'is_current' => true,
]);
$tenant->makeCurrent();
$this->mock(GraphClientInterface::class, function (MockInterface $mock) {
$payload = [
[
'id' => 'esp-1',
'displayName' => 'Enrollment Status Page',
'@odata.type' => '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration',
'deviceEnrollmentConfigurationType' => 'windows10EnrollmentCompletionPageConfiguration',
],
[
'id' => 'restriction-1',
'displayName' => 'Default Enrollment Restriction',
'@odata.type' => '#microsoft.graph.deviceEnrollmentPlatformRestrictionConfiguration',
'deviceEnrollmentConfigurationType' => 'deviceEnrollmentPlatformRestrictionConfiguration',
],
[
'id' => 'other-1',
'displayName' => 'Other Enrollment Config',
'@odata.type' => '#microsoft.graph.someOtherEnrollmentConfiguration',
'deviceEnrollmentConfigurationType' => 'someOtherEnrollmentConfiguration',
],
];
$mock->shouldReceive('listPolicies')
->andReturnUsing(function (string $policyType) use ($payload) {
if (in_array($policyType, ['enrollmentRestriction', 'windowsEnrollmentStatusPage'], true)) {
return new GraphResponse(true, $payload);
}
return new GraphResponse(true, []);
});
});
$service = app(PolicySyncService::class);
$service->syncPolicies($tenant, [
[
'type' => 'windowsEnrollmentStatusPage',
'platform' => 'all',
'filter' => null,
],
[
'type' => 'enrollmentRestriction',
'platform' => 'all',
'filter' => null,
],
]);
$espIds = Policy::query()
->where('tenant_id', $tenant->id)
->where('policy_type', 'windowsEnrollmentStatusPage')
->pluck('external_id')
->all();
$restrictionIds = Policy::query()
->where('tenant_id', $tenant->id)
->where('policy_type', 'enrollmentRestriction')
->orderBy('external_id')
->pluck('external_id')
->all();
expect($espIds)->toMatchArray(['esp-1']);
expect($restrictionIds)->toMatchArray(['other-1', 'restriction-1']);
});