diff --git a/nextjs/src/models/local/assignmnet/utils/assignmentMarkdownParser.ts b/nextjs/src/models/local/assignmnet/utils/assignmentMarkdownParser.ts index 4b037c4..f36c6ef 100644 --- a/nextjs/src/models/local/assignmnet/utils/assignmentMarkdownParser.ts +++ b/nextjs/src/models/local/assignmnet/utils/assignmentMarkdownParser.ts @@ -1,4 +1,7 @@ -import { timeUtils } from "../../timeUtils"; +import { + verifyDateOrThrow, + verifyDateStringOrUndefined, +} from "../../timeUtils"; import { AssignmentSubmissionType } from "../assignmentSubmissionType"; import { LocalAssignment } from "../localAssignment"; import { RubricItem } from "../rubricItem"; @@ -51,8 +54,8 @@ const parseSettings = (input: string) => { const submissionTypes = parseSubmissionTypes(input); const fileUploadExtensions = parseFileUploadExtensions(input); - const dueAt = timeUtils.verifyDateOrThrow(rawDueAt, "DueAt"); - const lockAt = timeUtils.verifyDateStringOrUndefined(rawLockAt); + const dueAt = verifyDateOrThrow(rawDueAt, "DueAt"); + const lockAt = verifyDateStringOrUndefined(rawLockAt); return { name, diff --git a/nextjs/src/models/local/localCourse.ts b/nextjs/src/models/local/localCourse.ts index dc7dbd7..2249c3e 100644 --- a/nextjs/src/models/local/localCourse.ts +++ b/nextjs/src/models/local/localCourse.ts @@ -11,9 +11,8 @@ export interface SimpleTimeOnly { minute: number; } - - export interface LocalCourseSettings { + name: string; assignmentGroups: LocalAssignmentGroup[]; daysOfWeek: DayOfWeek[]; canvasId?: number; @@ -32,7 +31,6 @@ export enum DayOfWeek { Saturday = "Saturday", } - // export const LocalCourseSettingsUtils = { // toYaml(settings: LocalCourseSettings): string { // return dump(settings, { noRefs: true }); @@ -42,4 +40,4 @@ export enum DayOfWeek { // const settings = load(rawText) as LocalCourseSettings; // return createLocalCourseSettings(settings); // }, -// }; \ No newline at end of file +// }; diff --git a/nextjs/src/services/tests/courseDifferenceChanges.test.ts b/nextjs/src/services/tests/courseDifferenceChanges.test.ts new file mode 100644 index 0000000..c8adad9 --- /dev/null +++ b/nextjs/src/services/tests/courseDifferenceChanges.test.ts @@ -0,0 +1,579 @@ +import { describe, it, expect } from "vitest"; +import { LocalCourse } from "@/models/local/localCourse"; +import { CourseDifferences } from "../fileStorage/courseDifferences"; +import { AssignmentSubmissionType } from "@/models/local/assignmnet/assignmentSubmissionType"; + +describe("CourseDifferencesChangesTests", () => { + it("can detect new settings", () => { + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: "09/07/2024 23:59:00", + endDate: "09/07/2024 23:59:00", + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [], + }; + const newCourse: LocalCourse = { + ...oldCourse, + settings: { + ...oldCourse.settings, + name: "new course name", + }, + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(0); + expect(differences.settings).not.toBeNull(); + expect(differences.settings?.name).toBe("new course name"); + }); + + it("can detect new module", () => { + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: "09/07/2024 23:59:00", + endDate: "09/07/2024 23:59:00", + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [], + }; + const newCourse: LocalCourse = { + ...oldCourse, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [], + pages: [], + }, + ], + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).not.toBeNull(); + expect(differences.modules).toHaveLength(1); + expect(differences.modules?.[0].name).toBe("new module"); + }); + + it("can detect changed assignment", () => { + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: "09/07/2024 23:59:00", + endDate: "09/07/2024 23:59:00", + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [ + { + name: "test assignment", + description: "", + dueAt: "09/07/2024 23:59:00", + submissionTypes: [], + allowedFileUploadExtensions: [], + rubric: [], + }, + ], + quizzes: [], + pages: [], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + modules: [ + { + name: "new module", + assignments: [ + { + name: "test assignment", + description: "new description", + dueAt: "09/07/2024 23:59:00", + submissionTypes: [], + allowedFileUploadExtensions: [], + rubric: [], + }, + ], + quizzes: [], + pages: [], + }, + ], + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).not.toBeNull(); + expect(differences.modules).toHaveLength(1); + expect(differences.modules?.[0].assignments?.[0].description).toBe("new description"); + }); + + it("can properly ignore unchanged modules", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [ + { + name: "test assignment", + description: "", + dueAt: commonDate, + submissionTypes: [], + allowedFileUploadExtensions: [], + rubric: [], + }, + ], + quizzes: [], + pages: [], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(0); + }); + + it("only changed assignment represented", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [ + { + name: "test assignment", + description: "", + dueAt: commonDate, + submissionTypes: [AssignmentSubmissionType.ONLINE_UPLOAD], + allowedFileUploadExtensions: [], + rubric: [{ points: 1, label: "rubric" }], + }, + { + name: "test assignment 2", + description: "", + dueAt: commonDate, + submissionTypes: [], + allowedFileUploadExtensions: [], + rubric: [], + }, + ], + quizzes: [], + pages: [], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + modules: [ + { + name: "new module", + assignments: [ + { + name: "test assignment", + description: "", + dueAt: commonDate, + submissionTypes: [AssignmentSubmissionType.ONLINE_UPLOAD], + allowedFileUploadExtensions: [], + rubric: [{ points: 1, label: "rubric" }], + }, + { + name: "test assignment 2 with a new name", + description: "", + dueAt: commonDate, + submissionTypes: [], + allowedFileUploadExtensions: [], + rubric: [], + }, + ], + quizzes: [], + pages: [], + }, + ], + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(1); + expect(differences.modules?.[0].assignments).toHaveLength(1); + expect(differences.modules?.[0].assignments?.[0].name).toBe("test assignment 2 with a new name"); + }); + + it("identical quizzes ignored", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [ + { + name: "Test Quiz", + description: "this is my description", + dueAt: commonDate, + shuffleAnswers: true, + showCorrectAnswers: false, + oneQuestionAtATime: false, + allowedAttempts: -1, + questions: [], + }, + ], + pages: [], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(0); + }); + + it("can detect different quiz", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [ + { + name: "Test Quiz", + description: "this is my description", + dueAt: commonDate, + shuffleAnswers: true, + showCorrectAnswers: false, + oneQuestionAtATime: false, + allowedAttempts: -1, + questions: [], + }, + ], + pages: [], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [ + { + name: "Test Quiz", + description: "this is my description", + dueAt: commonDate, + shuffleAnswers: true, + showCorrectAnswers: false, + oneQuestionAtATime: false, + allowedAttempts: -1, + questions: [], + lockAt: "12/31/9999 23:59:59", + }, + ], + pages: [], + }, + ], + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(1); + expect(differences.modules?.[0].quizzes).toHaveLength(1); + expect(differences.modules?.[0].quizzes?.[0].lockAt).toBe("12/31/9999 23:59:59"); + }); + + it("can detect only different quiz when other quizzes stay", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [ + { + name: "Test Quiz", + description: "this is my description", + dueAt: commonDate, + shuffleAnswers: true, + showCorrectAnswers: false, + oneQuestionAtATime: false, + allowedAttempts: -1, + questions: [], + }, + ], + pages: [], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [ + { + name: "Test Quiz", + description: "this is my description", + dueAt: commonDate, + shuffleAnswers: true, + showCorrectAnswers: false, + oneQuestionAtATime: false, + allowedAttempts: -1, + questions: [], + }, + { + name: "Test Quiz 2", + description: "this is my description", + dueAt: commonDate, + shuffleAnswers: true, + showCorrectAnswers: false, + oneQuestionAtATime: false, + allowedAttempts: -1, + questions: [], + }, + ], + pages: [], + }, + ], + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(1); + expect(differences.modules?.[0].quizzes).toHaveLength(1); + expect(differences.modules?.[0].quizzes?.[0].name).toBe("Test Quiz 2"); + }); + + it("same pages not detected", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [], + pages: [ + { + name: "test page", + text: "test description", + dueAt: commonDate, + }, + ], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(0); + }); + + it("different page detected", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [], + pages: [ + { + name: "test page", + text: "test description", + dueAt: commonDate, + }, + ], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [], + pages: [ + { + name: "test page", + text: "test description changed", + dueAt: commonDate, + }, + ], + }, + ], + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(1); + expect(differences.modules?.[0].pages).toHaveLength(1); + expect(differences.modules?.[0].pages?.[0].text).toBe("test description changed"); + }); + + it("different page detected but not same page", () => { + const commonDate = "09/07/2024 23:59:00"; + const oldCourse: LocalCourse = { + settings: { + name: "Test Course", + assignmentGroups: [], + daysOfWeek: [], + startDate: commonDate, + endDate: commonDate, + defaultDueTime: { + hour: 23, + minute: 59, + }, + }, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [], + pages: [ + { + name: "test page", + text: "test description", + dueAt: commonDate, + }, + ], + }, + ], + }; + const newCourse: LocalCourse = { + ...oldCourse, + modules: [ + { + name: "new module", + assignments: [], + quizzes: [], + pages: [ + { + name: "test page", + text: "test description", + dueAt: commonDate, + }, + { + name: "test page 2", + text: "test description", + dueAt: commonDate, + }, + ], + }, + ], + }; + + const differences = CourseDifferences.getNewChanges(newCourse, oldCourse); + + expect(differences.modules).toHaveLength(1); + expect(differences.modules?.[0].pages).toHaveLength(1); + expect(differences.modules?.[0].pages?.[0].name).toBe("test page 2"); + }); +}); diff --git a/nextjs/src/services/tests/courseDifferencesDeletions.test.ts b/nextjs/src/services/tests/courseDifferencesDeletions.test.ts index 6645804..739dcbd 100644 --- a/nextjs/src/services/tests/courseDifferencesDeletions.test.ts +++ b/nextjs/src/services/tests/courseDifferencesDeletions.test.ts @@ -6,6 +6,7 @@ describe("CourseDifferencesDeletionsTests", () => { it("same module does not get deleted", () => { const oldCourse: LocalCourse = { settings: { + name: "test course", assignmentGroups: [], daysOfWeek: [], startDate: "09/07/2024 23:59:00", @@ -44,6 +45,7 @@ describe("CourseDifferencesDeletionsTests", () => { it("changed module - old one gets deleted", () => { const oldCourse: LocalCourse = { settings: { + name: "test course", assignmentGroups: [], daysOfWeek: [], startDate: "09/07/2024 23:59:00", @@ -83,6 +85,7 @@ describe("CourseDifferencesDeletionsTests", () => { it("new assignment name gets deleted", () => { const oldCourse: LocalCourse = { settings: { + name: "test course", assignmentGroups: [], daysOfWeek: [], startDate: "09/07/2024 23:59:00", @@ -144,6 +147,7 @@ describe("CourseDifferencesDeletionsTests", () => { it("assignments with changed descriptions do not get deleted", () => { const oldCourse: LocalCourse = { settings: { + name: "test course", assignmentGroups: [], daysOfWeek: [], startDate: "09/07/2024 23:59:00", @@ -200,6 +204,7 @@ describe("CourseDifferencesDeletionsTests", () => { it("can detect changed and unchanged assignments", () => { const oldCourse: LocalCourse = { settings: { + name: "test course", assignmentGroups: [], daysOfWeek: [], startDate: "09/07/2024 23:59:00", @@ -276,6 +281,7 @@ describe("CourseDifferencesDeletionsTests", () => { it("changed quizzes get deleted", () => { const oldCourse: LocalCourse = { settings: { + name: "test course", assignmentGroups: [], daysOfWeek: [], startDate: "09/07/2024 23:59:00", @@ -360,6 +366,7 @@ describe("CourseDifferencesDeletionsTests", () => { it("changed pages get deleted", () => { const oldCourse: LocalCourse = { settings: { + name: "test course", assignmentGroups: [], daysOfWeek: [], startDate: "09/07/2024 23:59:00",