From 76e97ddcdb515f2af781a4b146d9e47eaacdf9e2 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 17 Jul 2026 16:56:23 -0400 Subject: [PATCH] fix(ui): guard page custom-element registrations against re-registration The shared jsdom registry persists across test files under isolate:false while modules re-evaluate per file, so any page imported by two test files threw NotSupportedError at import time (ui/src/pages/usage/usage-page.test.ts started failing when gateway-source-replacement.test.ts became a second importer). All other components already guard with customElements.get; these nine pages were the only bare defines. --- ui/src/pages/about/about-page.ts | 4 +++- ui/src/pages/activity/activity-page.ts | 4 +++- ui/src/pages/config/config-page.ts | 4 +++- ui/src/pages/debug/debug-page.ts | 4 +++- ui/src/pages/memory-import/memory-import-page.ts | 4 +++- ui/src/pages/model-providers/model-providers-page.ts | 4 +++- ui/src/pages/model-setup/model-setup-page.ts | 4 +++- ui/src/pages/usage/usage-page.ts | 4 +++- ui/src/pages/worktrees/worktrees-page.ts | 4 +++- 9 files changed, 27 insertions(+), 9 deletions(-) diff --git a/ui/src/pages/about/about-page.ts b/ui/src/pages/about/about-page.ts index bb0c7c84cf94..72ef1bc1a90b 100644 --- a/ui/src/pages/about/about-page.ts +++ b/ui/src/pages/about/about-page.ts @@ -97,4 +97,6 @@ class AboutPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-about-page", AboutPage); +if (!customElements.get("openclaw-about-page")) { + customElements.define("openclaw-about-page", AboutPage); +} diff --git a/ui/src/pages/activity/activity-page.ts b/ui/src/pages/activity/activity-page.ts index 95a6f54e3de7..5522c7592461 100644 --- a/ui/src/pages/activity/activity-page.ts +++ b/ui/src/pages/activity/activity-page.ts @@ -247,4 +247,6 @@ class ActivityPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-activity-page", ActivityPage); +if (!customElements.get("openclaw-activity-page")) { + customElements.define("openclaw-activity-page", ActivityPage); +} diff --git a/ui/src/pages/config/config-page.ts b/ui/src/pages/config/config-page.ts index fa140f183088..016781775960 100644 --- a/ui/src/pages/config/config-page.ts +++ b/ui/src/pages/config/config-page.ts @@ -1002,5 +1002,7 @@ export class ConfigPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-config-page", ConfigPage); +if (!customElements.get("openclaw-config-page")) { + customElements.define("openclaw-config-page", ConfigPage); +} /* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */ diff --git a/ui/src/pages/debug/debug-page.ts b/ui/src/pages/debug/debug-page.ts index 6f4e8b818706..72999653ce0e 100644 --- a/ui/src/pages/debug/debug-page.ts +++ b/ui/src/pages/debug/debug-page.ts @@ -231,4 +231,6 @@ class DebugPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-debug-page", DebugPage); +if (!customElements.get("openclaw-debug-page")) { + customElements.define("openclaw-debug-page", DebugPage); +} diff --git a/ui/src/pages/memory-import/memory-import-page.ts b/ui/src/pages/memory-import/memory-import-page.ts index dbd4a627adc8..cf5bac096da1 100644 --- a/ui/src/pages/memory-import/memory-import-page.ts +++ b/ui/src/pages/memory-import/memory-import-page.ts @@ -353,4 +353,6 @@ export class MemoryImportPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-memory-import-page", MemoryImportPage); +if (!customElements.get("openclaw-memory-import-page")) { + customElements.define("openclaw-memory-import-page", MemoryImportPage); +} diff --git a/ui/src/pages/model-providers/model-providers-page.ts b/ui/src/pages/model-providers/model-providers-page.ts index 771ece5bc43d..c74ec7dd622e 100644 --- a/ui/src/pages/model-providers/model-providers-page.ts +++ b/ui/src/pages/model-providers/model-providers-page.ts @@ -593,4 +593,6 @@ export class ModelProvidersPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-model-providers-page", ModelProvidersPage); +if (!customElements.get("openclaw-model-providers-page")) { + customElements.define("openclaw-model-providers-page", ModelProvidersPage); +} diff --git a/ui/src/pages/model-setup/model-setup-page.ts b/ui/src/pages/model-setup/model-setup-page.ts index a81586eacc1d..578c085bb71e 100644 --- a/ui/src/pages/model-setup/model-setup-page.ts +++ b/ui/src/pages/model-setup/model-setup-page.ts @@ -526,4 +526,6 @@ export class ModelSetupPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-model-setup-page", ModelSetupPage); +if (!customElements.get("openclaw-model-setup-page")) { + customElements.define("openclaw-model-setup-page", ModelSetupPage); +} diff --git a/ui/src/pages/usage/usage-page.ts b/ui/src/pages/usage/usage-page.ts index 087b315278e9..2537d82d723d 100644 --- a/ui/src/pages/usage/usage-page.ts +++ b/ui/src/pages/usage/usage-page.ts @@ -715,4 +715,6 @@ class UsagePage extends OpenClawLightDomElement { } } -customElements.define("openclaw-usage-page", UsagePage); +if (!customElements.get("openclaw-usage-page")) { + customElements.define("openclaw-usage-page", UsagePage); +} diff --git a/ui/src/pages/worktrees/worktrees-page.ts b/ui/src/pages/worktrees/worktrees-page.ts index 2b153af9e9c5..7adefa4d5503 100644 --- a/ui/src/pages/worktrees/worktrees-page.ts +++ b/ui/src/pages/worktrees/worktrees-page.ts @@ -711,4 +711,6 @@ class WorktreesPage extends OpenClawLightDomElement { } } -customElements.define("openclaw-worktrees-page", WorktreesPage); +if (!customElements.get("openclaw-worktrees-page")) { + customElements.define("openclaw-worktrees-page", WorktreesPage); +}