Skip to content

Commit

Permalink
unit tests and linting
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmaLRussell committed Nov 8, 2023
1 parent c921357 commit 97cba33
Show file tree
Hide file tree
Showing 12 changed files with 170 additions and 136 deletions.
4 changes: 3 additions & 1 deletion app/static/src/app/components/WodinApp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ export default defineComponent({
// If there's a load (share) session id, then immediately initialise with that
// If there is no latest session id then immediately initialise a new session - display modal conditional on
// this value as well as sessionInitialised to avoid momentary display of modal when this is true.
const immediateInitialise = computed(() => loadSessionId.value || !latestSessionId.value);
const immediateInitialise = computed(() => {
return !sessionInitialised.value && (loadSessionId.value || !latestSessionId.value);
});
if (immediateInitialise.value) {
initialise(loadSessionId.value || "");
Expand Down
3 changes: 1 addition & 2 deletions app/static/src/app/components/WodinSession.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ErrorsMutation } from "../store/errors/mutations";
import { localStorageManager } from "../localStorageManager";
import { AppStateGetter } from "../store/appState/getters";
import { SessionMetadata } from "../types/responseTypes";
import {SessionsMutation} from "../store/sessions/mutations";
import { SessionsMutation } from "../store/sessions/mutations";
export default defineComponent({
name: "WodinSession",
Expand All @@ -36,7 +36,6 @@ export default defineComponent({
const initialised = ref(false);
const appInitialised = computed(() => !!store.state.config && !!store.state.sessions.sessionsMetadata);
// These props won't change as provided by server
// eslint-disable-next-line vue/no-setup-props-destructure
const {
Expand Down
1 change: 1 addition & 0 deletions app/static/src/app/store/basic/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const defaultState: () => any = () => {
baseUrl: null,
appsPath: null,
config: null,
loadSessionId: null,
queuedStateUploadIntervalId: -1,
stateUploadInProgress: false,
configured: false,
Expand Down
1 change: 1 addition & 0 deletions app/static/src/app/store/fit/fit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const defaultState: () => any = () => {
baseUrl: null,
appsPath: null,
config: null,
loadSessionId: null,
queuedStateUploadIntervalId: -1,
stateUploadInProgress: false,
configured: false,
Expand Down
1 change: 1 addition & 0 deletions app/static/src/app/store/stochastic/stochastic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const defaultState: () => any = () => {
baseUrl: null,
appsPath: null,
config: null,
loadSessionId: null,
queuedStateUploadIntervalId: -1,
stateUploadInProgress: false,
configured: false,
Expand Down
9 changes: 7 additions & 2 deletions app/static/tests/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,11 @@ export const mockMultiSensitivityState = (state: Partial<MultiSensitivityState>
};
};

const mockSessionsState = (): SessionsState => {
export const mockSessionsState = (state: Partial<SessionsState> = {}): SessionsState => {
return {
sessionsMetadata: null
sessionsMetadata: null,
latestSessionId: null,
...state
};
};

Expand All @@ -214,6 +216,7 @@ export const mockBasicState = (state: Partial<BasicState> = {}): BasicState => {
basicProp: "",
...mockAppConfig
},
loadSessionId: null,
code: mockCodeState(),
model: mockModelState(),
run: mockRunState(),
Expand Down Expand Up @@ -266,6 +269,7 @@ export const mockFitState = (state: Partial<FitState> = {}): FitState => {
appType: "fit",
...mockAppConfig
},
loadSessionId: null,
code: mockCodeState(),
model: mockModelState(),
run: mockRunState(),
Expand Down Expand Up @@ -301,6 +305,7 @@ export const mockStochasticState = (state: Partial<StochasticState> = {}): Stoch
maxReplicatesDisplay: 20,
...mockAppConfig
},
loadSessionId: null,
code: mockCodeState(),
model: mockModelState(),
run: mockRunState(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ describe("SessionInitialiseModal", () => {
it("renders as expected", () => {
const wrapper = getWrapper();
expect(wrapper.find("#session-initialise-modal .modal").classes()).toContain("show");
expect((wrapper.find("#session-initialise-modal .modal").element as HTMLDivElement).style.display)
.toBe("block");
expect(wrapper.find(".modal-backdrop").exists()).toBe(true);
expect(wrapper.find(".modal-body").text())
.toBe("Would you like to reload the most recent session or start a new session?");
Expand Down
64 changes: 37 additions & 27 deletions app/static/tests/unit/components/sessions/sessionsPage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { nextTick } from "vue";
import SessionsPage from "../../../../src/app/components/sessions/SessionsPage.vue";
import ErrorsAlert from "../../../../src/app/components/ErrorsAlert.vue";
import { BasicState } from "../../../../src/app/store/basic/state";
import { mockBasicState, mockUserPreferences } from "../../../mocks";
import { mockBasicState, mockSessionsState, mockUserPreferences } from "../../../mocks";
import { SessionsAction } from "../../../../src/app/store/sessions/actions";
import { SessionMetadata } from "../../../../src/app/types/responseTypes";
import EditSessionLabel from "../../../../src/app/components/sessions/EditSessionLabel.vue";
import ConfirmModal from "../../../../src/app/components/ConfirmModal.vue";
import { AppStateAction } from "../../../../src/app/store/appState/actions";
import { SessionsState } from "../../../../src/app/store/sessions/state";

const mockRouter = {
push: jest.fn()
Expand Down Expand Up @@ -40,7 +40,7 @@ describe("SessionsPage", () => {

const currentSessionId = "abc";

const getWrapper = (sessionsMetadata: SessionMetadata[] | null, sessionId: string | undefined,
const getWrapper = (sessionsState: Partial<SessionsState>, sessionId: string | undefined,
userPreferences = mockUserPreferences()) => {
const store = new Vuex.Store<BasicState>({
state: mockBasicState({
Expand All @@ -58,9 +58,7 @@ describe("SessionsPage", () => {
modules: {
sessions: {
namespaced: true,
state: {
sessionsMetadata
},
state: mockSessionsState(sessionsState),
actions: {
[SessionsAction.GetSessions]: mockGetSessions,
[SessionsAction.GenerateFriendlyId]: mockGenerateFriendlyId,
Expand Down Expand Up @@ -92,7 +90,7 @@ describe("SessionsPage", () => {
];

it("renders as expected", () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
const rows = wrapper.findAll(".container .row");
expect(rows.at(0)!.find("h2").text()).toBe("Sessions");

Expand Down Expand Up @@ -159,15 +157,15 @@ describe("SessionsPage", () => {
});

it("shows loading message when session metadata is null in store", () => {
const wrapper = getWrapper(null, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata: null }, currentSessionId);
const rows = wrapper.findAll(".container .row");
expect(rows.length).toBe(2);
expect(rows.at(0)!.text()).toBe("Sessions");
expect(wrapper.find("#loading-sessions").text()).toBe("Loading sessions...");
});

it("renders as expected when no current session", () => {
const wrapper = getWrapper(sessionsMetadata, undefined);
const wrapper = getWrapper({ sessionsMetadata }, undefined);

expect(wrapper.find("#current-session").exists()).toBe(false);
const noCurrent = wrapper.find("#no-current-session");
Expand All @@ -181,7 +179,7 @@ describe("SessionsPage", () => {

it("renders as expected when no previous sessions", () => {
// include current session in metadata only
const wrapper = getWrapper([sessionsMetadata[0]], currentSessionId);
const wrapper = getWrapper({ sessionsMetadata: [sessionsMetadata[0]] }, currentSessionId);
expect(wrapper.find("#no-current-session").exists()).toBe(false);
const current = wrapper.find("#current-session");
expect(current.exists()).toBe(true);
Expand All @@ -195,7 +193,7 @@ describe("SessionsPage", () => {
});

it("renders as expected when no current session and no previous sessions", () => {
const wrapper = getWrapper([], undefined);
const wrapper = getWrapper({ sessionsMetadata: [] }, undefined);
expect(wrapper.find("#current-session").exists()).toBe(false);
const noCurrent = wrapper.find("#no-current-session");
expect(noCurrent.exists()).toBe(true);
Expand All @@ -207,14 +205,14 @@ describe("SessionsPage", () => {
});

it("dispatches getSessions action on mount", async () => {
getWrapper(null, currentSessionId);
getWrapper({ sessionsMetadata: null }, currentSessionId);
await nextTick();
await nextTick();
expect(mockGetSessions).toHaveBeenCalledTimes(1);
});

it("shows edit label dialog when click icon", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
const rows = wrapper.findAll(".previous-session-row");
const session1Cells = rows.at(1)!.findAll("div.session-col-value");
await session1Cells.at(2)!.findComponent(VueFeather).trigger("click");
Expand All @@ -225,7 +223,7 @@ describe("SessionsPage", () => {
});

it("copy link dispatches GenerateFriendlyId only if session has no friendly id", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
// session 1 already has a friendly id so action should not be dispatched
await wrapper.find("#current-session .session-copy-link").trigger("click");
expect(mockGenerateFriendlyId).not.toHaveBeenCalled();
Expand All @@ -237,7 +235,7 @@ describe("SessionsPage", () => {
});

it("copy code dispatches GenerateFriendlyId only if session has no friendly id", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
// session 1 already has a friendly id so action should not be dispatched
await wrapper.find("#current-session .session-copy-code").trigger("click");
expect(mockGenerateFriendlyId).not.toHaveBeenCalled();
Expand All @@ -249,7 +247,7 @@ describe("SessionsPage", () => {
});

it("copy link copies link to clipboard and updates confirmation", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);

// current session
await wrapper.find("#current-session .session-copy-link").trigger("click");
Expand All @@ -268,7 +266,7 @@ describe("SessionsPage", () => {
});

it("copy code copies friendly id to clipboard and updates confirmation", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);

// current session
await wrapper.find("#current-session .session-copy-code").trigger("click");
Expand All @@ -285,7 +283,7 @@ describe("SessionsPage", () => {
});

it("mouseleave event from copy control in previous session row clears confirm text", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
const rows = wrapper.findAll(".previous-session-row");
const session3Cells = rows.at(1)!.findAll("div.session-col-value");
await session3Cells.at(5)!.find(".session-copy-code").trigger("click");
Expand All @@ -296,7 +294,7 @@ describe("SessionsPage", () => {
});

it("mouseleave event from copy control for current session clears confirm text", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
await wrapper.find("#current-session .session-copy-code").trigger("click");
expect(wrapper.find("#current-session .session-copy-confirm").text()).toBe("Copied: bad-cat");

Expand All @@ -308,7 +306,7 @@ describe("SessionsPage", () => {
const runAsync = async () => {
// the mock generate action won't mutate the state, so friendly id will still be null after it's done,
// and the component will assume the id could not be fetched
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
const rows = wrapper.findAll(".previous-session-row");
const session2Cells = rows.at(0)!.findAll("div.session-col-value");
await session2Cells.at(5)!.find(".session-copy-code").trigger("click");
Expand All @@ -326,7 +324,7 @@ describe("SessionsPage", () => {
});

it("opens and closes confirm delete dialog", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
const rows = wrapper.findAll(".container .row");
const session1Cells = rows.at(3)!.findAll("div.session-col-value");
await session1Cells.at(4)!.findComponent(VueFeather).trigger("click");
Expand All @@ -337,7 +335,7 @@ describe("SessionsPage", () => {
});

it("deletes session on confirm", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
const rows = wrapper.findAll(".container .row");
const session1Cells = rows.at(3)!.findAll("div.session-col-value");
await session1Cells.at(4)!.findComponent(VueFeather).trigger("click"); // set session to delete
Expand All @@ -352,7 +350,7 @@ describe("SessionsPage", () => {
delete (window as any).location;
window.location = { ...realLocation, assign: jest.fn() };

const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
await wrapper.find("#session-code-input").setValue("bad-dog");
await wrapper.find("#load-session-from-code").trigger("click");
expect(window.location.assign).toHaveBeenCalledTimes(1);
Expand All @@ -362,21 +360,21 @@ describe("SessionsPage", () => {
});

it("can save show unlabelled sessions preference", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
await wrapper.find("input#show-unlabelled-check").trigger("click");
expect(mockSaveUserPreferences).toHaveBeenCalledTimes(1);
expect(mockSaveUserPreferences.mock.calls[0][1]).toStrictEqual({ showUnlabelledSessions: false });
});

it("can save show duplicate sessions preference", async () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId);
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId);
await wrapper.find("input#show-duplicates-check").trigger("click");
expect(mockSaveUserPreferences).toHaveBeenCalledTimes(1);
expect(mockSaveUserPreferences.mock.calls[0][1]).toStrictEqual({ showDuplicateSessions: true });
});

it("when showUnlabelledSessions is false, filters out unlabelled sessions from view", () => {
const wrapper = getWrapper(sessionsMetadata, currentSessionId,
const wrapper = getWrapper({ sessionsMetadata }, currentSessionId,
{ showUnlabelledSessions: false, showDuplicateSessions: true });
const rows = wrapper.findAll(".container .row");

Expand Down Expand Up @@ -405,9 +403,21 @@ describe("SessionsPage", () => {
});

it("clicking start session initialises session and navigates to app homepage", async () => {
const wrapper = getWrapper(sessionsMetadata, undefined);
const wrapper = getWrapper({ sessionsMetadata }, undefined);
await wrapper.find("span#start-session").trigger("click");
expect(mockInitialiseSession.mock.calls[0][1]).toStrictEqual({ loadSessionId: "", copySession: true });
expect(mockRouter.push).toHaveBeenCalledWith("/");
});

it("does not show reload session option if there is no latest session id", () => {
const wrapper = getWrapper({ sessionsMetadata }, undefined);
expect(wrapper.find("#reload-session").exists()).toBe(false);
});

it("clicking reload session initialises session and navigates to app homepage", async () => {
const wrapper = getWrapper({ sessionsMetadata, latestSessionId: "xyz" }, undefined);
await wrapper.find("#reload-session").trigger("click");
expect(mockInitialiseSession.mock.calls[0][1]).toStrictEqual({ loadSessionId: "xyz", copySession: false });
expect(mockRouter.push).toHaveBeenCalledWith("/");
});
});
Loading

0 comments on commit 97cba33

Please sign in to comment.