Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 优化数字键盘及虚拟输入框无障碍 #6494

Merged
merged 16 commits into from
Dec 22, 2023
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
// maxConcurrency: 1,
maxConcurrency: 1,
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
modulePathIgnorePatterns: ['<rootDir>/lib/', '<rootDir>/dist/'],
moduleDirectories: ['node_modules', 'src/tests'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ exports[`ActionSheet basic usage 1`] = `
class="adm-popup adm-action-sheet-popup"
>
<div
aria-hidden="true"
class="adm-mask"
style="background: rgba(0, 0, 0, 0.55); opacity: 1;"
>
Expand Down
8 changes: 7 additions & 1 deletion src/components/dialog/tests/dialog.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */

import React from 'react'
import {
render,
Expand All @@ -6,6 +8,7 @@ import {
waitFor,
waitForElementToBeRemoved,
screen,
waitFakeTimers,
} from 'testing'
import Dialog, { DialogAlertProps } from '..'
import { act } from '@testing-library/react'
Expand Down Expand Up @@ -65,8 +68,11 @@ describe('Dialog', () => {
)

fireEvent.click(screen.getByRole('button', { name: 'btn' }))
const mask = await screen.findByRole('button', { name: '背景蒙层' })
await waitFakeTimers()

const mask = document.querySelector('.adm-mask-aria-button')!
fireEvent.click(mask)

await waitForElementToBeRemoved(mask)
expect(onClose).toBeCalled()
expect(afterClose).toBeCalled()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ exports[`ImageViewer.Multi calling ref.current.swipeTo before initialization 2`]
</span>
</button>
<div
aria-hidden="true"
class="adm-mask"
style="background: rgba(0, 0, 0, 0.75); opacity: 1;"
>
Expand Down
22 changes: 16 additions & 6 deletions src/components/image-viewer/tests/image-viewer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ jest.mock('../../../utils/use-drag-and-pinch', () => {
}
})

async function getImages() {
const images = await screen.findAllByText(
(content, element) => element?.tagName.toLowerCase() === 'img'
)

return images[0]
}

describe('ImageViewer.Multi', () => {
test('calling ref.current.swipeTo before initialization', async () => {
function App() {
Expand Down Expand Up @@ -149,12 +157,13 @@ describe('ImageViewer.Multi', () => {
</>
)
fireEvent.click(screen.getByText('show'))
const imgs = await screen.findAllByRole('img')
expect(imgs[0]).toBeVisible()
const img = await getImages()

expect(img).toBeVisible()
await act(async () => {
await userEvent.click(imgs[0])
await userEvent.click(img)
})
await waitFor(() => expect(imgs[0]).not.toBeVisible())
await waitFor(() => expect(img).not.toBeVisible())
})

test('slide and slide with pinched should be work', async () => {
Expand All @@ -174,7 +183,7 @@ describe('ImageViewer.Multi', () => {
)
})

await screen.findAllByRole('img')
await getImages()

G?.onPinch({
origin: [235, 202],
Expand Down Expand Up @@ -254,7 +263,8 @@ describe('ImageViewer', () => {
</button>
)
fireEvent.click(screen.getByText('show'))
const img = await screen.findByRole('img')

const img = await getImages()
expect(img).toBeVisible()

act(() => {
Expand Down
1 change: 1 addition & 0 deletions src/components/mask/mask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export const Mask: FC<MaskProps> = p => {
<animated.div
className={classPrefix}
ref={ref}
aria-hidden
style={{
...props.style,
background,
Expand Down
8 changes: 7 additions & 1 deletion src/components/modal/tests/modal.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import React from 'react'
import {
render,
Expand All @@ -7,6 +8,7 @@ import {
waitForElementToBeRemoved,
screen,
act,
waitFakeTimers,
} from 'testing'
import Modal, { ModalAlertProps } from '..'

Expand Down Expand Up @@ -66,9 +68,13 @@ describe('Modal', () => {
)

fireEvent.click(screen.getByRole('button', { name: 'btn' }))
const mask = await screen.findByRole('button', { name: '背景蒙层' })
await waitFakeTimers()

const mask = document.querySelector('.adm-mask-aria-button')!
fireEvent.click(mask)

await waitForElementToBeRemoved(mask)

expect(onClose).toBeCalled()
expect(afterClose).toBeCalled()
})
Expand Down
15 changes: 9 additions & 6 deletions src/components/number-keyboard/number-keyboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Popup, { PopupProps } from '../popup'
import { NativeProps, withNativeProps } from '../../utils/native-props'
import SafeArea from '../safe-area'
import { useMemoizedFn } from 'ahooks'
import { useConfig } from '../config-provider'

const classPrefix = 'adm-number-keyboard'

Expand Down Expand Up @@ -59,6 +60,8 @@ export const NumberKeyboard: FC<NumberKeyboardProps> = p => {
onInput,
} = props

const { locale } = useConfig()

const keyboardRef = useRef<HTMLDivElement | null>(null)

const keys = useMemo(() => {
Expand Down Expand Up @@ -138,8 +141,8 @@ export const NumberKeyboard: FC<NumberKeyboardProps> = p => {
onClick={() => {
props.onClose?.()
}}
role='grid'
title='CLOSE'
role='button'
title={locale.common.close}
tabIndex={-1}
>
<DownOutline />
Expand All @@ -160,7 +163,7 @@ export const NumberKeyboard: FC<NumberKeyboardProps> = p => {

const ariaProps = key
? {
role: 'grid',
role: 'button',
title: key,
tabIndex: -1,
}
Expand Down Expand Up @@ -233,16 +236,16 @@ export const NumberKeyboard: FC<NumberKeyboardProps> = p => {
// Long press should not trigger native context menu
e.preventDefault()
}}
title='BACKSPACE'
role='grid'
title={locale.Input.clear}
role='button'
tabIndex={-1}
>
<TextDeletionOutline />
</div>
<div
className={`${classPrefix}-key ${classPrefix}-key-extra ${classPrefix}-key-ok`}
onTouchEnd={e => onKeyPress(e, 'OK')}
role='grid'
role='button'
tabIndex={-1}
aria-label={confirmText}
>
Expand Down
7 changes: 4 additions & 3 deletions src/components/number-keyboard/tests/number-keyboard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ describe('NumberKeyboard', () => {
test('onClose should be called by close button', () => {
const onClose = jest.fn()
render(<NumberKeyboard visible onClose={onClose} />)
fireEvent.click(screen.getByTitle('CLOSE'))

fireEvent.click(screen.getByTitle('关闭'))
expect(onClose).toBeCalledTimes(1)
})

Expand Down Expand Up @@ -75,7 +76,7 @@ describe('NumberKeyboard', () => {
/>
)
const confirm = screen.getByText('confirm')
const del = screen.getByTitle('BACKSPACE')
const del = screen.getByTitle('清除')
expect(confirm).toBeInTheDocument()
expect(confirm).toHaveClass(
`${classPrefix}-key-extra ${classPrefix}-key-ok`
Expand Down Expand Up @@ -118,7 +119,7 @@ describe('NumberKeyboard', () => {
const popup = document.querySelector(`.${classPrefix}-popup`)
const main = document.querySelector(`.${classPrefix}-main`)
expect(main).not.toHaveTextContent('1234567890')
fireEvent.click(screen.getByTitle('CLOSE'))
fireEvent.click(screen.getByTitle('关闭'))
await waitFor(() => expect(popup).not.toBeVisible())
})

Expand Down
4 changes: 2 additions & 2 deletions src/components/virtual-input/tests/virtual-input.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ describe('VirtualInput', () => {
expect(document.querySelector(`.${classPrefix}-content`)).toHaveTextContent(
'0'
)
expect(screen.getByTitle('CLOSE')).toBeInTheDocument()
fireEvent.click(screen.getByTitle('CLOSE'))
expect(screen.getByTitle('关闭')).toBeInTheDocument()
fireEvent.click(screen.getByTitle('关闭'))
fireEvent.blur(screen.getByTestId('virtualInput'))
await waitFor(() => {
expect(
Expand Down
2 changes: 1 addition & 1 deletion src/components/virtual-input/virtual-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export const VirtualInput = forwardRef<VirtualInputRef, VirtualInputProps>(
[`${classPrefix}-disabled`]: props.disabled,
})}
tabIndex={props.disabled ? undefined : 0}
role='option'
role='textbox'
onFocus={onFocus}
onBlur={onBlur}
onClick={props.onClick}
Expand Down
9 changes: 9 additions & 0 deletions src/tests/testing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@ export const actSleep = (time: number) => {
return act(() => sleep(time))
}

export const waitFakeTimers = async () => {
for (let i = 0; i < 10; i += 1) {
await act(async () => {
jest.advanceTimersByTime(1000)
await Promise.resolve()
})
}
}

export const mockDrag = async (el: Element, options: any[], time?: number) => {
const [downOptions, ...moveOptions] = options
fireEvent.mouseDown(el, {
Expand Down
Loading