Skip to content

fix(a11y): add accessible names to icon-only buttons, fix placeholder - #13666

Merged
olayinkaadelakun merged 11 commits into
feat/a11yfrom
LE-1568
Jun 24, 2026
Merged

fix(a11y): add accessible names to icon-only buttons, fix placeholder#13666
olayinkaadelakun merged 11 commits into
feat/a11yfrom
LE-1568

Conversation

@olayinkaadelakun

@olayinkaadelakun olayinkaadelakun commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes three failing Lighthouse accessibility audits on /flows, bringing the score from 87 → 100.

Audit WCAG Rule Before After
button-name 4.1.2 (Critical) ❌ 35 unlabelled buttons ✅ All buttons named
color-contrast 1.4.3 (Serious) ❌ Placeholder at 2.56:1 ✅ ~6.1:1 on white
target-size 2.5.8 (Serious) ❌ Options trigger 16×24px ✅ min 24×24px

What changed

Accessible button names — added aria-label to every icon-only button on the /flows page:

  • App header: home/back button, notification bell
  • Sidebar: upload project, add project, per-project options trigger
  • Flow list toolbar: list/grid view toggles (with aria-pressed state), bulk download
  • Per-flow rows: select checkbox and kebab menu (both include the flow name for context)
  • Pagination: page-size select trigger

Placeholder contrast (src/style/index.css) — darkened --placeholder-foreground in light mode from #a1a1aa (2.56:1 on white) to ~#606066 (6.1:1). Dark mode unchanged.

Touch target (select-options.tsx) — added min-h-[24px] min-w-[24px] to the per-project options trigger.

i18n — 8 new translation keys added to all 7 locale files (en, de, es, fr, ja, pt, zh-Hans) with English placeholder values for non-English locales.

Test plan

  • make test_frontend — all unit tests pass

QA guildline
https://datastax.jira.com/browse/LE-1568?focusedCommentId=811695

Summary by CodeRabbit

  • Accessibility Improvements

    • Added descriptive labels to buttons throughout the application, including navigation, notifications, view toggles, and action menus, for improved screen reader support.
    • Enhanced color contrast for placeholder text to meet accessibility standards.
    • Added accessibility test coverage to verify label compliance.
  • Internationalization

    • Added new translation keys across supported languages for improved UI text localization.

… contrast, and enforce touch target size on /flows
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95d3b33f-1bd0-4044-9a1d-6b6100fe507f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds aria-label attributes to icon-only buttons in AppHeader, FolderSidebar, PaginatorComponent, and MainPage header/list components. Backs the new labels with i18n keys in en.json and propagates them to six locale files. Darkens the --placeholder-foreground CSS variable to meet WCAG contrast requirements. New accessibility test suites verify the added attributes.

Changes

Accessibility improvements across UI components

Layer / File(s) Summary
New i18n keys for aria-labels across all locales
src/frontend/src/locales/en.json, src/frontend/src/locales/de.json, src/frontend/src/locales/es.json, src/frontend/src/locales/fr.json, src/frontend/src/locales/ja.json, src/frontend/src/locales/pt.json, src/frontend/src/locales/zh-Hans.json
en.json adds header.home, flows.viewList/viewGrid/downloadSelected/selectFlow/moreOptions, folder.optionsFor, and paginator.pageLabel. All six non-English locale files receive those accessibility keys plus new MCP install/status, playground, assistant, and flow paste wording entries.
aria-label and aria-pressed additions to UI components
src/frontend/src/components/core/appHeaderComponent/index.tsx, src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/add-folder-button.tsx, src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/upload-folder-button.tsx, src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/select-options.tsx, src/frontend/src/components/common/paginatorComponent/index.tsx, src/frontend/src/pages/MainPage/components/header/index.tsx, src/frontend/src/pages/MainPage/components/list/index.tsx
AppHeader home and notifications buttons gain aria-label. AddFolderButton, UploadFolderButton, and SelectOptions trigger gain aria-label (SelectOptions also adds compact sizing classes). PaginatorComponent SelectTrigger gains aria-label. HeaderComponent view-toggle buttons gain aria-label and aria-pressed; download button gains aria-label. ListComponent checkbox and more-options button gain aria-label.
Accessibility test suites
src/frontend/src/components/core/appHeaderComponent/__tests__/app-header-a11y.test.tsx, src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/add-folder-button.test.tsx, src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/upload-folder-button.test.tsx, src/frontend/src/components/common/paginatorComponent/__tests__/PaginatorComponent.test.tsx, src/frontend/src/pages/MainPage/components/header/__tests__/header.test.tsx
New app-header-a11y.test.tsx asserts aria-label on home and notifications buttons. New add-folder-button.test.tsx and upload-folder-button.test.tsx assert aria-label and disabled state. PaginatorComponent test updates the SelectTrigger mock to forward aria-label and adds an accessibility describe block. header.test.tsx removes the note prop from its modal mock and adds a suite verifying aria-label and aria-pressed on icon-only controls.
Placeholder foreground contrast fix
src/frontend/src/style/index.css
--placeholder-foreground is darkened from 240 5% 65% to 240 5% 40% in the light theme root to satisfy WCAG 1.4.3.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

lgtm

Suggested reviewers

  • keval718

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 3 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error PR includes tests for 6 of 8 components (75% coverage). ListComponent and select-options.tsx were modified to add aria-label attributes but lack corresponding test files. Add test files for ListComponent and select-options.tsx to verify aria-label attributes work correctly (flows.selectFlow, flows.moreOptions for ListComponent; folder.optionsFor for select-options).
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Quality And Coverage ⚠️ Warning Tests are primarily smoke tests with excessive mocking of internal UI components, failing to validate actual accessibility behavior. Multiple review issues remain unfixed: app-header-a11y mocks 16... Replace over-mocked unit tests with minimal mocking (external deps only) and add Playwright e2e tests to verify aria-labels work with real UI components. Fix assertion logic (use === not >=) and use semantic in SelectTrigger mock.
Excessive Mock Usage Warning ⚠️ Warning Multiple test files exhibit excessive mocking of core UI components and internal logic, violating guidelines. app-header-a11y.test.tsx (16 mocks) is flagged as "over-mocked"; upload/add-folder-butt... Reduce core component mocks: render real Button, shadTooltip, genericIcon components. Port app-header test to Playwright. Fix SelectTrigger mock to use button element and forward props correctly with {...rest}.
Test File Naming And Structure ❓ Inconclusive Custom check requirement is contradictory with project conventions. It states "Frontend tests: *.test.ts or .test.tsx using Playwright," but the project documents unit tests (.test.tsx) use Jest/... Clarify whether the check requires: (1) unit tests to use Playwright instead of Jest/RTL (contradicting .agents/skills/frontend-testing), or (2) clarify that .test.tsx should use Jest/RTL and only E2E tests (.spec.ts) use Playwright. T...
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The pull request title 'fix(a11y): add accessible names to icon-only buttons, fix placeholder' clearly and specifically summarizes the main changes: accessibility fixes for icon-only buttons and placeholder styling. The title directly reflects the primary objectives documented in the PR.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch LE-1568

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the bug Something isn't working label Jun 15, 2026
@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

✅ Test Coverage Advisor

No source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉

Advisory check only — never blocks merge.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 15, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/frontend/src/locales/zh-Hans.json (1)

899-903: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing header.home locale key breaks localized accessible name

AppHeader now reads t("header.home") (Line 67 in src/frontend/src/components/core/appHeaderComponent/index.tsx), but this locale block has no header.home key near the other header keys. In zh-Hans, that makes the home button’s aria-label fallback instead of being translated.

Suggested patch
   "header.goToDiscord": "前往 Discord 服务器",
   "header.goToGithub": "访问 GitHub 代码库",
+  "header.home": "返回首页",
   "header.notifications": "通知和错误",
   "header.notificationsLabel": "通知",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/locales/zh-Hans.json` around lines 899 - 903, The
zh-Hans.json locale file is missing the header.home key that AppHeader component
tries to reference with t("header.home"). Add the missing header.home key to the
locale block alongside the other header keys (header.goToDiscord,
header.goToGithub, header.notifications, header.notificationsLabel) with an
appropriate Chinese translation for the home button's accessible name label.
🧹 Nitpick comments (2)
src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/add-folder-button.test.tsx (1)

20-37: ⚡ Quick win

Reduce primitive UI mocking for this accessibility assertion.

Mocking @/components/ui/button here can mask real prop-forwarding issues; keep the real button and mock only non-essential dependencies so the aria-label test validates real behavior.

As per coding guidelines: "Warn when mocks are used instead of testing real behavior and interactions, and suggest using real objects or test doubles when mocks become excessive."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/add-folder-button.test.tsx`
around lines 20 - 37, Remove the jest.mock for "`@/components/ui/button`" to use
the real Button component instead, since mocking a primitive UI component masks
real prop-forwarding issues and prevents validating actual aria-label behavior.
Keep only mocks for non-essential dependencies that are not part of the
accessibility assertion being tested, so the aria-label test can validate real
behavior against the actual Button component.

Source: Coding guidelines

src/frontend/src/pages/MainPage/components/header/__tests__/header.test.tsx (1)

236-249: ⚡ Quick win

Avoid English-substring filtering for aria-label verification.

Filtering by "view" | "list" | "grid" makes this test locale-coupled and less reliable for i18n-backed labels. Prefer stable selectors (role + known button identity/testid) and then assert aria-label is present/non-empty on those exact controls.

Refactor direction
-      const labelled = container.querySelectorAll("button[aria-label]");
-      const viewBtns = Array.from(labelled).filter((b) => {
-        const label = b.getAttribute("aria-label") ?? "";
-        return (
-          label.toLowerCase().includes("view") ||
-          label.toLowerCase().includes("list") ||
-          label.toLowerCase().includes("grid")
-        );
-      });
-      expect(viewBtns.length).toBeGreaterThanOrEqual(2);
+      const pressedButtons = container.querySelectorAll("button[aria-pressed]");
+      expect(pressedButtons.length).toBe(2);
+      pressedButtons.forEach((btn) => {
+        expect(btn).toHaveAttribute("aria-label");
+        expect(btn.getAttribute("aria-label")?.trim().length).toBeGreaterThan(0);
+      });

As per coding guidelines, “Tests should cover the main functionality being implemented” and should remain clear about what is being validated rather than relying on brittle heuristics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/pages/MainPage/components/header/__tests__/header.test.tsx`
around lines 236 - 249, The test in the "view toggle buttons have aria-label
attributes" test case is using English substring matching to filter buttons,
which couples the test to a specific locale and makes it brittle for
internationalization. Replace the current filtering logic that checks for
"view", "list", and "grid" substrings in aria-label with a more stable approach:
use role-based selectors (such as role="button" combined with a specific testid
or data-testid attribute on the view toggle controls) to reliably identify the
two view toggle buttons regardless of locale, and then assert that each of those
identified buttons has a non-empty aria-label attribute. This ensures the test
validates that the controls are properly labeled without depending on English
text content.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/frontend/src/components/common/paginatorComponent/__tests__/PaginatorComponent.test.tsx`:
- Around line 43-47: The SelectTrigger mock in the test file does not properly
forward all props to the underlying div element, which reduces test fidelity.
Instead of only explicitly handling the aria-label prop, use the spread operator
to forward all rest props to the div element (for example, replace
aria-label={rest["aria-label"]} with {...rest}). This change should be applied
at the anchor location in
src/frontend/src/components/common/paginatorComponent/__tests__/PaginatorComponent.test.tsx
at lines 43-47 in the SelectTrigger mock, and at the sibling location at lines
70-76 where the same mock pattern appears, to ensure consistent prop forwarding
behavior across all mocks.

In
`@src/frontend/src/components/core/appHeaderComponent/__tests__/app-header-a11y.test.tsx`:
- Around line 5-91: This test file (app-header-a11y.test.tsx) is over-mocked and
diverges from the frontend Playwright testing pattern. The excessive mocking of
internal UI components (Button, Separator, genericIconComponent, etc.), hooks,
and stores means the test verifies mocked wiring rather than real accessibility
behavior. To fix this: convert the test from Jest/RTL to Playwright following
the frontend testing conventions, minimize mocks to only external boundaries
(API calls, third-party libraries), and rewrite the test to assert on actual
accessible names and ARIA attributes rendered in the real AppHeader UI rather
than testing mocked component interactions. This will ensure the test validates
genuine accessibility behavior as intended.

In
`@src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/upload-folder-button.test.tsx`:
- Around line 4-26: Remove the jest.mock calls for the internal UI components
Button, shadTooltipComponent, and genericIconComponent in the test setup. These
mocks are obscuring actual component behavior and should not be mocked according
to testing guidelines. Keep the mock for react-i18next since it is an external
dependency. Either allow the real components to render naturally (by removing
their mock definitions) or replace the mocks with minimal test doubles that
preserve the expected behavior without hiding implementation details. This will
ensure the test verifies real interaction behavior with the actual UI
components.

In `@src/frontend/src/locales/fr.json`:
- Line 70: The French locale file (fr.json) is missing translations for several
accessibility keys that were added for the flows feature, causing French users
to fall back to the default locale. Add French translations for the following
missing keys: header.home, flows.viewList, flows.viewGrid,
flows.downloadSelected, flows.selectFlow, flows.moreOptions, folder.optionsFor,
and paginator.pageLabel to the fr.json file. Each key should have an appropriate
French translation that matches the context and purpose of the original
accessibility label.
- Around line 1558-1559: In the French translation file, fix two issues with the
playground labels. First, correct the broken Trans markup in the
playground.noInputHint string where the XML tags are malformed around "Chat » (
Input" — ensure the opening and closing tags are properly balanced and correctly
delimit the translatable text. Second, replace the noun "Déroulement" in
playground.runFlow with an appropriate action verb that conveys the command to
execute or run the flow, as the current value reads as a descriptive noun rather
than an action label.

In `@src/frontend/src/locales/ja.json`:
- Line 70: The PR introduces new accessibility/i18n contract requirements for
the `/flows` feature, but the corresponding translation keys are missing from
the locale files. Add the following eight missing keys to both
`src/frontend/src/locales/ja.json` (line 70-70) and
`src/frontend/src/locales/pt.json` (line 70-70): `header.home`,
`flows.viewList`, `flows.viewGrid`, `flows.downloadSelected`,
`flows.selectFlow`, `flows.moreOptions`, `folder.optionsFor`, and
`paginator.pageLabel`. Use English text as placeholder values in both files, as
translations can be added later. Ensure the keys are added at the correct
location in the JSON structure where other localization entries are defined,
maintaining consistent formatting with existing entries.

In `@src/frontend/src/pages/MainPage/components/header/__tests__/header.test.tsx`:
- Around line 266-279: The test "exactly one view toggle is aria-pressed=true
and one is false" has assertions that do not match its name. Currently, the
expectations on trueCount and falseCount use toBeGreaterThanOrEqual(1), which
allows for multiple buttons with the same aria-pressed value to pass. Change
both expect(trueCount).toBeGreaterThanOrEqual(1) and
expect(falseCount).toBeGreaterThanOrEqual(1) to use toBe(1) instead to enforce
exactly one button with aria-pressed="true" and exactly one with
aria-pressed="false".

---

Outside diff comments:
In `@src/frontend/src/locales/zh-Hans.json`:
- Around line 899-903: The zh-Hans.json locale file is missing the header.home
key that AppHeader component tries to reference with t("header.home"). Add the
missing header.home key to the locale block alongside the other header keys
(header.goToDiscord, header.goToGithub, header.notifications,
header.notificationsLabel) with an appropriate Chinese translation for the home
button's accessible name label.

---

Nitpick comments:
In
`@src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/add-folder-button.test.tsx`:
- Around line 20-37: Remove the jest.mock for "`@/components/ui/button`" to use
the real Button component instead, since mocking a primitive UI component masks
real prop-forwarding issues and prevents validating actual aria-label behavior.
Keep only mocks for non-essential dependencies that are not part of the
accessibility assertion being tested, so the aria-label test can validate real
behavior against the actual Button component.

In `@src/frontend/src/pages/MainPage/components/header/__tests__/header.test.tsx`:
- Around line 236-249: The test in the "view toggle buttons have aria-label
attributes" test case is using English substring matching to filter buttons,
which couples the test to a specific locale and makes it brittle for
internationalization. Replace the current filtering logic that checks for
"view", "list", and "grid" substrings in aria-label with a more stable approach:
use role-based selectors (such as role="button" combined with a specific testid
or data-testid attribute on the view toggle controls) to reliably identify the
two view toggle buttons regardless of locale, and then assert that each of those
identified buttons has a non-empty aria-label attribute. This ensures the test
validates that the controls are properly labeled without depending on English
text content.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b3604eee-78df-4bf9-95fb-940ac3a3c173

📥 Commits

Reviewing files that changed from the base of the PR and between de06b91 and 54a8903.

📒 Files selected for processing (20)
  • src/frontend/src/components/common/paginatorComponent/__tests__/PaginatorComponent.test.tsx
  • src/frontend/src/components/common/paginatorComponent/index.tsx
  • src/frontend/src/components/core/appHeaderComponent/__tests__/app-header-a11y.test.tsx
  • src/frontend/src/components/core/appHeaderComponent/index.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/add-folder-button.test.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/upload-folder-button.test.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/add-folder-button.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/select-options.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/upload-folder-button.tsx
  • src/frontend/src/locales/de.json
  • src/frontend/src/locales/en.json
  • src/frontend/src/locales/es.json
  • src/frontend/src/locales/fr.json
  • src/frontend/src/locales/ja.json
  • src/frontend/src/locales/pt.json
  • src/frontend/src/locales/zh-Hans.json
  • src/frontend/src/pages/MainPage/components/header/__tests__/header.test.tsx
  • src/frontend/src/pages/MainPage/components/header/index.tsx
  • src/frontend/src/pages/MainPage/components/list/index.tsx
  • src/frontend/src/style/index.css

Comment on lines 43 to 47
SelectTrigger: ({ children, ...rest }: any) => (
<div data-testid="page-select-trigger" aria-label={rest["aria-label"]}>
{children}
</div>
),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use a semantic trigger mock that forwards props.

Suggested test-fidelity fix
-    SelectTrigger: ({ children, ...rest }: any) => (
-      <div data-testid="page-select-trigger" aria-label={rest["aria-label"]}>
-        {children}
-      </div>
-    ),
+    SelectTrigger: ({ children, ...rest }: any) => (
+      <button type="button" data-testid="page-select-trigger" {...rest}>
+        {children}
+      </button>
+    ),

As per coding guidelines: "Ensure mocks are used appropriately for external dependencies, not core logic" and "Warn when mocks are used instead of testing real behavior and interactions."

Also applies to: 70-76

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/frontend/src/components/common/paginatorComponent/__tests__/PaginatorComponent.test.tsx`
around lines 43 - 47, The SelectTrigger mock in the test file does not properly
forward all props to the underlying div element, which reduces test fidelity.
Instead of only explicitly handling the aria-label prop, use the spread operator
to forward all rest props to the div element (for example, replace
aria-label={rest["aria-label"]} with {...rest}). This change should be applied
at the anchor location in
src/frontend/src/components/common/paginatorComponent/__tests__/PaginatorComponent.test.tsx
at lines 43-47 in the SelectTrigger mock, and at the sibling location at lines
70-76 where the same mock pattern appears, to ensure consistent prop forwarding
behavior across all mocks.

Source: Coding guidelines

Comment on lines +5 to +91
jest.mock("react-i18next", () => ({
useTranslation: () => ({ t: (key: string) => key }),
}));

jest.mock("@/components/common/genericIconComponent", () => ({
__esModule: true,
default: ({ name }: { name: string }) => (
<span data-testid={`icon-${name}`}>{name}</span>
),
}));

jest.mock("@/components/ui/button", () => ({
Button: ({
children,
"aria-label": ariaLabel,
"data-testid": testId,
unstyled,
...props
}: any) => (
<button aria-label={ariaLabel} data-testid={testId} {...props}>
{children}
</button>
),
}));

jest.mock("@/components/ui/separator", () => ({
Separator: () => <hr />,
}));

jest.mock("@/components/common/shadTooltipComponent", () => ({
__esModule: true,
default: ({ children }: any) => <>{children}</>,
}));

jest.mock("@/components/common/modelProviderCountComponent", () => ({
__esModule: true,
default: () => null,
}));

jest.mock("@/alerts/alertDropDown", () => ({
__esModule: true,
default: ({ children }: any) => <>{children}</>,
}));

jest.mock("@/assets/LangflowLogo.svg?react", () => ({
__esModule: true,
default: () => <svg data-testid="langflow-logo" />,
}));

jest.mock("@/customization/components/custom-AccountMenu", () => ({
__esModule: true,
default: () => null,
}));

jest.mock("@/customization/components/custom-langflow-counts", () => ({
__esModule: true,
default: () => null,
}));

jest.mock("@/customization/components/custom-org-selector", () => ({
CustomOrgSelector: () => null,
}));

jest.mock("@/customization/hooks/use-custom-navigate", () => ({
useCustomNavigate: () => jest.fn(),
}));

jest.mock("@/customization/hooks/use-custom-theme", () => ({
__esModule: true,
default: () => ({ dark: false }),
}));

jest.mock("@/stores/alertStore", () => ({
__esModule: true,
default: () => ({
notificationCenter: false,
setNotificationCenter: jest.fn(),
}),
}));

jest.mock("./components/FlowMenu", () => ({ FlowMenu: () => null }), {
virtual: true,
});
jest.mock("../components/FlowMenu", () => ({
__esModule: true,
default: () => null,
}));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Test is over-mocked and diverges from the frontend testing pattern

This suite mocks most of AppHeader’s runtime surface (UI primitives, dropdowns, hooks/store), so it mostly verifies mocked wiring rather than real accessibility behavior. It also uses Jest/RTL instead of the frontend Playwright pattern.

Please keep unit mocking minimal (external boundaries only) and add/port coverage to a Playwright test that asserts accessible names on the rendered UI.

As per coding guidelines, “Frontend test files should follow the naming convention *.test.ts or *.test.tsx using Playwright” and “Warn when mocks are used instead of testing real behavior and interactions … Recommend integration tests when unit tests become overly mocked.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/frontend/src/components/core/appHeaderComponent/__tests__/app-header-a11y.test.tsx`
around lines 5 - 91, This test file (app-header-a11y.test.tsx) is over-mocked
and diverges from the frontend Playwright testing pattern. The excessive mocking
of internal UI components (Button, Separator, genericIconComponent, etc.),
hooks, and stores means the test verifies mocked wiring rather than real
accessibility behavior. To fix this: convert the test from Jest/RTL to
Playwright following the frontend testing conventions, minimize mocks to only
external boundaries (API calls, third-party libraries), and rewrite the test to
assert on actual accessible names and ARIA attributes rendered in the real
AppHeader UI rather than testing mocked component interactions. This will ensure
the test validates genuine accessibility behavior as intended.

Source: Coding guidelines

Comment on lines +4 to +26
jest.mock("react-i18next", () => ({
useTranslation: () => ({ t: (key: string) => key }),
}));

jest.mock("@/components/common/genericIconComponent", () => ({
__esModule: true,
default: ({ name }: { name: string }) => (
<span data-testid={`icon-${name}`}>{name}</span>
),
}));

jest.mock("@/components/common/shadTooltipComponent", () => ({
__esModule: true,
default: ({ children }: { children: React.ReactNode }) => <>{children}</>,
}));

jest.mock("@/components/ui/button", () => ({
Button: ({ children, "aria-label": ariaLabel, disabled, ...props }: any) => (
<button aria-label={ariaLabel} disabled={disabled} {...props}>
{children}
</button>
),
}));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify frontend test framework usage and mock density (read-only).
# Expected: if guideline is enforced, frontend *.test.ts/tsx should primarily use Playwright APIs.

echo "== Frontend test files =="
fd -e ts -e tsx '.test$' src/frontend/src

echo
echo "== Files importing Jest/RTL in frontend tests =="
rg -n --type=ts --type=tsx '(`@testing-library/react`|jest\.mock|describe\(|it\()' src/frontend/src --iglob '**/*.test.ts' --iglob '**/*.test.tsx'

echo
echo "== Files importing Playwright in frontend tests =="
rg -n --type=ts --type=tsx '(`@playwright/test`|test\(|expect\()' src/frontend/src --iglob '**/*.test.ts' --iglob '**/*.test.tsx'

Repository: langflow-ai/langflow

Length of output: 266


🏁 Script executed:

#!/bin/bash
# Find all test files in frontend with correct syntax
echo "== All test files in frontend =="
find src/frontend -name "*.test.ts" -o -name "*.test.tsx" 2>/dev/null | head -20

echo
echo "== Check specific file existence =="
ls -la "src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/upload-folder-button.test.tsx" 2>&1

echo
echo "== Checking package.json for testing framework dependencies =="
cat package.json | grep -A 10 -B 2 '"jest"\|"playwright"\|"vitest"' 2>/dev/null || echo "Not found in top-level search"

Repository: langflow-ai/langflow

Length of output: 2229


🏁 Script executed:

#!/bin/bash
# Search for test framework usage without type flags
echo "== Jest usage in frontend tests =="
grep -r "jest.mock\|describe(\|it(" src/frontend --include="*.test.ts*" 2>/dev/null | head -5

echo
echo "== Playwright usage in frontend tests =="
grep -r "`@playwright/test`\|test(" src/frontend --include="*.test.ts*" 2>/dev/null | head -5

echo
echo "== Looking for jest/vitest in package.json =="
grep -i "jest\|vitest\|playwright" package*.json 2>/dev/null | head -20

Repository: langflow-ai/langflow

Length of output: 1565


🏁 Script executed:

#!/bin/bash
# Read package.json to check testing framework dependencies
echo "== Frontend package.json test dependencies =="
cat src/frontend/package.json | grep -A 30 '"devDependencies"' | head -40

Repository: langflow-ai/langflow

Length of output: 1197


🏁 Script executed:

#!/bin/bash
# Read the specific test file to assess mock usage
echo "== Content of upload-folder-button.test.tsx =="
cat src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/upload-folder-button.test.tsx

Repository: langflow-ai/langflow

Length of output: 1655


Reduce internal component mocks to test real interaction behavior.

The test mocks internal UI components (Button, shadTooltipComponent, genericIconComponent) that should be rendered for real to verify actual behavior. Per coding guidelines, mocks should be limited to external dependencies (like react-i18next); mocking core UI logic obscures what's actually being tested. Consider importing and rendering the real components, or replacing mocks with minimal test doubles that preserve behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/__tests__/upload-folder-button.test.tsx`
around lines 4 - 26, Remove the jest.mock calls for the internal UI components
Button, shadTooltipComponent, and genericIconComponent in the test setup. These
mocks are obscuring actual component behavior and should not be mocked according
to testing guidelines. Keep the mock for react-i18next since it is an external
dependency. Either allow the real components to render naturally (by removing
their mock definitions) or replace the mocks with minimal test doubles that
preserve the expected behavior without hiding implementation details. This will
ensure the test verifies real interaction behavior with the actual UI
components.

Source: Coding guidelines

"assistant.loading": "Chargement en cours...",
"assistant.maxSessionsLabel": "Nbre max. de sessions",
"assistant.maxSessionsTooltip": "Le nombre maximal de sessions d' {{max}} s a été atteint. Supprimez une session pour en créer une nouvelle.",
"assistant.mentionNoMatches": "Aucun composant correspondant sur le canevas",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Mirror the new /flows accessibility keys in French.

This locale still omits header.home, flows.viewList/viewGrid/downloadSelected/selectFlow/moreOptions, folder.optionsFor, and paginator.pageLabel, so French users will fall back to the default locale for the new aria labels.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/locales/fr.json` at line 70, The French locale file
(fr.json) is missing translations for several accessibility keys that were added
for the flows feature, causing French users to fall back to the default locale.
Add French translations for the following missing keys: header.home,
flows.viewList, flows.viewGrid, flows.downloadSelected, flows.selectFlow,
flows.moreOptions, folder.optionsFor, and paginator.pageLabel to the fr.json
file. Each key should have an appropriate French translation that matches the
context and purpose of the original accessibility label.

Comment on lines +1558 to +1559
"playground.noInputHint": "Ajoutez un composant « <1>Chat » ( Input</1> ) à votre flux pour envoyer des messages.",
"playground.runFlow": "Déroulement",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the French playground labels.

playground.noInputHint has broken Trans markup, and playground.runFlow reads as a noun (Déroulement) instead of the action label the UI needs.

💡 Suggested copy
-  "playground.noInputHint": "Ajoutez un composant « <1>Chat » ( Input</1> ) à votre flux pour envoyer des messages.",
-  "playground.runFlow": "Déroulement",
+  "playground.noInputHint": "Ajoutez un composant « <1>Chat Input</1> » à votre flux pour envoyer des messages.",
+  "playground.runFlow": "Exécuter le flux",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"playground.noInputHint": "Ajoutez un composant « <1>Chat » ( Input</1> ) à votre flux pour envoyer des messages.",
"playground.runFlow": "Déroulement",
"playground.noInputHint": "Ajoutez un composant « <1>Chat Input</1> » à votre flux pour envoyer des messages.",
"playground.runFlow": "Exécuter le flux",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/locales/fr.json` around lines 1558 - 1559, In the French
translation file, fix two issues with the playground labels. First, correct the
broken Trans markup in the playground.noInputHint string where the XML tags are
malformed around "Chat » ( Input" — ensure the opening and closing tags are
properly balanced and correctly delimit the translatable text. Second, replace
the noun "Déroulement" in playground.runFlow with an appropriate action verb
that conveys the command to execute or run the flow, as the current value reads
as a descriptive noun rather than an action label.

"assistant.loading": "ロード中...",
"assistant.maxSessionsLabel": "セッションの最大数",
"assistant.maxSessionsTooltip": "{{max}} セッションの上限に達しました。 セッションを削除して、新しいセッションを作成します。",
"assistant.mentionNoMatches": "キャンバス上に一致するコンポーネントがありません",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Missing required accessibility i18n keys for the new /flows aria-label wiring.

Both locale files are missing the key set introduced by this PR’s accessibility/i18n contract, so translated labels for the updated controls will not resolve in these locales.

  • src/frontend/src/locales/ja.json#L70-L70: add header.home, flows.viewList, flows.viewGrid, flows.downloadSelected, flows.selectFlow, flows.moreOptions, folder.optionsFor, and paginator.pageLabel (use English placeholders if translation is pending, per PR objective).
  • src/frontend/src/locales/pt.json#L70-L70: add header.home, flows.viewList, flows.viewGrid, flows.downloadSelected, flows.selectFlow, flows.moreOptions, folder.optionsFor, and paginator.pageLabel (use English placeholders if translation is pending, per PR objective).
📍 Affects 2 files
  • src/frontend/src/locales/ja.json#L70-L70 (this comment)
  • src/frontend/src/locales/pt.json#L70-L70
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/locales/ja.json` at line 70, The PR introduces new
accessibility/i18n contract requirements for the `/flows` feature, but the
corresponding translation keys are missing from the locale files. Add the
following eight missing keys to both `src/frontend/src/locales/ja.json` (line
70-70) and `src/frontend/src/locales/pt.json` (line 70-70): `header.home`,
`flows.viewList`, `flows.viewGrid`, `flows.downloadSelected`,
`flows.selectFlow`, `flows.moreOptions`, `folder.optionsFor`, and
`paginator.pageLabel`. Use English text as placeholder values in both files, as
translations can be added later. Ensure the keys are added at the correct
location in the JSON structure where other localization entries are defined,
maintaining consistent formatting with existing entries.

Comment on lines +266 to +279
it("exactly one view toggle is aria-pressed=true and one is false", () => {
const { container } = render(
<HeaderComponent {...defaultProps} view="grid" />,
);
const allPressed = container.querySelectorAll("button[aria-pressed]");
const trueCount = Array.from(allPressed).filter(
(b) => b.getAttribute("aria-pressed") === "true",
).length;
const falseCount = Array.from(allPressed).filter(
(b) => b.getAttribute("aria-pressed") === "false",
).length;
expect(trueCount).toBeGreaterThanOrEqual(1);
expect(falseCount).toBeGreaterThanOrEqual(1);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

exactly one assertion currently does not enforce “exactly one”.

This test name promises strict cardinality, but toBeGreaterThanOrEqual(1) allows multiple aria-pressed="true" or multiple "false" buttons to pass.

Proposed fix
-      expect(trueCount).toBeGreaterThanOrEqual(1);
-      expect(falseCount).toBeGreaterThanOrEqual(1);
+      expect(trueCount).toBe(1);
+      expect(falseCount).toBe(1);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/src/pages/MainPage/components/header/__tests__/header.test.tsx`
around lines 266 - 279, The test "exactly one view toggle is aria-pressed=true
and one is false" has assertions that do not match its name. Currently, the
expectations on trueCount and falseCount use toBeGreaterThanOrEqual(1), which
allows for multiple buttons with the same aria-pressed value to pass. Change
both expect(trueCount).toBeGreaterThanOrEqual(1) and
expect(falseCount).toBeGreaterThanOrEqual(1) to use toBe(1) instead to enforce
exactly one button with aria-pressed="true" and exactly one with
aria-pressed="false".

@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.85714% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.31%. Comparing base (5ea9fe6) to head (60d1bbe).

Files with missing lines Patch % Lines
...sideBarFolderButtons/components/select-options.tsx 0.00% 2 Missing ⚠️
...ntend/src/pages/MainPage/components/list/index.tsx 0.00% 2 Missing ⚠️
...d/src/components/core/appHeaderComponent/index.tsx 0.00% 1 Missing ⚠️
...rFolderButtons/components/get-started-progress.tsx 0.00% 1 Missing ⚠️

❌ Your project check has failed because the head coverage (54.33%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##           feat/a11y   #13666      +/-   ##
=============================================
+ Coverage      58.25%   58.31%   +0.05%     
=============================================
  Files           2307     2307              
  Lines         219525   219551      +26     
  Branches       31174    32978    +1804     
=============================================
+ Hits          127893   128030     +137     
+ Misses         90173    90062     -111     
  Partials        1459     1459              
Flag Coverage Δ
frontend 57.52% <82.85%> (+0.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...src/components/common/paginatorComponent/index.tsx 91.13% <100.00%> (+0.05%) ⬆️
...e/appHeaderComponent/components/FlowMenu/index.tsx 94.01% <100.00%> (+0.07%) ⬆️
...eBarFolderButtons/components/add-folder-button.tsx 91.66% <100.00%> (+49.11%) ⬆️
...rFolderButtons/components/upload-folder-button.tsx 89.74% <100.00%> (+42.37%) ⬆️
...s/MemoriesMainContent/components/MemoryDetails.tsx 95.67% <100.00%> (+0.08%) ⬆️
...riesMainContent/components/MemoryDetailsHeader.tsx 93.57% <100.00%> (ø)
...idebarComponent/components/sidebarSegmentedNav.tsx 96.19% <100.00%> (+0.15%) ⬆️
...end/src/pages/MainPage/components/header/index.tsx 92.30% <100.00%> (+0.16%) ⬆️
...d/src/components/core/appHeaderComponent/index.tsx 37.50% <0.00%> (-0.25%) ⬇️
...rFolderButtons/components/get-started-progress.tsx 25.77% <0.00%> (-1.47%) ⬇️
... and 2 more

... and 62 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 43%
43.37% (57896/133481) 69.08% (7856/11371) 41.7% (1302/3122)

Unit Test Results

Tests Skipped Failures Errors Time
4967 0 💤 0 ❌ 0 🔥 14m 15s ⏱️

@viktoravelino

Copy link
Copy Markdown
Collaborator

this PR should target feat/a11y branch

@olayinkaadelakun
olayinkaadelakun changed the base branch from release-1.11.0 to feat/a11y June 15, 2026 23:07
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 15, 2026
@github-actions github-actions Bot removed the bug Something isn't working label Jun 16, 2026

@viktoravelino viktoravelino left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Frontend a11y review. Left inline comments on blocking issues and test gaps.

)
}
data-testid="notification_button"
aria-label={t("header.notifications")}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug: duplicate aria-label prop on same JSX element. npx tsc --noEmit reports TS17001: JSX elements cannot have multiple attributes with the same name.

Suggested change: remove this duplicate and keep the existing aria-label above.

"mainPage.timeElapsed.hour_other": "{{count}} hours",
"mainPage.timeElapsed.minute_one": "{{count}} minute",
"mainPage.timeElapsed.minute_other": "{{count}} minutes",
"flows.viewList": "List view",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug: these new a11y i18n keys were added only to en.json. de, es, fr, ja, pt, and zh-Hans are missing header.home, flows.viewList, flows.viewGrid, flows.downloadSelected, flows.selectFlow, flows.moreOptions, folder.optionsFor, and paginator.pageLabel, so localized UIs expose raw keys as accessible names.

Suggested change: add the same keys to all locale files, using English placeholders if translations are not ready.

const { container } = render(<HeaderComponent {...defaultProps} />);
// Both view toggle buttons must carry an aria-label (actual text depends on loaded locale)
const labelled = container.querySelectorAll("button[aria-label]");
const viewBtns = Array.from(labelled).filter((b) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

risk: test filters view-toggle buttons by English substrings (view, list, grid). That makes the assertion locale-coupled and can miss the actual controls.

Suggested change: select the two button[aria-pressed] controls, assert count is 2, then assert each has a non-empty aria-label.

const falseCount = Array.from(allPressed).filter(
(b) => b.getAttribute("aria-pressed") === "false",
).length;
expect(trueCount).toBeGreaterThanOrEqual(1);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

risk: test name says “exactly one”, but toBeGreaterThanOrEqual(1) allows multiple pressed/unpressed controls.

Suggested change: use expect(trueCount).toBe(1) and expect(falseCount).toBe(1).

@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Jun 16, 2026
@olayinkaadelakun olayinkaadelakun changed the title fix(a11y): add accessible names to icon-only buttons, fix placeholder… fix(a11y): add accessible names to icon-only buttons, fix placeholder Jun 17, 2026
@github-actions github-actions Bot added the bug Something isn't working label Jun 17, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 17, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 17, 2026

@viktoravelino viktoravelino left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

… session filter label mismatch on flow editor (#13668)

* fix(a11y): fix aria-allowed-attr, invalid sidebar list structure, and session filter label mismatch on flow editor

* [autofix.ci] apply automated fixes

* improve translations

* remove app-header-a11y

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 22, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 22, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 22, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 22, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 22, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 23, 2026
@olayinkaadelakun
olayinkaadelakun merged commit 6f7c1f8 into feat/a11y Jun 24, 2026
103 of 104 checks passed
@olayinkaadelakun
olayinkaadelakun deleted the LE-1568 branch June 24, 2026 15:25
pony-maggie pushed a commit to pony-maggie/langflow that referenced this pull request Jun 25, 2026
* chore: add accessibility action plan and gap report for IBM Level 1 compliance

* feat: integrate accessibility checker for automated a11y scans

- Added `accessibility-checker` package to the project dependencies.
- Enhanced test fixtures to include accessibility scanning capabilities.
- Implemented `runA11yScan` method in the `LangflowPage` type for running accessibility checks.
- Created utility functions for building accessibility scan labels, formatting failure messages, and generating summary attachments.
- Updated test setup to manage accessibility sessions and assert compliance based on scan results.

* feat: add accessibility test usage documentation for IBM scans

* feat: enhance accessibility testing with JSON report aggregation and new tests

* feat: add GitHub Actions workflow for IBM accessibility scans

* feat: update a11y scan workflow to allow testing from feat/a11y branch

* feat: skip Puppeteer download during npm install in Dockerfiles for accessibility testing

* feat: enhance a11y scan workflow to resolve and scan latest release branches

* test: add component a11y unit tests (jest-axe) (langflow-ai#13613)

* test: add component a11y unit tests (jest-axe)

Cover 14 components in two waves. 16 tests fail by design - each
encodes a known gap from a11y-action-plan (phases 0-3) and flips to
a regression lock once the component fix lands. 23 tests pass as
regression locks for already-correct semantics.

* ci: split a11y unit tests into separate workflow

Main jest CI excludes *.a11y.test.* so known-gap failures don't
block PRs; new a11y-unit-tests.yml runs them as informational check.

* fix(a11y): resolve component gaps flagged by a11y unit tests

Fixes all 16 failing jest-axe gap tests:
- TableHead defaults scope=col
- alert display area gets aria-live region
- app header becomes <header> landmark; bell button labeled
- icon wrapper decorative by default (aria-hidden), ariaLabel opt-in
- Input drops wrapping <label> (name pollution) and hides placeholder span
- password toggle back in tab order with aria-label/aria-pressed
- CheckBoxDiv exposes checkbox role + state
- accordion trigger renders native Radix button
- dialogs focus container on open instead of suppressing autofocus
- full-screen modal exposes dialog role/aria-modal/ariaLabel
- flow list card focusable with keyboard activation

Also wraps test focus calls in act() and mocks the icon loader so
the a11y suite runs without React warnings.

* fix: skip Puppeteer Chrome download in remaining Dockerfiles

frontend and base images still ran bare npm install; puppeteer (via
accessibility-checker, test-only) tried to fetch Chrome and broke the
Docker image build in CI.

* test: extend a11y unit test coverage (jest-axe)

Adds axe + semantics tests for untested primitives (button, alert,
textarea, radio-group, dropdown-menu, tooltip, popover) and two
known-gap tests that fail by design until fixes land:
- copyFieldAreaComponent copy action is a bare div onClick (plan 2.4)
- DialogContentWithouFixed renders an empty fragment (plan 1.6)

* fix: make webhook copy field a real button (a11y)

Copy action was a bare div onClick - no role, name, or keyboard
support (a11y-action-plan 2.4). Drops the no-longer-needed
DialogContentWithouFixed known-gap test.

* feat: update a11y unit tests and improve accessibility semantics in components

* feat: enable pull request trigger for a11y scan workflow

* feat: Add a11y regression scan suite (langflow-ai#13663)

* test: add component a11y unit tests (jest-axe)

Cover 14 components in two waves. 16 tests fail by design - each
encodes a known gap from a11y-action-plan (phases 0-3) and flips to
a regression lock once the component fix lands. 23 tests pass as
regression locks for already-correct semantics.

* ci: split a11y unit tests into separate workflow

Main jest CI excludes *.a11y.test.* so known-gap failures don't
block PRs; new a11y-unit-tests.yml runs them as informational check.

* fix(a11y): resolve component gaps flagged by a11y unit tests

Fixes all 16 failing jest-axe gap tests:
- TableHead defaults scope=col
- alert display area gets aria-live region
- app header becomes <header> landmark; bell button labeled
- icon wrapper decorative by default (aria-hidden), ariaLabel opt-in
- Input drops wrapping <label> (name pollution) and hides placeholder span
- password toggle back in tab order with aria-label/aria-pressed
- CheckBoxDiv exposes checkbox role + state
- accordion trigger renders native Radix button
- dialogs focus container on open instead of suppressing autofocus
- full-screen modal exposes dialog role/aria-modal/ariaLabel
- flow list card focusable with keyboard activation

Also wraps test focus calls in act() and mocks the icon loader so
the a11y suite runs without React warnings.

* fix: skip Puppeteer Chrome download in remaining Dockerfiles

frontend and base images still ran bare npm install; puppeteer (via
accessibility-checker, test-only) tried to fetch Chrome and broke the
Docker image build in CI.

* test: extend a11y unit test coverage (jest-axe)

Adds axe + semantics tests for untested primitives (button, alert,
textarea, radio-group, dropdown-menu, tooltip, popover) and two
known-gap tests that fail by design until fixes land:
- copyFieldAreaComponent copy action is a bare div onClick (plan 2.4)
- DialogContentWithouFixed renders an empty fragment (plan 1.6)

* fix: make webhook copy field a real button (a11y)

Copy action was a bare div onClick - no role, name, or keyboard
support (a11y-action-plan 2.4). Drops the no-longer-needed
DialogContentWithouFixed known-gap test.

* feat: update a11y unit tests and improve accessibility semantics in components

* feat: enable pull request trigger for a11y scan workflow

* test: add a11y regression scan suite

* test: make a11y scans non-blocking

* test: discover a11y scan specs

* ci: group a11y workflow checks

* fix(a11y): restore focus-visible indicators (langflow-ai#13664)

* fix(a11y): restore focus-visible indicators

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>

* a11y: improve auth accessibility coverage (langflow-ai#13724)

* fix: improve auth accessibility coverage

* fix(a11y): restore delete trigger tab focus

* test(dialog): cover nested description

* fix(a11y): add accessible names and hide decorative icons in LangflowCounts (langflow-ai#13731)

* fix(a11y): add accessible names and hide decorative icons in LangflowCounts

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* fix(a11y): add accessible names to icon-only buttons, fix placeholder (langflow-ai#13666)

* fix(a11y): add accessible names to icon-only buttons, fix placeholder contrast, and enforce touch target size on /flows

* [autofix.ci] apply automated fixes

* fix issues

* [autofix.ci] apply automated fixes

* fix(a11y): fix aria-allowed-attr, invalid sidebar list structure, and session filter label mismatch on flow editor (langflow-ai#13668)

* fix(a11y): fix aria-allowed-attr, invalid sidebar list structure, and session filter label mismatch on flow editor

* [autofix.ci] apply automated fixes

* improve translations

* remove app-header-a11y

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>

* label get-started close button and fix dark-mode placeholder contrast

* remove testing change

* improve the lint of the testcase

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>

* fix: update package dependencies and versions in package-lock.json

* chore: Remove accessibility documentation and reports

- Deleted the accessibility action plan, gap report, level 1 requirements, and test usage documentation.
- This cleanup is part of a broader effort to streamline accessibility resources and focus on actionable items.

* chore: Add accessibility scan reports (langflow-ai#13812)

* feat: add accessibility scan reports

* docs: add a11y scan route map

* test(a11y): add manifest-backed scans

* ci(a11y): summarize scans by route

* fix: update Playwright version to 1.60.0 and enhance a11y scan options

* fix(test): keep fixture args destructured

* test(a11y): bootstrap asset route scans

---------

Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
YeonghyeonKO pushed a commit to YeonghyeonKO/langflow-hynix that referenced this pull request Jul 2, 2026
…eral page (langflow-ai#13811)

* chore: add accessibility action plan and gap report for IBM Level 1 compliance

* feat: integrate accessibility checker for automated a11y scans

- Added `accessibility-checker` package to the project dependencies.
- Enhanced test fixtures to include accessibility scanning capabilities.
- Implemented `runA11yScan` method in the `LangflowPage` type for running accessibility checks.
- Created utility functions for building accessibility scan labels, formatting failure messages, and generating summary attachments.
- Updated test setup to manage accessibility sessions and assert compliance based on scan results.

* feat: add accessibility test usage documentation for IBM scans

* feat: enhance accessibility testing with JSON report aggregation and new tests

* feat: add GitHub Actions workflow for IBM accessibility scans

* feat: update a11y scan workflow to allow testing from feat/a11y branch

* feat: skip Puppeteer download during npm install in Dockerfiles for accessibility testing

* feat: enhance a11y scan workflow to resolve and scan latest release branches

* test: add component a11y unit tests (jest-axe) (langflow-ai#13613)

* test: add component a11y unit tests (jest-axe)

Cover 14 components in two waves. 16 tests fail by design - each
encodes a known gap from a11y-action-plan (phases 0-3) and flips to
a regression lock once the component fix lands. 23 tests pass as
regression locks for already-correct semantics.

* ci: split a11y unit tests into separate workflow

Main jest CI excludes *.a11y.test.* so known-gap failures don't
block PRs; new a11y-unit-tests.yml runs them as informational check.

* fix(a11y): resolve component gaps flagged by a11y unit tests

Fixes all 16 failing jest-axe gap tests:
- TableHead defaults scope=col
- alert display area gets aria-live region
- app header becomes <header> landmark; bell button labeled
- icon wrapper decorative by default (aria-hidden), ariaLabel opt-in
- Input drops wrapping <label> (name pollution) and hides placeholder span
- password toggle back in tab order with aria-label/aria-pressed
- CheckBoxDiv exposes checkbox role + state
- accordion trigger renders native Radix button
- dialogs focus container on open instead of suppressing autofocus
- full-screen modal exposes dialog role/aria-modal/ariaLabel
- flow list card focusable with keyboard activation

Also wraps test focus calls in act() and mocks the icon loader so
the a11y suite runs without React warnings.

* fix: skip Puppeteer Chrome download in remaining Dockerfiles

frontend and base images still ran bare npm install; puppeteer (via
accessibility-checker, test-only) tried to fetch Chrome and broke the
Docker image build in CI.

* test: extend a11y unit test coverage (jest-axe)

Adds axe + semantics tests for untested primitives (button, alert,
textarea, radio-group, dropdown-menu, tooltip, popover) and two
known-gap tests that fail by design until fixes land:
- copyFieldAreaComponent copy action is a bare div onClick (plan 2.4)
- DialogContentWithouFixed renders an empty fragment (plan 1.6)

* fix: make webhook copy field a real button (a11y)

Copy action was a bare div onClick - no role, name, or keyboard
support (a11y-action-plan 2.4). Drops the no-longer-needed
DialogContentWithouFixed known-gap test.

* feat: update a11y unit tests and improve accessibility semantics in components

* feat: enable pull request trigger for a11y scan workflow

* feat: Add a11y regression scan suite (langflow-ai#13663)

* test: add component a11y unit tests (jest-axe)

Cover 14 components in two waves. 16 tests fail by design - each
encodes a known gap from a11y-action-plan (phases 0-3) and flips to
a regression lock once the component fix lands. 23 tests pass as
regression locks for already-correct semantics.

* ci: split a11y unit tests into separate workflow

Main jest CI excludes *.a11y.test.* so known-gap failures don't
block PRs; new a11y-unit-tests.yml runs them as informational check.

* fix(a11y): resolve component gaps flagged by a11y unit tests

Fixes all 16 failing jest-axe gap tests:
- TableHead defaults scope=col
- alert display area gets aria-live region
- app header becomes <header> landmark; bell button labeled
- icon wrapper decorative by default (aria-hidden), ariaLabel opt-in
- Input drops wrapping <label> (name pollution) and hides placeholder span
- password toggle back in tab order with aria-label/aria-pressed
- CheckBoxDiv exposes checkbox role + state
- accordion trigger renders native Radix button
- dialogs focus container on open instead of suppressing autofocus
- full-screen modal exposes dialog role/aria-modal/ariaLabel
- flow list card focusable with keyboard activation

Also wraps test focus calls in act() and mocks the icon loader so
the a11y suite runs without React warnings.

* fix: skip Puppeteer Chrome download in remaining Dockerfiles

frontend and base images still ran bare npm install; puppeteer (via
accessibility-checker, test-only) tried to fetch Chrome and broke the
Docker image build in CI.

* test: extend a11y unit test coverage (jest-axe)

Adds axe + semantics tests for untested primitives (button, alert,
textarea, radio-group, dropdown-menu, tooltip, popover) and two
known-gap tests that fail by design until fixes land:
- copyFieldAreaComponent copy action is a bare div onClick (plan 2.4)
- DialogContentWithouFixed renders an empty fragment (plan 1.6)

* fix: make webhook copy field a real button (a11y)

Copy action was a bare div onClick - no role, name, or keyboard
support (a11y-action-plan 2.4). Drops the no-longer-needed
DialogContentWithouFixed known-gap test.

* feat: update a11y unit tests and improve accessibility semantics in components

* feat: enable pull request trigger for a11y scan workflow

* test: add a11y regression scan suite

* test: make a11y scans non-blocking

* test: discover a11y scan specs

* ci: group a11y workflow checks

* fix(a11y): restore focus-visible indicators (langflow-ai#13664)

* fix(a11y): restore focus-visible indicators

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>

* a11y: improve auth accessibility coverage (langflow-ai#13724)

* fix: improve auth accessibility coverage

* fix(a11y): restore delete trigger tab focus

* test(dialog): cover nested description

* fix(a11y): add accessible names and hide decorative icons in LangflowCounts (langflow-ai#13731)

* fix(a11y): add accessible names and hide decorative icons in LangflowCounts

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* fix(a11y): add accessible names to icon-only buttons, fix placeholder (langflow-ai#13666)

* fix(a11y): add accessible names to icon-only buttons, fix placeholder contrast, and enforce touch target size on /flows

* [autofix.ci] apply automated fixes

* fix issues

* [autofix.ci] apply automated fixes

* fix(a11y): fix aria-allowed-attr, invalid sidebar list structure, and session filter label mismatch on flow editor (langflow-ai#13668)

* fix(a11y): fix aria-allowed-attr, invalid sidebar list structure, and session filter label mismatch on flow editor

* [autofix.ci] apply automated fixes

* improve translations

* remove app-header-a11y

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>

* label get-started close button and fix dark-mode placeholder contrast

* remove testing change

* improve the lint of the testcase

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>

* fix(a11y): resolve WCAG 2.1 Level A and AA violations on settings general page

* fix Biome issue

* remove files that were added by incorrectly merging Release-1.11.0

* improve testcases

---------

Co-authored-by: Viktor Avelino <viktor.avelino@gmail.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants