mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 14:30:41 +00:00
## Summary
Enable the previously disabled `playwright/no-force-option` lint rule at
error level and resolve all 29 violations across 10 files.
## Changes
### Lint rule
- `.oxlintrc.json`: `playwright/no-force-option` changed from `off` to
`error`
### Shared utility
- `CanvasHelper.ts`: Add `mouseClickAt()` and `mouseDblclickAt()`
methods that convert canvas-element-relative positions to absolute page
coordinates and use `page.mouse` APIs, avoiding Playwright's locator
actionability checks that fail when Vue DOM overlays sit above the
`<canvas>` element
### Force removal (20 violations)
- `selectionToolboxActions.spec.ts`: Remove `force: true` from 8 toolbox
button clicks (the `pointer-events: none` splitter overlay does not
intercept `elementFromPoint()`)
- `selectionToolboxSubmenus.spec.ts`: Remove `force: true` from 2
popover menu item clicks
- `BuilderSelectHelper.ts`: Remove `force: true` from 2 widget/node
clicks (builder mode does not disable pointer events)
- `linkInteraction.spec.ts`: Remove `force: true` from 3 slot `dragTo()`
calls (`::after` pseudo-elements do not intercept `elementFromPoint()`)
- `SidebarTab.ts`: Remove `force: true` from toast dismissal (`.catch()`
already handles failures)
- `nodeHelp.spec.ts`: Remove `force: true` from info button click
(preceding `toBeVisible()` assertion is sufficient)
### Rewrites (3 violations)
- `integerWidget.spec.ts`: Replace force-clicking disabled buttons with
`toBeDisabled()` assertions
- `Topbar.ts`: Replace force-click with `waitFor({ state: 'visible' })`
after hover
### Canvas coordinate clicks (9 violations)
- `litegraphUtils.ts`: Convert `NodeReference.click()` and
`navigateIntoSubgraph()` to use
`canvasOps.mouseClickAt()`/`mouseDblclickAt()`
- `subgraphPromotion.spec.ts`: Convert 3 right-click canvas calls to
`canvasOps.mouseClickAt()`
- `selectionToolboxSubmenus.spec.ts`: Convert 1 canvas dismiss-click to
`canvasOps.mouseClickAt()`
## Rationale
The original `force: true` usages were added defensively based on
incorrect assumptions about the `z-999 pointer-events: none` splitter
overlay intercepting Playwright's actionability checks. In reality,
`elementFromPoint()` skips elements with `pointer-events: none`, so the
overlay is transparent to Playwright's hit-test.
For canvas coordinate clicks, `force: true` on a locator does not tunnel
through DOM overlays — it only skips Playwright's preflight checks.
`page.mouse.click()` is the correct API for coordinate-based canvas
interactions.
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11164-fix-enable-playwright-no-force-option-lint-rule-33f6d73d365081e78601c6114121d272)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Amp <amp@ampcode.com>
178 lines
5.9 KiB
JSON
178 lines
5.9 KiB
JSON
{
|
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
"ignorePatterns": [
|
|
".i18nrc.cjs",
|
|
".nx/*",
|
|
"**/vite.config.*.timestamp*",
|
|
"**/vitest.config.*.timestamp*",
|
|
"components.d.ts",
|
|
"coverage/*",
|
|
"dist/*",
|
|
"packages/registry-types/src/comfyRegistryTypes.ts",
|
|
"playwright-report/*",
|
|
"src/extensions/core/*",
|
|
"src/scripts/*",
|
|
"src/types/generatedManagerTypes.ts",
|
|
"src/types/vue-shim.d.ts",
|
|
"test-results/*",
|
|
"vitest.setup.ts"
|
|
],
|
|
"plugins": [
|
|
"eslint",
|
|
"import",
|
|
"oxc",
|
|
"typescript",
|
|
"unicorn",
|
|
"vitest",
|
|
"vue"
|
|
],
|
|
"rules": {
|
|
"no-async-promise-executor": "off",
|
|
"no-console": [
|
|
"error",
|
|
{
|
|
"allow": ["warn", "error"]
|
|
}
|
|
],
|
|
"no-control-regex": "off",
|
|
"no-eval": "error",
|
|
"no-redeclare": "error",
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"paths": [
|
|
{
|
|
"name": "primevue/calendar",
|
|
"message": "Calendar is deprecated in PrimeVue 4+. Use DatePicker instead: import DatePicker from 'primevue/datepicker'"
|
|
},
|
|
{
|
|
"name": "primevue/dropdown",
|
|
"message": "Dropdown is deprecated in PrimeVue 4+. Use Select instead: import Select from 'primevue/select'"
|
|
},
|
|
{
|
|
"name": "primevue/inputswitch",
|
|
"message": "InputSwitch is deprecated in PrimeVue 4+. Use ToggleSwitch instead: import ToggleSwitch from 'primevue/toggleswitch'"
|
|
},
|
|
{
|
|
"name": "primevue/overlaypanel",
|
|
"message": "OverlayPanel is deprecated in PrimeVue 4+. Use Popover instead: import Popover from 'primevue/popover'"
|
|
},
|
|
{
|
|
"name": "primevue/sidebar",
|
|
"message": "Sidebar is deprecated in PrimeVue 4+. Use Drawer instead: import Drawer from 'primevue/drawer'"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"no-unsafe-optional-chaining": "error",
|
|
"no-self-assign": "allow",
|
|
"no-unused-expressions": "off",
|
|
"no-unused-private-class-members": "off",
|
|
"no-useless-rename": "off",
|
|
"import/default": "error",
|
|
"import/export": "error",
|
|
"import/namespace": "error",
|
|
"import/no-duplicates": "error",
|
|
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
|
|
"jest/expect-expect": "off",
|
|
"jest/no-conditional-expect": "off",
|
|
"jest/no-disabled-tests": "off",
|
|
"jest/no-standalone-expect": "off",
|
|
"jest/valid-title": "off",
|
|
"typescript/no-this-alias": "off",
|
|
"typescript/no-unnecessary-parameter-property-assignment": "off",
|
|
"typescript/no-unsafe-declaration-merging": "off",
|
|
"typescript/no-unused-vars": "off",
|
|
"unicorn/no-empty-file": "off",
|
|
"vitest/require-mock-type-parameters": "off",
|
|
"unicorn/no-new-array": "off",
|
|
"unicorn/no-single-promise-in-promise-methods": "off",
|
|
"unicorn/no-useless-fallback-in-spread": "off",
|
|
"unicorn/no-useless-spread": "off",
|
|
"typescript/await-thenable": "off",
|
|
"typescript/no-base-to-string": "off",
|
|
"typescript/no-duplicate-type-constituents": "off",
|
|
"typescript/no-for-in-array": "off",
|
|
"typescript/no-meaningless-void-operator": "off",
|
|
"typescript/no-redundant-type-constituents": "off",
|
|
"typescript/restrict-template-expressions": "off",
|
|
"typescript/unbound-method": "off",
|
|
"typescript/no-floating-promises": "error",
|
|
"typescript/no-explicit-any": "error",
|
|
"typescript/no-import-type-side-effects": "error",
|
|
"typescript/no-empty-object-type": [
|
|
"error",
|
|
{
|
|
"allowInterfaces": "always"
|
|
}
|
|
],
|
|
"vue/no-import-compiler-macros": "error"
|
|
},
|
|
"overrides": [
|
|
{
|
|
"files": ["**/*.{stories,test,spec}.ts", "**/*.stories.vue"],
|
|
"rules": {
|
|
"no-console": "allow"
|
|
}
|
|
},
|
|
{
|
|
"files": ["browser_tests/**/*.ts"],
|
|
"jsPlugins": ["eslint-plugin-playwright"],
|
|
"rules": {
|
|
"typescript/no-explicit-any": "error",
|
|
"no-async-promise-executor": "error",
|
|
"no-control-regex": "error",
|
|
"no-useless-rename": "error",
|
|
"no-unused-private-class-members": "error",
|
|
"unicorn/no-empty-file": "error",
|
|
"playwright/consistent-spacing-between-blocks": "error",
|
|
"playwright/expect-expect": [
|
|
"error",
|
|
{
|
|
"assertFunctionNames": [
|
|
"recordMeasurement",
|
|
"logMeasurement",
|
|
"builderSaveAs"
|
|
],
|
|
"assertFunctionPatterns": [
|
|
"^expect",
|
|
"^assert",
|
|
"^verify",
|
|
"^searchAndExpect",
|
|
"waitForOpen",
|
|
"waitForClosed",
|
|
"waitForRequest"
|
|
]
|
|
}
|
|
],
|
|
"playwright/max-nested-describe": "error",
|
|
"playwright/no-duplicate-hooks": "error",
|
|
"playwright/no-element-handle": "error",
|
|
"playwright/no-eval": "error",
|
|
"playwright/no-focused-test": "error",
|
|
"playwright/no-force-option": "error",
|
|
"playwright/no-networkidle": "error",
|
|
"playwright/no-page-pause": "error",
|
|
"playwright/no-skipped-test": "error",
|
|
"playwright/no-unsafe-references": "error",
|
|
"playwright/no-unused-locators": "error",
|
|
"playwright/no-useless-await": "error",
|
|
"playwright/no-useless-not": "error",
|
|
"playwright/no-wait-for-navigation": "error",
|
|
"playwright/no-wait-for-selector": "error",
|
|
"playwright/no-wait-for-timeout": "error",
|
|
"playwright/prefer-hooks-on-top": "error",
|
|
"playwright/prefer-locator": "error",
|
|
"playwright/prefer-to-have-count": "error",
|
|
"playwright/prefer-to-have-length": "error",
|
|
"playwright/prefer-web-first-assertions": "error",
|
|
"playwright/prefer-native-locators": "error",
|
|
"playwright/require-to-pass-timeout": "error",
|
|
"playwright/valid-expect": "error",
|
|
"playwright/valid-expect-in-promise": "error",
|
|
"playwright/valid-title": "error"
|
|
}
|
|
}
|
|
]
|
|
}
|