From d0df3886fa7acaa3d5f63360e2af78aab2deaaaa Mon Sep 17 00:00:00 2001 From: John Chilton Date: Fri, 1 Sep 2017 10:32:39 -0400 Subject: [PATCH] More workflow index page Selenium tests. - Fix rename test for recent change to using alert. - Test basic adding a tag. - Outline of a test for downloading workflows. - Add test for publishing display on index. - Add test for using the search box on the workflow index page. --- test/galaxy_selenium/navigates_galaxy.py | 57 ++++++++++-- test/selenium_tests/framework.py | 11 ++- .../test_workflow_management.py | 87 ++++++++++++++++--- 3 files changed, 136 insertions(+), 19 deletions(-) diff --git a/test/galaxy_selenium/navigates_galaxy.py b/test/galaxy_selenium/navigates_galaxy.py index b9f53e1ac43..46de25ee388 100644 --- a/test/galaxy_selenium/navigates_galaxy.py +++ b/test/galaxy_selenium/navigates_galaxy.py @@ -28,7 +28,7 @@ class NullTourCallback(object): pass -def retry_call_during_transitions(f, attempts=5, sleep=.1): +def retry_call_during_transitions(f, attempts=5, sleep=.1, exception_check=exception_indicates_stale_element): previous_attempts = 0 while True: try: @@ -37,18 +37,18 @@ def retry_call_during_transitions(f, attempts=5, sleep=.1): if previous_attempts > attempts: raise - if not exception_indicates_stale_element(e): + if not exception_check(e): raise time.sleep(sleep) previous_attempts += 1 -def retry_during_transitions(f, attempts=5, sleep=.1): +def retry_during_transitions(f, attempts=5, sleep=.1, exception_check=exception_indicates_stale_element): @wraps(f) def _retry(*args, **kwds): - retry_call_during_transitions(partial(f, *args, **kwds), attempts=attempts, sleep=sleep) + return retry_call_during_transitions(partial(f, *args, **kwds), attempts=attempts, sleep=sleep, exception_check=exception_check) return _retry @@ -395,12 +395,26 @@ class NavigatesGalaxy(HasDriver): def workflow_index_table_elements(self): self.wait_for_selector_visible("tbody.workflow-search") - table_elements = self.driver.find_elements_by_css_selector("tbody.workflow-search > tr") + table_elements = self.driver.find_elements_by_css_selector("tbody.workflow-search > tr:not([style*='display: none'])") return table_elements + def workflow_index_table_row(self, workflow_index=0): + return self.workflow_index_table_elements()[workflow_index] + + @retry_during_transitions + def workflow_index_click_search(self): + search_element = self.wait_for_selector_clickable("input.search-wf") + search_element.click() + return search_element + + def workflow_index_rename(self, new_name, workflow_index=0): + self.workflow_index_click_option("Rename", workflow_index=workflow_index) + alert = self.driver.switch_to.alert + alert.send_keys(new_name) + alert.accept() + def workflow_index_click_option(self, option_title, workflow_index=0): - table_elements = self.workflow_index_table_elements() - workflow_row = table_elements[workflow_index] + workflow_row = self.workflow_index_table_row(workflow_index=workflow_index) workflow_button = workflow_row.find_element_by_css_selector(".menubutton") workflow_button.click() menu_element = self.wait_for_selector_visible("ul.action-dpd") @@ -415,6 +429,35 @@ class NavigatesGalaxy(HasDriver): if not found_option: raise AssertionError("Failed to find workflow action option with title [%s]" % option_title) + def workflow_index_click_tag_display(self, workflow_index=0): + workflow_row_element = self.workflow_index_table_row(workflow_index) + tag_display = workflow_row_element.find_element_by_css_selector(".tags-display") + tag_display.click() + + def workflow_index_tags(self, workflow_index=0): + workflow_row_element = self.workflow_index_table_row(workflow_index) + tag_display = workflow_row_element.find_element_by_css_selector(".tags-display") + tag_spans = tag_display.find_elements_by_css_selector("span.label") + tags = [] + for tag_span in tag_spans: + tags.append(tag_span.text) + return tags + + def workflow_sharing_click_publish(self): + button = self.wait_for_selector_clickable("input[name='make_accessible_and_publish']") + button.click() + + def tagging_add(self, tags, auto_closes=True, parent_selector=""): + + for i, tag in enumerate(tags): + if auto_closes or i == 0: + tag_area = parent_selector + ".tags-input input[type='text']" + tag_area = self.wait_for_selector_clickable(tag_area) + tag_area.click() + + tag_area.send_keys(tag) + self.send_enter(tag_area) + def workflow_run_submit(self): button = self.wait_for_selector(".ui-form-header button") button.click() diff --git a/test/selenium_tests/framework.py b/test/selenium_tests/framework.py index bf0c3bf70a4..092667e7d23 100644 --- a/test/selenium_tests/framework.py +++ b/test/selenium_tests/framework.py @@ -6,16 +6,17 @@ import datetime import json import os import time + import traceback -from functools import wraps +from functools import partial, wraps import requests from galaxy_selenium import ( driver_factory, ) -from galaxy_selenium.navigates_galaxy import NavigatesGalaxy +from galaxy_selenium.navigates_galaxy import NavigatesGalaxy, retry_during_transitions try: from pyvirtualdisplay import Display @@ -112,6 +113,9 @@ def selenium_test(f): return func_wrapper +retry_assertion_during_transitions = partial(retry_during_transitions, exception_check=lambda e: isinstance(e, AssertionError)) + + class SeleniumTestCase(FunctionalTestCase, NavigatesGalaxy): framework_tool_and_types = True @@ -149,6 +153,9 @@ class SeleniumTestCase(FunctionalTestCase, NavigatesGalaxy): def setup_driver_and_session(self): self.display = driver_factory.virtual_display_if_enabled(headless_selenium()) self.driver = get_driver() + # New workflow index page does not degrade well to smaller sizes, needed + # to increase this. + self.driver.set_window_size(1280, 900) if self.ensure_registered: self.register() diff --git a/test/selenium_tests/test_workflow_management.py b/test/selenium_tests/test_workflow_management.py index f4d4369a066..94a5811f4fc 100644 --- a/test/selenium_tests/test_workflow_management.py +++ b/test/selenium_tests/test_workflow_management.py @@ -1,6 +1,7 @@ from .framework import ( + retry_assertion_during_transitions, selenium_test, - SeleniumTestCase + SeleniumTestCase, ) @@ -33,16 +34,82 @@ class WorkflowManagementTestCase(SeleniumTestCase): def test_rename(self): self.workflow_index_open() self._workflow_import_from_url() - self.workflow_index_click_option("Rename") - rename_form_element = self.wait_for_selector("form") - self.fill(rename_form_element, { - "new_name": "CoolNewName" - }) - self.click_submit(rename_form_element) + self.workflow_index_rename("CoolNewName") - table_elements = self.workflow_index_table_elements() - renamed_workflow_button = table_elements[0].find_element_by_css_selector(".menubutton") - assert 'CoolNewName' in renamed_workflow_button.text, renamed_workflow_button.text + @retry_assertion_during_transitions + def check_name(): + row_element = self.workflow_index_table_row() + renamed_workflow_button = row_element.find_element_by_css_selector(".menubutton") + assert 'CoolNewName' in renamed_workflow_button.text, renamed_workflow_button.text + + check_name() + + @selenium_test + def test_download(self): + self.workflow_index_open() + self._workflow_import_from_url() + # TODO: fill this test out - getting downloaded files in general through Selenium is a bit tough, + # going through the motions though should catch a couple potential problems. + self.workflow_index_click_option("Download") + + @selenium_test + def test_tagging(self): + self.workflow_index_open() + self._workflow_import_from_url() + + self.workflow_index_click_tag_display() + self.tagging_add(["cooltag"]) + + @retry_assertion_during_transitions + def check_tags(): + self.assertEqual(self.workflow_index_tags(), ["cooltag"]) + + check_tags() + + @selenium_test + def test_index_search(self): + self.workflow_index_open() + self._workflow_import_from_url() + self.workflow_index_rename("searchforthis") + self._assert_showing_n_workflows(1) + + search_box = self.workflow_index_click_search() + search_box.send_keys("doesnotmatch") + self._assert_showing_n_workflows(0) + + # Prevent stale element textbox by re-fetching, seems to be + # needed but I don't understand why exactly. -John + search_box = self.workflow_index_click_search() + search_box.clear() + self.send_enter(search_box) + self._assert_showing_n_workflows(1) + + search_box = self.workflow_index_click_search() + search_box.send_keys("searchforthis") + self.send_enter(search_box) + self._assert_showing_n_workflows(1) + + @selenium_test + def test_publishing_display(self): + self.workflow_index_open() + self._workflow_import_from_url() + self.workflow_index_rename("managementesttopublish") + + row_element = self.workflow_index_table_row() + columns = row_element.find_elements_by_css_selector("td") + assert columns[4].text == "No" + + self.workflow_index_click_option("Share") + self.workflow_sharing_click_publish() + + self.workflow_index_open() + row_element = self.workflow_index_table_row() + columns = row_element.find_elements_by_css_selector("td") + assert columns[4].text == "Yes" + + @retry_assertion_during_transitions + def _assert_showing_n_workflows(self, n): + self.assertEqual(len(self.workflow_index_table_elements()), n) def _workflow_import_from_url(self): element = self.wait_for_selector_clickable(self.test_data["selectors"]["workflows"]["import_button"])