TenantAtlas/apps/platform/tests/Feature/System/CustomerHealth/CustomerHealthDashboardWidgetsTest.php
ahmido e64bae9cfc feat: cut over tenant core to managed environments (#335)
## Summary
- replace the legacy Tenant and TenantMembership core models with ManagedEnvironment and ManagedEnvironmentMembership
- propagate the managed environment naming and key changes across Filament resources, pages, controllers, jobs, models, and supporting runtime paths
- add feature 279 spec artifacts and focused managed-environment test coverage for model behavior, route binding, panel context, authorization, and legacy guardrails

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ManagedEnvironment/LegacyTenantCoreGuardTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentAuthorizationTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentPanelContextTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentRouteBindingTest.php tests/Unit/ManagedEnvironment/ManagedEnvironmentContextResolverTest.php tests/Unit/ManagedEnvironment/ManagedEnvironmentModelTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`

## Notes
- branch pushed from commit `1123b122`
- browser smoke test file was added but not run in this pass

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #335
2026-05-07 06:38:14 +00:00

186 lines
6.4 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\System\Pages\Dashboard;
use App\Filament\System\Widgets\CustomerHealthKpis;
use App\Models\Finding;
use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Models\ProductUsageEvent;
use App\Models\ProviderConnection;
use App\Models\ReviewPack;
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use App\Support\Auth\PlatformCapabilities;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\ProductTelemetry\ProductUsageEventCatalog;
use App\Support\SystemConsole\SystemConsoleWindow;
use Carbon\CarbonImmutable;
use Filament\Facades\Filament;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
uses(RefreshDatabase::class);
beforeEach(function (): void {
Filament::setCurrentPanel('system');
Filament::bootCurrentPanel();
CarbonImmutable::setTestNow(CarbonImmutable::parse('2026-04-27 12:00:00'));
});
afterEach(function (): void {
CarbonImmutable::setTestNow();
});
it('renders aggregate healthy, warning, critical, and unknown counts with a visible time-basis cue', function (): void {
actingAsCustomerHealthSystemUser();
$baselineStats = customerHealthStats(Livewire::withQueryParams([
'window' => SystemConsoleWindow::LastDay,
])->test(CustomerHealthKpis::class));
seedCustomerHealthWorkspace('Healthy Workspace');
seedCustomerHealthWorkspace('Warning Workspace', recentUsage: false, historicalUsage: true);
seedCustomerHealthWorkspace('Critical Workspace', failedRun: true);
seedCustomerHealthWorkspace('Unknown Workspace', recentRun: false, readyReviewPack: false);
$stats = customerHealthStats(Livewire::withQueryParams([
'window' => SystemConsoleWindow::LastDay,
])->test(CustomerHealthKpis::class));
expect((int) $stats['Healthy']['value'] - (int) $baselineStats['Healthy']['value'])->toBe(1)
->and($stats['Healthy']['description'])->toBe('Operational stability, review-pack readiness, and engagement freshness honor Last 24 hours.')
->and((int) $stats['Warning']['value'] - (int) $baselineStats['Warning']['value'])->toBe(1)
->and($stats['Warning']['description'])->toBe('Onboarding readiness, provider health, and governance pressure stay point-in-time.')
->and((int) $stats['Critical']['value'] - (int) $baselineStats['Critical']['value'])->toBe(1)
->and((int) $stats['Unknown']['value'] - (int) $baselineStats['Unknown']['value'])->toBe(1)
->and($stats['Unknown']['description'])->toBe('Missing or stale inputs stay explicit instead of silently reading healthy.');
});
it('registers the customer health widget on the system dashboard for authorized users', function (): void {
$user = actingAsCustomerHealthSystemUser();
$response = $this->actingAs($user, 'platform')->get(Dashboard::getUrl(panel: 'system'));
$response->assertSuccessful()
->assertSee('Customer health')
->assertSeeLivewire(CustomerHealthKpis::class);
});
/**
* @return array<string, array{value:string,description:string|null}>
*/
function customerHealthStats($component): array
{
$method = new ReflectionMethod(CustomerHealthKpis::class, 'getStats');
$method->setAccessible(true);
return collect($method->invoke($component->instance()))
->mapWithKeys(fn (Stat $stat): array => [
(string) $stat->getLabel() => [
'value' => (string) $stat->getValue(),
'description' => $stat->getDescription(),
],
])
->all();
}
function actingAsCustomerHealthSystemUser(): PlatformUser
{
$user = PlatformUser::factory()->create([
'capabilities' => [
PlatformCapabilities::ACCESS_SYSTEM_PANEL,
PlatformCapabilities::CONSOLE_VIEW,
],
'is_active' => true,
]);
test()->actingAs($user, 'platform');
return $user;
}
/**
* @return array{workspace: Workspace, tenant: ManagedEnvironment}
*/
function seedCustomerHealthWorkspace(
string $workspaceName,
bool $readyReviewPack = true,
bool $recentUsage = true,
bool $historicalUsage = false,
bool $recentRun = true,
bool $failedRun = false,
): array {
$workspace = Workspace::factory()->create(['name' => $workspaceName]);
$tenant = ManagedEnvironment::factory()->for($workspace)->create([
'name' => $workspaceName.' ManagedEnvironment',
'status' => ManagedEnvironment::STATUS_ACTIVE,
]);
ProviderConnection::factory()
->for($tenant)
->verifiedHealthy()
->create([
'workspace_id' => (int) $workspace->getKey(),
'is_default' => true,
]);
if ($readyReviewPack) {
ReviewPack::factory()
->for($tenant)
->ready()
->create([
'workspace_id' => (int) $workspace->getKey(),
'created_at' => now()->subHour(),
'generated_at' => now()->subHour(),
'expires_at' => now()->addDays(30),
]);
}
if ($recentUsage) {
ProductUsageEvent::factory()
->for($tenant)
->forEvent(ProductUsageEventCatalog::ONBOARDING_CHECKPOINT_COMPLETED)
->create([
'workspace_id' => (int) $workspace->getKey(),
'occurred_at' => now()->subMinutes(20),
]);
} elseif ($historicalUsage) {
ProductUsageEvent::factory()
->for($tenant)
->forEvent(ProductUsageEventCatalog::ONBOARDING_CHECKPOINT_COMPLETED)
->create([
'workspace_id' => (int) $workspace->getKey(),
'occurred_at' => now()->subDays(3),
]);
}
if ($recentRun) {
OperationRun::factory()
->forTenant($tenant)
->create([
'workspace_id' => (int) $workspace->getKey(),
'status' => OperationRunStatus::Completed->value,
'outcome' => $failedRun ? OperationRunOutcome::Failed->value : OperationRunOutcome::Succeeded->value,
'created_at' => now()->subMinutes(10),
'started_at' => now()->subMinutes(15),
'completed_at' => now()->subMinutes(5),
]);
}
Finding::factory()
->for($tenant)
->closed()
->create([
'severity' => Finding::SEVERITY_LOW,
]);
return [
'workspace' => $workspace,
'tenant' => $tenant,
];
}