From 3a8bd1b0c55cca3ce7b8db5a2ce327352a6c14ba Mon Sep 17 00:00:00 2001 From: Maneek21 <208369276+Maneek21@users.noreply.github.com> Date: Wed, 2 Sep 2026 10:09:57 +0530 Subject: [PATCH] fix(web): prevent nested Apps mobile overflow --- .../src/app/(app)/settings/apps/apps-client.tsx | 2 +- ...form-track-a-certification-workflow.test.mjs | 1 + .../ci/app-platform-phase6-browser-smoke.mjs | 17 +++++++++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/(app)/settings/apps/apps-client.tsx b/apps/web/src/app/(app)/settings/apps/apps-client.tsx index 90cab097..fc063ebc 100644 --- a/apps/web/src/app/(app)/settings/apps/apps-client.tsx +++ b/apps/web/src/app/(app)/settings/apps/apps-client.tsx @@ -148,7 +148,7 @@ function InspectionCard({ pending, upgradeTarget, busy, onCancel, onStage }: { p function AppCard({ app, canManage, busy, onActivate, onDisable, onChooseUpgrade }: { app: AppInstallation; canManage: boolean; busy: boolean; onActivate: () => void; onDisable: () => void; onChooseUpgrade: () => void }) { const connected = app.manifest.compatibility.app_protocol !== '0'; const tone = app.state === 'active' ? 'var(--status-green)' : app.state === 'disabled' ? 'var(--outline)' : 'var(--status-amber)'; - return
+ return

{app.name}

{app.state}

{app.app_id}@{app.version}

{app.manifest.description ?? 'Declarative workspace App.'}

{app.manifest.modules.length} Module{app.manifest.modules.length === 1 ? '' : 's'} · Protocol v{app.manifest.compatibility.app_protocol} · {app.manifest.license}
diff --git a/scripts/app-platform-track-a-certification-workflow.test.mjs b/scripts/app-platform-track-a-certification-workflow.test.mjs index b3925bf0..68324cc9 100644 --- a/scripts/app-platform-track-a-certification-workflow.test.mjs +++ b/scripts/app-platform-track-a-certification-workflow.test.mjs @@ -232,6 +232,7 @@ test('the exact browser fixture is mandatory, so the Phase 6 legacy path cannot /identity\.locator\('\.\.'\)\.getByText\(state, \{ exact: true \}\)/, ); assert.doesNotMatch(browserSmoke, /card\.getByText\(state, \{ exact: true \}\)/); + assert.match(browserSmoke, /documentOverflow <= 2 && appScrollOverflow <= 2/); }); test('the exact candidate database matrix includes grants and the automation lifecycle', () => { diff --git a/scripts/ci/app-platform-phase6-browser-smoke.mjs b/scripts/ci/app-platform-phase6-browser-smoke.mjs index a887d8f4..761fbeef 100644 --- a/scripts/ci/app-platform-phase6-browser-smoke.mjs +++ b/scripts/ci/app-platform-phase6-browser-smoke.mjs @@ -730,8 +730,21 @@ async function exerciseTrackAAutomation( await automationFact(row, label).waitFor({ state: 'visible', timeout: 20_000 }); } setStage('automation_mobile_overflow'); - const overflow = await page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth); - requireCondition(overflow <= 2, 'AUTOMATION_MOBILE_HORIZONTAL_OVERFLOW'); + const [documentOverflow, appScrollOverflow] = await Promise.all([ + page.evaluate(() => document.documentElement.scrollWidth - window.innerWidth), + card.evaluate((element) => { + let ancestor = element.parentElement; + while (ancestor) { + const overflowY = getComputedStyle(ancestor).overflowY; + if (overflowY === 'auto' || overflowY === 'scroll') { + return ancestor.scrollWidth - ancestor.clientWidth; + } + ancestor = ancestor.parentElement; + } + return 0; + }), + ]); + requireCondition(documentOverflow <= 2 && appScrollOverflow <= 2, 'AUTOMATION_MOBILE_HORIZONTAL_OVERFLOW'); setStage('automation_mobile_safe_surface'); await assertSafeRenderedSurface(page, markers, 'AUTOMATION_MOBILE_MANAGEMENT'); setStage('automation_mobile_screenshot');