TenantAtlas/apps/platform/tests/Feature/SettingsCatalogDefinitionResolverTest.php
ahmido ce0615a9c1 Spec 182: relocate Laravel platform to apps/platform (#213)
## Summary
- move the Laravel application into `apps/platform` and keep the repository root for orchestration, docs, and tooling
- update the local command model, Sail/Docker wiring, runtime paths, and ignore rules around the new platform location
- add relocation quickstart/contracts plus focused smoke coverage for bootstrap, command model, routes, and runtime behavior

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/PlatformRelocation`
- integrated browser smoke validated `/up`, `/`, `/admin`, `/admin/choose-workspace`, and tenant route semantics for `200`, `403`, and `404`

## Remaining Rollout Checks
- validate Dokploy build context and working-directory assumptions against the new `apps/platform` layout
- confirm web, queue, and scheduler processes all start from the expected working directory in staging/production
- verify no legacy volume mounts or asset-publish paths still point at the old root-level `public/` or `storage/` locations

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #213
2026-04-08 08:40:47 +00:00

177 lines
6.1 KiB
PHP

<?php
use App\Models\SettingsCatalogDefinition;
use App\Services\Graph\GraphClientInterface;
use App\Services\Graph\GraphContractRegistry;
use App\Services\Graph\GraphResponse;
use App\Services\Intune\SettingsCatalogDefinitionResolver;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
uses(RefreshDatabase::class);
beforeEach(function () {
// Clear cache before each test
Cache::flush();
});
it('uses cached definitions from database on second call', function () {
// Arrange
$definitionId = 'device_vendor_msft_policy_config_defender_allowbehaviormonitoring';
// Pre-populate cache
SettingsCatalogDefinition::create([
'definition_id' => $definitionId,
'display_name' => 'Allow Behavior Monitoring',
'description' => 'Enable behavior monitoring',
'help_text' => 'This setting controls...',
'raw' => ['id' => $definitionId],
]);
$mockClient = Mockery::mock(GraphClientInterface::class);
// Should NOT call Graph API
$mockClient->shouldNotReceive('request');
$resolver = new SettingsCatalogDefinitionResolver($mockClient, new GraphContractRegistry);
// Act
$result = $resolver->resolve([$definitionId]);
// Assert
expect($result)->toHaveCount(1);
expect($result[$definitionId])->toMatchArray([
'displayName' => 'Allow Behavior Monitoring',
'description' => 'Enable behavior monitoring',
]);
});
it('returns fallback for missing definitions with prettified ID', function () {
// Arrange
$definitionId = 'device_vendor_msft_policy_config_unknown_setting';
$mockClient = Mockery::mock(GraphClientInterface::class);
$mockResponse = Mockery::mock(GraphResponse::class);
$mockResponse->shouldReceive('successful')->andReturn(false);
$mockClient->shouldReceive('request')
->once()
->andReturn($mockResponse);
$resolver = new SettingsCatalogDefinitionResolver($mockClient, new GraphContractRegistry);
// Act
$result = $resolver->resolve([$definitionId]);
// Assert
expect($result)->toHaveCount(1);
expect($result[$definitionId])->toMatchArray([
'displayName' => 'Device Vendor Msft Policy Config Unknown Setting',
'description' => null,
'isFallback' => true,
]);
});
it('resolveOne method returns single definition from cache', function () {
// Arrange
$definitionId = 'device_vendor_msft_policy_config_connectivity_disallownetworkconnectivityactivetest';
SettingsCatalogDefinition::create([
'definition_id' => $definitionId,
'display_name' => 'Disallow Network Connectivity Active Test',
'description' => 'Disable NCSI probes',
'raw' => ['id' => $definitionId],
]);
$mockClient = Mockery::mock(GraphClientInterface::class);
$mockClient->shouldNotReceive('request');
$resolver = new SettingsCatalogDefinitionResolver($mockClient, new GraphContractRegistry);
// Act
$result = $resolver->resolveOne($definitionId);
// Assert
expect($result)->toMatchArray([
'displayName' => 'Disallow Network Connectivity Active Test',
'description' => 'Disable NCSI probes',
]);
});
it('handles batch of definitions with mixed cached and uncached', function () {
// Arrange
$cachedId = 'device_vendor_msft_policy_config_cached_setting';
$uncachedId = 'device_vendor_msft_policy_config_uncached_setting';
// Pre-cache one definition
SettingsCatalogDefinition::create([
'definition_id' => $cachedId,
'display_name' => 'Cached Setting',
'description' => 'This was cached',
'raw' => ['id' => $cachedId],
]);
$mockClient = Mockery::mock(GraphClientInterface::class);
$mockResponse = Mockery::mock(GraphResponse::class);
$mockResponse->shouldReceive('successful')->andReturn(false);
$mockClient->shouldReceive('request')
->once()
->with('GET', "/deviceManagement/configurationSettings/{$uncachedId}")
->andReturn($mockResponse);
$resolver = new SettingsCatalogDefinitionResolver($mockClient, new GraphContractRegistry);
// Act
$result = $resolver->resolve([$cachedId, $uncachedId]);
// Assert
expect($result)->toHaveCount(2);
expect($result[$cachedId]['displayName'])->toBe('Cached Setting');
expect($result[$uncachedId]['displayName'])->toBe('Device Vendor Msft Policy Config Uncached Setting'); // Fallback
expect($result[$uncachedId]['isFallback'])->toBeTrue();
});
it('warmCache method pre-populates cache without throwing', function () {
// Arrange
$definitionId = 'device_vendor_msft_policy_config_firewall_enablefirewall';
SettingsCatalogDefinition::create([
'definition_id' => $definitionId,
'display_name' => 'Enable Firewall',
'description' => 'Turn Windows Firewall on or off',
'raw' => ['id' => $definitionId],
]);
$mockClient = Mockery::mock(GraphClientInterface::class);
$mockClient->shouldNotReceive('request');
$resolver = new SettingsCatalogDefinitionResolver($mockClient, new GraphContractRegistry);
// Act & Assert (should not throw)
expect(fn () => $resolver->warmCache([$definitionId]))->not->toThrow(Exception::class);
// Cache should be populated
$cached = SettingsCatalogDefinition::where('definition_id', $definitionId)->first();
expect($cached)->not->toBeNull();
expect($cached->display_name)->toBe('Enable Firewall');
});
it('warmCache handles errors gracefully without throwing', function () {
// Arrange
$definitionIds = ['device_vendor_msft_policy_config_test'];
$mockClient = Mockery::mock(GraphClientInterface::class);
$mockClient->shouldReceive('request')
->once()
->andThrow(new Exception('Graph API error'));
$resolver = new SettingsCatalogDefinitionResolver($mockClient, new GraphContractRegistry);
// Act & Assert (should not throw)
expect(fn () => $resolver->warmCache($definitionIds))->not->toThrow(Exception::class);
// Cache should remain empty
$cached = SettingsCatalogDefinition::where('definition_id', $definitionIds[0])->first();
expect($cached)->toBeNull();
});