From 8bee82496625f870273f1e68bf787b3d9d83189e Mon Sep 17 00:00:00 2001 From: ahmido Date: Sun, 22 Feb 2026 11:36:27 +0000 Subject: [PATCH] fix: restore full suite (Pest helper collision + ops-ux spec sync) (#130) ## Why `dev` full suite was hard-failing with `PHP Fatal error: Cannot redeclare function makeAssignment()` due to two Pest files defining the same global helper. Additionally, Ops-UX tests were out of sync with the new summary rendering + new whitelisted keys. ## What changed - Renamed the Entra Admin Roles test helper to `makeEntraAssignment()` to avoid global collision. - Updated Ops-UX canonical key list in `specs/055-ops-ux-rollout/spec.md` to include: - `report_created`, `report_deduped`, `alert_events_produced` - Updated `SummaryCountsWhitelistTest` to match the new summary rendering: - no `Summary:` prefix - humanized keys (`Total`, `Processed`) ## Verification - `vendor/bin/sail artisan test --compact`: - **1572 passed**, **7 skipped** (8044 assertions) Co-authored-by: Ahmed Darrazi Reviewed-on: https://git.cloudarix.de/ahmido/TenantAtlas/pulls/130 --- specs/055-ops-ux-rollout/spec.md | 2 +- .../EntraAdminRolesFindingGeneratorTest.php | 42 +++++++++---------- .../OpsUx/SummaryCountsWhitelistTest.php | 9 ++-- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/specs/055-ops-ux-rollout/spec.md b/specs/055-ops-ux-rollout/spec.md index 1f2170d..3762867 100644 --- a/specs/055-ops-ux-rollout/spec.md +++ b/specs/055-ops-ux-rollout/spec.md @@ -184,7 +184,7 @@ ### Functional Requirements ### Canonical allowed summary keys (single source of truth) The following keys are the ONLY allowed summary keys for Ops-UX rendering: -`total, processed, succeeded, failed, skipped, compliant, noncompliant, unknown, created, updated, deleted, items, tenants, high, medium, low, findings_created, findings_resolved, findings_reopened, findings_unchanged, errors_recorded, posture_score` +`total, processed, succeeded, failed, skipped, compliant, noncompliant, unknown, created, updated, deleted, items, tenants, high, medium, low, findings_created, findings_resolved, findings_reopened, findings_unchanged, errors_recorded, posture_score, report_created, report_deduped, alert_events_produced` All normalizers/renderers MUST reference this canonical list (no duplicated lists in multiple places). diff --git a/tests/Feature/EntraAdminRoles/EntraAdminRolesFindingGeneratorTest.php b/tests/Feature/EntraAdminRoles/EntraAdminRolesFindingGeneratorTest.php index d5dd023..5317e99 100644 --- a/tests/Feature/EntraAdminRoles/EntraAdminRolesFindingGeneratorTest.php +++ b/tests/Feature/EntraAdminRoles/EntraAdminRolesFindingGeneratorTest.php @@ -45,7 +45,7 @@ function readerRoleDef(): array ]; } -function makeAssignment(string $id, string $roleDefId, string $principalId, string $odataType = '#microsoft.graph.user', string $displayName = 'User', string $scopeId = '/'): array +function makeEntraAssignment(string $id, string $roleDefId, string $principalId, string $odataType = '#microsoft.graph.user', string $displayName = 'User', string $scopeId = '/'): array { return [ 'id' => $id, @@ -91,8 +91,8 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef(), secAdminRoleDef()], [ - makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin'), - makeAssignment('a2', 'def-secadmin', 'user-2', '#microsoft.graph.user', 'Bob SecAdmin'), + makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin'), + makeEntraAssignment('a2', 'def-secadmin', 'user-2', '#microsoft.graph.user', 'Bob SecAdmin'), ], ); @@ -128,8 +128,8 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef(), secAdminRoleDef()], [ - makeAssignment('a1', 'def-ga', 'user-1'), - makeAssignment('a2', 'def-secadmin', 'user-2'), + makeEntraAssignment('a1', 'def-ga', 'user-1'), + makeEntraAssignment('a2', 'def-secadmin', 'user-2'), ], ); @@ -152,7 +152,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1')], + [makeEntraAssignment('a1', 'def-ga', 'user-1')], ); $generator = makeGenerator(); @@ -179,7 +179,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator // First scan: user-1 has GA $payload1 = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1')], + [makeEntraAssignment('a1', 'def-ga', 'user-1')], ); $generator->generate($tenant, $payload1); @@ -207,7 +207,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator // Scan 1: create $payload1 = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice')], + [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice')], ); $generator->generate($tenant, $payload1); @@ -218,7 +218,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator // Scan 3: re-assign → re-open $payload3 = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Reactivated')], + [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Reactivated')], ); $result3 = $generator->generate($tenant, $payload3); @@ -242,7 +242,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $assignments = []; for ($i = 1; $i <= 6; $i++) { - $assignments[] = makeAssignment("a{$i}", 'def-ga', "user-{$i}", '#microsoft.graph.user', "GA User {$i}"); + $assignments[] = makeEntraAssignment("a{$i}", 'def-ga', "user-{$i}", '#microsoft.graph.user', "GA User {$i}"); } $payload = buildPayload([gaRoleDef()], $assignments); @@ -274,7 +274,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $assignments = []; for ($i = 1; $i <= 6; $i++) { - $assignments[] = makeAssignment("a{$i}", 'def-ga', "user-{$i}"); + $assignments[] = makeEntraAssignment("a{$i}", 'def-ga', "user-{$i}"); } $generator->generate($tenant, buildPayload([gaRoleDef()], $assignments)); @@ -301,7 +301,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1')], + [makeEntraAssignment('a1', 'def-ga', 'user-1')], ); $generator->generate($tenant, $payload); @@ -321,7 +321,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1')], + [makeEntraAssignment('a1', 'def-ga', 'user-1')], ); // Scan 1: alert events produced for new finding @@ -340,7 +340,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin')], + [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice Admin')], ); makeGenerator()->generate($tenant, $payload); @@ -378,9 +378,9 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef()], [ - makeAssignment('a1', 'def-ga', 'p-user', '#microsoft.graph.user', 'User'), - makeAssignment('a2', 'def-ga', 'p-group', '#microsoft.graph.group', 'Group'), - makeAssignment('a3', 'def-ga', 'p-sp', '#microsoft.graph.servicePrincipal', 'SP'), + makeEntraAssignment('a1', 'def-ga', 'p-user', '#microsoft.graph.user', 'User'), + makeEntraAssignment('a2', 'def-ga', 'p-group', '#microsoft.graph.group', 'Group'), + makeEntraAssignment('a3', 'def-ga', 'p-sp', '#microsoft.graph.servicePrincipal', 'SP'), ], ); @@ -403,7 +403,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1')], + [makeEntraAssignment('a1', 'def-ga', 'user-1')], ); makeGenerator()->generate($tenant, $payload); @@ -425,7 +425,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator // Scan 1: create $payload = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1')], + [makeEntraAssignment('a1', 'def-ga', 'user-1')], ); $generator->generate($tenant, $payload); @@ -454,7 +454,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [gaRoleDef()], - [makeAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice', '/administrativeUnits/au-123')], + [makeEntraAssignment('a1', 'def-ga', 'user-1', '#microsoft.graph.user', 'Alice', '/administrativeUnits/au-123')], ); makeGenerator()->generate($tenant, $payload); @@ -473,7 +473,7 @@ function makeGenerator(): EntraAdminRolesFindingGenerator $payload = buildPayload( [readerRoleDef()], - [makeAssignment('a1', 'def-reader', 'user-1')], + [makeEntraAssignment('a1', 'def-reader', 'user-1')], ); $result = makeGenerator()->generate($tenant, $payload); diff --git a/tests/Feature/OpsUx/SummaryCountsWhitelistTest.php b/tests/Feature/OpsUx/SummaryCountsWhitelistTest.php index bb62eb0..3153849 100644 --- a/tests/Feature/OpsUx/SummaryCountsWhitelistTest.php +++ b/tests/Feature/OpsUx/SummaryCountsWhitelistTest.php @@ -43,11 +43,10 @@ $body = (string) ($notification->data['body'] ?? ''); - expect($body)->toContain('Summary:'); - expect($body)->toContain('total: 10'); - expect($body)->toContain('processed: 5'); - expect($body)->not->toContain('secrets'); - expect($body)->not->toContain('failed:'); + expect($body)->toContain('Total: 10'); + expect($body)->toContain('Processed: 5'); + expect($body)->not->toContain('Secrets'); + expect($body)->not->toContain('Failed:'); })->group('ops-ux'); it('sanitizes summary_counts values and drops non-whitelisted keys', function (): void {