From 1161fbcc4da29fbc9d0564d981f26a7355a38e8c Mon Sep 17 00:00:00 2001 From: Gandalf the Greybeard Date: Tue, 17 Mar 2026 22:42:41 +0000 Subject: [PATCH] fix(e2e): use client-side routing for settings navigation The PluginSettings component reads the plugin registry once on mount and never re-renders when new plugins register. Using page.goto() for the settings URL re-initializes the SPA, causing PluginSettings to mount before async plugin scripts finish calling registerPluginSettings(). Replace page.goto() with pushState + popstate to do client-side routing. This preserves the already-loaded plugin registrations from the main page, so PluginSettings sees the plugin immediately on mount. Co-Authored-By: Paperclip --- e2e/settings.spec.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/e2e/settings.spec.ts b/e2e/settings.spec.ts index 7a51e87..6840aad 100644 --- a/e2e/settings.spec.ts +++ b/e2e/settings.spec.ts @@ -2,10 +2,12 @@ import { test, expect, Page } from '@playwright/test'; /** Navigate to the Polaris plugin settings page and wait for settings to render. */ async function goToPolarisSettings(page: Page) { - // Load the main page first so Headlamp fetches the plugin list and stores - // it in localStorage (headlampPluginSettings). The PluginSettings component - // initializes its state from localStorage on mount, so the data must already - // be there before we navigate to the settings page. + // Load the main page first so all plugin scripts execute and call + // registerPluginSettings(). Headlamp loads plugins asynchronously — the + // PluginSettings component reads the plugin registry once on mount and + // never re-renders when new plugins register. A full page.goto() to the + // settings URL would re-initialize the SPA, causing PluginSettings to + // mount before plugin scripts finish executing. await page.goto('/'); const sidebar = page.getByRole('navigation', { name: 'Navigation' }); await expect(sidebar).toBeVisible({ timeout: 15_000 }); @@ -13,8 +15,14 @@ async function goToPolarisSettings(page: Page) { timeout: 15_000, }); - // Now navigate to plugin settings — localStorage has the plugin list - await page.goto('/c/main/settings/plugins'); + // Navigate to plugin settings via client-side routing (pushState + popstate) + // instead of page.goto(). This preserves the already-loaded plugin scripts + // and their registerPluginSettings() registrations. React Router's history + // listener picks up the popstate event and re-renders with the new route. + await page.evaluate(() => { + window.history.pushState({}, '', '/c/main/settings/plugins'); + window.dispatchEvent(new PopStateEvent('popstate', { state: {} })); + }); // Find and click the Polaris plugin entry to open its settings const pluginEntry = page.locator('text=headlamp-polaris').first();