Skip to content

Commit ebbcc79

Browse files
authored
Merge pull request #296 from seleniumbase/add-attribute-methods
Add methods for setting and removing element attributes
2 parents 031fffb + 90f1d93 commit ebbcc79

File tree

3 files changed

+84
-39
lines changed

3 files changed

+84
-39
lines changed

help_docs/method_summary.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ self.get_text(selector, by=By.CSS_SELECTOR, timeout=settings.SMALL_TIMEOUT)
3333
self.get_attribute(selector, attribute, by=By.CSS_SELECTOR,
3434
timeout=settings.SMALL_TIMEOUT)
3535

36+
self.set_attribute(selector, attribute, value, by=By.CSS_SELECTOR,
37+
timeout=settings.SMALL_TIMEOUT)
38+
39+
self.remove_attribute(selector, attribute, by=By.CSS_SELECTOR,
40+
timeout=settings.SMALL_TIMEOUT)
41+
42+
self.get_property_value(selector, property, by=By.CSS_SELECTOR,
43+
timeout=settings.SMALL_TIMEOUT)
44+
3645
self.refresh_page()
3746

3847
self.refresh()
@@ -129,9 +138,6 @@ self.post_error_message(message, duration=None, pause=True)
129138
self.set_messenger_theme(theme="default", location="default",
130139
max_messages="default")
131140

132-
self.get_property_value(selector, property, by=By.CSS_SELECTOR,
133-
timeout=settings.SMALL_TIMEOUT)
134-
135141
self.bring_to_front(selector, by=By.CSS_SELECTOR)
136142

137143
self.highlight(selector, by=By.CSS_SELECTOR, loops=4, scroll=True)

seleniumbase/fixtures/base_case.py

Lines changed: 74 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ def get_text(self, selector, by=By.CSS_SELECTOR,
399399

400400
def get_attribute(self, selector, attribute, by=By.CSS_SELECTOR,
401401
timeout=settings.SMALL_TIMEOUT):
402+
""" This method uses JavaScript to get the value of an attribute. """
402403
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
403404
timeout = self.__get_new_timeout(timeout)
404405
if page_utils.is_xpath_selector(selector):
@@ -424,6 +425,79 @@ def get_attribute(self, selector, attribute, by=By.CSS_SELECTOR,
424425
raise Exception("Element {%s} has no attribute {%s}!" % (
425426
selector, attribute))
426427

428+
def set_attribute(self, selector, attribute, value, by=By.CSS_SELECTOR,
429+
timeout=settings.SMALL_TIMEOUT):
430+
""" This method uses JavaScript to set/update an attribute. """
431+
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
432+
timeout = self.__get_new_timeout(timeout)
433+
if page_utils.is_xpath_selector(selector):
434+
by = By.XPATH
435+
if self.is_element_visible(selector, by=by):
436+
self.scroll_to(selector, by=by, timeout=timeout)
437+
attribute = re.escape(attribute)
438+
attribute = self.__escape_quotes_if_needed(attribute)
439+
value = re.escape(value)
440+
value = self.__escape_quotes_if_needed(value)
441+
css_selector = self.convert_to_css_selector(selector, by=by)
442+
css_selector = re.escape(css_selector)
443+
css_selector = self.__escape_quotes_if_needed(css_selector)
444+
script = ("""document.querySelector('%s').setAttribute('%s','%s');"""
445+
% (css_selector, attribute, value))
446+
self.execute_script(script)
447+
448+
def remove_attribute(self, selector, attribute, by=By.CSS_SELECTOR,
449+
timeout=settings.SMALL_TIMEOUT):
450+
""" This method uses JavaScript to remove an attribute. """
451+
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
452+
timeout = self.__get_new_timeout(timeout)
453+
if page_utils.is_xpath_selector(selector):
454+
by = By.XPATH
455+
if self.is_element_visible(selector, by=by):
456+
self.scroll_to(selector, by=by, timeout=timeout)
457+
attribute = re.escape(attribute)
458+
attribute = self.__escape_quotes_if_needed(attribute)
459+
css_selector = self.convert_to_css_selector(selector, by=by)
460+
css_selector = re.escape(css_selector)
461+
css_selector = self.__escape_quotes_if_needed(css_selector)
462+
script = ("""document.querySelector('%s').removeAttribute('%s');"""
463+
% (css_selector, attribute))
464+
self.execute_script(script)
465+
466+
def get_property_value(self, selector, property, by=By.CSS_SELECTOR,
467+
timeout=settings.SMALL_TIMEOUT):
468+
""" Returns the property value of a page element's computed style.
469+
Example:
470+
opacity = self.get_property_value("html body a", "opacity")
471+
self.assertTrue(float(opacity) > 0, "Element not visible!") """
472+
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
473+
timeout = self.__get_new_timeout(timeout)
474+
if page_utils.is_xpath_selector(selector):
475+
by = By.XPATH
476+
if page_utils.is_link_text_selector(selector):
477+
selector = page_utils.get_link_text_from_selector(selector)
478+
by = By.LINK_TEXT
479+
self.wait_for_ready_state_complete()
480+
page_actions.wait_for_element_present(
481+
self.driver, selector, by, timeout)
482+
try:
483+
selector = self.convert_to_css_selector(selector, by=by)
484+
except Exception:
485+
# Don't run action if can't convert to CSS_Selector for JavaScript
486+
raise Exception(
487+
"Exception: Could not convert {%s}(by=%s) to CSS_SELECTOR!" % (
488+
selector, by))
489+
selector = re.escape(selector)
490+
selector = self.__escape_quotes_if_needed(selector)
491+
script = ("""var $elm = document.querySelector('%s');
492+
$val = window.getComputedStyle($elm).getPropertyValue('%s');
493+
return $val;"""
494+
% (selector, property))
495+
value = self.execute_script(script)
496+
if value is not None:
497+
return value
498+
else:
499+
return "" # Return an empty string if the property doesn't exist
500+
427501
def refresh_page(self):
428502
self.__last_page_load_url = None
429503
self.driver.refresh()
@@ -1297,41 +1371,6 @@ def post_error_message(self, message, duration=None, pause=True):
12971371
duration = float(duration) + 0.15
12981372
time.sleep(float(duration))
12991373

1300-
def get_property_value(self, selector, property, by=By.CSS_SELECTOR,
1301-
timeout=settings.SMALL_TIMEOUT):
1302-
""" Returns the property value of a page element's computed style.
1303-
Example:
1304-
opacity = self.get_property_value("html body a", "opacity")
1305-
self.assertTrue(float(opacity) > 0, "Element not visible!") """
1306-
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
1307-
timeout = self.__get_new_timeout(timeout)
1308-
if page_utils.is_xpath_selector(selector):
1309-
by = By.XPATH
1310-
if page_utils.is_link_text_selector(selector):
1311-
selector = page_utils.get_link_text_from_selector(selector)
1312-
by = By.LINK_TEXT
1313-
self.wait_for_ready_state_complete()
1314-
page_actions.wait_for_element_present(
1315-
self.driver, selector, by, timeout)
1316-
try:
1317-
selector = self.convert_to_css_selector(selector, by=by)
1318-
except Exception:
1319-
# Don't run action if can't convert to CSS_Selector for JavaScript
1320-
raise Exception(
1321-
"Exception: Could not convert {%s}(by=%s) to CSS_SELECTOR!" % (
1322-
selector, by))
1323-
selector = re.escape(selector)
1324-
selector = self.__escape_quotes_if_needed(selector)
1325-
script = ("""var $elm = document.querySelector('%s');
1326-
$val = window.getComputedStyle($elm).getPropertyValue('%s');
1327-
return $val;"""
1328-
% (selector, property))
1329-
value = self.execute_script(script)
1330-
if value is not None:
1331-
return value
1332-
else:
1333-
return "" # Return an empty string if the property doesn't exist
1334-
13351374
def bring_to_front(self, selector, by=By.CSS_SELECTOR):
13361375
""" Updates the Z-index of a page element to bring it into view.
13371376
Useful when getting a WebDriverException, such as the one below:

setup.py

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

1818
setup(
1919
name='seleniumbase',
20-
version='1.21.4',
20+
version='1.21.5',
2121
description='Reliable Browser Automation & Testing Framework',
2222
long_description=long_description,
2323
long_description_content_type='text/markdown',

0 commit comments

Comments
 (0)