Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFR] browser windows handling #157

Merged
merged 4 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/widgetastic/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ def url(self, address):
self.logger.info('Opening URL: %r', address)
self.selenium.get(address)

@property
def title(self):
"""Returns current title"""
current_title = self.selenium.title
self.logger.info('Current title: %r', current_title)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use f strings here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't do that. 1. f-strings will limit wt.core to py 3.6+ ; 2. logger module has its own syntax for logging statements.

return current_title

@property
def handles_alerts(self):
return self.selenium.capabilities.get('handlesAlerts', True)
Expand Down Expand Up @@ -815,6 +822,65 @@ def get_current_location(self):
# useful if it is necessary to recognize current frame
return self.execute_script('return self.location.toString()')

@property
def current_window_handle(self):
"""Returns the current window handle"""
window_handle = self.selenium.current_window_handle
self.logger.debug("current_window_handle -> %r", window_handle)
return window_handle
digitronik marked this conversation as resolved.
Show resolved Hide resolved

@property
def window_handles(self):
"""Returns all available window handles"""
handles = self.selenium.window_handles
self.logger.debug("window_handles -> %r", handles)
return handles

def switch_to_window(self, window_handle):
"""switches focus to the specified window

Args:
window_handle: The name or window handle
"""
self.logger.debug("switch_to_window -> %r", window_handle)
self.selenium.switch_to.window(window_handle)

def new_window(self, url, focus=False):
izapolsk marked this conversation as resolved.
Show resolved Hide resolved
"""Opens the url in new window of the browser.

Args:
url: web address to open in new window
focus: switch focus to new window; default False
Returns:
new windows handle
"""
handles = set(self.window_handles)
self.logger.info("Opening URL %r in new window", url)
self.selenium.execute_script("window.open('{url}', '_blank')".format(url=url))
new_handle = (set(self.window_handles) - handles).pop()

if focus:
self.switch_to_window(new_handle)
return new_handle

def close_window(self, window_handle=None):
"""Close window form browser

Args:
window_handle: The name or window handle; default current window handle
"""
main_window_handle = self.current_window_handle
self.logger.debug(
"close_window -> %r", window_handle if window_handle else main_window_handle
)

if window_handle and window_handle != main_window_handle:
self.switch_to_window(window_handle)
self.selenium.close()
self.switch_to_window(main_window_handle)
else:
self.selenium.close()


class BrowserParentWrapper(object):
"""A wrapper/proxy class that ensures passing of correct parent locator on elements lookup.
Expand Down
73 changes: 73 additions & 0 deletions testing/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@
from widgetastic.widget import View, Text


@pytest.fixture()
def current_and_new_handle(request, browser, test_server):
"""fixture return current and newly open window handle"""
handle = browser.new_window(url=test_server.url)

@request.addfinalizer
def _close_window():
if handle in browser.window_handles:
browser.close_window(handle)
return browser.current_window_handle, handle


def test_is_displayed(browser):
assert browser.is_displayed('#hello')

Expand Down Expand Up @@ -218,3 +230,64 @@ def test_size(browser):
width, height = browser.size_of('#exact_dimensions')
assert width == 42
assert height == 69


def test_title(browser):
"""Test title of current window"""
assert browser.title == "Test page"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please write some docblocs for these tests, stating what component of window handling they're covering.

This case looks more like a test of the new title attribute than it is a test of current_window_handle, which is tested in test_window_handles below anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added separate tests for each method... with small doc block. 👍



def test_current_window_handle(browser):
"""Test current window handle property"""
assert browser.current_window_handle


@pytest.mark.parametrize("focus", [False, True], ids=["no_focus", "focus"])
def test_new_window(request, browser, focus, test_server):
"""Test open new window with and without focus"""
# main window handle
main_handle = browser.current_window_handle

# open new window focus/no-focus
handle = browser.new_window(url=test_server.url, focus=focus)

@request.addfinalizer
def _close_window():
browser.close_window(handle)

assert handle

if focus:
assert handle == browser.current_window_handle

@request.addfinalizer
def _back_to_main():
browser.switch_to_window(main_handle)
else:
assert handle != browser.current_window_handle


def test_window_handles(browser, current_and_new_handle):
"""Test window handles property"""
assert len(browser.window_handles) == 2
assert set(browser.window_handles) == set(current_and_new_handle)


def test_close_window(browser, current_and_new_handle):
"""Test close window"""
main_handle, new_handle = current_and_new_handle

assert new_handle in browser.window_handles
browser.close_window(new_handle)
assert new_handle not in browser.window_handles


def test_switch_to_window(browser, current_and_new_handle):
"""Test switch to other window"""
main_handle, new_handle = current_and_new_handle

# switch to new window
browser.switch_to_window(new_handle)
assert new_handle == browser.current_window_handle
browser.switch_to_window(main_handle)
assert main_handle == browser.current_window_handle