From 4a92363190646ed64b4ab01141fd07ea6c6cba4a Mon Sep 17 00:00:00 2001 From: mvdbeek Date: Fri, 13 Sep 2024 17:18:18 +0200 Subject: [PATCH] Prevent optional output to required input connection in editor Fixes https://github.com/galaxyproject/galaxy/issues/18791 --- .../components/Workflow/Editor/NodeOutput.vue | 2 +- .../Workflow/Editor/modules/terminals.test.ts | 10 +++ .../Workflow/Editor/modules/terminals.ts | 3 + .../Editor/test-data/parameter_steps.json | 64 +++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/client/src/components/Workflow/Editor/NodeOutput.vue b/client/src/components/Workflow/Editor/NodeOutput.vue index d76c17e44345..1ce9500f6c34 100644 --- a/client/src/components/Workflow/Editor/NodeOutput.vue +++ b/client/src/components/Workflow/Editor/NodeOutput.vue @@ -300,7 +300,7 @@ const outputDetails = computed(() => { const outputType = collectionType && collectionType.isCollection && collectionType.collectionType ? `output is ${collectionTypeToDescription(collectionType)}` - : `output is ${terminal.value.type || "dataset"}`; + : `output is ${terminal.value.optional ? "optional " : ""}${terminal.value.type || "dataset"}`; if (isMultiple.value) { if (!collectionType) { collectionType = NULL_COLLECTION_TYPE_DESCRIPTION; diff --git a/client/src/components/Workflow/Editor/modules/terminals.test.ts b/client/src/components/Workflow/Editor/modules/terminals.test.ts index 844c9114bb14..7cc4fb0e26c2 100644 --- a/client/src/components/Workflow/Editor/modules/terminals.test.ts +++ b/client/src/components/Workflow/Editor/modules/terminals.test.ts @@ -298,6 +298,16 @@ describe("canAccept", () => { "Cannot attach a text parameter to a integer input" ); }); + it("rejects optional integer to required parameter connection", () => { + const integerInputParam = terminals["multi data"]!["advanced|advanced_threshold"] as InputParameterTerminal; + const optionalIntegerOutputParam = terminals["optional integer parameter input"]![ + "output" + ] as OutputParameterTerminal; + expect(integerInputParam.canAccept(optionalIntegerOutputParam).canAccept).toBe(false); + expect(integerInputParam.canAccept(optionalIntegerOutputParam).reason).toBe( + "Cannot attach an optional output to a required parameter" + ); + }); it("rejects data to parameter connection", () => { const dataOut = terminals["data input"]!["output"] as OutputTerminal; const integerInputParam = terminals["multi data"]!["advanced|advanced_threshold"] as InputParameterTerminal; diff --git a/client/src/components/Workflow/Editor/modules/terminals.ts b/client/src/components/Workflow/Editor/modules/terminals.ts index 7ed030b537e2..cb86c796a9c5 100644 --- a/client/src/components/Workflow/Editor/modules/terminals.ts +++ b/client/src/components/Workflow/Editor/modules/terminals.ts @@ -540,6 +540,9 @@ export class InputParameterTerminal extends BaseInputTerminal { const effectiveThisType = this.effectiveType(this.type); const otherType = ("type" in other && other.type) || "data"; const effectiveOtherType = this.effectiveType(otherType); + if (!this.optional && other.optional) { + return new ConnectionAcceptable(false, `Cannot attach an optional output to a required parameter`); + } const canAccept = effectiveThisType === effectiveOtherType; return new ConnectionAcceptable( canAccept, diff --git a/client/src/components/Workflow/Editor/test-data/parameter_steps.json b/client/src/components/Workflow/Editor/test-data/parameter_steps.json index d3cff2cf8d98..bb0ad17cd901 100644 --- a/client/src/components/Workflow/Editor/test-data/parameter_steps.json +++ b/client/src/components/Workflow/Editor/test-data/parameter_steps.json @@ -906,5 +906,69 @@ "left": 12.8729248046875, "top": 501.7839660644531 } + }, + "19": { + "id": 19, + "type": "parameter_input", + "label": "optional text parameter input", + "content_id": null, + "name": "Input parameter", + "tool_state": { + "parameter_definition": "{\"__current_case__\": 0, \"optional\": {\"__current_case__\": 1, \"optional\": \"true\"}, \"parameter_type\": \"text\", \"restrictions\": {\"__current_case__\": 0, \"how\": \"none\"}}", + "__page__": null, + "__rerun_remap_job_id__": null + }, + "errors": null, + "inputs": [], + "outputs": [ + { + "name": "output", + "label": "optional text parameter input", + "type": "text", + "optional": true, + "parameter": true + } + ], + "annotation": "", + "post_job_actions": {}, + "uuid": "71c030ff-a29f-4e32-a735-37471e7a3f12", + "workflow_outputs": [], + "input_connections": {}, + "position": { + "left": 95.0506591796875, + "top": 867.0427551269531 + } + }, + "19": { + "id": 19, + "type": "parameter_input", + "label": "optional integer parameter input", + "content_id": null, + "name": "Input parameter", + "tool_state": { + "parameter_definition": "{\"__current_case__\": 1, \"optional\": {\"__current_case__\": 1, \"optional\": \"true\"}, \"parameter_type\": \"integer\"}", + "__page__": null, + "__rerun_remap_job_id__": null + }, + "errors": null, + "inputs": [], + "outputs": [ + { + "name": "output", + "label": "integer parameter input", + "type": "integer", + "optional": true, + "parameter": true + } + ], + "annotation": "", + "post_job_actions": {}, + "uuid": "634f06f1-b279-4160-9390-a004018e92ce", + "workflow_outputs": [], + "input_connections": {}, + "position": { + "left": 148.72970581054688, + "top": 620.5069274902344 + } } }