Skip to content

Commit

Permalink
Merge branch 'BC-5444-typing-date' of https://github.com/hpi-schul-cl…
Browse files Browse the repository at this point in the history
…oud/nuxt-client into BC-5444-typing-date
  • Loading branch information
odalys-dataport committed Nov 3, 2023
2 parents 489c6f6 + cca4aa4 commit c279749
Show file tree
Hide file tree
Showing 23 changed files with 807 additions and 620 deletions.
32 changes: 32 additions & 0 deletions src/components/data-external-tool/ExternalToolApi.composable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
ToolApiFactory,
ToolApiInterface,
ToolLaunchRequestResponse,
} from "@/serverApi/v3";
import { ToolLaunchRequest } from "@/store/external-tool";
import { ExternalToolMapper } from "@/store/external-tool/mapper";
import { $axios } from "@/utils/api";
import { AxiosResponse } from "axios";

export const useExternalToolApi = () => {
const toolApi: ToolApiInterface = ToolApiFactory(undefined, "/v3", $axios);

const fetchLaunchDataCall = async (
contextExternalToolId: string
): Promise<ToolLaunchRequest> => {
const response: AxiosResponse<ToolLaunchRequestResponse> =
await toolApi.toolLaunchControllerGetToolLaunchRequest(
contextExternalToolId
);

const mapped: ToolLaunchRequest = ExternalToolMapper.mapToToolLaunchRequest(
response.data
);

return mapped;
};

return {
fetchLaunchDataCall,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as serverApi from "@/serverApi/v3/api";
import { ToolLaunchRequestResponse } from "@/serverApi/v3/api";
import {
ToolLaunchRequest,
ToolLaunchRequestMethodEnum,
} from "@/store/external-tool";
import {
mockApiResponse,
toolLaunchRequestResponseFactory,
} from "@@/tests/test-utils";
import { createMock, DeepMocked } from "@golevelup/ts-jest";
import { useExternalToolApi } from "./ExternalToolApi.composable";

describe("ExternalToolApi.composable", () => {
let toolApi: DeepMocked<serverApi.ToolApiInterface>;

beforeEach(() => {
toolApi = createMock<serverApi.ToolApiInterface>();

jest.spyOn(serverApi, "ToolApiFactory").mockReturnValue(toolApi);
});

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

describe("fetchLaunchDataCall", () => {
const setup = () => {
const launchRequest: ToolLaunchRequestResponse =
toolLaunchRequestResponseFactory.build();

toolApi.toolLaunchControllerGetToolLaunchRequest.mockResolvedValue(
mockApiResponse({ data: launchRequest })
);

return {
launchRequest,
};
};

it("should call the api for a tool launch request", async () => {
setup();

await useExternalToolApi().fetchLaunchDataCall("contextExternalToolId");

expect(
toolApi.toolLaunchControllerGetToolLaunchRequest
).toHaveBeenCalledWith("contextExternalToolId");
});

it("should return launch request data", async () => {
const { launchRequest } = setup();

const result: ToolLaunchRequest =
await useExternalToolApi().fetchLaunchDataCall("contextExternalToolId");

expect(result).toEqual<ToolLaunchRequest>({
url: launchRequest.url,
payload: launchRequest.payload,
method: ToolLaunchRequestMethodEnum.Get,
openNewTab: launchRequest.openNewTab,
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { ExternalToolDisplayData } from "@/store/external-tool";
import { externalToolDisplayDataFactory } from "@@/tests/test-utils";
import { createMock, DeepMocked } from "@golevelup/ts-jest";
import { useErrorHandler } from "../error-handling/ErrorHandler.composable";
import { useContextExternalToolApi } from "./ContextExternalToolApi.composable";
import { useExternalToolElementDisplayState } from "./ExternalToolElementDisplayState.composable";
import { useContextExternalToolApi } from "./index";

jest.mock("@data-external-tool");
jest.mock("@data-external-tool/ContextExternalToolApi.composable");
jest.mock("@/components/error-handling/ErrorHandler.composable");

describe("ExternalToolElementDisplayState.composable", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
ToolLaunchRequest,
ToolLaunchRequestMethodEnum,
} from "@/store/external-tool";
import { BusinessError } from "@/store/types/commons";
import { HttpStatusCode } from "@/store/types/http-status-code.enum";
import { mapAxiosErrorToResponseError } from "@/utils/api";
import { ref, Ref } from "vue";
import { useExternalToolApi } from "./ExternalToolApi.composable";

export const useExternalToolLaunchState = () => {
const { fetchLaunchDataCall } = useExternalToolApi();

const isLoading: Ref<boolean> = ref(false);
const error: Ref<BusinessError | undefined> = ref();
const toolLaunchRequest: Ref<ToolLaunchRequest | undefined> = ref();

const fetchLaunchRequest = async (
contextExternalToolId: string
): Promise<void> => {
isLoading.value = true;
error.value = undefined;

try {
toolLaunchRequest.value = await fetchLaunchDataCall(
contextExternalToolId
);
} catch (axiosError: unknown) {
const apiError = mapAxiosErrorToResponseError(axiosError);

error.value = {
error: apiError,
message: apiError.message,
statusCode: apiError.code,
};
}

isLoading.value = false;
};

const launchTool = () => {
if (!toolLaunchRequest.value) {
return;
}

switch (toolLaunchRequest.value.method) {
case ToolLaunchRequestMethodEnum.Get:
handleGetLaunchRequest(toolLaunchRequest.value);
break;
case ToolLaunchRequestMethodEnum.Post:
handlePostLaunchRequest(toolLaunchRequest.value);
break;
default:
error.value = {
message: "Unknown launch method",
statusCode: HttpStatusCode.UnprocessableEntity,
};
break;
}
};

const handleGetLaunchRequest = (toolLaunch: ToolLaunchRequest) => {
if (toolLaunch.openNewTab) {
window.open(toolLaunch.url, "_blank");
return;
}
window.location.href = toolLaunch.url;
};

const handlePostLaunchRequest = (toolLaunch: ToolLaunchRequest) => {
const form: HTMLFormElement = document.createElement("form");
form.method = "POST";
form.action = toolLaunch.url;
form.target = toolLaunch.openNewTab ? "_blank" : "_self";
form.id = "launch-form";

const payload = JSON.parse(toolLaunch.payload || "{}");

for (const key in payload) {
if (Object.prototype.hasOwnProperty.call(payload, key)) {
const hiddenField = document.createElement("input");
hiddenField.type = "hidden";
hiddenField.name = key;
hiddenField.value = payload[key];

form.appendChild(hiddenField);
}
}

document.body.appendChild(form);
form.submit();
};

return {
toolLaunchRequest,
error,
isLoading,
fetchLaunchRequest,
launchTool,
};
};
Loading

0 comments on commit c279749

Please sign in to comment.