Files
ComfyUI_frontend/browser_tests/tests/vueNodes/widgets/float/floatWidget.spec.ts
Dante 64dd3d7557 test: add e2e specs for float and combo Vue widgets (#11447)
## Summary

Adds two Playwright specs extending
\`browser_tests/tests/vueNodes/widgets/\` to cover float and combo value
types, following the existing \`integerWidget.spec.ts\` /
\`multilineStringWidget.spec.ts\` pattern. Part of a
widget-test-coverage sequence.

## Changes

- **What**:
- \`browser_tests/tests/vueNodes/widgets/float/floatWidget.spec.ts\` (3)
— number-input value change, increment/decrement on \`denoise\`, and
persistence through litegraph widget state after user edit.
- \`browser_tests/tests/vueNodes/widgets/combo/comboWidget.spec.ts\` (3)
— dropdown lists known sampler options, combo value updates on select,
\`scheduler\` value persists.

Reuses the existing \`vueNodes/linked-int-widget.json\` fixture
(KSampler exposes \`cfg\` / \`denoise\` floats and \`sampler_name\` /
\`scheduler\` combos). No new fixture files.

## Review Focus

- Specs tagged \`@vue-nodes\`, consistent with the sibling suites.
- Persistence assertions read widget state via
\`window.graph._nodes_by_id[...].widgets\` (typed through
\`TestGraphAccess\` from \`@e2e/types/globals\`) rather than
JSON-serializing the whole graph — avoids \`unknown\` typing on
\`window.graph.serialize()\`.
- Boolean and color e2e specs are intentionally NOT in this PR — they'd
need new workflow fixtures, which I'd prefer to design with you before
writing.
- \`pnpm typecheck:browser\` is clean locally; CI run needed to validate
the Playwright behaviour since I couldn't run the full e2e suite
locally.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11447-test-add-e2e-specs-for-float-and-combo-Vue-widgets-3486d73d365081f79302edc87595130c)
by [Unito](https://www.unito.io)
2026-04-22 20:58:26 +00:00

84 lines
2.9 KiB
TypeScript

import {
comfyExpect as expect,
comfyPageFixture as test
} from '@e2e/fixtures/ComfyPage'
test.describe('Vue Float Widget', { tag: '@vue-nodes' }, () => {
test('evaluates expression input using the widget precision', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('vueNodes/linked-int-widget')
const cfgWidget = comfyPage.vueNodes
.getWidgetByName('KSampler', 'cfg')
.first()
const { input } = comfyPage.vueNodes.getInputNumberControls(cfgWidget)
// 2.1 + 1.23 = 3.33 — well away from any half-point, so the expected
// value is the same under half-up, half-even, and half-away-from-zero.
await input.fill('2.1 + 1.23')
await input.blur()
await expect(input).toHaveValue('3.3')
})
test('increment and decrement buttons update the value', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('vueNodes/linked-int-widget')
// cfg has room to grow (initial 8, max 100); denoise is at its max (1)
// so its increment button is disabled and can't be used here.
const cfgWidget = comfyPage.vueNodes
.getWidgetByName('KSampler', 'cfg')
.first()
const controls = comfyPage.vueNodes.getInputNumberControls(cfgWidget)
const initial = Number(await controls.input.inputValue())
await controls.incrementButton.click()
await expect
.poll(async () => Number(await controls.input.inputValue()))
.toBeGreaterThan(initial)
const afterIncrement = Number(await controls.input.inputValue())
await controls.decrementButton.click()
await expect
.poll(async () => Number(await controls.input.inputValue()))
.toBeLessThan(afterIncrement)
})
test('persists value across a serialize and reload round-trip', async ({
comfyPage
}) => {
await comfyPage.workflow.loadWorkflow('vueNodes/linked-int-widget')
const cfgWidget = comfyPage.vueNodes
.getWidgetByName('KSampler', 'cfg')
.first()
const { input } = comfyPage.vueNodes.getInputNumberControls(cfgWidget)
// KSampler's cfg is precision=1, so pick a value that lands on the grid
await input.fill('7.5')
await input.blur()
await expect(input).toHaveValue('7.5')
const serialized = await comfyPage.workflow.getExportedWorkflow()
await comfyPage.workflow.loadGraphData(serialized)
await comfyPage.vueNodes.waitForNodes()
const [ksamplerNode] = await comfyPage.nodeOps.getNodeRefsByType('KSampler')
if (!ksamplerNode) {
throw new Error('KSampler node not found after reload')
}
const cfgWidgetAfterReload = await ksamplerNode.getWidgetByName('cfg')
await expect.poll(() => cfgWidgetAfterReload.getValue()).toBe(7.5)
// Also assert the Vue input mirrors the persisted value, so a broken
// rehydration path that keeps litegraph state correct but renders stale
// UI (or vice versa) still fails this test.
await expect(input).toHaveValue('7.5')
})
})