set('graph_contracts.types.deviceConfiguration', [ 'resource' => 'deviceManagement/deviceConfigurations', 'allowed_select' => ['id', 'displayName'], 'allowed_expand' => [], 'type_family' => ['#microsoft.graph.deviceConfiguration'], ]); config()->set('graph.base_url', 'https://graph.microsoft.com'); config()->set('graph.version', 'beta'); config()->set('graph.tenant_id', 'tenant'); config()->set('graph.client_id', 'client'); config()->set('graph.client_secret', 'secret'); config()->set('graph.scope', 'https://graph.microsoft.com/.default'); }); it('falls back when capability errors occur on select', function () { $callCount = 0; Http::fake([ 'https://login.microsoftonline.com/*' => Http::response([ 'access_token' => 'fake-token', 'expires_in' => 3600, ], 200), 'https://graph.microsoft.com/*' => function (Request $request) use (&$callCount) { $callCount++; if ($callCount === 1) { return Http::response([ 'error' => [ 'code' => 'Request_BadRequest', 'message' => 'Request is invalid due to $select', ], ], 400); } return Http::response(['id' => 'policy-1', 'displayName' => 'Policy'], 200); }, ]); $client = new MicrosoftGraphClient( logger: app(GraphLogger::class), contracts: app(GraphContractRegistry::class), ); $response = $client->getPolicy('deviceConfiguration', 'policy-1', [ 'select' => ['id', 'displayName', 'unsupported'], 'tenant' => 'tenant', 'access_token' => 'token', ]); expect($response->successful())->toBeTrue(); expect($callCount)->toBe(2); expect($response->warnings)->not->toBeEmpty(); });