diff --git a/frontend/src/scripts/api.ts b/frontend/src/scripts/api.ts index 17c1326..41b56e2 100644 --- a/frontend/src/scripts/api.ts +++ b/frontend/src/scripts/api.ts @@ -1,8 +1,8 @@ import { AuthHeader } from "../security/AuthContext"; /* Timetable solver backend endpoint URL */ -const API_URL = "http://localhost:8080/timetabling"; -export const LOCAL_API_URL = "http://localhost:8080" +export const API_URL = "http://localhost:8080"; +export const LOCAL_API_URL = "http://localhost:8080"; /* =========================================== Defining types =========================================== */ @@ -62,9 +62,13 @@ export type Time = string; * @param problem A TimetableProblem is a list of units with no allocated time and room. * @returns A TimetableSolution with all units allocated a time and a room. */ -export async function fetchTimetableSolution(problem: TimetableProblem, authHeader: AuthHeader): Promise { +export async function fetchTimetableSolution(problem: TimetableProblem, authHeader: AuthHeader, url?: string): Promise { try { - const response = await fetch(API_URL, { + let api_url = API_URL; + if (url !== undefined) { + api_url = url; + } + const response = await fetch(api_url+"/timetabling", { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/frontend/src/tests/api.test.ts b/frontend/src/tests/api.test.ts index 235c6bf..0f26572 100644 --- a/frontend/src/tests/api.test.ts +++ b/frontend/src/tests/api.test.ts @@ -1,73 +1,80 @@ +import { describe, it, expect } from 'vitest'; +import { fetchTimetableSolution, LOCAL_API_URL, TimetableProblem } from '../scripts/api'; +import moment from 'moment'; +import { AuthHeader } from '../security/AuthContext'; + /** - * NOTE: NEED TO FIX THESE TESTS / THINK OF A WAY TO MAKE THESE TESTS WORK NOW THAT WE HAVE BASIC AUTH IN BACKEND. + * Test fetchTimetableSolution API method. + * Check if connection to backend is working. + * Check that output matches expected output. */ +describe('fetchTimetableSolution', { timeout: 200000 }, () => { + /** + * Validate end-to-end scheduling and data consistency of 1 API method call. + */ + it('return TimetableSolution', async () => { + const problem: TimetableProblem = { + campusName: "Geelong", + units: [{ campus: "Geelong", course: "B", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], + daysOfWeek: ["MONDAY"], + startTimes: ["11:00:00"], + rooms: [{ campus: "Geelong", buildingId: "01", roomCode: "Room A", capacity: 10, lab: true }] + }; + const authHeader: AuthHeader = `Basic ${btoa(`${import.meta.env.VITE_FRONTEND_USERNAME}:${import.meta.env.VITE_FRONTEND_PASSWORD}`)}`; -// import { describe, it, expect } from 'vitest'; -// import { fetchTimetableSolution, TimetableProblem } from '../scripts/api'; -// import moment from 'moment'; - -// /** -// * Test fetchTimetableSolution API method. -// * Check if connection to backend is working. -// * Check that output matches expected output. -// */ -// describe('fetchTimetableSolution', { timeout: 60000 }, () => { -// /** -// * Validate end-to-end scheduling and data consistency of 1 API method call. -// */ -// it('return TimetableSolution', async () => { -// const problem: TimetableProblem = { -// campusName: "A", -// units: [{ campus: "A", course: "B", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], -// daysOfWeek: ["MONDAY"], -// startTimes: ["11:00:00"], -// rooms: [{ campus: "A", buildingId: "01", roomCode: "Room A", capacity: 10, lab: true }] -// }; - -// const solution = await fetchTimetableSolution(problem, ''); -// expect(solution).not.toBeNull(); -// expect(solution?.units[0].dayOfWeek).toEqual(problem.daysOfWeek[0]); -// expect(solution?.units[0].startTime).toEqual(problem.startTimes[0]); -// expect(solution?.units[0].end).toEqual(addSecondsToTimeString(problem.startTimes[0], problem.units[0].duration)); -// expect(solution?.units[0].room).toHaveProperty("roomCode", problem.rooms[0].roomCode); -// expect(solution?.daysOfWeek).toEqual(problem.daysOfWeek); -// expect(solution?.startTimes).toEqual(problem.startTimes); + const solution = await fetchTimetableSolution(problem, authHeader, LOCAL_API_URL); + expect(solution).not.toBeNull(); + expect(solution?.units[0].dayOfWeek).toEqual(problem.daysOfWeek[0]); + expect(solution?.units[0].startTime).toEqual(problem.startTimes[0]); + expect(solution?.units[0].end).toEqual(addSecondsToTimeString(problem.startTimes[0], problem.units[0].duration)); + expect(solution?.units[0].room).toHaveProperty("roomCode", problem.rooms[0].roomCode); + expect(solution?.daysOfWeek).toEqual(problem.daysOfWeek); + expect(solution?.startTimes).toEqual(problem.startTimes); -// }); + }); -// /** -// * Validate that backend server can handle multiple solve requests concurrently. -// */ -// it ('can be called multiple times', async () => { -// const problem: TimetableProblem = { -// campusName: "B", -// units: [{ campus: "B", course: "C", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], -// daysOfWeek: ["MONDAY"], -// startTimes: ["11:00:00"], -// rooms: [{ campus: "B", buildingId: "02", roomCode: "Room A", capacity: 10, lab: true }] -// }; + /** + * Validate that backend server can handle multiple solve requests concurrently. + */ + it ('can be called multiple times', async () => { + const problem0: TimetableProblem = { + campusName: "Adelaide", + units: [{ campus: "Adelaide", course: "C", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], + daysOfWeek: ["MONDAY"], + startTimes: ["11:00:00"], + rooms: [{ campus: "Adelaide", buildingId: "02", roomCode: "Room A", capacity: 10, lab: true }] + }; -// const solutions = await Promise.all([fetchTimetableSolution(problem, ''), fetchTimetableSolution(problem, ''), fetchTimetableSolution(problem, '')]); + const problem1: TimetableProblem = { + campusName: "Melbourne", + units: [{ campus: "Melbourne", course: "C", unitId: 0, name: "Unit0", duration: 1200, students: [], wantsLab: true }], + daysOfWeek: ["MONDAY"], + startTimes: ["11:00:00"], + rooms: [{ campus: "Melbourne", buildingId: "02", roomCode: "Room A", capacity: 10, lab: true }] + }; + + const authHeader: AuthHeader = `Basic ${btoa(`${import.meta.env.VITE_FRONTEND_USERNAME}:${import.meta.env.VITE_FRONTEND_PASSWORD}`)}`; + const solutions = await Promise.all([fetchTimetableSolution(problem0, authHeader, LOCAL_API_URL), fetchTimetableSolution(problem1, authHeader, LOCAL_API_URL)]); -// for (let i = 0; i < solutions.length; i++) { -// expect(solutions[i]).not.toBeNull(); -// } + for (let i = 0; i < solutions.length; i++) { + expect(solutions[i]).not.toBeNull(); + } -// }); + }); -// }); +}); -// /** -// * Helper function. -// * Add a string representing time with a number representing number of seconds to add. -// * -// * @param timeString string representing time -// * @param secondsToAdd number in seconds -// * @returns string representing time after specified seconds have been added to it -// */ -// function addSecondsToTimeString(timeString: string, secondsToAdd: number) { -// const time = moment(timeString, 'HH:mm:ss'); -// time.add(secondsToAdd, 'seconds'); -// return time.format('HH:mm:ss'); -// } \ No newline at end of file +/** + * Helper function. + * Add a string representing time with a number representing number of seconds to add. + * + * @param timeString string representing time + * @param secondsToAdd number in seconds + * @returns string representing time after specified seconds have been added to it + */ +function addSecondsToTimeString(timeString: string, secondsToAdd: number) { + const time = moment(timeString, 'HH:mm:ss'); + time.add(secondsToAdd, 'seconds'); + return time.format('HH:mm:ss'); +} \ No newline at end of file