189 lines
6.3 KiB
PHP
189 lines
6.3 KiB
PHP
<?php
|
|
|
|
use App\Models\InventoryLink;
|
|
use App\Models\Tenant;
|
|
use App\Services\Graph\GraphClientInterface;
|
|
use App\Services\Graph\GraphResponse;
|
|
use App\Services\Inventory\InventorySyncService;
|
|
|
|
class FakeGraphClientForDeps implements GraphClientInterface
|
|
{
|
|
public function listPolicies(string $policyType, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true, [
|
|
[
|
|
'id' => 'pol-1',
|
|
'displayName' => 'Test Policy',
|
|
'assignments' => [
|
|
['target' => ['groupId' => 'group-1']],
|
|
['target' => ['groupId' => 'group-2']],
|
|
],
|
|
'roleScopeTagIds' => ['scope-tag-1', 'scope-tag-2'],
|
|
],
|
|
], 200);
|
|
}
|
|
|
|
public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true, [], 200);
|
|
}
|
|
|
|
public function getOrganization(array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true, [], 200);
|
|
}
|
|
|
|
public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true, [], 200);
|
|
}
|
|
|
|
public function getServicePrincipalPermissions(array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true, [], 200);
|
|
}
|
|
|
|
public function request(string $method, string $path, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true, [], 200);
|
|
}
|
|
}
|
|
|
|
it('extracts edges during inventory sync and marks missing appropriately', function () {
|
|
$tenant = Tenant::factory()->create();
|
|
$this->app->bind(GraphClientInterface::class, fn () => new FakeGraphClientForDeps);
|
|
|
|
$svc = app(InventorySyncService::class);
|
|
|
|
$run = $svc->syncNow($tenant, [
|
|
'policy_types' => ['deviceConfiguration'],
|
|
'categories' => [],
|
|
'include_foundations' => false,
|
|
'include_dependencies' => true,
|
|
]);
|
|
|
|
expect($run->status)->toBe('success');
|
|
|
|
$edges = InventoryLink::query()->where('tenant_id', $tenant->getKey())->get();
|
|
// 2 assigned_to + 2 scoped_by = 4
|
|
expect($edges->count())->toBe(4);
|
|
});
|
|
|
|
it('respects 50-edge limit for outbound extraction', function () {
|
|
$tenant = Tenant::factory()->create();
|
|
// Fake client returning 60 group assignments
|
|
$this->app->bind(GraphClientInterface::class, function () {
|
|
return new class implements GraphClientInterface
|
|
{
|
|
public function listPolicies(string $policyType, array $options = []): GraphResponse
|
|
{
|
|
$assignments = [];
|
|
for ($i = 1; $i <= 60; $i++) {
|
|
$assignments[] = ['target' => ['groupId' => 'g-'.$i]];
|
|
}
|
|
|
|
return new GraphResponse(true, [[
|
|
'id' => 'pol-2',
|
|
'displayName' => 'Big Assignments',
|
|
'assignments' => $assignments,
|
|
]]);
|
|
}
|
|
|
|
public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function getOrganization(array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function getServicePrincipalPermissions(array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function request(string $method, string $path, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
};
|
|
});
|
|
|
|
$svc = app(InventorySyncService::class);
|
|
$svc->syncNow($tenant, [
|
|
'policy_types' => ['deviceConfiguration'],
|
|
'categories' => [],
|
|
'include_foundations' => false,
|
|
'include_dependencies' => true,
|
|
]);
|
|
|
|
$count = InventoryLink::query()->where('tenant_id', $tenant->getKey())->count();
|
|
expect($count)->toBe(50);
|
|
});
|
|
|
|
it('persists unsupported reference warnings on the sync run record', function () {
|
|
$tenant = Tenant::factory()->create();
|
|
|
|
$this->app->bind(GraphClientInterface::class, function () {
|
|
return new class implements GraphClientInterface
|
|
{
|
|
public function listPolicies(string $policyType, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true, [[
|
|
'id' => 'pol-warn-1',
|
|
'displayName' => 'Unsupported Assignment Target',
|
|
'assignments' => [
|
|
['target' => ['filterId' => 'filter-only-no-group']],
|
|
],
|
|
]]);
|
|
}
|
|
|
|
public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function getOrganization(array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function getServicePrincipalPermissions(array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
|
|
public function request(string $method, string $path, array $options = []): GraphResponse
|
|
{
|
|
return new GraphResponse(true);
|
|
}
|
|
};
|
|
});
|
|
|
|
$svc = app(InventorySyncService::class);
|
|
$run = $svc->syncNow($tenant, [
|
|
'policy_types' => ['deviceConfiguration'],
|
|
'categories' => [],
|
|
'include_foundations' => false,
|
|
'include_dependencies' => true,
|
|
]);
|
|
|
|
$warnings = $run->error_context['warnings'] ?? null;
|
|
expect($warnings)->toBeArray()->toHaveCount(1);
|
|
expect($warnings[0]['type'] ?? null)->toBe('unsupported_reference');
|
|
|
|
expect(InventoryLink::query()->where('tenant_id', $tenant->getKey())->count())->toBe(0);
|
|
});
|