From 965970a17a38b54d988bbb2051cce8faad3e9d39 Mon Sep 17 00:00:00 2001 From: M Pacer Date: Fri, 9 Mar 2018 11:54:10 -0800 Subject: [PATCH 1/7] creates selenium driver(session-scope) & authenticated_browser fixtures Originally written by @takluyver while pair programming --- notebook/tests/selenium/conftest.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/notebook/tests/selenium/conftest.py b/notebook/tests/selenium/conftest.py index 9d0d082a1..215d6b790 100644 --- a/notebook/tests/selenium/conftest.py +++ b/notebook/tests/selenium/conftest.py @@ -63,8 +63,8 @@ def notebook_server(): requests.post(urljoin(info['url'], 'api/shutdown'), headers={'Authorization': 'token '+info['token']}) - -def _get_selenium_driver(): +@pytest.fixture(scope='session') +def selenium_driver(): if os.environ.get('SAUCE_USERNAME'): username = os.environ["SAUCE_USERNAME"] access_key = os.environ["SAUCE_ACCESS_KEY"] @@ -81,16 +81,19 @@ def _get_selenium_driver(): capabilities['version'] = '57.0' hub_url = "%s:%s@localhost:4445" % (username, access_key) print("Connecting remote driver on Sauce Labs") - return Remote(desired_capabilities=capabilities, + driver = Remote(desired_capabilities=capabilities, command_executor="http://%s/wd/hub" % hub_url) elif os.environ.get('JUPYTER_TEST_BROWSER') == 'chrome': - return Chrome() + driver = Chrome() else: - return Firefox() + driver = Firefox() + + yield driver + + # Teardown + driver.quit() @pytest.fixture -def browser(notebook_server): - b = _get_selenium_driver() - b.get("{url}?token={token}".format(**notebook_server)) - yield b - b.quit() +def authenticated_browser(selenium_driver, notebook_server): + selenium_driver.get("{url}?token={token}".format(**notebook_server)) + return selenium_driver From 1f549fcce40b7043f76ff4b90228e0fd5d57bde4 Mon Sep 17 00:00:00 2001 From: M Pacer Date: Fri, 9 Mar 2018 11:58:33 -0800 Subject: [PATCH 2/7] change dashboard test to click on links, go back, and check for contents --- notebook/tests/selenium/test_dashboard_nav.py | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/notebook/tests/selenium/test_dashboard_nav.py b/notebook/tests/selenium/test_dashboard_nav.py index b273ca907..3568c1e95 100644 --- a/notebook/tests/selenium/test_dashboard_nav.py +++ b/notebook/tests/selenium/test_dashboard_nav.py @@ -3,13 +3,13 @@ import os from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC - pjoin = os.path.join def get_list_items(browser): return [{ 'link': a.get_attribute('href'), 'label': a.find_element_by_class_name('item_name').text, + 'element': a, } for a in browser.find_elements_by_class_name('item_link')] @@ -17,29 +17,28 @@ def wait_for_selector(browser, selector, timeout=10): wait = WebDriverWait(browser, timeout) return wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, selector))) - - -def test_items(browser, visited=None): - tree_root_url = browser.current_url - if visited is None: - visited = set() - - wait_for_selector(browser, '.item_link') - items = get_list_items(browser) - print(browser.current_url, len(items)) - for item in items: - print(item) - url = item['link'] - if url.startswith(tree_root_url): - print("Going to", url) - if url in visited: - continue - visited.add(url) - browser.get(url) - wait_for_selector(browser, '.item_link') - assert browser.current_url == url - - test_items(browser, visited) - #browser.back() - - print() +def test_items(authenticated_browser): + tree_root_url = authenticated_browser.current_url + visited_dict = {} + # Going down the tree to collect links + while True: + wait_for_selector(authenticated_browser, '.item_link') + items = get_list_items(authenticated_browser) + visited_dict[authenticated_browser.current_url] = items + print(authenticated_browser.current_url, len(items)) + if len(items)>1: + item = items[1] + url = item['link'] + item["element"].click() + assert authenticated_browser.current_url == url + else: + break + # Going back up the tree while we still have unvisited links + while visited_dict: + wait_for_selector(authenticated_browser, '.item_link') + current_items = get_list_items(authenticated_browser) + current_items_links = [item["link"] for item in current_items] + stored_items = visited_dict.pop(authenticated_browser.current_url) + stored_items_links = [item["link"] for item in stored_items] + assert stored_items_links == current_items_links + authenticated_browser.back() From f4c90eb5d2f918c1d997b149ac9eda55a31d0b8d Mon Sep 17 00:00:00 2001 From: M Pacer Date: Thu, 22 Mar 2018 14:06:18 -0700 Subject: [PATCH 3/7] introduce only_dir_links function to extract tree links from listing --- notebook/tests/selenium/test_dashboard_nav.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/notebook/tests/selenium/test_dashboard_nav.py b/notebook/tests/selenium/test_dashboard_nav.py index 3568c1e95..e3fd3d4ca 100644 --- a/notebook/tests/selenium/test_dashboard_nav.py +++ b/notebook/tests/selenium/test_dashboard_nav.py @@ -13,10 +13,21 @@ def get_list_items(browser): } for a in browser.find_elements_by_class_name('item_link')] +def only_dir_links(browser): + try: + assert 'tree' in browser.current_url + except AssertionError: + raise("You currently ") + wait_for_selector(browser, '.item_link') + items = get_list_items(browser) + return [i for i in items if 'tree' in i['link'] and i['label'] != '..'] + + def wait_for_selector(browser, selector, timeout=10): wait = WebDriverWait(browser, timeout) return wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, selector))) + def test_items(authenticated_browser): tree_root_url = authenticated_browser.current_url visited_dict = {} @@ -42,3 +53,4 @@ def test_items(authenticated_browser): stored_items_links = [item["link"] for item in stored_items] assert stored_items_links == current_items_links authenticated_browser.back() + From c8605f189b4e1389cc98f695430a19a686703c2c Mon Sep 17 00:00:00 2001 From: M Pacer Date: Thu, 22 Mar 2018 14:07:35 -0700 Subject: [PATCH 4/7] use only_dir_links inside test to avoid clicking '..' or non-dir links --- notebook/tests/selenium/test_dashboard_nav.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/notebook/tests/selenium/test_dashboard_nav.py b/notebook/tests/selenium/test_dashboard_nav.py index e3fd3d4ca..aae4d7c75 100644 --- a/notebook/tests/selenium/test_dashboard_nav.py +++ b/notebook/tests/selenium/test_dashboard_nav.py @@ -34,20 +34,19 @@ def test_items(authenticated_browser): # Going down the tree to collect links while True: wait_for_selector(authenticated_browser, '.item_link') - items = get_list_items(authenticated_browser) - visited_dict[authenticated_browser.current_url] = items - print(authenticated_browser.current_url, len(items)) - if len(items)>1: - item = items[1] - url = item['link'] + current_url = authenticated_browser.current_url + items = visited_dict[current_url] = only_dir_links(authenticated_browser) + try: + item = items[0] + text, url = (item['label'], item['link']) item["element"].click() assert authenticated_browser.current_url == url - else: + except IndexError: break # Going back up the tree while we still have unvisited links while visited_dict: wait_for_selector(authenticated_browser, '.item_link') - current_items = get_list_items(authenticated_browser) + current_items = only_dir_links(authenticated_browser) current_items_links = [item["link"] for item in current_items] stored_items = visited_dict.pop(authenticated_browser.current_url) stored_items_links = [item["link"] for item in stored_items] From 47d2be4a5e02d6c50ed582d4f5981ae6a99ce57d Mon Sep 17 00:00:00 2001 From: M Pacer Date: Thu, 22 Mar 2018 14:33:45 -0700 Subject: [PATCH 5/7] move check & wait from only_dir_links to get_list_items; add docstrings --- notebook/tests/selenium/test_dashboard_nav.py | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/notebook/tests/selenium/test_dashboard_nav.py b/notebook/tests/selenium/test_dashboard_nav.py index aae4d7c75..bbf21fd68 100644 --- a/notebook/tests/selenium/test_dashboard_nav.py +++ b/notebook/tests/selenium/test_dashboard_nav.py @@ -5,7 +5,29 @@ from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC pjoin = os.path.join + +class PageError(Exception): + """Error for an action being incompatible with the current jupyter web page. + + """ + def __init__(self, message): + self.message = message + + + def get_list_items(browser): + """Gets list items from a directory listing page + + Raises PageError if not in directory listing page (url has tree in it) + """ + try: + assert 'tree' in browser.current_url + except PageError: + raise PageError("You are not in the notebook's file tree view." + "This function can only be used the file tree context.") + # we need to make sure that at least one item link loads + wait_for_selector(browser, '.item_link') + return [{ 'link': a.get_attribute('href'), 'label': a.find_element_by_class_name('item_name').text, @@ -14,11 +36,9 @@ def get_list_items(browser): def only_dir_links(browser): - try: - assert 'tree' in browser.current_url - except AssertionError: - raise("You currently ") - wait_for_selector(browser, '.item_link') + """Return only links that point at other directories in the tree + + """ items = get_list_items(browser) return [i for i in items if 'tree' in i['link'] and i['label'] != '..'] @@ -29,7 +49,6 @@ def wait_for_selector(browser, selector, timeout=10): def test_items(authenticated_browser): - tree_root_url = authenticated_browser.current_url visited_dict = {} # Going down the tree to collect links while True: @@ -38,14 +57,12 @@ def test_items(authenticated_browser): items = visited_dict[current_url] = only_dir_links(authenticated_browser) try: item = items[0] - text, url = (item['label'], item['link']) item["element"].click() - assert authenticated_browser.current_url == url + assert authenticated_browser.current_url == item['link'] except IndexError: break # Going back up the tree while we still have unvisited links while visited_dict: - wait_for_selector(authenticated_browser, '.item_link') current_items = only_dir_links(authenticated_browser) current_items_links = [item["link"] for item in current_items] stored_items = visited_dict.pop(authenticated_browser.current_url) From f17e775a2cec64ef7f21bbe96173bec10618985a Mon Sep 17 00:00:00 2001 From: M Pacer Date: Thu, 22 Mar 2018 15:15:21 -0700 Subject: [PATCH 6/7] add jupyter_server_info to authenticated browser fixture --- notebook/tests/selenium/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/notebook/tests/selenium/conftest.py b/notebook/tests/selenium/conftest.py index 215d6b790..d7227b12b 100644 --- a/notebook/tests/selenium/conftest.py +++ b/notebook/tests/selenium/conftest.py @@ -95,5 +95,6 @@ def selenium_driver(): @pytest.fixture def authenticated_browser(selenium_driver, notebook_server): + selenium_driver.jupyter_server_info = notebook_server selenium_driver.get("{url}?token={token}".format(**notebook_server)) return selenium_driver From e688774b86e9085e1651013f3ea1d8b2a5e137ed Mon Sep 17 00:00:00 2001 From: M Pacer Date: Thu, 22 Mar 2018 15:17:02 -0700 Subject: [PATCH 7/7] add explicit url_in_tree function to test whether urls are in the tree --- notebook/tests/selenium/test_dashboard_nav.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/notebook/tests/selenium/test_dashboard_nav.py b/notebook/tests/selenium/test_dashboard_nav.py index bbf21fd68..9b588c75e 100644 --- a/notebook/tests/selenium/test_dashboard_nav.py +++ b/notebook/tests/selenium/test_dashboard_nav.py @@ -3,6 +3,8 @@ import os from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC + +from notebook.utils import url_path_join pjoin = os.path.join @@ -13,16 +15,20 @@ class PageError(Exception): def __init__(self, message): self.message = message - + +def url_in_tree(browser, url=None): + if url is None: + url = browser.current_url + tree_url = url_path_join(browser.jupyter_server_info['url'], 'tree') + return url.startswith(tree_url) + def get_list_items(browser): """Gets list items from a directory listing page Raises PageError if not in directory listing page (url has tree in it) """ - try: - assert 'tree' in browser.current_url - except PageError: + if not url_in_tree(browser): raise PageError("You are not in the notebook's file tree view." "This function can only be used the file tree context.") # we need to make sure that at least one item link loads @@ -40,7 +46,8 @@ def only_dir_links(browser): """ items = get_list_items(browser) - return [i for i in items if 'tree' in i['link'] and i['label'] != '..'] + return [i for i in items + if url_in_tree(browser, i['link']) and i['label'] != '..'] def wait_for_selector(browser, selector, timeout=10):