Skip to content

Commit

Permalink
Merge branch 'main' into N21-2409-link-element-same-page-link
Browse files Browse the repository at this point in the history
  • Loading branch information
MarvinOehlerkingCap authored Feb 26, 2025
2 parents 383f118 + f11895c commit d64433c
Show file tree
Hide file tree
Showing 86 changed files with 2,235 additions and 1,289 deletions.
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module.exports = [
"error",
{ allowInterfaces: "with-single-extends" },
],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-require-imports": "warn",
"@typescript-eslint/no-restricted-imports": [
Expand Down
30 changes: 30 additions & 0 deletions src/components/administration/VidisMediaSyncSection.unit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import NotifierModule from "@/store/notifier";
import { NOTIFIER_MODULE_KEY } from "@/utils/inject";
import { axiosErrorFactory } from "@@/tests/test-utils";
import { createModuleMocks } from "@@/tests/test-utils/mock-store-module";
import {
createTestingI18n,
Expand All @@ -8,6 +9,7 @@ import {
import { useSchoolLicenseApi } from "@data-license";
import { createMock, DeepMocked } from "@golevelup/ts-jest";
import { mount } from "@vue/test-utils";
import { HttpStatusCode } from "../../store/types/http-status-code.enum";
import VidisMediaSyncSection from "./VidisMediaSyncSection.vue";

jest.mock("@data-license");
Expand Down Expand Up @@ -78,6 +80,34 @@ describe("VidisMediaSyncSection", () => {
});
});

describe("when the request fails with a timeout", () => {
const setup = () => {
const { wrapper } = getWrapper();

useSchoolLicenseApiMock.updateSchoolLicenses.mockRejectedValueOnce(
axiosErrorFactory
.withStatusCode(HttpStatusCode.RequestTimeout)
.build()
);

return {
wrapper,
};
};

it("should show a failure notification", async () => {
const { wrapper } = setup();

const button = wrapper.find('[data-testid="sync-vidis-media-button"]');
await button.trigger("click");

expect(notifierModule.show).toHaveBeenCalledWith({
status: "info",
text: "components.administration.externalToolsSection.vidis.notification.timeout",
});
});
});

describe("when the request fails", () => {
const setup = () => {
const { wrapper } = getWrapper();
Expand Down
23 changes: 18 additions & 5 deletions src/components/administration/VidisMediaSyncSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

<script setup lang="ts">
import NotifierModule from "@/store/notifier";
import { HttpStatusCode } from "@/store/types/http-status-code.enum";
import { mapAxiosErrorToResponseError } from "@/utils/api";
import { injectStrict, NOTIFIER_MODULE_KEY } from "@/utils/inject";
import { useSchoolLicenseApi } from "@data-license";
import { ref } from "vue";
Expand All @@ -48,11 +50,22 @@ const updateVidisLicenses = async () => {
"components.administration.externalToolsSection.vidis.notification.success"
),
});
} catch (e) {
notifierModule.show({
status: "error",
text: t("common.notification.error"),
});
} catch (errorResponse: unknown) {
const apiError = mapAxiosErrorToResponseError(errorResponse);
if (apiError.code === HttpStatusCode.RequestTimeout) {
notifierModule.show({
status: "info",
text: t(
"components.administration.externalToolsSection.vidis.notification.timeout"
),
});
} else {
notifierModule.show({
status: "error",
text: t("common.notification.error"),
});
}
}
isLoading.value = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function useExternalToolsSectionUtils(
t: (key: string) => string = () => "",
mediaLicenseEnabled = false
) {
const getHeaders: DataTableHeader[] = [
const getHeaders: DataTableHeader<SchoolExternalToolMediumResponse>[] = [
{
title: t("common.labels.name"),
value: "name",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ describe("useSchoolExternalToolUtils", () => {
const { tool } = setupTool();
const { getHeaders } = setup(tool);

const headers: DataTableHeader[] = getHeaders;

expect(Array.isArray(headers)).toBeTruthy();
expect(Array.isArray(getHeaders)).toBeTruthy();
});

describe("when translate the headers", () => {
Expand Down Expand Up @@ -97,24 +95,22 @@ describe("useSchoolExternalToolUtils", () => {
const { tool } = setupTool();
const { getHeaders, expectedTranslation } = setup(tool);

const headers: DataTableHeader[] = getHeaders;

expect(headers[0].title).toEqual(expectedTranslation);
expect(headers[0].value).toEqual("name");
expect(getHeaders[0].title).toEqual(expectedTranslation);
expect(getHeaders[0].value).toEqual("name");

expect(headers[1].title).toEqual(expectedTranslation);
expect(headers[1].value).toEqual("statusText");
expect(getHeaders[1].title).toEqual(expectedTranslation);
expect(getHeaders[1].value).toEqual("statusText");

expect(headers[2].title).toEqual(expectedTranslation);
expect(headers[2].value).toEqual("medium");
expect(getHeaders[2].title).toEqual(expectedTranslation);
expect(getHeaders[2].value).toEqual("medium");

expect(headers[3].title).toEqual(expectedTranslation);
expect(headers[3].value).toEqual("restrictToContexts");
expect(getHeaders[3].title).toEqual(expectedTranslation);
expect(getHeaders[3].value).toEqual("restrictToContexts");

expect(headers[4].title).toEqual("");
expect(headers[4].value).toEqual("actions");
expect(headers[4].sortable).toBe(false);
expect(headers[4].align).toEqual("end");
expect(getHeaders[4].title).toEqual("");
expect(getHeaders[4].value).toEqual("actions");
expect(getHeaders[4].sortable).toBe(false);
expect(getHeaders[4].align).toEqual("end");
});
});

Expand Down
11 changes: 8 additions & 3 deletions src/components/error-handling/ErrorHandler.composable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export type ErrorType =
| "notCreated"
| "notLoaded"
| "notUpdated"
| "notDeleted";
| "notDeleted"
| "notMoved";

export type BoardObjectType =
| "board"
Expand All @@ -22,8 +23,12 @@ export type ApiErrorHandler = (
error?: ApiResponseError | ApiValidationError
) => Promise<void> | void;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type ApiErrorHandlerFactory = (...args: any[]) => ApiErrorHandler;
export type ApiErrorHandlerFactory = (
errorType: ErrorType,
boardObjectType?: BoardObjectType,
status?: ErrorStatus,
timeout?: number
) => ApiErrorHandler;

export type ErrorMap = Record<number, ApiErrorHandler>;

Expand Down
11 changes: 6 additions & 5 deletions src/components/lern-store/AddContentButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
getMediatype,
getID,
} from "@/utils/helpers";
import { $axios } from "@/utils/api";
let slowAPICall;
Expand Down Expand Up @@ -121,10 +122,10 @@ export default {
url() {
if (getMediatype(this.resource) === "file-h5p") {
let baseUrlH5p = "";
if (this.$axios.defaults.baseURL.includes("/api")) {
baseUrlH5p = this.$axios.defaults.baseURL.slice(0, -4);
if ($axios.defaults.baseURL.includes("/api")) {
baseUrlH5p = $axios.defaults.baseURL.slice(0, -4);
} else {
baseUrlH5p = this.$axios.defaults.baseURL;
baseUrlH5p = $axios.defaults.baseURL;
}
return (
baseUrlH5p +
Expand Down Expand Up @@ -153,7 +154,7 @@ export default {
if (getMediatype(element) === "file-h5p") {
const elementID = getID(element);
if (elementID !== null) {
const baseUrlH5p = this.$axios.defaults.baseURL.slice(0, -4);
const baseUrlH5p = $axios.defaults.baseURL.slice(0, -4);
elementUrl = `${baseUrlH5p}/content/${elementID}`;
} else {
elementUrl = null;
Expand Down Expand Up @@ -185,7 +186,7 @@ export default {
let url = element.url;
if (element.merlinReference) {
const requestUrl = `/v1/edu-sharing-merlinToken/?merlinReference=${element.merlinReference}`;
url = (await this.$axios.get(requestUrl)).data || element.url;
url = (await $axios.get(requestUrl)).data || element.url;
}
return {
title: element.title,
Expand Down
3 changes: 2 additions & 1 deletion src/components/lern-store/LernstoreDetailView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ import { buildPageTitle } from "@/utils/pageTitle";
import { RenderHTML } from "@feature-render-html";
import { mdiCalendar, mdiClose, mdiOpenInNew, mdiPound } from "@icons/material";
import BaseLink from "../base/BaseLink";
import { $axios } from "@/utils/api";
const DEFAULT_AUTHOR = "admin";
Expand Down Expand Up @@ -319,7 +320,7 @@ export default {
methods: {
async goToMerlinContent(merlinReference) {
const requestUrl = `/v1/edu-sharing-merlinToken/?merlinReference=${merlinReference}`;
const url = (await this.$axios.get(requestUrl)).data;
const url = (await $axios.get(requestUrl)).data;
window.open(url, "_blank");
},
isNotStudent(roles) {
Expand Down
22 changes: 14 additions & 8 deletions src/components/molecules/CommonCartridgeExportModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,13 @@
</template>

<script setup lang="ts">
import { BoardElementResponseTypeEnum } from "@/serverApi/v3/api";
import {
BoardColumnBoard,
BoardElement,
BoardElementType,
BoardLesson,
BoardTask,
} from "@/types/course-room/CourseRoom";
import {
COMMON_CARTRIDGE_EXPORT_MODULE_KEY,
injectStrict,
Expand Down Expand Up @@ -223,27 +229,27 @@ watch(
allTasks.value = [];
allColumnBoards.value = [];
newValue.forEach((element: any) => {
if (element.type === BoardElementResponseTypeEnum.Lesson) {
newValue.forEach((element: BoardElement) => {
if (element.type === BoardElementType.Lesson) {
allTopics.value.push({
isSelected: true,
title: element.content.name,
title: (element.content as BoardLesson).name,
id: element.content.id,
});
}
if (element.type === BoardElementResponseTypeEnum.Task) {
if (element.type === BoardElementType.Task) {
allTasks.value.push({
isSelected: true,
title: element.content.name,
title: (element.content as BoardTask).name,
id: element.content.id,
});
}
if (element.type === BoardElementResponseTypeEnum.ColumnBoard) {
if (element.type === BoardElementType.ColumnBoard) {
allColumnBoards.value.push({
isSelected: true,
title: element.content.title,
title: (element.content as BoardColumnBoard).title,
id: element.content.id,
});
}
Expand Down
14 changes: 7 additions & 7 deletions src/components/molecules/CommonCartridgeImportModal.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,29 +59,29 @@ describe("@/components/molecules/CommonCartridgeImportModal", () => {

const confirmBtn = wrapper.findComponent(
"[data-testId='dialog-confirm-btn']"
) as any;
);

expect(confirmBtn.exists()).toBe(true);
expect(confirmBtn.isDisabled()).toBe(true);
expect(confirmBtn.classes()).toContain("v-btn--disabled");
});

it("should contain enabled cancel button", async () => {
const { wrapper } = setup();

const cancelBtn = wrapper.findComponent(
"[data-testid='dialog-cancel-btn']"
) as any;
);

expect(cancelBtn.exists()).toBe(true);
expect(cancelBtn.isDisabled()).toBe(false);
expect(cancelBtn.classes()).not.toContain("v-btn--disabled");
});

it("should contain file input", () => {
const { wrapper } = setup();

const fileInput = wrapper.findComponent(
"[data-testid='dialog-file-input']"
) as any;
);

expect(fileInput.exists()).toBe(true);
});
Expand All @@ -99,9 +99,9 @@ describe("@/components/molecules/CommonCartridgeImportModal", () => {

const confirmBtn = wrapper.findComponent(
"[data-testId='dialog-confirm-btn']"
) as any;
);

expect(confirmBtn.isDisabled()).toBe(false);
expect(confirmBtn.classes()).not.toContain("v-btn--disabled");
});
});

Expand Down
7 changes: 5 additions & 2 deletions src/components/molecules/InfoBox.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import {
} from "@@/tests/test-utils/setup";
import { mount } from "@vue/test-utils";
import InfoBox from "./InfoBox.vue";
import { VNode } from "vue";

type MountingSlots = Record<string, string | (() => VNode[])>;

describe("@/components/molecules/InfoBox", () => {
describe("when active is true", () => {
const setup = (slots: any) => {
const setup = (slots: MountingSlots) => {
const wrapper = mount(InfoBox, {
global: { plugins: [createTestingVuetify(), createTestingI18n()] },
props: {
Expand Down Expand Up @@ -44,7 +47,7 @@ describe("@/components/molecules/InfoBox", () => {
});

describe("when active is false", () => {
const setup = (slots: any) => {
const setup = (slots: MountingSlots) => {
const wrapper = mount(InfoBox, {
global: { plugins: [createTestingVuetify(), createTestingI18n()] },
props: {
Expand Down
Loading

0 comments on commit d64433c

Please sign in to comment.