@@ -44,7 +44,7 @@ configs().forEach(({ title, screenshot, config }) => {
4444 } ) ;
4545} ) ;
4646
47- configs ( { modes : [ 'ios' ] , directions : [ 'ltr' ] } ) . forEach ( ( { title, config } ) => {
47+ configs ( { modes : [ 'ios' ] , directions : [ 'ltr' ] } ) . forEach ( ( { title, screenshot , config } ) => {
4848 test . describe ( title ( 'checkbox: ionChange' ) , ( ) => {
4949 test ( 'should fire ionChange when interacting with checkbox' , async ( { page } ) => {
5050 await page . setContent (
@@ -133,4 +133,177 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
133133 expect ( clickCount ) . toBe ( 1 ) ;
134134 } ) ;
135135 } ) ;
136+
137+ test . describe ( title ( 'checkbox: ionFocus' ) , ( ) => {
138+ test ( 'should fire ionFocus when checkbox is focused' , async ( { page, pageUtils } ) => {
139+ await page . setContent (
140+ `
141+ <ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
142+ ` ,
143+ config
144+ ) ;
145+
146+ const ionFocus = await page . spyOnEvent ( 'ionFocus' ) ;
147+
148+ // Test focus with keyboard navigation.
149+ await pageUtils . pressKeys ( 'Tab' ) ;
150+
151+ expect ( ionFocus ) . toHaveReceivedEventTimes ( 1 ) ;
152+
153+ // Reset focus.
154+ const checkbox = page . locator ( 'ion-checkbox' ) ;
155+ const checkboxBoundingBox = ( await checkbox . boundingBox ( ) ) ! ;
156+ await page . mouse . click ( 0 , checkboxBoundingBox . height + 1 ) ;
157+
158+ // Test focus with click.
159+ await checkbox . click ( ) ;
160+
161+ expect ( ionFocus ) . toHaveReceivedEventTimes ( 2 ) ;
162+ } ) ;
163+
164+ test ( 'should fire ionFocus when interacting with checkbox in item' , async ( { page, pageUtils } ) => {
165+ await page . setContent (
166+ `
167+ <ion-item>
168+ <ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
169+ </ion-item>
170+ ` ,
171+ config
172+ ) ;
173+
174+ const ionFocus = await page . spyOnEvent ( 'ionFocus' ) ;
175+
176+ // Test focus with keyboard navigation.
177+ await pageUtils . pressKeys ( 'Tab' ) ;
178+
179+ expect ( ionFocus ) . toHaveReceivedEventTimes ( 1 ) ;
180+
181+ // Verify that the event target is the checkbox and not the item.
182+ const eventByKeyboard = ionFocus . events [ 0 ] ;
183+ expect ( ( eventByKeyboard . target as HTMLElement ) . tagName . toLowerCase ( ) ) . toBe ( 'ion-checkbox' ) ;
184+
185+ // Reset focus.
186+ const checkbox = page . locator ( 'ion-checkbox' ) ;
187+ const checkboxBoundingBox = ( await checkbox . boundingBox ( ) ) ! ;
188+ await page . mouse . click ( 0 , checkboxBoundingBox . height + 1 ) ;
189+
190+ // Test focus with click.
191+ const item = page . locator ( 'ion-item' ) ;
192+ await item . click ( ) ;
193+
194+ expect ( ionFocus ) . toHaveReceivedEventTimes ( 2 ) ;
195+
196+ // Verify that the event target is the checkbox and not the item.
197+ const eventByClick = ionFocus . events [ 0 ] ;
198+ expect ( ( eventByClick . target as HTMLElement ) . tagName . toLowerCase ( ) ) . toBe ( 'ion-checkbox' ) ;
199+ } ) ;
200+
201+ test ( 'should not fire when programmatically setting a value' , async ( { page } ) => {
202+ await page . setContent (
203+ `
204+ <ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
205+ ` ,
206+ config
207+ ) ;
208+
209+ const ionFocus = await page . spyOnEvent ( 'ionFocus' ) ;
210+ const checkbox = page . locator ( 'ion-checkbox' ) ;
211+
212+ await checkbox . evaluate ( ( el : HTMLIonCheckboxElement ) => ( el . checked = true ) ) ;
213+ expect ( ionFocus ) . not . toHaveReceivedEvent ( ) ;
214+ } ) ;
215+
216+ test ( 'should not have visual regressions' , async ( { page, pageUtils } ) => {
217+ await page . setContent (
218+ `
219+ <style>
220+ #container {
221+ display: inline-block;
222+ padding: 10px;
223+ }
224+ </style>
225+
226+ <div id="container">
227+ <ion-checkbox>Unchecked</ion-checkbox>
228+ </div>
229+ ` ,
230+ config
231+ ) ;
232+
233+ await pageUtils . pressKeys ( 'Tab' ) ;
234+
235+ const container = page . locator ( '#container' ) ;
236+
237+ await expect ( container ) . toHaveScreenshot ( screenshot ( `checkbox-focus` ) ) ;
238+ } ) ;
239+ } ) ;
240+
241+ test . describe ( title ( 'checkbox: ionBlur' ) , ( ) => {
242+ test ( 'should fire ionBlur when checkbox is blurred' , async ( { page, pageUtils } ) => {
243+ await page . setContent (
244+ `
245+ <ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
246+ ` ,
247+ config
248+ ) ;
249+
250+ const ionBlur = await page . spyOnEvent ( 'ionBlur' ) ;
251+
252+ // Test blur with keyboard navigation.
253+ // Focus the checkbox.
254+ await pageUtils . pressKeys ( 'Tab' ) ;
255+ // Blur the checkbox.
256+ await pageUtils . pressKeys ( 'Tab' ) ;
257+
258+ expect ( ionBlur ) . toHaveReceivedEventTimes ( 1 ) ;
259+
260+ // Test blur with click.
261+ const checkbox = page . locator ( 'ion-checkbox' ) ;
262+ // Focus the checkbox.
263+ await checkbox . click ( ) ;
264+ // Blur the checkbox by clicking outside of it.
265+ const checkboxBoundingBox = ( await checkbox . boundingBox ( ) ) ! ;
266+ await page . mouse . click ( 0 , checkboxBoundingBox . height + 1 ) ;
267+
268+ expect ( ionBlur ) . toHaveReceivedEventTimes ( 2 ) ;
269+ } ) ;
270+
271+ test ( 'should fire ionBlur after interacting with checkbox in item' , async ( { page, pageUtils } ) => {
272+ await page . setContent (
273+ `
274+ <ion-item>
275+ <ion-checkbox aria-label="checkbox" value="my-checkbox"></ion-checkbox>
276+ </ion-item>
277+ ` ,
278+ config
279+ ) ;
280+
281+ const ionBlur = await page . spyOnEvent ( 'ionBlur' ) ;
282+
283+ // Test blur with keyboard navigation.
284+ // Focus the checkbox.
285+ await pageUtils . pressKeys ( 'Tab' ) ;
286+ // Blur the checkbox.
287+ await pageUtils . pressKeys ( 'Tab' ) ;
288+
289+ expect ( ionBlur ) . toHaveReceivedEventTimes ( 1 ) ;
290+
291+ // Verify that the event target is the checkbox and not the item.
292+ const event = ionBlur . events [ 0 ] ;
293+ expect ( ( event . target as HTMLElement ) . tagName . toLowerCase ( ) ) . toBe ( 'ion-checkbox' ) ;
294+
295+ // Test blur with click.
296+ const item = page . locator ( 'ion-item' ) ;
297+ await item . click ( ) ;
298+ // Blur the checkbox by clicking outside of it.
299+ const itemBoundingBox = ( await item . boundingBox ( ) ) ! ;
300+ await page . mouse . click ( 0 , itemBoundingBox . height + 1 ) ;
301+
302+ expect ( ionBlur ) . toHaveReceivedEventTimes ( 2 ) ;
303+
304+ // Verify that the event target is the checkbox and not the item.
305+ const eventByClick = ionBlur . events [ 0 ] ;
306+ expect ( ( eventByClick . target as HTMLElement ) . tagName . toLowerCase ( ) ) . toBe ( 'ion-checkbox' ) ;
307+ } ) ;
308+ } ) ;
136309} ) ;
0 commit comments