Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
1061b34
style: Splitter style tailwind conversion part 1
DrJKL Dec 3, 2025
dbbc91b
cleanup: Fix focus mode in splitter, more idiomatic store/ref use
DrJKL Dec 3, 2025
e339201
cleanup: Simplify changes in TopMenuSection
DrJKL Dec 3, 2025
ef8ee69
Consistency: Open the info in the properties panel too.
DrJKL Dec 3, 2025
46b9820
cleanup: unused action
DrJKL Dec 3, 2025
35fd781
i18n: Fix Panel title pluralization
DrJKL Dec 3, 2025
9f3a270
style: Buttons
DrJKL Dec 3, 2025
684f81a
fix: Subgraph edit toggle logic
DrJKL Dec 3, 2025
f074e87
cleanup: Node Info Tab
DrJKL Dec 3, 2025
ad91453
cleanup: Parameters Accordions
DrJKL Dec 3, 2025
8bb1ca5
cleanup: Search bar, not fully there
DrJKL Dec 3, 2025
fa385b7
cleanup: Parameters and searchbox padding
DrJKL Dec 3, 2025
568cef2
cleanup: TabSettings part 1
DrJKL Dec 3, 2025
ea2e948
fix: Need a simpler way to detect when we can/should re-search
DrJKL Dec 3, 2025
65ffbfd
cleanup: TabSettings part 2
DrJKL Dec 3, 2025
09bf43f
Minimap in focus mode, but not in OG Comfy mode
DrJKL Dec 4, 2025
82b2ab1
Node state fix
DrJKL Dec 4, 2025
06a5e60
YAGNI: Accordion item properties
DrJKL Dec 4, 2025
c7ed24c
Suggested change
DrJKL Dec 4, 2025
969c357
[automated] Update test expectations
invalid-email-address Dec 4, 2025
1d4e4a9
cleanup: Button classes.
DrJKL Dec 4, 2025
d85cf45
test: Update the help panel tests
DrJKL Dec 4, 2025
3a59cf5
Consistently devolved model binding
DrJKL Dec 4, 2025
d1dc3d5
test: Remove old sidebar button expectation.
DrJKL Dec 4, 2025
b5ada2e
feat: make node title editable from Properties Panel
DrJKL Dec 4, 2025
ad03429
style: margin for searchbox to let the ring show
DrJKL Dec 4, 2025
6c36d1f
fix: Sticky header background
DrJKL Dec 4, 2025
0f37003
style: Add minimum height for some widgets
DrJKL Dec 4, 2025
73e523d
Re-add forced refresh. There are some re-render issues still.
DrJKL Dec 4, 2025
f34d988
test: Minimal properties panel Playwright test
DrJKL Dec 4, 2025
7971ce6
test: Test works! Update expectations
DrJKL Dec 5, 2025
7602911
Good rabbit suggestion
DrJKL Dec 5, 2025
7ee085b
test: Add properties panel locator to fixture, scope assertions to it.
DrJKL Dec 5, 2025
97acd83
test: Restructure actionbar locators
DrJKL Dec 5, 2025
744a29f
Fix: Focus mode on the right.
DrJKL Dec 5, 2025
c3fc13c
fix: Hide bottom gutter in focus mode
DrJKL Dec 5, 2025
6d1018a
[automated] Update test expectations
invalid-email-address Dec 5, 2025
d418b29
Title logic cleanup
DrJKL Dec 5, 2025
e978707
feat: Handle empty Inputs sections
DrJKL Dec 5, 2025
4e8f383
Yeah, I like that better.
DrJKL Dec 5, 2025
c222784
test: Also test searchbox filtering
DrJKL Dec 5, 2025
a0ed98b
Error handling while searching
DrJKL Dec 5, 2025
96e1c04
[automated] Update test expectations
invalid-email-address Dec 6, 2025
e4acaeb
type: Add generic for Tabs
DrJKL Dec 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions browser_tests/fixtures/ComfyPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,32 @@ dotenv.config()

type WorkspaceStore = ReturnType<typeof useWorkspaceStore>

class ComfyPropertiesPanel {
readonly root: Locator
readonly panelTitle: Locator
readonly searchBox: Locator

constructor(readonly page: Page) {
this.root = page.getByTestId('properties-panel')
this.panelTitle = this.root.locator('h3')
this.searchBox = this.root.getByPlaceholder('Search...')
}
}

class ComfyMenu {
private _nodeLibraryTab: NodeLibrarySidebarTab | null = null
private _workflowsTab: WorkflowsSidebarTab | null = null
private _topbar: Topbar | null = null

public readonly sideToolbar: Locator
public readonly propertiesPanel: ComfyPropertiesPanel
public readonly themeToggleButton: Locator
public readonly saveButton: Locator

constructor(public readonly page: Page) {
this.sideToolbar = page.locator('.side-tool-bar-container')
this.themeToggleButton = page.locator('.comfy-vue-theme-toggle')
this.propertiesPanel = new ComfyPropertiesPanel(page)
this.saveButton = page
.locator('button[title="Save the current workflow"]')
.nth(0)
Expand Down
8 changes: 6 additions & 2 deletions browser_tests/helpers/actionbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import type { AutoQueueMode } from '../../src/stores/queueStore'
export class ComfyActionbar {
public readonly root: Locator
public readonly queueButton: ComfyQueueButton
public readonly propertiesButton: Locator

constructor(public readonly page: Page) {
this.root = page.locator('.actionbar')
this.root = page.locator('.actionbar-container')
this.queueButton = new ComfyQueueButton(this)
this.propertiesButton = this.root.getByLabel('Toggle properties panel')
}

async isDocked() {
const className = await this.root.getAttribute('class')
const className = await this.root
.locator('.actionbar')
.getAttribute('class')
return className?.includes('static') ?? false
}
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 30 additions & 15 deletions browser_tests/tests/nodeHelp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,10 @@ test.describe('Node Help', () => {
await expect(helpButton).toBeVisible()
await helpButton.click()

// Verify that the node library sidebar is opened
await expect(
comfyPage.menu.nodeLibraryTab.selectedTabButton
).toBeVisible()

// Verify that the help page is shown for the correct node
const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)
Comment on lines +56 to +58
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Unify help panel selectors and consider a shared fixture helper

The switch to comfyPage.page.locator('[data-testid="properties-panel"]') for help content is a good move toward stable, specific selectors and matches the properties-panel refactor. However:

  • The node-library tests above still use .sidebar-content-container for help content (e.g., Lines 93–95 and 122–123). If node help is now intended to live in the properties panel for all entry points, those tests should likely assert against the same [data-testid="properties-panel"] locator for consistency and to avoid silently targeting a legacy container.
  • This locator is now repeated in many tests in this file. It would be cleaner and easier to maintain if the ComfyPage fixture exposed a propertiesPanel/helpPanel locator, and these tests reused that instead of inlining page.locator('[data-testid="properties-panel"]') everywhere.

I recommend (1) confirming whether node-library help is also rendered via the properties panel and aligning those tests accordingly, and (2) extracting a shared locator on comfyPage to deduplicate this pattern. Based on learnings, this also better follows the “prefer specific selectors in browser tests” guidance.

Also applies to: 170-172, 202-204, 237-239, 287-289, 362-364, 404-406, 473-475, 498-500, 544-546

await expect(helpPage).toContainText('KSampler')
await expect(helpPage.locator('.node-help-content')).toBeVisible()
})
Expand Down Expand Up @@ -170,7 +167,9 @@ test.describe('Node Help', () => {
await helpButton.click()

// Verify loading spinner is shown
const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)
await expect(helpPage.locator('.p-progressspinner')).toBeVisible()

// Wait for content to load
Expand Down Expand Up @@ -200,7 +199,9 @@ test.describe('Node Help', () => {
await helpButton.click()

// Verify fallback content is shown (description, inputs, outputs)
const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)
await expect(helpPage).toContainText('Description')
await expect(helpPage).toContainText('Inputs')
await expect(helpPage).toContainText('Outputs')
Expand Down Expand Up @@ -233,7 +234,9 @@ test.describe('Node Help', () => {
)
await helpButton.click()

const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)
await expect(helpPage).toContainText('KSampler Documentation')

// Check that relative image paths are prefixed correctly
Expand Down Expand Up @@ -281,7 +284,9 @@ test.describe('Node Help', () => {
)
await helpButton.click()

const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)

// Check relative video paths are prefixed
const relativeVideo = helpPage.locator('video[src*="demo.mp4"]')
Expand Down Expand Up @@ -354,7 +359,9 @@ This is documentation for a custom node.
if (await helpButton.isVisible()) {
await helpButton.click()

const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)
await expect(helpPage).toContainText('Custom Node Documentation')

// Check image path for custom nodes
Expand Down Expand Up @@ -394,7 +401,9 @@ This is documentation for a custom node.
)
await helpButton.click()

const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)

// Dangerous elements should be removed
await expect(helpPage.locator('script')).toHaveCount(0)
Expand Down Expand Up @@ -461,7 +470,9 @@ This is English documentation.
)
await helpButton.click()

const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)
await expect(helpPage).toContainText('KSamplerノード')
await expect(helpPage).toContainText('これは日本語のドキュメントです')

Expand All @@ -484,7 +495,9 @@ This is English documentation.
)
await helpButton.click()

const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)

// Should show fallback content (node description)
await expect(helpPage).toBeVisible()
Expand Down Expand Up @@ -528,7 +541,9 @@ This is English documentation.
)
await helpButton.click()

const helpPage = comfyPage.page.locator('.sidebar-content-container')
const helpPage = comfyPage.page.locator(
'[data-testid="properties-panel"]'
)
await expect(helpPage).toContainText('KSampler Help')
await expect(helpPage).toContainText('This is KSampler documentation')

Expand Down
35 changes: 35 additions & 0 deletions browser_tests/tests/propertiesPanel/propertiesPanel.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expect } from '@playwright/test'

import { comfyPageFixture as test } from '../../fixtures/ComfyPage'

test.describe('Properties panel', () => {
test('opens and updates title based on selection', async ({ comfyPage }) => {
await comfyPage.actionbar.propertiesButton.click()

const { propertiesPanel } = comfyPage.menu

await expect(propertiesPanel.panelTitle).toContainText(
'No node(s) selected'
)

await comfyPage.selectNodes(['KSampler', 'CLIP Text Encode (Prompt)'])

await expect(propertiesPanel.panelTitle).toContainText('3 nodes selected')
await expect(propertiesPanel.root.getByText('KSampler')).toHaveCount(1)
await expect(
propertiesPanel.root.getByText('CLIP Text Encode (Prompt)')
).toHaveCount(2)

await propertiesPanel.searchBox.fill('seed')
await expect(propertiesPanel.root.getByText('KSampler')).toHaveCount(1)
await expect(
propertiesPanel.root.getByText('CLIP Text Encode (Prompt)')
).toHaveCount(0)

await propertiesPanel.searchBox.fill('')
await expect(propertiesPanel.root.getByText('KSampler')).toHaveCount(1)
await expect(
propertiesPanel.root.getByText('CLIP Text Encode (Prompt)')
).toHaveCount(2)
})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading