Skip to content

Commit

Permalink
N21-1319 ctl showing tool usage (#2922)
Browse files Browse the repository at this point in the history
* N21-1319 generate Api
* N21-1319 metadata and mapper
* N21-1319 store action
* N21-1319 composable and display count
* N21-1319 translation
  • Loading branch information
mrikallab authored Nov 20, 2023
1 parent d718801 commit ffc3698
Show file tree
Hide file tree
Showing 18 changed files with 3,859 additions and 3,184 deletions.
173 changes: 162 additions & 11 deletions src/components/administration/ExternalToolSection.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,25 @@ import createComponentMocks from "@@/tests/test-utils/componentMocks";
import { i18nMock } from "@@/tests/test-utils/i18nMock";
import { mdiCheckCircle, mdiRefreshCircle } from "@mdi/js";
import { mount, Wrapper } from "@vue/test-utils";
import Vue from "vue";
import Vue, { ref } from "vue";
import ExternalToolSection from "./ExternalToolSection.vue";
import { createMock, DeepMocked } from "@golevelup/ts-jest";
import { useSchoolExternalToolUsage } from "@data-external-tool";
import {
schoolExternalToolFactory,
schoolExternalToolMetadataFactory,
} from "@@/tests/test-utils/factory";

jest.mock("@data-external-tool");

describe("ExternalToolSection", () => {
let el: HTMLDivElement;

const setup = (getters: Partial<SchoolExternalToolsModule> = {}) => {
let useSchoolExternalToolUsageMock: DeepMocked<
ReturnType<typeof useSchoolExternalToolUsage>
>;

const getWrapper = (getters: Partial<SchoolExternalToolsModule> = {}) => {
el = document.createElement("div");
el.setAttribute("data-app", "true");
document.body.appendChild(el);
Expand Down Expand Up @@ -63,17 +75,30 @@ describe("ExternalToolSection", () => {
};
};

beforeEach(() => {
useSchoolExternalToolUsageMock =
createMock<ReturnType<typeof useSchoolExternalToolUsage>>();

jest
.mocked(useSchoolExternalToolUsage)
.mockReturnValue(useSchoolExternalToolUsageMock);
});

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

describe("when component is used", () => {
it("should be found in the dom", () => {
const { wrapper } = setup();
const { wrapper } = getWrapper();
expect(wrapper.findComponent(ExternalToolSection).exists()).toBeTruthy();
});
});

describe("onMounted is called", () => {
describe("when component is mounted", () => {
it("should load the external tools", () => {
const { schoolExternalToolsModule } = setup();
const { schoolExternalToolsModule } = getWrapper();

expect(
schoolExternalToolsModule.loadSchoolExternalTools
Expand All @@ -86,7 +111,7 @@ describe("ExternalToolSection", () => {
const setupItems = () => {
const firstToolName = "Test";
const secondToolName = "Test2";
const { wrapper, schoolExternalToolsModule } = setup({
const { wrapper, schoolExternalToolsModule } = getWrapper({
getSchoolExternalTools: [
{
id: "testId",
Expand Down Expand Up @@ -213,7 +238,7 @@ describe("ExternalToolSection", () => {

describe("when deletion is confirmed", () => {
it("should call externalToolsModule.deleteSchoolExternalTool", async () => {
const { wrapper, schoolExternalToolsModule } = setup({
const { wrapper, schoolExternalToolsModule } = getWrapper({
getSchoolExternalTools: [
{
id: "testId",
Expand All @@ -234,7 +259,9 @@ describe("ExternalToolSection", () => {
const deleteButton = firstRowButtons.at(1);
await deleteButton.trigger("click");

const confirmButton = wrapper.find("[data-testId=dialog-confirm]");
const confirmButton = wrapper.find(
"[data-testId=delete-dialog-confirm]"
);
await confirmButton.trigger("click");

expect(
Expand All @@ -243,7 +270,7 @@ describe("ExternalToolSection", () => {
});

it("should call notifierModule.show", async () => {
const { wrapper, notifierModule } = setup({
const { wrapper, notifierModule } = getWrapper({
getSchoolExternalTools: [
{
id: "testId",
Expand All @@ -264,7 +291,9 @@ describe("ExternalToolSection", () => {
const deleteButton = firstRowButtons.at(1);
await deleteButton.trigger("click");

const confirmButton = wrapper.find("[data-testId=dialog-confirm]");
const confirmButton = wrapper.find(
"[data-testId=delete-dialog-confirm]"
);
await confirmButton.trigger("click");

expect(notifierModule.show).toHaveBeenCalled();
Expand All @@ -277,7 +306,7 @@ describe("ExternalToolSection", () => {
describe("getItemName is called", () => {
describe("when itemToDelete is set", () => {
it("should return the name", () => {
const { wrapper } = setup();
const { wrapper } = getWrapper();

const expectedName = "Name";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand All @@ -298,7 +327,7 @@ describe("ExternalToolSection", () => {

describe("when itemToDelete is not set", () => {
it("should return an empty string", () => {
const { wrapper } = setup();
const { wrapper } = getWrapper();

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
Expand All @@ -312,4 +341,126 @@ describe("ExternalToolSection", () => {
});
});
});

describe("when deleting a schoolExternalTool", () => {
describe("when metadata is given", () => {
const setup = () => {
const schoolExternalToolMetadata =
schoolExternalToolMetadataFactory.build();

useSchoolExternalToolUsageMock.metadata = ref(
schoolExternalToolMetadata
);

const { wrapper, notifierModule } = getWrapper({
getSchoolExternalTools: [
schoolExternalToolFactory.build(),
schoolExternalToolFactory.build(),
],
});

return {
wrapper,
notifierModule,
schoolExternalToolMetadata,
};
};

it("should display delete dialog", async () => {
const { wrapper } = setup();

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

const firstRowButtons = tableRows.at(0).findAll("button");

const deleteButton = firstRowButtons.at(1);
await deleteButton.trigger("click");

const dialog = wrapper.find('[data-testid="delete-dialog"]');

expect(dialog.isVisible()).toBeTruthy();
});

it("should display tool usage count", async () => {
const { wrapper, schoolExternalToolMetadata } = setup();

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

const firstRowButtons = tableRows.at(0).findAll("button");

const deleteButton = firstRowButtons.at(1);
await deleteButton.trigger("click");

const dialogContent = wrapper.find(
'[data-testid="delete-dialog-content"]'
);

expect(dialogContent.text()).toEqual(
`components.administration.externalToolsSection.dialog.content {"itemName":"name","courseCount":${schoolExternalToolMetadata.course},"boardElementCount":${schoolExternalToolMetadata.boardElement}}`
);
});

it("should not display notification", async () => {
const { wrapper, notifierModule } = setup();

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

const firstRowButtons = tableRows.at(0).findAll("button");

const deleteButton = firstRowButtons.at(1);
await deleteButton.trigger("click");

expect(notifierModule.show).not.toHaveBeenCalled();
});
});

describe("when metadata is undefined", () => {
const setup = () => {
useSchoolExternalToolUsageMock.metadata = ref(undefined);

const { wrapper, notifierModule } = getWrapper({
getSchoolExternalTools: [
schoolExternalToolFactory.build({}),
schoolExternalToolFactory.build(),
],
});

return {
wrapper,
notifierModule,
};
};

it("should not display delete dialog", async () => {
const { wrapper } = setup();

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

const firstRowButtons = tableRows.at(0).findAll("button");

const deleteButton = firstRowButtons.at(1);
await deleteButton.trigger("click");

const dialog = wrapper.find('[data-testid="delete-dialog"]');

expect(dialog).not.toBe("visible");
});

it("should display notification", async () => {
const { wrapper, notifierModule } = setup();

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

const firstRowButtons = tableRows.at(0).findAll("button");

const deleteButton = firstRowButtons.at(1);
await deleteButton.trigger("click");

expect(notifierModule.show).toHaveBeenCalledWith({
status: "error",
text: "components.administration.externalToolsSection.dialog.content.metadata.error",
});
});
});
});
});
37 changes: 31 additions & 6 deletions src/components/administration/ExternalToolSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
{{ t("components.administration.externalToolsSection.info") }}
</p>
<v-data-table
data-testid="external-tool-section-table"
v-if="items.length"
:disable-pagination="true"
:hide-default-footer="true"
Expand Down Expand Up @@ -45,9 +46,14 @@
{{ t("components.administration.externalToolsSection.action.add") }}
</v-btn>

<v-dialog v-model="isDeleteDialogOpen" max-width="360">
<v-dialog
v-if="metadata"
data-testid="delete-dialog"
v-model="isDeleteDialogOpen"
max-width="360"
>
<v-card :ripple="false">
<v-card-title>
<v-card-title data-testid="delete-dialog-title">
<h2 class="text-h4 my-2">
{{
t("components.administration.externalToolsSection.dialog.title")
Expand All @@ -56,11 +62,16 @@
</v-card-title>
<v-card-text class="text--primary">
<RenderHTML
data-testid="delete-dialog-content"
class="text-md mt-2"
:html="
t(
'components.administration.externalToolsSection.dialog.content',
{ itemName: getItemName }
{
itemName: getItemName,
courseCount: metadata.course,
boardElementCount: metadata.boardElement,
}
)
"
component="p"
Expand All @@ -69,7 +80,7 @@
<v-card-actions>
<v-spacer />
<v-btn
data-testId="dialog-cancel"
data-testId="delete-dialog-cancel"
class="dialog-closed"
depressed
text
Expand All @@ -78,7 +89,7 @@
{{ t("common.actions.cancel") }}
</v-btn>
<v-btn
data-testId="dialog-confirm"
data-testId="delete-dialog-confirm"
class="dialog-confirmed px-6"
color="primary"
depressed
Expand Down Expand Up @@ -120,6 +131,7 @@ import { DataTableHeader } from "vuetify";
import { useExternalToolsSectionUtils } from "./external-tool-section-utils.composable";
import ExternalToolToolbar from "./ExternalToolToolbar.vue";
import { SchoolExternalToolItem } from "./school-external-tool-item";
import { useSchoolExternalToolUsage } from "@data-external-tool";
export default defineComponent({
name: "ExternalToolSection",
Expand Down Expand Up @@ -147,6 +159,8 @@ export default defineComponent({
i18n.tc(key, 0, values);
const { getHeaders, getItems } = useExternalToolsSectionUtils(t);
const { fetchSchoolExternalToolUsage, metadata } =
useSchoolExternalToolUsage();
const headers: DataTableHeader[] = getHeaders;
Expand Down Expand Up @@ -189,9 +203,19 @@ export default defineComponent({
const isDeleteDialogOpen: Ref<boolean> = ref(false);
const openDeleteDialog = (item: SchoolExternalToolItem) => {
const openDeleteDialog = async (item: SchoolExternalToolItem) => {
itemToDelete.value = item;
isDeleteDialogOpen.value = true;
await fetchSchoolExternalToolUsage(item.id);
if (!metadata.value) {
notifierModule.show({
text: t(
"components.administration.externalToolsSection.dialog.content.metadata.error"
),
status: "error",
});
}
};
const onCloseDeleteDialog = () => {
Expand All @@ -214,6 +238,7 @@ export default defineComponent({
getItemName,
mdiRefreshCircle,
mdiCheckCircle,
metadata,
};
},
});
Expand Down
Loading

0 comments on commit ffc3698

Please sign in to comment.