Skip to content

Commit

Permalink
fix/adjust jests for errors shown in WorkflowInvocationOverview
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedhamidawan committed Aug 28, 2024
1 parent 50ac08c commit 91e7ce2
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,49 @@
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";
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;
Expand Down Expand Up @@ -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);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ function onCancel() {
<div v-else-if="workflow && !isSubworkflow">
<InvocationGraph
class="mt-1"
data-description="workflow invocation graph"
:invocation="invocation"
:workflow="workflow"
:is-terminal="invocationAndJobTerminal"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createTestingPinia } from "@pinia/testing";
import { mount, shallowMount, Wrapper } from "@vue/test-utils";
import { shallowMount, Wrapper } from "@vue/test-utils";
import flushPromises from "flush-promises";
import { PiniaVuePlugin, setActivePinia } from "pinia";
import { getLocalVue } from "tests/jest/helpers";
Expand Down Expand Up @@ -79,22 +79,20 @@ jest.mock("@/stores/invocationStore", () => {
};
});

// Sample workflow
const workflowData = {
id: "workflow-id",
name: "Test Workflow",
version: 0,
};

// Mock the workflow store to return the expected workflow data given the stored workflow ID
// Mock the workflow store to return a workflow for `getStoredWorkflowByInstanceId`
jest.mock("@/stores/workflowStore", () => {
const originalModule = jest.requireActual("@/stores/workflowStore");
return {
...originalModule,
useWorkflowStore: () => ({
...originalModule.useWorkflowStore(),
getStoredWorkflowByInstanceId: jest.fn().mockImplementation(() => workflowData),
fetchWorkflowForInstanceId: jest.fn(),
getStoredWorkflowByInstanceId: jest.fn().mockImplementation(() => {
return {
id: "workflow-id",
name: "Test Workflow",
version: 0,
};
}),
}),
};
});
Expand All @@ -105,30 +103,18 @@ jest.mock("@/stores/workflowStore", () => {
* @param fullPage Whether to render the header as well or just the invocation state tabs
* @returns The mounted wrapper
*/
async function mountWorkflowInvocationState(invocationId: string, shallow = true, isFullPage = false) {
async function mountWorkflowInvocationState(invocationId: string, isFullPage = false) {
const pinia = createTestingPinia();
setActivePinia(pinia);

let wrapper;
if (shallow) {
wrapper = shallowMount(WorkflowInvocationState as object, {
propsData: {
invocationId,
isFullPage,
},
pinia,
localVue,
});
} else {
wrapper = mount(WorkflowInvocationState as object, {
propsData: {
invocationId,
isFullPage,
},
pinia,
localVue,
});
}
const wrapper = shallowMount(WorkflowInvocationState as object, {
propsData: {
invocationId,
isFullPage,
},
pinia,
localVue,
});
await flushPromises();
return wrapper;
}
Expand Down Expand Up @@ -193,22 +179,15 @@ describe("WorkflowInvocationState check invocation and job terminal states", ()

describe("WorkflowInvocationState check 'Report' tab disabled state and header", () => {
it("determines that 'Report' tab is disabled for non-terminal invocation", async () => {
const wrapper = await mountWorkflowInvocationState("non-terminal-id", true);
const wrapper = await mountWorkflowInvocationState("non-terminal-id");
const reportTab = wrapper.find(selectors.invocationReportTab);
expect(reportTab.attributes("disabled")).toBe("true");
});
it("determines that 'Report' tab is not disabled for terminal invocation", async () => {
const wrapper = await mountWorkflowInvocationState(invocationData.id, true);
const wrapper = await mountWorkflowInvocationState(invocationData.id);
const reportTab = wrapper.find(selectors.invocationReportTab);
expect(reportTab.attributes("disabled")).toBeUndefined();
});
it("determines that a header is displayed for the invocation", async () => {
const wrapper = await mountWorkflowInvocationState(invocationData.id, true, true);
const heading = wrapper.find(selectors.fullPageHeading);
expect(heading.exists()).toBe(true);
expect(heading.text()).toContain('Invoked Workflow: "Test Workflow"');
expect(wrapper.html()).toContain(`Workflow Version: ${workflowData.version + 1}`);
});
});

/**
Expand Down
1 change: 0 additions & 1 deletion client/src/composables/useWorkflowInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export function useWorkflowInstance(workflowId: string) {
await workflowStore.fetchWorkflowForInstanceId(workflowId);
} catch (e) {
error.value = errorMessageAsString(e);
console.error("unable to fetch workflow \n", error.value);
} finally {
loading.value = false;
}
Expand Down

0 comments on commit 91e7ce2

Please sign in to comment.