generateur_v3/frontend/src/test/exo.test.ts

941 lines
22 KiB
TypeScript

import { render, fireEvent, createEvent } from "@testing-library/svelte";
import { writable } from "svelte/store";
import { describe, expect, test, vi } from "vitest";
import Card from "../components/exos/Card.svelte";
import ContextTest from "./ContextTest.svelte";
import type { Exercice } from "../types/exo.type";
import DownloadForm from "../components/exos/DownloadForm.svelte";
import ModalCard from "../components/exos/ModalCard.svelte";
import Head from "../components/exos/Head.svelte";
import TagContainer from "../components/exos/TagContainer.svelte";
import Tag from "src/components/exos/Tag.svelte";
import EditForm from "src/components/exos/EditForm.svelte";
import FileInput from "src/components/forms/FileInput.svelte";
import Pagination from "src/components/exos/Pagination.svelte";
const auth = { key: "auth", value: { isAuth: writable(true) } };
const modal = {
key: "modal",
value: {
show: (c, o) => {
},
close: () => {
}
}
};
const nav = {
key: "navigation", value: {
navigate: () => {
}
}
};
const notif = {
key: "notif",
value: {
alert: () => {
}, info: () => {
}, success: () => {
}, error: () => {
}
}
};
const alert = {
key: "alert", value: {
alert: () => {
}
}
};
describe("Exo card", () => {
const contexts = [auth, nav, modal, notif, alert];
const baseExo: Exercice = {
csv: true,
pdf: true,
web: true,
name: "Title",
consigne: "The consigne",
author: { username: "ouioui" },
private: false,
id_code: "ABCDEF",
exo_source: "/test",
original: null,
examples: {
type: "csv",
data: [
{ calcul: "1+...=2", correction: "2" },
{ calcul: "1+...=2", correction: "2" },
{ calcul: "1+...=2", correction: "2" }
]
},
is_author: true,
tags: []
};
test("Copy", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: { ...baseExo, is_author: false }
}
}
});
card.getByTestId("copy");
});
test("TagEditing", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts: [
...contexts,
{
key: "modal",
value: {
show: () => {
expect(true).toBeFalsy();
}
}
},
{ key: "tags", value: writable({ data: [], isLoading: false }) }
],
props: {
exo: baseExo
}
}
});
const expand = card.getByText("+", { exact: true });
fireEvent.click(expand).then(() => {
card.getByRole("button", { name: "Annuler" });
card.getByRole("button", { name: "Valider !" });
const tags = card.container.querySelector(".svelecte");
expect(tags).not.toBeNull();
});
});
test("No auth", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts: [nav, notif, modal, { key: "auth", value: { isAuth: writable(false) } }],
props: {
exo: { ...baseExo, is_author: false }
}
}
});
expect(card.queryByTestId("copy")).toBeNull();
expect(card.queryByTestId("tags")).toBeNull();
card.getByText((c, e) => {
return c == "Par" && e?.children[0].innerHTML == "ouioui";
});
});
test("Example", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: { ...baseExo }
}
}
});
const exs = card.queryAllByText(baseExo.examples.data[0].calcul);
expect(exs.length).toBe(3);
});
test("Check author", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: { ...baseExo, is_author: false }
}
}
});
card.getByText((c, e) => {
return c == "Par" && e?.children[0].innerHTML == "ouioui";
});
});
test("Check title", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: baseExo
}
}
});
card.getByText("Title");
});
test("Check consigne", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: baseExo
}
}
});
card.getByText("The consigne");
});
test("Check no consigne", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: { ...baseExo, consigne: null }
}
}
});
expect(card.queryByTestId("consigne")).toBeNull();
});
test("Show", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts: [
...contexts,
{
key: "modal",
value: {
show: (c, o) => {
expect(c).toBe(ModalCard);
expect(o.exo).toBe(baseExo);
}
}
},
{
key: "navigation",
value: {
navigate: (url) => {
expect(url).toBe("/exercices/" + baseExo.id_code);
}
}
}
],
props: {
exo: baseExo
}
}
});
const cardElement = card.container.querySelector(".card");
fireEvent.click(cardElement).then(() => {
});
});
test("Public mark", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: { ...baseExo, private: false }
}
}
});
card.getByText("Public");
expect(card.queryByText("Privé")).toBeNull();
});
test("Private mark", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: { ...baseExo, private: true }
}
}
});
card.getByText("Privé");
expect(card.queryByText("Public")).toBeNull();
});
test("tags", () => {
const card = render(ContextTest, {
props: {
component: Card,
contexts,
props: {
exo: { ...baseExo, is_author: false }
}
}
});
card.getByTestId("tags");
});
});
describe("Modal card download", () => {
const contexts = [auth, nav, modal, notif, alert];
const baseExo: Exercice = {
supports: { csv: true, pdf: true, web: true },
name: "Title",
consigne: "The consigne",
author: { username: "ouioui" },
private: false,
id_code: "ABCDEF",
exo_source: "/test",
original: null,
examples: {
type: "csv",
data: [
{ calcul: "1+...=2", correction: "2" },
{ calcul: "1+...=2", correction: "2" },
{ calcul: "1+...=2", correction: "2" }
]
},
is_author: true,
tags: []
};
test("Copy", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, is_author: false }
}
}
});
card.getByTestId("copy");
});
test("TagEditing", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts: [...contexts, { key: "tags", value: writable({ data: [], isLoading: false }) }],
props: {
exo: baseExo
}
}
});
const expand = card.getByText("+", { exact: true });
fireEvent.click(expand).then(() => {
setTimeout(() => {
card.getByRole("button", { name: "Annuler" });
card.getByRole("button", { name: "Valider !" });
const tags = card.container.querySelector(".svelecte");
expect(tags).not.toBeNull();
}, 1000);
});
});
test("No auth", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts: [nav, notif, modal, alert, { key: "auth", value: { isAuth: writable(false) } }],
props: {
exo: { ...baseExo, is_author: false }
}
}
});
expect(card.queryByTestId("copy")).toBeNull();
expect(card.queryByTestId("tags")).toBeNull();
expect(card.queryByTestId("delete")).toBeNull();
expect(card.queryByTestId("edit")).toBeNull();
card.getByText((c, e) => {
return c == "Par" && e?.children[0].innerHTML == "ouioui";
});
});
test("tags", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, is_author: false }
}
}
});
card.getByTestId("tags");
});
test("Icons", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, is_author: true }
}
}
});
card.getByTestId("delete");
card.getByTestId("edit");
});
test("Example", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo }
}
}
});
const exs = card.queryAllByText(baseExo.examples.data[0].calcul);
expect(exs.length).toBe(3);
});
test("Check author", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, is_author: false }
}
}
});
card.getByText((c, e) => {
return c == "Par" && e?.children[0].innerHTML == "ouioui";
});
});
test("Check original author", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: {
...baseExo,
is_author: true,
original: { id_code: "AOB", name: "test2", author: "lilian" }
}
}
}
});
card.getByText((c, e) => {
return c == "Exercice original de" && e?.children[0].innerHTML == "lilian";
});
});
test("Check title", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: baseExo
}
}
});
card.getByText("Title");
});
test("Check consigne", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: baseExo
}
}
});
card.getByText("The consigne");
});
test("Check no consigne", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, consigne: null }
}
}
});
expect(card.queryByTestId("consigne")).toBeNull();
});
test("Public mark", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, private: false }
}
}
});
card.getByText("Public");
expect(card.queryByText("Privé")).toBeNull();
});
test("Private mark", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, private: true }
}
}
});
card.getByText("Privé");
expect(card.queryByText("Public")).toBeNull();
});
test("no csv", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, supports: { csv: false } }
}
}
});
const input = card.getByRole("textbox");
expect(input.disabled).toBeTruthy();
const btn = card.getByRole("button", { name: "Télécharger" });
expect(btn.disabled).toBeTruthy();
});
test("csv", () => {
const card = render(ContextTest, {
props: {
component: DownloadForm,
contexts,
props: {
exo: { ...baseExo, supports: { csv: true } }
}
}
});
const input = card.getByRole("textbox");
expect(input.disabled).toBeFalsy();
const btn = card.getByRole("button", { name: "Télécharger" });
expect(btn.disabled).toBeFalsy();
});
});
describe("Heading", () => {
const contexts = [auth, nav, modal];
test("Auth", () => {
const head = render(ContextTest, {
props: {
component: Head,
contexts: [
...contexts,
{ key: "tags", value: writable({ data: [] }) },
{ key: "exos", value: writable({ data: { items: [] } }) }
],
props: {
location: "public"
}
}
});
head.getByRole("button", { name: "Nouveau" });
const svelecte = head.container.querySelector(".svelecte");
expect(svelecte).not.toBeNull();
const select = head.getByRole("combobox");
expect(select.value).toBe("public");
});
test("No auth", () => {
const head = render(ContextTest, {
props: {
component: Head,
contexts: [
nav,
modal,
{ key: "auth", value: { isAuth: writable(false) } },
{ key: "tags", value: writable({ data: [] }) },
{ key: "exos", value: writable({ data: { items: [] } }) }
],
props: {
location: "public"
}
}
});
expect(head.queryByRole("button", { name: "Nouveau" })).toBeNull();
const svelecte = head.container.querySelector(".svelecte");
expect(svelecte).toBeNull();
expect(head.queryByRole("combobox")).toBeNull();
});
});
describe("Tag container", () => {
test("Tag selection", () => {
const tags = [
{ label: "test1", color: "#00ff00", id_code: "ABC" },
{ label: "test2", color: "#00ff00", id_code: "DEF" },
{ label: "test3", color: "#00ff00", id_code: "GHI" },
{ label: "test4", color: "#00ff00", id_code: "KLM" }
];
const selected = [tags[0], tags[2]];
const container = render(ContextTest, {
props: {
component: TagContainer,
contexts: [
notif,
{
key: "tags",
value: writable({
data: tags
})
}
],
props: {
exo: {
name: "test",
id_code: "ABD",
tags: selected
}
}
}
});
const expand = container.getByText("+", { exact: true });
fireEvent.click(expand).then(() => {
const tagsSelector = container.container.querySelector(".sv-control");
if (tagsSelector != null) {
fireEvent.click(tagsSelector).then(() => {
tags.map((t) => {
const tag = container.getByText(t.label);
if (selected.includes(t)) {
expect(tag.classList.contains("disabled")).toBeTruthy();
} else {
expect(tag.classList.contains("disabled")).toBeFalsy();
}
});
});
}
});
});
});
describe("Tag", () => {
test("With delete", () => {
let called = false;
const remove = () => {
called = true;
};
const tag = render(ContextTest, {
props: {
component: Tag,
contexts: [notif],
props: {
label: "test",
color: "#00ff00",
remove
}
}
});
tag.getByText("test");
const del = tag.getByRole("button");
expect(del).not.toBeNull();
fireEvent.click(del).then(() => {
expect(called).toBeTruthy();
});
});
test("Without delete", () => {
const tag = render(ContextTest, {
props: {
component: Tag,
contexts: [notif],
props: {
label: "test",
color: "#00ff00"
}
}
});
tag.getByText("test");
expect(tag.queryByRole("button")).toBeNull();
});
});
describe("ExoForm", () => {
test("Edit", () => {
const exo = {
name: "test",
id_code: "ABC",
private: true,
consigne: "the consigne",
exo_source: "test.py",
tags: []
};
const form = render(ContextTest, {
props: {
component: EditForm,
contexts: [notif, alert],
props: {
exo,
editing: true,
cancel: () => {},
updateExo: () => {}
}
}
});
const input = form.getByRole("textbox", { name: "Nom" });
expect(input.value).toBe(exo.name);
const consigneInput = form.getByRole("textbox", { name: "Consigne" });
expect(consigneInput.value).toBe(exo.consigne);
form.getByText("test.py");
const privateInput = form.getByRole("checkbox", { name: "Privé" });
expect(privateInput.checked).toBeTruthy();
const btn = form.getByRole("button", { name: "Modifier" });
expect(btn.disabled).toBeFalsy();
const cancelBtn = form.getByRole("button", { name: "Annuler" });
expect(cancelBtn.disabled).toBeFalsy();
});
});
describe("FileInput", () => {
test("with default value", () => {
const fileInput = render(FileInput, {
defaultValue: "test.py",
id_code: "ABC",
label: "Choisir",
value: []
});
const input = fileInput.getByLabelText("Choisir");
fileInput.getByText("test.py");
fireEvent(input, createEvent("change", input, {
target: { files: [new File(["(⌐□_□)"], "test2.py", { type: "text/plain" })] }
})).then(() => {
fileInput.getByText("test2.py");
expect(fileInput.queryByText("test.py")).toBeNull();
});
});
test("whithout default value", () => {
const fileInput = render(FileInput, {
id_code: "ABC",
label: "Choisir",
value: []
});
const input = fileInput.getByLabelText("Choisir");
fileInput.getByText("...");
fireEvent(input, createEvent("change", input, {
target: { files: [new File(["(⌐□_□)"], "test2.py", { type: "text/plain" })] }
})).then(() => {
fileInput.getByText("test2.py");
expect(fileInput.queryByText("...")).toBeNull();
});
});
});
describe("Pagination", () => {
test("< 6", () => {
const pagination = render(Pagination, {
props: {
page: 1,
total: 6
}
});
pagination.getByText("1");
pagination.getByText("2");
pagination.getByText("3");
pagination.getByText("4");
pagination.getByText("5");
pagination.getByText("6");
});
test("> 7 start", () => {
const pagination = render(Pagination, {
props: {
page: 1,
total: 9
}
});
pagination.getByText("1");
pagination.getByText("2");
pagination.getByText("...");
pagination.getByText("8");
pagination.getByText("9");
});
test("> 7 middle", () => {
const pagination = render(Pagination, {
props: {
page: 5,
total: 9
}
});
pagination.getByText("1");
pagination.getByText("2");
const trim = pagination.getAllByText("...");
expect(trim.length).toBe(2);
pagination.getByText("4");
pagination.getByText("5");
pagination.getByText("6");
pagination.getByText("8");
pagination.getByText("9");
});
test("> 7 end", () => {
const pagination = render(Pagination, {
props: {
page: 8,
total: 9
}
});
pagination.getByText("1");
pagination.getByText("2");
pagination.getByText("...");
pagination.getByText("8");
pagination.getByText("9");
});
test("> 7 3", () => {
const pagination = render(Pagination, {
props: {
page: 3,
total: 9
}
});
pagination.getByText("1");
pagination.getByText("2");
pagination.getByText("3");
pagination.getByText("4");
pagination.getByText("...");
pagination.getByText("8");
pagination.getByText("9");
});
test("> 7 4", () => {
const pagination = render(Pagination, {
props: {
page: 4,
total: 9
}
});
pagination.getByText("1");
pagination.getByText("2");
pagination.getByText("3");
pagination.getByText("4");
pagination.getByText("5");
pagination.getByText("...");
pagination.getByText("8");
pagination.getByText("9");
});
test("> 7 3 before end", () => {
const pagination = render(Pagination, {
props: {
page: 6,
total: 9
}
});
pagination.getByText("1");
pagination.getByText("2");
pagination.getByText("...");
pagination.getByText("5");
pagination.getByText("6");
pagination.getByText("7");
pagination.getByText("8");
pagination.getByText("9");
});
test("> 7 2 before end", () => {
const pagination = render(Pagination, {
props: {
page: 7,
total: 9
}
});
pagination.getByText("1");
pagination.getByText("2");
pagination.getByText("...");
pagination.getByText("6");
pagination.getByText("7");
pagination.getByText("8");
pagination.getByText("9");
});
test("buttons enabled", () => {
const pagination = render(Pagination, {
props: {
page: 2,
total: 9
}
});
const back = pagination.getByRole("button", { name: "<" });
expect(back.disabled).toBeFalsy();
const next = pagination.getByRole("button", { name: ">" });
expect(next.disabled).toBeFalsy();
});
test("next button disabled", () => {
const pagination = render(Pagination, {
props: {
page: 9,
total: 9
}
});
const next = pagination.getByRole("button", { name: ">" });
expect(next.disabled).toBeTruthy();
});
test("back button disabled", () => {
const pagination = render(Pagination, {
props: {
page: 1,
total: 9
}
});
const back = pagination.getByRole("button", { name: "<" });
expect(back.disabled).toBeTruthy();
});
});