@@ -94,6 +94,13 @@ def click(self, selector, by=By.CSS_SELECTOR,
94
94
timeout = self ._get_new_timeout (timeout )
95
95
if page_utils .is_xpath_selector (selector ):
96
96
by = By .XPATH
97
+ if page_utils .is_link_text_selector (selector ):
98
+ selector = page_utils .get_link_text_from_selector (selector )
99
+ by = By .LINK_TEXT
100
+ if not self .is_link_text_visible (selector ):
101
+ # Handle a special case of links hidden in dropdowns
102
+ self .click_link_text (selector , timeout = timeout )
103
+ return
97
104
element = page_actions .wait_for_element_visible (
98
105
self .driver , selector , by , timeout = timeout )
99
106
self ._demo_mode_highlight_if_active (selector , by )
@@ -161,6 +168,59 @@ def click_chain(self, selectors_list, by=By.CSS_SELECTOR,
161
168
if spacing > 0 :
162
169
time .sleep (spacing )
163
170
171
+ def is_link_text_present (self , link_text ):
172
+ """ Returns True if the link text appears in the HTML of the page.
173
+ The element doesn't need to be visible,
174
+ such as elements hidden inside a dropdown selection. """
175
+ self .wait_for_ready_state_complete ()
176
+ source = self .driver .page_source
177
+ soup = BeautifulSoup (source , "html.parser" )
178
+ html_links = soup .find_all ('a' )
179
+ for html_link in html_links :
180
+ if html_link .text == link_text :
181
+ if html_link .has_attr ('href' ):
182
+ return True
183
+ return False
184
+
185
+ def get_href_from_link_text (self , link_text ):
186
+ self .wait_for_ready_state_complete ()
187
+ source = self .driver .page_source
188
+ soup = BeautifulSoup (source , "html.parser" )
189
+ html_links = soup .find_all ('a' )
190
+ for html_link in html_links :
191
+ if html_link .text == link_text :
192
+ if html_link .has_attr ('href' ):
193
+ href = html_link .get ('href' )
194
+ if href .startswith ('//' ):
195
+ link = "http:" + href
196
+ elif href .startswith ('/' ):
197
+ url = self .driver .current_url
198
+ domain_url = self .get_domain_url (url )
199
+ link = domain_url + href
200
+ else :
201
+ link = href
202
+ return link
203
+ raise Exception (
204
+ 'Could not parse link from link_text [%s]' % link_text )
205
+ raise Exception ("Link Text [%s] was not found!" % link_text )
206
+
207
+ def wait_for_href_from_link_text (self , link_text ,
208
+ timeout = settings .SMALL_TIMEOUT ):
209
+ start_ms = time .time () * 1000.0
210
+ stop_ms = start_ms + (timeout * 1000.0 )
211
+ for x in range (int (timeout * 5 )):
212
+ try :
213
+ href = self .get_href_from_link_text (link_text )
214
+ return href
215
+ except Exception :
216
+ now_ms = time .time () * 1000.0
217
+ if now_ms >= stop_ms :
218
+ break
219
+ time .sleep (0.2 )
220
+ raise Exception (
221
+ "Link text [%s] was not present after %s seconds!" % (
222
+ link_text , timeout ))
223
+
164
224
def click_link_text (self , link_text , timeout = settings .SMALL_TIMEOUT ):
165
225
""" This method clicks link text on a page """
166
226
# If using phantomjs, might need to extract and open the link directly
@@ -171,38 +231,28 @@ def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT):
171
231
element = self .wait_for_link_text_visible (link_text )
172
232
element .click ()
173
233
return
174
- source = self .driver .page_source
175
- soup = BeautifulSoup (source , "html.parser" )
176
- html_links = soup .find_all ('a' )
177
- for html_link in html_links :
178
- if html_link .text == link_text :
179
- if html_link .has_attr ('href' ):
180
- href = html_link .get ('href' )
181
- if href .startswith ('//' ):
182
- link = "http:" + href
183
- elif href .startswith ('/' ):
184
- url = self .driver .current_url
185
- domain_url = self .get_domain_url (url )
186
- link = domain_url + href
187
- else :
188
- link = href
189
- self .open (link )
190
- return
191
- raise Exception (
192
- 'Could not parse link from link_text [%s]' % link_text )
193
- raise Exception ("Link text [%s] was not found!" % link_text )
194
- # Not using phantomjs
195
- element = self .wait_for_link_text_visible (link_text , timeout = timeout )
196
- self ._demo_mode_highlight_if_active (link_text , by = By .LINK_TEXT )
234
+ self .open (self .get_href_from_link_text (link_text ))
235
+ return
236
+ self .wait_for_href_from_link_text (link_text , timeout = timeout )
197
237
pre_action_url = self .driver .current_url
198
238
try :
199
- element .click ()
200
- except (StaleElementReferenceException , ENI_Exception ):
201
- self .wait_for_ready_state_complete ()
202
- time .sleep (0.05 )
203
239
element = self .wait_for_link_text_visible (
204
- link_text , timeout = timeout )
205
- element .click ()
240
+ link_text , timeout = 0.2 )
241
+ self ._demo_mode_highlight_if_active (link_text , by = By .LINK_TEXT )
242
+ try :
243
+ element .click ()
244
+ except (StaleElementReferenceException , ENI_Exception ):
245
+ self .wait_for_ready_state_complete ()
246
+ time .sleep (0.05 )
247
+ element = self .wait_for_link_text_visible (
248
+ link_text , timeout = timeout )
249
+ element .click ()
250
+ except Exception :
251
+ # The link text is probably hidden under a dropdown menu
252
+ if not self ._click_dropdown_link_text (link_text ):
253
+ element = self .wait_for_link_text_visible (
254
+ link_text , timeout = settings .MINI_TIMEOUT )
255
+ element .click ()
206
256
if settings .WAIT_FOR_RSC_ON_CLICKS :
207
257
self .wait_for_ready_state_complete ()
208
258
if self .demo_mode :
@@ -1283,6 +1333,32 @@ def process_checks(self, print_only=False):
1283
1333
1284
1334
############
1285
1335
1336
+ def _click_dropdown_link_text (self , link_text ):
1337
+ """ When a link is hidden under a dropdown menu, use this. """
1338
+ href = self .wait_for_href_from_link_text (link_text )
1339
+ source = self .driver .page_source
1340
+ soup = BeautifulSoup (source , "html.parser" )
1341
+ drop_down_list = soup .select ('[class*=dropdown]' )
1342
+ for item in drop_down_list :
1343
+ if link_text in item .text .split ('\n ' ) and href in item .decode ():
1344
+ dropdown_css = ""
1345
+ for css_class in item ['class' ]:
1346
+ dropdown_css += '.'
1347
+ dropdown_css += css_class
1348
+ dropdown_css = item .name + dropdown_css
1349
+ link_css = '[href="%s"]' % href
1350
+ matching_dropdowns = self .find_visible_elements (dropdown_css )
1351
+ for dropdown in matching_dropdowns :
1352
+ # The same class names might be used for multiple dropdowns
1353
+ try :
1354
+ page_actions .hover_element_and_click (
1355
+ self .driver , dropdown , link_css ,
1356
+ click_by = By .CSS_SELECTOR , timeout = 0.2 )
1357
+ return True
1358
+ except Exception :
1359
+ pass
1360
+ return False
1361
+
1286
1362
def _pick_select_option (self , dropdown_selector , option ,
1287
1363
dropdown_by = By .CSS_SELECTOR , option_by = "text" ,
1288
1364
timeout = settings .SMALL_TIMEOUT ):
0 commit comments