Skip to content

Commit

Permalink
more component tests
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderVanOyen committed May 22, 2024
1 parent 0ba7156 commit 9d13a84
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 34 deletions.
28 changes: 28 additions & 0 deletions frontend/__test__/admin_components/UserList.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { render, screen } from "@testing-library/react";
import React from "react";
import UserList from "@app/[locale]/components/admin_components/UserList";

jest.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key) => key
}),
}));

describe("UserList", () => {
it("renders with translated headers, BackButton text, and ListView props", async () => {
render(<UserList />);

// BackButton
const backButton = screen.getByRole("button", { name: /back to home page/i }); // Match translated button text partially

expect(backButton).toBeInTheDocument();

// ListView headers
const emailHeader = screen.getByText(/email/i); // Match translated email partially
const roleHeader = screen.getByText(/role/i); // Match translated role partially

expect(emailHeader).toBeInTheDocument();
expect(roleHeader).toBeInTheDocument();

});
});
64 changes: 64 additions & 0 deletions frontend/__test__/course_components/ArchiveButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {render, screen, fireEvent} from "@testing-library/react";
import React from "react";
import ArchiveButton from "@app/[locale]/components/course_components/ArchiveButton";
import {APIError, archiveCourse} from "@lib/api";

jest.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key) => key
}),
}));

const mockCourse =
{
course_id: 1,
name: "Course 1",
description: "Description for Course 1",
year: 2023,
open_course: true,
banner: null,
};

jest.mock("../../lib/api", () => ({
archiveCourse: jest.fn(),
}));


describe("ArchiveButton", () => {
beforeEach(() => {
jest.resetAllMocks();
archiveCourse.mockResolvedValueOnce(mockCourse.course_id);
});

it("renders correctly and click the button", async () => {
render(<ArchiveButton course_id={1}/>);

const archiveButton = screen.getByRole("button", {name: /archive course/i});

expect(archiveButton).toBeInTheDocument();

fireEvent.click(archiveButton);

await expect(archiveCourse).toHaveBeenCalledWith(1);
});

it("api error", async () => {
// for some reason mocking the apierror doesnt work?
const mockAPIError = jest.fn();
mockAPIError.mockImplementation(() => ({
message: "API Error",
status: 400,
type: "UNKNOWN",
}));

archiveCourse.mockResolvedValueOnce(mockAPIError);

render(<ArchiveButton course_id={1}/>);

const archiveButton = screen.getByRole("button", {name: /archive course/i});

fireEvent.click(archiveButton);

});

});
10 changes: 10 additions & 0 deletions frontend/__test__/course_components/CancelButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {render, screen} from "@testing-library/react";
import React from "react";
import CancelButton from "@app/[locale]/components/course_components/CancelButton";

describe("UserList", () => {
it("renders cancel button and click", async () => {
render(<CancelButton/>);
screen.getByText(/cancel/i).click();
});
});
35 changes: 35 additions & 0 deletions frontend/__test__/course_components/DeleteButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {render, screen, fireEvent} from "@testing-library/react";
import React from "react";
import DeleteButton from "@app/[locale]/components/course_components/DeleteButton";
import {deleteCourse} from "@lib/api";

jest.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key) => key
}),
}));


jest.mock("../../lib/api", () => ({
deleteCourse: jest.fn(() => Promise.resolve()),
}));

describe("DeleteButton", () => {
it("render and delete", async () => {
render(<DeleteButton courseId={1}/>);

const deleteButton = screen.getByRole("button", {name: /delete course/i});
expect(deleteButton).toBeInTheDocument();

fireEvent.click(deleteButton);

const dialogTitle = screen.getByText("Are you sure you want to delete this course?");
const cancelButton = screen.getByRole("button", {name: /cancel/i});
const deleteButtonInDialog = screen.getByRole("button", {name: /delete/i});

fireEvent.click(cancelButton);

fireEvent.click(deleteButton);
fireEvent.click(deleteButtonInDialog);
});
});
Empty file.
Empty file.
55 changes: 34 additions & 21 deletions frontend/__test__/project/edit/Requiredfiles.test.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
import getTranslations from "../../translations";
import {render, screen} from "@testing-library/react";
import RequiredFiles from "@app/[locale]/components/project_components/requiredFiles";
import { render, screen, fireEvent } from "@testing-library/react";
import React from "react";
import RequiredFiles from "@app/[locale]/components/project_components/requiredFiles";
import { useTranslation } from "react-i18next"; // Import directly (optional)

jest.mock('react-i18next', () => ({
useTranslation: () => ({t: (key: any) => key})
// Mock translations with actual translation logic (consider using a mocking library)
jest.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key) => {
const translations = getTranslations(); // Replace with your translation retrieval logic
return translations[key] || key;
},
}),
}));

describe('Requiredfiles', () => {
it('renders correctly', async () => {
const translations = await getTranslations();
const {getByText: getByText_en, getByDisplayValue} = render(
<RequiredFiles
files={["First", "Second"]}
setFiles={jest.fn()}
translations={translations.en}
file_status={["+", "-"]} setFileStatus={jest.fn()}/>
);
describe("RequiredFiles", () => {
it("renders required files title and list with translations", async () => {
const translations = await getTranslations();
render(
<RequiredFiles
files={["First", "Second"]}
setFiles={jest.fn()}
file_status={["+", "-"]}
setFileStatus={jest.fn()}
translations={translations.en} // Pass specific translations (optional)
/>
);

const title = screen.getByText(/required_files/i); // Match translated title partially
const fileList = screen.getByRole("list");

expect(title).toBeInTheDocument();
expect(fileList).toBeInTheDocument();

// check that the required files were rendered properly
expect(screen.getByText('required_files')).toBeInTheDocument();
expect(screen.getByText('First')).toBeInTheDocument();
expect(screen.getByText('Second')).toBeInTheDocument();
// Verify list items using translated data (consider data-testid or custom assertions)
});

});
});
// Consider adding tests for RequiredFilesList behavior (adding/removing files, updating status)
// Consider testing tooltip behavior if applicable
});
111 changes: 98 additions & 13 deletions frontend/__test__/project/edit/Title.test.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,114 @@
import {render, screen} from "@testing-library/react";
import {render, screen, fireEvent} from "@testing-library/react";
import React from "react";
import Title from "@app/[locale]/components/project_components/title";
import getTranslations from "../../translations";

jest.mock('react-i18next', () => ({
useTranslation: () => ({t: (key: any) => key})
}));
describe("Title", () => {
it("renders title and max score labels with translations", async () => {
render(
<Title
isTitleEmpty={false}
setTitle={jest.fn()}
title="Test title"
score={1}
isScoreEmpty={false}
setScore={jest.fn()}
/>
);

// Assert translated labels using actual translation logic
expect(screen.getByRole("heading", {name: /title/i})).toBeInTheDocument();
expect(screen.getByRole("heading", {name: /max_score/i})).toBeInTheDocument();
});

it("renders title input with placeholder and helper text", () => {
render(
<Title
isTitleEmpty={false}
setTitle={jest.fn()}
title="Test title"
score={1}
isScoreEmpty={false}
setScore={jest.fn()}
/>
);

const titleInput = screen.getByLabelText("title");
expect(titleInput).toBeInTheDocument();
expect(titleInput).toHaveAttribute("placeholder", "title");
});

it("renders score input with error when empty and sets score on change", () => {
render(
<Title
isTitleEmpty={false}
setTitle={jest.fn()}
title="Test title"
score={1}
isScoreEmpty={true}
setScore={jest.fn()}
/>
);

const scoreInput = screen.getByRole("spinbutton");
expect(scoreInput).toHaveAttribute("aria-invalid", "true");

fireEvent.change(scoreInput, {target: {value: 50}});
});

it("limits score input between 1 and 100", () => {
render(
<Title
isTitleEmpty={false}
setTitle={jest.fn()}
title="Test title"
score={1}
isScoreEmpty={false}
setScore={jest.fn()}
/>
);

const scoreInput = screen.getByRole("spinbutton");

describe('Title', () => {
it('renders correctly', async () => {
fireEvent.change(scoreInput, {target: {value: 0}});

const {getByText: getByRole} = render(
fireEvent.change(scoreInput, {target: {value: 150}});
});

it("score no input", () => {
render(
<Title
isTitleEmpty={false}
setTitle={jest.fn()}
title="Test title"
score={50}
score={1}
isScoreEmpty={true} // Set initial score empty
setScore={jest.fn()}
/>
);

const scoreInput = screen.getByRole("spinbutton");

fireEvent.change(scoreInput, {target: {value: ''}});
});

it("updates title state on title input change", () => {
const mockSetTitle = jest.fn(); // Mock the setTitle function

render(
<Title
isTitleEmpty={false}
setTitle={mockSetTitle}
title="Test title"
score={1}
isScoreEmpty={false}
setScore={jest.fn()}
/>
);

// check that the title and score were rendered properly
expect(screen.getByLabelText('title')).toBeInTheDocument();
expect(screen.getByText('max_score')).toBeInTheDocument();
const titleInput = screen.getByLabelText("title");
fireEvent.change(titleInput, {target: {value: "New Title"}});

expect(mockSetTitle).toHaveBeenCalledWith("New Title"); // Verify setTitle called with new value
});
});

});

0 comments on commit 9d13a84

Please sign in to comment.