diff --git a/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.test.js b/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.test.js index f4e069fb3cc7..ab154ae17813 100644 --- a/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.test.js +++ b/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.test.js @@ -1,5 +1,6 @@ import { createTestingPinia } from "@pinia/testing"; import { shallowMount } from "@vue/test-utils"; +import flushPromises from "flush-promises"; import { getLocalVue } from "tests/jest/helpers"; import invocationData from "../Workflow/test/json/invocation.json"; @@ -7,6 +8,42 @@ import WorkflowInvocationOverview from "./WorkflowInvocationOverview"; const localVue = getLocalVue(); +// Constants +const workflowData = { + id: "workflow-id", + name: "Test Workflow", + version: 0, +}; +const selectors = { + bAlertStub: "balert-stub", +}; +const alertMessages = { + unOwned: "Workflow is neither importable, nor owned by or shared with current user", + nonExistent: "No workflow found for this invocation.", +}; + +// Mock the workflow store to return the expected workflow data given the stored workflow ID +jest.mock("@/stores/workflowStore", () => { + const originalModule = jest.requireActual("@/stores/workflowStore"); + return { + ...originalModule, + useWorkflowStore: () => ({ + ...originalModule.useWorkflowStore(), + getStoredWorkflowByInstanceId: jest.fn().mockImplementation((workflowId) => { + if (["unowned-workflow", "nonexistant-workflow"].includes(workflowId)) { + return undefined; + } + return workflowData; + }), + fetchWorkflowForInstanceId: jest.fn().mockImplementation((workflowId) => { + if (workflowId === "unowned-workflow") { + throw new Error(alertMessages.unOwned); + } + }), + }), + }; +}); + describe("WorkflowInvocationOverview.vue with terminal invocation", () => { let wrapper; let propsData; @@ -61,3 +98,39 @@ describe("WorkflowInvocationOverview.vue with invocation scheduling running", () expect(wrapper.find(".cancel-workflow-scheduling").exists()).toBeTruthy(); }); }); + +describe("WorkflowInvocationOverview.vue for a valid/invalid workflow", () => { + async function loadWrapper(invocationData) { + const propsData = { + invocation: invocationData, + invocationAndJobTerminal: true, + invocationSchedulingTerminal: true, + jobStatesSummary: {}, + }; + const wrapper = shallowMount(WorkflowInvocationOverview, { + propsData, + localVue, + }); + await flushPromises(); + return wrapper; + } + + it("displays the workflow invocation graph for a valid workflow", async () => { + const wrapper = await loadWrapper(invocationData); + expect(wrapper.find("[data-description='workflow invocation graph']").exists()).toBeTruthy(); + }); + + it("displays an alert for an unowned workflow", async () => { + const wrapper = await loadWrapper({ ...invocationData, workflow_id: "unowned-workflow" }); + expect(wrapper.find("[data-description='workflow invocation graph']").exists()).toBeFalsy(); + const alert = wrapper.find(selectors.bAlertStub); + expect(alert.text()).toContain(alertMessages.unOwned); + }); + + it("displays an alert for a nonexistant workflow", async () => { + const wrapper = await loadWrapper({ ...invocationData, workflow_id: "nonexistant-workflow" }); + expect(wrapper.find("[data-description='workflow invocation graph']").exists()).toBeFalsy(); + const alert = wrapper.find(selectors.bAlertStub); + expect(alert.text()).toContain(alertMessages.nonExistent); + }); +}); diff --git a/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue b/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue index b4145df6cc73..bf04dd5ce80c 100644 --- a/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue +++ b/client/src/components/WorkflowInvocationState/WorkflowInvocationOverview.vue @@ -240,6 +240,7 @@ function onCancel() {