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 21, 2025
2 parents ee9be66 + 15d074a commit ccc847a
Show file tree
Hide file tree
Showing 21 changed files with 825 additions and 86 deletions.
128 changes: 92 additions & 36 deletions src/components/administration/ExternalToolSection.unit.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ConfigResponse } from "@/serverApi/v3";
import { ConfigResponse, MediaSourceLicenseType } from "@/serverApi/v3";
import AuthModule from "@/store/auth";
import EnvConfigModule from "@/store/env-config";
import { SchoolExternalToolMetadata } from "@/store/external-tool";
Expand All @@ -10,6 +10,7 @@ import {
NOTIFIER_MODULE_KEY,
SCHOOL_EXTERNAL_TOOLS_MODULE_KEY,
} from "@/utils/inject";
import { mockedPiniaStoreTyping, MockedStore } from "@@/tests/test-utils";
import {
envsFactory,
meResponseFactory,
Expand All @@ -23,9 +24,12 @@ import {
createTestingVuetify,
} from "@@/tests/test-utils/setup";
import { useSchoolExternalToolUsage } from "@data-external-tool";
import { useSchoolLicenseStore } from "@data-license";
import { createMock, DeepMocked } from "@golevelup/ts-jest";
import { mdiAlert, mdiCheckCircle } from "@icons/material";
import { createTestingPinia } from "@pinia/testing";
import { mount } from "@vue/test-utils";
import { setActivePinia } from "pinia";
import { nextTick, ref } from "vue";
import { Router, useRouter } from "vue-router";
import { VCardText } from "vuetify/lib/components/index.mjs";
Expand All @@ -43,6 +47,13 @@ describe("ExternalToolSection", () => {
let useSchoolExternalToolUsageMock: DeepMocked<
ReturnType<typeof useSchoolExternalToolUsage>
>;
let schoolLicenseStore: MockedStore<typeof useSchoolLicenseStore>;

beforeAll(() => {
setActivePinia(createTestingPinia());

schoolLicenseStore = mockedPiniaStoreTyping(useSchoolLicenseStore);
});

const createDatasheetButtonIndex = 1;

Expand Down Expand Up @@ -79,7 +90,6 @@ describe("ExternalToolSection", () => {
const wrapper = mount(ExternalToolSection, {
global: {
plugins: [createTestingVuetify(), createTestingI18n()],

provide: {
[SCHOOL_EXTERNAL_TOOLS_MODULE_KEY.valueOf()]:
schoolExternalToolsModule,
Expand All @@ -88,7 +98,6 @@ describe("ExternalToolSection", () => {
[ENV_CONFIG_MODULE_KEY.valueOf()]: envConfigModule,
},
},

stubs: {
VIcon: true,
},
Expand Down Expand Up @@ -130,6 +139,12 @@ describe("ExternalToolSection", () => {
schoolExternalToolsModule.loadSchoolExternalTools
).toHaveBeenCalledWith("schoolId");
});

it("should load the school licenses", () => {
getWrapper();

expect(schoolLicenseStore.fetchMediaSchoolLicenses).toHaveBeenCalled();
});
});
});

Expand All @@ -145,35 +160,56 @@ describe("ExternalToolSection", () => {
name: firstToolName,
status: schoolToolConfigurationStatusFactory.build(),
isDeactivated: false,
medium: {
mediumId: "tool1",
mediaSourceId: "licensedSource",
mediaSourceName: "Medium Source Name",
mediaSourceLicenseType: MediaSourceLicenseType.SchoolLicense,
},
});

const { wrapper, schoolExternalToolsModule } = getWrapper({
getSchoolExternalTools: [
schoolExternalTool,
{
id: "testId2",
toolId: "toolId",
schoolId: "schoolId",
parameters: [],
name: secondToolName,
status: schoolToolConfigurationStatusFactory.build({
isOutdatedOnScopeSchool: true,
}),
isDeactivated: false,
},
{
id: "testId3",
toolId: "toolId",
schoolId: "schoolId",
parameters: [],
name: "Test3",
status: schoolToolConfigurationStatusFactory.build({
isGloballyDeactivated: true,
}),
isDeactivated: true,
},
],
});
schoolLicenseStore.isLicensed.mockReturnValueOnce(true);
schoolLicenseStore.isLicensed.mockReturnValue(false);

const { wrapper, schoolExternalToolsModule } = getWrapper(
{
getSchoolExternalTools: [
schoolExternalTool,
{
id: "testId2",
toolId: "toolId",
schoolId: "schoolId",
parameters: [],
name: secondToolName,
status: schoolToolConfigurationStatusFactory.build({
isOutdatedOnScopeSchool: true,
}),
isDeactivated: false,
medium: {
mediumId: "tool2",
mediaSourceId: "notLicensedSource",
mediaSourceName: undefined,
mediaSourceLicenseType: MediaSourceLicenseType.SchoolLicense,
},
},
{
id: "testId3",
toolId: "toolId",
schoolId: "schoolId",
parameters: [],
name: "Test3",
status: schoolToolConfigurationStatusFactory.build({
isGloballyDeactivated: true,
}),
isDeactivated: true,
medium: undefined,
},
],
},
{
FEATURE_SCHULCONNEX_MEDIA_LICENSE_ENABLED: true,
}
);

const windowMock = createMock<Window>();
jest.spyOn(window, "open").mockImplementation(() => windowMock);
Expand Down Expand Up @@ -204,9 +240,12 @@ describe("ExternalToolSection", () => {
"components.administration.externalToolsSection.table.header.status"
);
expect(vueWrapperArray[2].find("span").text()).toEqual(
"components.administration.externalToolsSection.table.header.medium"
);
expect(vueWrapperArray[3].find("span").text()).toEqual(
"components.administration.externalToolsSection.table.header.restrictedTo"
);
expect(vueWrapperArray[3].find("span").text()).toEqual("");
expect(vueWrapperArray[4].find("span").text()).toEqual("");
});
});

Expand Down Expand Up @@ -235,24 +274,41 @@ describe("ExternalToolSection", () => {
const secondRow = tableRows[1].findAll("td");
const thirdRow = tableRows[2].findAll("td");

expect(true).toBeTruthy();
expect(firstRow[1].html()).toContain(mdiCheckCircle);
expect(firstRow[1].find("span").text()).toEqual(
"components.externalTools.status.latest"
);
expect(firstRow[1].html()).toContain(mdiCheckCircle);
expect(secondRow[1].find("span").text()).toEqual(
"components.externalTools.status.outdated"
);

expect(secondRow[1].html()).toContain(mdiAlert);
expect(secondRow[1].find("span").text()).toEqual(
"components.externalTools.status.outdated"
);

expect(thirdRow[1].html()).toContain(mdiAlert);
expect(thirdRow[1].find("span").text()).toEqual(
"components.externalTools.status.deactivated"
);
});

it("medium status should be rendered in the datatable", () => {
const { wrapper } = setupItems();

const tableRows = wrapper.find("tbody").findAll("tr");

const firstRow = tableRows[0].findAll("td");
const secondRow = tableRows[1].findAll("td");
const thirdRow = tableRows[2].findAll("td");

expect(firstRow[2].html()).toContain(mdiCheckCircle);
expect(firstRow[2].find("span").text()).toEqual("Medium Source Name");

expect(secondRow[2].html()).toContain(mdiAlert);
expect(secondRow[2].find("span").text()).toEqual("");

expect(thirdRow[2].html()).not.toContain("v-icon");
expect(thirdRow[2].find("span").text()).toEqual("-");
});

describe("when actions buttons are rendered", () => {
it("the buttons should be displayed", () => {
const { wrapper } = setupItems();
Expand Down
76 changes: 70 additions & 6 deletions src/components/administration/ExternalToolSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,50 @@
</span>
</div>
</template>
<template #[`item.medium`]="{ item }">
<div
v-if="item.medium"
class="text-no-wrap"
data-testid="external-tool-medium"
>
<VProgressCircular v-if="isLicensesLoading" />
<VIcon
v-else-if="
item.medium.mediaSourceLicenseType !==
MediaSourceLicenseType.SchoolLicense ||
isLicensedToSchool(
item.medium.mediumId,
item.medium.mediaSourceId
)
"
start
color="success"
aria-hidden="false"
:aria-label="
t(
'components.administration.externalToolsSection.table.ariaLabel.mediumAvailable'
)
"
>
{{ mdiCheckCircle }}
</VIcon>
<VIcon
v-else
start
color="warning"
aria-hidden="false"
:aria-label="
t(
'components.administration.externalToolsSection.table.ariaLabel.mediumUnavailable'
)
"
>
{{ mdiAlert }}
</VIcon>
<span>{{ item.medium.mediaSourceName || "" }}</span>
</div>
<span v-else data-testid="external-tool-medium"> - </span>
</template>
<template #[`item.restrictToContexts`]="{ item }">
<span data-testid="external-tool-context-restriction">
{{ item.restrictToContexts }}
Expand Down Expand Up @@ -145,13 +189,16 @@
</template>

<script setup lang="ts">
import { ToolApiAxiosParamCreator } from "@/serverApi/v3";
import {
MediaSourceLicenseType,
ToolApiAxiosParamCreator,
} from "@/serverApi/v3";
import { RequestArgs } from "@/serverApi/v3/base";
import AuthModule from "@/store/auth";
import EnvConfigModule from "@/store/env-config";
import NotifierModule from "@/store/notifier";
import SchoolExternalToolsModule from "@/store/school-external-tools";
import { DataTableHeader } from "@/store/types/data-table-header";
import { DataTableHeader } from "@/types/vuetify";
import {
AUTH_MODULE_KEY,
ENV_CONFIG_MODULE_KEY,
Expand All @@ -160,6 +207,7 @@ import {
SCHOOL_EXTERNAL_TOOLS_MODULE_KEY,
} from "@/utils/inject";
import { useSchoolExternalToolUsage } from "@data-external-tool";
import { useSchoolLicenseStore } from "@data-license";
import { mdiAlert, mdiCheckCircle } from "@icons/material";
import { computed, ComputedRef, onMounted, Ref, ref } from "vue";
import { useI18n } from "vue-i18n";
Expand All @@ -178,17 +226,22 @@ const authModule: AuthModule = injectStrict(AUTH_MODULE_KEY);
const router = useRouter();
const schoolLicenseStore = useSchoolLicenseStore();
onMounted(async () => {
if (authModule.getSchool) {
await schoolExternalToolsModule.loadSchoolExternalTools(
authModule.getSchool.id
);
schoolExternalToolsModule.loadSchoolExternalTools(authModule.getSchool.id);
schoolLicenseStore.fetchMediaSchoolLicenses();
}
});
const { t } = useI18n();
const { getHeaders, getItems } = useExternalToolsSectionUtils(t);
const { getHeaders, getItems } = useExternalToolsSectionUtils(
t,
envConfigModule.getEnv.FEATURE_SCHULCONNEX_MEDIA_LICENSE_ENABLED
);
const { fetchSchoolExternalToolUsage, metadata } = useSchoolExternalToolUsage();
const headers: DataTableHeader[] = getHeaders;
Expand Down Expand Up @@ -275,6 +328,17 @@ const isMediaBoardUsageVisible: ComputedRef<boolean> = computed(() => {
const isVidisEnabled: ComputedRef<boolean> = computed(() => {
return envConfigModule.getEnv.FEATURE_VIDIS_MEDIA_ACTIVATIONS_ENABLED;
});
const isLicensedToSchool = (
mediumId: string,
mediaSourceId?: string
): boolean => {
return schoolLicenseStore.isLicensed(mediumId, mediaSourceId);
};
const isLicensesLoading: ComputedRef<boolean> = computed(() => {
return schoolLicenseStore.isLoading;
});
</script>

<style lang="scss" scoped>
Expand Down
Loading

0 comments on commit ccc847a

Please sign in to comment.