Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/SELab-2/UGent-1 into 180…
Browse files Browse the repository at this point in the history
…-bring-back-all-submission-page

# Conflicts:
#	frontend/app/[locale]/components/ProjectDetailsPage.tsx
#	frontend/locales/en/common.json
#	frontend/locales/nl/common.json
  • Loading branch information
gilles-arnout committed May 22, 2024
2 parents 4813326 + f763222 commit 269748e
Show file tree
Hide file tree
Showing 38 changed files with 1,674 additions and 757 deletions.
23 changes: 23 additions & 0 deletions .template.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
DATABASE=postgres
DEBUG=1
DJANGO_ALLOWED_HOSTS='localhost example.com 127.0.0.1 [::1] django'
DJANGO_SUPERUSER_EMAIL=abc@example.com
DJANGO_SUPERUSER_PASSWORD=abc
FRONTEND_URL=http://localhost:3000
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
NEXT_PUBLIC_REDIRECT_URL=/redirect
OAUTH_CLIENT_ID=1234
OAUTH_CLIENT_SECRET=1234
OAUTH_TENANT_ID=1234
REGISTRY_NAME=sel2-1.ugent.be:2002
REGISTRY_PASSWORD=testding
REGISTRY_URL=https://sel2-1.ugent.be:2002
REGISTRY_USER=test
SECRET_KEY=development_key
SQL_DATABASE=pigeonhole_dev
SQL_ENGINE=django.db.backends.postgresql
SQL_HOST=pigeonhole-database
SQL_PASSWORD=password
SQL_PORT=5432
SQL_USER=pigeonhole
SUBMISSIONS_PATH=./backend/uploads/submissions/
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ frontshell:
componenttest:
docker exec -it pigeonhole-frontend npx jest

coveragecomponenttest:
docker exec -it pigeonhole-frontend npx jest --coverage --silent

silentcomponenttest:
docker exec -it pigeonhole-frontend npx jest --silent

Expand Down
2 changes: 1 addition & 1 deletion frontend/__test__/AccountMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('AccountMenu', () => {
fireEvent.click(screen.getByRole('button'));
fireEvent.click(screen.getByRole('menuitem', {name: 'logout'}));

expect(window.location.href).toBe('undefined/auth/logout');
expect(window.location.href).not.toBe(originalLocation);

window.location = originalLocation;
});
Expand Down
13 changes: 11 additions & 2 deletions frontend/__test__/CASButton.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import {fireEvent, render} from '@testing-library/react';
import {cleanup, fireEvent, render} from '@testing-library/react';
import CASButton from '../app/[locale]/components/CASButton';
import React from "react";

const OLD_ENV = process.env

describe('CASButton', () => {
afterEach(() => {
cleanup()
jest.clearAllMocks()
jest.resetModules()
process.env = {...OLD_ENV}
delete process.env.NODE_ENV
})

it('renders correctly', () => {
const {getByText, getByRole} = render(<CASButton/>);

Expand All @@ -28,7 +37,7 @@ describe('CASButton', () => {
fireEvent.click(button);

// undefined, because i havent mocked the process.env stuff
expect(window.location.href).toBe('undefined/microsoft/to-auth-redirect?next=undefined/home');
expect(window.location.href).not.toBe(originalLocation);

// restore the original window.location
window.location = originalLocation;
Expand Down
123 changes: 123 additions & 0 deletions frontend/__test__/CourseCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from 'react';
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
import CourseCard from '../app/[locale]/components/CourseCard';
import '@testing-library/jest-dom';

// Mocking the API calls
jest.mock('../lib/api', () => ({
getProjectsFromCourse: jest.fn(),
getLastSubmissionFromProject: jest.fn(),
}));

describe('CourseCard', () => {
const mockCourse = {
course_id: 1,
name: 'Test Course',
description: "test description",
open_course: true,
invite_token: "token",
year: 2024,
archived: false,
banner: "banner"
};


const mockProjects = [
{
project_id: 1,
course_id: mockCourse,
name: "Project 1",
description: "Description for Project 1",
deadline: "2023-12-31T23:59:59",
visible: true,
max_score: 20,
number_of_groups: 5,
group_size: 1,
file_structure: "file structure",
conditions: "conditions",
test_files: null,
},
{
project_id: 2,
course_id: mockCourse,
name: "Project 2",
description: "Description for Project 2",
deadline: "2024-01-31T23:59:59",
visible: true,
max_score: 20,
number_of_groups: 3,
group_size: 2,
file_structure: "file structure",
conditions: "conditions",
test_files: null,
},
];

const mockLastSubmission = {
submission_id: 1,
group_id: 1,
submission_nr: 1,
file: 'file.pdf',
timestamp: '2024-05-20',
output_test: 'output',
};

beforeEach(() => {
jest.resetAllMocks();
require('../lib/api').getProjectsFromCourse.mockResolvedValue(mockProjects);
require('../lib/api').getLastSubmissionFromProject.mockResolvedValue(mockLastSubmission);
});

it('renders correctly', async () => {
render(<CourseCard params={{course: mockCourse}}/>);

// Check if course name is rendered
expect(screen.getByText('Test Course')).toBeInTheDocument();

// Check if 'projects' title is rendered
expect(screen.getByText('projects')).toBeInTheDocument();
});

it('displays no projects message when there are no projects', async () => {
require('../lib/api').getProjectsFromCourse.mockResolvedValue([]);

render(<CourseCard params={{course: mockCourse}}/>);

await waitFor(() => {
// Check if no projects message is displayed
expect(screen.getByText('no_projects')).toBeInTheDocument();
});
});



it('mouse enter and leave', () => {
render(<CourseCard params={{course: mockCourse}}/>);

const cardMedia = screen.getByText('Test Course').closest('.MuiCardMedia-root');

// Hover over the card media
fireEvent.mouseEnter(cardMedia);

// Unhover the card media
fireEvent.mouseLeave(cardMedia);
});

it('redirects to the correct URL on card media click', () => {
render(<CourseCard params={{course: mockCourse}}/>);

const box = screen.getByText('Test Course');

// Mock window.location.href
delete window.location;
window.location = {href: ''};

// Click on the Box inside the CardMedia
fireEvent.click(box);

// Check if window.location.href is updated correctly
expect(window.location.href).toBe(`/course/${mockCourse.course_id}`);
});


});
172 changes: 87 additions & 85 deletions frontend/__test__/EditCourseForm.test.tsx
Original file line number Diff line number Diff line change
@@ -1,105 +1,107 @@
import {act, render, screen} from '@testing-library/react';
import {act, render, screen, waitFor, fireEvent} from '@testing-library/react';
import EditCourseForm from '../app/[locale]/components/EditCourseForm';
import React from "react";
import * as api from "@lib/api";
import {updateCourse} from "@lib/api";

// Mock useTranslation hook
jest.mock('react-i18next', () => ({
useTranslation: () => ({t: (key: any) => key})
}));

jest.mock('../lib/api', () => ({
getCourses: jest.fn(),
getUserData: jest.fn(),
// Mock API functions
jest.mock("../lib/api", () => ({
getCourse: jest.fn(),
getImage: jest.fn(),
postData: jest.fn(),
updateCourse: jest.fn(),
}));


global.fetch = jest.fn(() =>
Promise.resolve({
blob: () => Promise.resolve(new Blob([])),
json: () => Promise.resolve({data: 'mocked data'}),
})
);

// Mock next/image component
jest.mock('next/image', () => {
return () => <img/>;
});

const mockCourse = {
id: 1,
name: 'Test Course',
description: 'Test Description',
open_course: true,
year: 2022,
banner: new Blob([], { type: 'image/png' }),
};

describe('EditCourseForm', () => {
beforeEach(() => {
fetch.mockClear();
(api.getCourse as jest.Mock).mockResolvedValueOnce({
name: 'Test Course',
course_id: 1,
description: "Test Description",
banner: new Blob([], { type: 'image/png' }),
open_course: true,
invite_token: "token"
beforeEach(async () => {
(api.getCourse as jest.Mock).mockResolvedValue(mockCourse);
(api.getImage as jest.Mock).mockResolvedValue(new Blob([], { type: 'image/png' }));
});

it('renders correctly', async () => {
await act(async () => {
render(<EditCourseForm courseId={1}/>);
});
});

it('check boxes', async () => {
await act(async () => {
render(<EditCourseForm courseId={1}/>);
});
// check if the name input was rendered properly
expect(screen.getByText("course name")).toBeInTheDocument();

// check if the description input was rendered properly
expect(screen.getByText("description")).toBeInTheDocument();
// check if the save button was rendered properly
expect(screen.getByText('save changes')).toBeInTheDocument();
});

it('fills form fields with course data', async () => {
await act(async () => {
render(<EditCourseForm courseId={mockCourse.id}/>);
});

// wait for the course data to be fetched
await waitFor(() => expect(api.getCourse).toHaveBeenCalled());

// check if the name field was filled correctly
expect(screen.getByDisplayValue(mockCourse.name)).toBeInTheDocument();

// check if the description field was filled correctly
expect(screen.getByDisplayValue(mockCourse.description)).toBeInTheDocument();

// check if the access select field was filled correctly
expect(screen.getByDisplayValue(mockCourse.open_course.toString())).toBeInTheDocument();
});


it('submits the form correctly', async () => {
const file = new File(['dummy content'], 'test.png', { type: 'image/png' });

await act(async () => {
render(<EditCourseForm courseId={mockCourse.id}/>);
});

// wait for the course data to be fetched
await waitFor(() => expect(api.getCourse).toHaveBeenCalled());

// fill in the form fields
fireEvent.change(screen.getByDisplayValue(mockCourse.name), { target: { value: 'new name' } });
fireEvent.change(screen.getByDisplayValue(mockCourse.description), { target: { value: 'new description' } });
fireEvent.change(screen.getByDisplayValue(mockCourse.open_course.toString()), { target: { value: 'true' } });

// mock formData and file reader
const formData = new FormData();
global.FormData = jest.fn(() => formData) as any;

const mockFileReader = {
readAsArrayBuffer: jest.fn(),
result: new ArrayBuffer(10),
onload: jest.fn(),
};
global.FileReader = jest.fn(() => mockFileReader) as any;

// submit the form
await waitFor(() => fireEvent.submit(screen.getByText("save changes")));
});
//TODO remove this test
it ('remove this test', () => {});
//
// it('renders correctly', async () => {
// await act(async () => {
// render(<EditCourseForm courseId={1}/>);
// });
// });
//
// it('check boxes', async () => {
// await act(async () => {
// render(<EditCourseForm courseId={1}/>);
// })
// // check if the name input was rendered properly
// expect(screen.getByText("course name")).toBeInTheDocument();
//
// // check if the description input was rendered properly
// expect(screen.getByText("description")).toBeInTheDocument();
//
// // check if the save button was rendered properly
// expect(screen.getByRole('button', {name: /save changes/i})).toBeInTheDocument();
// });
//
// it('fills form fields with course data', async () => {
// render(<EditCourseForm courseId={mockCourse.id}/>);
//
// // wait for the course data to be fetched
// await waitFor(() => expect(axios.get).toHaveBeenCalled());
//
// // check if the name field was filled correctly
// expect(screen.getByLabelText("course name")).toBeInTheDocument();
//
// // check if the description field was filled correctly
// expect(screen.getByLabelText("description")).toBeInTheDocument();
//
// // check if the access select field was filled correctly
// expect(screen.getByLabelText('access')).toBeInTheDocument();
// });
//
// it('submits the form correctly', async () => {
// const file = new File(['...'], 'test.png', {type: 'image/png'});
//
// render(<EditCourseForm courseId={mockCourse.id}/>);
//
// // wait for the course data to be fetched
// await waitFor(() => expect(axios.get).toHaveBeenCalled());
//
// // fill in the form fields
// fireEvent.change(screen.getByLabelText(/name/i), {target: {value: 'new name'}});
// fireEvent.change(screen.getByLabelText(/description/i), {target: {value: 'new description'}});
// fireEvent.change(screen.getByLabelText(/access/i), {target: {value: 'true'}});
// fireEvent.change(screen.getByLabelText(/select image/i), {target: {files: [file]}});
//
// // submit the form
// fireEvent.click(screen.getByRole('button', {name: /save changes/i}));
//
// // wait for the form to be submitted
// await waitFor(() => expect(axios.post).toHaveBeenCalled());
// await waitFor(() => expect(axios.put).toHaveBeenCalled());
//
// // check if the form was submitted with the correct data
// expect(axios.put).toHaveBeenCalledWith(expect.stringContaining(String(mockCourse.id)), expect.anything(), expect.anything());
// });
});
});
Loading

0 comments on commit 269748e

Please sign in to comment.