Skip to content

Commit

Permalink
add launch of tool on the media shelf
Browse files Browse the repository at this point in the history
  • Loading branch information
MarvinOehlerkingCap committed Apr 18, 2024
1 parent f743625 commit b35d3df
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 62 deletions.
252 changes: 202 additions & 50 deletions src/modules/feature/media-shelf/MediaBoardExternalToolElement.unit.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import EnvConfigModule from "@/store/env-config";
import NotifierModule from "@/store/notifier";
import { AlertPayload } from "@/store/types/alert-payload";
import { ComponentProps } from "@/types/vue";
import { ENV_CONFIG_MODULE_KEY, NOTIFIER_MODULE_KEY } from "@/utils/inject";
import { createModuleMocks } from "@/utils/mock-store-module";
import {
axiosErrorFactory,
businessErrorFactory,
envsFactory,
externalToolDisplayDataFactory,
mediaExternalToolElementResponseFactory,
} from "@@/tests/test-utils";
import { useContextExternalToolApi } from "@data-external-tool";
import { createTestingI18n } from "@@/tests/test-utils/setup";
import {
useContextExternalToolApi,
useExternalToolLaunchState,
} from "@data-external-tool";
import { createMock, DeepMocked } from "@golevelup/ts-jest";
import { flushPromises, shallowMount } from "@vue/test-utils";
import { nextTick, ref } from "vue";
import { MediaElementDisplay } from "./data";
import MediaBoardElementDisplay from "./MediaBoardElementDisplay.vue";
import MediaBoardExternalToolElement from "./MediaBoardExternalToolElement.vue";
Expand All @@ -17,108 +29,248 @@ describe("MediaBoardExternalToolElement", () => {
let useContextExternalToolApiMock: DeepMocked<
ReturnType<typeof useContextExternalToolApi>
>;
let useExternalToolLaunchStateMock: DeepMocked<
ReturnType<typeof useExternalToolLaunchState>
>;

const getWrapper = (
props: ComponentProps<typeof MediaBoardExternalToolElement>
) => {
const refreshTime = 299000;
const envConfigModule = createModuleMocks(EnvConfigModule, {
getEnv: envsFactory.build({ CTL_TOOLS_RELOAD_TIME_MS: refreshTime }),
});
const notifierModule = createModuleMocks(NotifierModule);

const wrapper = shallowMount(MediaBoardExternalToolElement, {
global: {
plugins: [createTestingI18n()],
provide: {
[ENV_CONFIG_MODULE_KEY.valueOf()]: envConfigModule,
[NOTIFIER_MODULE_KEY.valueOf()]: notifierModule,
},
},
props,
});

return {
wrapper,
notifierModule,
refreshTime,
};
};

beforeEach(() => {
useContextExternalToolApiMock =
createMock<ReturnType<typeof useContextExternalToolApi>>();
useExternalToolLaunchStateMock = createMock<
ReturnType<typeof useExternalToolLaunchState>
>({
error: ref(),
});

jest
.mocked(useContextExternalToolApi)
.mockReturnValue(useContextExternalToolApiMock);
jest
.mocked(useExternalToolLaunchState)
.mockReturnValue(useExternalToolLaunchStateMock);

jest.useFakeTimers("legacy");
});

afterEach(() => {
jest.resetAllMocks();
});

describe("when the api returns display data", () => {
const setup = async () => {
const externalToolElement =
mediaExternalToolElementResponseFactory.build();
const displayDataResponse = externalToolDisplayDataFactory.build({
name: "name",
description: "description",
describe("when loading external tool data", () => {
describe("when the api returns data", () => {
const setup = async () => {
const externalToolElement =
mediaExternalToolElementResponseFactory.build();
const displayDataResponse = externalToolDisplayDataFactory.build({
name: "name",
description: "description",
});

useContextExternalToolApiMock.fetchDisplayDataCall.mockResolvedValue(
displayDataResponse
);

const { wrapper } = getWrapper({
element: externalToolElement,
});

await flushPromises();

return {
wrapper,
externalToolElement,
displayDataResponse,
};
};

it("should call the api to load display data", async () => {
const { externalToolElement } = await setup();

expect(
useContextExternalToolApiMock.fetchDisplayDataCall
).toHaveBeenCalledWith(
externalToolElement.content.contextExternalToolId
);
});

it("should call the state to load the launch request", async () => {
const { externalToolElement } = await setup();

expect(
useExternalToolLaunchStateMock.fetchLaunchRequest
).toHaveBeenCalledWith(
externalToolElement.content.contextExternalToolId
);
});

useContextExternalToolApiMock.fetchDisplayDataCall.mockResolvedValue(
displayDataResponse
);
it("should map to the display props", async () => {
const { wrapper, displayDataResponse } = await setup();

const displayComponent = wrapper.findComponent(
MediaBoardElementDisplay
);

const { wrapper } = getWrapper({
element: externalToolElement,
expect(displayComponent.props().element).toEqual<MediaElementDisplay>({
title: displayDataResponse.name,
description: displayDataResponse.description,
thumbnail: undefined,
});
});
});

await flushPromises();
describe("when the display data api returns an error", () => {
const setup = async () => {
const externalToolElement =
mediaExternalToolElementResponseFactory.build();
const error = axiosErrorFactory.build();

useContextExternalToolApiMock.fetchDisplayDataCall.mockRejectedValue(
error
);

const logger = jest.spyOn(console, "error").mockImplementation();

const { wrapper } = getWrapper({
element: externalToolElement,
});

await flushPromises();

return {
wrapper,
logger,
error,
};
};

it("should log the error", async () => {
const { logger, error } = await setup();

expect(logger).toHaveBeenCalledWith(error);
});
});
});

describe("when the refresh time is over", () => {
const setup = () => {
const { wrapper, refreshTime } = getWrapper({
element: mediaExternalToolElementResponseFactory.build(),
});

return {
wrapper,
externalToolElement,
displayDataResponse,
refreshTime,
};
};

it("should call the api", async () => {
const { externalToolElement } = await setup();
it("should refresh the display data", async () => {
const { refreshTime } = setup();
await nextTick();

expect(
useContextExternalToolApiMock.fetchDisplayDataCall
).toHaveBeenCalledWith(externalToolElement.content.contextExternalToolId);
});

it("should map to the display props", async () => {
const { wrapper, displayDataResponse } = await setup();
useExternalToolLaunchStateMock.fetchLaunchRequest
).toHaveBeenCalledTimes(1);

const displayComponent = wrapper.findComponent(MediaBoardElementDisplay);
jest.advanceTimersByTime(refreshTime + 1000);
await nextTick();

expect(displayComponent.props().element).toEqual<MediaElementDisplay>({
title: displayDataResponse.name,
description: displayDataResponse.description,
thumbnail: undefined,
});
expect(
useExternalToolLaunchStateMock.fetchLaunchRequest
).toHaveBeenCalledTimes(2);
});
});

describe("when the api returns an error", () => {
const setup = async () => {
const externalToolElement =
mediaExternalToolElementResponseFactory.build();
const error = axiosErrorFactory.build();
describe("when clicking the element", () => {
describe("when a launch request is available", () => {
const setup = () => {
const externalToolElement =
mediaExternalToolElementResponseFactory.build();
const { wrapper } = getWrapper({
element: externalToolElement,
});

return {
wrapper,
externalToolElement,
};
};

useContextExternalToolApiMock.fetchDisplayDataCall.mockRejectedValue(
error
);
it("should launch the tool", async () => {
const { wrapper } = setup();

const logger = jest.spyOn(console, "error").mockImplementation();
await wrapper.trigger("click");

const { wrapper } = getWrapper({
element: externalToolElement,
expect(useExternalToolLaunchStateMock.launchTool).toHaveBeenCalled();
});

await flushPromises();
it("should load the next launch request", async () => {
const { wrapper, externalToolElement } = setup();

return {
wrapper,
logger,
error,
await wrapper.trigger("click");

expect(
useExternalToolLaunchStateMock.fetchLaunchRequest
).toHaveBeenCalledWith(
externalToolElement.content.contextExternalToolId
);
});
});

describe("when loading the launch request failed", () => {
const setup = () => {
const externalToolElement =
mediaExternalToolElementResponseFactory.build();
const { wrapper, notifierModule } = getWrapper({
element: externalToolElement,
});

useExternalToolLaunchStateMock.error.value =
businessErrorFactory.build();

return {
wrapper,
externalToolElement,
notifierModule,
};
};
};

it("should log the error", async () => {
const { logger, error } = await setup();
it("should show an error notification", async () => {
const { wrapper, notifierModule } = setup();

await wrapper.trigger("click");

expect(logger).toHaveBeenCalledWith(error);
expect(notifierModule.show).toHaveBeenCalledWith<[AlertPayload]>({
status: "error",
text: "error.generic",
});
});
});
});
});
Loading

0 comments on commit b35d3df

Please sign in to comment.