@@ -34,6 +34,66 @@ configs({ directions: ['ltr'] }).forEach(({ title, config, screenshot }) => {
3434 const alert = page . locator ( 'ion-alert' ) ;
3535 await expect ( alert ) . toHaveScreenshot ( screenshot ( `select-basic-alert-scroll-to-selected` ) ) ;
3636 } ) ;
37+
38+ test ( 'it should not focus any option when opened with no value' , async ( { page } ) => {
39+ // ion-app is required to apply the focused styles
40+ await page . setContent (
41+ `
42+ <ion-app>
43+ <ion-select label="Fruit" interface="alert">
44+ <ion-select-option value="apples">Apples</ion-select-option>
45+ <ion-select-option value="bananas">Bananas</ion-select-option>
46+ <ion-select-option value="oranges">Oranges</ion-select-option>
47+ </ion-select>
48+ </ion-app>
49+ ` ,
50+ config
51+ ) ;
52+
53+ const select = page . locator ( 'ion-select' ) ;
54+ const ionAlertDidPresent = await page . spyOnEvent ( 'ionAlertDidPresent' ) ;
55+
56+ await select . click ( ) ;
57+ await ionAlertDidPresent . next ( ) ;
58+
59+ await page . waitForChanges ( ) ;
60+
61+ const alert = page . locator ( 'ion-alert' ) ;
62+
63+ // Verify that no option has the ion-focused class
64+ const focusedOptions = alert . locator ( '.alert-radio-button.ion-focused' ) ;
65+ await expect ( focusedOptions ) . toHaveCount ( 0 ) ;
66+ } ) ;
67+
68+ test ( 'it should not focus any option when opened with a value' , async ( { page } ) => {
69+ // ion-app is required to apply the focused styles
70+ await page . setContent (
71+ `
72+ <ion-app>
73+ <ion-select label="Fruit" interface="alert" value="bananas">
74+ <ion-select-option value="apples">Apples</ion-select-option>
75+ <ion-select-option value="bananas">Bananas</ion-select-option>
76+ <ion-select-option value="oranges">Oranges</ion-select-option>
77+ </ion-select>
78+ </ion-app>
79+ ` ,
80+ config
81+ ) ;
82+
83+ const select = page . locator ( 'ion-select' ) ;
84+ const ionAlertDidPresent = await page . spyOnEvent ( 'ionAlertDidPresent' ) ;
85+
86+ await select . click ( ) ;
87+ await ionAlertDidPresent . next ( ) ;
88+
89+ await page . waitForChanges ( ) ;
90+
91+ const alert = page . locator ( 'ion-alert' ) ;
92+
93+ // Alert interface doesn't apply ion-focused class to selected options
94+ const focusedOptions = alert . locator ( '.alert-radio-button.ion-focused' ) ;
95+ await expect ( focusedOptions ) . toHaveCount ( 0 ) ;
96+ } ) ;
3797 } ) ;
3898
3999 test . describe ( 'select: action sheet' , ( ) => {
@@ -56,6 +116,107 @@ configs({ directions: ['ltr'] }).forEach(({ title, config, screenshot }) => {
56116 const actionSheet = page . locator ( 'ion-action-sheet' ) ;
57117 await expect ( actionSheet ) . toHaveScreenshot ( screenshot ( `select-basic-action-sheet-scroll-to-selected` ) ) ;
58118 } ) ;
119+
120+ test ( 'it should not focus any option when opened with no value' , async ( { page } ) => {
121+ // ion-app is required to apply the focused styles
122+ await page . setContent (
123+ `
124+ <ion-app>
125+ <ion-select label="Fruit" interface="action-sheet">
126+ <ion-select-option value="apples">Apples</ion-select-option>
127+ <ion-select-option value="bananas">Bananas</ion-select-option>
128+ <ion-select-option value="oranges">Oranges</ion-select-option>
129+ </ion-select>
130+ </ion-app>
131+ ` ,
132+ config
133+ ) ;
134+
135+ const select = page . locator ( 'ion-select' ) ;
136+ const ionActionSheetDidPresent = await page . spyOnEvent ( 'ionActionSheetDidPresent' ) ;
137+
138+ await select . click ( ) ;
139+ await ionActionSheetDidPresent . next ( ) ;
140+
141+ await page . waitForChanges ( ) ;
142+
143+ const actionSheet = page . locator ( 'ion-action-sheet' ) ;
144+
145+ // Verify that none of the options have the ion-focused class
146+ const focusedOptions = actionSheet . locator ( '.action-sheet-button.ion-focused' ) ;
147+ await expect ( focusedOptions ) . toHaveCount ( 0 ) ;
148+ } ) ;
149+
150+ test ( 'it should focus the second option when opened with a value' , async ( { page } ) => {
151+ // ion-app is required to apply the focused styles
152+ await page . setContent (
153+ `
154+ <ion-app>
155+ <ion-select label="Fruit" interface="action-sheet" value="bananas">
156+ <ion-select-option value="apples">Apples</ion-select-option>
157+ <ion-select-option value="bananas">Bananas</ion-select-option>
158+ <ion-select-option value="oranges">Oranges</ion-select-option>
159+ </ion-select>
160+ </ion-app>
161+ ` ,
162+ config
163+ ) ;
164+
165+ const select = page . locator ( 'ion-select' ) ;
166+ const ionActionSheetDidPresent = await page . spyOnEvent ( 'ionActionSheetDidPresent' ) ;
167+
168+ await select . click ( ) ;
169+ await ionActionSheetDidPresent . next ( ) ;
170+
171+ await page . waitForChanges ( ) ;
172+
173+ const actionSheet = page . locator ( 'ion-action-sheet' ) ;
174+
175+ // Find the button containing "Bananas" and verify it has the ion-focused class
176+ const bananasOption = actionSheet . locator ( '.action-sheet-button:has-text("Bananas")' ) ;
177+ await expect ( bananasOption ) . toHaveClass ( / i o n - f o c u s e d / ) ;
178+ } ) ;
179+
180+ test ( 'it should focus the second option when opened with a value and a header' , async ( { page } ) => {
181+ test . info ( ) . annotations . push ( {
182+ type : 'issue' ,
183+ description : 'https://github.com/ionic-team/ionic-framework/issues/30480' ,
184+ } ) ;
185+
186+ // ion-app is required to apply the focused styles
187+ await page . setContent (
188+ `
189+ <ion-app>
190+ <ion-select label="Fruit" interface="action-sheet" value="bananas">
191+ <ion-select-option value="apples">Apples</ion-select-option>
192+ <ion-select-option value="bananas">Bananas</ion-select-option>
193+ <ion-select-option value="oranges">Oranges</ion-select-option>
194+ </ion-select>
195+ </ion-app>
196+ ` ,
197+ config
198+ ) ;
199+
200+ const select = page . locator ( 'ion-select' ) ;
201+ await select . evaluate ( ( el : HTMLIonSelectElement ) => {
202+ el . interfaceOptions = {
203+ header : 'Header' ,
204+ } ;
205+ } ) ;
206+
207+ const ionActionSheetDidPresent = await page . spyOnEvent ( 'ionActionSheetDidPresent' ) ;
208+
209+ await select . click ( ) ;
210+ await ionActionSheetDidPresent . next ( ) ;
211+
212+ await page . waitForChanges ( ) ;
213+
214+ const actionSheet = page . locator ( 'ion-action-sheet' ) ;
215+
216+ // Find the option containing "Bananas" and verify it has the ion-focused class
217+ const bananasOption = actionSheet . locator ( '.action-sheet-button:has-text("Bananas")' ) ;
218+ await expect ( bananasOption ) . toHaveClass ( / i o n - f o c u s e d / ) ;
219+ } ) ;
59220 } ) ;
60221
61222 test . describe ( 'select: popover' , ( ) => {
@@ -78,6 +239,39 @@ configs({ directions: ['ltr'] }).forEach(({ title, config, screenshot }) => {
78239 await expect ( popover ) . toBeVisible ( ) ;
79240 } ) ;
80241
242+ test ( 'it should focus the second option when opened with a value' , async ( { page, skip } ) => {
243+ // TODO (ROU-5437)
244+ skip . browser ( 'webkit' , 'Safari 16 only allows text fields and pop-up menus to be focused.' ) ;
245+
246+ // ion-app is required to apply the focused styles
247+ await page . setContent (
248+ `
249+ <ion-app>
250+ <ion-select label="Fruit" interface="popover" value="bananas">
251+ <ion-select-option value="apples">Apples</ion-select-option>
252+ <ion-select-option value="bananas">Bananas</ion-select-option>
253+ <ion-select-option value="oranges">Oranges</ion-select-option>
254+ </ion-select>
255+ </ion-app>
256+ ` ,
257+ config
258+ ) ;
259+
260+ const select = page . locator ( 'ion-select' ) ;
261+ const ionPopoverDidPresent = await page . spyOnEvent ( 'ionPopoverDidPresent' ) ;
262+
263+ await select . click ( ) ;
264+ await ionPopoverDidPresent . next ( ) ;
265+
266+ await page . waitForChanges ( ) ;
267+
268+ const popover = page . locator ( 'ion-popover' ) ;
269+
270+ // Find the option containing "Bananas" and verify it has the ion-focused class
271+ const bananasOption = popover . locator ( '.select-interface-option:has-text("Bananas")' ) ;
272+ await expect ( bananasOption ) . toHaveClass ( / i o n - f o c u s e d / ) ;
273+ } ) ;
274+
81275 test ( 'it should scroll to selected option when opened' , async ( { page } ) => {
82276 const ionPopoverDidPresent = await page . spyOnEvent ( 'ionPopoverDidPresent' ) ;
83277
@@ -106,6 +300,36 @@ configs({ directions: ['ltr'] }).forEach(({ title, config, screenshot }) => {
106300 await expect ( modal ) . toBeVisible ( ) ;
107301 } ) ;
108302
303+ test ( 'it should focus the second option when opened with a value' , async ( { page } ) => {
304+ // ion-app is required to apply the focused styles
305+ await page . setContent (
306+ `
307+ <ion-app>
308+ <ion-select label="Fruit" interface="modal" value="bananas">
309+ <ion-select-option value="apples">Apples</ion-select-option>
310+ <ion-select-option value="bananas">Bananas</ion-select-option>
311+ <ion-select-option value="oranges">Oranges</ion-select-option>
312+ </ion-select>
313+ </ion-app>
314+ ` ,
315+ config
316+ ) ;
317+
318+ const select = page . locator ( 'ion-select' ) ;
319+ const ionModalDidPresent = await page . spyOnEvent ( 'ionModalDidPresent' ) ;
320+
321+ await select . click ( ) ;
322+ await ionModalDidPresent . next ( ) ;
323+
324+ await page . waitForChanges ( ) ;
325+
326+ const modal = page . locator ( 'ion-modal' ) ;
327+
328+ // Find the option containing "Bananas" and verify it has the ion-focused class
329+ const bananasOption = modal . locator ( '.select-interface-option:has-text("Bananas")' ) ;
330+ await expect ( bananasOption ) . toHaveClass ( / i o n - f o c u s e d / ) ;
331+ } ) ;
332+
109333 test ( 'it should scroll to selected option when opened' , async ( { page } ) => {
110334 const ionModalDidPresent = await page . spyOnEvent ( 'ionModalDidPresent' ) ;
111335
0 commit comments