What Changed Removed per-file uses(TestCase::class ...) bindings in Unit tests to avoid Pest v4 “folder already uses the test case” discovery failure (kept RefreshDatabase where needed). Updated the backup scheduling job test to pass the newly required BulkOperationService when manually calling RunBackupScheduleJob::handle(). Where Unit (bulk cleanup across 56 files) RunBackupScheduleJobTest.php Verification ./vendor/bin/sail test → 443 passed, 5 skipped Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #45
238 lines
6.9 KiB
PHP
238 lines
6.9 KiB
PHP
<?php
|
|
|
|
use App\Services\Graph\AssignmentFetcher;
|
|
use App\Services\Graph\GraphContractRegistry;
|
|
use App\Services\Graph\GraphException;
|
|
use App\Services\Graph\GraphResponse;
|
|
use App\Services\Graph\MicrosoftGraphClient;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
beforeEach(function () {
|
|
$this->graphClient = Mockery::mock(MicrosoftGraphClient::class);
|
|
$this->fetcher = new AssignmentFetcher($this->graphClient, app(GraphContractRegistry::class));
|
|
});
|
|
|
|
test('primary endpoint success', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'settingsCatalogPolicy';
|
|
$assignments = [
|
|
['id' => 'assign-1', 'target' => ['@odata.type' => '#microsoft.graph.groupAssignmentTarget', 'groupId' => 'group-1']],
|
|
['id' => 'assign-2', 'target' => ['@odata.type' => '#microsoft.graph.groupAssignmentTarget', 'groupId' => 'group-2']],
|
|
];
|
|
|
|
$response = new GraphResponse(
|
|
success: true,
|
|
data: ['value' => $assignments]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', "/deviceManagement/configurationPolicies/{$policyId}/assignments", [
|
|
'tenant' => $tenantId,
|
|
])
|
|
->andReturn($response);
|
|
|
|
$result = $this->fetcher->fetch($policyType, $tenantId, $policyId);
|
|
|
|
expect($result)->toBe($assignments);
|
|
});
|
|
|
|
test('app protection uses derived assignments list endpoint', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'appProtectionPolicy';
|
|
$assignments = [
|
|
['id' => 'assign-1', 'target' => ['@odata.type' => '#microsoft.graph.groupAssignmentTarget', 'groupId' => 'group-1']],
|
|
];
|
|
|
|
$response = new GraphResponse(
|
|
success: true,
|
|
data: ['value' => $assignments]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', "/deviceAppManagement/androidManagedAppProtections/{$policyId}/assignments", [
|
|
'tenant' => $tenantId,
|
|
])
|
|
->andReturn($response);
|
|
|
|
$result = $this->fetcher->fetch(
|
|
$policyType,
|
|
$tenantId,
|
|
$policyId,
|
|
[],
|
|
false,
|
|
'#microsoft.graph.androidManagedAppProtection'
|
|
);
|
|
|
|
expect($result)->toBe($assignments);
|
|
});
|
|
|
|
test('does not use fallback when primary succeeds with empty assignments', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'settingsCatalogPolicy';
|
|
|
|
$primaryResponse = new GraphResponse(
|
|
success: true,
|
|
data: ['value' => []]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', "/deviceManagement/configurationPolicies/{$policyId}/assignments", [
|
|
'tenant' => $tenantId,
|
|
])
|
|
->andReturn($primaryResponse);
|
|
|
|
$result = $this->fetcher->fetch($policyType, $tenantId, $policyId);
|
|
|
|
expect($result)->toBe([]);
|
|
});
|
|
|
|
test('uses fallback when primary endpoint fails', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'settingsCatalogPolicy';
|
|
$assignments = [
|
|
['id' => 'assign-1', 'target' => ['@odata.type' => '#microsoft.graph.groupAssignmentTarget', 'groupId' => 'group-1']],
|
|
];
|
|
|
|
$primaryFailure = new GraphResponse(
|
|
success: false,
|
|
data: [],
|
|
status: 400,
|
|
errors: [['message' => 'Bad Request']]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', "/deviceManagement/configurationPolicies/{$policyId}/assignments", [
|
|
'tenant' => $tenantId,
|
|
])
|
|
->andReturn($primaryFailure);
|
|
|
|
$fallbackResponse = new GraphResponse(
|
|
success: true,
|
|
data: ['value' => [['id' => $policyId, 'assignments' => $assignments]]]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', 'deviceManagement/configurationPolicies', [
|
|
'tenant' => $tenantId,
|
|
'query' => [
|
|
'$expand' => 'assignments',
|
|
'$filter' => "id eq '{$policyId}'",
|
|
],
|
|
])
|
|
->andReturn($fallbackResponse);
|
|
|
|
$result = $this->fetcher->fetch($policyType, $tenantId, $policyId);
|
|
|
|
expect($result)->toBe($assignments);
|
|
});
|
|
|
|
test('fail soft on error', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'settingsCatalogPolicy';
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->twice()
|
|
->andThrow(new GraphException('Graph API error', 500, ['request_id' => 'request-id-123']));
|
|
|
|
$result = $this->fetcher->fetch($policyType, $tenantId, $policyId);
|
|
|
|
expect($result)->toBe([]);
|
|
});
|
|
|
|
test('returns empty array when both endpoints return empty', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'settingsCatalogPolicy';
|
|
|
|
// Primary returns empty
|
|
$primaryResponse = new GraphResponse(
|
|
success: true,
|
|
data: ['value' => []]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', "/deviceManagement/configurationPolicies/{$policyId}/assignments", Mockery::any())
|
|
->andReturn($primaryResponse);
|
|
|
|
$result = $this->fetcher->fetch($policyType, $tenantId, $policyId);
|
|
|
|
expect($result)->toBe([]);
|
|
});
|
|
|
|
test('fallback handles missing assignments key', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'settingsCatalogPolicy';
|
|
|
|
$primaryResponse = new GraphResponse(
|
|
success: false,
|
|
data: ['value' => []]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->andReturn($primaryResponse);
|
|
|
|
// Fallback returns policy without assignments key
|
|
$fallbackResponse = new GraphResponse(
|
|
success: true,
|
|
data: ['value' => [['id' => $policyId]]]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->andReturn($fallbackResponse);
|
|
|
|
$result = $this->fetcher->fetch($policyType, $tenantId, $policyId);
|
|
|
|
expect($result)->toBe([]);
|
|
});
|
|
|
|
test('throws when both endpoints fail with throwOnFailure enabled', function () {
|
|
$tenantId = 'tenant-123';
|
|
$policyId = 'policy-456';
|
|
$policyType = 'settingsCatalogPolicy';
|
|
|
|
$failureResponse = new GraphResponse(
|
|
success: false,
|
|
data: [],
|
|
status: 403,
|
|
errors: [['message' => 'Forbidden']]
|
|
);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', "/deviceManagement/configurationPolicies/{$policyId}/assignments", Mockery::any())
|
|
->andReturn($failureResponse);
|
|
|
|
$this->graphClient
|
|
->shouldReceive('request')
|
|
->once()
|
|
->with('GET', 'deviceManagement/configurationPolicies', Mockery::any())
|
|
->andReturn($failureResponse);
|
|
|
|
$this->fetcher->fetch($policyType, $tenantId, $policyId, [], true);
|
|
})->throws(GraphException::class);
|