Skip to content

Commit 87d479f

Browse files
authored
fix(picker): add aria-* for datepicker (#4028)
* fix(picker): add aria-* for datepicker * fix(e2e): fix date-picker's e2e error
1 parent 7088018 commit 87d479f

File tree

10 files changed

+51
-38
lines changed

10 files changed

+51
-38
lines changed

examples/sites/demos/pc/app/date-picker/align.spec.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,35 @@ test.use({
66
test('[DatePicker] 测试对齐方式', async ({ page }) => {
77
page.on('pageerror', (exception) => expect(exception).toBeNull())
88
await page.goto('date-picker#align')
9-
await page.locator('.settings-btn').first().click()
10-
await page.locator('label').filter({ hasText: '单示例' }).click()
11-
await page.waitForSelector('.demo-date-picker-wrap', { state: 'visible' })
12-
9+
const demo = page.locator('#align')
1310
// 左对齐
14-
const leftDateInputDom = page.getByRole('textbox').nth(1)
15-
const leftDatePanelDom = page.locator('.tiny-picker-panel').nth(2)
11+
const leftDateInputDom = demo.locator('.tiny-input__inner').nth(0)
12+
const leftDatePanelDom = page.locator('body > .tiny-picker-panel').nth(0)
1613
const leftClosePanel = page.getByText('左对齐:')
1714
await page.waitForTimeout(200)
1815

1916
await leftDateInputDom.click()
2017
await page.waitForTimeout(200)
21-
await expect(leftDatePanelDom).toHaveAttribute('x-placement', /bottom-start|top-start/)
18+
await expect(leftDatePanelDom).toHaveAttribute('x-placement', 'bottom-start')
2219
await leftClosePanel.click()
2320

2421
// 居中对齐
25-
const centerDateInputDom = page.getByRole('textbox').nth(2)
26-
const centerDatePanelDom = page.locator('.tiny-picker-panel').nth(2)
22+
const centerDateInputDom = demo.locator('.tiny-input__inner').nth(1)
23+
const centerDatePanelDom = page.locator('body > .tiny-picker-panel').nth(1)
2724
const centerClosePanel = page.getByText('居中对齐:')
2825

2926
await centerDateInputDom.click()
3027
await page.waitForTimeout(200)
31-
await expect(centerDatePanelDom).toHaveAttribute('x-placement', /bottom|top/)
28+
await expect(centerDatePanelDom).toHaveAttribute('x-placement', /bottom/)
3229
await centerClosePanel.click()
3330

3431
// 右对齐
35-
const rightDateInputDom = page.getByRole('textbox').nth(3)
36-
const rightDatePanelDom = page.locator('.tiny-picker-panel').nth(2)
32+
const rightDateInputDom = demo.locator('.tiny-input__inner').nth(2)
33+
const rightDatePanelDom = page.locator('body > .tiny-picker-panel').nth(2)
3734
const rightClosePanel = page.getByText('右对齐:')
3835

3936
await rightDateInputDom.click()
4037
await page.waitForTimeout(200)
41-
await expect(rightDatePanelDom).toHaveAttribute('x-placement', /bottom-end|top-end/)
38+
await expect(rightDatePanelDom).toHaveAttribute('x-placement', /bottom-end/)
4239
await rightClosePanel.click()
4340
})

examples/sites/demos/pc/app/date-picker/clear.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ test('[DatePicker] 测试清除输入', async ({ page }) => {
66

77
const demo = page.locator('#clear')
88

9-
const datePickerDefaultClearIcon = demo.getByRole('textbox').nth(0)
10-
const datePickerHideClearIcon = demo.getByRole('textbox').nth(1)
11-
const datePickerCustomClearIcon = demo.getByRole('textbox').nth(2)
9+
const datePickerDefaultClearIcon = demo.getByRole('combobox').nth(0)
10+
const datePickerHideClearIcon = demo.getByRole('combobox').nth(1)
11+
const datePickerCustomClearIcon = demo.getByRole('combobox').nth(2)
1212
const clearIcon = demo.locator('.tiny-date-editor .tiny-input__icon-container .baseClearicon')
1313

1414
// 默认显示清除按钮

examples/sites/demos/pc/app/date-picker/default-value.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,20 @@ test('[DatePicker] 测试选择器打开时默认时间设置', async ({ page })
77
await page.locator('label').filter({ hasText: '单示例' }).click()
88

99
// default-value: 打开日期面板,默认显示的日期
10-
await page.getByRole('textbox').nth(1).click()
10+
await page.getByRole('combobox').nth(0).click()
1111
await expect(page.getByRole('button', { name: '2000 年' })).toBeVisible()
1212
await expect(page.getByRole('button', { name: '11 月' })).toBeVisible()
1313

1414
// default-time: 日期时间 (范围),选择日期之后默认显示的时间 (范围)
15-
const dateInputDefaultTime = page.getByRole('textbox').nth(2)
15+
const dateInputDefaultTime = page.getByRole('combobox').nth(1)
1616
await dateInputDefaultTime.fill('2023-05-20 09:00:00')
1717
await dateInputDefaultTime.press('Enter')
1818

19-
await page.getByRole('textbox', { name: '2023-05-20 09:00:00' }).click()
19+
await page.getByRole('combobox', { name: '2023-05-20 09:00:00' }).click()
2020
await page.getByRole('cell', { name: '15' }).getByText('15').last().click()
2121
await expect(page.getByRole('textbox', { name: '选择时间' })).toHaveValue('09:00:00')
2222

23-
await page.getByRole('textbox').nth(3).click()
23+
await page.getByRole('combobox').nth(2).click()
2424
await page.getByRole('cell', { name: '10' }).getByText('10').last().click()
2525
await page.getByRole('cell', { name: '10' }).getByText('10').nth(1).click()
2626
await expect(page.getByRole('textbox', { name: '开始时间' })).toHaveValue('09:00:00')

examples/sites/demos/pc/app/date-picker/events.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test('[DatePicker] 测试事件', async ({ page }) => {
1919
await page
2020
.locator('div')
2121
.filter({ hasText: /^blur:$/ })
22-
.getByRole('textbox')
22+
.getByRole('combobox')
2323
.click()
2424
await page.getByRole('cell', { name: '15' }).getByText('15').last().click()
2525
const blurEventMessageDom = page.locator('div').filter({ hasText: '触发 blur 事件' }).nth(1)
@@ -33,7 +33,7 @@ test('[DatePicker] 测试事件', async ({ page }) => {
3333
await page
3434
.locator('div')
3535
.filter({ hasText: /^change:$/ })
36-
.getByRole('textbox')
36+
.getByRole('combobox')
3737
.click()
3838
await page.getByRole('cell', { name: '15' }).getByText('15').last().click()
3939
const changeEventMessageDom = page.locator('div').filter({ hasText: '触发 change 事件,组件绑定值为:' }).nth(1)

examples/sites/demos/pc/app/date-picker/format.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ test('[DatePicker] 测试日期格式化', async ({ page }) => {
55
await page.goto('date-picker#format')
66

77
// format: 日期输入框中显示的格式
8-
await page.getByRole('textbox', { name: '2023 年 05 月 24 日' }).first().click()
8+
await page.getByRole('combobox', { name: '2023 年 05 月 24 日' }).first().click()
99
await page.getByRole('cell', { name: '20' }).getByText('20').last().click()
10-
await expect(page.getByRole('textbox', { name: '2023 年 05 月 20 日' }).first()).toBeVisible()
10+
await expect(page.getByRole('combobox', { name: '2023 年 05 月 20 日' }).first()).toBeVisible()
1111

1212
// time-format: 时间输入框中显示的格式
1313
await page.locator('.tiny-date-editor input').nth(1).click()
14-
await page.getByRole('cell', { name: '24' }).locator('span').click();
14+
await page.getByRole('cell', { name: '24' }).locator('span').click()
1515
await page.getByRole('button', { name: '确定' }).click()
1616
await expect(page.locator('.tiny-date-editor input').nth(1)).toHaveValue('2023 年 05 月 24 日 08 时 00 分 00 秒')
1717

examples/sites/demos/pc/app/date-picker/now.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { test, expect } from '@playwright/test'
33
test('“此刻”逻辑定制', async ({ page }) => {
44
page.on('pageerror', (exception) => expect(exception).toBeNull())
55
await page.goto('date-picker#now')
6-
await page.getByRole('textbox', { name: '-11-11 10:10:11' }).first().click()
6+
await page.getByRole('combobox', { name: '-11-11 10:10:11' }).first().click()
77
await page.getByText('此刻(服务器时间)').click()
88
await page.getByRole('button', { name: '确定' }).click()
9-
await expect(page.getByRole('textbox', { name: '-12-11 18:18:18' })).toBeVisible()
10-
await page.getByRole('textbox', { name: '-11-11 10:10:11' }).click()
9+
await expect(page.getByRole('combobox', { name: '-12-11 18:18:18' })).toBeVisible()
10+
await page.getByRole('combobox', { name: '-11-11 10:10:11' }).click()
1111
await page.getByRole('button', { name: '此刻' }).click()
12-
await expect(page.getByRole('textbox', { name: '-10-08 18:18:18' })).toBeVisible()
12+
await expect(page.getByRole('combobox', { name: '-10-08 18:18:18' })).toBeVisible()
1313
})

examples/sites/demos/pc/app/date-picker/shortcuts.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ test('[DatePicker] 测试选择快捷选项日期:今天/昨天/一周前', as
55
await page.goto('date-picker#shortcuts')
66

77
// 日期选择:今天/昨天/一周前
8-
const datePickerDom = page.getByRole('textbox', { name: '请选择日期' })
8+
const datePickerDom = page.getByRole('combobox', { name: '请选择日期' })
99
await datePickerDom.click()
1010
await page.getByRole('button', { name: '今天' }).click()
1111
await page.locator('.tiny-date-editor input').first().click()

examples/sites/demos/pc/app/date-picker/slot.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@ test('[DatePicker] 测试尺寸设置', async ({ page }) => {
77
let btn = page.getByRole('button', { name: '自定义按钮' })
88
let nowBtn = page.getByRole('button', { name: '自定义此刻' })
99

10-
await page.locator('#slot').getByRole('textbox', { name: '请选择日期', exact: true }).click()
10+
await page.locator('#slot').getByRole('combobox', { name: '请选择日期', exact: true }).click()
1111
await page.waitForTimeout(200)
1212
await expect(btn).toBeVisible()
1313

14-
await page.getByRole('textbox', { name: '请选择日期时间' }).click()
14+
await page.getByRole('combobox', { name: '请选择日期时间' }).click()
1515
await page.waitForTimeout(200)
1616
await expect(nowBtn).toBeVisible()
1717

18-
await page.locator('#slot').getByRole('textbox', { name: '请选择周' }).click()
18+
await page.locator('#slot').getByRole('combobox', { name: '请选择周' }).click()
1919
await page.waitForTimeout(200)
2020
await expect(btn.first()).toBeVisible()
2121

22-
await page.locator('#slot').getByRole('textbox', { name: '请选择月份' }).click()
22+
await page.locator('#slot').getByRole('combobox', { name: '请选择月份' }).click()
2323
await page.waitForTimeout(200)
2424
await expect(btn.first()).toBeVisible()
2525

26-
await page.locator('#slot').getByRole('textbox', { name: '请选择年份' }).click()
26+
await page.locator('#slot').getByRole('combobox', { name: '请选择年份' }).click()
2727
await page.waitForTimeout(200)
2828
await expect(btn.first()).toBeVisible()
2929

packages/renderless/src/picker/vue.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ import {
7070
formatInputValue
7171
} from './index'
7272
import { dateMobileToggle, timeMobileToggle, dateToTimeArray, timeArrayToDate, timeMobileConfirm } from './mb'
73-
import { DATEPICKER } from '@opentiny/utils'
73+
import { DATEPICKER, nanoid } from '@opentiny/utils'
7474
import type {
7575
IPickerProps,
7676
IPickerApi,
@@ -178,7 +178,8 @@ const initState = ({ api, reactive, vm, computed, props, utils, parent, breakpoi
178178
(state.innerWidth < 335 && state.type === 'datetimerange')) &&
179179
state.displayValue &&
180180
state.displayValue[1]
181-
)
181+
),
182+
ariaPanelId: 'panel-' + nanoid.api.nanoid(8)
182183
})
183184

184185
return state

packages/vue/src/picker/src/pc.vue

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
@mouseenter="handleMouseEnter"
3838
@mouseleave="state.showClose = false"
3939
:validate-event="false"
40+
role="combobox"
41+
aria-haspopup="dialog"
42+
aria-autocomplete="none"
43+
:aria-owns="state.ariaPanelId"
44+
:aria-controls="state.ariaPanelId"
4045
>
4146
<template v-if="label" #prefix>
4247
<tiny-tooltip
@@ -58,9 +63,10 @@
5863
@mouseleave="state.showClose = false"
5964
v-if="state.haveTrigger"
6065
class="baseClearicon"
66+
aria-label="clear"
6167
/>
6268
</transition>
63-
<component :is="state.triggerClass" @click="handleFocus" class="tiny-svg-size" />
69+
<component :is="state.triggerClass" @click="handleFocus" class="tiny-svg-size" aria-label="calendar" />
6470
</i>
6571
</template>
6672
</tiny-input>
@@ -101,6 +107,11 @@
101107
@focus="handleFocus"
102108
tabindex="1"
103109
class="tiny-range-input"
110+
role="combobox"
111+
aria-haspopup="dialog"
112+
aria-autocomplete="none"
113+
:aria-owns="state.ariaPanelId"
114+
:aria-controls="state.ariaPanelId"
104115
/>
105116
<slot name="range-separator">
106117
<span v-if="typeof rangeSeparator === 'string'" class="tiny-range-separator">{{ rangeSeparator }}</span>
@@ -151,6 +162,10 @@
151162
@pick="handlePick"
152163
@select-range="handleSelectRange"
153164
@select-change="handleSelectChange"
165+
role="dialog"
166+
aria-modal="false"
167+
aria-lable="picker-panel"
168+
:id="state.ariaPanelId"
154169
>
155170
<template v-if="$slots.footer || $slots.now || $slots.confirm" #footer="scoped">
156171
<slot name="footer" v-bind="scoped">

0 commit comments

Comments
 (0)