diff --git a/core/http/react-ui/e2e/addons-runtime.spec.js b/core/http/react-ui/e2e/addons-runtime.spec.js index 23ad3ab72..e30d8cd7f 100644 --- a/core/http/react-ui/e2e/addons-runtime.spec.js +++ b/core/http/react-ui/e2e/addons-runtime.spec.js @@ -88,7 +88,8 @@ test.describe('Add-on UI runtime', () => { await expect(surface(page)).toBeVisible({ timeout: 20_000 }) await expect(page.getByTestId('fx-title')).toHaveText('Hello fixture') await expect(page.getByTestId('fx-where')).toHaveText('page=home path=') - await expect(page.locator('h1.page-title')).toHaveText('UI fixture') + // The shell draws no title over the page: the add-on draws its own. + await expect(page.locator('h1.page-title')).toHaveCount(0) // Every file came from the owner through the asset route, under one digest. const js = answers.find(a => a.url.endsWith('/ui.js')) const css = answers.find(a => a.url.endsWith('/ui/style.css')) @@ -142,8 +143,9 @@ test.describe('Add-on UI runtime', () => { return { sheet: document.querySelector('style[data-addon-style="uifixture"]')?.textContent || '', title: style(document.querySelector('[data-testid="fx-title"]')).color, - hostTitle: style(document.querySelector('h1.page-title')).color, - hostTitleSize: style(document.querySelector('h1.page-title')).fontSize, + hostNavColor: style(document.querySelector('.sidebar-nav a, .sidebar-nav button')).color, + hostNavSize: style(document.querySelector('.sidebar-nav a, .sidebar-nav button')).fontSize, + shellTitles: document.querySelectorAll('h1.page-title').length, bodyBackground: style(document.body).backgroundColor, token: style(root).getPropertyValue('--fx-token').trim(), rootToken: style(document.documentElement).getPropertyValue('--fx-token').trim(), @@ -151,8 +153,9 @@ test.describe('Add-on UI runtime', () => { } }) expect(probe.title).toBe('rgb(1, 2, 3)') - expect(probe.hostTitle).not.toBe('rgb(255, 0, 0)') - expect(probe.hostTitleSize).not.toBe('11px') + expect(probe.shellTitles).toBe(0) + expect(probe.hostNavColor).not.toBe('rgb(255, 0, 0)') + expect(probe.hostNavSize).not.toBe('11px') expect(probe.bodyBackground).not.toBe('rgb(255, 0, 255)') expect(probe.token).toBe('1') expect(probe.rootToken).toBe('') @@ -173,8 +176,8 @@ test.describe('Add-on UI runtime', () => { await expect(card).toBeVisible({ timeout: 20_000 }) await expect(card).toContainText('This add-on had a problem') await shoot(page, 'esm-error-boundary') - // The page header, the sidebar and the other routes are untouched. - await expect(page.locator('h1.page-title')).toHaveText('UI fixture') + // The sidebar and the other routes are untouched, and the shell adds no title. + await expect(page.locator('h1.page-title')).toHaveCount(0) await expect(page.locator('.sidebar-nav')).toBeVisible() await page.goto('/app/addons/uifixture/home') await expect(page.getByTestId('fx-title')).toBeVisible({ timeout: 20_000 }) @@ -328,7 +331,7 @@ test.describe('Add-on UI runtime', () => { // The router error page never replaces the host. await expect(page.getByText('Unexpected Application Error')).toHaveCount(0) await expect(page.locator('.sidebar-nav')).toBeVisible() - await expect(page.locator('h1.page-title')).toHaveText('UI fixture') + await expect(page.locator('h1.page-title')).toHaveCount(0) await layer.getByRole('button', { name: 'Close' }).last().click() await expect(layer).toHaveCount(0) } diff --git a/core/http/react-ui/e2e/addons-shell.spec.js b/core/http/react-ui/e2e/addons-shell.spec.js index f15a81b78..1df8067be 100644 --- a/core/http/react-ui/e2e/addons-shell.spec.js +++ b/core/http/react-ui/e2e/addons-shell.spec.js @@ -46,8 +46,10 @@ test.describe('Add-on shell', () => { await expect(page.getByTestId('fx-title')).toHaveText('Hello fixture') await page.getByRole('button', { name: 'Increment' }).click() await expect(surface.getByText('hooks 1')).toBeVisible() - // The sheet's `h1` rule never reaches the host's own page title. - await expect(page.locator('h1.page-title')).not.toHaveCSS('font-size', '11px') + // The shell draws no title over the add-on page, and the sheet's `h1` + // rule never reaches the host's own chrome. + await expect(page.locator('h1.page-title')).toHaveCount(0) + await expect(page.locator('.sidebar-nav a, .sidebar-nav button').first()).not.toHaveCSS('font-size', '11px') await expect(page.locator('style[data-addon-style="uifixture"]')).toHaveCount(1) // The detail view of the add-on links the declared navigation page. await page.goto('/app/addons?detail=uifixture') diff --git a/core/http/react-ui/src/addons/AddonRoute.jsx b/core/http/react-ui/src/addons/AddonRoute.jsx index 45926adbf..5d20d5114 100644 --- a/core/http/react-ui/src/addons/AddonRoute.jsx +++ b/core/http/react-ui/src/addons/AddonRoute.jsx @@ -154,7 +154,7 @@ export default function AddonRoute() { if (registry.status === 'idle' || (registry.status === 'error' && !app)) { if (registry.status === 'error') return unavailable('import_failed', reloadButton) return ( -
+
) } const isStale = Boolean(instance && instance.status === 'stale') @@ -184,7 +184,6 @@ export default function AddonRoute() { if (!instance || instance.status === 'loading') { return (
-
) @@ -193,7 +192,7 @@ export default function AddonRoute() { // survives the moment it is withdrawn. return (
- + {/* The add-on draws its own title; the shell adds none. */} {isStale && (
{t('shell.stale', { title })}