diff --git a/browser_tests/tests/domWidget.spec.ts b/browser_tests/tests/domWidget.spec.ts index 4ff305e1a..288ed078a 100644 --- a/browser_tests/tests/domWidget.spec.ts +++ b/browser_tests/tests/domWidget.spec.ts @@ -1,15 +1,35 @@ import { expect } from '@playwright/test' import { comfyPageFixture as test } from '../fixtures/ComfyPage' +import { PerformanceMonitor } from '../helpers/performanceMonitor' test.describe('DOM Widget', () => { - test('Collapsed multiline textarea is not visible', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('collapsed_multiline') + test('@perf Collapsed multiline textarea is not visible', async ({ + comfyPage + }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'collapsed-multiline-textarea-visibility' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('collapsed_multiline') + }) + const textareaWidget = comfyPage.page.locator('.comfy-multiline-input') await expect(textareaWidget).not.toBeVisible() + + await perfMonitor.finishMonitoring(testName) }) - test('Multiline textarea correctly collapses', async ({ comfyPage }) => { + test('@perf Multiline textarea correctly collapses', async ({ + comfyPage + }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'multiline-textarea-collapse' + + await perfMonitor.startMonitoring(testName) + const multilineTextAreas = comfyPage.page.locator('.comfy-multiline-input') const firstMultiline = multilineTextAreas.first() const lastMultiline = multilineTextAreas.last() @@ -17,34 +37,90 @@ test.describe('DOM Widget', () => { await expect(firstMultiline).toBeVisible() await expect(lastMultiline).toBeVisible() - const nodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') - for (const node of nodes) { - await node.click('collapse') - } + let nodes: any[] + await perfMonitor.measureOperation('get-nodes-by-type', async () => { + nodes = await comfyPage.getNodeRefsByType('CLIPTextEncode') + }) + + await perfMonitor.markEvent('before-collapse') + + await perfMonitor.measureOperation('collapse-all-nodes', async () => { + for (const node of nodes!) { + await node.click('collapse') + } + }) + + await perfMonitor.markEvent('after-collapse') + await expect(firstMultiline).not.toBeVisible() await expect(lastMultiline).not.toBeVisible() + + await perfMonitor.finishMonitoring(testName) }) - test('Position update when entering focus mode', async ({ comfyPage }) => { - await comfyPage.setSetting('Comfy.UseNewMenu', 'Top') - await comfyPage.executeCommand('Workspace.ToggleFocusMode') - await comfyPage.nextFrame() + test('@perf Position update when entering focus mode', async ({ + comfyPage + }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'focus-mode-position-update' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('set-menu-setting', async () => { + await comfyPage.setSetting('Comfy.UseNewMenu', 'Top') + }) + + await perfMonitor.measureOperation('toggle-focus-mode', async () => { + await comfyPage.executeCommand('Workspace.ToggleFocusMode') + }) + + await perfMonitor.measureOperation('wait-frame-update', async () => { + await comfyPage.nextFrame() + }) + await expect(comfyPage.canvas).toHaveScreenshot('focus-mode-on.png') + + await perfMonitor.finishMonitoring(testName) }) // No DOM widget should be created by creation of interim LGraphNode objects. - test('Copy node with DOM widget by dragging + alt', async ({ comfyPage }) => { - const initialCount = await comfyPage.getDOMWidgetCount() + test('@perf Copy node with DOM widget by dragging + alt', async ({ + comfyPage + }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'copy-node-alt-drag' + + await perfMonitor.startMonitoring(testName) + + let initialCount: number + await perfMonitor.measureOperation('get-initial-widget-count', async () => { + initialCount = await comfyPage.getDOMWidgetCount() + }) + + await perfMonitor.markEvent('before-copy-operation') // TextEncodeNode1 - await comfyPage.page.mouse.move(618, 191) - await comfyPage.page.keyboard.down('Alt') - await comfyPage.page.mouse.down() - await comfyPage.page.mouse.move(100, 100) - await comfyPage.page.mouse.up() - await comfyPage.page.keyboard.up('Alt') + await perfMonitor.measureOperation('position-mouse-on-node', async () => { + await comfyPage.page.mouse.move(618, 191) + }) - const finalCount = await comfyPage.getDOMWidgetCount() - expect(finalCount).toBe(initialCount + 1) + await perfMonitor.measureOperation('alt-drag-copy', async () => { + await comfyPage.page.keyboard.down('Alt') + await comfyPage.page.mouse.down() + await comfyPage.page.mouse.move(100, 100) + await comfyPage.page.mouse.up() + await comfyPage.page.keyboard.up('Alt') + }) + + await perfMonitor.markEvent('after-copy-operation') + + let finalCount: number + await perfMonitor.measureOperation('get-final-widget-count', async () => { + finalCount = await comfyPage.getDOMWidgetCount() + }) + + expect(finalCount!).toBe(initialCount! + 1) + + await perfMonitor.finishMonitoring(testName) }) }) diff --git a/browser_tests/tests/litegraphEvent.spec.ts b/browser_tests/tests/litegraphEvent.spec.ts index 8d8f6c2e8..e03ab068a 100644 --- a/browser_tests/tests/litegraphEvent.spec.ts +++ b/browser_tests/tests/litegraphEvent.spec.ts @@ -1,6 +1,7 @@ import { expect } from '@playwright/test' import { comfyPageFixture as test } from '../fixtures/ComfyPage' +import { PerformanceMonitor } from '../helpers/performanceMonitor' function listenForEvent(): Promise { return new Promise((resolve) => { @@ -11,27 +12,49 @@ function listenForEvent(): Promise { } test.describe('Canvas Event', () => { - test('Emit litegraph:canvas empty-release', async ({ comfyPage }) => { + test('@perf Emit litegraph:canvas empty-release', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'canvas-empty-release' + + await perfMonitor.startMonitoring(testName) + const eventPromise = comfyPage.page.evaluate(listenForEvent) - const disconnectPromise = comfyPage.disconnectEdge() + + await perfMonitor.measureOperation('disconnect-edge', async () => { + await comfyPage.disconnectEdge() + }) + const event = await eventPromise - await disconnectPromise expect(event).not.toBeNull() // No further check on event content as the content is dropped by // playwright for some reason. // See https://github.com/microsoft/playwright/issues/31580 + + await perfMonitor.finishMonitoring(testName) }) - test('Emit litegraph:canvas empty-double-click', async ({ comfyPage }) => { + test('@perf Emit litegraph:canvas empty-double-click', async ({ + comfyPage + }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'canvas-double-click' + + await perfMonitor.startMonitoring(testName) + const eventPromise = comfyPage.page.evaluate(listenForEvent) - const doubleClickPromise = comfyPage.doubleClickCanvas() + + await perfMonitor.measureOperation('double-click-canvas', async () => { + await comfyPage.doubleClickCanvas() + }) + const event = await eventPromise - await doubleClickPromise expect(event).not.toBeNull() // No further check on event content as the content is dropped by // playwright for some reason. // See https://github.com/microsoft/playwright/issues/31580 + + await perfMonitor.finishMonitoring(testName) }) }) diff --git a/browser_tests/tests/nodeDisplay.spec.ts b/browser_tests/tests/nodeDisplay.spec.ts index 1fa197650..604d16367 100644 --- a/browser_tests/tests/nodeDisplay.spec.ts +++ b/browser_tests/tests/nodeDisplay.spec.ts @@ -1,38 +1,102 @@ import { expect } from '@playwright/test' import { comfyPageFixture as test } from '../fixtures/ComfyPage' +import { PerformanceMonitor } from '../helpers/performanceMonitor' // If an input is optional by node definition, it should be shown as // a hollow circle no matter what shape it was defined in the workflow JSON. test.describe('Optional input', () => { - test('No shape specified', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('optional_input_no_shape') + test('@perf No shape specified', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'optional-input-no-shape' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('optional_input_no_shape') + }) + await expect(comfyPage.canvas).toHaveScreenshot('optional_input.png') + + await perfMonitor.finishMonitoring(testName) }) - test('Wrong shape specified', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('optional_input_wrong_shape') + test('@perf Wrong shape specified', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'optional-input-wrong-shape' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('optional_input_wrong_shape') + }) + await expect(comfyPage.canvas).toHaveScreenshot('optional_input.png') + + await perfMonitor.finishMonitoring(testName) }) - test('Correct shape specified', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('optional_input_correct_shape') + test('@perf Correct shape specified', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'optional-input-correct-shape' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('optional_input_correct_shape') + }) + await expect(comfyPage.canvas).toHaveScreenshot('optional_input.png') + + await perfMonitor.finishMonitoring(testName) }) - test('Force input', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('force_input') + test('@perf Force input', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'force-input' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('force_input') + }) + await expect(comfyPage.canvas).toHaveScreenshot('force_input.png') + + await perfMonitor.finishMonitoring(testName) }) - test('Default input', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('default_input') + test('@perf Default input', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'default-input' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('default_input') + }) + await expect(comfyPage.canvas).toHaveScreenshot('default_input.png') + + await perfMonitor.finishMonitoring(testName) }) - test('Only optional inputs', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('only_optional_inputs') - expect(await comfyPage.getGraphNodesCount()).toBe(1) + test('@perf Only optional inputs', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'only-optional-inputs' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('only_optional_inputs') + }) + + let nodeCount: number + await perfMonitor.measureOperation('get-nodes-count', async () => { + nodeCount = await comfyPage.getGraphNodesCount() + }) + expect(nodeCount!).toBe(1) + await expect( comfyPage.page.locator('.comfy-missing-nodes') ).not.toBeVisible() @@ -41,11 +105,29 @@ test.describe('Optional input', () => { await expect(comfyPage.page.locator('.comfy-multiline-input')).toHaveCount( 1 ) + + await perfMonitor.finishMonitoring(testName) }) - test('Old workflow with converted input', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('old_workflow_converted_input') - const node = await comfyPage.getNodeRefById('1') - const inputs = await node.getProperty('inputs') + test('@perf Old workflow with converted input', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'old-workflow-converted-input' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('old_workflow_converted_input') + }) + + let node: any + await perfMonitor.measureOperation('get-node', async () => { + node = await comfyPage.getNodeRefById('1') + }) + + let inputs: any + await perfMonitor.measureOperation('get-node-inputs', async () => { + inputs = await node.getProperty('inputs') + }) + const vaeInput = inputs.find((w) => w.name === 'vae') const convertedInput = inputs.find((w) => w.name === 'strength') @@ -53,29 +135,85 @@ test.describe('Optional input', () => { expect(convertedInput).toBeDefined() expect(vaeInput.link).toBeNull() expect(convertedInput.link).not.toBeNull() + + await perfMonitor.finishMonitoring(testName) }) - test('Renamed converted input', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('renamed_converted_widget') - const node = await comfyPage.getNodeRefById('3') - const inputs = await node.getProperty('inputs') + test('@perf Renamed converted input', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'renamed-converted-input' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('renamed_converted_widget') + }) + + let node: any + await perfMonitor.measureOperation('get-node', async () => { + node = await comfyPage.getNodeRefById('3') + }) + + let inputs: any + await perfMonitor.measureOperation('get-node-inputs', async () => { + inputs = await node.getProperty('inputs') + }) + const renamedInput = inputs.find((w) => w.name === 'breadth') expect(renamedInput).toBeUndefined() + + await perfMonitor.finishMonitoring(testName) }) - test('slider', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('simple_slider') + test('@perf slider', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'simple-slider' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('simple_slider') + }) + await expect(comfyPage.canvas).toHaveScreenshot('simple_slider.png') + + await perfMonitor.finishMonitoring(testName) }) - test('unknown converted widget', async ({ comfyPage }) => { - await comfyPage.setSetting('Comfy.Workflow.ShowMissingNodesWarning', false) - await comfyPage.loadWorkflow('missing_nodes_converted_widget') + test('@perf unknown converted widget', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'unknown-converted-widget' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('set-setting', async () => { + await comfyPage.setSetting( + 'Comfy.Workflow.ShowMissingNodesWarning', + false + ) + }) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('missing_nodes_converted_widget') + }) + await expect(comfyPage.canvas).toHaveScreenshot( 'missing_nodes_converted_widget.png' ) + + await perfMonitor.finishMonitoring(testName) }) - test('dynamically added input', async ({ comfyPage }) => { - await comfyPage.loadWorkflow('dynamically_added_input') + test('@perf dynamically added input', async ({ comfyPage }) => { + const perfMonitor = new PerformanceMonitor(comfyPage.page) + const testName = 'dynamically-added-input' + + await perfMonitor.startMonitoring(testName) + + await perfMonitor.measureOperation('load-workflow', async () => { + await comfyPage.loadWorkflow('dynamically_added_input') + }) + await expect(comfyPage.canvas).toHaveScreenshot( 'dynamically_added_input.png' ) + + await perfMonitor.finishMonitoring(testName) }) })