diff --git a/browser_tests/tests/nodeHelp.spec.ts b/browser_tests/tests/nodeHelp.spec.ts
index 93da58310d..ec14dc3b6f 100644
--- a/browser_tests/tests/nodeHelp.spec.ts
+++ b/browser_tests/tests/nodeHelp.spec.ts
@@ -553,12 +553,6 @@ This is English documentation.
)
await selectNodeWithPan(comfyPage, checkpointNodes[0])
- // Click help button again
- const helpButton2 = comfyPage.page.locator(
- '.selection-toolbox button[data-testid="info-button"]'
- )
- await helpButton2.click()
-
// Content should update
await expect(helpPage).toContainText('Checkpoint Loader Help')
await expect(helpPage).toContainText(
diff --git a/src/components/sidebar/tabs/nodeLibrary/NodeHelpPage.vue b/src/components/sidebar/tabs/nodeLibrary/NodeHelpPage.vue
index 4adcf71c41..2c12089f15 100644
--- a/src/components/sidebar/tabs/nodeLibrary/NodeHelpPage.vue
+++ b/src/components/sidebar/tabs/nodeLibrary/NodeHelpPage.vue
@@ -19,14 +19,31 @@
diff --git a/src/composables/graph/useSelectionState.ts b/src/composables/graph/useSelectionState.ts
index 23268ba2a6..5848eafb42 100644
--- a/src/composables/graph/useSelectionState.ts
+++ b/src/composables/graph/useSelectionState.ts
@@ -105,12 +105,11 @@ export function useSelectionState() {
const isSidebarActive =
sidebarTabStore.activeSidebarTabId === nodeLibraryTabId
- const currentHelpNode: any = nodeHelpStore.currentHelpNode
+ const currentHelpNode = nodeHelpStore.currentHelpNode
const isSameNodeHelpOpen =
isSidebarActive &&
nodeHelpStore.isHelpOpen &&
- currentHelpNode &&
- currentHelpNode.nodePath === def.nodePath
+ currentHelpNode?.nodePath === def.nodePath
if (isSameNodeHelpOpen) {
nodeHelpStore.closeHelp()
diff --git a/tests-ui/tests/components/sidebar/nodeLibrary/NodeHelpPage.test.ts b/tests-ui/tests/components/sidebar/nodeLibrary/NodeHelpPage.test.ts
new file mode 100644
index 0000000000..d164d5a053
--- /dev/null
+++ b/tests-ui/tests/components/sidebar/nodeLibrary/NodeHelpPage.test.ts
@@ -0,0 +1,97 @@
+import { flushPromises, mount } from '@vue/test-utils'
+import { computed, ref } from 'vue'
+import { beforeEach, describe, expect, test, vi } from 'vitest'
+
+import NodeHelpPage from '@/components/sidebar/tabs/nodeLibrary/NodeHelpPage.vue'
+import { useSelectionState } from '@/composables/graph/useSelectionState'
+import { useNodeHelpStore } from '@/stores/workspace/nodeHelpStore'
+
+vi.mock('@/composables/graph/useSelectionState')
+vi.mock('@/stores/workspace/nodeHelpStore')
+
+const baseNode = {
+ nodePath: 'NodeA',
+ display_name: 'Node A',
+ description: '',
+ inputs: {},
+ outputs: []
+}
+
+describe('NodeHelpPage', () => {
+ const selection = ref(null)
+ let openHelp: ReturnType
+
+ const mountPage = () =>
+ mount(NodeHelpPage, {
+ props: { node: baseNode as any },
+ global: {
+ stubs: {
+ ProgressSpinner: true,
+ Button: true
+ }
+ }
+ })
+
+ beforeEach(() => {
+ vi.resetAllMocks()
+ selection.value = null
+ openHelp = vi.fn()
+
+ vi.mocked(useSelectionState).mockReturnValue({
+ nodeDef: computed(() => selection.value)
+ } as any)
+
+ vi.mocked(useNodeHelpStore).mockReturnValue({
+ renderedHelpHtml: ref('help
'),
+ isLoading: ref(false),
+ error: ref(null),
+ isHelpOpen: true,
+ currentHelpNode: { nodePath: 'NodeA' },
+ openHelp,
+ closeHelp: vi.fn()
+ } as any)
+ })
+
+ test('opens help for a newly selected node while help is open', async () => {
+ const wrapper = mountPage()
+
+ selection.value = { nodePath: 'NodeB' }
+ await flushPromises()
+
+ expect(openHelp).toHaveBeenCalledWith({ nodePath: 'NodeB' })
+
+ wrapper.unmount()
+ })
+
+ test('does not reopen help when the same node stays selected', async () => {
+ const wrapper = mountPage()
+
+ selection.value = { nodePath: 'NodeA' }
+ await flushPromises()
+
+ expect(openHelp).not.toHaveBeenCalled()
+
+ wrapper.unmount()
+ })
+
+ test('does not react to selection when help is closed', async () => {
+ vi.mocked(useNodeHelpStore).mockReturnValueOnce({
+ renderedHelpHtml: ref('help
'),
+ isLoading: ref(false),
+ error: ref(null),
+ isHelpOpen: false,
+ currentHelpNode: null,
+ openHelp,
+ closeHelp: vi.fn()
+ } as any)
+
+ const wrapper = mountPage()
+
+ selection.value = { nodePath: 'NodeB' }
+ await flushPromises()
+
+ expect(openHelp).not.toHaveBeenCalled()
+
+ wrapper.unmount()
+ })
+})
diff --git a/tests-ui/tests/composables/graph/useSelectionState.test.ts b/tests-ui/tests/composables/graph/useSelectionState.test.ts
index ccab3054f7..cf0e4bd841 100644
--- a/tests-ui/tests/composables/graph/useSelectionState.test.ts
+++ b/tests-ui/tests/composables/graph/useSelectionState.test.ts
@@ -1,6 +1,7 @@
import { createPinia, setActivePinia } from 'pinia'
import { beforeEach, describe, expect, test, vi } from 'vitest'
-import { type Ref, ref } from 'vue'
+import { ref } from 'vue'
+import type { Ref } from 'vue'
import { useSelectionState } from '@/composables/graph/useSelectionState'
import { useNodeLibrarySidebarTab } from '@/composables/sidebarTabs/useNodeLibrarySidebarTab'