mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-20 12:29:39 +00:00
NodeLibrarySidebarTabV2 was built without nodeHelpStore integration, causing 'Node Info' to open the generic node list instead of showing the selected node's help page. This mirrors the V1 pattern of conditionally rendering NodeHelpPage when isHelpOpen is true. Fixes #9996
649 lines
22 KiB
TypeScript
649 lines
22 KiB
TypeScript
import {
|
||
comfyExpect as expect,
|
||
comfyPageFixture as test
|
||
} from '@e2e/fixtures/ComfyPage'
|
||
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
|
||
import { fitToViewInstant } from '@e2e/fixtures/utils/fitToView'
|
||
import type { WorkspaceStore } from '@e2e/types/globals'
|
||
import type { NodeReference } from '@e2e/fixtures/utils/litegraphUtils'
|
||
|
||
// TODO: there might be a better solution for this
|
||
// Helper function to pan canvas and select node
|
||
async function selectNodeWithPan(comfyPage: ComfyPage, nodeRef: NodeReference) {
|
||
const nodePos = await nodeRef.getPosition()
|
||
|
||
await comfyPage.page.evaluate((pos) => {
|
||
const app = window.app!
|
||
const canvas = app.canvas
|
||
canvas.ds.offset[0] = -pos.x + canvas.canvas.width / 2
|
||
canvas.ds.offset[1] = -pos.y + canvas.canvas.height / 2 + 100
|
||
canvas.setDirty(true, true)
|
||
}, nodePos)
|
||
|
||
await comfyPage.nextFrame()
|
||
await nodeRef.click('title')
|
||
}
|
||
|
||
async function openSelectionToolboxHelp(comfyPage: ComfyPage) {
|
||
await expect(comfyPage.selectionToolbox).toBeVisible()
|
||
|
||
const helpButton = comfyPage.selectionToolbox.getByTestId('info-button')
|
||
await expect(helpButton).toBeVisible()
|
||
await helpButton.click()
|
||
await comfyPage.nextFrame()
|
||
|
||
return comfyPage.page.getByTestId('properties-panel')
|
||
}
|
||
|
||
async function setLocaleAndWaitForWorkflowReload(
|
||
comfyPage: ComfyPage,
|
||
locale: string
|
||
) {
|
||
await comfyPage.page.evaluate(async (targetLocale) => {
|
||
const workflow = (window.app!.extensionManager as WorkspaceStore).workflow
|
||
.activeWorkflow
|
||
|
||
if (!workflow) {
|
||
throw new Error('No active workflow while waiting for locale reload')
|
||
}
|
||
|
||
const changeTracker = workflow.changeTracker.constructor as unknown as {
|
||
isLoadingGraph: boolean
|
||
}
|
||
|
||
let sawLoading = false
|
||
const waitForReload = new Promise<void>((resolve, reject) => {
|
||
const timeoutAt = performance.now() + 5000
|
||
|
||
const tick = () => {
|
||
if (changeTracker.isLoadingGraph) {
|
||
sawLoading = true
|
||
}
|
||
|
||
if (sawLoading && !changeTracker.isLoadingGraph) {
|
||
resolve()
|
||
return
|
||
}
|
||
|
||
if (performance.now() > timeoutAt) {
|
||
reject(
|
||
new Error(
|
||
`Timed out waiting for workflow reload after setting locale to ${targetLocale}`
|
||
)
|
||
)
|
||
return
|
||
}
|
||
|
||
requestAnimationFrame(tick)
|
||
}
|
||
|
||
tick()
|
||
})
|
||
|
||
await window.app!.extensionManager.setting.set('Comfy.Locale', targetLocale)
|
||
await waitForReload
|
||
}, locale)
|
||
}
|
||
|
||
test.describe('Node Help V1', { tag: ['@slow', '@ui'] }, () => {
|
||
test.beforeEach(async ({ comfyPage }) => {
|
||
await comfyPage.settings.setSetting('Comfy.NodeLibrary.NewDesign', false)
|
||
})
|
||
|
||
test.describe('Selection Toolbox', () => {
|
||
test('Should open help menu for selected node', async ({ comfyPage }) => {
|
||
// Load a workflow with a node
|
||
await comfyPage.settings.setSetting('Comfy.Canvas.SelectionToolbox', true)
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
|
||
// Select a single node (KSampler) using node references
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
if (ksamplerNodes.length === 0) {
|
||
throw new Error('No KSampler nodes found in the workflow')
|
||
}
|
||
|
||
// Select the node with panning to ensure toolbox is visible
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
// Verify that the help page is shown for the correct node
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
await expect(helpPage).toContainText('KSampler')
|
||
await expect(helpPage.locator('.node-help-content')).toBeVisible()
|
||
})
|
||
})
|
||
|
||
test.describe('Node Library Sidebar', () => {
|
||
test('Should open help menu from node library', async ({ comfyPage }) => {
|
||
// Open the node library sidebar
|
||
await comfyPage.menu.nodeLibraryTab.open()
|
||
|
||
// Wait for node library to load
|
||
await expect(comfyPage.menu.nodeLibraryTab.nodeLibraryTree).toBeVisible()
|
||
|
||
// Search for KSampler to make it easier to find
|
||
await comfyPage.menu.nodeLibraryTab.nodeLibrarySearchBoxInput.fill(
|
||
'KSampler'
|
||
)
|
||
|
||
// Find the KSampler node in search results
|
||
const ksamplerNode = comfyPage.page
|
||
.locator('.tree-explorer-node-label')
|
||
.filter({ hasText: 'KSampler' })
|
||
.first()
|
||
await expect(ksamplerNode).toBeVisible()
|
||
|
||
// Hover over the node to show action buttons
|
||
await ksamplerNode.hover()
|
||
|
||
// Click the help button
|
||
const helpButton = ksamplerNode.getByRole('button', {
|
||
name: /learn more/i
|
||
})
|
||
await expect(helpButton).toBeVisible()
|
||
await helpButton.click()
|
||
|
||
// Verify that the help page is shown
|
||
const helpPage = comfyPage.page.locator('.sidebar-content-container')
|
||
await expect(helpPage).toContainText('KSampler')
|
||
await expect(helpPage.locator('.node-help-content')).toBeVisible()
|
||
})
|
||
|
||
test('Should show node library tab when clicking back from help page', async ({
|
||
comfyPage
|
||
}) => {
|
||
// Open the node library sidebar
|
||
await comfyPage.menu.nodeLibraryTab.open()
|
||
|
||
// Wait for node library to load
|
||
await expect(comfyPage.menu.nodeLibraryTab.nodeLibraryTree).toBeVisible()
|
||
|
||
// Search for KSampler
|
||
await comfyPage.menu.nodeLibraryTab.nodeLibrarySearchBoxInput.fill(
|
||
'KSampler'
|
||
)
|
||
|
||
// Find and interact with the node
|
||
const ksamplerNode = comfyPage.page
|
||
.locator('.tree-explorer-node-label')
|
||
.filter({ hasText: 'KSampler' })
|
||
.first()
|
||
await ksamplerNode.hover()
|
||
const helpButton = ksamplerNode.getByRole('button', {
|
||
name: /learn more/i
|
||
})
|
||
await helpButton.click()
|
||
|
||
// Verify help page is shown
|
||
const helpPage = comfyPage.page.locator('.sidebar-content-container')
|
||
await expect(helpPage).toContainText('KSampler')
|
||
|
||
// Click the back button - use a more specific selector
|
||
const backButton = helpPage.getByRole('button', { name: /back/i })
|
||
await backButton.click()
|
||
|
||
// Verify that we're back to the node library view
|
||
await expect(comfyPage.menu.nodeLibraryTab.nodeLibraryTree).toBeVisible()
|
||
await expect(
|
||
comfyPage.menu.nodeLibraryTab.nodeLibrarySearchBoxInput
|
||
).toBeVisible()
|
||
|
||
// Verify help page is no longer visible
|
||
await expect(helpPage.locator('.node-help-content')).toBeHidden()
|
||
})
|
||
})
|
||
|
||
test.describe('Help Content', () => {
|
||
test.beforeEach(async ({ comfyPage }) => {
|
||
await comfyPage.settings.setSetting('Comfy.Canvas.SelectionToolbox', true)
|
||
})
|
||
|
||
test('Should display loading state while fetching help', async ({
|
||
comfyPage
|
||
}) => {
|
||
// Mock slow network response
|
||
await comfyPage.page.route('**/docs/**/*.md', async (route) => {
|
||
await new Promise((resolve) => setTimeout(resolve, 1000))
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: '# Test Help Content\nThis is test help content.'
|
||
})
|
||
})
|
||
|
||
// Load workflow and select a node
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
// Verify loading spinner is shown
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
await expect(helpPage.locator('.p-progressspinner')).toBeVisible()
|
||
|
||
// Wait for content to load
|
||
await expect(helpPage).toContainText('Test Help Content')
|
||
})
|
||
|
||
test('Should display fallback content when help file not found', async ({
|
||
comfyPage
|
||
}) => {
|
||
// Mock 404 response for help files
|
||
await comfyPage.page.route('**/docs/**/*.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 404,
|
||
body: 'Not Found'
|
||
})
|
||
})
|
||
|
||
// Load workflow and select a node
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
// Verify fallback content is shown (description, inputs, outputs)
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
await expect(helpPage).toContainText('Description')
|
||
await expect(helpPage).toContainText('Inputs')
|
||
await expect(helpPage).toContainText('Outputs')
|
||
})
|
||
|
||
test('Should render markdown with images correctly', async ({
|
||
comfyPage
|
||
}) => {
|
||
// Mock response with markdown containing images
|
||
await comfyPage.page.route('**/docs/KSampler/en.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: `# KSampler Documentation
|
||
|
||

|
||

|
||
|
||
## Parameters
|
||
- **steps**: Number of steps
|
||
`
|
||
})
|
||
})
|
||
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
await expect(helpPage).toContainText('KSampler Documentation')
|
||
|
||
// Check that relative image paths are prefixed correctly
|
||
const relativeImage = helpPage.locator('img[alt="Example Image"]')
|
||
await expect(relativeImage).toBeVisible()
|
||
await expect(relativeImage).toHaveAttribute(
|
||
'src',
|
||
/.*\/docs\/KSampler\/example\.jpg/
|
||
)
|
||
|
||
// Check that absolute URLs are not modified
|
||
const externalImage = helpPage.locator('img[alt="External Image"]')
|
||
await expect(externalImage).toHaveAttribute(
|
||
'src',
|
||
'https://example.com/image.png'
|
||
)
|
||
})
|
||
|
||
test('Should render video elements with source tags in markdown', async ({
|
||
comfyPage
|
||
}) => {
|
||
// Mock response with video elements
|
||
await comfyPage.page.route('**/docs/KSampler/en.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: `# KSampler Demo
|
||
|
||
<video src="demo.mp4" controls autoplay></video>
|
||
<video src="/absolute/video.mp4" controls></video>
|
||
|
||
<video controls>
|
||
<source src="video.mp4" type="video/mp4">
|
||
<source src="https://example.com/video.webm" type="video/webm">
|
||
</video>
|
||
`
|
||
})
|
||
})
|
||
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
|
||
// Check relative video paths are prefixed
|
||
const relativeVideo = helpPage.locator('video[src*="demo.mp4"]')
|
||
await expect(relativeVideo).toBeVisible()
|
||
await expect(relativeVideo).toHaveAttribute(
|
||
'src',
|
||
/.*\/docs\/KSampler\/demo\.mp4/
|
||
)
|
||
await expect(relativeVideo).toHaveAttribute('controls', '')
|
||
await expect(relativeVideo).toHaveAttribute('autoplay', '')
|
||
|
||
// Check absolute paths are not modified
|
||
const absoluteVideo = helpPage.locator('video[src="/absolute/video.mp4"]')
|
||
await expect(absoluteVideo).toHaveAttribute('src', '/absolute/video.mp4')
|
||
|
||
// Check video source elements
|
||
const relativeVideoSource = helpPage.locator('source[src*="video.mp4"]')
|
||
await expect(relativeVideoSource).toHaveAttribute(
|
||
'src',
|
||
/.*\/docs\/KSampler\/video\.mp4/
|
||
)
|
||
|
||
const externalVideoSource = helpPage.locator(
|
||
'source[src="https://example.com/video.webm"]'
|
||
)
|
||
await expect(externalVideoSource).toHaveAttribute(
|
||
'src',
|
||
'https://example.com/video.webm'
|
||
)
|
||
})
|
||
|
||
test('Should handle custom node documentation paths', async ({
|
||
comfyPage
|
||
}) => {
|
||
// First load workflow with custom node
|
||
await comfyPage.workflow.loadWorkflow('groupnodes/group_node_v1.3.3')
|
||
|
||
// Mock custom node documentation with fallback
|
||
await comfyPage.page.route(
|
||
'**/extensions/*/docs/*/en.md',
|
||
async (route) => {
|
||
await route.fulfill({ status: 404 })
|
||
}
|
||
)
|
||
|
||
await comfyPage.page.route('**/extensions/*/docs/*.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: `# Custom Node Documentation
|
||
|
||
This is documentation for a custom node.
|
||
|
||

|
||
`
|
||
})
|
||
})
|
||
|
||
// Find and select a custom/group node
|
||
const nodeRefs = await comfyPage.page.evaluate(() => {
|
||
return window.app!.graph!.nodes.map((n) => n.id)
|
||
})
|
||
if (nodeRefs.length > 0) {
|
||
const firstNode = await comfyPage.nodeOps.getNodeRefById(nodeRefs[0])
|
||
await selectNodeWithPan(comfyPage, firstNode)
|
||
}
|
||
|
||
const helpButton = comfyPage.selectionToolbox.getByTestId('info-button')
|
||
if (await helpButton.isVisible()) {
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
await expect(helpPage).toContainText('Custom Node Documentation')
|
||
|
||
// Check image path for custom nodes
|
||
const image = helpPage.locator('img[alt="Custom Image"]')
|
||
await expect(image).toHaveAttribute(
|
||
'src',
|
||
/.*\/extensions\/.*\/docs\/assets\/custom\.png/
|
||
)
|
||
}
|
||
})
|
||
|
||
test('Should sanitize dangerous HTML content', async ({ comfyPage }) => {
|
||
// Mock response with potentially dangerous content
|
||
await comfyPage.page.route('**/docs/KSampler/en.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: `# Safe Content
|
||
|
||
<script>alert('XSS')</script>
|
||
<img src="x" onerror="alert('XSS')">
|
||
<a href="javascript:alert('XSS')">Dangerous Link</a>
|
||
<iframe src="evil.com"></iframe>
|
||
|
||
<!-- Safe content -->
|
||
<video src="safe.mp4" controls></video>
|
||
<img src="safe.jpg" alt="Safe Image">
|
||
`
|
||
})
|
||
})
|
||
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
|
||
// Dangerous elements should be removed
|
||
await expect(helpPage.locator('script')).toHaveCount(0)
|
||
await expect(helpPage.locator('iframe')).toHaveCount(0)
|
||
|
||
// Check that onerror attribute is removed
|
||
const images = helpPage.locator('img')
|
||
const imageCount = await images.count()
|
||
for (let i = 0; i < imageCount; i++) {
|
||
const img = images.nth(i)
|
||
await expect(img).not.toHaveAttribute('onerror')
|
||
}
|
||
|
||
// Check that javascript: links are sanitized
|
||
const links = helpPage.locator('a')
|
||
const linkCount = await links.count()
|
||
for (let i = 0; i < linkCount; i++) {
|
||
const link = links.nth(i)
|
||
await expect(link).not.toHaveAttribute('href', /^javascript:/i)
|
||
}
|
||
|
||
// Safe content should remain
|
||
await expect(helpPage.locator('video[src*="safe.mp4"]')).toBeVisible()
|
||
await expect(helpPage.locator('img[alt="Safe Image"]')).toBeVisible()
|
||
})
|
||
|
||
test('Should handle locale-specific documentation', async ({
|
||
comfyPage
|
||
}) => {
|
||
// Mock different responses for different locales
|
||
await comfyPage.page.route('**/docs/KSampler/ja.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: `# KSamplerノード
|
||
|
||
これは日本語のドキュメントです。
|
||
`
|
||
})
|
||
})
|
||
|
||
await comfyPage.page.route('**/docs/KSampler/en.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: `# KSampler Node
|
||
|
||
This is English documentation.
|
||
`
|
||
})
|
||
})
|
||
|
||
// Set locale to Japanese
|
||
await setLocaleAndWaitForWorkflowReload(comfyPage, 'ja')
|
||
|
||
try {
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
await expect(helpPage).toContainText('KSamplerノード')
|
||
await expect(helpPage).toContainText('これは日本語のドキュメントです')
|
||
} finally {
|
||
await setLocaleAndWaitForWorkflowReload(comfyPage, 'en')
|
||
}
|
||
})
|
||
|
||
test('Should handle network errors gracefully', async ({ comfyPage }) => {
|
||
// Mock network error
|
||
await comfyPage.page.route('**/docs/**/*.md', async (route) => {
|
||
await route.abort('failed')
|
||
})
|
||
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
|
||
// Should show fallback content (node description)
|
||
await expect(helpPage).toBeVisible()
|
||
await expect(helpPage.locator('.p-progressspinner')).toBeHidden()
|
||
|
||
// Should show some content even on error
|
||
await expect(helpPage).not.toHaveText('')
|
||
})
|
||
|
||
test('Should update help content when switching between nodes', async ({
|
||
comfyPage
|
||
}) => {
|
||
// Mock different help content for different nodes
|
||
await comfyPage.page.route('**/docs/KSampler/en.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: '# KSampler Help\n\nThis is KSampler documentation.'
|
||
})
|
||
})
|
||
|
||
await comfyPage.page.route(
|
||
'**/docs/CheckpointLoaderSimple/en.md',
|
||
async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: '# Checkpoint Loader Help\n\nThis is Checkpoint Loader documentation.'
|
||
})
|
||
}
|
||
)
|
||
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
await fitToViewInstant(comfyPage)
|
||
|
||
// Select KSampler first
|
||
const ksamplerNodes =
|
||
await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
|
||
const helpPage = await openSelectionToolboxHelp(comfyPage)
|
||
await expect(helpPage).toContainText('KSampler Help')
|
||
await expect(helpPage).toContainText('This is KSampler documentation')
|
||
|
||
// Now select Checkpoint Loader
|
||
const checkpointNodes = await comfyPage.nodeOps.getNodeRefsByType(
|
||
'CheckpointLoaderSimple'
|
||
)
|
||
await selectNodeWithPan(comfyPage, checkpointNodes[0])
|
||
|
||
// Content should update
|
||
await expect(helpPage).toContainText('Checkpoint Loader Help')
|
||
await expect(helpPage).toContainText(
|
||
'This is Checkpoint Loader documentation'
|
||
)
|
||
await expect(helpPage).not.toContainText('KSampler documentation')
|
||
})
|
||
})
|
||
})
|
||
|
||
test.describe('Node Help V2 Sidebar', { tag: ['@slow', '@ui'] }, () => {
|
||
test.beforeEach(async ({ comfyPage }) => {
|
||
await comfyPage.settings.setSetting('Comfy.NodeLibrary.NewDesign', true)
|
||
await comfyPage.settings.setSetting('Comfy.Canvas.SelectionToolbox', true)
|
||
})
|
||
|
||
async function openNodeInfoViMoreOptions(comfyPage: ComfyPage) {
|
||
await expect(comfyPage.selectionToolbox).toBeVisible()
|
||
|
||
const moreOptionsBtn = comfyPage.page.getByTestId('more-options-button')
|
||
await expect(moreOptionsBtn).toBeVisible()
|
||
await moreOptionsBtn.click()
|
||
await comfyPage.nextFrame()
|
||
|
||
const menu = comfyPage.page.locator('.p-contextmenu')
|
||
await expect(menu.getByText('Node Info', { exact: true })).toBeVisible()
|
||
await menu.getByText('Node Info', { exact: true }).click()
|
||
await comfyPage.nextFrame()
|
||
}
|
||
|
||
test('Should open node help in V2 sidebar when clicking Node Info', async ({
|
||
comfyPage
|
||
}) => {
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
|
||
const ksamplerNodes = await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
if (ksamplerNodes.length === 0) {
|
||
throw new Error('No KSampler nodes found in the workflow')
|
||
}
|
||
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
await openNodeInfoViMoreOptions(comfyPage)
|
||
|
||
const sidebarContent = comfyPage.page.locator('.sidebar-content-container')
|
||
await expect(sidebarContent).toBeVisible()
|
||
await expect(sidebarContent.locator('.node-help-content')).toBeVisible()
|
||
await expect(sidebarContent).toContainText('KSampler')
|
||
await expect(sidebarContent.getByPlaceholder('Search...')).toBeHidden()
|
||
})
|
||
|
||
test('Should return to V2 node library when clicking back from help page', async ({
|
||
comfyPage
|
||
}) => {
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
|
||
const ksamplerNodes = await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
if (ksamplerNodes.length === 0) {
|
||
throw new Error('No KSampler nodes found in the workflow')
|
||
}
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
await openNodeInfoViMoreOptions(comfyPage)
|
||
|
||
const sidebarContent = comfyPage.page.locator('.sidebar-content-container')
|
||
await expect(sidebarContent.locator('.node-help-content')).toBeVisible()
|
||
|
||
const backButton = sidebarContent.getByRole('button', {
|
||
name: /back/i
|
||
})
|
||
await backButton.click()
|
||
|
||
await expect(sidebarContent.getByPlaceholder('Search...')).toBeVisible()
|
||
await expect(sidebarContent.locator('.node-help-content')).toBeHidden()
|
||
})
|
||
|
||
test('Should show correct node info when opening help for different node types', async ({
|
||
comfyPage
|
||
}) => {
|
||
await comfyPage.page.route('**/docs/KSampler/en.md', async (route) => {
|
||
await route.fulfill({
|
||
status: 200,
|
||
body: '# KSampler Help\n\nKSampler documentation content.'
|
||
})
|
||
})
|
||
|
||
await comfyPage.workflow.loadWorkflow('default')
|
||
|
||
const ksamplerNodes = await comfyPage.nodeOps.getNodeRefsByType('KSampler')
|
||
if (ksamplerNodes.length === 0) {
|
||
throw new Error('No KSampler nodes found in the workflow')
|
||
}
|
||
await selectNodeWithPan(comfyPage, ksamplerNodes[0])
|
||
await openNodeInfoViMoreOptions(comfyPage)
|
||
|
||
const sidebarContent = comfyPage.page.locator('.sidebar-content-container')
|
||
await expect(sidebarContent).toContainText('KSampler Help')
|
||
await expect(sidebarContent).toContainText('KSampler documentation content')
|
||
})
|
||
})
|