Skip to content

Commit 13837ff

Browse files
committed
fix (picker): fixing pickers tests
1 parent 3b19548 commit 13837ff

File tree

4 files changed

+58
-78
lines changed

4 files changed

+58
-78
lines changed

core/src/components/picker/picker.tsx

Lines changed: 3 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -133,63 +133,12 @@ export class Picker implements ComponentInterface {
133133
* function that has been set in onPointerDown
134134
* so that we enter/exit input mode correctly.
135135
*/
136-
private onClick = (ev: PointerEvent) => {
136+
private onClick = () => {
137137
const { actionOnClick } = this;
138138
if (actionOnClick) {
139139
actionOnClick();
140140
this.actionOnClick = undefined;
141141
}
142-
143-
/**
144-
* In order to avoid a11y issues we must manage focus
145-
* on the picker columns and picker itself.
146-
* This is because once picker is clicked we got an issue/warning because
147-
* picker input is being focused, and once it has tabindex -1 it can't be focused,
148-
* which ends on focusing the picker itself.
149-
* During the process above we fall into issues since there is an element
150-
* with tabindex -1 and aria-hidden='true' that is focused, which is not allowed.
151-
* That said and since onClick is being propagated to the picker itself, we need to
152-
* manage focus on the picker columns and picker itself to avoid the issue.
153-
*/
154-
const clickedTarget = ev.target as HTMLElement;
155-
let elementToFocus: HTMLElement | null = null;
156-
157-
switch (clickedTarget.tagName) {
158-
case 'ION-PICKER':
159-
/**
160-
* If the user clicked the picker itself
161-
* then we should focus the first picker options
162-
* so that users can scroll through them.
163-
*/
164-
const ionPickerColumn = this.el.querySelector('ion-picker-column');
165-
elementToFocus = ionPickerColumn?.shadowRoot?.querySelector('.picker-opts') as HTMLElement | null;
166-
break;
167-
168-
case 'ION-PICKER-COLUMN':
169-
/**
170-
* If the user clicked a picker column
171-
* then we should focus its own picker options
172-
* so that users can scroll through them.
173-
*/
174-
elementToFocus = clickedTarget.shadowRoot?.querySelector('.picker-opts') as HTMLElement | null;
175-
break;
176-
177-
case 'ION-PICKER-COLUMN-OPTION':
178-
/**
179-
* If the user clicked a picker column option
180-
* then we should focus its picker options parent so that
181-
* users can scroll through them.
182-
*/
183-
const ionPickerColumnOption = clickedTarget.closest('ion-picker-column');
184-
if (ionPickerColumnOption) {
185-
elementToFocus = ionPickerColumnOption.shadowRoot?.querySelector('.picker-opts') as HTMLElement | null;
186-
}
187-
break;
188-
}
189-
190-
if (elementToFocus) {
191-
elementToFocus.focus();
192-
}
193142
};
194143

195144
/**
@@ -461,7 +410,7 @@ export class Picker implements ComponentInterface {
461410
colEl: HTMLIonPickerColumnElement,
462411
value: string,
463412
zeroBehavior: 'start' | 'end' = 'start'
464-
): boolean => {
413+
): boolean => {
465414
if (!value) {
466415
return false;
467416
}
@@ -588,7 +537,7 @@ export class Picker implements ComponentInterface {
588537
return (
589538
<Host
590539
onPointerDown={(ev: PointerEvent) => this.onPointerDown(ev)}
591-
onClick={(ev: PointerEvent) => this.onClick(ev)}
540+
onClick={() => this.onClick()}
592541
>
593542
<input
594543
aria-hidden="true"

core/src/components/picker/test/basic/index.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ <h2>One Numeric Input</h2>
7070
<h2>Two Numeric Input</h2>
7171
<ion-picker>
7272
<ion-picker-column numeric-input="true" id="dual-numeric-first"></ion-picker-column>
73-
<ion-picker-column numeric-input="true" id="dual-numeric-second"></ion-picker-column>
73+
<ion-picker-column numeric-input="true" id="dual-numeric-second" ></ion-picker-column>
7474
</ion-picker>
7575
</div>
7676
<div class="grid-item">
@@ -177,6 +177,10 @@ <h2>Modal</h2>
177177
'onion'
178178
);
179179

180+
const columnDualNumericFirst = document.querySelector('ion-picker-column#dual-numeric-first');
181+
columnDualNumericFirst.addEventListener('ionChange', (ev) => {
182+
console.log('Column change', ev.detail);
183+
});
180184
setPickerColumn(
181185
'#dual-numeric-first',
182186
[
@@ -195,6 +199,10 @@ <h2>Modal</h2>
195199
],
196200
3
197201
);
202+
const columnDualNumericSecond = document.querySelector('ion-picker-column#dual-numeric-second');
203+
columnDualNumericSecond.addEventListener('ionChange', (ev) => {
204+
console.log('Column change', ev.detail);
205+
});
198206
setPickerColumn('#dual-numeric-second', minutes, 3);
199207

200208
setPickerColumn(

core/src/components/picker/test/basic/picker.e2e.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,32 +106,44 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
106106
});
107107

108108
test('tabbing should correctly move focus between columns', async ({ page }) => {
109-
const firstColumn = page.locator('ion-picker-column#first');
110-
const secondColumn = page.locator('ion-picker-column#second');
109+
const firstColumn = await page.evaluate(() => document.querySelector('ion-picker-column#first'));
110+
const secondColumn = await page.evaluate(() => document.querySelector('ion-picker-column#second'));
111+
111112

112113
// Focus first column
113114
await page.keyboard.press('Tab');
114-
await expect(firstColumn).toBeFocused();
115+
116+
let activeElement = await page.evaluate(() => document.activeElement);
117+
expect(activeElement).toEqual(firstColumn);
115118

116119
await page.waitForChanges();
117120

118121
// Focus second column
119122
await page.keyboard.press('Tab');
120-
await expect(secondColumn).toBeFocused();
123+
124+
activeElement = await page.evaluate(() => document.activeElement);
125+
expect(activeElement).toEqual(secondColumn);
121126
});
122127

123128
test('tabbing should correctly move focus back', async ({ page }) => {
124-
const firstColumn = page.locator('ion-picker-column#first');
125-
const secondColumn = page.locator('ion-picker-column#second');
129+
const firstColumn = await page.evaluate(() => document.querySelector('ion-picker-column#first'));
130+
const secondColumn = await page.evaluate(() => document.querySelector('ion-picker-column#second'));
126131

127-
await secondColumn.evaluate((el: HTMLIonPickerColumnElement) => el.setFocus());
128-
await expect(secondColumn).toBeFocused();
132+
await page.evaluate((selector) => {
133+
const el = document.querySelector(selector) as HTMLElement | null;
134+
el?.focus();
135+
}, 'ion-picker-column#second');
136+
137+
let activeElement = await page.evaluate(() => document.activeElement);
138+
expect(activeElement).toEqual(secondColumn);
129139

130140
await page.waitForChanges();
131141

132142
// Focus first column
133143
await page.keyboard.press('Shift+Tab');
134-
await expect(firstColumn).toBeFocused();
144+
145+
activeElement = await page.evaluate(() => document.activeElement);
146+
expect(activeElement).toEqual(firstColumn);
135147
});
136148
});
137149
});

core/src/components/picker/test/keyboard-entry/picker.e2e.ts

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,21 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
3535
</script>
3636
`,
3737
config
38-
);
39-
38+
);
39+
4040
const column = page.locator('ion-picker-column');
41+
42+
const colShadowRoot = await column.evaluateHandle((el) => el.shadowRoot);
43+
const columnPickerOpts = await colShadowRoot.evaluateHandle((root) => root?.querySelector('.picker-opts'));
44+
4145
const ionChange = await page.spyOnEvent('ionChange');
42-
await column.evaluate((el: HTMLIonPickerColumnElement) => el.setFocus());
43-
46+
await columnPickerOpts.evaluate((el) => el && (el as HTMLElement).focus());
47+
4448
await page.keyboard.press('Digit2');
45-
49+
4650
await expect(ionChange).toHaveReceivedEventDetail({ value: 2 });
4751
await expect(column).toHaveJSProperty('value', 2);
52+
4853
});
4954

5055
test('should scroll to and update the value prop for multiple columns', async ({ page }) => {
@@ -99,22 +104,24 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
99104
);
100105
const firstColumn = page.locator('ion-picker-column#first');
101106
const secondColumn = page.locator('ion-picker-column#second');
102-
const highlight = page.locator('ion-picker .picker-highlight');
103107
const firstIonChange = await (firstColumn as E2ELocator).spyOnEvent('ionChange');
104108
const secondIonChange = await (secondColumn as E2ELocator).spyOnEvent('ionChange');
105109

106-
const box = await highlight.boundingBox();
107-
if (box !== null) {
108-
await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
109-
}
110-
111-
await expect(firstColumn).toHaveClass(/picker-column-active/);
112-
await expect(secondColumn).toHaveClass(/picker-column-active/);
110+
const firstColShadowRoot = await firstColumn.evaluateHandle((el) => el.shadowRoot);
111+
const columnPickerOpts = await firstColShadowRoot.evaluateHandle((root) => root?.querySelector('.picker-opts'));
112+
113+
// Focus first column
114+
await columnPickerOpts.evaluate((el) => el && (el as HTMLElement).focus());
113115

114116
await page.keyboard.press('Digit2');
115117

116118
await expect(firstIonChange).toHaveReceivedEventDetail({ value: 2 });
117119
await expect(firstColumn).toHaveJSProperty('value', 2);
120+
121+
// Focus second column
122+
await page.keyboard.press('Tab');
123+
124+
await page.waitForChanges();
118125

119126
await page.keyboard.press('Digit2+Digit4');
120127

@@ -155,8 +162,12 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
155162
);
156163

157164
const column = page.locator('ion-picker-column');
165+
166+
const colShadowRoot = await column.evaluateHandle((el) => el.shadowRoot);
167+
const columnPickerOpts = await colShadowRoot.evaluateHandle((root) => root?.querySelector('.picker-opts'));
168+
158169
const ionChange = await page.spyOnEvent('ionChange');
159-
await column.evaluate((el: HTMLIonPickerColumnElement) => el.setFocus());
170+
await columnPickerOpts.evaluate((el) => el && (el as HTMLElement).focus());
160171

161172
await page.keyboard.press('Digit0');
162173

0 commit comments

Comments
 (0)