Skip to content

Commit 6eb8f1c

Browse files
committed
test: add browser tests for bring-node-to-front behavior
Verifies overlapping nodes come to front when: - Clicking on the node body - Clicking on a widget
1 parent 901c9f4 commit 6eb8f1c

File tree

5 files changed

+136
-0
lines changed

5 files changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import {
2+
comfyExpect as expect,
3+
comfyPageFixture as test
4+
} from '../../../../fixtures/ComfyPage'
5+
import { fitToViewInstant } from '../../../../helpers/fitToView'
6+
7+
test.describe('Vue Node Bring to Front', () => {
8+
test.beforeEach(async ({ comfyPage }) => {
9+
await comfyPage.setSetting('Comfy.UseNewMenu', 'Disabled')
10+
await comfyPage.setSetting('Comfy.VueNodes.Enabled', true)
11+
await comfyPage.loadWorkflow('vueNodes/simple-triple')
12+
await comfyPage.vueNodes.waitForNodes()
13+
await fitToViewInstant(comfyPage)
14+
})
15+
16+
/**
17+
* Helper to get the z-index of a node by its title
18+
*/
19+
async function getNodeZIndex(
20+
comfyPage: Awaited<
21+
ReturnType<(typeof test)['__dirtyFixtureLookup']>
22+
>['comfyPage'],
23+
title: string
24+
): Promise<number> {
25+
const node = comfyPage.vueNodes.getNodeByTitle(title)
26+
const style = await node.getAttribute('style')
27+
const match = style?.match(/z-index:\s*(\d+)/)
28+
return match ? parseInt(match[1], 10) : 0
29+
}
30+
31+
/**
32+
* Helper to get the bounding box center of a node
33+
*/
34+
async function getNodeCenter(
35+
comfyPage: Awaited<
36+
ReturnType<(typeof test)['__dirtyFixtureLookup']>
37+
>['comfyPage'],
38+
title: string
39+
): Promise<{ x: number; y: number }> {
40+
const node = comfyPage.vueNodes.getNodeByTitle(title)
41+
const box = await node.boundingBox()
42+
if (!box) throw new Error(`Node "${title}" not found`)
43+
return { x: box.x + box.width / 2, y: box.y + box.height / 2 }
44+
}
45+
46+
test('should bring overlapped node to front when clicking on it', async ({
47+
comfyPage
48+
}) => {
49+
// Get initial positions
50+
const clipCenter = await getNodeCenter(comfyPage, 'CLIP Text Encode')
51+
const ksamplerHeader = await comfyPage.page
52+
.getByText('KSampler')
53+
.boundingBox()
54+
if (!ksamplerHeader) throw new Error('KSampler header not found')
55+
56+
// Drag KSampler on top of CLIP Text Encode
57+
await comfyPage.dragAndDrop(
58+
{ x: ksamplerHeader.x + 50, y: ksamplerHeader.y + 10 },
59+
clipCenter
60+
)
61+
await comfyPage.nextFrame()
62+
63+
// Screenshot showing KSampler on top of CLIP
64+
await expect(comfyPage.canvas).toHaveScreenshot(
65+
'bring-to-front-overlapped-before.png'
66+
)
67+
68+
// KSampler should be on top (higher z-index) after being dragged
69+
const ksamplerZIndexBefore = await getNodeZIndex(comfyPage, 'KSampler')
70+
const clipZIndexBefore = await getNodeZIndex(comfyPage, 'CLIP Text Encode')
71+
expect(ksamplerZIndexBefore).toBeGreaterThan(clipZIndexBefore)
72+
73+
// Click on CLIP Text Encode (underneath) - need to click on a visible part
74+
// Since KSampler is on top, we click on the edge of CLIP that should still be visible
75+
const clipNode = comfyPage.vueNodes.getNodeByTitle('CLIP Text Encode')
76+
const clipBox = await clipNode.boundingBox()
77+
if (!clipBox) throw new Error('CLIP node not found')
78+
79+
// Click on the bottom-left corner of CLIP which should be visible
80+
await comfyPage.page.mouse.click(clipBox.x + 30, clipBox.y + 10)
81+
await comfyPage.nextFrame()
82+
83+
// CLIP should now be on top
84+
const clipZIndexAfter = await getNodeZIndex(comfyPage, 'CLIP Text Encode')
85+
expect(clipZIndexAfter).toBeGreaterThan(ksamplerZIndexBefore)
86+
87+
// Screenshot showing CLIP now on top
88+
await expect(comfyPage.canvas).toHaveScreenshot(
89+
'bring-to-front-overlapped-after.png'
90+
)
91+
})
92+
93+
test('should bring overlapped node to front when clicking on its widget', async ({
94+
comfyPage
95+
}) => {
96+
// Get CLIP Text Encode position (it has a text widget)
97+
const clipCenter = await getNodeCenter(comfyPage, 'CLIP Text Encode')
98+
99+
// Get VAE Decode position and drag it on top of CLIP
100+
const vaeHeader = await comfyPage.page.getByText('VAE Decode').boundingBox()
101+
if (!vaeHeader) throw new Error('VAE Decode header not found')
102+
103+
await comfyPage.dragAndDrop(
104+
{ x: vaeHeader.x + 50, y: vaeHeader.y + 10 },
105+
{ x: clipCenter.x - 50, y: clipCenter.y }
106+
)
107+
await comfyPage.nextFrame()
108+
109+
// VAE should be on top after drag
110+
const vaeZIndexBefore = await getNodeZIndex(comfyPage, 'VAE Decode')
111+
const clipZIndexBefore = await getNodeZIndex(comfyPage, 'CLIP Text Encode')
112+
expect(vaeZIndexBefore).toBeGreaterThan(clipZIndexBefore)
113+
114+
// Screenshot showing VAE on top
115+
await expect(comfyPage.canvas).toHaveScreenshot(
116+
'bring-to-front-widget-overlapped-before.png'
117+
)
118+
119+
// Click on the text widget of CLIP Text Encode
120+
const clipNode = comfyPage.vueNodes.getNodeByTitle('CLIP Text Encode')
121+
const clipBox = await clipNode.boundingBox()
122+
const textWidget = clipNode.locator('textarea').first()
123+
if (!clipBox) throw new Error('CLIP node not found')
124+
await comfyPage.page.mouse.click(clipBox.x + 170, clipBox.y + 80)
125+
await comfyPage.nextFrame()
126+
127+
// CLIP should now be on top
128+
const clipZIndexAfter = await getNodeZIndex(comfyPage, 'CLIP Text Encode')
129+
expect(clipZIndexAfter).toBeGreaterThan(vaeZIndexBefore)
130+
131+
// Screenshot showing CLIP now on top after widget click
132+
await expect(comfyPage.canvas).toHaveScreenshot(
133+
'bring-to-front-widget-overlapped-after.png'
134+
)
135+
})
136+
})
66.7 KB
Loading
69.3 KB
Loading
Loading
Loading

0 commit comments

Comments
 (0)