Skip to content

Commit 0192867

Browse files
authored
Merge pull request #160 from PublicisSapient/120-tech-unit-testing-for-autocomplete-combobox
unit test cases for combobox
2 parents fdde543 + da0d664 commit 0192867

File tree

1 file changed

+293
-0
lines changed

1 file changed

+293
-0
lines changed

js/test/combobox.test.js

+293
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
'use strict';
2+
import config from './test-config.js';
3+
import testHelpers from './test-helpers.js';
4+
5+
//Utility function to get current value
6+
const getActiveElementValue = async () => {
7+
return page.evaluate(() => document?.activeElement?.value);
8+
};
9+
//Utility function is added to test autosuggestion functionality of all comboboxes
10+
const testAutosuggestions = async (
11+
listSelector,
12+
typeText,
13+
expectedSubstring,
14+
expectedCount,
15+
) => {
16+
await page.waitForSelector(`${listSelector}`);
17+
// Getting all the visible option elements
18+
const suggestions = await page.evaluate((selector) => {
19+
const parent = document.querySelector(selector);
20+
const items = Array.from(parent.querySelectorAll('[role="option"]'));
21+
return items
22+
.filter((item) => !item.hasAttribute('hidden'))
23+
.map((item) => item.textContent?.toLowerCase()?.trim());
24+
}, `${listSelector}`);
25+
26+
const allContainSubstring = suggestions.every((suggestion) =>
27+
suggestion.includes(expectedSubstring),
28+
);
29+
// Assertions to test the autosuggestion options
30+
expect(allContainSubstring).toBeTruthy();
31+
expect(suggestions.length).toBe(expectedCount);
32+
console.log(
33+
`Suggestions after typing '${typeText}': ${suggestions.join(', ')}`,
34+
);
35+
};
36+
37+
describe("All combobox's Attributes Test", () => {
38+
let domInfo;
39+
beforeAll(async () => {
40+
await page.goto(`${config.BASE_URL}/combobox.php`);
41+
});
42+
43+
it('ARIA attributes are set', async () => {
44+
domInfo = await page.evaluate(() => {
45+
const comboEls = document.querySelectorAll(
46+
'input[role="combobox"]',
47+
);
48+
return {
49+
comboBoxList: Array.from(comboEls)?.map((el) => {
50+
const ariaDescribedBy = el.getAttribute('aria-describedby');
51+
const ariaOwns = el.getAttribute('aria-owns');
52+
const domElementForAriaDescribedby =
53+
document.getElementById(ariaDescribedBy);
54+
const domElementForAriaOwns =
55+
document.getElementById(ariaOwns);
56+
const roleForAriaOwns =
57+
domElementForAriaOwns.getAttribute('role');
58+
return {
59+
ariaDescribedBy,
60+
ariaOwns,
61+
ariaExpanded: el.getAttribute('aria-expanded'),
62+
ariaAutocomplete: el.getAttribute('aria-autocomplete'),
63+
domElementForAriaDescribedby,
64+
domElementForAriaOwns,
65+
roleForAriaOwns,
66+
};
67+
}),
68+
};
69+
});
70+
// Test all aria attributes of the combobox
71+
domInfo.comboBoxList.forEach((combobox) => {
72+
expect(combobox.ariaDescribedBy).not.toBeNull();
73+
expect(combobox.ariaOwns).not.toBeNull();
74+
expect(combobox.ariaExpanded).toBe('false');
75+
expect(combobox.ariaAutocomplete).toBe('list');
76+
expect(combobox.domElementForAriaDescribedby).not.toBeNull();
77+
// Verify the aria-own dom element
78+
expect(combobox.domElementForAriaOwns).not.toBeNull();
79+
expect(combobox.roleForAriaOwns).toBe('listbox');
80+
});
81+
});
82+
afterAll(async () => {});
83+
});
84+
85+
describe('ARIA Combobox Test for Accessible features', () => {
86+
let domInfo;
87+
beforeAll(async () => {
88+
await page.goto(`${config.BASE_URL}/combobox.php`);
89+
await page.waitForSelector('#aria-fruit');
90+
await page.focus('#aria-fruit');
91+
await page.type('#aria-fruit', 'ap', { delay: 100 });
92+
await testHelpers.pauseFor(100);
93+
});
94+
it('ARIA Combobox is able to suggest the correct autosuggestion', async () => {
95+
await testAutosuggestions('#aria-fruit__list', 'ap', 'ap', 3);
96+
});
97+
98+
it('ARIA Combobox is able to update the autosuggestion on typing', async () => {
99+
// Updating the typing string from "ap -> app"
100+
await page.type('#aria-fruit', 'p', { delay: 100 });
101+
await testHelpers.pauseFor(100);
102+
103+
await testAutosuggestions('#aria-fruit__list', 'app', 'app', 2);
104+
});
105+
it('ARIA Combobox is able to alert the matching count updates using aria-live', async () => {
106+
// Getting the alert element
107+
const ariaInfoOfCount = await page.evaluate(() => {
108+
const alertElem = document.querySelector(
109+
'#example1 [role="alert"]',
110+
);
111+
const ariaLive = alertElem.getAttribute('aria-live');
112+
return {
113+
alertElemValue: alertElem?.textContent,
114+
ariaLive,
115+
};
116+
});
117+
// Testing the aria-live attribute
118+
expect(ariaInfoOfCount.alertElemValue).toContain('2 items');
119+
expect(ariaInfoOfCount.ariaLive).toBe('assertive');
120+
});
121+
122+
it('ARIA Combobox select value using keyboard', async () => {
123+
// Using keyboard to go through the List
124+
testHelpers.keyDownAndUp(page, 'ArrowDown');
125+
// Enter
126+
await page.keyboard.press('Enter');
127+
// Pause for 100 ms
128+
await testHelpers.pauseFor(100);
129+
domInfo = await page.evaluate(() => {
130+
const focusedElementType = document?.activeElement?.type;
131+
const inputElement = document.getElementById('aria-fruit');
132+
const ariaExpanded = inputElement.getAttribute('aria-expanded');
133+
const selectedValue = inputElement.value;
134+
135+
return {
136+
ariaExpanded,
137+
selectedValue,
138+
focusedElementType,
139+
};
140+
});
141+
expect(domInfo.ariaExpanded).toBe('false');
142+
expect(domInfo.selectedValue).toBe('Apple');
143+
expect(domInfo.focusedElementType).toBe('reset');
144+
});
145+
146+
it('ARIA Combobox is able to reset using the reset button', async () => {
147+
// Focus will be on the Reset button
148+
await page.keyboard.press('Enter');
149+
await testHelpers.pauseFor(100);
150+
const valueAfterReset = await getActiveElementValue();
151+
expect(valueAfterReset).toBe('');
152+
});
153+
it('ARIA Combobox is able to reset using the escape key', async () => {
154+
await page.type('#aria-fruit', 'app', { delay: 100 });
155+
// Now let's press ESCAPE to check if the value is reset.
156+
page.keyboard.press('Escape');
157+
// await 100ms before continuing further
158+
await testHelpers.fastPause();
159+
const valueAfterEscapeButton = await getActiveElementValue();
160+
expect(valueAfterEscapeButton).toBe('');
161+
});
162+
afterAll(async () => {});
163+
});
164+
describe('AutoSubmit Combobox Test', () => {
165+
beforeAll(async () => {
166+
await page.goto(`${config.BASE_URL}/combobox.php`);
167+
await page.waitForSelector('#video-games');
168+
await page.focus('#video-games');
169+
await page.type('#video-games', 'ap', { delay: 100 });
170+
});
171+
it('ARIA Combobox is able to suggest the correct autosuggestion', async () => {
172+
await testAutosuggestions('#video-games__list', 'ap', 'ap', 3);
173+
});
174+
175+
it('ARIA Combobox is able to update the autosuggestion on typing', async () => {
176+
// Updating the typing string from "ap -> app"
177+
await page.type('#video-games', 'p', { delay: 100 });
178+
await testHelpers.pauseFor(100);
179+
180+
await testAutosuggestions('#video-games__list', 'app', 'app', 2);
181+
});
182+
it('ARIA Combobox is able to alert the matching count updates', async () => {
183+
const ariaInfoOfCount = await page.evaluate(() => {
184+
const alertElem = document.querySelector(
185+
'#submit-on-select-example [role="alert"]',
186+
);
187+
const ariaLive = alertElem.getAttribute('aria-live');
188+
return {
189+
alertElemValue: alertElem?.textContent,
190+
ariaLive,
191+
};
192+
});
193+
expect(ariaInfoOfCount.alertElemValue).toContain('2 items');
194+
expect(ariaInfoOfCount.ariaLive).toBe('polite');
195+
});
196+
it('ARIA Combobox is able to reset using the reset button', async () => {
197+
page.keyboard.press('Tab');
198+
// We pause to ensure any action due to the keypress has started
199+
await testHelpers.fastPause();
200+
// Focus will be on the Reset button
201+
await page.keyboard.press('Enter');
202+
await testHelpers.pauseFor(100);
203+
const valueAfterReset = await getActiveElementValue();
204+
expect(valueAfterReset).toBe('');
205+
});
206+
it('ARIA Combobox is able to reset using the escape key', async () => {
207+
await page.type('#video-games', 'app', { delay: 100 });
208+
// Now let's press ESCAPE to check if the value is reset.
209+
page.keyboard.press('Escape');
210+
// await 100ms before continuing further
211+
await testHelpers.fastPause();
212+
const valueAfterEscapeButton = await getActiveElementValue();
213+
expect(valueAfterEscapeButton).toBe('');
214+
});
215+
216+
it('AutoSubmit using the aria combobox is completely keyboard accessible', async () => {
217+
await page.type('#video-games', 'a', { delay: 100 });
218+
testHelpers.keyDownAndUp(page, 'ArrowDown');
219+
await page.keyboard.press('Enter');
220+
// Testing Redirection on submission
221+
await page.waitForNavigation();
222+
const currentUrl = await page.url();
223+
expect(currentUrl.includes('google.com')).toBe(true);
224+
});
225+
afterAll(async () => {});
226+
});
227+
describe('ARIA Combobox with categories Test', () => {
228+
beforeAll(async () => {
229+
await page.goto(`${config.BASE_URL}/combobox.php`);
230+
await page.waitForSelector('#aria-example-2');
231+
await page.focus('#aria-example-2');
232+
});
233+
it('ARIA Combobox is able to suggest the correct autosuggestion', async () => {
234+
await page.type('#aria-example-2', 'ch', { delay: 100 });
235+
await testAutosuggestions('#aria-example-2__list', 'ch', 'ch', 6);
236+
});
237+
it('ARIA Combobox is able to update the autosuggestion on typing', async () => {
238+
// Updating the typing string from "ch -> chi"
239+
await page.type('#aria-example-2', 'i', { delay: 100 });
240+
await testHelpers.pauseFor(100);
241+
242+
await testAutosuggestions('#aria-example-2__list', 'chi', 'chi', 3);
243+
});
244+
it('ARIA Combobox is able to alert the matching count updates', async () => {
245+
const ariaInfoOfCount = await page.evaluate(() => {
246+
const alertElem = document.querySelector(
247+
'#example2 [role="alert"]',
248+
);
249+
const ariaLive = alertElem.getAttribute('aria-live');
250+
return {
251+
alertElemValue: alertElem?.textContent,
252+
ariaLive,
253+
};
254+
});
255+
expect(ariaInfoOfCount.alertElemValue).toContain('3 items');
256+
expect(ariaInfoOfCount.ariaLive).toBe('polite');
257+
});
258+
it('ARIA Combobox is able to reset using the escape key', async () => {
259+
// Now let's press ESCAPE to check if the value is reset.
260+
page.keyboard.press('Escape');
261+
// await 100ms before continuing further
262+
await testHelpers.fastPause();
263+
const valueAfterEscapeButton = await getActiveElementValue();
264+
265+
expect(valueAfterEscapeButton).toBe('');
266+
});
267+
it('Selection in different categories using the aria combobox is completely keyboard accessible', async () => {
268+
await page.focus('#aria-example-2');
269+
await page.type('#aria-example-2', 'can', { delay: 100 });
270+
testHelpers.keyDownAndUp(page, 'ArrowDown');
271+
await page.keyboard.press('Enter');
272+
await testHelpers.pauseFor(100);
273+
//Testing the category and value selection
274+
const selected = await page.$eval(
275+
'.enable-combobox__category-alert',
276+
(el) => {
277+
const arr = el.value.split(',').map((item) => item.trim());
278+
return { value: arr[0], category: arr[1] }; // containing value and category
279+
},
280+
);
281+
expect(selected.value).toBe('Canada');
282+
expect(selected.category).toBe('Other States group');
283+
});
284+
it('ARIA Combobox is able to reset using the reset button', async () => {
285+
// Focus will be on the Reset button
286+
await page.keyboard.press('Enter');
287+
await testHelpers.pauseFor(100);
288+
const valueAfterReset = await getActiveElementValue();
289+
expect(valueAfterReset).toBe('');
290+
});
291+
292+
afterAll(async () => {});
293+
});

0 commit comments

Comments
 (0)