109 lines
8.2 KiB
PHP
109 lines
8.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Pages\TenantDashboard;
|
|
use App\Models\BackupItem;
|
|
use App\Models\BackupSet;
|
|
use App\Models\Finding;
|
|
use App\Models\OperationRun;
|
|
use App\Models\ProviderConnection;
|
|
use App\Support\OperationRunOutcome;
|
|
use App\Support\OperationRunStatus;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
|
|
pest()->browser()->timeout(20_000);
|
|
|
|
it('smokes the current tenant dashboard baseline before productization hardening', function (): void {
|
|
[$user, $tenant] = createUserWithTenant(role: 'owner', workspaceRole: 'manager');
|
|
|
|
Finding::factory()->create([
|
|
'tenant_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'finding_type' => Finding::FINDING_TYPE_DRIFT,
|
|
'severity' => Finding::SEVERITY_HIGH,
|
|
'status' => Finding::STATUS_NEW,
|
|
]);
|
|
|
|
OperationRun::factory()->create([
|
|
'tenant_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'type' => 'inventory_sync',
|
|
'status' => OperationRunStatus::Completed->value,
|
|
'outcome' => OperationRunOutcome::Failed->value,
|
|
'completed_at' => now()->subHour(),
|
|
]);
|
|
|
|
$backupSet = BackupSet::factory()->create([
|
|
'tenant_id' => (int) $tenant->getKey(),
|
|
'name' => 'Browser smoke backup',
|
|
'item_count' => 1,
|
|
'completed_at' => now()->subMinutes(30),
|
|
]);
|
|
|
|
BackupItem::factory()->create([
|
|
'tenant_id' => (int) $tenant->getKey(),
|
|
'backup_set_id' => (int) $backupSet->getKey(),
|
|
'payload' => ['id' => 'browser-smoke-policy'],
|
|
'metadata' => [],
|
|
'assignments' => [],
|
|
]);
|
|
|
|
ProviderConnection::factory()->platform()->consentGranted()->create([
|
|
'tenant_id' => (int) $tenant->getKey(),
|
|
'workspace_id' => (int) $tenant->workspace_id,
|
|
'is_default' => true,
|
|
]);
|
|
|
|
$this->actingAs($user)->withSession([
|
|
WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id,
|
|
WorkspaceContext::LAST_TENANT_IDS_SESSION_KEY => [
|
|
(string) $tenant->workspace_id => (int) $tenant->getKey(),
|
|
],
|
|
]);
|
|
|
|
$page = visit(TenantDashboard::getUrl(panel: 'tenant', tenant: $tenant))
|
|
->waitForText($tenant->name)
|
|
->waitForText('Backup posture')
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-posture-pill\"]') !== null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-context-chip-workspace\"]') !== null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-context-chip-provider\"][data-provider-key=\"microsoft\"]') !== null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-context-chip-provider-microsoft-logo\"]') !== null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-context-chip-latest-activity\"]') !== null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-context-chip-latest-activity-icon\"]') !== null", true)
|
|
->assertScript("(() => { const chips = document.querySelector('[data-testid=\"tenant-dashboard-context-chips\"]'); const firstKpi = document.querySelector('[data-testid=\"tenant-dashboard-kpi\"]'); if (! chips || ! firstKpi) return false; return chips.getBoundingClientRect().top < firstKpi.getBoundingClientRect().top; })()", true)
|
|
->assertSee('Recommended next actions')
|
|
->assertSee('Active operations')
|
|
->assertSee('Current review')
|
|
->assertSee('Risk exceptions')
|
|
->assertSee('Provider Health')
|
|
->assertSee('Customer-safe output')
|
|
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-kpi\"]').length === 4", true)
|
|
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-kpi\"][data-kpi-has-icon=\"true\"]').length === 4", true)
|
|
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-kpi\"][data-kpi-has-chart=\"true\"]').length === 2", true)
|
|
->assertScript("(() => { const rows = document.querySelectorAll('[data-testid=\"tenant-dashboard-governance-status\"]'); const icons = document.querySelectorAll('[data-testid=\"tenant-dashboard-governance-status-icon\"]'); return rows.length > 0 && rows.length === icons.length; })()", true)
|
|
->assertScript("(() => { const rows = Array.from(document.querySelectorAll('[data-testid=\"tenant-dashboard-governance-status\"]')); return rows.length > 0 && rows.every((row) => { const interactive = row.getAttribute('data-governance-interactive') === 'true'; return interactive ? row.tagName === 'A' : row.tagName === 'DIV'; }); })()", true)
|
|
->assertScript("(() => { const governance = Array.from(document.querySelectorAll('[data-testid=\"tenant-dashboard-governance-status\"]')); const operations = Array.from(document.querySelectorAll('[data-testid=\"tenant-dashboard-recent-operation\"]')); const rows = [...governance, ...operations]; return rows.length > 0 && rows.every((row) => row.getAttribute('data-overview-row-style') === 'secondary-list-row'); })()", true)
|
|
->assertScript("(() => { const interactiveGovernance = Array.from(document.querySelectorAll('[data-testid=\"tenant-dashboard-governance-status\"][data-governance-interactive=\"true\"]')); const operations = Array.from(document.querySelectorAll('[data-testid=\"tenant-dashboard-recent-operation\"]')); const rows = [...interactiveGovernance, ...operations]; return rows.length > 0 && rows.every((row) => row.className.includes('hover:shadow-md') && row.className.includes('hover:ring-1')); })()", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-kpi\"][data-kpi-key=\"high_severity_findings\"][data-kpi-has-chart=\"true\"]') !== null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-kpi\"][data-kpi-key=\"active_operations\"][data-kpi-has-chart=\"true\"]') !== null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-kpi\"][data-kpi-key=\"overdue_findings\"][data-kpi-has-chart=\"true\"]') === null", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-kpi\"][data-kpi-key=\"missing_permissions\"][data-kpi-has-chart=\"true\"]') === null", true)
|
|
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-recommended-action\"]').length <= 3", true)
|
|
->assertScript("(() => { const actions = document.querySelectorAll('[data-testid=\"tenant-dashboard-recommended-action\"]'); const icons = document.querySelectorAll('[data-testid=\"tenant-dashboard-recommended-action-icon\"]'); return actions.length === 0 || icons.length === actions.length; })()", true)
|
|
->assertScript("(() => { const rows = document.querySelectorAll('[data-testid=\"tenant-dashboard-recent-operation\"]'); const icons = document.querySelectorAll('[data-testid=\"tenant-dashboard-recent-operation-icon\"]'); return rows.length === icons.length; })()", true)
|
|
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-readiness-card\"]').length === 4", true)
|
|
->assertScript("document.querySelector('[data-testid=\"tenant-dashboard-readiness-card\"][data-readiness-key=\"provider_health\"]') !== null", true)
|
|
->assertScript("! document.body.innerHTML.includes('fixed bottom-4 right-4 z-[999999] w-96 space-y-2')", true)
|
|
->assertScript("(() => { const overview = document.querySelector('[data-testid=\"tenant-dashboard-overview\"]'); const main = document.querySelector('[data-testid=\"tenant-dashboard-overview-main\"]'); if (! overview || ! main) return false; const overviewWidth = overview.getBoundingClientRect().width; const mainWidth = main.getBoundingClientRect().width; return overviewWidth >= 600 && mainWidth >= 400; })()", true)
|
|
->assertScript("document.querySelectorAll('[data-testid=\"tenant-dashboard-overview\"] table').length === 0", true)
|
|
->assertNoJavaScriptErrors()
|
|
->assertNoConsoleLogs();
|
|
|
|
$page
|
|
->resize(430, 900)
|
|
->assertScript('window.innerWidth <= 430', true)
|
|
->assertScript('document.documentElement.scrollWidth <= window.innerWidth', true)
|
|
->assertNoJavaScriptErrors();
|
|
});
|