diff --git a/.env_example b/.env_example index a6987ae26..520521fe0 100644 --- a/.env_example +++ b/.env_example @@ -33,4 +33,3 @@ DISABLE_VUE_PLUGINS=false # Algolia credentials required for developing with the new custom node manager. ALGOLIA_APP_ID=4E0RO38HS8 ALGOLIA_API_KEY=684d998c36b67a9a9fce8fc2d8860579 - diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 8decf07cd..06139b08a 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -7,3 +7,21 @@ c53f197de2a3e0fa66b16dedc65c131235c1c4b6 # Reorganize renderer components into domain-driven folder structure c8a83a9caede7bdb5f8598c5492b07d08c339d49 + +# Domain-driven design (DDD) refactors - September 2025 +# These commits reorganized the codebase into domain-driven architecture + +# [refactor] Improve renderer domain organization (#5552) +6349ceee6c0a57fc7992e85635def9b6e22eaeb2 + +# [refactor] Improve settings domain organization (#5550) +4c8c4a1ad4f53354f700a33ea1b95262aeda2719 + +# [refactor] Improve workflow domain organization (#5584) +ca312fd1eab540cc4ddc0e3d244d38b3858574f0 + +# [refactor] Move thumbnail functionality to renderer/core domain (#5586) +e3bb29ceb8174b8bbca9e48ec7d42cd540f40efa + +# [refactor] Improve updates/notifications domain organization (#5590) +27ab355f9c73415dc39f4d3f512b02308f847801 diff --git a/.github/workflows/backport.yaml b/.github/workflows/backport.yaml index 3f4b93242..907695e57 100644 --- a/.github/workflows/backport.yaml +++ b/.github/workflows/backport.yaml @@ -133,11 +133,10 @@ jobs: if: steps.check-existing.outputs.skip != 'true' && steps.backport.outputs.success env: GH_TOKEN: ${{ secrets.PR_GH_TOKEN }} + PR_TITLE: ${{ github.event.pull_request.title }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} run: | - PR_TITLE="${{ github.event.pull_request.title }}" - PR_NUMBER="${{ github.event.pull_request.number }}" - PR_AUTHOR="${{ github.event.pull_request.user.login }}" - for backport in ${{ steps.backport.outputs.success }}; do IFS=':' read -r version branch <<< "${backport}" diff --git a/.github/workflows/publish-frontend-types.yaml b/.github/workflows/publish-frontend-types.yaml new file mode 100644 index 000000000..398f5e0a7 --- /dev/null +++ b/.github/workflows/publish-frontend-types.yaml @@ -0,0 +1,137 @@ +name: Publish Frontend Types + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to publish (e.g., 1.26.7)' + required: true + type: string + dist_tag: + description: 'npm dist-tag to use' + required: true + default: latest + type: string + ref: + description: 'Git ref to checkout (commit SHA, tag, or branch)' + required: false + type: string + workflow_call: + inputs: + version: + required: true + type: string + dist_tag: + required: false + type: string + default: latest + ref: + required: false + type: string + +concurrency: + group: publish-frontend-types-${{ github.workflow }}-${{ inputs.version }}-${{ inputs.dist_tag }} + cancel-in-progress: false + +jobs: + publish_types_manual: + name: Publish @comfyorg/comfyui-frontend-types + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Validate inputs + shell: bash + run: | + set -euo pipefail + VERSION="${{ inputs.version }}" + SEMVER_REGEX='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*))?(\+([0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*))?$' + if [[ ! "$VERSION" =~ $SEMVER_REGEX ]]; then + echo "::error title=Invalid version::Version '$VERSION' must follow semantic versioning (x.y.z[-suffix][+build])" >&2 + exit 1 + fi + + - name: Determine ref to checkout + id: resolve_ref + shell: bash + run: | + set -euo pipefail + REF="${{ inputs.ref }}" + VERSION="${{ inputs.version }}" + if [ -n "$REF" ]; then + if ! git check-ref-format --allow-onelevel "$REF"; then + echo "::error title=Invalid ref::Ref '$REF' fails git check-ref-format validation." >&2 + exit 1 + fi + echo "ref=$REF" >> "$GITHUB_OUTPUT" + else + echo "ref=refs/tags/v$VERSION" >> "$GITHUB_OUTPUT" + fi + + - name: Checkout repository + uses: actions/checkout@v5 + with: + ref: ${{ steps.resolve_ref.outputs.ref }} + fetch-depth: 1 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: 'lts/*' + cache: 'pnpm' + registry-url: https://registry.npmjs.org + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Build types + run: pnpm build:types + + - name: Verify version matches input + id: verify + shell: bash + run: | + PKG_VERSION=$(node -p "require('./package.json').version") + TYPES_PKG_VERSION=$(node -p "require('./dist/package.json').version") + if [ "$PKG_VERSION" != "${{ inputs.version }}" ]; then + echo "Error: package.json version $PKG_VERSION does not match input ${{ inputs.version }}" >&2 + exit 1 + fi + if [ "$TYPES_PKG_VERSION" != "${{ inputs.version }}" ]; then + echo "Error: dist/package.json version $TYPES_PKG_VERSION does not match input ${{ inputs.version }}" >&2 + exit 1 + fi + echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT + + - name: Check if version already on npm + id: check_npm + shell: bash + run: | + set -euo pipefail + NAME=$(node -p "require('./dist/package.json').name") + VER="${{ steps.verify.outputs.version }}" + STATUS=0 + OUTPUT=$(npm view "${NAME}@${VER}" --json 2>&1) || STATUS=$? + if [ "$STATUS" -eq 0 ]; then + echo "exists=true" >> "$GITHUB_OUTPUT" + echo "::warning title=Already published::${NAME}@${VER} already exists on npm. Skipping publish." + else + if echo "$OUTPUT" | grep -q "E404"; then + echo "exists=false" >> "$GITHUB_OUTPUT" + else + echo "::error title=Registry lookup failed::$OUTPUT" >&2 + exit "$STATUS" + fi + fi + + - name: Publish package + if: steps.check_npm.outputs.exists == 'false' + run: pnpm publish --access public --tag "${{ inputs.dist_tag }}" + working-directory: dist + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8958ce147..c359e3da4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -18,7 +18,7 @@ jobs: is_prerelease: ${{ steps.check_prerelease.outputs.is_prerelease }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install pnpm uses: pnpm/action-setup@v4 with: @@ -73,7 +73,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Download dist artifact uses: actions/download-artifact@v4 with: @@ -98,7 +98,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Download dist artifact uses: actions/download-artifact@v4 with: @@ -126,34 +126,8 @@ jobs: publish_types: needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install pnpm - uses: pnpm/action-setup@v4 - with: - version: 10 - - uses: actions/setup-node@v4 - with: - node-version: 'lts/*' - cache: 'pnpm' - registry-url: https://registry.npmjs.org - - - name: Cache tool outputs - uses: actions/cache@v4 - with: - path: | - .cache - tsconfig.tsbuildinfo - dist - key: types-tools-cache-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - types-tools-cache-${{ runner.os }}- - - - run: pnpm install --frozen-lockfile - - run: pnpm build:types - - name: Publish package - run: pnpm publish --access public - working-directory: dist - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + uses: ./.github/workflows/publish-frontend-types.yaml + with: + version: ${{ needs.build.outputs.version }} + ref: ${{ github.event.pull_request.merge_commit_sha }} + secrets: inherit diff --git a/.github/workflows/test-ui.yaml b/.github/workflows/test-ui.yaml index f8f6cf955..eaaaefee0 100644 --- a/.github/workflows/test-ui.yaml +++ b/.github/workflows/test-ui.yaml @@ -229,7 +229,13 @@ jobs: - name: Run Playwright tests (${{ matrix.browser }}) id: playwright - run: npx playwright test --project=${{ matrix.browser }} --reporter=html + run: | + # Run tests with both HTML and JSON reporters + PLAYWRIGHT_JSON_OUTPUT_NAME=playwright-report/report.json \ + npx playwright test --project=${{ matrix.browser }} \ + --reporter=list \ + --reporter=html \ + --reporter=json working-directory: ComfyUI_frontend - uses: actions/upload-artifact@v4 @@ -275,7 +281,12 @@ jobs: merge-multiple: true - name: Merge into HTML Report - run: npx playwright merge-reports --reporter html ./all-blob-reports + run: | + # Generate HTML report + npx playwright merge-reports --reporter=html ./all-blob-reports + # Generate JSON report separately with explicit output path + PLAYWRIGHT_JSON_OUTPUT_NAME=playwright-report/report.json \ + npx playwright merge-reports --reporter=json ./all-blob-reports working-directory: ComfyUI_frontend - name: Upload HTML report diff --git a/.github/workflows/update-electron-types.yaml b/.github/workflows/update-electron-types.yaml index 0dfcdea34..96f85f6b0 100644 --- a/.github/workflows/update-electron-types.yaml +++ b/.github/workflows/update-electron-types.yaml @@ -40,7 +40,7 @@ jobs: - name: Get new version id: get-version run: | - NEW_VERSION=$(pnpm list @comfyorg/comfyui-electron-types --json --depth=0 | jq -r '.[0].version') + NEW_VERSION=$(pnpm list @comfyorg/comfyui-electron-types --json --depth=0 | jq -r '.[0].dependencies."@comfyorg/comfyui-electron-types".version') echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT - name: Create Pull Request diff --git a/.gitignore b/.gitignore index 100bcd13e..5a58d1b1a 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,7 @@ tests-ui/workflows/examples /blob-report/ /playwright/.cache/ browser_tests/**/*-win32.png -browser-tests/local/ +browser_tests/local/ .env diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..ae90f7051 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +ignore-workspace-root-check=true diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html index 76aca2401..05e082ef0 100644 --- a/.storybook/preview-head.html +++ b/.storybook/preview-head.html @@ -57,9 +57,8 @@ /* Override Storybook's problematic & selector styles */ /* Reset only the specific properties that Storybook injects */ - #storybook-root li+li, - #storybook-docs li+li { - margin: inherit; - padding: inherit; + li+li { + margin: 0; + padding: revert-layer; } \ No newline at end of file diff --git a/browser_tests/fixtures/ComfyPage.ts b/browser_tests/fixtures/ComfyPage.ts index c32dd3937..c9a8820f5 100644 --- a/browser_tests/fixtures/ComfyPage.ts +++ b/browser_tests/fixtures/ComfyPage.ts @@ -5,13 +5,14 @@ import dotenv from 'dotenv' import * as fs from 'fs' import type { LGraphNode } from '../../src/lib/litegraph/src/litegraph' -import type { NodeId } from '../../src/schemas/comfyWorkflowSchema' +import type { NodeId } from '../../src/platform/workflow/validation/schemas/workflowSchema' import type { KeyCombo } from '../../src/schemas/keyBindingSchema' import type { useWorkspaceStore } from '../../src/stores/workspaceStore' import { NodeBadgeMode } from '../../src/types/nodeSource' import { ComfyActionbar } from '../helpers/actionbar' import { ComfyTemplates } from '../helpers/templates' import { ComfyMouse } from './ComfyMouse' +import { VueNodeHelpers } from './VueNodeHelpers' import { ComfyNodeSearchBox } from './components/ComfyNodeSearchBox' import { SettingDialog } from './components/SettingDialog' import { @@ -144,6 +145,7 @@ export class ComfyPage { public readonly templates: ComfyTemplates public readonly settingDialog: SettingDialog public readonly confirmDialog: ConfirmDialog + public readonly vueNodes: VueNodeHelpers /** Worker index to test user ID */ public readonly userIds: string[] = [] @@ -172,6 +174,7 @@ export class ComfyPage { this.templates = new ComfyTemplates(page) this.settingDialog = new SettingDialog(page, this) this.confirmDialog = new ConfirmDialog(page) + this.vueNodes = new VueNodeHelpers(page) } convertLeafToContent(structure: FolderStructure): FolderStructure { @@ -1421,7 +1424,7 @@ export class ComfyPage { } async closeDialog() { - await this.page.locator('.p-dialog-close-button').click() + await this.page.locator('.p-dialog-close-button').click({ force: true }) await expect(this.page.locator('.p-dialog')).toBeHidden() } diff --git a/browser_tests/fixtures/VueNodeHelpers.ts b/browser_tests/fixtures/VueNodeHelpers.ts new file mode 100644 index 000000000..e3b3de542 --- /dev/null +++ b/browser_tests/fixtures/VueNodeHelpers.ts @@ -0,0 +1,110 @@ +/** + * Vue Node Test Helpers + */ +import type { Locator, Page } from '@playwright/test' + +export class VueNodeHelpers { + constructor(private page: Page) {} + + /** + * Get locator for all Vue node components in the DOM + */ + get nodes(): Locator { + return this.page.locator('[data-node-id]') + } + + /** + * Get locator for selected Vue node components (using visual selection indicators) + */ + get selectedNodes(): Locator { + return this.page.locator( + '[data-node-id].outline-black, [data-node-id].outline-white' + ) + } + + /** + * Get total count of Vue nodes in the DOM + */ + async getNodeCount(): Promise { + return await this.nodes.count() + } + + /** + * Get count of selected Vue nodes + */ + async getSelectedNodeCount(): Promise { + return await this.selectedNodes.count() + } + + /** + * Get all Vue node IDs currently in the DOM + */ + async getNodeIds(): Promise { + return await this.nodes.evaluateAll((nodes) => + nodes + .map((n) => n.getAttribute('data-node-id')) + .filter((id): id is string => id !== null) + ) + } + + /** + * Select a specific Vue node by ID + */ + async selectNode(nodeId: string): Promise { + await this.page.locator(`[data-node-id="${nodeId}"]`).click() + } + + /** + * Select multiple Vue nodes by IDs using Ctrl+click + */ + async selectNodes(nodeIds: string[]): Promise { + if (nodeIds.length === 0) return + + // Select first node normally + await this.selectNode(nodeIds[0]) + + // Add additional nodes with Ctrl+click + for (let i = 1; i < nodeIds.length; i++) { + await this.page.locator(`[data-node-id="${nodeIds[i]}"]`).click({ + modifiers: ['Control'] + }) + } + } + + /** + * Clear all selections by clicking empty space + */ + async clearSelection(): Promise { + await this.page.mouse.click(50, 50) + } + + /** + * Delete selected Vue nodes using Delete key + */ + async deleteSelected(): Promise { + await this.page.locator('#graph-canvas').focus() + await this.page.keyboard.press('Delete') + } + + /** + * Delete selected Vue nodes using Backspace key + */ + async deleteSelectedWithBackspace(): Promise { + await this.page.locator('#graph-canvas').focus() + await this.page.keyboard.press('Backspace') + } + + /** + * Wait for Vue nodes to be rendered + */ + async waitForNodes(expectedCount?: number): Promise { + if (expectedCount !== undefined) { + await this.page.waitForFunction( + (count) => document.querySelectorAll('[data-node-id]').length >= count, + expectedCount + ) + } else { + await this.page.waitForSelector('[data-node-id]') + } + } +} diff --git a/browser_tests/fixtures/utils/litegraphUtils.ts b/browser_tests/fixtures/utils/litegraphUtils.ts index c9bf88a91..4becc999c 100644 --- a/browser_tests/fixtures/utils/litegraphUtils.ts +++ b/browser_tests/fixtures/utils/litegraphUtils.ts @@ -1,6 +1,6 @@ import type { Page } from '@playwright/test' -import type { NodeId } from '../../../src/schemas/comfyWorkflowSchema' +import type { NodeId } from '../../../src/platform/workflow/validation/schemas/workflowSchema' import { ManageGroupNode } from '../../helpers/manageGroupNode' import type { ComfyPage } from '../ComfyPage' import type { Position, Size } from '../types' diff --git a/browser_tests/helpers/templates.ts b/browser_tests/helpers/templates.ts index d659e125a..0d2c9f31e 100644 --- a/browser_tests/helpers/templates.ts +++ b/browser_tests/helpers/templates.ts @@ -4,7 +4,7 @@ import path from 'path' import { TemplateInfo, WorkflowTemplates -} from '../../src/types/workflowTemplateTypes' +} from '../../src/platform/workflow/templates/types/template' export class ComfyTemplates { readonly content: Locator diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png index 423859696..1ba61954e 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-light-red-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png index 7751d090e..70c81dfbb 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-all-colors-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png index 22e014cff..47083ae5c 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/custom-color-palette-obsidian-dark-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png index 4a5c11c2b..722020a96 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/default-color-palette-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png index 423859696..1ba61954e 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-lightened-colors-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png index 95ef93d47..ee50ed0c5 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-2-arc-theme-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png index ec52820b1..3d490143e 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-changed-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png index 3702c5e46..f5eeaa61b 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-3-color-removed-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png index ba4591403..6b0e3a30a 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-0-5-chromium-linux.png differ diff --git a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png index 4a5c11c2b..722020a96 100644 Binary files a/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png and b/browser_tests/tests/colorPalette.spec.ts-snapshots/node-opacity-1-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png index acd3b340e..6f5edfd8f 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png index bb6defb05..9a695eed8 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-node-with-link-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png index 1927ba4ae..1c1a63047 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/copied-widget-value-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png index 1cd84c832..164773278 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/drag-copy-copied-node-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png index b7bead810..be7214acf 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/no-node-copied-chromium-linux.png differ diff --git a/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png b/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png index 241a48448..fdc151be1 100644 Binary files a/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png and b/browser_tests/tests/copyPaste.spec.ts-snapshots/paste-in-text-area-with-node-previously-copied-chromium-linux.png differ diff --git a/browser_tests/tests/dialog.spec.ts b/browser_tests/tests/dialog.spec.ts index 8ac7449f4..cf2e5e6be 100644 --- a/browser_tests/tests/dialog.spec.ts +++ b/browser_tests/tests/dialog.spec.ts @@ -36,6 +36,10 @@ test('Does not report warning on undo/redo', async ({ comfyPage }) => { await comfyPage.loadWorkflow('missing/missing_nodes') await comfyPage.closeDialog() + // Wait for any async operations to complete after dialog closes + await comfyPage.nextFrame() + await comfyPage.page.waitForTimeout(100) + // Make a change to the graph await comfyPage.doubleClickCanvas() await comfyPage.searchBox.fillAndSelectFirstNode('KSampler') diff --git a/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png b/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png index 4d4bd7c57..90bc677fc 100644 Binary files a/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png and b/browser_tests/tests/domWidget.spec.ts-snapshots/focus-mode-on-chromium-linux.png differ diff --git a/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png b/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png index 109c5436a..8b8287a40 100644 Binary files a/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png and b/browser_tests/tests/execution.spec.ts-snapshots/execution-error-unconnected-slot-chromium-linux.png differ diff --git a/browser_tests/tests/extensionAPI.spec.ts b/browser_tests/tests/extensionAPI.spec.ts index 7711ccf3b..09a08384c 100644 --- a/browser_tests/tests/extensionAPI.spec.ts +++ b/browser_tests/tests/extensionAPI.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test' -import { SettingParams } from '../../src/types/settingTypes' +import { SettingParams } from '../../src/platform/settings/types' import { comfyPageFixture as test } from '../fixtures/ComfyPage' test.describe('Topbar commands', () => { @@ -247,7 +247,7 @@ test.describe('Topbar commands', () => { test.describe('Dialog', () => { test('Should allow showing a prompt dialog', async ({ comfyPage }) => { await comfyPage.page.evaluate(() => { - window['app'].extensionManager.dialog + void window['app'].extensionManager.dialog .prompt({ title: 'Test Prompt', message: 'Test Prompt Message' @@ -267,7 +267,7 @@ test.describe('Topbar commands', () => { comfyPage }) => { await comfyPage.page.evaluate(() => { - window['app'].extensionManager.dialog + void window['app'].extensionManager.dialog .confirm({ title: 'Test Confirm', message: 'Test Confirm Message' @@ -284,7 +284,7 @@ test.describe('Topbar commands', () => { test('Should allow dismissing a dialog', async ({ comfyPage }) => { await comfyPage.page.evaluate(() => { window['value'] = 'foo' - window['app'].extensionManager.dialog + void window['app'].extensionManager.dialog .confirm({ title: 'Test Confirm', message: 'Test Confirm Message' diff --git a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png index b0c849b88..f5ca69e54 100644 Binary files a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png and b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-hidden-links-chromium-linux.png differ diff --git a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png index cbf2b4f08..af9081d0a 100644 Binary files a/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png and b/browser_tests/tests/graphCanvasMenu.spec.ts-snapshots/canvas-with-visible-links-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png index ed5712f00..e2e2f2206 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/adjusted-widget-value-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png index 8a387cb47..27c987620 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/batch-disconnect-links-disconnected-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png index e1c4fe01a..5732eea2b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png index 98027277e..3ebdeb306 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/batch-move-links-moved-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png index 36be4e4fc..ba16c1a37 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-2x-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/default-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png index fa37a19a8..fd4b5a115 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/deleted-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png index a73a56622..c07494c21 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/disconnected-edge-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png index 86c45da4d..a3d7a8443 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/dragged-node1-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png index ce0c454eb..b8e5cdab9 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link1-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png index 7fe839d52..e425d88e8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/dragging-link2-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png index 351b73b99..99bd797a8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/group-fit-to-contents-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png index 046886851..3e8474a2b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/group-selected-nodes-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png index b36ec42fd..082281496 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/group-title-edited-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png index 6eb2b1ac1..750d15c1b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-alt-shift-drag-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png index e2e04c7e7..d0bd046ad 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-click-node-select-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png index 6eb2b1ac1..750d15c1b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-left-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png index 6eb2b1ac1..750d15c1b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-middle-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png index 2d944759e..c457dea5c 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/legacy-wheel-zoom-out-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png index 391228994..7a631a02f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/moved-link-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png index 117d4bb8a..8255f0f5a 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/node-title-edited-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png index 099a0b05b..7181cdcfc 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-bypassed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png index 23f5e9c7e..f6b135cb6 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-pinned-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png index 349014360..a6d09ff18 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unbypassed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png index 349014360..a6d09ff18 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/nodes-unpinned-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png index 892b43b72..7445cc3f9 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-from-far-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-one-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png index 1648d9e8f..5b2380510 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-back-to-two-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png index 788a96295..02d3823e4 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png index fa37a19a8..fd4b5a115 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-far-away-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png index 1648d9e8f..5b2380510 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-one-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png index 892b43b72..7445cc3f9 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-step-two-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png index d0798275d..89cdd22d2 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panned-touch-mobile-chrome-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png index e2984d5c3..6d06644e3 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/panning-when-dragging-link-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png index 1b221cac9..51f5fc50e 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/pinned-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png index 0ba6e8df2..a8fed2ac0 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-closed-text-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png index d23f7108a..6811cb646 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png index 1f5fd61ed..6ce3ce119 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/prompt-dialog-opened-text-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png index 336d7526d..a149cb8ef 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png index a9f182581..f57ca3be8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-2x-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png index e2e04c7e7..d0bd046ad 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node1-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png index 8590a08d8..9e998d26f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-2x-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png index 9c5c9677b..f76d1945d 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/selected-node2-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png index 869a1c4b6..797b10f6f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png index 869a1c4b6..797b10f6f 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-fit-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png index 764f05410..1dfcfa4fe 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/single-ksampler-modified-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png index 71dcfaed8..dc1258e21 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png index 6640f4f38..2a80227ab 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/snap-to-slot-linked-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png index 7f0f6f24f..37866d892 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/snapped-highlighted-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png index e2e04c7e7..d0bd046ad 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-click-node-select-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png index 2d944759e..c457dea5c 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-ctrl-wheel-zoom-out-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png index 2f5526019..a9d0efb74 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-initial-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png index 349014360..a6d09ff18 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-left-drag-select-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png index 6eb2b1ac1..750d15c1b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-middle-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png index 1c8538715..57b6438ae 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-center-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png index 2f5526019..a9d0efb74 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-left-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png index 1c8538715..57b6438ae 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-shift-wheel-pan-right-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png index a6baaa6ad..3db5f8a8c 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/standard-space-drag-pan-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png index 51725b7e7..2c3343f6b 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/string-input-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png index a727dce70..7b7b8f84a 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/string-node-id-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png index 56e147eba..67a37ae57 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-back-open-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png index 3744ac657..dfd279b57 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/text-encode-toggled-off-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png index 336d7526d..a149cb8ef 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/unpinned-all-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-back-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png index 96ed23cf5..3d891b985 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-default-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png index 3ecf7ebb2..39ec12552 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png index 759d66b50..ef8c2d9b2 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png index 6b3c9f349..4be78a0bd 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-high-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png index 5b60237c3..a3f68aaf7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-in-low-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png index aa411c13c..910bf98e6 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png index 73cc47ffa..27b3ff339 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-high-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png index bc5a9c57c..a135084e8 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-out-low-zoom-speed-chromium-linux.png differ diff --git a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png index a39ae0d7d..e807682d3 100644 Binary files a/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png and b/browser_tests/tests/interaction.spec.ts-snapshots/zoomed-very-far-out-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png index 15b1e0f14..eb4903bf8 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/dropped-workflow-url-hidream-dev-example-png-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png index c1a5b4340..2e327dff0 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/edited-workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png index 082c4a0c6..2ff59b391 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/large-workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png index 1464d93a2..8f347b607 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/no-workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png index 37ccbb323..65446a6c7 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-m4v-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png index 37ccbb323..65446a6c7 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mov-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png index 37ccbb323..65446a6c7 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-mp4-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png index c1a5b4340..2e327dff0 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-svg-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png index 662eefd90..58e7be2ea 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webm-chromium-linux.png differ diff --git a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png index c1a5b4340..2e327dff0 100644 Binary files a/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png and b/browser_tests/tests/loadWorkflowInMedia.spec.ts-snapshots/workflow-webp-chromium-linux.png differ diff --git a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png index 8d69066c2..0b2859d12 100644 Binary files a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png and b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-high-quality-chromium-linux.png differ diff --git a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png index ea86cb4e1..a6d8fe852 100644 Binary files a/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png and b/browser_tests/tests/lodThreshold.spec.ts-snapshots/lod-comparison-low-quality-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png index 68985db05..eaf2a528c 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Hide-built-in-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png index eec02ef30..8b8c993c3 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-None-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png index ca68ad258..97a24c6dc 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-Show-all-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png index 57c5199b1..3e28c594a 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png index 7bde04b28..b81e9e785 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-left-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png index d64c6c93b..7b5a380fc 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-light-color-palette-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png index 6d7c32276..1c2e2e274 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-multiple-chromium-linux.png differ diff --git a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png index 942bbf724..6975bdeae 100644 Binary files a/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png and b/browser_tests/tests/nodeBadge.spec.ts-snapshots/node-badge-unknown-color-palette-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png index 196990019..415531498 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/default-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png index aff3b2012..5ae61ea03 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/dynamically-added-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png index 5d97d949b..f76546805 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/force-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png index 9d086a2e7..84ed95b0d 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/missing-nodes-converted-widget-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png index b58d1cd5b..10c5870f3 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/optional-input-chromium-linux.png differ diff --git a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png index e5855068f..ecea34922 100644 Binary files a/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png and b/browser_tests/tests/nodeDisplay.spec.ts-snapshots/simple-slider-chromium-linux.png differ diff --git a/browser_tests/tests/nodeHelp.spec.ts b/browser_tests/tests/nodeHelp.spec.ts index 68ce7b8d5..764849286 100644 --- a/browser_tests/tests/nodeHelp.spec.ts +++ b/browser_tests/tests/nodeHelp.spec.ts @@ -46,7 +46,7 @@ test.describe('Node Help', () => { // Click the help button in the selection toolbox const helpButton = comfyPage.selectionToolbox.locator( - 'button:has(.pi-question-circle)' + 'button[data-testid="info-button"]' ) await expect(helpButton).toBeVisible() await helpButton.click() @@ -164,7 +164,7 @@ test.describe('Node Help', () => { // Click help button const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -194,7 +194,7 @@ test.describe('Node Help', () => { // Click help button const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -228,7 +228,7 @@ test.describe('Node Help', () => { await selectNodeWithPan(comfyPage, ksamplerNodes[0]) const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -276,7 +276,7 @@ test.describe('Node Help', () => { await selectNodeWithPan(comfyPage, ksamplerNodes[0]) const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -348,7 +348,7 @@ This is documentation for a custom node. } const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) if (await helpButton.isVisible()) { await helpButton.click() @@ -389,7 +389,7 @@ This is documentation for a custom node. await selectNodeWithPan(comfyPage, ksamplerNodes[0]) const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -456,7 +456,7 @@ This is English documentation. await selectNodeWithPan(comfyPage, ksamplerNodes[0]) const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -479,7 +479,7 @@ This is English documentation. await selectNodeWithPan(comfyPage, ksamplerNodes[0]) const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -522,7 +522,7 @@ This is English documentation. await selectNodeWithPan(comfyPage, ksamplerNodes[0]) const helpButton = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton.click() @@ -538,7 +538,7 @@ This is English documentation. // Click help button again const helpButton2 = comfyPage.page.locator( - '.selection-toolbox button:has(.pi-question-circle)' + '.selection-toolbox button[data-testid="info-button"]' ) await helpButton2.click() diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png index 17e2e13e2..1202e34d9 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png index 0ca779dc6..f4bd4d3f9 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/added-node-no-connection-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png index ac61db5cd..0d57dcd25 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-batch-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png index aacd4d499..127e5be05 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/auto-linked-node-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png index aacd4d499..127e5be05 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-context-menu-search-chromium-linux.png differ diff --git a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png index 84ee3f655..ade1f674d 100644 Binary files a/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png and b/browser_tests/tests/nodeSearchBox.spec.ts-snapshots/link-release-context-menu-chromium-linux.png differ diff --git a/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png b/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png index 789f31c5a..509067e9f 100644 Binary files a/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png and b/browser_tests/tests/noteNode.spec.ts-snapshots/note-nodes-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png index b09ed4e59..d64126266 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png index 76c6e3bd2..40d877ff9 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png index d2c15dc6b..ff50afcd4 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/primitive-node-connected-dom-widget-chromium-linux.png differ diff --git a/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png b/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png index f6b317330..b8c243f0b 100644 Binary files a/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png and b/browser_tests/tests/primitiveNode.spec.ts-snapshots/static-primitive-connected-chromium-linux.png differ diff --git a/browser_tests/tests/remoteWidgets.spec.ts b/browser_tests/tests/remoteWidgets.spec.ts index 4a390af96..05bb578df 100644 --- a/browser_tests/tests/remoteWidgets.spec.ts +++ b/browser_tests/tests/remoteWidgets.spec.ts @@ -190,7 +190,9 @@ test.describe('Remote COMBO Widget', () => { await comfyPage.page.keyboard.press('Control+A') await expect( - comfyPage.page.locator('.selection-toolbox .pi-refresh') + comfyPage.page.locator( + '.selection-toolbox button[data-testid="refresh-button"]' + ) ).toBeVisible() }) diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png index 91ff758aa..75c7dd2b3 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-0-5x-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png index ef29bdd8e..be8c019f3 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-2x-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png index 7a2f59080..d7ee9ff26 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-alt-click-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png index aac33499e..11ecdabd0 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png index 694049cdd..8723985d2 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-context-menu-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png index a73a56622..c07494c21 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/native-reroute-delete-from-midpoint-context-menu-chromium-linux.png differ diff --git a/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png b/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png index 38c957f06..6e63295b8 100644 Binary files a/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png and b/browser_tests/tests/rerouteNode.spec.ts-snapshots/reroute-inserted-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png index 8d2b7c63f..d141d9912 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-group-group-added-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png index a44032d6d..2755d74c5 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/add-node-node-added-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png index ce3c5ac6b..fbadb08da 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/node-pinned-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png index 520dfbb51..a73ca4c33 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-menu-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png index dc82953e1..238946afa 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-bypassed-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png index 2ae5c3ff2..1635e4e89 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png index 5241f3517..4c1ed8d69 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-badge-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png index 31ac480af..ea0156109 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-collapsed-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png index b92e9b1aa..4910f554a 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-group-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png index 26e017ff5..f381be240 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-node-properties-panel-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png index fc30c3368..4440ef029 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-pinned-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png index 2ae5c3ff2..1635e4e89 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png index 59ea157f9..700e9d2c5 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/right-click-unpinned-node-moved-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png index 349014360..a6d09ff18 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-2-nodes-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png index 5e26ed857..c0b91f3ec 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-pinned-chromium-linux.png differ diff --git a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png index a3c584b32..a80e1ad38 100644 Binary files a/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png and b/browser_tests/tests/rightClickMenu.spec.ts-snapshots/selected-nodes-unpinned-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png index 0d9878344..96f6507e1 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-nodes-border-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png index 7c454dd81..af92221f3 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-multiple-selections-border-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png index 8973c1ed3..f9b9b012c 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-node-no-border-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png index c0112a796..2006231c7 100644 Binary files a/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png and b/browser_tests/tests/selectionToolbox.spec.ts-snapshots/selection-toolbox-single-selection-no-border-chromium-linux.png differ diff --git a/browser_tests/tests/selectionToolboxSubmenus.spec.ts b/browser_tests/tests/selectionToolboxSubmenus.spec.ts new file mode 100644 index 000000000..a7311c15a --- /dev/null +++ b/browser_tests/tests/selectionToolboxSubmenus.spec.ts @@ -0,0 +1,177 @@ +import { expect } from '@playwright/test' + +import { comfyPageFixture as test } from '../fixtures/ComfyPage' + +test.describe('Selection Toolbox - More Options Submenus', () => { + test.beforeEach(async ({ comfyPage }) => { + await comfyPage.setSetting('Comfy.Canvas.SelectionToolbox', true) + await comfyPage.loadWorkflow('nodes/single_ksampler') + await comfyPage.nextFrame() + await comfyPage.selectNodes(['KSampler']) + await comfyPage.nextFrame() + }) + + const openMoreOptions = async (comfyPage: any) => { + const ksamplerNodes = await comfyPage.getNodeRefsByTitle('KSampler') + if (ksamplerNodes.length === 0) { + throw new Error('No KSampler nodes found') + } + + // Drag the KSampler to the center of the screen + const nodePos = await ksamplerNodes[0].getPosition() + const viewportSize = comfyPage.page.viewportSize() + const centerX = viewportSize.width / 3 + const centerY = viewportSize.height / 2 + await comfyPage.dragAndDrop( + { x: nodePos.x, y: nodePos.y }, + { x: centerX, y: centerY } + ) + await comfyPage.nextFrame() + + await ksamplerNodes[0].click('title') + await comfyPage.nextFrame() + await comfyPage.page.waitForTimeout(500) + + await expect(comfyPage.page.locator('.selection-toolbox')).toBeVisible({ + timeout: 5000 + }) + + const moreOptionsBtn = comfyPage.page.locator( + '[data-testid="more-options-button"]' + ) + await expect(moreOptionsBtn).toBeVisible({ timeout: 3000 }) + + await comfyPage.page.click('[data-testid="more-options-button"]') + + await comfyPage.nextFrame() + + const menuOptionsVisible = await comfyPage.page + .getByText('Rename') + .isVisible({ timeout: 2000 }) + .catch(() => false) + if (menuOptionsVisible) { + return + } + + await moreOptionsBtn.click({ force: true }) + await comfyPage.nextFrame() + await comfyPage.page.waitForTimeout(2000) + + const menuOptionsVisibleAfterClick = await comfyPage.page + .getByText('Rename') + .isVisible({ timeout: 2000 }) + .catch(() => false) + if (menuOptionsVisibleAfterClick) { + return + } + + throw new Error('Could not open More Options menu - popover not showing') + } + + test('opens Node Info from More Options menu', async ({ comfyPage }) => { + await openMoreOptions(comfyPage) + const nodeInfoButton = comfyPage.page.getByText('Node Info', { + exact: true + }) + await expect(nodeInfoButton).toBeVisible() + await nodeInfoButton.click() + await comfyPage.nextFrame() + }) + + test('changes node shape via Shape submenu', async ({ comfyPage }) => { + const nodeRef = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] + const initialShape = await nodeRef.getProperty('shape') + + await openMoreOptions(comfyPage) + await comfyPage.page.getByText('Shape', { exact: true }).click() + await expect(comfyPage.page.getByText('Box', { exact: true })).toBeVisible({ + timeout: 5000 + }) + await comfyPage.page.getByText('Box', { exact: true }).click() + await comfyPage.nextFrame() + + const newShape = await nodeRef.getProperty('shape') + expect(newShape).not.toBe(initialShape) + expect(newShape).toBe(1) + }) + + test('changes node color via Color submenu swatch', async ({ comfyPage }) => { + const nodeRef = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] + const initialColor = await nodeRef.getProperty('color') + + await openMoreOptions(comfyPage) + await comfyPage.page.getByText('Color', { exact: true }).click() + const blueSwatch = comfyPage.page.locator('[title="Blue"]') + await expect(blueSwatch.first()).toBeVisible({ timeout: 5000 }) + await blueSwatch.first().click() + await comfyPage.nextFrame() + + const newColor = await nodeRef.getProperty('color') + expect(newColor).toBe('#223') + if (initialColor) { + expect(newColor).not.toBe(initialColor) + } + }) + + test('renames a node using Rename action', async ({ comfyPage }) => { + const nodeRef = (await comfyPage.getNodeRefsByTitle('KSampler'))[0] + await openMoreOptions(comfyPage) + await comfyPage.page + .getByText('Rename', { exact: true }) + .click({ force: true }) + const input = comfyPage.page.locator( + '.group-title-editor.node-title-editor .editable-text input' + ) + await expect(input).toBeVisible() + await input.fill('RenamedNode') + await input.press('Enter') + await comfyPage.nextFrame() + const newTitle = await nodeRef.getProperty('title') + expect(newTitle).toBe('RenamedNode') + }) + + test('closes More Options menu when clicking outside', async ({ + comfyPage + }) => { + await openMoreOptions(comfyPage) + await expect( + comfyPage.page.getByText('Rename', { exact: true }) + ).toBeVisible({ timeout: 5000 }) + + await comfyPage.page + .locator('#graph-canvas') + .click({ position: { x: 0, y: 50 }, force: true }) + await comfyPage.nextFrame() + await expect( + comfyPage.page.getByText('Rename', { exact: true }) + ).not.toBeVisible() + }) + + test('closes More Options menu when clicking the button again (toggle)', async ({ + comfyPage + }) => { + await openMoreOptions(comfyPage) + await expect( + comfyPage.page.getByText('Rename', { exact: true }) + ).toBeVisible({ timeout: 5000 }) + + await comfyPage.page.evaluate(() => { + const btn = document.querySelector('[data-testid="more-options-button"]') + if (btn) { + const event = new MouseEvent('click', { + bubbles: true, + cancelable: true, + view: window, + detail: 1 + }) + btn.dispatchEvent(event) + } + }) + await comfyPage.nextFrame() + await comfyPage.page.waitForTimeout(500) + + await expect( + comfyPage.page.getByText('Rename', { exact: true }) + ).not.toBeVisible() + }) +}) diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png index 719ec65e4..ce88325aa 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-card-after-hover-chromium-linux.png differ diff --git a/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png b/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png index b880fca84..bf1d18934 100644 Binary files a/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png and b/browser_tests/tests/templates.spec.ts-snapshots/template-card-before-hover-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/deleteKeyInteraction.spec.ts b/browser_tests/tests/vueNodes/deleteKeyInteraction.spec.ts new file mode 100644 index 000000000..a00d93eb0 --- /dev/null +++ b/browser_tests/tests/vueNodes/deleteKeyInteraction.spec.ts @@ -0,0 +1,141 @@ +import { expect } from '@playwright/test' + +import { comfyPageFixture as test } from '../../fixtures/ComfyPage' + +test.describe('Vue Nodes - Delete Key Interaction', () => { + test.beforeEach(async ({ comfyPage }) => { + // Enable Vue nodes rendering + await comfyPage.setSetting('Comfy.VueNodes.Enabled', true) + await comfyPage.setSetting('Comfy.Graph.CanvasMenu', false) + await comfyPage.setup() + }) + + test('Can select all and delete Vue nodes with Delete key', async ({ + comfyPage + }) => { + await comfyPage.vueNodes.waitForNodes() + + // Get initial Vue node count + const initialNodeCount = await comfyPage.vueNodes.getNodeCount() + expect(initialNodeCount).toBeGreaterThan(0) + + // Select all Vue nodes + await comfyPage.ctrlA() + + // Verify all Vue nodes are selected + const selectedCount = await comfyPage.vueNodes.getSelectedNodeCount() + expect(selectedCount).toBe(initialNodeCount) + + // Delete with Delete key + await comfyPage.vueNodes.deleteSelected() + + // Verify all Vue nodes were deleted + const finalNodeCount = await comfyPage.vueNodes.getNodeCount() + expect(finalNodeCount).toBe(0) + }) + + test('Can select specific Vue node and delete it', async ({ comfyPage }) => { + await comfyPage.vueNodes.waitForNodes() + + // Get initial Vue node count + const initialNodeCount = await comfyPage.vueNodes.getNodeCount() + expect(initialNodeCount).toBeGreaterThan(0) + + // Get first Vue node ID and select it + const nodeIds = await comfyPage.vueNodes.getNodeIds() + await comfyPage.vueNodes.selectNode(nodeIds[0]) + + // Verify selection + const selectedCount = await comfyPage.vueNodes.getSelectedNodeCount() + expect(selectedCount).toBe(1) + + // Delete with Delete key + await comfyPage.vueNodes.deleteSelected() + + // Verify one Vue node was deleted + const finalNodeCount = await comfyPage.vueNodes.getNodeCount() + expect(finalNodeCount).toBe(initialNodeCount - 1) + }) + + test('Can select and delete Vue node with Backspace key', async ({ + comfyPage + }) => { + await comfyPage.vueNodes.waitForNodes() + + const initialNodeCount = await comfyPage.vueNodes.getNodeCount() + + // Select first Vue node + const nodeIds = await comfyPage.vueNodes.getNodeIds() + await comfyPage.vueNodes.selectNode(nodeIds[0]) + + // Delete with Backspace key instead of Delete + await comfyPage.vueNodes.deleteSelectedWithBackspace() + + // Verify Vue node was deleted + const finalNodeCount = await comfyPage.vueNodes.getNodeCount() + expect(finalNodeCount).toBe(initialNodeCount - 1) + }) + + test('Delete key does not delete node when typing in Vue node widgets', async ({ + comfyPage + }) => { + const initialNodeCount = await comfyPage.getGraphNodesCount() + + // Find a text input widget in a Vue node + const textWidget = comfyPage.page + .locator('input[type="text"], textarea') + .first() + + // Click on text widget to focus it + await textWidget.click() + await textWidget.fill('test text') + + // Press Delete while focused on widget - should delete text, not node + await textWidget.press('Delete') + + // Node count should remain the same + const finalNodeCount = await comfyPage.getGraphNodesCount() + expect(finalNodeCount).toBe(initialNodeCount) + }) + + test('Delete key does not delete node when nothing is selected', async ({ + comfyPage + }) => { + await comfyPage.vueNodes.waitForNodes() + + // Ensure no Vue nodes are selected + await comfyPage.vueNodes.clearSelection() + const selectedCount = await comfyPage.vueNodes.getSelectedNodeCount() + expect(selectedCount).toBe(0) + + // Press Delete key - should not crash and should handle gracefully + await comfyPage.page.keyboard.press('Delete') + + // Vue node count should remain the same + const nodeCount = await comfyPage.vueNodes.getNodeCount() + expect(nodeCount).toBeGreaterThan(0) + }) + + test('Can multi-select with Ctrl+click and delete multiple Vue nodes', async ({ + comfyPage + }) => { + await comfyPage.vueNodes.waitForNodes() + const initialNodeCount = await comfyPage.vueNodes.getNodeCount() + + // Multi-select first two Vue nodes using Ctrl+click + const nodeIds = await comfyPage.vueNodes.getNodeIds() + const nodesToSelect = nodeIds.slice(0, 2) + await comfyPage.vueNodes.selectNodes(nodesToSelect) + + // Verify expected nodes are selected + const selectedCount = await comfyPage.vueNodes.getSelectedNodeCount() + expect(selectedCount).toBe(nodesToSelect.length) + + // Delete selected Vue nodes + await comfyPage.vueNodes.deleteSelected() + + // Verify expected nodes were deleted + const finalNodeCount = await comfyPage.vueNodes.getNodeCount() + expect(finalNodeCount).toBe(initialNodeCount - nodesToSelect.length) + }) +}) diff --git a/browser_tests/tests/widget.spec.ts b/browser_tests/tests/widget.spec.ts index b23faabfc..728b5d028 100644 --- a/browser_tests/tests/widget.spec.ts +++ b/browser_tests/tests/widget.spec.ts @@ -264,7 +264,13 @@ test.describe('Animated image widget', () => { expect(filename).toContain('animated_webp.webp') }) - test('Can preview saved animated webp image', async ({ comfyPage }) => { + // FIXME: This test keeps flip-flopping because it relies on animated webp timing, + // which is inherently unreliable in CI environments. The test asset is an animated + // webp with 2 frames, and the test depends on animation frame timing to verify that + // animated webp images are properly displayed (as opposed to being treated as static webp). + // While the underlying functionality works (animated webp are correctly distinguished + // from static webp), the test is flaky due to timing dependencies with webp animation frames. + test.fixme('Can preview saved animated webp image', async ({ comfyPage }) => { await comfyPage.loadWorkflow('widgets/save_animated_webp') // Get position of the load animated webp node diff --git a/browser_tests/tests/widget.spec.ts-snapshots/animated-image-preview-saved-webp-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/animated-image-preview-saved-webp-chromium-linux.png deleted file mode 100644 index b2fe8bb40..000000000 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/animated-image-preview-saved-webp-chromium-linux.png and /dev/null differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png index 2879c3d15..05764b532 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png index d882ba9fb..fb055e8c8 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/boolean-widget-toggled-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png index 4bd504117..745e69148 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/empty-latent-resized-80-percent-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png index 39bd0fd14..0b7cb495d 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-changed-by-combo-value-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png index 39bd0fd14..0b7cb495d 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/image-preview-drag-and-dropped-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png index 2d95e6dd1..520576df1 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-resized-min-width-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png index 52f20bbce..1b01d4972 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/ksampler-widget-added-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png index 9fd907f38..fde5a2de9 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/load-audio-widget-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png index 5af9039e0..538e0b460 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/load-checkpoint-resized-min-width-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png index 843ebacc7..b631cd32d 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/load-image-widget-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png index 566ab88e8..d5e10e061 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/resized-to-original-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png index ff3fdcbfb..b356214e8 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/seed-widget-dragged-chromium-linux.png differ diff --git a/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png b/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png index 6fe4d1e2b..2c82d9c8d 100644 Binary files a/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png and b/browser_tests/tests/widget.spec.ts-snapshots/slider-widget-dragged-chromium-linux.png differ diff --git a/components.json b/components.json new file mode 100644 index 000000000..5526f900d --- /dev/null +++ b/components.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://shadcn-vue.com/schema.json", + "style": "new-york", + "typescript": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/assets/css/style.css", + "baseColor": "stone", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "composables": "@/composables", + "utils": "@/utils", + "ui": "@/components/ui", + "lib": "@/lib" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/docs/adr/0004-fork-primevue-ui-library.md b/docs/adr/0004-fork-primevue-ui-library.md new file mode 100644 index 000000000..02bd18736 --- /dev/null +++ b/docs/adr/0004-fork-primevue-ui-library.md @@ -0,0 +1,62 @@ +# 4. Fork PrimeVue UI Library + +Date: 2025-08-27 + +## Status + +Rejected + +## Context + +ComfyUI's frontend requires modifications to PrimeVue components that cannot be achieved through the library's customization APIs. Two specific technical incompatibilities have been identified with the transform-based canvas architecture: + +**Screen Coordinate Hit-Testing Conflicts:** +- PrimeVue components use `getBoundingClientRect()` for screen coordinate calculations that don't account for CSS transforms +- The Slider component directly uses raw `pageX/pageY` coordinates ([lines 102-103](https://github.com/primefaces/primevue/blob/master/packages/primevue/src/slider/Slider.vue#L102-L103)) without transform-aware positioning +- This breaks interaction in transformed coordinate spaces where screen coordinates don't match logical element positions + +**Virtual Canvas Scroll Interference:** +- LiteGraph's infinite canvas uses scroll coordinates semantically for graph navigation via the `DragAndScale` coordinate system +- PrimeVue overlay components automatically trigger `scrollIntoView` behavior which interferes with this virtual positioning +- This issue is documented in [PrimeVue discussion #4270](https://github.com/orgs/primefaces/discussions/4270) where the feature request was made to disable this behavior + +**Historical Overlay Issues:** +- Previous z-index positioning conflicts required manual workarounds (commit `6d4eafb0`) where PrimeVue Dialog components needed `autoZIndex: false` and custom mask styling, later resolved by removing PrimeVue's automatic z-index management entirely + +**Minimal Update Overhead:** +- Analysis of git history shows only 2 PrimeVue version updates in 2+ years, indicating that upstream sync overhead is negligible for this project + +**Future Interaction System Requirements:** +- The ongoing canvas architecture evolution will require more granular control over component interaction and event handling as the transform-based system matures +- Predictable need for additional component modifications beyond current identified issues + +## Decision + +We will **NOT** fork PrimeVue. After evaluation, forking was determined to be unnecessarily complex and costly. + +**Rationale for Rejection:** + +- **Significant Implementation Complexity**: PrimeVue is structured as a monorepo ([primefaces/primevue](https://github.com/primefaces/primevue)) with significant code in a separate monorepo ([PrimeUIX](https://github.com/primefaces/primeuix)). Forking would require importing both repositories whole and selectively pruning or exempting components from our workspace tooling, adding substantial complexity. + +- **Alternative Solutions Available**: The modifications we identified (e.g., scroll interference issues, coordinate system conflicts) have less costly solutions that don't require maintaining a full fork. For example, coordinate issues could be addressed through event interception and synthetic event creation with scaled values. + +- **Maintenance Burden**: Ongoing maintenance and upgrades would be very painful, requiring manual conflict resolution and keeping pace with upstream changes across multiple repositories. + +- **Limited Tooling Support**: There isn't adequate tooling that provides the granularity needed to cleanly manage a PrimeVue fork within our existing infrastructure. + +## Consequences + +### Alternative Approach + +- **Use PrimeVue as External Dependency**: Continue using PrimeVue as a standard npm dependency +- **Targeted Workarounds**: Implement specific solutions for identified issues (coordinate system conflicts, scroll interference) without forking the entire library +- **Selective Component Replacement**: Use libraries like shadcn/ui to replace specific problematic PrimeVue components and adjust them to match our design system +- **Upstream Engagement**: Continue engaging with PrimeVue community for feature requests and bug reports +- **Maintain Flexibility**: Preserve ability to upgrade PrimeVue versions without fork maintenance overhead + +## Notes + +- Technical issues documented in the Context section remain valid concerns +- Solutions will be pursued through targeted fixes rather than wholesale forking +- Future re-evaluation possible if PrimeVue's architecture significantly changes or if alternative tooling becomes available +- This decision prioritizes maintainability and development velocity over maximum customization control diff --git a/docs/adr/README.md b/docs/adr/README.md index 00e50a639..5f6e5c2cf 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -13,6 +13,7 @@ An Architecture Decision Record captures an important architectural decision mad | [0001](0001-merge-litegraph-into-frontend.md) | Merge LiteGraph.js into ComfyUI Frontend | Accepted | 2025-08-05 | | [0002](0002-monorepo-conversion.md) | Restructure as a Monorepo | Accepted | 2025-08-25 | | [0003](0003-crdt-based-layout-system.md) | Centralized Layout Management with CRDT | Proposed | 2025-08-27 | +| [0004](0004-fork-primevue-ui-library.md) | Fork PrimeVue UI Library | Rejected | 2025-08-27 | ## Creating a New ADR diff --git a/eslint.config.js b/eslint.config.js index 7e3248b20..cddba3bbd 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -64,6 +64,9 @@ export default [ 'vue/no-v-html': 'off', // Enforce dark-theme: instead of dark: prefix 'vue/no-restricted-class': ['error', '/^dark:/'], + 'vue/multi-word-component-names': 'off', // TODO: fix + 'vue/no-template-shadow': 'off', // TODO: fix + 'vue/one-component-per-file': 'off', // TODO: fix // Restrict deprecated PrimeVue components 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index 63a28a2dc..e568820c0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@comfyorg/comfyui-frontend", "private": true, - "version": "1.27.2", + "version": "1.27.4", "type": "module", "repository": "https://github.com/Comfy-Org/ComfyUI_frontend", "homepage": "https://comfy.org", @@ -25,10 +25,10 @@ "preinstall": "npx only-allow pnpm", "prepare": "husky || true && git config blame.ignoreRevsFile .git-blame-ignore-revs || true", "preview": "nx preview", - "lint": "eslint src --cache --concurrency=$npm_package_config_eslint_concurrency", - "lint:fix": "eslint src --fix --cache --concurrency=$npm_package_config_eslint_concurrency", - "lint:no-cache": "eslint src --concurrency=$npm_package_config_eslint_concurrency", - "lint:fix:no-cache": "eslint src --fix --concurrency=$npm_package_config_eslint_concurrency", + "lint": "eslint src --cache", + "lint:fix": "eslint src --cache --fix", + "lint:no-cache": "eslint src", + "lint:fix:no-cache": "eslint src --fix", "knip": "knip --cache", "knip:no-cache": "knip", "locale": "lobe-i18n locale", @@ -37,9 +37,6 @@ "storybook": "nx storybook -p 6006", "build-storybook": "storybook build" }, - "config": { - "eslint_concurrency": "4" - }, "devDependencies": { "@eslint/js": "^9.8.0", "@iconify-json/lucide": "^1.2.66", @@ -86,6 +83,7 @@ "tailwindcss": "^4.1.12", "tailwindcss-primeui": "^0.6.1", "tsx": "^4.15.6", + "tw-animate-css": "^1.3.8", "typescript": "^5.4.5", "typescript-eslint": "^8.42.0", "unplugin-icons": "^0.22.0", @@ -103,7 +101,7 @@ "dependencies": { "@alloc/quick-lru": "^5.2.0", "@atlaskit/pragmatic-drag-and-drop": "^1.3.1", - "@comfyorg/comfyui-electron-types": "^0.4.69", + "@comfyorg/comfyui-electron-types": "0.4.73-0", "@iconify/json": "^2.2.380", "@primeuix/forms": "0.0.2", "@primeuix/styled": "0.3.2", @@ -143,6 +141,7 @@ "pinia": "^2.1.7", "primeicons": "^7.0.0", "primevue": "^4.2.5", + "reka-ui": "^2.5.0", "semver": "^7.7.2", "tailwind-merge": "^3.3.1", "three": "^0.170.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 68fbf59b2..acc01cc0c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^1.3.1 version: 1.3.1 '@comfyorg/comfyui-electron-types': - specifier: ^0.4.69 - version: 0.4.69 + specifier: 0.4.73-0 + version: 0.4.73-0 '@iconify/json': specifier: ^2.2.380 version: 2.2.380 @@ -134,6 +134,9 @@ importers: primevue: specifier: ^4.2.5 version: 4.2.5(vue@3.5.13(typescript@5.9.2)) + reka-ui: + specifier: ^2.5.0 + version: 2.5.0(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)) semver: specifier: ^7.7.2 version: 7.7.2 @@ -303,6 +306,9 @@ importers: tsx: specifier: ^4.15.6 version: 4.19.4 + tw-animate-css: + specifier: ^1.3.8 + version: 1.3.8 typescript: specifier: ^5.4.5 version: 5.9.2 @@ -980,8 +986,8 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} - '@comfyorg/comfyui-electron-types@0.4.69': - resolution: {integrity: sha512-emEapJvbbx8lXiJ/84gmk+fYU73MmqkQKgBDQkyDwctcOb+eNe347PaH/+0AIjX8A/DtFHfnwgh9J8k3RVdqZA==} + '@comfyorg/comfyui-electron-types@0.4.73-0': + resolution: {integrity: sha512-WlItGJQx9ZWShNG9wypx3kq+19pSig/U+s5sD2SAeEcMph4u8A/TS+lnRgdKhT58VT1uD7cMcj2SJpfdBPNWvw==} '@csstools/color-helpers@5.1.0': resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} @@ -1570,6 +1576,18 @@ packages: '@firebase/webchannel-wrapper@1.0.3': resolution: {integrity: sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==} + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} + + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + + '@floating-ui/vue@1.1.9': + resolution: {integrity: sha512-BfNqNW6KA83Nexspgb9DZuz578R7HT8MZw1CfK9I6Ah4QReNWEJsXWHN+SdmOVLNGmTPDi+fDT535Df5PzMLbQ==} + '@grpc/grpc-js@1.9.15': resolution: {integrity: sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==} engines: {node: ^8.13.0 || >=10.10.0} @@ -1610,6 +1628,12 @@ packages: '@iconify/utils@2.3.0': resolution: {integrity: sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==} + '@internationalized/date@3.9.0': + resolution: {integrity: sha512-yaN3brAnHRD+4KyyOsJyk49XUvj2wtbNACSqg0bz3u8t2VuzhC8Q5dfRnrSxjnnbDb+ienBnkn1TzQfE154vyg==} + + '@internationalized/number@3.6.5': + resolution: {integrity: sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g==} + '@intlify/core-base@9.14.3': resolution: {integrity: sha512-nbJ7pKTlXFnaXPblyfiH6awAx1C0PWNNuqXAR74yRwgi5A/Re/8/5fErLY0pv4R8+EHj3ZaThMHdnuC/5OBa6g==} engines: {node: '>= 16'} @@ -2243,6 +2267,9 @@ packages: storybook: ^9.1.1 vue: ^3.0.0 + '@swc/helpers@0.5.17': + resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} + '@tailwindcss/node@4.1.12': resolution: {integrity: sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==} @@ -2333,6 +2360,14 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 || ^7 + '@tanstack/virtual-core@3.13.12': + resolution: {integrity: sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==} + + '@tanstack/vue-virtual@3.13.12': + resolution: {integrity: sha512-vhF7kEU9EXWXh+HdAwKJ2m3xaOnTTmgcdXcF2pim8g4GvI7eRrk2YRuV5nUlZnd/NbCIX4/Ja2OZu5EjJL06Ww==} + peerDependencies: + vue: ^2.7.0 || ^3.0.0 + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -2609,6 +2644,9 @@ packages: '@types/web-bluetooth@0.0.20': resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + '@types/web-bluetooth@0.0.21': + resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==} + '@types/webxr@0.5.20': resolution: {integrity: sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==} @@ -2859,12 +2897,21 @@ packages: '@vueuse/core@11.0.0': resolution: {integrity: sha512-shibzNGjmRjZucEm97B8V0NO5J3vPHMCE/mltxQ3vHezbDoFQBMtK11XsfwfPionxSbo+buqPmsCljtYuXIBpw==} + '@vueuse/core@12.8.2': + resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==} + '@vueuse/metadata@11.0.0': resolution: {integrity: sha512-0TKsAVT0iUOAPWyc9N79xWYfovJVPATiOPVKByG6jmAYdDiwvMVm9xXJ5hp4I8nZDxpCcYlLq/Rg9w1Z/jrGcg==} + '@vueuse/metadata@12.8.2': + resolution: {integrity: sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==} + '@vueuse/shared@11.0.0': resolution: {integrity: sha512-i4ZmOrIEjSsL94uAEt3hz88UCz93fMyP/fba9S+vypX90fKg3uYX9cThqvWc9aXxuTzR0UGhOKOTQd//Goh1nQ==} + '@vueuse/shared@12.8.2': + resolution: {integrity: sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==} + '@webgpu/types@0.1.51': resolution: {integrity: sha512-ktR3u64NPjwIViNCck+z9QeyN0iPkQCUOQ07ZCV1RzlkfP+olLTeEZ95O1QHS+v4w9vJeY9xj/uJuSphsHy5rQ==} @@ -3018,6 +3065,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} @@ -3488,6 +3539,9 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -5105,6 +5159,9 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -5555,6 +5612,11 @@ packages: resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true + reka-ui@2.5.0: + resolution: {integrity: sha512-81aMAmJeVCy2k0E6x7n1kypDY6aM1ldLis5+zcdV1/JtoAlSDck5OBsyLRJU9CfgbrQp1ImnRnBSmC4fZ2fkZQ==} + peerDependencies: + vue: '>= 3.2.0' + relateurl@0.2.7: resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} engines: {node: '>= 0.10'} @@ -5989,6 +6051,9 @@ packages: engines: {node: '>=18.0.0'} hasBin: true + tw-animate-css@1.3.8: + resolution: {integrity: sha512-Qrk3PZ7l7wUcGYhwZloqfkWCmaXZAoqjkdbIDvzfGshwGtexa/DAs9koXxIkrpEasyevandomzCBAV1Yyop5rw==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -6291,8 +6356,8 @@ packages: vue-component-type-helpers@2.2.12: resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==} - vue-component-type-helpers@3.0.6: - resolution: {integrity: sha512-6CRM8X7EJqWCJOiKPvSLQG+hJPb/Oy2gyJx3pLjUEhY7PuaCthQu3e0zAGI1lqUBobrrk9IT0K8sG2GsCluxoQ==} + vue-component-type-helpers@3.0.7: + resolution: {integrity: sha512-TvyUcFXmjZcXUvU+r1MOyn4/vv4iF+tPwg5Ig33l/FJ3myZkxeQpzzQMLMFWcQAjr6Xs7BRwVy/TwbmNZUA/4w==} vue-demi@0.14.10: resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} @@ -7437,7 +7502,7 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@comfyorg/comfyui-electron-types@0.4.69': {} + '@comfyorg/comfyui-electron-types@0.4.73-0': {} '@csstools/color-helpers@5.1.0': {} @@ -7999,6 +8064,26 @@ snapshots: '@firebase/webchannel-wrapper@1.0.3': {} + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/utils@0.2.10': {} + + '@floating-ui/vue@1.1.9(vue@3.5.13(typescript@5.9.2))': + dependencies: + '@floating-ui/dom': 1.7.4 + '@floating-ui/utils': 0.2.10 + vue-demi: 0.14.10(vue@3.5.13(typescript@5.9.2)) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + '@grpc/grpc-js@1.9.15': dependencies: '@grpc/proto-loader': 0.7.13 @@ -8050,6 +8135,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@internationalized/date@3.9.0': + dependencies: + '@swc/helpers': 0.5.17 + + '@internationalized/number@3.6.5': + dependencies: + '@swc/helpers': 0.5.17 + '@intlify/core-base@9.14.3': dependencies: '@intlify/message-compiler': 9.14.3 @@ -8832,7 +8925,11 @@ snapshots: storybook: 9.1.1(@testing-library/dom@10.4.1)(prettier@3.3.2)(vite@5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2)) type-fest: 2.19.0 vue: 3.5.13(typescript@5.9.2) - vue-component-type-helpers: 3.0.6 + vue-component-type-helpers: 3.0.7 + + '@swc/helpers@0.5.17': + dependencies: + tslib: 2.8.1 '@tailwindcss/node@4.1.12': dependencies: @@ -8905,6 +9002,13 @@ snapshots: tailwindcss: 4.1.12 vite: 5.4.19(@types/node@20.14.10)(lightningcss@1.30.1)(terser@5.39.2) + '@tanstack/virtual-core@3.13.12': {} + + '@tanstack/vue-virtual@3.13.12(vue@3.5.13(typescript@5.9.2))': + dependencies: + '@tanstack/virtual-core': 3.13.12 + vue: 3.5.13(typescript@5.9.2) + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.27.1 @@ -9212,6 +9316,8 @@ snapshots: '@types/web-bluetooth@0.0.20': {} + '@types/web-bluetooth@0.0.21': {} + '@types/webxr@0.5.20': {} '@typescript-eslint/eslint-plugin@8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2))(eslint@9.35.0(jiti@2.4.2))(typescript@5.9.2)': @@ -9618,8 +9724,19 @@ snapshots: - '@vue/composition-api' - vue + '@vueuse/core@12.8.2(typescript@5.9.2)': + dependencies: + '@types/web-bluetooth': 0.0.21 + '@vueuse/metadata': 12.8.2 + '@vueuse/shared': 12.8.2(typescript@5.9.2) + vue: 3.5.13(typescript@5.9.2) + transitivePeerDependencies: + - typescript + '@vueuse/metadata@11.0.0': {} + '@vueuse/metadata@12.8.2': {} + '@vueuse/shared@11.0.0(vue@3.5.13(typescript@5.9.2))': dependencies: vue-demi: 0.14.10(vue@3.5.13(typescript@5.9.2)) @@ -9627,6 +9744,12 @@ snapshots: - '@vue/composition-api' - vue + '@vueuse/shared@12.8.2(typescript@5.9.2)': + dependencies: + vue: 3.5.13(typescript@5.9.2) + transitivePeerDependencies: + - typescript + '@webgpu/types@0.1.51': {} '@xterm/addon-fit@0.10.0(@xterm/xterm@5.5.0)': @@ -9775,6 +9898,10 @@ snapshots: argparse@2.0.1: {} + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + aria-query@5.3.0: dependencies: dequal: 2.0.3 @@ -10244,6 +10371,8 @@ snapshots: define-lazy-prop@3.0.0: {} + defu@6.1.4: {} + delayed-stream@1.0.0: {} dequal@2.0.3: {} @@ -12135,6 +12264,8 @@ snapshots: object-keys@1.1.1: {} + ohash@2.0.11: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -12711,6 +12842,23 @@ snapshots: dependencies: jsesc: 3.0.2 + reka-ui@2.5.0(typescript@5.9.2)(vue@3.5.13(typescript@5.9.2)): + dependencies: + '@floating-ui/dom': 1.7.4 + '@floating-ui/vue': 1.1.9(vue@3.5.13(typescript@5.9.2)) + '@internationalized/date': 3.9.0 + '@internationalized/number': 3.6.5 + '@tanstack/vue-virtual': 3.13.12(vue@3.5.13(typescript@5.9.2)) + '@vueuse/core': 12.8.2(typescript@5.9.2) + '@vueuse/shared': 12.8.2(typescript@5.9.2) + aria-hidden: 1.2.6 + defu: 6.1.4 + ohash: 2.0.11 + vue: 3.5.13(typescript@5.9.2) + transitivePeerDependencies: + - '@vue/composition-api' + - typescript + relateurl@0.2.7: {} remark-frontmatter@5.0.0: @@ -13158,6 +13306,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tw-animate-css@1.3.8: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -13504,7 +13654,7 @@ snapshots: vue-component-type-helpers@2.2.12: {} - vue-component-type-helpers@3.0.6: {} + vue-component-type-helpers@3.0.7: {} vue-demi@0.14.10(vue@3.5.13(typescript@5.9.2)): dependencies: diff --git a/scripts/cicd/extract-playwright-counts.ts b/scripts/cicd/extract-playwright-counts.ts new file mode 100755 index 000000000..ff6f44db3 --- /dev/null +++ b/scripts/cicd/extract-playwright-counts.ts @@ -0,0 +1,183 @@ +#!/usr/bin/env tsx +import fs from 'fs' +import path from 'path' + +interface TestStats { + expected?: number + unexpected?: number + flaky?: number + skipped?: number + finished?: number +} + +interface ReportData { + stats?: TestStats +} + +interface TestCounts { + passed: number + failed: number + flaky: number + skipped: number + total: number +} + +/** + * Extract test counts from Playwright HTML report + * @param reportDir - Path to the playwright-report directory + * @returns Test counts { passed, failed, flaky, skipped, total } + */ +function extractTestCounts(reportDir: string): TestCounts { + const counts: TestCounts = { + passed: 0, + failed: 0, + flaky: 0, + skipped: 0, + total: 0 + } + + try { + // First, try to find report.json which Playwright generates with JSON reporter + const jsonReportFile = path.join(reportDir, 'report.json') + if (fs.existsSync(jsonReportFile)) { + const reportJson: ReportData = JSON.parse( + fs.readFileSync(jsonReportFile, 'utf-8') + ) + if (reportJson.stats) { + const stats = reportJson.stats + counts.total = stats.expected || 0 + counts.passed = + (stats.expected || 0) - + (stats.unexpected || 0) - + (stats.flaky || 0) - + (stats.skipped || 0) + counts.failed = stats.unexpected || 0 + counts.flaky = stats.flaky || 0 + counts.skipped = stats.skipped || 0 + return counts + } + } + + // Try index.html - Playwright HTML report embeds data in a script tag + const indexFile = path.join(reportDir, 'index.html') + if (fs.existsSync(indexFile)) { + const content = fs.readFileSync(indexFile, 'utf-8') + + // Look for the embedded report data in various formats + // Format 1: window.playwrightReportBase64 + let dataMatch = content.match( + /window\.playwrightReportBase64\s*=\s*["']([^"']+)["']/ + ) + if (dataMatch) { + try { + const decodedData = Buffer.from(dataMatch[1], 'base64').toString( + 'utf-8' + ) + const reportData: ReportData = JSON.parse(decodedData) + + if (reportData.stats) { + const stats = reportData.stats + counts.total = stats.expected || 0 + counts.passed = + (stats.expected || 0) - + (stats.unexpected || 0) - + (stats.flaky || 0) - + (stats.skipped || 0) + counts.failed = stats.unexpected || 0 + counts.flaky = stats.flaky || 0 + counts.skipped = stats.skipped || 0 + return counts + } + } catch (e) { + // Continue to try other formats + } + } + + // Format 2: window.playwrightReport + dataMatch = content.match(/window\.playwrightReport\s*=\s*({[\s\S]*?});/) + if (dataMatch) { + try { + // Use Function constructor instead of eval for safety + const reportData = new Function( + 'return ' + dataMatch[1] + )() as ReportData + + if (reportData.stats) { + const stats = reportData.stats + counts.total = stats.expected || 0 + counts.passed = + (stats.expected || 0) - + (stats.unexpected || 0) - + (stats.flaky || 0) - + (stats.skipped || 0) + counts.failed = stats.unexpected || 0 + counts.flaky = stats.flaky || 0 + counts.skipped = stats.skipped || 0 + return counts + } + } catch (e) { + // Continue to try other formats + } + } + + // Format 3: Look for stats in the HTML content directly + // Playwright sometimes renders stats in the UI + const statsMatch = content.match( + /(\d+)\s+passed[^0-9]*(\d+)\s+failed[^0-9]*(\d+)\s+flaky[^0-9]*(\d+)\s+skipped/i + ) + if (statsMatch) { + counts.passed = parseInt(statsMatch[1]) || 0 + counts.failed = parseInt(statsMatch[2]) || 0 + counts.flaky = parseInt(statsMatch[3]) || 0 + counts.skipped = parseInt(statsMatch[4]) || 0 + counts.total = + counts.passed + counts.failed + counts.flaky + counts.skipped + return counts + } + + // Format 4: Try to extract from summary text patterns + const passedMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+passed/i) + const failedMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+failed/i) + const flakyMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+flaky/i) + const skippedMatch = content.match(/(\d+)\s+(?:tests?|specs?)\s+skipped/i) + const totalMatch = content.match( + /(\d+)\s+(?:tests?|specs?)\s+(?:total|ran)/i + ) + + if (passedMatch) counts.passed = parseInt(passedMatch[1]) || 0 + if (failedMatch) counts.failed = parseInt(failedMatch[1]) || 0 + if (flakyMatch) counts.flaky = parseInt(flakyMatch[1]) || 0 + if (skippedMatch) counts.skipped = parseInt(skippedMatch[1]) || 0 + if (totalMatch) { + counts.total = parseInt(totalMatch[1]) || 0 + } else if ( + counts.passed || + counts.failed || + counts.flaky || + counts.skipped + ) { + counts.total = + counts.passed + counts.failed + counts.flaky + counts.skipped + } + } + } catch (error) { + console.error(`Error reading report from ${reportDir}:`, error) + } + + return counts +} + +// Main execution +const reportDir = process.argv[2] + +if (!reportDir) { + console.error('Usage: extract-playwright-counts.ts ') + process.exit(1) +} + +const counts = extractTestCounts(reportDir) + +// Output as JSON for easy parsing in shell script +console.log(JSON.stringify(counts)) + +export { extractTestCounts } diff --git a/scripts/cicd/pr-playwright-deploy-and-comment.sh b/scripts/cicd/pr-playwright-deploy-and-comment.sh index 767a7f514..aeab37c8e 100755 --- a/scripts/cicd/pr-playwright-deploy-and-comment.sh +++ b/scripts/cicd/pr-playwright-deploy-and-comment.sh @@ -58,6 +58,12 @@ if ! command -v wrangler > /dev/null 2>&1; then } fi +# Check if tsx is available, install if not +if ! command -v tsx > /dev/null 2>&1; then + echo "Installing tsx..." >&2 + npm install -g tsx >&2 || echo "Failed to install tsx" >&2 +fi + # Deploy a single browser report, WARN: ensure inputs are sanitized before calling this function deploy_report() { dir="$1" @@ -159,12 +165,16 @@ else echo "Available reports:" ls -la reports/ 2>/dev/null || echo "Reports directory not found" - # Deploy all reports in parallel and collect URLs + # Deploy all reports in parallel and collect URLs + test counts temp_dir=$(mktemp -d) pids="" i=0 - # Start parallel deployments + # Store current working directory for absolute paths + SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + BASE_DIR="$(pwd)" + + # Start parallel deployments and count extractions for browser in $BROWSERS; do if [ -d "reports/playwright-report-$browser" ]; then echo "Found report for $browser, deploying in parallel..." @@ -172,11 +182,26 @@ else url=$(deploy_report "reports/playwright-report-$browser" "$browser" "$cloudflare_branch") echo "$url" > "$temp_dir/$i.url" echo "Deployment result for $browser: $url" + + # Extract test counts using tsx (TypeScript executor) + EXTRACT_SCRIPT="$SCRIPT_DIR/extract-playwright-counts.ts" + REPORT_DIR="$BASE_DIR/reports/playwright-report-$browser" + + if command -v tsx > /dev/null 2>&1 && [ -f "$EXTRACT_SCRIPT" ]; then + echo "Extracting counts from $REPORT_DIR using $EXTRACT_SCRIPT" >&2 + counts=$(tsx "$EXTRACT_SCRIPT" "$REPORT_DIR" 2>&1 || echo '{}') + echo "Extracted counts for $browser: $counts" >&2 + echo "$counts" > "$temp_dir/$i.counts" + else + echo "Script not found or tsx not available: $EXTRACT_SCRIPT" >&2 + echo '{}' > "$temp_dir/$i.counts" + fi ) & pids="$pids $!" else echo "Report not found for $browser at reports/playwright-report-$browser" echo "failed" > "$temp_dir/$i.url" + echo '{}' > "$temp_dir/$i.counts" fi i=$((i + 1)) done @@ -186,8 +211,9 @@ else wait $pid done - # Collect URLs in order + # Collect URLs and counts in order urls="" + all_counts="" i=0 for browser in $BROWSERS; do if [ -f "$temp_dir/$i.url" ]; then @@ -200,37 +226,147 @@ else else urls="$urls $url" fi + + if [ -f "$temp_dir/$i.counts" ]; then + counts=$(cat "$temp_dir/$i.counts") + echo "Read counts for $browser from $temp_dir/$i.counts: $counts" >&2 + else + counts="{}" + echo "No counts file found for $browser at $temp_dir/$i.counts" >&2 + fi + if [ -z "$all_counts" ]; then + all_counts="$counts" + else + all_counts="$all_counts|$counts" + fi + i=$((i + 1)) done # Clean up temp directory rm -rf "$temp_dir" + # Calculate total test counts across all browsers + total_passed=0 + total_failed=0 + total_flaky=0 + total_skipped=0 + total_tests=0 + + # Parse counts and calculate totals + IFS='|' + set -- $all_counts + for counts_json; do + if [ "$counts_json" != "{}" ] && [ -n "$counts_json" ]; then + # Parse JSON counts using simple grep/sed if jq is not available + if command -v jq > /dev/null 2>&1; then + passed=$(echo "$counts_json" | jq -r '.passed // 0') + failed=$(echo "$counts_json" | jq -r '.failed // 0') + flaky=$(echo "$counts_json" | jq -r '.flaky // 0') + skipped=$(echo "$counts_json" | jq -r '.skipped // 0') + total=$(echo "$counts_json" | jq -r '.total // 0') + else + # Fallback parsing without jq + passed=$(echo "$counts_json" | sed -n 's/.*"passed":\([0-9]*\).*/\1/p') + failed=$(echo "$counts_json" | sed -n 's/.*"failed":\([0-9]*\).*/\1/p') + flaky=$(echo "$counts_json" | sed -n 's/.*"flaky":\([0-9]*\).*/\1/p') + skipped=$(echo "$counts_json" | sed -n 's/.*"skipped":\([0-9]*\).*/\1/p') + total=$(echo "$counts_json" | sed -n 's/.*"total":\([0-9]*\).*/\1/p') + fi + + total_passed=$((total_passed + ${passed:-0})) + total_failed=$((total_failed + ${failed:-0})) + total_flaky=$((total_flaky + ${flaky:-0})) + total_skipped=$((total_skipped + ${skipped:-0})) + total_tests=$((total_tests + ${total:-0})) + fi + done + unset IFS + + # Determine overall status + if [ $total_failed -gt 0 ]; then + status_icon="❌" + status_text="Some tests failed" + elif [ $total_flaky -gt 0 ]; then + status_icon="⚠️" + status_text="Tests passed with flaky tests" + elif [ $total_tests -gt 0 ]; then + status_icon="✅" + status_text="All tests passed!" + else + status_icon="🕵🏻" + status_text="No test results found" + fi + # Generate completion comment comment="$COMMENT_MARKER ## 🎭 Playwright Test Results -✅ **Tests completed successfully!** +$status_icon **$status_text** -⏰ Completed at: $(date -u '+%m/%d/%Y, %I:%M:%S %p') UTC +⏰ Completed at: $(date -u '+%m/%d/%Y, %I:%M:%S %p') UTC" + + # Add summary counts if we have test data + if [ $total_tests -gt 0 ]; then + comment="$comment + +### 📈 Summary +- **Total Tests:** $total_tests +- **Passed:** $total_passed ✅ +- **Failed:** $total_failed $([ $total_failed -gt 0 ] && echo '❌' || echo '') +- **Flaky:** $total_flaky $([ $total_flaky -gt 0 ] && echo '⚠️' || echo '') +- **Skipped:** $total_skipped $([ $total_skipped -gt 0 ] && echo '⏭️' || echo '')" + fi + + comment="$comment ### 📊 Test Reports by Browser" - # Add browser results + # Add browser results with individual counts i=0 - for browser in $BROWSERS; do + IFS='|' + set -- $all_counts + for counts_json; do + # Get browser name + browser=$(echo "$BROWSERS" | cut -d' ' -f$((i + 1))) # Get URL at position i url=$(echo "$urls" | cut -d' ' -f$((i + 1))) if [ "$url" != "failed" ] && [ -n "$url" ]; then + # Parse individual browser counts + if [ "$counts_json" != "{}" ] && [ -n "$counts_json" ]; then + if command -v jq > /dev/null 2>&1; then + b_passed=$(echo "$counts_json" | jq -r '.passed // 0') + b_failed=$(echo "$counts_json" | jq -r '.failed // 0') + b_flaky=$(echo "$counts_json" | jq -r '.flaky // 0') + b_skipped=$(echo "$counts_json" | jq -r '.skipped // 0') + b_total=$(echo "$counts_json" | jq -r '.total // 0') + else + b_passed=$(echo "$counts_json" | sed -n 's/.*"passed":\([0-9]*\).*/\1/p') + b_failed=$(echo "$counts_json" | sed -n 's/.*"failed":\([0-9]*\).*/\1/p') + b_flaky=$(echo "$counts_json" | sed -n 's/.*"flaky":\([0-9]*\).*/\1/p') + b_skipped=$(echo "$counts_json" | sed -n 's/.*"skipped":\([0-9]*\).*/\1/p') + b_total=$(echo "$counts_json" | sed -n 's/.*"total":\([0-9]*\).*/\1/p') + fi + + if [ -n "$b_total" ] && [ "$b_total" != "0" ]; then + counts_str=" • ✅ $b_passed / ❌ $b_failed / ⚠️ $b_flaky / ⏭️ $b_skipped" + else + counts_str="" + fi + else + counts_str="" + fi + comment="$comment -- ✅ **${browser}**: [View Report](${url})" +- ✅ **${browser}**: [View Report](${url})${counts_str}" else comment="$comment - ❌ **${browser}**: Deployment failed" fi i=$((i + 1)) done + unset IFS comment="$comment diff --git a/scripts/collect-i18n-general.ts b/scripts/collect-i18n-general.ts index 63d97d530..f0b6dde0c 100644 --- a/scripts/collect-i18n-general.ts +++ b/scripts/collect-i18n-general.ts @@ -3,8 +3,8 @@ import * as fs from 'fs' import { comfyPageFixture as test } from '../browser_tests/fixtures/ComfyPage' import { CORE_MENU_COMMANDS } from '../src/constants/coreMenuCommands' import { SERVER_CONFIG_ITEMS } from '../src/constants/serverConfig' +import type { FormItem, SettingParams } from '../src/platform/settings/types' import type { ComfyCommandImpl } from '../src/stores/commandStore' -import type { FormItem, SettingParams } from '../src/types/settingTypes' import { formatCamelCase, normalizeI18nKey } from '../src/utils/formatUtil' const localePath = './src/locales/en/main.json' diff --git a/scripts/generate-json-schema.ts b/scripts/generate-json-schema.ts index 76aa41b2e..1a2056626 100644 --- a/scripts/generate-json-schema.ts +++ b/scripts/generate-json-schema.ts @@ -5,7 +5,7 @@ import { zodToJsonSchema } from 'zod-to-json-schema' import { zComfyWorkflow, zComfyWorkflow1 -} from '../src/schemas/comfyWorkflowSchema' +} from '../src/platform/workflow/validation/schemas/workflowSchema' import { zComfyNodeDef as zComfyNodeDefV2 } from '../src/schemas/nodeDef/nodeDefSchemaV2' import { zComfyNodeDef as zComfyNodeDefV1 } from '../src/schemas/nodeDefSchema' diff --git a/src/assets/css/style.css b/src/assets/css/style.css index 3258cbba5..70b6bf0d3 100644 --- a/src/assets/css/style.css +++ b/src/assets/css/style.css @@ -2,8 +2,9 @@ @import 'tailwindcss/theme' layer(theme); @import 'tailwindcss/utilities' layer(utilities); +@import 'tw-animate-css'; -@plugin "tailwindcss-primeui"; +@plugin 'tailwindcss-primeui'; @config '../../../tailwind.config.ts'; @@ -98,6 +99,7 @@ --color-danger-100: #c02323; --color-danger-200: #d62952; + --color-bypass: #6A246A; --color-error: #962a2a; --color-blue-selection: rgb( from var(--color-blue-100) r g b / 0.3); @@ -114,6 +116,14 @@ --color-dark-elevation-2: rgba(from white r g b / 0.03); } +@theme inline { + --color-node-component-surface: var(--color-charcoal-300); + --color-node-component-surface-highlight: var(--color-slate-100); + --color-node-component-surface-hovered: var(--color-charcoal-500); + --color-node-component-surface-selected: var(--color-charcoal-700); + --color-node-stroke: var(--color-stone-100); +} + @custom-variant dark-theme { .dark-theme & { @slot; @@ -952,9 +962,7 @@ audio.comfy-audio.empty-audio-widget { /* Uses default styling - no overrides needed */ } -/* Smooth transitions between LOD levels */ .lg-node { - transition: min-height 0.2s ease; /* Disable text selection on all nodes */ user-select: none; -webkit-user-select: none; diff --git a/src/assets/icons/custom/mask.svg b/src/assets/icons/custom/mask.svg new file mode 100644 index 000000000..1e1a6d97c --- /dev/null +++ b/src/assets/icons/custom/mask.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/base/common/downloadUtil.ts b/src/base/common/downloadUtil.ts new file mode 100644 index 000000000..307a3e35b --- /dev/null +++ b/src/base/common/downloadUtil.ts @@ -0,0 +1,41 @@ +/** + * Utility functions for downloading files + */ + +// Constants +const DEFAULT_DOWNLOAD_FILENAME = 'download.png' + +/** + * Download a file from a URL by creating a temporary anchor element + * @param url - The URL of the file to download (must be a valid URL string) + * @param filename - Optional filename override (will use URL filename or default if not provided) + * @throws {Error} If the URL is invalid or empty + */ +export const downloadFile = (url: string, filename?: string): void => { + if (!url || typeof url !== 'string' || url.trim().length === 0) { + throw new Error('Invalid URL provided for download') + } + const link = document.createElement('a') + link.href = url + link.download = + filename || extractFilenameFromUrl(url) || DEFAULT_DOWNLOAD_FILENAME + + // Trigger download + document.body.appendChild(link) + link.click() + document.body.removeChild(link) +} + +/** + * Extract filename from a URL's query parameters + * @param url - The URL to extract filename from + * @returns The extracted filename or null if not found + */ +const extractFilenameFromUrl = (url: string): string | null => { + try { + const urlObj = new URL(url, window.location.origin) + return urlObj.searchParams.get('filename') + } catch { + return null + } +} diff --git a/src/components/LiteGraphCanvasSplitterOverlay.vue b/src/components/LiteGraphCanvasSplitterOverlay.vue index bd5070250..6e3cd5842 100644 --- a/src/components/LiteGraphCanvasSplitterOverlay.vue +++ b/src/components/LiteGraphCanvasSplitterOverlay.vue @@ -50,7 +50,7 @@ import Splitter from 'primevue/splitter' import SplitterPanel from 'primevue/splitterpanel' import { computed } from 'vue' -import { useSettingStore } from '@/stores/settingStore' +import { useSettingStore } from '@/platform/settings/settingStore' import { useBottomPanelStore } from '@/stores/workspace/bottomPanelStore' import { useSidebarTabStore } from '@/stores/workspace/sidebarTabStore' diff --git a/src/components/MenuHamburger.vue b/src/components/MenuHamburger.vue index 58c725763..b46c27e27 100644 --- a/src/components/MenuHamburger.vue +++ b/src/components/MenuHamburger.vue @@ -23,8 +23,8 @@ import Button from 'primevue/button' import { CSSProperties, computed, watchEffect } from 'vue' +import { useSettingStore } from '@/platform/settings/settingStore' import { app } from '@/scripts/app' -import { useSettingStore } from '@/stores/settingStore' import { useWorkspaceStore } from '@/stores/workspaceStore' import { showNativeSystemMenu } from '@/utils/envUtil' diff --git a/src/components/actionbar/BatchCountEdit.vue b/src/components/actionbar/BatchCountEdit.vue index 281b886df..603ca6067 100644 --- a/src/components/actionbar/BatchCountEdit.vue +++ b/src/components/actionbar/BatchCountEdit.vue @@ -37,8 +37,8 @@ import { storeToRefs } from 'pinia' import InputNumber from 'primevue/inputnumber' import { computed } from 'vue' +import { useSettingStore } from '@/platform/settings/settingStore' import { useQueueSettingsStore } from '@/stores/queueStore' -import { useSettingStore } from '@/stores/settingStore' const queueSettingsStore = useQueueSettingsStore() const { batchCount } = storeToRefs(queueSettingsStore) diff --git a/src/components/actionbar/ComfyActionbar.vue b/src/components/actionbar/ComfyActionbar.vue index 24b3f8858..589815dc8 100644 --- a/src/components/actionbar/ComfyActionbar.vue +++ b/src/components/actionbar/ComfyActionbar.vue @@ -24,7 +24,7 @@ import { clamp } from 'es-toolkit/compat' import Panel from 'primevue/panel' import { Ref, computed, inject, nextTick, onMounted, ref, watch } from 'vue' -import { useSettingStore } from '@/stores/settingStore' +import { useSettingStore } from '@/platform/settings/settingStore' import ComfyQueueButton from './ComfyQueueButton.vue' @@ -37,7 +37,7 @@ const visible = computed(() => position.value !== 'Disabled') const topMenuRef = inject>('topMenuRef') const panelRef = ref(null) const dragHandleRef = ref(null) -const isDocked = useLocalStorage('Comfy.MenuPosition.Docked', false) +const isDocked = useLocalStorage('Comfy.MenuPosition.Docked', true) const storedPosition = useLocalStorage('Comfy.MenuPosition.Floating', { x: 0, y: 0 diff --git a/src/components/bottomPanel/tabs/terminal/BaseTerminal.vue b/src/components/bottomPanel/tabs/terminal/BaseTerminal.vue index 62741a4e5..52cb75a7f 100644 --- a/src/components/bottomPanel/tabs/terminal/BaseTerminal.vue +++ b/src/components/bottomPanel/tabs/terminal/BaseTerminal.vue @@ -3,13 +3,37 @@
+
diff --git a/src/components/graph/selectionToolbox/ExtensionCommandButton.vue b/src/components/graph/selectionToolbox/ExtensionCommandButton.vue index 3dc84f710..92cd09e38 100644 --- a/src/components/graph/selectionToolbox/ExtensionCommandButton.vue +++ b/src/components/graph/selectionToolbox/ExtensionCommandButton.vue @@ -7,6 +7,7 @@ }" severity="secondary" text + icon-class="w-4 h-4" :icon="typeof command.icon === 'function' ? command.icon() : command.icon" @click="() => commandStore.execute(command.id)" /> diff --git a/src/components/graph/selectionToolbox/FrameNodes.vue b/src/components/graph/selectionToolbox/FrameNodes.vue new file mode 100644 index 000000000..6d800a16f --- /dev/null +++ b/src/components/graph/selectionToolbox/FrameNodes.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/graph/selectionToolbox/HelpButton.vue b/src/components/graph/selectionToolbox/HelpButton.vue deleted file mode 100644 index e77701bd4..000000000 --- a/src/components/graph/selectionToolbox/HelpButton.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - diff --git a/src/components/graph/selectionToolbox/InfoButton.spec.ts b/src/components/graph/selectionToolbox/InfoButton.spec.ts new file mode 100644 index 000000000..da2a13831 --- /dev/null +++ b/src/components/graph/selectionToolbox/InfoButton.spec.ts @@ -0,0 +1,149 @@ +import { mount } from '@vue/test-utils' +import { createPinia, setActivePinia } from 'pinia' +import PrimeVue from 'primevue/config' +import Tooltip from 'primevue/tooltip' +import { beforeEach, describe, expect, it, vi } from 'vitest' +import { createI18n } from 'vue-i18n' + +import InfoButton from '@/components/graph/selectionToolbox/InfoButton.vue' +// NOTE: The component import must come after mocks so they take effect. +import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' +import { useNodeDefStore } from '@/stores/nodeDefStore' + +const mockLGraphNode = { + type: 'TestNode', + title: 'Test Node' +} + +vi.mock('@/utils/litegraphUtil', () => ({ + isLGraphNode: vi.fn(() => true) +})) + +vi.mock('@/composables/sidebarTabs/useNodeLibrarySidebarTab', () => ({ + useNodeLibrarySidebarTab: () => ({ + id: 'node-library' + }) +})) + +const openHelpMock = vi.fn() +const closeHelpMock = vi.fn() +const nodeHelpState: { currentHelpNode: any } = { currentHelpNode: null } +vi.mock('@/stores/workspace/nodeHelpStore', () => ({ + useNodeHelpStore: () => ({ + openHelp: (def: any) => { + nodeHelpState.currentHelpNode = def + openHelpMock(def) + }, + closeHelp: () => { + nodeHelpState.currentHelpNode = null + closeHelpMock() + }, + get currentHelpNode() { + return nodeHelpState.currentHelpNode + }, + get isHelpOpen() { + return nodeHelpState.currentHelpNode !== null + } + }) +})) + +const toggleSidebarTabMock = vi.fn((id: string) => { + sidebarState.activeSidebarTabId = + sidebarState.activeSidebarTabId === id ? null : id +}) +const sidebarState: { activeSidebarTabId: string | null } = { + activeSidebarTabId: 'other-tab' +} +vi.mock('@/stores/workspace/sidebarTabStore', () => ({ + useSidebarTabStore: () => ({ + get activeSidebarTabId() { + return sidebarState.activeSidebarTabId + }, + toggleSidebarTab: toggleSidebarTabMock + }) +})) + +describe('InfoButton', () => { + let canvasStore: ReturnType + let nodeDefStore: ReturnType + + const i18n = createI18n({ + legacy: false, + locale: 'en', + messages: { + en: { + g: { + info: 'Node Info' + } + } + } + }) + + beforeEach(() => { + setActivePinia(createPinia()) + canvasStore = useCanvasStore() + nodeDefStore = useNodeDefStore() + + vi.clearAllMocks() + }) + + const mountComponent = () => { + return mount(InfoButton, { + global: { + plugins: [i18n, PrimeVue], + directives: { tooltip: Tooltip }, + stubs: { + 'i-lucide:info': true, + Button: { + template: + '', + props: ['severity', 'text', 'class'], + emits: ['click'] + } + } + } + }) + } + + it('should handle click without errors', async () => { + const mockNodeDef = { + nodePath: 'test/node', + display_name: 'Test Node' + } + canvasStore.selectedItems = [mockLGraphNode] as any + vi.spyOn(nodeDefStore, 'fromLGraphNode').mockReturnValue(mockNodeDef as any) + const wrapper = mountComponent() + const button = wrapper.find('button') + await button.trigger('click') + expect(button.exists()).toBe(true) + }) + + it('should have correct CSS classes', () => { + const mockNodeDef = { + nodePath: 'test/node', + display_name: 'Test Node' + } + canvasStore.selectedItems = [mockLGraphNode] as any + vi.spyOn(nodeDefStore, 'fromLGraphNode').mockReturnValue(mockNodeDef as any) + + const wrapper = mountComponent() + const button = wrapper.find('button') + + expect(button.classes()).toContain('help-button') + expect(button.attributes('severity')).toBe('secondary') + }) + + it('should have correct tooltip', () => { + const mockNodeDef = { + nodePath: 'test/node', + display_name: 'Test Node' + } + canvasStore.selectedItems = [mockLGraphNode] as any + vi.spyOn(nodeDefStore, 'fromLGraphNode').mockReturnValue(mockNodeDef as any) + + const wrapper = mountComponent() + const button = wrapper.find('button') + + expect(button.exists()).toBe(true) + }) +}) diff --git a/src/components/graph/selectionToolbox/InfoButton.vue b/src/components/graph/selectionToolbox/InfoButton.vue new file mode 100644 index 000000000..3fd159d89 --- /dev/null +++ b/src/components/graph/selectionToolbox/InfoButton.vue @@ -0,0 +1,22 @@ + + + diff --git a/src/components/graph/selectionToolbox/Load3DViewerButton.vue b/src/components/graph/selectionToolbox/Load3DViewerButton.vue index b207e5018..5187f0c02 100644 --- a/src/components/graph/selectionToolbox/Load3DViewerButton.vue +++ b/src/components/graph/selectionToolbox/Load3DViewerButton.vue @@ -1,6 +1,5 @@ diff --git a/src/components/graph/selectionToolbox/MoreOptions.vue b/src/components/graph/selectionToolbox/MoreOptions.vue new file mode 100644 index 000000000..f40a49b60 --- /dev/null +++ b/src/components/graph/selectionToolbox/MoreOptions.vue @@ -0,0 +1,316 @@ + + + diff --git a/src/components/graph/selectionToolbox/PinButton.vue b/src/components/graph/selectionToolbox/PinButton.vue deleted file mode 100644 index 86598339b..000000000 --- a/src/components/graph/selectionToolbox/PinButton.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/components/graph/selectionToolbox/RefreshSelectionButton.vue b/src/components/graph/selectionToolbox/RefreshSelectionButton.vue index 786fe511f..0da7364a0 100644 --- a/src/components/graph/selectionToolbox/RefreshSelectionButton.vue +++ b/src/components/graph/selectionToolbox/RefreshSelectionButton.vue @@ -1,17 +1,22 @@ diff --git a/src/components/graph/selectionToolbox/SaveToSubgraphLibrary.vue b/src/components/graph/selectionToolbox/SaveToSubgraphLibrary.vue index 8fa1b94d6..7f76d2eab 100644 --- a/src/components/graph/selectionToolbox/SaveToSubgraphLibrary.vue +++ b/src/components/graph/selectionToolbox/SaveToSubgraphLibrary.vue @@ -21,8 +21,8 @@ import { computed } from 'vue' import { useI18n } from 'vue-i18n' import { SubgraphNode } from '@/lib/litegraph/src/litegraph' +import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { useCommandStore } from '@/stores/commandStore' -import { useCanvasStore } from '@/stores/graphStore' const { t } = useI18n() const commandStore = useCommandStore() diff --git a/src/components/graph/selectionToolbox/SubmenuPopover.vue b/src/components/graph/selectionToolbox/SubmenuPopover.vue new file mode 100644 index 000000000..056f0f90b --- /dev/null +++ b/src/components/graph/selectionToolbox/SubmenuPopover.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/components/graph/selectionToolbox/VerticalDivider.vue b/src/components/graph/selectionToolbox/VerticalDivider.vue new file mode 100644 index 000000000..dc6876a3e --- /dev/null +++ b/src/components/graph/selectionToolbox/VerticalDivider.vue @@ -0,0 +1,3 @@ + diff --git a/src/components/graph/widgets/DomWidget.vue b/src/components/graph/widgets/DomWidget.vue index 11cfafa1c..305af0621 100644 --- a/src/components/graph/widgets/DomWidget.vue +++ b/src/components/graph/widgets/DomWidget.vue @@ -23,10 +23,10 @@ import { CSSProperties, computed, nextTick, onMounted, ref, watch } from 'vue' import { useAbsolutePosition } from '@/composables/element/useAbsolutePosition' import { useDomClipping } from '@/composables/element/useDomClipping' +import { useSettingStore } from '@/platform/settings/settingStore' +import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' import { isComponentWidget, isDOMWidget } from '@/scripts/domWidget' import { DomWidgetState } from '@/stores/domWidgetStore' -import { useCanvasStore } from '@/stores/graphStore' -import { useSettingStore } from '@/stores/settingStore' const { widgetState } = defineProps<{ widgetState: DomWidgetState diff --git a/src/components/helpcenter/HelpCenterMenuContent.vue b/src/components/helpcenter/HelpCenterMenuContent.vue index c91589407..f90922e39 100644 --- a/src/components/helpcenter/HelpCenterMenuContent.vue +++ b/src/components/helpcenter/HelpCenterMenuContent.vue @@ -143,10 +143,10 @@ import { useI18n } from 'vue-i18n' import PuzzleIcon from '@/components/icons/PuzzleIcon.vue' import { useConflictAcknowledgment } from '@/composables/useConflictAcknowledgment' import { useManagerState } from '@/composables/useManagerState' -import { type ReleaseNote } from '@/services/releaseService' +import { useSettingStore } from '@/platform/settings/settingStore' +import { type ReleaseNote } from '@/platform/updates/common/releaseService' +import { useReleaseStore } from '@/platform/updates/common/releaseStore' import { useCommandStore } from '@/stores/commandStore' -import { useReleaseStore } from '@/stores/releaseStore' -import { useSettingStore } from '@/stores/settingStore' import { ManagerTab } from '@/types/comfyManagerTypes' import { electronAPI, isElectron } from '@/utils/envUtil' import { formatVersionAnchor } from '@/utils/formatUtil' diff --git a/src/components/input/MultiSelect.accessibility.stories.ts b/src/components/input/MultiSelect.accessibility.stories.ts new file mode 100644 index 000000000..5df8fe5a7 --- /dev/null +++ b/src/components/input/MultiSelect.accessibility.stories.ts @@ -0,0 +1,380 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' +import type { MultiSelectProps } from 'primevue/multiselect' +import { ref } from 'vue' + +import MultiSelect from './MultiSelect.vue' +import { type SelectOption } from './types' + +// Combine our component props with PrimeVue MultiSelect props +interface ExtendedProps extends Partial { + // Our custom props + label?: string + showSearchBox?: boolean + showSelectedCount?: boolean + showClearButton?: boolean + searchPlaceholder?: string + listMaxHeight?: string + popoverMinWidth?: string + popoverMaxWidth?: string + // Override modelValue type to match our Option type + modelValue?: SelectOption[] +} + +const meta: Meta = { + title: 'Components/Input/MultiSelect/Accessibility', + component: MultiSelect, + tags: ['autodocs'], + parameters: { + docs: { + description: { + component: ` +# MultiSelect Accessibility Guide + +This MultiSelect component provides full keyboard accessibility and screen reader support following WCAG 2.1 AA guidelines. + +## Keyboard Navigation + +- **Tab** - Focus the trigger button +- **Enter/Space** - Open/close dropdown when focused +- **Arrow Up/Down** - Navigate through options when dropdown is open +- **Enter/Space** - Select/deselect options when navigating +- **Escape** - Close dropdown + +## Screen Reader Support + +- Uses \`role="combobox"\` to identify as dropdown +- \`aria-haspopup="listbox"\` indicates popup contains list +- \`aria-expanded\` shows dropdown state +- \`aria-label\` provides accessible name with i18n fallback +- Selected count announced to screen readers + +## Testing Instructions + +1. **Tab Navigation**: Use Tab key to focus the component +2. **Keyboard Opening**: Press Enter or Space to open dropdown +3. **Option Navigation**: Use Arrow keys to navigate options +4. **Selection**: Press Enter/Space to select options +5. **Closing**: Press Escape to close dropdown +6. **Screen Reader**: Test with screen reader software + +Try these stories with keyboard-only navigation! + ` + } + } + }, + argTypes: { + label: { + control: 'text', + description: 'Label for the trigger button' + }, + showSearchBox: { + control: 'boolean', + description: 'Show search box in dropdown header' + }, + showSelectedCount: { + control: 'boolean', + description: 'Show selected count in dropdown header' + }, + showClearButton: { + control: 'boolean', + description: 'Show clear all button in dropdown header' + } + } +} + +export default meta +type Story = StoryObj + +const frameworkOptions = [ + { name: 'React', value: 'react' }, + { name: 'Vue', value: 'vue' }, + { name: 'Angular', value: 'angular' }, + { name: 'Svelte', value: 'svelte' }, + { name: 'TypeScript', value: 'typescript' }, + { name: 'JavaScript', value: 'javascript' } +] + +export const KeyboardNavigationDemo: Story = { + render: (args) => ({ + components: { MultiSelect }, + setup() { + const selectedFrameworks = ref([]) + const searchQuery = ref('') + + return { + args: { + ...args, + options: frameworkOptions, + modelValue: selectedFrameworks, + 'onUpdate:modelValue': (value: SelectOption[]) => { + selectedFrameworks.value = value + }, + 'onUpdate:searchQuery': (value: string) => { + searchQuery.value = value + } + }, + selectedFrameworks, + searchQuery + } + }, + template: ` +
+
+

🎯 Keyboard Navigation Test

+

+ Use your keyboard to navigate this MultiSelect: +

+
    +
  1. Tab to focus the dropdown
  2. +
  3. Enter/Space to open dropdown
  4. +
  5. Arrow Up/Down to navigate options
  6. +
  7. Enter/Space to select options
  8. +
  9. Escape to close dropdown
  10. +
+
+ +
+ + +

+ Selected: {{ selectedFrameworks.map(f => f.name).join(', ') || 'None' }} +

+
+
+ ` + }), + args: { + label: 'Choose Frameworks', + showSearchBox: true, + showSelectedCount: true, + showClearButton: true + } +} + +export const ScreenReaderFriendly: Story = { + render: (args) => ({ + components: { MultiSelect }, + setup() { + const selectedColors = ref([]) + const selectedSizes = ref([]) + + const colorOptions = [ + { name: 'Red', value: 'red' }, + { name: 'Blue', value: 'blue' }, + { name: 'Green', value: 'green' }, + { name: 'Yellow', value: 'yellow' } + ] + + const sizeOptions = [ + { name: 'Small', value: 'sm' }, + { name: 'Medium', value: 'md' }, + { name: 'Large', value: 'lg' }, + { name: 'Extra Large', value: 'xl' } + ] + + return { + selectedColors, + selectedSizes, + colorOptions, + sizeOptions, + args + } + }, + template: ` +
+
+

♿ Screen Reader Test

+

+ These dropdowns have proper ARIA attributes and labels for screen readers: +

+
    +
  • role="combobox" identifies as dropdown
  • +
  • aria-haspopup="listbox" indicates popup type
  • +
  • aria-expanded shows open/closed state
  • +
  • aria-label provides accessible name
  • +
  • Selection count announced to assistive technology
  • +
+
+ +
+
+ + +

+ {{ selectedColors.length }} color(s) selected +

+
+ +
+ + +

+ {{ selectedSizes.length }} size(s) selected +

+
+
+
+ ` + }) +} + +export const FocusManagement: Story = { + render: (args) => ({ + components: { MultiSelect }, + setup() { + const selectedItems = ref([]) + const focusTestOptions = [ + { name: 'Option A', value: 'a' }, + { name: 'Option B', value: 'b' }, + { name: 'Option C', value: 'c' } + ] + + return { + selectedItems, + focusTestOptions, + args + } + }, + template: ` +
+
+

🎯 Focus Management Test

+

+ Test focus behavior with multiple form elements: +

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+ Test: Tab through all elements and verify focus rings are visible and logical. +
+
+ ` + }) +} + +export const AccessibilityChecklist: Story = { + render: () => ({ + template: ` +
+
+

♿ MultiSelect Accessibility Checklist

+ +
+
+

✅ Implemented Features

+
    +
  • + + Keyboard Navigation: Tab, Enter, Space, Arrow keys, Escape +
  • +
  • + + ARIA Attributes: role, aria-haspopup, aria-expanded, aria-label +
  • +
  • + + Focus Management: Visible focus rings and logical tab order +
  • +
  • + + Internationalization: Translatable aria-label fallbacks +
  • +
  • + + Screen Reader Support: Proper announcements and state +
  • +
  • + + Color Contrast: Meets WCAG AA requirements +
  • +
+
+ +
+

📋 Testing Guidelines

+
    +
  1. Keyboard Only: Navigate using only keyboard
  2. +
  3. Screen Reader: Test with NVDA, JAWS, or VoiceOver
  4. +
  5. Focus Visible: Ensure focus rings are always visible
  6. +
  7. Tab Order: Verify logical progression
  8. +
  9. Announcements: Check state changes are announced
  10. +
  11. Escape Behavior: Escape always closes dropdown
  12. +
+
+
+ +
+

🎯 Quick Test

+

+ Close your eyes, use only the keyboard, and try to select multiple options from any dropdown above. + If you can successfully navigate and make selections, the accessibility implementation is working! +

+
+
+
+ ` + }) +} diff --git a/src/components/input/MultiSelect.stories.ts b/src/components/input/MultiSelect.stories.ts index e4b41d68f..45a1bdbdb 100644 --- a/src/components/input/MultiSelect.stories.ts +++ b/src/components/input/MultiSelect.stories.ts @@ -3,6 +3,7 @@ import type { MultiSelectProps } from 'primevue/multiselect' import { ref } from 'vue' import MultiSelect from './MultiSelect.vue' +import { type SelectOption } from './types' // Combine our component props with PrimeVue MultiSelect props // Since we use v-bind="$attrs", all PrimeVue props are available @@ -13,8 +14,11 @@ interface ExtendedProps extends Partial { showSelectedCount?: boolean showClearButton?: boolean searchPlaceholder?: string + listMaxHeight?: string + popoverMinWidth?: string + popoverMaxWidth?: string // Override modelValue type to match our Option type - modelValue?: Array<{ name: string; value: string }> + modelValue?: SelectOption[] } const meta: Meta = { @@ -42,6 +46,18 @@ const meta: Meta = { }, searchPlaceholder: { control: 'text' + }, + listMaxHeight: { + control: 'text', + description: 'Maximum height of the dropdown list' + }, + popoverMinWidth: { + control: 'text', + description: 'Minimum width of the popover' + }, + popoverMaxWidth: { + control: 'text', + description: 'Maximum width of the popover' } }, args: { @@ -274,3 +290,140 @@ export const CustomSearchPlaceholder: Story = { searchPlaceholder: 'Filter packages...' } } + +export const CustomMaxHeight: Story = { + render: () => ({ + components: { MultiSelect }, + setup() { + const selected1 = ref([]) + const selected2 = ref([]) + const selected3 = ref([]) + const manyOptions = Array.from({ length: 20 }, (_, i) => ({ + name: `Option ${i + 1}`, + value: `option${i + 1}` + })) + return { selected1, selected2, selected3, manyOptions } + }, + template: ` +
+
+

Small Height (10rem)

+ +
+
+

Default Height (28rem)

+ +
+
+

Large Height (32rem)

+ +
+
+ ` + }), + parameters: { + controls: { disable: true }, + actions: { disable: true }, + slot: { disable: true } + } +} + +export const CustomMinWidth: Story = { + render: () => ({ + components: { MultiSelect }, + setup() { + const selected1 = ref([]) + const selected2 = ref([]) + const selected3 = ref([]) + const options = [ + { name: 'A', value: 'a' }, + { name: 'B', value: 'b' }, + { name: 'Very Long Option Name Here', value: 'long' } + ] + return { selected1, selected2, selected3, options } + }, + template: ` +
+
+

Auto Width

+ +
+
+

Min Width 18rem

+ +
+
+

Min Width 28rem

+ +
+
+ ` + }), + parameters: { + controls: { disable: true }, + actions: { disable: true }, + slot: { disable: true } + } +} + +export const CustomMaxWidth: Story = { + render: () => ({ + components: { MultiSelect }, + setup() { + const selected1 = ref([]) + const selected2 = ref([]) + const selected3 = ref([]) + const longOptions = [ + { name: 'Short', value: 'short' }, + { + name: 'This is a very long option name that would normally expand the dropdown', + value: 'long1' + }, + { + name: 'Another extremely long option that demonstrates max-width constraint', + value: 'long2' + } + ] + return { selected1, selected2, selected3, longOptions } + }, + template: ` +
+
+

Auto Width

+ +
+
+

Max Width 18rem

+ +
+
+

Min 12rem Max 22rem

+ +
+
+ ` + }), + parameters: { + controls: { disable: true }, + actions: { disable: true }, + slot: { disable: true } + } +} diff --git a/src/components/input/MultiSelect.vue b/src/components/input/MultiSelect.vue index ffafde707..af9f5075f 100644 --- a/src/components/input/MultiSelect.vue +++ b/src/components/input/MultiSelect.vue @@ -1,10 +1,9 @@ @@ -15,20 +15,56 @@ import InputText from 'primevue/inputtext' import { computed } from 'vue' -const { placeHolder, showBorder = false } = defineProps<{ +import { cn } from '@/utils/tailwindUtil' + +const { + placeHolder, + showBorder = false, + size = 'md' +} = defineProps<{ placeHolder?: string showBorder?: boolean + size?: 'md' | 'lg' }>() // defineModel without arguments uses 'modelValue' as the prop name const searchQuery = defineModel() const wrapperStyle = computed(() => { - return showBorder - ? 'flex w-full items-center rounded gap-2 bg-white dark-theme:bg-zinc-800 p-1 border border-solid border-zinc-200 dark-theme:border-zinc-700' - : 'flex w-full items-center rounded px-2 py-1.5 gap-2 bg-white dark-theme:bg-zinc-800' + const baseClasses = [ + 'relative flex w-full items-center gap-2', + 'bg-white dark-theme:bg-zinc-800', + 'cursor-text' + ] + + if (showBorder) { + return cn( + ...baseClasses, + 'rounded p-2', + 'border border-solid', + 'border-zinc-200 dark-theme:border-zinc-700' + ) + } + + // Size-specific classes matching button sizes for consistency + const sizeClasses = { + md: 'h-8 px-2 py-1.5', // Matches button sm size + lg: 'h-10 px-4 py-2' // Matches button md size + }[size] + + return cn(...baseClasses, 'rounded-lg', sizeClasses) +}) + +const inputStyle = computed(() => { + return cn( + 'absolute inset-0 w-full h-full pl-11', + 'border-none outline-none bg-transparent', + 'text-sm text-neutral dark-theme:text-white' + ) }) const iconColorStyle = computed(() => { - return !showBorder ? 'text-neutral' : 'text-zinc-300 dark-theme:text-zinc-700' + return cn( + !showBorder ? 'text-neutral' : ['text-zinc-300', 'dark-theme:text-zinc-700'] + ) }) diff --git a/src/components/input/SingleSelect.accessibility.stories.ts b/src/components/input/SingleSelect.accessibility.stories.ts new file mode 100644 index 000000000..cc58466d1 --- /dev/null +++ b/src/components/input/SingleSelect.accessibility.stories.ts @@ -0,0 +1,464 @@ +import type { Meta, StoryObj } from '@storybook/vue3-vite' +import { ref } from 'vue' + +import SingleSelect from './SingleSelect.vue' + +interface SingleSelectProps { + label?: string + options?: Array<{ name: string; value: string }> + listMaxHeight?: string + popoverMinWidth?: string + popoverMaxWidth?: string + modelValue?: string | null +} + +const meta: Meta = { + title: 'Components/Input/SingleSelect/Accessibility', + component: SingleSelect, + tags: ['autodocs'], + parameters: { + docs: { + description: { + component: ` +# SingleSelect Accessibility Guide + +This SingleSelect component provides full keyboard accessibility and screen reader support following WCAG 2.1 AA guidelines. + +## Keyboard Navigation + +- **Tab** - Focus the trigger button +- **Enter/Space** - Open/close dropdown when focused +- **Arrow Up/Down** - Navigate through options when dropdown is open +- **Enter/Space** - Select option when navigating +- **Escape** - Close dropdown + +## Screen Reader Support + +- Uses \`role="combobox"\` to identify as dropdown +- \`aria-haspopup="listbox"\` indicates popup contains list +- \`aria-expanded\` shows dropdown state +- \`aria-label\` provides accessible name with i18n fallback +- Selected option announced to screen readers + +## Testing Instructions + +1. **Tab Navigation**: Use Tab key to focus the component +2. **Keyboard Opening**: Press Enter or Space to open dropdown +3. **Option Navigation**: Use Arrow keys to navigate options +4. **Selection**: Press Enter/Space to select an option +5. **Closing**: Press Escape to close dropdown +6. **Screen Reader**: Test with screen reader software + +Try these stories with keyboard-only navigation! + ` + } + } + }, + argTypes: { + label: { + control: 'text', + description: 'Label for the trigger button' + }, + listMaxHeight: { + control: 'text', + description: 'Maximum height of dropdown list' + } + } +} + +export default meta +type Story = StoryObj + +const sortOptions = [ + { name: 'Name A → Z', value: 'name-asc' }, + { name: 'Name Z → A', value: 'name-desc' }, + { name: 'Most Popular', value: 'popular' }, + { name: 'Most Recent', value: 'recent' }, + { name: 'File Size', value: 'size' } +] + +const priorityOptions = [ + { name: 'High Priority', value: 'high' }, + { name: 'Medium Priority', value: 'medium' }, + { name: 'Low Priority', value: 'low' }, + { name: 'No Priority', value: 'none' } +] + +export const KeyboardNavigationDemo: Story = { + render: (args) => ({ + components: { SingleSelect }, + setup() { + const selectedSort = ref(null) + const selectedPriority = ref('medium') + + return { + args, + selectedSort, + selectedPriority, + sortOptions, + priorityOptions + } + }, + template: ` +
+
+

🎯 Keyboard Navigation Test

+

+ Use your keyboard to navigate these SingleSelect dropdowns: +

+
    +
  1. Tab to focus the dropdown
  2. +
  3. Enter/Space to open dropdown
  4. +
  5. Arrow Up/Down to navigate options
  6. +
  7. Enter/Space to select option
  8. +
  9. Escape to close dropdown
  10. +
+
+ +
+
+ + +

+ Selected: {{ selectedSort ? sortOptions.find(o => o.value === selectedSort)?.name : 'None' }} +

+
+ +
+ + + + +

+ Selected: {{ selectedPriority ? priorityOptions.find(o => o.value === selectedPriority)?.name : 'None' }} +

+
+
+
+ ` + }) +} + +export const ScreenReaderFriendly: Story = { + render: (args) => ({ + components: { SingleSelect }, + setup() { + const selectedLanguage = ref('en') + const selectedTheme = ref(null) + + const languageOptions = [ + { name: 'English', value: 'en' }, + { name: 'Spanish', value: 'es' }, + { name: 'French', value: 'fr' }, + { name: 'German', value: 'de' }, + { name: 'Japanese', value: 'ja' } + ] + + const themeOptions = [ + { name: 'Light Theme', value: 'light' }, + { name: 'Dark Theme', value: 'dark' }, + { name: 'Auto (System)', value: 'auto' }, + { name: 'High Contrast', value: 'contrast' } + ] + + return { + selectedLanguage, + selectedTheme, + languageOptions, + themeOptions, + args + } + }, + template: ` +
+
+

♿ Screen Reader Test

+

+ These dropdowns have proper ARIA attributes and labels for screen readers: +

+
    +
  • role="combobox" identifies as dropdown
  • +
  • aria-haspopup="listbox" indicates popup type
  • +
  • aria-expanded shows open/closed state
  • +
  • aria-label provides accessible name
  • +
  • Selected option value announced to assistive technology
  • +
+
+ +
+
+ + +

+ Current: {{ selectedLanguage ? languageOptions.find(o => o.value === selectedLanguage)?.name : 'None selected' }} +

+
+ +
+ + +

+ Current: {{ selectedTheme ? themeOptions.find(o => o.value === selectedTheme)?.name : 'No theme selected' }} +

+
+
+ +
+

🎧 Screen Reader Testing Tips

+
    +
  • • Listen for role announcements when focusing
  • +
  • • Verify dropdown state changes are announced
  • +
  • • Check that selected values are spoken clearly
  • +
  • • Ensure option navigation is announced
  • +
+
+
+ ` + }) +} + +export const FormIntegration: Story = { + render: (args) => ({ + components: { SingleSelect }, + setup() { + const formData = ref({ + category: null as string | null, + status: 'draft' as string | null, + assignee: null as string | null + }) + + const categoryOptions = [ + { name: 'Bug Report', value: 'bug' }, + { name: 'Feature Request', value: 'feature' }, + { name: 'Documentation', value: 'docs' }, + { name: 'Question', value: 'question' } + ] + + const statusOptions = [ + { name: 'Draft', value: 'draft' }, + { name: 'Review', value: 'review' }, + { name: 'Approved', value: 'approved' }, + { name: 'Published', value: 'published' } + ] + + const assigneeOptions = [ + { name: 'Alice Johnson', value: 'alice' }, + { name: 'Bob Smith', value: 'bob' }, + { name: 'Carol Davis', value: 'carol' }, + { name: 'David Wilson', value: 'david' } + ] + + const handleSubmit = () => { + alert('Form submitted with: ' + JSON.stringify(formData.value, null, 2)) + } + + return { + formData, + categoryOptions, + statusOptions, + assigneeOptions, + handleSubmit, + args + } + }, + template: ` +
+
+

📝 Form Integration Test

+

+ Test keyboard navigation through a complete form with SingleSelect components. + Tab order should be logical and all elements should be accessible. +

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +