Skip to content

Commit bcda984

Browse files
authored
Merge pull request #146 from seleniumbase/fix-link-text-clicking-bug
Fix link_text clicking bug
2 parents f36a7d9 + af214fc commit bcda984

File tree

4 files changed

+73
-43
lines changed

4 files changed

+73
-43
lines changed

help_docs/method_summary.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ self.click_chain(selectors_list, by=By.CSS_SELECTOR,
1818

1919
self.is_link_text_present(link_text)
2020

21-
self.get_href_from_link_text(link_text)
21+
self.get_link_text_attribute(link_text, attribute)
2222

23-
self.wait_for_href_from_link_text(link_text, timeout=settings.SMALL_TIMEOUT)
23+
self.wait_for_link_text_present(link_text, timeout=settings.SMALL_TIMEOUT)
2424

2525
self.click_link_text(link_text, timeout=settings.SMALL_TIMEOUT)
2626

seleniumbase/fixtures/base_case.py

Lines changed: 69 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -175,45 +175,37 @@ def is_link_text_present(self, link_text):
175175
The element doesn't need to be visible,
176176
such as elements hidden inside a dropdown selection. """
177177
self.wait_for_ready_state_complete()
178-
source = self.driver.page_source
178+
source = self.get_page_source()
179179
soup = BeautifulSoup(source, "html.parser")
180180
html_links = soup.find_all('a')
181181
for html_link in html_links:
182-
if html_link.text == link_text:
183-
if html_link.has_attr('href'):
184-
return True
182+
if html_link.text.strip() == link_text.strip():
183+
return True
185184
return False
186185

187-
def get_href_from_link_text(self, link_text):
186+
def get_link_text_attribute(self, link_text, attribute):
188187
self.wait_for_ready_state_complete()
189-
source = self.driver.page_source
188+
source = self.get_page_source()
190189
soup = BeautifulSoup(source, "html.parser")
191190
html_links = soup.find_all('a')
192191
for html_link in html_links:
193-
if html_link.text == link_text:
194-
if html_link.has_attr('href'):
195-
href = html_link.get('href')
196-
if href.startswith('//'):
197-
link = "http:" + href
198-
elif href.startswith('/'):
199-
url = self.driver.current_url
200-
domain_url = self.get_domain_url(url)
201-
link = domain_url + href
202-
else:
203-
link = href
204-
return link
192+
if html_link.text.strip() == link_text.strip():
193+
if html_link.has_attr(attribute):
194+
attribute_value = html_link.get(attribute)
195+
return attribute_value
205196
raise Exception(
206197
'Could not parse link from link_text [%s]' % link_text)
207198
raise Exception("Link Text [%s] was not found!" % link_text)
208199

209-
def wait_for_href_from_link_text(self, link_text,
210-
timeout=settings.SMALL_TIMEOUT):
200+
def wait_for_link_text_present(self, link_text,
201+
timeout=settings.SMALL_TIMEOUT):
211202
start_ms = time.time() * 1000.0
212203
stop_ms = start_ms + (timeout * 1000.0)
213204
for x in range(int(timeout * 5)):
214205
try:
215-
href = self.get_href_from_link_text(link_text)
216-
return href
206+
if not self.is_link_text_present(link_text):
207+
raise Exception("Link text [%s] not found!" % link_text)
208+
return
217209
except Exception:
218210
now_ms = time.time() * 1000.0
219211
if now_ms >= stop_ms:
@@ -233,10 +225,11 @@ def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT):
233225
element = self.wait_for_link_text_visible(link_text)
234226
element.click()
235227
return
236-
self.open(self.get_href_from_link_text(link_text))
228+
self.open(self._get_href_from_link_text(link_text))
237229
return
238-
self.wait_for_href_from_link_text(link_text, timeout=timeout)
239-
pre_action_url = self.driver.current_url
230+
if not self.is_link_text_present(link_text):
231+
self.wait_for_link_text_present(link_text)
232+
pre_action_url = self.get_current_url()
240233
try:
241234
element = self.wait_for_link_text_visible(
242235
link_text, timeout=0.2)
@@ -250,11 +243,33 @@ def click_link_text(self, link_text, timeout=settings.SMALL_TIMEOUT):
250243
link_text, timeout=timeout)
251244
element.click()
252245
except Exception:
253-
# The link text is probably hidden under a dropdown menu
254-
if not self._click_dropdown_link_text(link_text):
255-
element = self.wait_for_link_text_visible(
256-
link_text, timeout=settings.MINI_TIMEOUT)
257-
element.click()
246+
hidden_css = None
247+
try:
248+
href = self._get_href_from_link_text(link_text)
249+
link_css = '[href="%s"]' % href
250+
if self.is_element_visible(link_css):
251+
self.click(link_css)
252+
else:
253+
hidden_css = link_css
254+
raise Exception("Element %s is not clickable!" % link_css)
255+
except Exception:
256+
try:
257+
ng_click = self._get_ng_click_from_link_text(link_text)
258+
link_css = '[ng-click="%s"]' % (ng_click)
259+
if self.is_element_visible(link_css):
260+
self.click(link_css)
261+
else:
262+
if not hidden_css:
263+
hidden_css = link_css
264+
raise Exception(
265+
"Element %s is not clickable!" % link_css)
266+
except Exception:
267+
# The link text is probably hidden under a dropdown menu
268+
if not self._click_dropdown_link_text(link_text,
269+
hidden_css):
270+
element = self.wait_for_link_text_visible(
271+
link_text, timeout=settings.MINI_TIMEOUT)
272+
element.click()
258273
if settings.WAIT_FOR_RSC_ON_CLICKS:
259274
self.wait_for_ready_state_complete()
260275
if self.demo_mode:
@@ -278,7 +293,7 @@ def click_partial_link_text(self, partial_link_text,
278293
element = self.wait_for_partial_link_text(partial_link_text)
279294
element.click()
280295
return
281-
source = self.driver.page_source
296+
source = self.get_page_source()
282297
soup = BeautifulSoup(source, "html.parser")
283298
html_links = soup.fetch('a')
284299
for html_link in html_links:
@@ -583,7 +598,7 @@ def is_element_in_frame(self, selector, by=By.CSS_SELECTOR):
583598
selector, by = self._recalculate_selector(selector, by)
584599
if self.is_element_present(selector, by=by):
585600
return False
586-
source = self.driver.page_source
601+
source = self.get_page_source()
587602
soup = BeautifulSoup(source, "html.parser")
588603
iframe_list = soup.select('iframe')
589604
for iframe in iframe_list:
@@ -608,7 +623,7 @@ def enter_frame_of_element(self, selector, by=By.CSS_SELECTOR):
608623
selector, by = self._recalculate_selector(selector, by)
609624
if self.is_element_present(selector, by=by):
610625
return None
611-
source = self.driver.page_source
626+
source = self.get_page_source()
612627
soup = BeautifulSoup(source, "html.parser")
613628
iframe_list = soup.select('iframe')
614629
for iframe in iframe_list:
@@ -1498,26 +1513,41 @@ def process_checks(self, print_only=False):
14981513

14991514
############
15001515

1501-
def _click_dropdown_link_text(self, link_text):
1516+
def _get_href_from_link_text(self, link_text):
1517+
href = self.get_link_text_attribute(link_text, "href")
1518+
if href.startswith('//'):
1519+
link = "http:" + href
1520+
elif href.startswith('/'):
1521+
url = self.driver.current_url
1522+
domain_url = self.get_domain_url(url)
1523+
link = domain_url + href
1524+
else:
1525+
link = href
1526+
return link
1527+
1528+
def _get_ng_click_from_link_text(self, link_text):
1529+
ng_click = self.get_link_text_attribute(link_text, "ng-click")
1530+
return ng_click
1531+
1532+
def _click_dropdown_link_text(self, link_text, hidden_css):
15021533
""" When a link is hidden under a dropdown menu, use this. """
1503-
href = self.wait_for_href_from_link_text(link_text)
1504-
source = self.driver.page_source
1534+
source = self.get_page_source()
15051535
soup = BeautifulSoup(source, "html.parser")
15061536
drop_down_list = soup.select('[class*=dropdown]')
1537+
csstype = hidden_css.split('[')[1].split('=')[0]
15071538
for item in drop_down_list:
1508-
if link_text in item.text.split('\n') and href in item.decode():
1539+
if link_text in item.text.split('\n') and csstype in item.decode():
15091540
dropdown_css = ""
15101541
for css_class in item['class']:
15111542
dropdown_css += '.'
15121543
dropdown_css += css_class
15131544
dropdown_css = item.name + dropdown_css
1514-
link_css = '[href="%s"]' % href
15151545
matching_dropdowns = self.find_visible_elements(dropdown_css)
15161546
for dropdown in matching_dropdowns:
15171547
# The same class names might be used for multiple dropdowns
15181548
try:
15191549
page_actions.hover_element_and_click(
1520-
self.driver, dropdown, link_css,
1550+
self.driver, dropdown, hidden_css,
15211551
click_by=By.CSS_SELECTOR, timeout=0.2)
15221552
return True
15231553
except Exception:

server_setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setup(
1010
name='seleniumbase',
11-
version='1.7.0',
11+
version='1.7.1',
1212
description='Web Automation & Testing Framework - http://seleniumbase.com',
1313
long_description='Web Automation and Testing Framework - seleniumbase.com',
1414
platforms='Mac * Windows * Linux * Docker',

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setup(
1010
name='seleniumbase',
11-
version='1.7.0',
11+
version='1.7.1',
1212
description='Web Automation & Testing Framework - http://seleniumbase.com',
1313
long_description='Web Automation and Testing Framework - seleniumbase.com',
1414
platforms='Mac * Windows * Linux * Docker',

0 commit comments

Comments
 (0)