diff --git a/package.json b/package.json
index 87f2a314..11d17a49 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"@babel/runtime": "^7.6.2",
"@sheerun/mutationobserver-shim": "^0.3.2",
"@types/testing-library__dom": "^6.0.0",
- "aria-query": "3.0.0",
+ "aria-query": "https://pkg.csb.dev/eps1lon/aria-query/commit/7dc0809b/aria-query",
"pretty-format": "^24.9.0",
"wait-for-expect": "^3.0.0"
},
diff --git a/src/__tests__/__snapshots__/role-helpers.js.snap b/src/__tests__/__snapshots__/role-helpers.js.snap
index ef5746b2..85a85770 100644
--- a/src/__tests__/__snapshots__/role-helpers.js.snap
+++ b/src/__tests__/__snapshots__/role-helpers.js.snap
@@ -169,5 +169,36 @@ textbox:
data-testid="a-textarea"
/>
+--------------------------------------------------
+combobox:
+
+
+
+
+
+--------------------------------------------------
+listbox:
+
+
+
+
+
+
+
--------------------------------------------------"
`;
diff --git a/src/__tests__/element-queries.js b/src/__tests__/element-queries.js
index 8a8bc35f..c568e75a 100644
--- a/src/__tests__/element-queries.js
+++ b/src/__tests__/element-queries.js
@@ -426,12 +426,12 @@ test('queryAllByRole returns semantic html elements', () => {
expect(queryAllByRole(/heading/i)).toHaveLength(6)
expect(queryAllByRole('list')).toHaveLength(2)
expect(queryAllByRole(/listitem/i)).toHaveLength(3)
- expect(queryAllByRole(/textbox/i)).toHaveLength(2)
+ expect(queryAllByRole(/textbox/i)).toHaveLength(1)
expect(queryAllByRole(/checkbox/i)).toHaveLength(1)
expect(queryAllByRole(/radio/i)).toHaveLength(1)
expect(queryAllByRole('row')).toHaveLength(3)
expect(queryAllByRole(/rowgroup/i)).toHaveLength(2)
- expect(queryAllByRole(/(table)|(textbox)/i)).toHaveLength(3)
+ expect(queryAllByRole(/(table)|(textbox)/i)).toHaveLength(2)
expect(queryAllByRole(/img/i)).toHaveLength(1)
})
diff --git a/src/__tests__/role-helpers.js b/src/__tests__/role-helpers.js
index 9563b66c..248d1231 100644
--- a/src/__tests__/role-helpers.js
+++ b/src/__tests__/role-helpers.js
@@ -55,7 +55,14 @@ function setup() {
+
+
+
+
+
+
+
@@ -93,7 +100,13 @@ function setup() {
radio2: getByTestId('a-radio-2'),
input: getByTestId('a-input-1'),
input2: getByTestId('a-input-2'),
+ input3: getByTestId('a-input-3'),
textarea: getByTestId('a-textarea'),
+ combobox1: getByTestId('a-combobox-1'),
+ combobox2: getByTestId('a-combobox-2'),
+ listbox1: getByTestId('a-listbox-1'),
+ listbox2: getByTestId('a-listbox-2'),
+ listbox3: getByTestId('a-listbox-3'),
}
}
@@ -126,6 +139,11 @@ test('getRoles returns expected roles for various dom nodes', () => {
input,
input2,
textarea,
+ combobox1,
+ combobox2,
+ listbox1,
+ listbox2,
+ listbox3,
} = setup()
expect(getRoles(section)).toEqual({
@@ -145,6 +163,8 @@ test('getRoles returns expected roles for various dom nodes', () => {
rowgroup: [tbody],
command: [menuItem, menuItem2],
menuitem: [menuItem, menuItem2],
+ combobox: [combobox1, combobox2],
+ listbox: [listbox1, listbox2, listbox3],
})
})
diff --git a/src/role-helpers.js b/src/role-helpers.js
index 6218461d..fadf6e73 100644
--- a/src/role-helpers.js
+++ b/src/role-helpers.js
@@ -69,16 +69,54 @@ function getImplicitAriaRoles(currentNode) {
}
}
+ //
with an accessible name?
+ if (currentNode.matches('form')) {
+ return ['form']
+ }
+
+ // with an accessible name?
+ if (currentNode.matches('section')) {
+ return ['region']
+ }
+
return []
}
function buildElementRoleList(elementRolesMap) {
function makeElementSelector({name, attributes = []}) {
- return `${name}${attributes
- .map(({name: attributeName, value}) =>
- value ? `[${attributeName}=${value}]` : `[${attributeName}]`,
- )
- .join('')}`
+ const inclusiveAttributeSelectors = []
+ const exclusiveAttributeSelectors = []
+ attributes.forEach(({name: attributeName, constraints = [], value}) => {
+ const selector = value
+ ? `[${attributeName}="${value}"]`
+ : `[${attributeName}]`
+
+ const shouldBeUndefined = constraints.indexOf('undefined') !== -1
+ const shouldBeGreaterOne = constraints.indexOf('>1') !== -1
+ const shouldHaveAnyValue = constraints.indexOf('set') !== -1
+
+ if (shouldHaveAnyValue) {
+ inclusiveAttributeSelectors.push(selector)
+ exclusiveAttributeSelectors.push(`[${attributeName}=""]`)
+ } else if (shouldBeGreaterOne) {
+ exclusiveAttributeSelectors.push(`[${attributeName}^="-"]`)
+ exclusiveAttributeSelectors.push(`[${attributeName}="0"]`)
+ exclusiveAttributeSelectors.push(`[${attributeName}="1"]`)
+ } else if (shouldBeUndefined) {
+ exclusiveAttributeSelectors.push(selector)
+ } else {
+ inclusiveAttributeSelectors.push(selector)
+ }
+ })
+
+ const inclusiveAttributeSelector = inclusiveAttributeSelectors.join('')
+ const exclusiveAttributeSelector = exclusiveAttributeSelectors.join('')
+
+ return `${name}${inclusiveAttributeSelector}${
+ exclusiveAttributeSelector === ''
+ ? ''
+ : `:not(${exclusiveAttributeSelector})`
+ }`
}
function getSelectorSpecificity({attributes = []}) {