Warning

This document is for an old release of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.

Source code for galaxy_test.selenium.test_tool_form

import json
from typing import (
    Any,
    Dict,
    List,
)

import pytest
from selenium.webdriver.common.by import By

from galaxy.model.unittest_utils.store_fixtures import one_hda_model_store_dict
from galaxy.selenium.navigates_galaxy import retry_call_during_transitions
from galaxy.util.unittest_utils import skip_if_github_down
from galaxy_test.base import rules_test_data
from galaxy_test.base.populators import (
    flakey,
    stage_rules_example,
)
from .framework import (
    managed_history,
    retry_assertion_during_transitions,
    selenium_test,
    SeleniumTestCase,
    UsesHistoryItemAssertions,
)


[docs]class TestToolForm(SeleniumTestCase, UsesHistoryItemAssertions):
[docs] @selenium_test def test_run_tool_verify_contents_by_peek(self): self._run_environment_test_tool() self.history_panel_wait_for_hid_ok(1) self.history_panel_click_item_title(hid=1) self.assert_item_peek_includes(1, "42")
[docs] @selenium_test def test_run_tool_verify_dataset_details(self): self._run_environment_test_tool() self.history_panel_wait_for_hid_ok(1) self._check_dataset_details_for_inttest_value(1)
[docs] @selenium_test def test_verify_dataset_details_tables(self): self._run_environment_test_tool() self.history_panel_wait_for_hid_ok(1) hda = self.latest_history_item() self._check_dataset_details_for_inttest_value(1) dataset_details_key_value_pairs = self._table_to_key_value_elements("table#dataset-details") number_found = name_found = format_found = False for key, value in dataset_details_key_value_pairs: if "Number" in key.text: assert str(hda["hid"]) in value.text number_found = True if "Name" in key.text: assert hda["name"] in value.text name_found = True if "Format" in key.text: assert hda["extension"] in value.text format_found = True assert number_found assert name_found assert format_found job_outputs = self._table_to_key_value_elements("table#job-outputs") assert job_outputs[0][0].text == "environment_variables" generic_item = job_outputs[0][1] assert "1: environment_variables" in generic_item.text generic_item.click() self.sleep_for(self.wait_types.UX_RENDER) assert generic_item.find_element(By.CSS_SELECTOR, "pre").text == "42\nmoo\nNOTTHREE" generic_item.find_element(By.CSS_SELECTOR, "[title='Run Job Again']").click() self.components.tool_form.execute.wait_for_visible()
[docs] @selenium_test def test_drilldown_tool(self): self._open_drilldown_test_tool() # click first option in first drilldown component self.wait_for_and_click(self.components.tool_form.drilldown_expand) self.wait_for_and_click(self.components.tool_form.drilldown_option) # click select all in second drilldown component self.wait_for_and_click(self.components.tool_form.drilldown_select_all(parameter="dd_recurse")) self.tool_form_execute() self.history_panel_wait_for_hid_ok(1) # click hid 1 in history panel self.history_panel_click_item_title(hid=1) # assert that the dataset peek is d = a dd_recurse = a,b,c self.assert_item_peek_includes(1, "dd a") self.assert_item_peek_includes(1, "dd_recurse aa,aba,abb,ba,bba,bbb")
def _open_drilldown_test_tool(self): self.home() self.tool_open("drill_down")
[docs] @staticmethod def click_menu_item(menu, text): for element in menu.find_elements(By.CSS_SELECTOR, "a"): if element.text == text: return element.click()
def _table_to_key_value_elements(self, table_selector): tool_parameters_table = self.wait_for_selector_visible(table_selector) tbody_element = tool_parameters_table.find_element(By.CSS_SELECTOR, "tbody") trs = tbody_element.find_elements(By.CSS_SELECTOR, "tr") assert trs key_value_pairs = [] for tr in trs: tds = tr.find_elements(By.CSS_SELECTOR, "td") assert tds key_value_pairs.append((tds[0], tds[1])) return key_value_pairs
[docs] @selenium_test def test_repeat_reordering(self): self.home() self.tool_open("text_repeat") def assert_input_order(inputs: List[str]): for index, input in enumerate(inputs): parameter_input = self.components.tool_form.parameter_input(parameter=f"the_repeat_{index}|texttest") parameter_value = parameter_input.wait_for_value() assert parameter_value == input self.components.tool_form.repeat_insert.wait_for_and_click() self.tool_set_value("the_repeat_0|texttest", "Text A") self.components.tool_form.repeat_insert.wait_for_and_click() self.tool_set_value("the_repeat_1|texttest", "Text B") self.components.tool_form.repeat_insert.wait_for_and_click() self.tool_set_value("the_repeat_2|texttest", "Text C") assert_input_order(["Text A", "Text B", "Text C"]) self.components.tool_form.repeat_move_up(parameter="the_repeat_1").wait_for_and_click() assert_input_order(["Text B", "Text A", "Text C"]) self.components.tool_form.repeat_move_up(parameter="the_repeat_2").wait_for_and_click() assert_input_order(["Text B", "Text C", "Text A"]) self.components.tool_form.repeat_move_up(parameter="the_repeat_1").wait_for_and_click() assert_input_order(["Text C", "Text B", "Text A"]) self.components.tool_form.repeat_move_up(parameter="the_repeat_0").wait_for_and_click() assert_input_order(["Text C", "Text B", "Text A"]) self.tool_form_execute() self.history_panel_wait_for_hid_ok(1) details = list(map(lambda d: d.text, self._get_dataset_tool_parameters(1))) assert details == ["texttest", "Text C", "texttest", "Text B", "texttest", "Text A"]
[docs] @selenium_test def test_rerun(self): self._run_environment_test_tool() self.history_panel_wait_for_hid_ok(1) self.hda_click_primary_action_button(1, "rerun") def check_recorded_val(): inttest_div_element = self.tool_parameter_div("inttest") inttest_input_element = inttest_div_element.find_element(By.CSS_SELECTOR, "input") recorded_val = inttest_input_element.get_attribute("value") # Assert form re-rendered with correct value in textbox. assert recorded_val == "42", recorded_val # These form entries seem to be replaced/updated occasionally # causing stale elements. retry_call_during_transitions(check_recorded_val) self.tool_form_execute() self.history_panel_wait_for_hid_ok(2) self._check_dataset_details_for_inttest_value(2)
[docs] @selenium_test def test_rerun_deleted_dataset(self): # upload a first dataset that should not become selected on re-run test_path = self.get_filename("1.tabular") self.perform_upload(test_path) self.history_panel_wait_for_hid_ok(1) self.tool_open("column_param") self.select_set_value("#col", "3") self.tool_form_execute() self.history_panel_wait_for_hid_ok(2) # delete source dataset and click re-run on resulting dataset item = self.history_panel_item_component(hid=1) item.delete_button.wait_for_and_click() item = self.history_panel_item_component(hid=2) item.title.wait_for_and_click() item.rerun_button.wait_for_and_click() # validate initial warnings error_input1 = self.components.tool_form.parameter_error(parameter="input1").wait_for_visible() error_col = self.components.tool_form.parameter_error(parameter="col").wait_for_visible() assert ( error_input1.text == "parameter 'input1': the previously selected dataset has been deleted. Using default: ''." ) assert error_col.text == "parameter 'col': an invalid option ('3') was selected (valid options: 1)" # validate errors when inputs are missing self.components.tool_form.parameter_data_input_collection(parameter="input1").wait_for_and_click() self.sleep_for(self.wait_types.UX_TRANSITION) error_input1 = self.components.tool_form.parameter_error(parameter="input1").wait_for_visible() error_col = self.components.tool_form.parameter_error(parameter="col").wait_for_visible() error_col_names = self.components.tool_form.parameter_error(parameter="col_names").wait_for_visible() assert error_input1.text == "Please provide a value for this option." assert error_col.text == "parameter 'col': requires a value, but no legal values defined" assert error_col_names.text == "parameter 'col_names': requires a value, but no legal values defined" # validate warnings when inputs are restored self.components.tool_form.parameter_data_input_single(parameter="input1").wait_for_and_click() self.sleep_for(self.wait_types.UX_TRANSITION) error_input1 = self.components.tool_form.parameter_error(parameter="input1").wait_for_visible() error_col = self.components.tool_form.parameter_error(parameter="col").wait_for_visible() assert ( error_input1.text == "parameter 'input1': the previously selected dataset has been deleted. Using default: ''." ) assert error_col.text == "parameter 'col': an invalid option ('3') was selected (valid options: 1)"
[docs] @selenium_test def test_rerun_dataset_collection_element(self): # upload a first dataset that should not become selected on re-run test_path = self.get_filename("1.fasta") self.perform_upload(test_path) self.history_panel_wait_for_hid_ok(1) history_id = self.current_history_id() # upload a nested collection self.dataset_collection_populator.create_list_of_list_in_history( history_id, collection_type="list:list", wait=True, ).json()["id"] self.tool_open("identifier_multiple") self.components.tool_form.parameter_data_input_collection(parameter="input1").wait_for_and_click() self.sleep_for(self.wait_types.UX_RENDER) select_field = self.components.tool_form.parameter_data_select(parameter="input1") self.select_set_value(select_field, "list:list") self.sleep_for(self.wait_types.UX_RENDER) self.tool_form_execute() self.history_panel_wait_for_hid_ok(7) self.history_panel_expand_collection(7) self.sleep_for(self.wait_types.UX_RENDER) self.history_panel_click_item_title(1) self.sleep_for(self.wait_types.UX_RENDER) self.hda_click_primary_action_button(1, "rerun") self.sleep_for(self.wait_types.UX_RENDER) self.tool_form_execute() self.components.history_panel.collection_view.back_to_history.wait_for_and_click() self.history_panel_wait_for_hid_ok(9)
[docs] @selenium_test @flakey def test_run_data(self): test_path = self.get_filename("1.fasta") test_path_decoy = self.get_filename("1.txt") # Upload form posts bad data if executed two times in a row like this, so # wait between uploads. xref https://github.com/galaxyproject/galaxy/issues/5169 self.perform_upload(test_path) self.history_panel_wait_for_hid_ok(1) self.perform_upload(test_path_decoy) self.history_panel_wait_for_hid_ok(2) self.home() self.tool_open("head") self.tool_set_value("input", "1.fasta", expected_type="data") self.screenshot("tool_form_simple_data") self.tool_form_execute() self.history_panel_wait_for_hid_ok(3) latest_hda = self.latest_history_item() assert latest_hda["hid"] == 3 assert latest_hda["name"] == "Select first on data 1"
[docs] @selenium_test def test_bibtex_rendering(self): self.home() # prefetch citations so they will be available quickly when rendering tool form. citations_api = self.api_get("tools/bibtex/citations") citation_count = len(citations_api) self.tool_open("bibtex") self.components.tool_form.about.wait_for_and_click() @retry_assertion_during_transitions def assert_citations_visible(): references = self.components.tool_form.reference.all() if (references_rendered := len(references)) != citation_count: citations_api = self.api_get("tools/bibtex/citations") current_citation_count = len(citations_api) message = f"Expected {citation_count} references to be rendered, {references_rendered} actually rendered. Currently the API yields {current_citation_count} references" raise AssertionError(message) return references references = assert_citations_visible() doi_resolved_citation = references[0] assert "platform for interactive" in doi_resolved_citation.text self.screenshot("tool_form_citations_formatted")
def _check_dataset_details_for_inttest_value(self, hid, expected_value="42"): tds = self._get_dataset_tool_parameters(hid) assert tds assert any(expected_value in td.text for td in tds) def _get_dataset_tool_parameters(self, hid): self.hda_click_details(hid) self.components.dataset_details._.wait_for_visible() tool_parameters_table = self.components.dataset_details.tool_parameters.wait_for_visible() tbody_element = tool_parameters_table.find_element(By.CSS_SELECTOR, "tbody") tds = tbody_element.find_elements(By.CSS_SELECTOR, "td") return tds def _run_environment_test_tool(self, inttest_value="42"): self.home() self.tool_open("environment_variables") self.tool_set_value("inttest", inttest_value) self.tool_form_execute()
[docs]class TestLoggedInToolForm(SeleniumTestCase): ensure_registered = True
[docs] @selenium_test def test_dataset_state_filtering(self): # upload an ok (HID 1) and a discarded (HID 2) dataset and run a tool # normally HID 2 would be selected but since it is discarded - it won't # be an option so verify the result was run with HID 1. test_path = self.get_filename("1.fasta") self.perform_upload(test_path) self.history_panel_wait_for_hid_ok(1) history_id = self.current_history_id() self.dataset_populator.create_contents_from_store( history_id, store_dict=one_hda_model_store_dict(include_source=False), ) self.home() self.tool_open("head") self.components.tool_form.execute.wait_for_visible() self.screenshot("tool_form_with_filtered_discarded_input") self.tool_form_execute() self.history_panel_wait_for_hid_ok(3) latest_hda = self.latest_history_item() assert latest_hda["hid"] == 3 assert latest_hda["name"] == "Select first on data 1"
[docs] @selenium_test def test_run_apply_rules_1(self): self._apply_rules_and_check(rules_test_data.EXAMPLE_1) self.screenshot("tool_apply_rules_example_1_final")
[docs] @selenium_test def test_run_apply_rules_2(self): self._apply_rules_and_check(rules_test_data.EXAMPLE_2) self.screenshot("tool_apply_rules_example_2_final")
[docs] @selenium_test def test_run_apply_rules_3(self): self._apply_rules_and_check(rules_test_data.EXAMPLE_3) self.screenshot("tool_apply_rules_example_3_final")
[docs] @selenium_test def test_run_apply_rules_4(self): self._apply_rules_and_check(rules_test_data.EXAMPLE_4) self.screenshot("tool_apply_rules_example_4_final")
[docs] @selenium_test @managed_history @skip_if_github_down @pytest.mark.gtn_screenshot @pytest.mark.local def test_run_apply_rules_tutorial(self): self.home() self.upload_rule_start() self.upload_rule_set_data_type("Collections") self.components.upload.rule_source_content.wait_for_and_send_keys( """https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-data/rules/treated1fb.txt treated_single_1 https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-data/rules/treated2fb.txt treated_paired_2 https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-data/rules/treated3fb.txt treated_paired_3 https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-data/rules/untreated1fb.txt untreated_single_4 https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-data/rules/untreated2fb.txt untreated_single_5 https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-data/rules/untreated3fb.txt untreated_paired_6 https://raw.githubusercontent.com/jmchilton/galaxy/apply_rules_tutorials/test-data/rules/untreated4fb.txt untreated_paired_7 """ ) self.screenshot("rules_apply_rules_example_4_1_input_paste") self.upload_rule_build() rule_builder = self.components.rule_builder rule_builder._.wait_for_and_click() self.rule_builder_set_mapping("url", "A") self.rule_builder_set_mapping("list-identifiers", ["B"]) self.rule_builder_set_collection_name("flat_count_list") self.rule_builder_set_extension("txt") self.screenshot("rules_apply_rules_example_4_2_input_rules") rule_builder.main_button_ok.wait_for_and_click() self.history_panel_wait_for_hid_ok(1) self.screenshot("rules_apply_rules_example_4_3_input_ready") self.history_multi_view_display_collection_contents(1, "list") self.screenshot("rules_apply_rules_example_4_4_input_list") self.home() add_depth_rules = { "rules": [ { "type": "add_column_metadata", "value": "identifier0", }, {"type": "add_column_regex", "target_column": 0, "expression": "(.*)_(.*)_.*", "group_count": 2}, ], "mapping": [ { "type": "list_identifiers", "columns": [1, 2, 0], } ], } self._tool_apply_with_source( add_depth_rules, hid=1, landing_screenshot="rules_apply_rules_example_4_5_apply_rules_landing", rule_init_screenshot="rules_apply_rules_example_4_6_apply_rules_init_flat", rule_complete_screenshot="rules_apply_rules_example_4_7_apply_rules_add_depth", ) self.history_panel_wait_for_hid_ok(16) self.history_multi_view_display_collection_contents(16, "list:list:list") self.screenshot("rules_apply_rules_example_4_8_nested") self.home() invert_rules = { "rules": [ { "type": "add_column_metadata", "value": "identifier0", }, { "type": "add_column_metadata", "value": "identifier1", }, { "type": "add_column_metadata", "value": "identifier2", }, ], "mapping": [ { "type": "list_identifiers", "columns": [1, 0, 2], } ], } self._tool_apply_with_source( invert_rules, rule_init_screenshot="rules_apply_rules_example_4_9_apply_rules_init_nested", rule_complete_screenshot="rules_apply_rules_example_4_10_apply_rules_inverted", ) self.history_panel_wait_for_hid_ok(24) self.history_multi_view_display_collection_contents(24, "list:list:list") self.screenshot("rules_apply_rules_example_4_11_inverted") self.home() filter_rules = { "rules": [ { "type": "add_column_metadata", "value": "identifier0", }, { "type": "add_filter_regex", "target_column": 0, "expression": ".*_single_.*", "invert": False, }, ], "mapping": [ { "type": "list_identifiers", "columns": [0], } ], } self._tool_apply_with_source( filter_rules, hid=1, rule_complete_screenshot="rules_apply_rules_example_4_12_apply_rules_filter" ) self.history_panel_wait_for_hid_ok(28) self.history_multi_view_display_collection_contents(28, "list") self.screenshot("rules_apply_rules_example_4_13_filtered") self.home() filter_and_nest_rules = { "rules": [ { "type": "add_column_metadata", "value": "identifier0", }, { "type": "add_filter_regex", "target_column": 0, "expression": ".*_single_.*", "invert": False, }, {"type": "add_column_regex", "target_column": 0, "expression": "(.*)_single_.*", "group_count": 1}, ], "mapping": [ { "type": "list_identifiers", "columns": [1, 0], } ], } self._tool_apply_with_source( filter_and_nest_rules, hid=1, rule_complete_screenshot="rules_apply_rules_example_4_14_apply_rules_filtered_and_nested", ) self.history_panel_wait_for_hid_ok(32) self.history_multi_view_display_collection_contents(32, "list:list") self.screenshot("rules_apply_rules_example_4_15_filtered_and_nested")
def _apply_rules_and_check(self, example: Dict[str, Any]) -> None: rule_builder = self.components.rule_builder self.home() history_id = self.current_history_id() stage_rules_example(self.api_interactor_for_logged_in_user(), history_id, example) self.dataset_populator.wait_for_history(history_id) self.home() self._tool_open_apply_rules() self.screenshot("tool_apply_rules_landing") self.tool_parameter_edit_rules() rule_builder._.wait_for_visible() self.screenshot("tool_apply_rules_builder_landing") self.rule_builder_set_source(json.dumps(example["rules"])) self.screenshot("tool_apply_rules_after") rule_builder.main_button_ok.wait_for_and_click() self.tool_form_execute() output_hid = example["output_hid"] self.home() self.history_panel_wait_for_hid_ok(output_hid) output_hdca = self.dataset_populator.get_history_collection_details(history_id, hid=output_hid, wait=False) example["check"](output_hdca, self.dataset_populator) def _tool_apply_with_source( self, rules_json, hid=None, landing_screenshot=None, rule_init_screenshot=None, rule_complete_screenshot=None ): self._tool_open_apply_rules() if hid: self.tool_set_value("input", f"{hid}:", expected_type="data_collection") if landing_screenshot: self.screenshot(landing_screenshot) rule_builder = self.components.rule_builder self.tool_parameter_edit_rules() rule_builder._.wait_for_visible() if rule_init_screenshot: self.screenshot(rule_init_screenshot) self.rule_builder_set_source(json.dumps(rules_json)) if rule_complete_screenshot: self.screenshot(rule_complete_screenshot) rule_builder.main_button_ok.wait_for_and_click() self.tool_form_execute() def _tool_open_apply_rules(self): self.tool_open("__APPLY_RULES__", outer=True) # may appear twice in panel, grab top-level link