Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #220 from golemhq/feature/highlight-element
Browse files Browse the repository at this point in the history
add highlight element setting, method, action
  • Loading branch information
luciano-renzi committed Jul 15, 2021
2 parents f4ae0f1 + 9a150af commit 11d2f2f
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 12 deletions.
4 changes: 4 additions & 0 deletions docs/source/golem-actions.md
Expand Up @@ -328,6 +328,10 @@ Get the element text

Get the element value attribute

### highlight_element(element)

Highlight element on the page

### javascript_click(element)

Click an element using Javascript
Expand Down
3 changes: 2 additions & 1 deletion docs/source/golem_public_api/webdriver-class.md
Expand Up @@ -203,7 +203,7 @@ from the current file_detector, then the class is instantiated with args and kwa
instantiation.
* kwargs - Keyword arguments, passed the same way as args.

#### **find**(element=None, id=None, name=None, link_text=None, partial_link_text=None, css=None, xpath=None, tag_name=None, timeout=None, wait_displayed=None) <small>[Golem]</small>
#### **find**(element=None, id=None, name=None, link_text=None, partial_link_text=None, css=None, xpath=None, tag_name=None, timeout=None, wait_displayed=None, highlight=None) <small>[Golem]</small>

Find a WebElement

Expand All @@ -215,6 +215,7 @@ Search criteria:
Other args:
* timeout: timeout (in seconds) to wait for element to be present. by default it uses the *search_timeout* setting value
* wait_displayed: wait for element to be displayed (visible). By default uses the *wait_displayed* setting value
* highlight: highlights element on the page when found

Usage:
```python
Expand Down
3 changes: 2 additions & 1 deletion docs/source/golem_public_api/webelement-class.md
Expand Up @@ -23,7 +23,7 @@ Clicks the element.
#### **double_click**() <small>[Golem]</small>
Double click the element

#### **find**(element=None, id=None, name=None, link_text=None, partial_link_text=None, css=None, xpath=None, tag_name=None, timeout=None, wait_displayed=None) <small>[Golem]</small>
#### **find**(element=None, id=None, name=None, link_text=None, partial_link_text=None, css=None, xpath=None, tag_name=None, timeout=None, wait_displayed=None, highlight=None) <small>[Golem]</small>
Find a WebElement

Search criteria:
Expand All @@ -34,6 +34,7 @@ Search criteria:
Other args:
* timeout: timeout (in seconds) to wait for element to be present. By default it uses the search_timeout setting value.
* wait_displayed: wait for element to be displayed (visible). By default uses the wait_displayed setting value.
* highlight: highlights element on the page when found

Usage:
```python
Expand Down
4 changes: 4 additions & 0 deletions docs/source/settings.md
Expand Up @@ -29,6 +29,10 @@ Take a screenshot on every step. Default is False.

Take a screenshot after 'test' function ends. Default is False.

### highlight_elements

Highlight elements on the screen when found. Default is False

### test_data

The location to store test data. Options are: 'infile' and 'csv'. Default is 'csv.'.
Expand Down
10 changes: 10 additions & 0 deletions golem/actions.py
Expand Up @@ -1252,6 +1252,16 @@ def go_forward():
get_browser().forward()


def highlight_element(element):
"""Highlight element on the page
Parameters:
element : element
"""
element = get_browser().find(element)
element.highlight()


def http_get(url, headers={}, params={}, verify_ssl_cert=True):
"""Perform an HTTP GET request to the given URL.
Headers and params are optional dictionaries.
Expand Down
4 changes: 4 additions & 0 deletions golem/core/settings_manager.py
Expand Up @@ -22,6 +22,9 @@
// Take a screenshot at the end of every test
"screenshot_on_end": false,
// Highlight elements on the screen when found
"highlight_elements": false,
// Where to store test data. Options are: 'infile', 'csv'. Default is 'csv'
"test_data": "csv",
Expand Down Expand Up @@ -79,6 +82,7 @@
('screenshot_on_error', True),
('screenshot_on_step', False),
('screenshot_on_end', False),
('highlight_elements', False),
('test_data', 'csv'),
('wait_hook', None),
('default_browser', 'chrome'),
Expand Down
19 changes: 14 additions & 5 deletions golem/webdriver/common.py
Expand Up @@ -10,7 +10,7 @@


def _find_webelement(root, selector_type, selector_value, element_name,
timeout=0, wait_displayed=False):
timeout=0, wait_displayed=False, highlight=False):
"""Finds a web element."""
webelement = None
remaining_time = lambda: timeout - (time.time() - start_time)
Expand Down Expand Up @@ -60,7 +60,8 @@ def _find_webelement(root, selector_type, selector_value, element_name,


def _find(self, element=None, id=None, name=None, link_text=None, partial_link_text=None,
css=None, xpath=None, tag_name=None, timeout=None, wait_displayed=None):
css=None, xpath=None, tag_name=None, timeout=None, wait_displayed=None,
highlight=None):
"""Find a webelement.
`element` can be:
Expand All @@ -83,6 +84,9 @@ def _find(self, element=None, id=None, name=None, link_text=None, partial_link_t
if wait_displayed is None:
wait_displayed = execution.settings['wait_displayed']

if highlight is None:
highlight = execution.settings['highlight_elements']

if isinstance(element, WebElement) or isinstance(element, ExtendedWebElement):
webelement = element
elif isinstance(element, tuple):
Expand Down Expand Up @@ -123,13 +127,18 @@ def _find(self, element=None, id=None, name=None, link_text=None, partial_link_t
raise IncorrectSelectorType('Selector is not a valid option')

if not webelement:
webelement = _find_webelement(self, selector_type, selector_value,
element_name, timeout, wait_displayed)
webelement = _find_webelement(self, selector_type, selector_value, element_name,
timeout, wait_displayed, highlight)
webelement.selector_type = selector_type
webelement.selector_value = selector_value
webelement.name = element_name

return extend_webelement(webelement)
webelement = extend_webelement(webelement)
# highlight element
if highlight:
webelement.highlight()

return webelement


def _find_all(self, element=None, id=None, name=None, link_text=None,
Expand Down
4 changes: 2 additions & 2 deletions golem/webdriver/extended_driver.py
Expand Up @@ -149,7 +149,7 @@ def element_is_present(self, element):

def find(self, element=None, id=None, name=None, link_text=None,
partial_link_text=None, css=None, xpath=None, tag_name=None,
timeout=None, wait_displayed=None) -> ExtendedRemoteWebElement:
timeout=None, wait_displayed=None, highlight=None) -> ExtendedRemoteWebElement:
"""Find a WebElement
Search criteria:
Expand All @@ -175,7 +175,7 @@ def find(self, element=None, id=None, name=None, link_text=None,
a golem.webdriver.extended_webelement.ExtendedRemoteWebElement
"""
return common._find(self, element, id, name, link_text, partial_link_text, css,
xpath, tag_name, timeout, wait_displayed)
xpath, tag_name, timeout, wait_displayed, highlight)

def find_all(self, element=None, id=None, name=None, link_text=None,
partial_link_text=None, css=None, xpath=None,
Expand Down
70 changes: 68 additions & 2 deletions golem/webdriver/extended_webelement.py
Expand Up @@ -40,7 +40,7 @@ def double_click(self):

def find(self, element=None, id=None, name=None, link_text=None,
partial_link_text=None, css=None, xpath=None, tag_name=None,
timeout=None, wait_displayed=None) -> 'ExtendedRemoteWebElement':
timeout=None, wait_displayed=None, highlight=None) -> 'ExtendedRemoteWebElement':
"""Find a WebElement
Search criteria:
Expand All @@ -66,7 +66,7 @@ def find(self, element=None, id=None, name=None, link_text=None,
a golem.webdriver.extended_webelement.ExtendedRemoteWebElement
"""
return _find(self, element, id, name, link_text, partial_link_text,
css, xpath, tag_name, timeout, wait_displayed)
css, xpath, tag_name, timeout, wait_displayed, highlight)

def find_all(self, element=None, id=None, name=None, link_text=None,
partial_link_text=None, css=None, xpath=None,
Expand Down Expand Up @@ -104,6 +104,13 @@ def has_focus(self):
script = 'return arguments[0] == document.activeElement'
return self.parent.execute_script(script, self)

def highlight(self):
"""Highlight element"""
try:
self.parent.execute_script(HIGHLIGHT_ELEMENT_SCRIPT, self)
except Exception as e:
pass

@property
def inner_html(self):
""""Element innerHTML attribute"""
Expand Down Expand Up @@ -331,3 +338,62 @@ def extend_webelement(web_element) -> ExtendedRemoteWebElement:
web_element.__class__ = ExtendedRemoteWebElement
return web_element


HIGHLIGHT_ELEMENT_SCRIPT = """
let boundingRect = arguments[0].getBoundingClientRect();
boundingRect.left = boundingRect.left + window.scrollX;
boundingRect.top = boundingRect.top + window.scrollY;
if(isNaN(boundingRect.width)) {
boundingRect.width = 0;
}
if(isNaN(boundingRect.height)) {
boundingRect.height = 0;
}
let borders = {
top: document.createElement('div'),
left: document.createElement('div'),
right: document.createElement('div'),
bottom: document.createElement('div'),
}
Object.keys(borders).forEach(border => {
borders[border].style.position = 'absolute';
borders[border].style.backgroundColor = 'yellow';
});
borders.top.style.left = boundingRect.left - 5 + 'px';
borders.top.style.top = boundingRect.top - 5 + 'px';
borders.top.style.width = boundingRect.width + 10 + 'px';
borders.top.style.height = '4px';
borders.left.style.left = boundingRect.left - 5 + 'px';
borders.left.style.top = boundingRect.top - 5 + 'px';
borders.left.style.height = boundingRect.height + 10 + 'px';
borders.left.style.width = '4px';
borders.right.style.left = boundingRect.left + boundingRect.width + 1 + 'px';
borders.right.style.top = boundingRect.top - 5 + 'px';
borders.right.style.height = boundingRect.height + 10 + 'px';
borders.right.style.width = '4px';
borders.bottom.style.left = boundingRect.left - 5 + 'px';
borders.bottom.style.top = boundingRect.top + boundingRect.height + 1 + 'px';
borders.bottom.style.width = boundingRect.width + 10 + 'px';
borders.bottom.style.height = '4px';
let zIndex = parseInt(arguments[0].style.zIndex);
if(!Number.isNaN(zIndex)) {
Object.keys(borders).forEach(border => borders[border].style.zIndex = zIndex + 1);
}
Object.keys(borders).forEach(border => document.body.appendChild(borders[border]));
setTimeout(() => {
Object.keys(borders).forEach(border => borders[border].style.backgroundColor = 'transparent');
}, 300);
setTimeout(() => {
Object.keys(borders).forEach(border => borders[border].style.backgroundColor = 'yellow');
}, 600);
setTimeout(() => {
Object.keys(borders).forEach(border => borders[border].remove());
}, 900);"""
2 changes: 1 addition & 1 deletion requirements_dev.txt
Expand Up @@ -4,6 +4,6 @@ selenium
pytest
requests
py-webdriver-manager
sphinx
sphinx==2.4.4
recommonmark
tox
2 changes: 2 additions & 0 deletions tests/core/settings_manager_test.py
Expand Up @@ -9,6 +9,7 @@
'screenshot_on_error': True,
'screenshot_on_step': False,
'screenshot_on_end': False,
'highlight_elements': False,
'test_data': 'csv',
'wait_hook': None,
'default_browser': 'chrome',
Expand Down Expand Up @@ -37,6 +38,7 @@
'operadriver_path': './drivers/operadriver*',
'search_timeout': 20,
'wait_displayed': False,
'highlight_elements': False,
'log_all_events': True,
'remote_browsers': {},
'remote_url': 'http://localhost:4444/wd/hub',
Expand Down

0 comments on commit 11d2f2f

Please sign in to comment.