From d6c9b38c5ffe8cf049df5ab7bbae9fa1e74a5f59 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Sun, 1 Dec 2024 19:27:32 -0500 Subject: [PATCH] Expand change stack UI testing... --- .../Editor/Actions/workflowActions.ts | 33 ++++++++++-- .../src/components/Workflow/Editor/Index.vue | 9 ++-- client/src/utils/navigation/navigation.yml | 3 ++ lib/galaxy/selenium/navigates_galaxy.py | 21 ++++---- .../selenium/test_workflow_editor.py | 51 ++++++++++++++----- 5 files changed, 90 insertions(+), 27 deletions(-) diff --git a/client/src/components/Workflow/Editor/Actions/workflowActions.ts b/client/src/components/Workflow/Editor/Actions/workflowActions.ts index 4418e0a3c519..a66ac66ccd35 100644 --- a/client/src/components/Workflow/Editor/Actions/workflowActions.ts +++ b/client/src/components/Workflow/Editor/Actions/workflowActions.ts @@ -18,13 +18,21 @@ export class LazySetValueAction extends LazyUndoRedoAction { showAttributesCallback; fromValue; toValue; + what: string | null; - constructor(fromValue: T, toValue: T, setValueHandler: (value: T) => void, showCanvasCallback: () => void) { + constructor( + fromValue: T, + toValue: T, + setValueHandler: (value: T) => void, + showCanvasCallback: () => void, + what: string | null = null + ) { super(); this.fromValue = structuredClone(fromValue); this.toValue = structuredClone(toValue); this.setValueHandler = setValueHandler; this.showAttributesCallback = showCanvasCallback; + this.what = what; } queued() { @@ -46,6 +54,16 @@ export class LazySetValueAction extends LazyUndoRedoAction { this.setValueHandler(this.toValue); } + get dataAttributes(): Record { + if (this.what) { + return { + type: `set-${this.what}`, + }; + } else { + return {}; + } + } + get name() { return this.internalName ?? "modify workflow"; } @@ -61,24 +79,33 @@ export class SetValueActionHandler { showAttributesCallback; lazyAction: LazySetValueAction | null = null; name?: string; + what: string | null; constructor( undoRedoStore: UndoRedoStore, setValueHandler: (value: T) => void, showCanvasCallback: () => void, - name?: string + name?: string, + what: string | null = null ) { this.undoRedoStore = undoRedoStore; this.setValueHandler = setValueHandler; this.showAttributesCallback = showCanvasCallback; this.name = name; + this.what = what; } set(from: T, to: T) { if (this.lazyAction && this.undoRedoStore.isQueued(this.lazyAction)) { this.lazyAction.changeValue(to); } else { - this.lazyAction = new LazySetValueAction(from, to, this.setValueHandler, this.showAttributesCallback); + this.lazyAction = new LazySetValueAction( + from, + to, + this.setValueHandler, + this.showAttributesCallback, + this.what + ); this.lazyAction.name = this.name; this.undoRedoStore.applyLazyAction(this.lazyAction); } diff --git a/client/src/components/Workflow/Editor/Index.vue b/client/src/components/Workflow/Editor/Index.vue index 9506a25386af..6ba440897926 100644 --- a/client/src/components/Workflow/Editor/Index.vue +++ b/client/src/components/Workflow/Editor/Index.vue @@ -324,7 +324,8 @@ export default { undoRedoStore, (value) => (license.value = value), showAttributes, - "set license" + "set license", + "license" ); /** user set license. queues an undo/redo action */ function setLicense(newLicense) { @@ -338,7 +339,8 @@ export default { undoRedoStore, (value) => (creator.value = value), showAttributes, - "set creator" + "set creator", + "creator" ); /** user set creator. queues an undo/redo action */ function setCreator(newCreator) { @@ -350,7 +352,8 @@ export default { undoRedoStore, (value) => (annotation.value = value), showAttributes, - "modify annotation" + "modify annotation", + "annotation" ); /** user set annotation. queues an undo/redo action */ function setAnnotation(newAnnotation) { diff --git a/client/src/utils/navigation/navigation.yml b/client/src/utils/navigation/navigation.yml index 6ba74371bc8f..1cb87a786fe3 100644 --- a/client/src/utils/navigation/navigation.yml +++ b/client/src/utils/navigation/navigation.yml @@ -722,6 +722,8 @@ workflow_editor: action_insert_data_input: ".action[data-type='step-insert'][data-step-type='data_input']" action_insert_data_collection_input: ".action[data-type='step-insert'][data-step-type='data_collection_input']" action_insert_parameter: ".action[data-type='step-insert'][data-step-type='parameter_input']" + action_set_license: ".action[data-type='set-license']" + action_set_annotation: ".action[data-type='set-annotation']" tool_bar: selectors: @@ -743,6 +745,7 @@ workflow_editor: duplicate_selection: "[title='duplicate selected']" delete_selection: "[title='delete selected']" auto_layout: "#auto-layout-button" + attributes: "#activity-workflow-editor-attributes" changes: "#activity-workflow-undo-redo" upgrade_all: "#activity-workflow-upgrade" comment: diff --git a/lib/galaxy/selenium/navigates_galaxy.py b/lib/galaxy/selenium/navigates_galaxy.py index 8d88faca8908..4eb21094258f 100644 --- a/lib/galaxy/selenium/navigates_galaxy.py +++ b/lib/galaxy/selenium/navigates_galaxy.py @@ -1212,14 +1212,14 @@ def workflow_editor_set_license(self, license: str) -> None: license_selector_option = self.components.workflow_editor.license_selector_option license_selector_option.wait_for_and_click() + def workflow_editor_license_text(self) -> str: + editor = self.components.workflow_editor + editor.license_selector.wait_for_visible() + return editor.license_current_value.wait_for_text() + def workflow_editor_add_tool_step(self, tool_id: str): self.tool_open(tool_id) - def workflow_editor_set_label(self, label: str, node: Optional[EditorNodeReference] = None): - editor = self.components.workflow_editor - self.workflow_editor_ensure_tool_form_open(node) - self.set_text_element(editor.label_input, label) - def workflow_editor_set_tool_vesrion(self, version: str, node: Optional[EditorNodeReference] = None) -> None: editor = self.components.workflow_editor self.workflow_editor_ensure_tool_form_open(node) @@ -1231,10 +1231,10 @@ def workflow_editor_ensure_tool_form_open(self, node: Optional[EditorNodeReferen editor = self.components.workflow_editor if node is not None: if isinstance(node, int): - node = editor.node.by_id(id=node) + node_component = editor.node.by_id(id=node) else: - node = editor.node._(label=node) - node.wait_for_and_click() + node_component = editor.node._(label=node) + node_component.wait_for_and_click() editor.node_inspector.wait_for_visible() def workflow_editor_click_option(self, option_label): @@ -1682,7 +1682,7 @@ def workflow_create_new(self, annotation=None, clear_placeholder=False, save_wor name_component.wait_for_visible().clear() name_component.wait_for_and_send_keys(name) annotation = annotation or self._get_random_name() - self.components.workflow_editor.edit_annotation.wait_for_and_send_keys(annotation) + self.workflow_editor_set_annotation(annotation) if save_workflow: save_button = self.components.workflow_editor.save_button save_button.wait_for_visible() @@ -1691,6 +1691,9 @@ def workflow_create_new(self, annotation=None, clear_placeholder=False, save_wor self.sleep_for(self.wait_types.UX_RENDER) return name + def workflow_editor_set_annotation(self, annotation: str): + self.components.workflow_editor.edit_annotation.wait_for_and_clear_and_send_keys(annotation) + def invocation_index_table_elements(self): invocations = self.components.invocations invocations.invocations_table.wait_for_visible() diff --git a/lib/galaxy_test/selenium/test_workflow_editor.py b/lib/galaxy_test/selenium/test_workflow_editor.py index 730d311bcb0f..67b23ef081e0 100644 --- a/lib/galaxy_test/selenium/test_workflow_editor.py +++ b/lib/galaxy_test/selenium/test_workflow_editor.py @@ -88,15 +88,13 @@ def test_edit_license(self): editor = self.components.workflow_editor name = self.workflow_create_new() editor.canvas_body.wait_for_visible() - editor.license_selector.wait_for_visible() - assert "Do not specify" in editor.license_current_value.wait_for_text() + assert "Do not specify" in self.workflow_editor_license_text() self.workflow_editor_set_license("MIT") self.workflow_editor_click_save() self.workflow_index_open_with_name(name) - editor.license_selector.wait_for_visible() - assert "MIT" in editor.license_current_value.wait_for_text() + assert "MIT" in self.workflow_editor_license_text() @selenium_test def test_optional_select_data_field(self): @@ -368,13 +366,10 @@ def test_reconnecting_nodes(self): self.assert_connected("input1#output", "first_cat#input1") @selenium_test - def test_editor_change_stack(self): + def test_editor_change_stack_inserting_inputs(self): editor = self.components.workflow_editor - annotation = "change_stack_test" - name = self.workflow_create_new(annotation=annotation) - - self.workflow_editor_set_license("MIT") - self.workflow_editor_click_save() + annotation = "change_stack_test_inserting_inputs" + self.workflow_create_new(annotation=annotation) self.workflow_editor_add_input(item_name="data_input") self.workflow_editor_add_input(item_name="data_collection_input") @@ -413,6 +408,38 @@ def test_editor_change_stack(self): editor.node.by_id(id=1).wait_for_present() editor.node.by_id(id=2).wait_for_present() + @selenium_test + def test_editor_change_stack_set_attributes(self): + editor = self.components.workflow_editor + annotation = "change_stack_test_set_attributes" + name = self.workflow_create_new(annotation=annotation) + + assert "Do not specify" in self.workflow_editor_license_text() + self.workflow_editor_set_license("MIT") + assert "MIT" in self.workflow_editor_license_text() + + editor.tool_bar.changes.wait_for_and_click() + + changes = editor.changes + changes.action_set_license.wait_for_and_click() + # it switches back so this isn't needed per se + # editor.tool_bar.attributes.wait_for_and_click() + assert "Do not specify" in self.workflow_editor_license_text() + + # for annotation we want to reset the change stack to dismiss + # the original setting of the annotation + name = self.workflow_index_open_with_name(name) + + annotation_modified = "change_stack_test_set_attributes modified!!!" + + self.workflow_editor_set_annotation(annotation_modified) + self.assert_wf_annotation_is(annotation_modified) + + editor.tool_bar.changes.wait_for_and_click() + changes.action_set_annotation.wait_for_and_click() + + self.assert_wf_annotation_is(annotation) + @selenium_test def test_rendering_output_collection_connections(self): self.open_in_workflow_editor(WORKFLOW_WITH_OUTPUT_COLLECTION) @@ -551,7 +578,7 @@ def test_editor_tool_upgrade_all_tools(self): annotation = "upgarde_all_test" self.workflow_create_new(annotation=annotation) self.workflow_editor_add_tool_step("multiple_versions") - self.workflow_editor_set_label(label="target label") + self.workflow_editor_set_node_label(label="target label") self.workflow_editor_set_tool_vesrion("0.1") self.assert_workflow_has_changes_and_save() @@ -733,7 +760,7 @@ def test_editor_duplicate_node(self): self.workflow_index_open() self.components.workflows.edit_button.wait_for_and_click() editor = self.components.workflow_editor - self.workflow_editor_set_label(label="source label", node="first_cat") + self.workflow_editor_set_node_label(label="source label", node="first_cat") # Select node using new label, ensures labels are synced between side panel and node cat_node = editor.node._(label="source label") self.assert_workflow_has_changes_and_save()