Skip to content

Commit e90dd68

Browse files
committed
Selenium test cases for IGV.
1 parent c0f34bc commit e90dd68

File tree

8 files changed

+122
-25
lines changed

8 files changed

+122
-25
lines changed

client/src/components/Panels/ActivityPanel.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ interface Props {
66
title: string;
77
goToAllTitle?: string;
88
href?: string;
9+
goToAllDataDescription?: string;
910
}
1011
1112
const props = withDefaults(defineProps<Props>(), {
1213
goToAllTitle: undefined,
1314
href: undefined,
15+
goToAllDataDescription: undefined,
1416
});
1517
1618
const emit = defineEmits(["goToAll"]);
@@ -38,7 +40,7 @@ const hasGoToAll = computed(() => props.goToAllTitle && props.href);
3840
v-if="hasGoToAll"
3941
class="activity-panel-footer"
4042
variant="primary"
41-
:data-description="`props.mainButtonText button`"
43+
:data-description="goToAllDataDescription"
4244
:to="props.href"
4345
size="sm"
4446
@click="emit('goToAll')">

client/src/components/Visualizations/VisualizationPanel.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ onMounted(() => {
9595
:is="props.datasetId ? 'div' : ActivityPanel"
9696
title="Visualizations"
9797
:go-to-all-title="datasetId ? undefined : 'Saved Visualizations'"
98+
go-to-all-data-description="visualizations show list"
9899
href="/visualizations/list">
99100
<template v-slot:header>
100101
<DelayedInput :delay="100" class="my-2" placeholder="search visualizations" @change="query = $event" />

client/src/utils/navigation/navigation.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,16 @@ visualization:
697697
selectors:
698698
activity: '#activity-visualizations'
699699
matched_plugin: '#center [data-plugin-name*="${id}"]'
700+
show_all_button: '[data-description="visualizations show list"]'
701+
702+
igv:
703+
selectors:
704+
_: ".igv-container"
705+
shadow_host: '#app .grid .overflow-hidden .overflow-auto div'
706+
current_genome: '.igv-current-genome'
707+
settings_button: button.n-button
708+
save_button: '[data-description="sidepanel save button"]'
709+
name_input: '.n-input__input input'
700710

701711
trs_search:
702712
selectors:

lib/galaxy/selenium/has_driver.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,12 @@ def send_escape(self, element: Optional[WebElement] = None):
244244
def send_backspace(self, element: Optional[WebElement] = None):
245245
self._send_key(Keys.BACKSPACE, element)
246246

247+
def aggressive_clear(self, element: WebElement) -> None:
248+
# for when a simple .clear() doesn't work
249+
self.driver.execute_script("arguments[0].value = '';", element)
250+
for _ in range(25):
251+
element.send_keys(Keys.BACKSPACE)
252+
247253
def _send_key(self, key: str, element: Optional[WebElement] = None):
248254
if element is None:
249255
self.action_chains().send_keys(key)

lib/galaxy/selenium/navigates_galaxy.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class WAIT_TYPES:
8383
# Creating a new history and loading it into the panel.
8484
DATABASE_OPERATION = WaitType("database_operation", 10)
8585
# Wait time for jobs to complete in default environment.
86-
JOB_COMPLETION = WaitType("job_completion", 30)
86+
JOB_COMPLETION = WaitType("job_completion", 45)
8787
# Wait time for a GIE to spawn.
8888
GIE_SPAWN = WaitType("gie_spawn", 30)
8989
# Wait time for toolshed search
@@ -669,6 +669,15 @@ def select_history_card_operation(self, card_name, action_selector, is_in_extra=
669669
action_selector = target_card.find_element(By.CSS_SELECTOR, action_selector)
670670
action_chains.move_to_element(action_selector).click().perform()
671671

672+
def edit_dataset_dbkey(self, dbkey_text):
673+
# precondition: need to be on the dataset edit component
674+
self.components.edit_dataset_attributes.dbkey_dropdown.wait_for_and_click()
675+
# choose database option from 'Database/Build' dropdown, that equals to dbkey_text
676+
self.components.edit_dataset_attributes.dbkey_dropdown_results.dbkey_dropdown_option(
677+
dbkey_text=dbkey_text
678+
).wait_for_and_click()
679+
self.components.edit_dataset_attributes.save_button.wait_for_and_click()
680+
672681
def get_history_card(self, card_name):
673682
card_list = self.components.histories.history_cards.all()
674683
for card in card_list:
@@ -1478,6 +1487,12 @@ def navigate_to_histories_page(self):
14781487
self.components.histories.activity.wait_for_and_click()
14791488
self.components.histories.history_cards.wait_for_present()
14801489

1490+
def navigate_to_saved_visualizations(self):
1491+
self.home()
1492+
visualizations = self.components.visualization
1493+
visualizations.activity.wait_for_and_click()
1494+
visualizations.show_all_button.wait_for_and_click()
1495+
14811496
def navigate_to_histories_shared_with_me_page(self):
14821497
self.home()
14831498
self.components.histories.activity.wait_for_and_click()
@@ -2111,7 +2126,7 @@ def history_panel_add_tags(self, tags):
21112126
def history_panel_rename(self, new_name):
21122127
editable_text_input_element = self.history_panel_name_input()
21132128
# a simple .clear() doesn't work here since we perform a .blur because of that
2114-
self.driver.execute_script("arguments[0].value = '';", editable_text_input_element)
2129+
self.aggressive_clear(editable_text_input_element)
21152130
editable_text_input_element.send_keys(new_name)
21162131
editable_text_input_element.send_keys(self.keys.ENTER)
21172132
return editable_text_input_element
@@ -2200,6 +2215,12 @@ def show_dataset_visualizations(self, hid):
22002215
)
22012216
visualize_tab_button.click()
22022217

2218+
def show_dataset_visualization(self, hid: int, visualization_id: str, screenshot_name: Optional[str] = None):
2219+
self.show_dataset_visualizations(hid)
2220+
self.components.visualization.matched_plugin(id=visualization_id).wait_for_visible()
2221+
self.screenshot_if(screenshot_name)
2222+
self.components.visualization.matched_plugin(id=visualization_id).wait_for_and_click()
2223+
22032224
def history_panel_item_view_dataset_details(self, hid):
22042225
self.display_dataset(hid)
22052226
self.show_dataset_details(hid)
@@ -2278,7 +2299,9 @@ def history_panel_click_item_title(self, hid, **kwds):
22782299

22792300
def history_panel_ensure_showing_item_details(self, hid):
22802301
if not self.history_panel_item_showing_details(hid):
2281-
self.history_panel_click_item_title(hid=hid, wait=True)
2302+
return self.history_panel_click_item_title(hid=hid, wait=True)
2303+
else:
2304+
return self.history_panel_item_component(hid=hid)
22822305

22832306
def history_panel_item_showing_details(self, hid):
22842307
item_component = self.history_panel_item_component(hid=hid)

lib/galaxy/selenium/smart_components.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,11 @@ def wait_for_and_clear_and_send_keys(self, *text):
148148
dom_element.clear()
149149
dom_element.send_keys(*text)
150150

151+
def wait_for_and_clear_aggressive_and_send_keys(self, *text):
152+
dom_element = self.wait_for_visible()
153+
self._has_driver.aggressive_clear(dom_element)
154+
dom_element.send_keys(*text)
155+
151156
def axe_eval(self) -> AxeResults:
152157
return self._has_driver.axe_eval(context=self._target.element_locator[1])
153158

lib/galaxy_test/selenium/test_history_dataset_state.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,7 @@ def test_dataset_change_dbkey(self):
4949
item.dbkey.wait_for_and_click()
5050
self.sleep_for(self.wait_types.UX_RENDER)
5151
self.screenshot("history_panel_edit_dbkey_post_click")
52-
self.components.edit_dataset_attributes.dbkey_dropdown.wait_for_and_click()
53-
# choose database option from 'Database/Build' dropdown, that equals to dbkey_text
54-
self.components.edit_dataset_attributes.dbkey_dropdown_results.dbkey_dropdown_option(
55-
dbkey_text=TEST_DBKEY_TEXT
56-
).wait_for_and_click()
57-
self.components.edit_dataset_attributes.save_button.wait_for_and_click()
52+
self.edit_dataset_dbkey(TEST_DBKEY_TEXT)
5853
self.sleep_for(self.wait_types.JOB_COMPLETION)
5954
self.history_panel_wait_for_hid_ok(FIRST_HID)
6055
self.assert_item_dbkey_displayed_as(FIRST_HID, "apiMel3")

lib/galaxy_test/selenium/test_visualizations.py

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
skip_without_visualization_plugin,
44
)
55
from .framework import (
6+
managed_history,
67
selenium_test,
78
SeleniumTestCase,
89
)
910

11+
IGV_DEFAULT_GENOME = "hg38"
12+
HG18_DBKEY_TEXT = "Human Mar. 2006 (NCBI36/hg18) (hg18)"
1013

11-
class TestVisualizations(SeleniumTestCase):
14+
15+
class TestVisualizationsAnonymous(SeleniumTestCase):
1216

1317
@skip_without_datatype("png")
1418
@skip_without_visualization_plugin("annotate_image")
@@ -17,11 +21,10 @@ def test_charts_image_annotate(self):
1721
hid = 1
1822
self.perform_upload(self.get_filename("454Score.png"))
1923
self.history_panel_wait_for_hid_state(hid, state="ok")
20-
self.show_dataset_visualizations(hid)
2124

22-
self.components.visualization.matched_plugin(id="annotate_image").wait_for_visible()
23-
self.screenshot("visualization_plugins_png")
24-
self.components.visualization.matched_plugin(id="annotate_image").wait_for_and_click()
25+
self.show_dataset_visualization(
26+
hid, visualization_id="annotate_image", screenshot_name="visualization_plugins_png"
27+
)
2528

2629
with self.visualization_panel():
2730
self.wait_for_selector("#image-annotate")
@@ -33,11 +36,9 @@ def test_charts_tabulator(self):
3336
hid = 1
3437
self.perform_upload(self.get_filename("1.tabular"))
3538
self.history_panel_wait_for_hid_state(hid, state="ok")
36-
self.show_dataset_visualizations(hid)
37-
38-
self.components.visualization.matched_plugin(id="tabulator").wait_for_visible()
39-
self.screenshot("visualization_plugins_tabulator")
40-
self.components.visualization.matched_plugin(id="tabulator").wait_for_and_click()
39+
self.show_dataset_visualization(
40+
hid, visualization_id="tabulator", screenshot_name="visualization_plugins_tabulator"
41+
)
4142

4243
with self.visualization_panel():
4344
self.wait_for_selector(".tabulator-table")
@@ -49,13 +50,67 @@ def test_charts_h5web(self):
4950
hid = 1
5051
self.perform_upload(self.get_filename("chopper.h5"))
5152
self.history_panel_wait_for_hid_state(hid, state="ok")
52-
self.show_dataset_visualizations(hid)
53-
54-
self.components.visualization.matched_plugin(id="h5web").wait_for_visible()
55-
self.screenshot("visualization_plugins_h5")
56-
self.components.visualization.matched_plugin(id="h5web").wait_for_and_click()
53+
self.show_dataset_visualization(hid, visualization_id="h5web", screenshot_name="visualization_plugins_h5")
5754

5855
with self.visualization_panel():
5956
# Look for the h5web-explorer-tree identifier to verify it loads.
6057
self.wait_for_selector("#h5web-explorer-tree")
6158
self.screenshot("visualization_plugin_charts_h5web_landing")
59+
60+
61+
class TestVisualizations(SeleniumTestCase):
62+
ensure_registered = True
63+
64+
@selenium_test
65+
@managed_history
66+
@skip_without_visualization_plugin("igv")
67+
def test_igv_loads_correct_genome(self):
68+
hid = 1
69+
self.perform_upload(self.get_filename("1.bed"))
70+
self.history_panel_wait_for_hid_state(hid, state="ok")
71+
self.show_dataset_visualization(hid, visualization_id="igv", screenshot_name="visualization_plugins_igv")
72+
73+
with self.visualization_panel():
74+
self._wait_for_igv_container()
75+
self.screenshot("visualization_plugin_igv_landing_default_genome")
76+
current_genome_text = self._igv_current_genome()
77+
assert IGV_DEFAULT_GENOME in current_genome_text
78+
79+
dataset_component = self.history_panel_ensure_showing_item_details(hid)
80+
dataset_component.dbkey.wait_for_and_click()
81+
self.edit_dataset_dbkey(HG18_DBKEY_TEXT)
82+
83+
self.show_dataset_visualization(hid, visualization_id="igv")
84+
85+
with self.visualization_panel():
86+
self._wait_for_igv_container()
87+
current_genome_text = self._igv_current_genome()
88+
self.screenshot("visualization_plugin_igv_landing_genome_from_dbkey_apimel3")
89+
assert "hg18" in current_genome_text
90+
91+
igv = self.components.igv
92+
igv.save_button.assert_absent_or_hidden()
93+
igv.settings_button.wait_for_and_click()
94+
self.sleep_for(self.wait_types.UX_TRANSITION)
95+
igv.name_input.wait_for_and_clear_aggressive_and_send_keys("igv with hg18")
96+
igv.save_button.wait_for_and_click()
97+
self.sleep_for(self.wait_types.UX_TRANSITION)
98+
99+
self.navigate_to_saved_visualizations()
100+
101+
def _igv_current_genome(self):
102+
igv = self.components.igv
103+
element = igv.shadow_host.wait_for_present()
104+
shadow_root = element.shadow_root
105+
igv_current_genome = self.navigation.igv.selectors.current_genome
106+
current_genome_element = shadow_root.find_element(*igv_current_genome.component_locator)
107+
return current_genome_element.text
108+
109+
def _wait_for_igv_container(self):
110+
igv = self.components.igv
111+
self.sleep_for(self.wait_types.UX_TRANSITION)
112+
element = igv.shadow_host.wait_for_present()
113+
shadow_root = element.shadow_root
114+
115+
igv_root_container = self.navigation.igv.selectors._
116+
shadow_root.find_element(*igv_root_container.component_locator)

0 commit comments

Comments
 (0)