fix(web): remove misleading ARIA states (#40015)

This commit is contained in:
yyh
2026-08-05 06:52:41 +00:00
committed by GitHub
parent 685e291e65
commit 0bf3416431
22 changed files with 38 additions and 20 deletions
@@ -352,8 +352,9 @@ describe('ConfigurationView', () => {
render(<ConfigurationView {...createViewModel({ contextValue })} />)
const badge = screen.getByRole('button', { name: 'appDebug.legacyAgentBadge.description' })
const badge = screen.getByRole('button', { name: 'appDebug.legacyAgentBadge.label' })
expect(badge).toHaveTextContent('appDebug.legacyAgentBadge.label')
expect(badge).not.toHaveAttribute('aria-label')
fireEvent.click(badge)
@@ -54,7 +54,6 @@ function LegacyAgentBadge() {
delay={300}
closeDelay={200}
type="button"
aria-label={description}
className="inline-flex h-5 shrink-0 cursor-pointer items-center gap-0.5 rounded-[5px] border border-text-warning bg-components-badge-bg-dimm px-1.25 system-2xs-medium-uppercase whitespace-nowrap text-text-warning outline-hidden hover:bg-state-warning-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid"
>
<span aria-hidden className="i-ri-alert-fill size-3 shrink-0" />
@@ -456,7 +456,7 @@ describe('AppCard', () => {
const card = screen.getByRole('button', { name: 'Preview Only App' })
expect(card).toHaveClass('opacity-60')
expect(card).toHaveAttribute('aria-disabled', 'true')
expect(card).not.toHaveAttribute('aria-disabled')
expect(screen.getByText('Only visible metadata')).toBeInTheDocument()
expect(screen.getByText('Readonly Author')).toBeInTheDocument()
const tagSelector = screen.getByLabelText('tag-selector')
@@ -495,7 +495,7 @@ describe('AppCard', () => {
const card = screen.getByRole('button', { name: 'Preview Only Starred App' })
expect(card).toHaveClass('opacity-60')
expect(card).toHaveAttribute('aria-disabled', 'true')
expect(card).not.toHaveAttribute('aria-disabled')
expect(screen.getByText('Readonly Author')).toBeInTheDocument()
expect(
screen.queryByRole('link', { name: 'Preview Only Starred App' }),
-1
View File
@@ -1204,7 +1204,6 @@ export function AppCard({
<article
role="button"
tabIndex={0}
aria-disabled="true"
aria-labelledby={appNameId}
aria-describedby={app.description ? appDescriptionId : undefined}
data-step-by-step-tour-target={stepByStepTourCardTarget}
@@ -106,7 +106,6 @@ export function StarredAppCard({
<div
role="button"
tabIndex={0}
aria-disabled="true"
aria-label={app.name}
data-step-by-step-tour-target={stepByStepTourCardTarget}
data-step-by-step-tour-highlight-part={stepByStepTourCardHighlightPart}
@@ -14,6 +14,7 @@ describe('AudioPreview', () => {
const audio = document.querySelector('audio')
expect(audio).toBeInTheDocument()
expect(audio).toHaveAttribute('title', 'Test Audio')
expect(audio?.parentElement).not.toHaveAttribute('aria-label')
})
it('should render source element with correct src and type', () => {
@@ -64,6 +64,7 @@ describe('PdfPreview', () => {
render(<PdfPreview url="https://example.com/doc.pdf" onCancel={mockOnCancel} />)
expect(document.querySelector('[tabindex="-1"]')).toBeInTheDocument()
expect(getScaleContainer()).not.toHaveAttribute('aria-label')
expect(screen.getByTestId('pdf-loader')).toBeInTheDocument()
expect(screen.getByTestId('pdf-highlighter')).toBeInTheDocument()
expect(screen.getByRole('status')).toBeInTheDocument()
@@ -14,6 +14,7 @@ describe('VideoPreview', () => {
const video = document.querySelector('video')
expect(video).toBeInTheDocument()
expect(video).toHaveAttribute('title', 'Test Video')
expect(video?.parentElement).not.toHaveAttribute('aria-label')
})
it('should render source element with correct src and type', () => {
@@ -22,7 +22,7 @@ const AudioPreview: FC<AudioPreviewProps> = ({ url, title, onCancel }) => {
className="inset-0! top-0! left-0! flex h-dvh! max-h-none! w-screen! max-w-none! translate-0! items-center justify-center overflow-hidden! rounded-none! border-none! bg-black/80 p-8! shadow-none!"
backdropClassName="bg-transparent!"
>
<div aria-label={title} tabIndex={-1} onClick={(e) => e.stopPropagation()}>
<div tabIndex={-1} onClick={(e) => e.stopPropagation()}>
<audio controls title={title} autoPlay={false} preload="metadata">
<source type="audio/mpeg" src={url} className="max-h-full max-w-full" />
</audio>
@@ -57,7 +57,6 @@ const PdfPreview: FC<PdfPreviewProps> = ({ url, onCancel }) => {
backdropClassName="bg-transparent!"
>
<div
aria-label={url}
tabIndex={-1}
onClick={(e) => e.stopPropagation()}
className="h-[95vh] max-h-full w-screen max-w-full overflow-hidden"
@@ -22,7 +22,7 @@ const VideoPreview: FC<VideoPreviewProps> = ({ url, title, onCancel }) => {
className="inset-0! top-0! left-0! flex h-dvh! max-h-none! w-screen! max-w-none! translate-0! items-center justify-center overflow-hidden! rounded-none! border-none! bg-black/80 p-8! shadow-none!"
backdropClassName="bg-transparent!"
>
<div aria-label={title} tabIndex={-1} onClick={(e) => e.stopPropagation()}>
<div tabIndex={-1} onClick={(e) => e.stopPropagation()}>
<video controls title={title} autoPlay={false} preload="metadata">
<source type="video/mp4" src={url} className="max-h-full max-w-full" />
</video>
@@ -99,6 +99,7 @@ describe('ImagePreview', () => {
const overlay = getOverlay()
expect(overlay).toBeInTheDocument()
expect(screen.getByTestId('image-preview-container')).not.toHaveAttribute('aria-label')
expect(overlay.closest('[data-base-ui-portal]')?.parentElement).toBe(document.body)
expect(screen.getByRole('img', { name: 'Preview Image' })).toHaveAttribute(
'src',
@@ -185,7 +185,6 @@ const ImagePreview: FC<ImagePreviewProps> = ({ url, title, onCancel, onPrev, onN
backdropClassName="bg-transparent!"
>
<div
aria-label={title}
data-testid="image-preview-container"
tabIndex={-1}
className="flex size-full items-center justify-center"
@@ -383,7 +383,7 @@ describe('DatasetCard Component', () => {
const card = screen.getByRole('button', { name: 'Preview Only Dataset' })
expect(card).toHaveClass('opacity-60')
expect(card).toHaveAttribute('aria-disabled', 'true')
expect(card).not.toHaveAttribute('aria-disabled')
expect(screen.getByText('Preview Only Dataset')).toBeInTheDocument()
const tagArea = screen.getByTestId('tag-area')
expect(tagArea).toHaveAttribute('data-can-bind-or-unbind-tags', 'false')
@@ -120,7 +120,6 @@ const DatasetCard = ({
<div
role={isPreviewOnly ? 'button' : undefined}
tabIndex={isPreviewOnly ? 0 : undefined}
aria-disabled={isPreviewOnly ? 'true' : undefined}
aria-label={isPreviewOnly ? dataset.name : undefined}
className={cardClassName}
data-disable-nprogress={true}
@@ -307,7 +307,9 @@ describe('PopupItem', () => {
)
fireEvent.click(screen.getByText('GPT-4'))
fireEvent.click(screen.getByText('COMMON.OPERATION.ADD'))
const addButton = screen.getByRole('button', { name: 'COMMON.OPERATION.ADD' })
expect(addButton.closest('[aria-disabled="true"]')).toBeNull()
fireEvent.click(addButton)
expect(onValueChange).not.toHaveBeenCalled()
expect(mockSetShowModelModal).toHaveBeenCalled()
@@ -225,7 +225,7 @@ function PopupItem({
)
const itemRender =
modelItem.status === ModelStatusEnum.noConfigure ? (
<div className={rowClassName} aria-disabled="true" onPointerDown={onPreviewCardClose}>
<div className={rowClassName} onPointerDown={onPreviewCardClose}>
{rowContent}
{canCreateCredential && (
<button
+20 -1
View File
@@ -1,5 +1,5 @@
import { useQuery } from '@tanstack/react-query'
import { screen, waitFor } from '@testing-library/react'
import { fireEvent, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { useRouter, useSearchParams } from '@/next/navigation'
import { renderWithConsoleQuery as render } from '@/test/console/query-data'
@@ -205,4 +205,23 @@ describe('NormalForm', () => {
)
})
})
it('should describe password visibility through its changing action name', () => {
mockQueryResults(
nonInviteQueryResult as unknown as ReturnType<typeof useQuery>,
nonInviteQueryResult as unknown as ReturnType<typeof useQuery>,
)
render(<NormalForm />)
const showPasswordButton = screen.getByRole('button', { name: 'login.showPassword' })
expect(showPasswordButton).not.toHaveAttribute('aria-pressed')
fireEvent.click(showPasswordButton)
expect(screen.getByRole('button', { name: 'login.hidePassword' })).not.toHaveAttribute(
'aria-pressed',
)
expect(screen.getByLabelText('login.password')).toHaveAttribute('type', 'text')
})
})
@@ -156,7 +156,6 @@ export default function MailAndPasswordAuth({ isInvite, isEmailSetup }: MailAndP
aria-label={t(($) => $[showPassword ? 'hidePassword' : 'showPassword'], {
ns: 'login',
})}
aria-pressed={showPassword}
className="mr-1 size-8 p-0 text-text-tertiary hover:text-text-secondary"
onClick={() => setShowPassword(!showPassword)}
>
@@ -138,14 +138,14 @@ describe('ContinueWorkItem', () => {
)
})
it('should render preview-only apps as disabled buttons and warn on click', async () => {
it('should render preview-only apps as action buttons that explain the access restriction', async () => {
const user = userEvent.setup()
renderItem(createApp({ permission_keys: [AppACLPermission.Preview] }))
const card = screen.getByRole('button', { name: /Continue App.*app\.types\.chatbot/i })
expect(card).toHaveAttribute('type', 'button')
expect(card).toHaveAttribute('aria-disabled', 'true')
expect(card).not.toHaveAttribute('aria-disabled')
expect(card).toHaveAccessibleDescription(/Alice.*5 minutes ago/)
expect(screen.queryByRole('link', { name: /Continue App/ })).not.toBeInTheDocument()
-1
View File
@@ -110,7 +110,6 @@ export function ContinueWorkItem({ app }: ContinueWorkItemProps) {
type="button"
aria-labelledby={`${appNameId} ${appModeId}`}
aria-describedby={appMetadataId}
aria-disabled="true"
className="absolute inset-0 z-10 cursor-not-allowed touch-manipulation appearance-none rounded-xl border-0 bg-transparent p-0 outline-hidden focus-visible:inset-ring-2 focus-visible:inset-ring-state-accent-solid"
onClick={showPreviewOnlyAccessWarning}
/>
@@ -770,7 +770,7 @@ describe('HomeContent', () => {
renderHomeContent()
const card = screen.getByRole('button', { name: /Preview Only App.*app\.types\.chatbot/ })
expect(card).toHaveAttribute('aria-disabled', 'true')
expect(card).not.toHaveAttribute('aria-disabled')
expect(screen.queryByRole('link', { name: /Preview Only App/ })).not.toBeInTheDocument()
expect(screen.getByText('Readonly Author')).toBeInTheDocument()