diff --git a/config/plugins/webhooks/gtn/script.js b/config/plugins/webhooks/gtn/script.js index 91d748ec617..7518ef30d82 100644 --- a/config/plugins/webhooks/gtn/script.js +++ b/config/plugins/webhooks/gtn/script.js @@ -1,8 +1,9 @@ -(function () { - var gtnWebhookLoaded = false; - var lastUpdate = 0; - var urlParams = new URLSearchParams(document.location.search); - var autoLoadTutorial = urlParams.get('autoload_gtn_tutorial') === null ? "" : urlParams.get('autoload_gtn_tutorial'); +(() => { + let gtnWebhookLoaded = false; + let lastUpdate = 0; + const urlParams = new URLSearchParams(document.location.search); + const autoLoadTutorial = + urlParams.get("autoload_gtn_tutorial") === null ? "" : urlParams.get("autoload_gtn_tutorial"); function removeOverlay() { const container = document.getElementById("gtn-container"); @@ -16,7 +17,7 @@ } function getIframeUrl() { - var loc; + let loc; try { loc = document.getElementById("gtn-embed").contentWindow.location.pathname; } catch (e) { @@ -26,7 +27,7 @@ } function getIframeScroll() { - var loc; + let loc; try { loc = parseInt(document.getElementById("gtn-embed").contentWindow.scrollY); } catch (e) { @@ -35,11 +36,9 @@ return loc; } - function restoreLocation() {} - function persistLocation() { // Don't save every scroll event. - var time = new Date().getTime(); + const time = new Date().getTime(); if (time - lastUpdate < 1000) { return; } @@ -48,7 +47,9 @@ } function addIframe() { - let url, message, onloadscroll; + let url; + let message; + let onloadscroll; gtnWebhookLoaded = true; let storedData = false; let safe = false; @@ -59,8 +60,7 @@ fetch("/training-material/") .then((response) => { if (!response.ok) { - url = - `https://training.galaxyproject.org/training-material/${autoLoadTutorial}?utm_source=webhook&utm_medium=noproxy&utm_campaign=gxy`; + url = `https://training.galaxyproject.org/training-material/${autoLoadTutorial}?utm_source=webhook&utm_medium=noproxy&utm_campaign=gxy`; message = ` Click to run unavailable. @@ -68,7 +68,7 @@ } else { safe = true; - var storedLocation = window.localStorage.getItem("gtn-in-galaxy"); + const storedLocation = window.localStorage.getItem("gtn-in-galaxy"); if ( storedLocation !== null && storedLocation.split(" ")[1] !== undefined && @@ -113,6 +113,7 @@ // Depends on the iframe being present document.getElementById("gtn-embed").addEventListener("load", () => { // Save our current location when possible + const gtnEmbed = document.getElementById("gtn-embed"); if (onloadscroll !== undefined) { document.getElementById("gtn-embed").contentWindow.scrollTo(0, parseInt(onloadscroll)); onloadscroll = undefined; @@ -121,26 +122,59 @@ if (safe) { persistLocation(); } - var gtn_tools = $("#gtn-embed").contents().find("span[data-tool]"); + // Add the class to the entire GTN page + document + .getElementById("gtn-embed") + .contentDocument.getElementsByTagName("body")[0] + .classList.add("galaxy-proxy-active"); + + const gtnToolElements = document + .getElementById("gtn-embed") + .contentDocument.querySelectorAll("span[data-tool]"); + // Buttonify - gtn_tools.addClass("galaxy-proxy-active"); + gtnToolElements.forEach(function (el) { + el.classList.add("galaxy-proxy-active"); + el.addEventListener("click", function (e) { + let target = e.target; - gtn_tools.click((e) => { - var target = e.target; + // Sometimes we get the i or the strong, not the parent. + if (e.target.tagName.toLowerCase() !== "span") { + target = e.target.parentElement; + } - // Sometimes we get the i or the strong, not the parent. - if (e.target.tagName.toLowerCase() !== "span") { - target = e.target.parentElement; - } + tool_id = target.dataset.tool; - tool_id = $(target).data("tool"); + if (tool_id === "upload1" || tool_id === "upload") { + document.getElementById("tool-panel-upload-button").click(); + } else { + Galaxy.router.push({ path: `/?tool_id=${encodeURIComponent(tool_id)}` }); + } + removeOverlay(); + }); + }); - if (tool_id === "upload1" || tool_id === "upload") { - document.getElementById("tool-panel-upload-button").click(); - } else { - Galaxy.router.push({ path: `/?tool_id=${encodeURIComponent(tool_id)}` }); - } - removeOverlay(); + const gtnWorkflowElements = document + .getElementById("gtn-embed") + .contentDocument.querySelectorAll("span[data-workflow]"); + + // Buttonify + gtnWorkflowElements.forEach(function (el) { + el.classList.add("galaxy-proxy-active"); + el.addEventListener("click", (e) => { + let target = e.target; + + // Sometimes we get the i or the strong, not the parent. + if (e.target.tagName.toLowerCase() !== "span") { + target = e.target.parentElement; + } + + trs_url = target.dataset.workflow; + Galaxy.router.push({ + path: `/workflows/trs_import?trs_url=${encodeURIComponent(trs_url)}&run_form=true`, + }); + removeOverlay(); + }); }); }); }); @@ -183,15 +217,15 @@ showOverlay(); } }); - if(autoLoadTutorial){ + if (autoLoadTutorial) { clean.click(); } }); // Remove the overlay on escape button click - document.addEventListener("keydown", (e) => { - // Check for escape button - "27" - if (e.which === 27 || e.keyCode === 27) { + document.addEventListener("keydown", (event) => { + // Check for escape button - "Escape" (modern browsers), "27" (old browsers) + if (event.key === "Escape" || event.keyCode === 27) { removeOverlay(); } }); diff --git a/lib/galaxy/selenium/navigates_galaxy.py b/lib/galaxy/selenium/navigates_galaxy.py index 264e87890cf..d5460312a15 100644 --- a/lib/galaxy/selenium/navigates_galaxy.py +++ b/lib/galaxy/selenium/navigates_galaxy.py @@ -1998,6 +1998,11 @@ class NavigatesGalaxy(HasDriver): self.wait_for_xpath_visible(xpath) self.screenshot_if(screenshot_after_submit) + def tutorial_mode_activate(self): + search_selector = "#gtn a" + self.wait_for_and_click_selector(search_selector) + self.wait_for_selector_visible("#gtn-screen") + class NotLoggedInException(SeleniumTimeoutException): def __init__(self, timeout_exception, user_info, dom_message): diff --git a/lib/galaxy_test/api/test_webhooks.py b/lib/galaxy_test/api/test_webhooks.py index 8c5cb9b8419..e640baffc17 100644 --- a/lib/galaxy_test/api/test_webhooks.py +++ b/lib/galaxy_test/api/test_webhooks.py @@ -11,7 +11,15 @@ class TestWebhooksApi(ApiTestCase): self._assert_status_code_is(response, 200) webhook_objs = self._assert_are_webhooks(response) ids = self._get_webhook_ids(webhook_objs) - for expected_id in ["history_test1", "history_test2", "masthead_test", "phdcomics", "trans_object", "xkcd"]: + for expected_id in [ + "history_test1", + "history_test2", + "masthead_test", + "phdcomics", + "trans_object", + "xkcd", + "gtn", + ]: assert expected_id in ids def test_get_data(self): diff --git a/lib/galaxy_test/selenium/test_tutorial_mode.py b/lib/galaxy_test/selenium/test_tutorial_mode.py new file mode 100644 index 00000000000..11dd08d2e4b --- /dev/null +++ b/lib/galaxy_test/selenium/test_tutorial_mode.py @@ -0,0 +1,33 @@ +from unittest import SkipTest + +import pytest + +from .framework import ( + selenium_test, + SeleniumTestCase, +) + + +class TestTutorialMode(SeleniumTestCase): + @selenium_test + @pytest.mark.gtn_screenshot + def test_activate_tutorial_mode(self): + self._ensure_tutorial_mode_available() + self.home() + self.screenshot("tutorial_mode_0_0") + self.tutorial_mode_activate() + self.screenshot("tutorial_mode_0_1") + + # Access inside the frame + self.driver.switch_to.frame("gtn-embed") + self.wait_for_selector_visible("#top-navbar") + self.screenshot("tutorial_mode_0_2") + + def _ensure_tutorial_mode_available(self): + """Skip a test if the webhook GTN doesn't appear.""" + response = self.api_get("webhooks", raw=True) + assert response.status_code == 200 + data = response.json() + webhooks = [x["id"] for x in data] + if "gtn" not in webhooks: + raise SkipTest('Skipping test, webhook "GTN Tutorial Mode" doesn\'t appear to be configured.') diff --git a/test/functional/webhooks/gtn b/test/functional/webhooks/gtn new file mode 120000 index 00000000000..ebc09166db5 --- /dev/null +++ b/test/functional/webhooks/gtn @@ -0,0 +1 @@ +../../../config/plugins/webhooks/gtn \ No newline at end of file