Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion playwright/e2e/a11y-question-inputs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { test as formTest } from '../support/fixtures/form.ts'
import { test as appNavigationTest } from '../support/fixtures/navigation.ts'
import { test as randomUserTest } from '../support/fixtures/random-user.ts'
import { test as topBarTest } from '../support/fixtures/topBar.ts'
import { QuestionType } from '../support/sections/QuestionType.ts'
import { GridSubtype, QuestionType } from '../support/sections/QuestionType.ts'
import { FormsView } from '../support/sections/TopBarSection.ts'

const test = mergeTests(randomUserTest, appNavigationTest, formTest, topBarTest)
Expand All @@ -32,6 +32,9 @@ test.describe('Accessibility: aria attributes on question inputs', () => {
const questions = await form.getQuestions()
await questions[0].fillTitle('My question')
await questions[0].fillDescription('Some context')
await expect(questions[0].descriptionInput).toHaveAccessibleName(
'Description of question number 1',
)

await topBar.toggleView(FormsView.View)

Expand Down Expand Up @@ -148,6 +151,9 @@ test.describe('Accessibility: aria attributes on question inputs', () => {
page.getByRole('heading', { name: 'My dropdown question' }),
).toHaveId('q1_title')
await expect(page.locator('#q1_desc')).toContainText('Choose an option')
await expect(question.getByRole('combobox')).toHaveAccessibleName(
'My dropdown question',
)
})

test('Date question with description has aria-labelledby and aria-describedby', async ({
Expand Down Expand Up @@ -176,6 +182,9 @@ test.describe('Accessibility: aria attributes on question inputs', () => {
page.getByRole('heading', { name: 'My date question' }),
).toHaveId('q1_title')
await expect(page.locator('#q1_desc')).toContainText('Pick a date')
await expect(question.getByRole('textbox')).toHaveAccessibleName(
'My date question',
)
})

test('Linear scale question with description has aria-labelledby and aria-describedby', async ({
Expand Down Expand Up @@ -261,4 +270,27 @@ test.describe('Accessibility: aria attributes on question inputs', () => {
).toHaveId('q1_title')
await expect(page.locator('#q1_desc')).toContainText('Pick a color')
})

test('Grid cells are named by row and column', async ({
appNavigation,
form,
topBar,
page,
}) => {
await appNavigation.clickNewForm()
await form.fillTitle('Test form')

await form.addQuestion(QuestionType.Grid, GridSubtype.RadioButtons)
const questions = await form.getQuestions()
await questions[0].fillTitle('Satisfaction')
await questions[0].addColumn('Good')
await questions[0].addRow('Service')

await topBar.toggleView(FormsView.View)

const question = page.getByRole('listitem', { name: /Question number 1/ })
await expect(
question.getByRole('radio', { name: 'Service, Good' }),
).toBeAttached()
})
})
1 change: 1 addition & 0 deletions playwright/support/sections/FormSection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class FormSection {
})
this.descriptionField = this.mainContent.getByRole('textbox', {
name: 'Description',
exact: true,
})
}

Expand Down
1 change: 1 addition & 0 deletions src/FormsSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
multiple
:options="availableGroups"
:placeholder="t('forms', 'Select groups')"
:aria-label-combobox="t('forms', 'Select groups')"
class="forms-settings__creation__multiselect"
label="displayName"
@update:modelValue="onCreationAllowedGroupsChange" />
Expand Down
1 change: 0 additions & 1 deletion src/components/OptionInputDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<NcTextArea
v-model="enteredOptions"
:label="t('forms', 'Add multiple options (one per line)')"
:placeholder="t('forms', 'Add multiple options (one per line)')"
resize="vertical"
rows="10" />
</div>
Expand Down
5 changes: 5 additions & 0 deletions src/components/Questions/Question.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@
ref="descriptionField"
dir="auto"
:value="description"
:aria-label="
t('forms', 'Description of question number {index}', {
index,
})
"
:placeholder="
t(
'forms',
Expand Down
1 change: 1 addition & 0 deletions src/components/Questions/QuestionDate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
:disabled="!readOnly"
:format="stringify"
:placeholder="datetimePickerPlaceholder"
:aria-label="text"
:showSecond="false"
:type="dateTimePickerType"
:disabledDate="disabledDates"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Questions/QuestionDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
:options="choices"
:searchable="false"
label="text"
:aria-label-combobox="selectOptionPlaceholder"
:aria-label-combobox="text"
:aria-errormessage="hasError ? errorId : undefined"
:aria-invalid="hasError ? 'true' : undefined"
@invalid.prevent="validate"
Expand Down
2 changes: 2 additions & 0 deletions src/components/Questions/QuestionFile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
type="multiselect"
:modelValue="maxFileSizeUnit"
:options="availableUnits"
:aria-label-combobox="t('forms', 'File size unit')"
required
:clearable="false"
:searchable="false"
Expand Down Expand Up @@ -68,6 +69,7 @@
<NcActionInput
key="allowed-file-extensions-multiselect"
:label="t('forms', 'Custom file extensions')"
:aria-label-combobox="t('forms', 'Custom file extensions')"
type="multiselect"
multiple
taggable
Expand Down
4 changes: 4 additions & 0 deletions src/components/Questions/QuestionGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
:modelValue="values[row.id]"
:value="column.id.toString()"
:name="`${row.id}-answer`"
:aria-label="`${row.text}, ${column.text}`"
type="radio"
@update:modelValue="
onChangeCheckboxRadio(row.id, $event)
Expand All @@ -61,6 +62,7 @@
:modelValue="values[row.id] || []"
:value="column.id.toString()"
:name="`${row.id}-answer`"
:aria-label="`${row.text}, ${column.text}`"
type="checkbox"
@update:modelValue="
onChangeCheckboxRadio(row.id, $event)
Expand All @@ -70,6 +72,8 @@
<template v-if="questionType === 'number'">
<NcInputField
type="number"
labelOutside
:aria-label="`${row.text}, ${column.text}`"
:modelValue="plainValues[row.id][column.id]"
@update:modelValue="
onChangeTextNumber(
Expand Down
6 changes: 4 additions & 2 deletions src/components/Questions/QuestionLinearScale.vue

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.

This hides parts of the labels in the browser

Image

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
type="multiselect"
:clearable="false"
:label="t('forms', 'Lowest value')"
:aria-label-combobox="t('forms', 'Lowest value')"
labelOutside
:options="[0, 1]"
required
Expand All @@ -29,6 +30,7 @@
type="multiselect"
:clearable="false"
:label="t('forms', 'Highest value')"
:aria-label-combobox="t('forms', 'Highest value')"
labelOutside
:options="[2, 3, 4, 5, 6, 7, 8, 9, 10]"
required
Expand Down Expand Up @@ -99,8 +101,8 @@
ref="highest"
:modelValue="optionsLabelHighest"
class="question-linear-scale__label-input"
:label="t('forms', 'Label (optional)')"
:aria-label="t('forms', 'Label for highest value')"
:label="t('forms', 'Label for highest value')"
:placeholder="t('forms', 'Label (optional)')"
resize="none"
@input="resizeLabel('highest')"
@blur="onBlur('highest')"
Expand Down
1 change: 1 addition & 0 deletions src/components/Questions/QuestionMultiple.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
class="question__item__pseudoInput" />
<input
:placeholder="t('forms', 'Other')"
:aria-label="t('forms', 'Other')"
class="question__input"
:disabled="!readOnly"
:maxlength="maxStringLengths.optionText"
Expand Down
1 change: 1 addition & 0 deletions src/components/SidebarTabs/SettingsSidebarTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<div v-show="formExpires && !formArchived" class="settings-div--indent">
<NcDateTimePicker
id="expiresDatetimePicker"
:aria-label="t('forms', 'Expiration date')"
:clearable="false"
:disabled="locked"
:disabledDate="notBeforeToday"
Expand Down
2 changes: 1 addition & 1 deletion src/components/SidebarTabs/SharingSearchDiv.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
:loading="showLoadingCircle"
:disabled="locked || !isCurrentUserOwner"
:options="options"
:placeholder="t('forms', 'Search for user, group or team …')"
:inputLabel="t('forms', 'Search for user, group or team …')"
:aria-label-listbox="t('forms', 'Search for user, group or team …')"
@search="asyncSearch"
@update:modelValue="addShare">
Expand Down
2 changes: 1 addition & 1 deletion src/components/SidebarTabs/TransferOwnership.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
class="modal-content__select"
:loading="loading"
:options="options"
:placeholder="t('forms', 'Search for a user')"
:inputLabel="t('forms', 'Search for a user')"
@search="
(query) => asyncSearch(query, [SHARE_TYPES.SHARE_TYPE_USER])
">
Expand Down
Loading