Skip to content

Commit

Permalink
Merge pull request #11152 from jmchilton/history_import_export_tests
Browse files Browse the repository at this point in the history
[21.01] Selenium tests for 21.01 history import and export UIs.
  • Loading branch information
mvdbeek authored Jan 18, 2021
2 parents bc5e453 + 53b9d35 commit afcb949
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 32 deletions.
3 changes: 2 additions & 1 deletion client/src/components/FilesDialog/FilesInput.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<b-form-input v-model="localValue" :placeholder="placeholder" @click="selectFile"> </b-form-input>
<b-form-input class="directory-form-input" v-model="localValue" :placeholder="placeholder" @click="selectFile">
</b-form-input>
</template>

<script>
Expand Down
7 changes: 4 additions & 3 deletions client/src/components/HistoryExport/ExportLink.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
<template>
<span>
<b
><a :href="link">{{ link }}</a></b
><a class="generated-export-link" :href="link">{{ link }}</a></b
>
<font-awesome-icon
v-b-tooltip.hover
title="Copy export URL to your clipboard"
class="copy-export-link"
icon="link"
style="cursor: pointer;"
@click="copyUrl"
/>
<i
title="Information about when the history export was generated is included in the job details. Additionally, if there are issues with export, the job details may help figure out the underlying problem or communicate issues to your Galaxy administrator."
>
(<a href="#" @click="showDetails">view job details</a>)
(<a class="show-job-link" href="#" @click="showDetails">view job details</a>)
</i>
<b-modal v-model="details" scrollable ok-only>
<b-modal v-model="details" modal-class="job-information-modal" scrollable ok-only hide-header>
<job-information :job_id="historyExport.job_id" :include-times="true" />
</b-modal>
</span>
Expand Down
10 changes: 6 additions & 4 deletions client/src/components/HistoryExport/Index.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
<template>
<span>
<span class="history-export-component">
<h2>Export history archive</h2>
<span v-if="initializing">
<loading-span message="Loading server configuration." />
</span>
<span v-else-if="hasWritableFileSources">
<b-card no-body>
<b-tabs pills card vertical>
<b-tab title="to a link" active>
<b-tab title="to a link" title-link-class="tab-export-to-link" active>
<b-card-text>
<ToLink :history-id="historyId" />
</b-card-text>
</b-tab>
<b-tab title="to a remote file">
<ToRemoteFile :history-id="historyId" />
<b-tab title="to a remote file" title-link-class="tab-export-to-file">
<b-card-text>
<ToRemoteFile :history-id="historyId" />
</b-card-text>
</b-tab>
</b-tabs>
</b-card>
Expand Down
8 changes: 4 additions & 4 deletions client/src/components/HistoryExport/ToRemoteFile.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div>
<div class="export-to-remote-file">
<b-alert v-if="errorMessage" show variant="danger" dismissible @dismissed="errorMessage = null">
{{ errorMessage }}
<JobError
Expand All @@ -20,14 +20,14 @@
</div>
<div v-else>
<b-form-group
id="directory"
id="fieldset-directory"
label-for="directory"
description="Select a 'remote files' directory to export history archive to."
class="mt-3"
>
<files-input v-model="directory" mode="directory" :requireWritable="true" />
<files-input id="directory" v-model="directory" mode="directory" :requireWritable="true" />
</b-form-group>
<b-form-group id="name" label-for="name" description="Give the exported file a name." class="mt-3">
<b-form-group id="fieldset-name" label-for="name" description="Give the exported file a name." class="mt-3">
<b-form-input id="name" v-model="name" placeholder="Name" required></b-form-input>
</b-form-group>
<b-row align-h="end">
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/HistoryImport.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<b-card title="Import a history from an archive">
<b-card body-class="history-import-component" title="Import a history from an archive">
<b-alert v-if="errorMessage" variant="danger" dismissible @dismissed="errorMessage = null" show>
{{ errorMessage }}
<JobError
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/JobInformation/JobError.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</div>
<!-- TODO: modal for reporting error. -->
</b-card-text>
<b-modal v-model="showInfo" scrollable ok-only>
<b-modal v-model="showInfo" modal-class="job-information-modal" scrollable ok-only hide-header>
<job-information :job_id="job.id" :include-times="true" />
</b-modal>
</b-card>
Expand Down
38 changes: 36 additions & 2 deletions lib/galaxy/selenium/navigates_galaxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,14 +517,24 @@ def click_center(self):
center_element = self.driver.find_element_by_css_selector("#center")
action_chains.move_to_element(center_element).click().perform()

def perform_upload(self, test_path, ext=None, genome=None, ext_all=None, genome_all=None):
def perform_upload(self, test_path, **kwd):
self._perform_upload(test_path=test_path, **kwd)

def perform_upload_of_pasted_content(self, paste_data, **kwd):
self._perform_upload(paste_data=paste_data, **kwd)

def _perform_upload(self, test_path=None, paste_data=None, ext=None, genome=None, ext_all=None, genome_all=None):
self.home()
self.upload_start_click()

self.upload_set_footer_extension(ext_all)
self.upload_set_footer_genome(genome_all)

self.upload_queue_local_file(test_path)
if test_path:
self.upload_queue_local_file(test_path)
else:
assert paste_data is not None
self.upload_paste_data(paste_data)

if ext is not None:
self.wait_for_selector_visible('.upload-extension')
Expand Down Expand Up @@ -635,6 +645,13 @@ def upload_queue_local_file(self, test_path, tab_id="regular"):
file_upload = self.wait_for_selector('div#%s input[type="file"]' % tab_id)
file_upload.send_keys(test_path)

def upload_paste_data(self, pasted_content, tab_id="regular"):
tab_locator = f"div#{tab_id}"
self.wait_for_and_click_selector(f"{tab_locator} button#btn-new")

textarea = self.wait_for_selector(f"{tab_locator} .upload-text-content")
textarea.send_keys(pasted_content)

def upload_rule_start(self):
self.upload_start_click()
self.upload_tab_click("rule-based")
Expand Down Expand Up @@ -865,6 +882,11 @@ def workflow_editor_click_save(self):
self.wait_for_and_click_selector("#workflow-save-button")
self.sleep_for(self.wait_types.DATABASE_OPERATION)

def navigate_to_histories_page(self):
self.home()
self.click_masthead_user()
self.components.masthead.histories.wait_for_and_click()

def navigate_to_user_preferences(self):
self.home()
self.click_masthead_user()
Expand Down Expand Up @@ -1164,6 +1186,18 @@ def histories_click_advanced_search(self):
search_selector = '#standard-search .advanced-search-toggle'
self.wait_for_and_click_selector(search_selector)

@retry_during_transitions
def histories_get_history_names(self):
self.sleep_for(self.wait_types.UX_RENDER)
names = []
grid = self.wait_for_selector('#grid-table-body')
for row in grid.find_elements_by_tag_name('tr'):
td = row.find_elements_by_tag_name('td')
name = td[1].text if td[0].text == '' else td[0].text
if name != "No items" and not name.startswith("No matching entries found"):
names.append(name)
return names

def history_panel_add_tags(self, tags):
tag_icon_selector = self.components.history_panel.tag_icon
tag_area_selector = self.components.history_panel.tag_area
Expand Down
33 changes: 33 additions & 0 deletions lib/galaxy/selenium/navigation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ history_panel:
options_show_history_structure:
type: xpath
selector: '//a[text()="Show Structure"]'
options_show_export_history_to_file:
type: xpath
selector: '//a[text()="Export History to File"]'
new_history_button: '#history-new-button'
multi_view_button: '#history-view-multi-button'

Expand Down Expand Up @@ -282,6 +285,9 @@ collection_builders:
reverse_datasets: ".reverse-column .column-datasets"

histories:
labels:
import_button: 'Import from file'

sharing:
selectors:
unshare_user_button: '.unshare_user'
Expand All @@ -291,6 +297,33 @@ histories:
labels:
unshare: 'Unshare'

files_dialog:
selectors:
ftp_row: 'span[title="gxftp://"]'
row: 'span[title="${uri}"]'

history_export:
selectors:
export_link: '.export-link'
running: '.history-export-component .loading-icon'
generated_export_link: '.generated-export-link'
copy_export_link: '.copy-export-link'
show_job_link: '.show-job-link'
job_table: '.info_data_table'
job_table_ok: '.job-information-modal .btn-primary'
tab_export_to_file: '.tab-export-to-file'
directory_input: '.directory-form-input'
name_input: '.export-to-remote-file #name'
export_button: '.export-button'
success_message: '.history-export-component .alert-success'

history_import:
selectors:
radio_button_remote_files: '.history-import-component .fa-folder-open'
import_button: '.import-button'
running: '.history-import-component .loading-icon'
success_message: '.history-import-component .alert-success'

pages:
selectors:
create: '.manage-table-actions .action-button'
Expand Down
17 changes: 1 addition & 16 deletions lib/galaxy_test/selenium/test_histories_list.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from .framework import (
retry_assertion_during_transitions,
retry_during_transitions,
selenium_test,
SharedStateSeleniumTestCase,
)
Expand Down Expand Up @@ -251,17 +250,8 @@ def assert_histories_in_grid(self, expected_histories, present=True):
else:
self.assertEqual(intersection, set())

@retry_during_transitions
def get_histories(self):
self.sleep_for(self.wait_types.UX_RENDER)
names = []
grid = self.wait_for_selector('#grid-table-body')
for row in grid.find_elements_by_tag_name('tr'):
td = row.find_elements_by_tag_name('td')
name = td[1].text if td[0].text == '' else td[0].text
if name != "No items" and not name.startswith("No matching entries found"):
names.append(name)
return names
return self.histories_get_history_names()

def set_filter(self, selector, value):
filter_input = self.wait_for_selector_clickable(selector)
Expand All @@ -275,11 +265,6 @@ def unset_filter(self, filter_key, filter_value):
self.wait_for_and_click_selector(close_button_selector)
self.sleep_for(self.wait_types.UX_RENDER)

def navigate_to_histories_page(self):
self.home()
self.click_masthead_user() # Open masthead menu
self.components.masthead.histories.wait_for_and_click()

def setup_shared_state(self):
SavedHistoriesTestCase.user_email = self._get_random_email()
SavedHistoriesTestCase.history1_name = self._get_random_name()
Expand Down
44 changes: 44 additions & 0 deletions lib/galaxy_test/selenium/test_history_export.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from .framework import (
selenium_test,
SeleniumTestCase
)


class HistoryExportTestCase(SeleniumTestCase):
ensure_registered = True

@selenium_test
def test_history_export(self):
gx_selenium_context = self
gx_selenium_context.perform_upload_of_pasted_content("my cool content")
gx_selenium_context.history_panel_wait_for_hid_ok(1)
gx_selenium_context.click_history_options()
gx_selenium_context.components.history_panel.options_show_export_history_to_file.wait_for_and_click()
history_export = gx_selenium_context.components.history_export
history_export.export_link.wait_for_and_click()
history_export.running.wait_for_visible()
history_export.running.wait_for_absent(wait_type=gx_selenium_context.wait_types.JOB_COMPLETION)
history_export.generated_export_link.wait_for_visible()
history_export.copy_export_link.wait_for_visible()
history_export.job_table.assert_absent_or_hidden()
history_export.show_job_link.wait_for_and_click()
history_export.job_table.wait_for_present()
history_export.job_table_ok.wait_for_and_click()
history_export.job_table.wait_for_absent()

gx_selenium_context.click_history_options()
gx_selenium_context.components.history_panel.options_show_export_history_to_file.wait_for_and_click()

# this time the exported link is still there
history_export.generated_export_link.wait_for_visible()
history_export.export_link.assert_absent()

gx_selenium_context.perform_upload_of_pasted_content("my cool content part 2")
gx_selenium_context.history_panel_wait_for_hid_ok(2)

gx_selenium_context.click_history_options()
gx_selenium_context.components.history_panel.options_show_export_history_to_file.wait_for_and_click()

# now we have a generated link and a link to update to the newest export
history_export.generated_export_link.wait_for_visible()
history_export.export_link.wait_for_visible()
65 changes: 65 additions & 0 deletions test/integration_selenium/test_history_import_export_ftp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import os

from .framework import (
selenium_test,
SeleniumIntegrationTestCase
)


class HistoryImportExportFtpSeleniumIntegrationTestCase(SeleniumIntegrationTestCase):
ensure_registered = True

@classmethod
def handle_galaxy_config_kwds(cls, config):
ftp_dir = cls.ftp_dir()
os.makedirs(ftp_dir)
config["ftp_upload_dir"] = ftp_dir
config["ftp_upload_site"] = "ftp://ftp.galaxyproject.com"

@classmethod
def ftp_dir(cls):
return cls.temp_config_dir("ftp")

@selenium_test
def test_history_import_export(self):
email = self.get_logged_in_user()["email"]
user_ftp_dir = os.path.join(self.ftp_dir(), email)
os.makedirs(user_ftp_dir)

gx_selenium_context = self
gx_selenium_context.perform_upload_of_pasted_content("my cool content")
gx_selenium_context.history_panel_wait_for_hid_ok(1)
gx_selenium_context.click_history_options()
gx_selenium_context.components.history_panel.options_show_export_history_to_file.wait_for_and_click()
history_export = gx_selenium_context.components.history_export
files_dialog = gx_selenium_context.components.files_dialog

# we land on link version, but go to export to file
history_export.export_link.wait_for_visible()
history_export.tab_export_to_file.wait_for_and_click()
history_export.export_link.wait_for_absent_or_hidden()
history_export.directory_input.wait_for_and_click()
files_dialog.ftp_row.wait_for_and_click()
history_export.name_input.wait_for_and_send_keys("my_export.tar.gz")
history_export.export_button.wait_for_and_click()

history_export.running.wait_for_visible()
history_export.running.wait_for_absent(wait_type=gx_selenium_context.wait_types.JOB_COMPLETION)
history_export.success_message.wait_for_visible()

gx_selenium_context.navigate_to_histories_page()
gx_selenium_context.components.histories.import_button.wait_for_and_click()
history_import = gx_selenium_context.components.history_import
history_import.radio_button_remote_files.wait_for_and_click()
files_dialog.ftp_row.wait_for_and_click()
files_dialog.row(uri="gxftp://my_export.tar.gz").wait_for_and_click()

history_import.import_button.wait_for_and_click()

history_import.running.wait_for_visible()
history_import.running.wait_for_absent(wait_type=gx_selenium_context.wait_types.JOB_COMPLETION)
history_import.success_message.wait_for_visible()

gx_selenium_context.navigate_to_histories_page()
newest_history_name = gx_selenium_context.histories_get_history_names()[0]
assert newest_history_name.startswith("imported from archive")

0 comments on commit afcb949

Please sign in to comment.