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
159 lines
5.3 KiB
PHP
159 lines
5.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Services\Graph\GraphContractRegistry;
|
|
use App\Services\Graph\GraphLogger;
|
|
use App\Services\Graph\MicrosoftGraphClient;
|
|
use Illuminate\Http\Client\Request;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
it('includes contract select fields when listing policies', function () {
|
|
Http::fake([
|
|
'graph.microsoft.com/*' => Http::response(['value' => []], 200),
|
|
]);
|
|
|
|
$logger = mock(GraphLogger::class);
|
|
$logger->shouldReceive('logRequest')->zeroOrMoreTimes()->andReturnNull();
|
|
$logger->shouldReceive('logResponse')->zeroOrMoreTimes()->andReturnNull();
|
|
|
|
$client = new MicrosoftGraphClient(
|
|
logger: $logger,
|
|
contracts: app(GraphContractRegistry::class),
|
|
);
|
|
|
|
$client->listPolicies('endpointSecurityPolicy', [
|
|
'access_token' => 'test-token',
|
|
]);
|
|
|
|
$client->listPolicies('securityBaselinePolicy', [
|
|
'access_token' => 'test-token',
|
|
]);
|
|
|
|
$client->listPolicies('settingsCatalogPolicy', [
|
|
'access_token' => 'test-token',
|
|
]);
|
|
|
|
Http::assertSent(function (Request $request) {
|
|
$url = $request->url();
|
|
|
|
if (! str_contains($url, '/deviceManagement/configurationPolicies')) {
|
|
return false;
|
|
}
|
|
|
|
parse_str((string) parse_url($url, PHP_URL_QUERY), $query);
|
|
|
|
expect($query)->toHaveKey('$select');
|
|
|
|
$select = (string) $query['$select'];
|
|
|
|
expect($select)->toContain('technologies')
|
|
->and($select)->toContain('templateReference')
|
|
->and($select)->toContain('name')
|
|
->and($select)->not->toContain('@odata.type');
|
|
|
|
expect($select)->not->toContain('displayName');
|
|
expect($select)->not->toContain('version');
|
|
|
|
return true;
|
|
});
|
|
});
|
|
|
|
it('retries list policies without $select on select/expand parsing errors', function () {
|
|
Http::fake([
|
|
'graph.microsoft.com/*' => Http::sequence()
|
|
->push([
|
|
'error' => [
|
|
'code' => 'BadRequest',
|
|
'message' => "Parsing OData Select and Expand failed: Could not find a property named 'version' on type 'microsoft.graph.deviceManagementConfigurationPolicy'.",
|
|
],
|
|
], 400)
|
|
->push([
|
|
'error' => [
|
|
'code' => 'BadRequest',
|
|
'message' => "Parsing OData Select and Expand failed: Could not find a property named 'version' on type 'microsoft.graph.deviceManagementConfigurationPolicy'.",
|
|
],
|
|
], 400)
|
|
->push(['value' => [['id' => 'policy-1', 'name' => 'Policy One']]], 200),
|
|
]);
|
|
|
|
$logger = mock(GraphLogger::class);
|
|
$logger->shouldReceive('logRequest')->zeroOrMoreTimes()->andReturnNull();
|
|
$logger->shouldReceive('logResponse')->zeroOrMoreTimes()->andReturnNull();
|
|
|
|
$client = new MicrosoftGraphClient(
|
|
logger: $logger,
|
|
contracts: app(GraphContractRegistry::class),
|
|
);
|
|
|
|
$response = $client->listPolicies('settingsCatalogPolicy', [
|
|
'access_token' => 'test-token',
|
|
]);
|
|
|
|
expect($response->successful())->toBeTrue();
|
|
expect($response->data)->toHaveCount(1);
|
|
expect($response->warnings)->toContain('Capability fallback applied: removed $select for compatibility.');
|
|
|
|
$recorded = Http::recorded();
|
|
|
|
expect($recorded)->toHaveCount(3);
|
|
|
|
[$firstRequest] = $recorded[0];
|
|
[$secondRequest] = $recorded[1];
|
|
[$thirdRequest] = $recorded[2];
|
|
|
|
parse_str((string) parse_url($firstRequest->url(), PHP_URL_QUERY), $firstQuery);
|
|
parse_str((string) parse_url($secondRequest->url(), PHP_URL_QUERY), $secondQuery);
|
|
parse_str((string) parse_url($thirdRequest->url(), PHP_URL_QUERY), $thirdQuery);
|
|
|
|
expect($firstQuery)->toHaveKey('$select');
|
|
expect($secondQuery)->toHaveKey('$select');
|
|
expect($thirdQuery)->not->toHaveKey('$select');
|
|
});
|
|
|
|
it('paginates list policies when nextLink is present', function () {
|
|
$nextLink = 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies?$skiptoken=page2';
|
|
|
|
Http::fake([
|
|
'graph.microsoft.com/*' => Http::sequence()
|
|
->push([
|
|
'value' => [
|
|
['id' => 'policy-1', 'name' => 'Policy One'],
|
|
],
|
|
'@odata.nextLink' => $nextLink,
|
|
], 200)
|
|
->push([
|
|
'value' => [
|
|
['id' => 'policy-2', 'name' => 'Policy Two'],
|
|
],
|
|
], 200),
|
|
]);
|
|
|
|
$logger = mock(GraphLogger::class);
|
|
$logger->shouldReceive('logRequest')->zeroOrMoreTimes()->andReturnNull();
|
|
$logger->shouldReceive('logResponse')->zeroOrMoreTimes()->andReturnNull();
|
|
|
|
$client = new MicrosoftGraphClient(
|
|
logger: $logger,
|
|
contracts: app(GraphContractRegistry::class),
|
|
);
|
|
|
|
$response = $client->listPolicies('settingsCatalogPolicy', [
|
|
'access_token' => 'test-token',
|
|
]);
|
|
|
|
expect($response->successful())->toBeTrue();
|
|
expect($response->data)->toHaveCount(2);
|
|
expect(collect($response->data)->pluck('id')->all())->toMatchArray(['policy-1', 'policy-2']);
|
|
|
|
$recorded = Http::recorded();
|
|
|
|
expect($recorded)->toHaveCount(2);
|
|
|
|
[$firstRequest] = $recorded[0];
|
|
[$secondRequest] = $recorded[1];
|
|
|
|
expect($firstRequest->url())->toContain('/deviceManagement/configurationPolicies');
|
|
expect($secondRequest->url())->toBe($nextLink);
|
|
});
|