Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup Jest Test Output (Part 1) #19164

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createTestingPinia } from "@pinia/testing";
import { mount } from "@vue/test-utils";
import { PiniaVuePlugin } from "pinia";
import { dispatchEvent, getLocalVue } from "tests/jest/helpers";
import { dispatchEvent, getLocalVue, stubHelpPopovers } from "tests/jest/helpers";

import { testDatatypesMapper } from "@/components/Datatypes/test_fixtures";
import { useDatatypesMapperStore } from "@/stores/datatypesMapperStore";
Expand Down Expand Up @@ -51,6 +51,8 @@ const defaultOptions = {
const SELECT_OPTIONS = ".multiselect__element";
const SELECTED_VALUE = ".multiselect__option--selected span";

stubHelpPopovers();

describe("FormData", () => {
it("regular data", async () => {
const wrapper = createTarget({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import flushPromises from "flush-promises";
import { getLocalVue } from "tests/jest/helpers";
import { h } from "vue";

import { useServerMock } from "@/api/client/__mocks__";
import { ROOT_COMPONENT } from "@/utils/navigation/schema";
Expand Down Expand Up @@ -42,6 +43,13 @@ async function mountComponent() {

const PREFERENCES = ROOT_COMPONENT.preferences;

// bootstrap vue will try to match targets to actual HTML elements in DOM but there
// may be no DOM for jest tests, just stub out an alternative minimal implementation.
jest.mock("@/components/ObjectStore/ObjectStoreSelectButtonPopover.vue", () => ({
name: "ObjectStoreSelectButtonPopover",
render: () => h("div", "Mocked Popover"),
}));

describe("SelectPreferredStore.vue", () => {
let axiosMock: MockAdapter;

Expand Down
5 changes: 5 additions & 0 deletions client/src/components/History/HistoryView.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ jest.mock("stores/services/history.services");

const { server, http } = useServerMock();

jest.mock("vue-router/composables", () => ({
useRoute: jest.fn(() => ({})),
useRouter: jest.fn(() => ({})),
}));

function create_history(historyId, userId, purged = false, archived = false) {
const historyName = `${userId}'s History ${historyId}`;
return {
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/JobInformation/JobInformation.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mount } from "@vue/test-utils";
import flushPromises from "flush-promises";
import { getLocalVue } from "tests/jest/helpers";
import { getLocalVue, stubHelpPopovers } from "tests/jest/helpers";

import { useServerMock } from "@/api/client/__mocks__";

Expand All @@ -16,6 +16,8 @@ const localVue = getLocalVue();

const { server, http } = useServerMock();

stubHelpPopovers();

describe("JobInformation/JobInformation.vue", () => {
let wrapper;
let jobInfoTable;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { shallowMount } from "@vue/test-utils";
import flushPromises from "flush-promises";
import { createPinia } from "pinia";
import { getLocalVue } from "tests/jest/helpers";
import { getLocalVue, suppressDebugConsole } from "tests/jest/helpers";

import { HttpResponse, useServerMock } from "@/api/client/__mocks__";

Expand All @@ -10,6 +10,8 @@ import Index from "./Index.vue";
const { server, http } = useServerMock();

describe("RepositoryDetails", () => {
suppressDebugConsole(); // we issue a debug warning when a repo has no revisions

it("test repository details index", async () => {
server.use(
http.get("/api/configuration", ({ response }) => {
Expand Down
15 changes: 15 additions & 0 deletions client/src/components/Workflow/Editor/Forms/FormTool.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { createTestingPinia } from "@pinia/testing";
import { mount } from "@vue/test-utils";
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import flushPromises from "flush-promises";
import { getLocalVue } from "tests/jest/helpers";

import { useServerMock } from "@/api/client/__mocks__";

import FormTool from "./FormTool";

jest.mock("@/api/schema");
Expand All @@ -17,10 +20,20 @@ jest.mock("@/composables/config", () => ({

const localVue = getLocalVue();

const { server, http } = useServerMock();

describe("FormTool", () => {
const axiosMock = new MockAdapter(axios);
axiosMock.onGet(`/api/webhooks`).reply(200, []);

beforeEach(() => {
server.use(
http.get("/api/configuration", ({ response }) => {
return response(200).json({});
})
);
});

function mountTarget() {
return mount(FormTool, {
propsData: {
Expand All @@ -35,6 +48,7 @@ describe("FormTool", () => {
description: "description",
inputs: [{ name: "input", label: "input", type: "text", value: "value" }],
help: "help_text",
help_format: "restructuredtext",
versions: ["1.0", "2.0", "3.0"],
citations: false,
},
Expand Down Expand Up @@ -71,5 +85,6 @@ describe("FormTool", () => {
state = wrapper.emitted().onSetData[1][1];
expect(state.tool_version).toEqual("3.0");
expect(state.tool_id).toEqual("tool_id+3.0");
await flushPromises();
});
});
2 changes: 1 addition & 1 deletion client/src/components/Workflow/Editor/Index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe("Index", () => {
const datatypesStore = useDatatypesMapperStore();
datatypesStore.datatypesMapper = testDatatypesMapper;
mockLoadWorkflow.mockResolvedValue({ steps: {} });
MockGetVersions.mockResolvedValue(() => []);
MockGetVersions.mockResolvedValue([]);
mockGetStateUpgradeMessages.mockImplementation(() => []);
mockGetAppRoot.mockImplementation(() => "prefix/");
Object.defineProperty(window, "onbeforeunload", {
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/Workflow/Editor/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
import { library } from "@fortawesome/fontawesome-svg-core";
import { faArrowLeft, faArrowRight, faHistory } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { useMagicKeys, whenever } from "@vueuse/core";
import { whenever } from "@vueuse/core";
import { logicAnd, logicNot, logicOr } from "@vueuse/math";
import { Toast } from "composables/toast";
import { storeToRefs } from "pinia";
Expand All @@ -199,6 +199,7 @@ import Vue, { computed, nextTick, onUnmounted, ref, unref, watch } from "vue";
import { getUntypedWorkflowParameters } from "@/components/Workflow/Editor/modules/parameters";
import { ConfirmDialog } from "@/composables/confirmDialog";
import { useDatatypesMapper } from "@/composables/datatypesMapper";
import { useMagicKeys } from "@/composables/useMagicKeys";
import { useUid } from "@/composables/utils/uid";
import { provideScopedWorkflowStores } from "@/composables/workflowStores";
import { hide_modal } from "@/layout/modal";
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/Workflow/Editor/NodeOutput.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ function propsForStep(step: Step) {
scroll: { x: ref(0), y: ref(0) },
scale: 1,
datatypesMapper: testDatatypesMapper,
parentNode: null,
readonly: true,
blank: false,
};
}

Expand Down
15 changes: 15 additions & 0 deletions client/src/composables/useMagicKeys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useMagicKeys as wrappedUseMagicKeys } from "@vueuse/core";
import Vue from "vue";

export function useMagicKeys() {
// a version of useMagicKeys from vueuse/core that doesn't console.error the
// the message [Vue warn]: Vue 2 does not support reactive collection types such as Map or Set.
// in all our tests. This can be dropped after the migration to Vue3.
const oldSlientConfig = Vue.config.silent;
try {
Vue.config.silent = true;
return wrappedUseMagicKeys();
} finally {
Vue.config.silent = oldSlientConfig;
}
}
2 changes: 1 addition & 1 deletion client/src/stores/workflowEditorToolbarStore.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMagicKeys } from "@vueuse/core";
import { computed, onScopeDispose, reactive, ref, watch } from "vue";

import { type Rectangle } from "@/components/Workflow/Editor/modules/geometry";
import { useMagicKeys } from "@/composables/useMagicKeys";
import { useUserLocalStorage } from "@/composables/userLocalStorage";

import { defineScopedStore } from "./scopedStore";
Expand Down
49 changes: 34 additions & 15 deletions client/src/utils/upload-queue.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,74 @@ function StubFile(name = null, size = 0, mode = "local") {
return { name, size, mode };
}

function instrumentedUploadQueue(options = {}) {
const uploadQueue = new UploadQueue(options);
uploadQueue.encountedErrors = false;
uploadQueue.opts.error = function (d, m) {
uploadQueue.encountedErrors = true;
};
return uploadQueue;
}

describe("UploadQueue", () => {
test("a queue is initialized to correct state", () => {
const q = new UploadQueue({ foo: 1 });
const q = instrumentedUploadQueue({ foo: 1 });
expect(q.size).toEqual(0);
expect(q.isRunning).toBe(false);
expect(q.opts.foo).toEqual(1); // passed as options
expect(q.opts.multiple).toBe(true); // default value
expect(q.encountedErrors).toBeFalsy();
});

test("resetting the queue removes all files from it", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
q.add([StubFile("a"), StubFile("b")]);
expect(q.size).toEqual(2);
q.reset();
expect(q.size).toEqual(0);
expect(q.encountedErrors).toBeFalsy();
});

test("calling configure updates options", () => {
const q = new UploadQueue({ foo: 1 });
const q = instrumentedUploadQueue({ foo: 1 });
expect(q.opts.foo).toEqual(1);
expect(q.opts.bar).toBeUndefined();
q.configure({ bar: 2 }); // overwrite bar
expect(q.opts.foo).toEqual(1); // value unchangee
expect(q.opts.bar).toEqual(2); // value overwritten
expect(q.encountedErrors).toBeFalsy();
});

test("calling start sets isRunning to true", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
q._process = jest.fn(); // mock this, otherwise it'll reset isRunning after it's done.
expect(q.isRunning).toBe(false);
q.start();
expect(q.isRunning).toBe(true);
expect(q.encountedErrors).toBeFalsy();
});

test("calling start is a noop if queue is running", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
const mockedProcess = jest.fn();
q._process = mockedProcess();
q.isRunning = true;
q.start();
expect(mockedProcess.mock.calls.length === 0); // function was not called
expect(q.encountedErrors).toBeFalsy();
});

test("calling start processes all files in queue", () => {
const fileEntries = {};
const q = new UploadQueue({
const q = instrumentedUploadQueue({
get: (index) => fileEntries[index],
announce: (index, file) => {
fileEntries[index] = {
fileMode: file.mode,
fileName: file.name,
fileSize: file.size,
fileContent: "fileContent",
targetHistoryId: "mockhistoryid",
};
},
});
Expand All @@ -71,20 +86,21 @@ describe("UploadQueue", () => {
q.add([StubFile("a"), StubFile("b")]);
q.start();
expect(q.size).toEqual(0);
expect(q.encountedErrors).toBeFalsy();
expect(spy.mock.calls.length).toEqual(3); // called for 2, 1, 0 files.
spy.mockRestore(); // not necessary, but safer, in case we later modify implementation.
});

test("calling stop sets isPaused to true", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
q.start();
expect(q.isPaused).toBe(false);
q.stop();
expect(q.isPaused).toBe(true);
});

test("adding files increases the queue size by the number of files", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
expect(q.size).toEqual(0);
q.add([StubFile("a"), StubFile("b")]);
expect(q.nextIndex).toEqual(2);
Expand All @@ -94,14 +110,14 @@ describe("UploadQueue", () => {
});

test("adding files increases the next index by the number of files", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
expect(q.nextIndex).toEqual(0);
q.add([StubFile("a"), StubFile("b")]);
expect(q.nextIndex).toEqual(2);
});

test("duplicate files are not added to the queue, unless the mode is set to 'new'", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
const file1 = StubFile("a", 1);
const file2 = StubFile("a", 1);
const file3 = StubFile("a", 1, "new");
Expand All @@ -115,7 +131,7 @@ describe("UploadQueue", () => {

test("adding a file calls opts.announce with correct arguments", () => {
const mockAnnounce = jest.fn();
const q = new UploadQueue({ announce: mockAnnounce });
const q = instrumentedUploadQueue({ announce: mockAnnounce });
const file = StubFile("a");
expect(mockAnnounce.mock.calls.length).toBe(0);
q.add([file]);
Expand All @@ -126,7 +142,7 @@ describe("UploadQueue", () => {

test("removing a file reduces the queue size by 1", () => {
const fileEntries = {};
const q = new UploadQueue({
const q = instrumentedUploadQueue({
announce: (index, file) => {
fileEntries[index] = file;
},
Expand All @@ -138,7 +154,7 @@ describe("UploadQueue", () => {
});

test("removing a file by index out of sequence is allowed", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
const file1 = StubFile("a");
const file2 = StubFile("b");
const file3 = StubFile("c");
Expand All @@ -149,10 +165,11 @@ describe("UploadQueue", () => {
expect(q.queue.get("0")).toBe(file1);
expect(q.queue.get("1")).toBeUndefined();
expect(q.queue.get("2")).toBe(file3);
expect(q.encountedErrors).toBeFalsy();
});

test("removing a file via _processIndex, obeys FIFO protocol", () => {
const q = new UploadQueue();
const q = instrumentedUploadQueue();
q.add([StubFile("a"), StubFile("b")]);
let nextIndex = q._processIndex();
expect(nextIndex).toEqual("0");
Expand All @@ -161,11 +178,12 @@ describe("UploadQueue", () => {
expect(nextIndex).toEqual("1");
q.remove(nextIndex);
expect(q._processIndex()).toBeUndefined();
expect(q.encountedErrors).toBeFalsy();
});

test("remote file batch", () => {
const fileEntries = {};
const q = new UploadQueue({
const q = instrumentedUploadQueue({
historyId: "historyId",
announce: (index, file) => {
fileEntries[index] = {
Expand Down Expand Up @@ -227,5 +245,6 @@ describe("UploadQueue", () => {
},
],
});
expect(q.encountedErrors).toBeFalsy();
});
});
13 changes: 13 additions & 0 deletions client/tests/jest/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,16 @@ export function injectTestRouter(localVue) {
const router = new VueRouter();
return router;
}

export function suppressDebugConsole() {
jest.spyOn(console, "debug").mockImplementation(jest.fn());
}

export function stubHelpPopovers() {
// bootstrap vue will try to match targets to actual HTML elements in DOM but there
// may be no DOM for jest tests, just stub out an alternative minimal implementation.
jest.mock("@/components/Help/HelpPopover.vue", () => ({
name: "HelpPopover",
render: (h) => h("div", "Mocked Popover"),
}));
}
Loading
Loading