{{ successMessage }}
@@ -16,7 +16,12 @@
@mouseover="onMouseOver(item)"
@focusout="onMouseLeave(item)"
@mouseleave="onMouseLeave(item)">
-
+
{{ item.stepLabel }}: {{ item.warningLabel }}
@@ -37,6 +42,8 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import BootstrapVue from "bootstrap-vue";
import Vue from "vue";
+import { dataAttributes } from "./modules/linting";
+
Vue.use(BootstrapVue);
library.add(faMagic);
@@ -80,6 +87,7 @@ export default {
},
},
methods: {
+ dataAttributes: dataAttributes,
onMouseOver(id) {
this.$emit("onMouseOver", id);
},
diff --git a/client/src/components/Workflow/Editor/modules/linting.ts b/client/src/components/Workflow/Editor/modules/linting.ts
index 75a7c142ab43..43aa4c899141 100644
--- a/client/src/components/Workflow/Editor/modules/linting.ts
+++ b/client/src/components/Workflow/Editor/modules/linting.ts
@@ -13,6 +13,7 @@ interface LintState {
name?: string;
inputName?: string;
autofix?: boolean;
+ data?: Record;
}
export const bestPracticeWarningAnnotation =
@@ -57,18 +58,27 @@ export function getMissingMetadata(steps: Steps) {
const noAnnotation = !step.annotation;
const noLabel = !step.label;
let warningLabel = null;
+ const data = {
+ "missing-label": "false",
+ "missing-annotation": "false",
+ };
if (noLabel && noAnnotation) {
warningLabel = "Missing a label and annotation";
+ data["missing-label"] = "true";
+ data["missing-annotation"] = "true";
} else if (noLabel) {
warningLabel = "Missing a label";
+ data["missing-label"] = "true";
} else if (noAnnotation) {
warningLabel = "Missing an annotation";
+ data["missing-annotation"] = "true";
}
if (warningLabel) {
inputs.push({
stepId: step.id,
stepLabel: step.label || step.content_id || step.name,
warningLabel: warningLabel,
+ data: data,
});
}
}
@@ -76,6 +86,15 @@ export function getMissingMetadata(steps: Steps) {
return inputs;
}
+export function dataAttributes(action: LintState): Record {
+ const result: Record = {};
+ for (const [key, value] of Object.entries(action.data || {})) {
+ result[`data-${key}`] = value;
+ }
+
+ return result;
+}
+
export function getUnlabeledOutputs(steps: Steps) {
const outputs: LintState[] = [];
Object.values(steps).forEach((step) => {
diff --git a/client/src/utils/navigation/navigation.yml b/client/src/utils/navigation/navigation.yml
index cbf0af1d6335..349bcd6cd26a 100644
--- a/client/src/utils/navigation/navigation.yml
+++ b/client/src/utils/navigation/navigation.yml
@@ -750,6 +750,13 @@ workflow_editor:
attributes: "#activity-workflow-editor-attributes"
changes: "#activity-workflow-undo-redo"
upgrade_all: "#activity-workflow-upgrade"
+ best_practices: "#activity-workflow-best-practices"
+
+ best_practices:
+ selectors:
+ section_input_metadata: '[data-description="linting input metadata"]'
+ item_input_metadata: '[data-description="linting input metadata"] [data-item-index="${index}"]'
+
comment:
selectors:
_: ".workflow-editor-comment"
diff --git a/lib/galaxy/selenium/navigates_galaxy.py b/lib/galaxy/selenium/navigates_galaxy.py
index fa64b4de4279..1cdb5bc734c0 100644
--- a/lib/galaxy/selenium/navigates_galaxy.py
+++ b/lib/galaxy/selenium/navigates_galaxy.py
@@ -1237,6 +1237,16 @@ def workflow_editor_set_tool_vesrion(self, version: str, node: Optional[EditorNo
editor.tool_version_button.wait_for_and_click()
assert self.select_dropdown_item(f"Switch to {version}"), "Switch to tool version dropdown item not found"
+ def workflow_editor_set_node_label(self, label: str, node: Optional[EditorNodeReference] = None):
+ self.workflow_editor_ensure_tool_form_open(node)
+ editor = self.components.workflow_editor
+ editor.label_input.wait_for_and_clear_and_send_keys(label)
+
+ def workflow_editor_set_node_annotation(self, annotation: str, node: Optional[EditorNodeReference] = None):
+ self.workflow_editor_ensure_tool_form_open(node)
+ editor = self.components.workflow_editor
+ editor.annotation_input.wait_for_and_clear_and_send_keys(annotation)
+
def workflow_editor_ensure_tool_form_open(self, node: Optional[EditorNodeReference] = None):
# if node is_empty just assume current tool step is open
editor = self.components.workflow_editor
diff --git a/lib/galaxy_test/selenium/test_workflow_editor.py b/lib/galaxy_test/selenium/test_workflow_editor.py
index 793bd399639d..510b68de2568 100644
--- a/lib/galaxy_test/selenium/test_workflow_editor.py
+++ b/lib/galaxy_test/selenium/test_workflow_editor.py
@@ -208,8 +208,8 @@ def test_data_input(self):
name = self.workflow_create_new()
self.workflow_editor_add_input(item_name="data_input")
self.screenshot("workflow_editor_data_input_new")
- editor.label_input.wait_for_and_send_keys("input1")
- editor.annotation_input.wait_for_and_send_keys("my cool annotation")
+ self.workflow_editor_set_node_label("input1")
+ self.workflow_editor_set_node_annotation("my cool annotation")
self.sleep_for(self.wait_types.UX_RENDER)
self.screenshot("workflow_editor_data_input_filled_in")
self.workflow_editor_click_save()
@@ -540,6 +540,38 @@ def test_rendering_simple_nested_workflow(self):
self.workflow_editor_maximize_center_pane()
self.screenshot("workflow_editor_simple_nested")
+ @selenium_test
+ def test_best_practices_input_label(self):
+ editor = self.components.workflow_editor
+ annotation = "best_practices_input_label"
+ self.workflow_create_new(annotation=annotation)
+ self.workflow_editor_add_input(item_name="data_input")
+ editor.tool_bar.best_practices.wait_for_and_click()
+ best_practices = editor.best_practices
+ section_element = best_practices.section_input_metadata.wait_for_present()
+ assert section_element.get_attribute("data-lint-status") == "warning"
+ item = best_practices.item_input_metadata(index=0)
+ element = item.wait_for_present()
+ assert element.get_attribute("data-missing-label") == "true"
+ assert element.get_attribute("data-missing-annotation") == "true"
+
+ item.wait_for_and_click()
+ self.workflow_editor_set_node_label("best practice input")
+
+ # editor.tool_bar.best_practices.wait_for_and_click()
+ element = item.wait_for_present()
+ assert element.get_attribute("data-missing-label") == "false"
+ assert element.get_attribute("data-missing-annotation") == "true"
+
+ self.workflow_editor_set_node_annotation("informative annotation")
+
+ @retry_assertion_during_transitions
+ def assert_linting_input_metadata_okay():
+ section_element = best_practices.section_input_metadata.wait_for_present()
+ assert section_element.get_attribute("data-lint-status") == "ok"
+
+ assert_linting_input_metadata_okay()
+
@selenium_test
def test_rendering_rules_workflow_1(self):
self.open_in_workflow_editor(WORKFLOW_WITH_RULES_1)