Skip to content

Commit

Permalink
Merge branch 'main' into BC-8427-member-dialogs-a11y
Browse files Browse the repository at this point in the history
  • Loading branch information
NFriedo authored Dec 5, 2024
2 parents 528e8ae + 58241d7 commit c25cbf8
Show file tree
Hide file tree
Showing 47 changed files with 1,016 additions and 246 deletions.
46 changes: 30 additions & 16 deletions src/components/share/ImportFlow.unit.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import vCustomDialog from "@/components/organisms/vCustomDialog.vue";
import ImportFlow from "@/components/share/ImportFlow.vue";
import ImportModal from "@/components/share/ImportModal.vue";
import SelectCourseModal from "@/components/share/SelectCourseModal.vue";
import SelectDestinationModal from "@/components/share/SelectDestinationModal.vue";
import {
CopyApiResponse,
CopyApiResponseStatusEnum,
Expand All @@ -11,15 +11,20 @@ import {
} from "@/serverApi/v3";
import { courseRoomListModule } from "@/store";
import CopyModule from "@/store/copy";
import CourseRoomListModule from "@/store/course-room-list";
import EnvConfigModule from "@/store/env-config";
import LoadingStateModule from "@/store/loading-state";
import NotifierModule from "@/store/notifier";
import CourseRoomListModule from "@/store/course-room-list";
import {
COPY_MODULE_KEY,
ENV_CONFIG_MODULE_KEY,
LOADING_STATE_MODULE_KEY,
NOTIFIER_MODULE_KEY,
} from "@/utils/inject";
import {
apiResponseErrorFactory,
axiosErrorFactory,
} from "@@/tests/test-utils";
import { createModuleMocks } from "@@/tests/test-utils/mock-store-module";
import {
createTestingI18n,
Expand Down Expand Up @@ -59,7 +64,7 @@ describe("@components/share/ImportFlow", () => {
],
provide: {
[COPY_MODULE_KEY.valueOf()]: copyModuleMock,
loadingStateModule: loadingStateModuleMock,
[LOADING_STATE_MODULE_KEY]: loadingStateModuleMock,
[NOTIFIER_MODULE_KEY.valueOf()]: notifierModule,
[ENV_CONFIG_MODULE_KEY.valueOf()]: envConfigModuleMock,
},
Expand Down Expand Up @@ -122,7 +127,16 @@ describe("@components/share/ImportFlow", () => {

it("is shown for insufficient permissions", async () => {
copyModuleMock.validateShareToken = () =>
Promise.reject({ response: { status: 403 } });
Promise.reject(
axiosErrorFactory.build({
response: {
data: apiResponseErrorFactory.build({
message: "FORBIDDEN",
code: 403,
}),
},
})
);
setup();
await nextTick();

Expand Down Expand Up @@ -151,7 +165,7 @@ describe("@components/share/ImportFlow", () => {
await nextTick();

const selectCourseModal = wrapper.findComponent({
name: "select-course-modal",
name: "SelectDestinationModal",
});

expect(selectCourseModal.props("isOpen")).toBe(true);
Expand All @@ -166,7 +180,7 @@ describe("@components/share/ImportFlow", () => {
select.setValue(course);

const selectCourseDialog = wrapper
.findComponent(SelectCourseModal)
.findComponent(SelectDestinationModal)
.findComponent(vCustomDialog);
selectCourseDialog.vm.$emit("next");

Expand All @@ -185,7 +199,7 @@ describe("@components/share/ImportFlow", () => {
select.setValue(course);

const selectCourseDialog = wrapper
.findComponent(SelectCourseModal)
.findComponent(SelectDestinationModal)
.findComponent(vCustomDialog);
selectCourseDialog.vm.$emit("next");

Expand All @@ -195,7 +209,7 @@ describe("@components/share/ImportFlow", () => {
importModalDialog.vm.$emit("dialog-confirmed");

expect(copyModuleMock.copyByShareToken).toHaveBeenCalledWith({
destinationCourseId: course.id,
destinationId: course.id,
token,
type: ShareTokenBodyParamsParentTypeEnum.Lessons,
newName: originalName,
Expand All @@ -217,7 +231,7 @@ describe("@components/share/ImportFlow", () => {
await nextTick();

const selectCourseModal = wrapper.findComponent({
name: "select-course-modal",
name: "SelectDestinationModal",
});
expect(selectCourseModal.props("isOpen")).toBe(true);
});
Expand All @@ -231,7 +245,7 @@ describe("@components/share/ImportFlow", () => {
select.setValue(course);

const selectCourseDialog = wrapper
.findComponent(SelectCourseModal)
.findComponent(SelectDestinationModal)
.findComponent(vCustomDialog);
selectCourseDialog.vm.$emit("next");

Expand All @@ -250,7 +264,7 @@ describe("@components/share/ImportFlow", () => {
select.setValue(course);

const selectCourseDialog = wrapper
.findComponent(SelectCourseModal)
.findComponent(SelectDestinationModal)
.findComponent(vCustomDialog);
selectCourseDialog.vm.$emit("next");

Expand All @@ -260,7 +274,7 @@ describe("@components/share/ImportFlow", () => {
importModalDialog.vm.$emit("dialog-confirmed");

expect(copyModuleMock.copyByShareToken).toHaveBeenCalledWith({
destinationCourseId: course.id,
destinationId: course.id,
token,
type: ShareTokenBodyParamsParentTypeEnum.Tasks,
newName: originalName,
Expand Down Expand Up @@ -427,7 +441,7 @@ describe("@components/share/ImportFlow", () => {
await nextTick();

const selectCourseModal = wrapper.findComponent({
name: "select-course-modal",
name: "SelectDestinationModal",
});

expect(selectCourseModal.props("isOpen")).toBe(true);
Expand All @@ -442,7 +456,7 @@ describe("@components/share/ImportFlow", () => {
select.setValue(course);

const selectCourseDialog = wrapper
.findComponent(SelectCourseModal)
.findComponent(SelectDestinationModal)
.findComponent(vCustomDialog);
selectCourseDialog.vm.$emit("next");

Expand All @@ -461,7 +475,7 @@ describe("@components/share/ImportFlow", () => {
select.setValue(course);

const selectCourseDialog = wrapper
.findComponent(SelectCourseModal)
.findComponent(SelectDestinationModal)
.findComponent(vCustomDialog);
selectCourseDialog.vm.$emit("next");

Expand All @@ -471,7 +485,7 @@ describe("@components/share/ImportFlow", () => {
importModalDialog.vm.$emit("dialog-confirmed");

expect(copyModuleMock.copyByShareToken).toHaveBeenCalledWith({
destinationCourseId: course.id,
destinationId: course.id,
token,
type: ShareTokenBodyParamsParentTypeEnum.ColumnBoard,
newName: originalName,
Expand Down
67 changes: 41 additions & 26 deletions src/components/share/ImportFlow.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<template>
<div>
<select-course-modal
<SelectDestinationModal
:is-open="isSelectCourseModalOpen"
:parent-name="parentName"
:parent-type="parentType"
:courses="courses"
@next="onCourseSelected"
:destinations="destinations"
:destination-type="destinationType"
@next="onReferenceSelected"
@cancel="onCancel"
/>
<import-modal
Expand All @@ -24,19 +25,25 @@
</div>
</template>

<script setup>
<script setup lang="ts">
import ImportModal from "@/components/share/ImportModal.vue";
import { useLoadingState } from "@/composables/loadingState";
import { ShareTokenBodyParamsParentTypeEnum } from "@/serverApi/v3/api";
import {
BoardExternalReferenceType,
ShareTokenInfoResponseParentTypeEnum,
} from "@/serverApi/v3/api";
import { ImportDestinationItem } from "@/store/types/rooms";
import { mapAxiosErrorToResponseError } from "@/utils/api";
import {
COPY_MODULE_KEY,
LOADING_STATE_MODULE_KEY,
NOTIFIER_MODULE_KEY,
injectStrict,
} from "@/utils/inject";
import { computed, inject, ref } from "vue";
import CopyResultModal from "../copy-result-modal/CopyResultModal.vue";
import SelectCourseModal from "./SelectCourseModal.vue";
import { PropType, computed, ref } from "vue";
import { useI18n } from "vue-i18n";
import CopyResultModal from "../copy-result-modal/CopyResultModal.vue";
import SelectDestinationModal from "./SelectDestinationModal.vue";
const props = defineProps({
token: {
Expand All @@ -47,8 +54,12 @@ const props = defineProps({
type: Boolean,
required: true,
},
courses: {
type: Array,
destinations: {
type: Array as PropType<ImportDestinationItem[]>,
required: true,
},
destinationType: {
type: String as PropType<BoardExternalReferenceType>,
required: true,
},
});
Expand All @@ -57,13 +68,15 @@ const emit = defineEmits(["success"]);
const { t } = useI18n();
const copyModule = injectStrict(COPY_MODULE_KEY);
const notifier = injectStrict(NOTIFIER_MODULE_KEY);
const loadingStateModule = inject("loadingStateModule");
const loadingStateModule = injectStrict(LOADING_STATE_MODULE_KEY);
const parentName = ref("");
const parentType = ref("lessons");
const parentType = ref<ShareTokenInfoResponseParentTypeEnum>(
ShareTokenInfoResponseParentTypeEnum.Lessons
);
const newName = ref("");
const destinationCourseId = ref(undefined);
const destinationId = ref<string>();
const isSelectCourseModalOpen = ref(false);
const isImportModalOpen = ref(false);
Expand All @@ -82,7 +95,7 @@ const { isLoadingDialogOpen } = useLoadingState(
t("components.molecules.import.options.loadingMessage")
);
const openModal = (modalName) => {
const openModal = (modalName: string) => {
isSelectCourseModalOpen.value = modalName === "selectCourse";
isImportModalOpen.value = modalName === "import";
isLoadingDialogOpen.value = modalName === "loading";
Expand All @@ -93,7 +106,7 @@ const closeModals = () => openModal("none");
// notifiers
const showFailureBackend = (name) => {
const showFailureBackend = (name: string) => {
notifier.show({
text: t("components.molecules.import.options.failure.backendError", {
name,
Expand Down Expand Up @@ -134,12 +147,14 @@ async function validateShareToken() {
parentName.value = validateResult.parentName;
parentType.value = validateResult.parentType;
openModal(
parentType.value === ShareTokenBodyParamsParentTypeEnum.Courses
parentType.value === ShareTokenInfoResponseParentTypeEnum.Courses
? "import"
: "selectCourse"
);
} catch (error) {
if (error.response?.status === 403) {
} catch (error: unknown) {
const apiError = mapAxiosErrorToResponseError(error);
if (apiError.code === 403) {
showFailurePermission();
} else {
showFailureInvalidToken();
Expand All @@ -148,38 +163,38 @@ async function validateShareToken() {
}
}
async function startImport(name) {
async function startImport(name: string) {
newName.value = name;
openModal("loading");
try {
await copyModule.copyByShareToken({
token: props.token,
type: parentType.value,
newName: newName.value,
destinationCourseId: destinationCourseId.value,
destinationId: destinationId.value,
});
if (copyResultModalItems.value.length === 0) {
loadingStateModule.close();
emit("success", newName.value, destinationCourseId.value);
emit("success", newName.value, destinationId.value);
copyModule.reset();
} else {
openModal("result");
}
} catch (error) {
} catch (error: unknown) {
showFailureBackend(newName.value);
}
}
// event handlers
const onCourseSelected = (courseId) => {
destinationCourseId.value = courseId;
const onReferenceSelected = (referenceId: string) => {
destinationId.value = referenceId;
openModal("import");
};
const onImport = (newName) => startImport(newName);
const onImport = (newName: string) => startImport(newName);
const onCancel = () => closeModals();
const onCopyResultModalClosed = () => {
emit("success", newName.value);
emit("success", newName.value, destinationId.value);
copyModule.reset();
};
</script>
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { mount } from "@vue/test-utils";
import SelectCourseModal from "@/components/share/SelectCourseModal.vue";
import SelectDestinationModal from "@/components/share/SelectDestinationModal.vue";
import {
createTestingI18n,
createTestingVuetify,
} from "@@/tests/test-utils/setup";

describe("@components/share/SelectCourseModal", () => {
describe("@components/share/SelectDestinationModal", () => {
const course = {
id: "1234",
title: "Mathe",
Expand All @@ -20,7 +20,7 @@ describe("@components/share/SelectCourseModal", () => {
};

const setup = () => {
const wrapper = mount(SelectCourseModal, {
const wrapper = mount(SelectDestinationModal, {
global: {
plugins: [createTestingVuetify(), createTestingI18n()],
},
Expand Down
Loading

0 comments on commit c25cbf8

Please sign in to comment.