@@ -252,6 +252,45 @@ def select_all(self, selector, timeout=settings.SMALL_TIMEOUT):
252
252
def find_elements (self , selector , timeout = settings .SMALL_TIMEOUT ):
253
253
return self .select_all (selector , timeout = timeout )
254
254
255
+ def find_visible_elements (self , selector , timeout = settings .SMALL_TIMEOUT ):
256
+ visible_elements = []
257
+ elements = self .select_all (selector , timeout = timeout )
258
+ for element in elements :
259
+ with suppress (Exception ):
260
+ position = element .get_position ()
261
+ if (position .width != 0 or position .height != 0 ):
262
+ visible_elements .append (element )
263
+ return visible_elements
264
+
265
+ def click_nth_element (self , selector , number ):
266
+ elements = self .select_all (selector )
267
+ if len (elements ) < number :
268
+ raise Exception (
269
+ "Not enough matching {%s} elements to "
270
+ "click number %s!" % (selector , number )
271
+ )
272
+ number = number - 1
273
+ if number < 0 :
274
+ number = 0
275
+ element = elements [number ]
276
+ element .click ()
277
+
278
+ def click_nth_visible_element (self , selector , number ):
279
+ """Finds all matching page elements and clicks the nth visible one.
280
+ Example: self.click_nth_visible_element('[type="checkbox"]', 5)
281
+ (Clicks the 5th visible checkbox on the page.)"""
282
+ elements = self .find_visible_elements (selector )
283
+ if len (elements ) < number :
284
+ raise Exception (
285
+ "Not enough matching {%s} elements to "
286
+ "click number %s!" % (selector , number )
287
+ )
288
+ number = number - 1
289
+ if number < 0 :
290
+ number = 0
291
+ element = elements [number ]
292
+ element .click ()
293
+
255
294
def click_link (self , link_text ):
256
295
self .find_elements_by_text (link_text , "a" )[0 ].click ()
257
296
@@ -479,18 +518,36 @@ def click_if_visible(self, selector):
479
518
self .__slow_mode_pause_if_set ()
480
519
self .loop .run_until_complete (self .page .wait ())
481
520
482
- def click_visible_elements (self , selector ):
521
+ def click_visible_elements (self , selector , limit = 0 ):
522
+ """Finds all matching page elements and clicks visible ones in order.
523
+ If a click reloads or opens a new page, the clicking will stop.
524
+ If no matching elements appear, an Exception will be raised.
525
+ If "limit" is set and > 0, will only click that many elements.
526
+ Also clicks elements that become visible from previous clicks.
527
+ Works best for actions such as clicking all checkboxes on a page.
528
+ Example: self.click_visible_elements('input[type="checkbox"]')"""
483
529
elements = self .select_all (selector )
530
+ click_count = 0
484
531
for element in elements :
532
+ if limit and limit > 0 and click_count >= limit :
533
+ return
485
534
try :
486
- position = element .get_position ()
487
- if (position .width != 0 or position .height != 0 ):
535
+ width = 0
536
+ height = 0
537
+ try :
538
+ position = element .get_position ()
539
+ width = position .width
540
+ height = position .height
541
+ except Exception :
542
+ continue
543
+ if (width != 0 or height != 0 ):
488
544
element .click ()
545
+ click_count += 1
489
546
time .sleep (0.0375 )
490
547
self .__slow_mode_pause_if_set ()
491
548
self .loop .run_until_complete (self .page .wait ())
492
549
except Exception :
493
- pass
550
+ break
494
551
495
552
def mouse_click (self , selector , timeout = settings .SMALL_TIMEOUT ):
496
553
"""(Attempt simulating a mouse click)"""
@@ -1238,6 +1295,7 @@ def gui_drag_drop_points(self, x1, y1, x2, y2, timeframe=0.35):
1238
1295
1239
1296
def gui_drag_and_drop (self , drag_selector , drop_selector , timeframe = 0.35 ):
1240
1297
self .__slow_mode_pause_if_set ()
1298
+ self .bring_active_window_to_front ()
1241
1299
x1 , y1 = self .get_gui_element_center (drag_selector )
1242
1300
self .__add_light_pause ()
1243
1301
x2 , y2 = self .get_gui_element_center (drop_selector )
@@ -1327,17 +1385,22 @@ def gui_hover_x_y(self, x, y, timeframe=0.25):
1327
1385
1328
1386
def gui_hover_element (self , selector , timeframe = 0.25 ):
1329
1387
self .__slow_mode_pause_if_set ()
1330
- x , y = self .get_gui_element_center (selector )
1331
- self .__add_light_pause ()
1332
- self .__gui_hover_x_y (x , y , timeframe = timeframe )
1333
- self .__slow_mode_pause_if_set ()
1388
+ element_rect = self .get_gui_element_rect (selector )
1389
+ width = element_rect ["width" ]
1390
+ height = element_rect ["height" ]
1391
+ if width > 0 and height > 0 :
1392
+ x , y = self .get_gui_element_center (selector )
1393
+ self .bring_active_window_to_front ()
1394
+ self .__gui_hover_x_y (x , y , timeframe = timeframe )
1395
+ self .__slow_mode_pause_if_set ()
1334
1396
self .loop .run_until_complete (self .page .wait ())
1335
1397
1336
1398
def gui_hover_and_click (self , hover_selector , click_selector ):
1337
1399
gui_lock = fasteners .InterProcessLock (
1338
1400
constants .MultiBrowser .PYAUTOGUILOCK
1339
1401
)
1340
1402
with gui_lock :
1403
+ self .bring_active_window_to_front ()
1341
1404
self .gui_hover_element (hover_selector )
1342
1405
time .sleep (0.15 )
1343
1406
self .gui_hover_element (click_selector )
0 commit comments