## Summary - separate provider-missing policy presence from local ignore semantics by introducing `missing_from_provider_at` - update policy, backup, and restore surfaces so current-state capture stays honest while historical restore continuity remains available - add focused sync, Filament, backup, restore, localization, and badge coverage for the new provider-missing behavior ## Scope - policy sync and model truth - policy resource visibility, badges, labels, and action gating - backup/export eligibility and restore continuity messaging - spec 261 artifacts and focused tests ## Validation - feature-specific Pest coverage is included in the branch - validation was not re-run as part of this commit/push/PR handoff Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #316
196 lines
7.3 KiB
PHP
196 lines
7.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Resources\PolicyResource\Pages\ListPolicies;
|
|
use App\Filament\Resources\PolicyResource\Pages\ViewPolicy;
|
|
use App\Filament\Resources\PolicyResource\RelationManagers\VersionsRelationManager;
|
|
use App\Filament\Resources\PolicyVersionResource\Pages\ListPolicyVersions;
|
|
use App\Models\Policy;
|
|
use App\Models\PolicyVersion;
|
|
use App\Support\Badges\BadgeCatalog;
|
|
use App\Support\Badges\BadgeDomain;
|
|
use Filament\Actions\Action;
|
|
use Filament\Facades\Filament;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\App;
|
|
use Livewire\Features\SupportTesting\Testable;
|
|
use Livewire\Livewire;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
function getPolicyInventoryEmptyStateAction(Testable $component, string $name): ?Action
|
|
{
|
|
foreach ($component->instance()->getTable()->getEmptyStateActions() as $action) {
|
|
if ($action instanceof Action && $action->getName() === $name) {
|
|
return $action;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
it('renders policy inventory list copy from the active German locale', function (): void {
|
|
App::setLocale('de');
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($user);
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$component = Livewire::test(ListPolicies::class)
|
|
->assertSee(__('localization.policy.common.policies'))
|
|
->assertSee(__('localization.policy.resource.empty_state_heading'))
|
|
->assertSee(__('localization.policy.resource.empty_state_description'));
|
|
|
|
$action = getPolicyInventoryEmptyStateAction($component, 'sync');
|
|
|
|
expect($action)->not->toBeNull()
|
|
->and($action?->getLabel())->toBe(__('localization.policy.resource.sync_action_primary'));
|
|
});
|
|
|
|
it('renders source-unavailable policy labels from the active German locale', function (): void {
|
|
App::setLocale('de');
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($user);
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
Policy::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'display_name' => 'German Source Unavailable Policy',
|
|
'ignored_at' => null,
|
|
'missing_from_provider_at' => now()->subMinute(),
|
|
]);
|
|
|
|
Livewire::test(ListPolicies::class)
|
|
->set('tableFilters.visibility.value', 'provider_missing')
|
|
->assertSee(__('localization.policy.badges.source_unavailable'));
|
|
|
|
$badge = BadgeCatalog::spec(BadgeDomain::PolicyProviderPresence, 'provider_missing');
|
|
|
|
expect($badge->label)->toBe(__('localization.policy.badges.source_unavailable'));
|
|
});
|
|
|
|
it('renders policy version list copy from the active German locale', function (): void {
|
|
App::setLocale('de');
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($user);
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
Livewire::test(ListPolicyVersions::class)
|
|
->assertSee(__('localization.policy.versions.empty_state_heading'))
|
|
->assertSee(__('localization.policy.versions.empty_state_description'))
|
|
->assertSee(__('localization.policy.versions.open_backup_sets'));
|
|
});
|
|
|
|
it('renders the restore-to-Microsoft-Intune action from the active German locale', function (): void {
|
|
App::setLocale('de');
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($user);
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$policy = Policy::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
]);
|
|
|
|
PolicyVersion::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'policy_id' => $policy->getKey(),
|
|
'metadata' => [],
|
|
]);
|
|
|
|
Livewire::test(VersionsRelationManager::class, [
|
|
'ownerRecord' => $policy,
|
|
'pageClass' => ViewPolicy::class,
|
|
])->assertSee(__('localization.policy.relation.restore_to_microsoft_intune'));
|
|
});
|
|
|
|
it('renders policy version quality and related labels from the active German locale', function (): void {
|
|
App::setLocale('de');
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($user);
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$policy = Policy::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'display_name' => 'Windows Policy',
|
|
'platform' => 'all',
|
|
]);
|
|
|
|
PolicyVersion::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'policy_id' => $policy->getKey(),
|
|
'version_number' => 1,
|
|
'platform' => 'all',
|
|
'snapshot' => ['id' => 'policy-1'],
|
|
'metadata' => [],
|
|
]);
|
|
|
|
Livewire::test(ListPolicyVersions::class)
|
|
->assertSee(__('localization.policy.common.captured'))
|
|
->assertSee(__('localization.policy.versions.snapshot_mode_full'))
|
|
->assertSee(__('localization.policy.versions.compact_summary_full_payload'))
|
|
->assertSee(__('localization.policy.versions.next_action_open_version_detail'))
|
|
->assertSee(__('localization.policy.versions.related_action_view_policy'))
|
|
->assertSee(__('localization.policy.common.platform_label_all'));
|
|
});
|
|
|
|
it('renders policy detail and capture-snapshot copy from the active German locale', function (): void {
|
|
App::setLocale('de');
|
|
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($user);
|
|
$tenant->makeCurrent();
|
|
Filament::setTenant($tenant, true);
|
|
|
|
$policy = Policy::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'display_name' => 'Enrollment Notifications',
|
|
'platform' => 'all',
|
|
]);
|
|
|
|
PolicyVersion::factory()->create([
|
|
'tenant_id' => $tenant->getKey(),
|
|
'policy_id' => $policy->getKey(),
|
|
'snapshot' => [
|
|
'displayName' => 'Enrollment Notifications',
|
|
'platforms' => 'all',
|
|
'lastModifiedDateTime' => '2026-01-04T11:22:52Z',
|
|
'createdDateTime' => '2026-01-04T11:22:52Z',
|
|
],
|
|
'metadata' => [],
|
|
]);
|
|
|
|
Livewire::withQueryParams(['tab' => 'general::tab'])
|
|
->test(ViewPolicy::class, ['record' => $policy->getRouteKey()])
|
|
->assertSee(__('localization.policy.resource.capture_snapshot_action'))
|
|
->assertSee(__('localization.policy.resource.details_section'))
|
|
->assertSee(__('localization.policy.resource.tab_general'))
|
|
->assertSee(__('localization.policy.resource.general_field_platforms'))
|
|
->assertSee(__('localization.policy.common.platform_label_all'))
|
|
->assertSee(__('localization.policy.resource.general_field_last_modified'))
|
|
->assertSee(__('localization.policy.resource.general_field_created'));
|
|
|
|
Livewire::test(ViewPolicy::class, ['record' => $policy->getRouteKey()])
|
|
->assertActionExists('capture_snapshot', function (Action $action): bool {
|
|
return $action->getLabel() === __('localization.policy.resource.capture_snapshot_action')
|
|
&& $action->isConfirmationRequired()
|
|
&& (string) $action->getModalHeading() === __('localization.policy.resource.capture_snapshot_modal_heading')
|
|
&& str_contains((string) $action->getModalDescription(), __('localization.policy.resource.capture_snapshot_modal_subheading'))
|
|
&& str_contains((string) $action->getModalDescription(), __('localization.policy.common.source_microsoft_intune'));
|
|
});
|
|
}); |