From c557bbcc28a57275b784f04b3c29d1d6e3f58f86 Mon Sep 17 00:00:00 2001 From: Alex Mickelson Date: Tue, 17 Dec 2024 14:09:41 -0700 Subject: [PATCH] moving name out of file, will mirror file system name --- requests/semester.http | 2 +- .../[assignmentName]/EditAssignment.tsx | 4 +- .../[moduleName]/quiz/[quizName]/EditQuiz.tsx | 12 +++++- .../utils/assignmentMarkdownParser.ts | 6 +-- .../local/quiz/utils/quizMarkdownUtils.ts | 7 ++-- .../local/tests/assignmentMarkdown.test.ts | 39 ++++++++++++------- .../quizMarkdown/matchingAnswerErrors.test.ts | 8 ++-- .../quizMarkdown/matchingAnswers.test.ts | 20 +++++----- .../quizMarkdown/multipleAnswers.test.ts | 12 +++--- .../quizDeterministicChecks.test.ts | 35 ++++++++++------- .../tests/quizMarkdown/quizMarkdown.test.ts | 32 +++++++-------- .../tests/quizMarkdown/testAnswer.test.ts | 19 ++++----- src/services/canvas/canvasModuleService.ts | 6 +-- .../assignmentsFileStorageService.ts | 4 +- .../courseItemFileStorageService.ts | 5 ++- .../tests/fileStorageParsingErrors.test.ts | 2 +- vitest.config.ts | 10 ++++- 17 files changed, 127 insertions(+), 96 deletions(-) diff --git a/requests/semester.http b/requests/semester.http index 4dea593..0f99920 100644 --- a/requests/semester.http +++ b/requests/semester.http @@ -19,7 +19,7 @@ GET https://snow.instructure.com/api/v1/courses?enrollment_term_id=751&per_page= Authorization: Bearer {{$dotenv CANVAS_TOKEN}} ### -GET https://snow.instructure.com/api/v1/courses/855351/modules +GET https://snow.instructure.com/api/v1/courses/1014136/modules Authorization: Bearer {{$dotenv CANVAS_TOKEN}} ### diff --git a/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx b/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx index 62d55fb..2ff7194 100644 --- a/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx +++ b/src/app/course/[courseName]/modules/[moduleName]/assignment/[assignmentName]/EditAssignment.tsx @@ -21,6 +21,7 @@ import { LocalCourseSettings } from "@/models/local/localCourseSettings"; import { useRouter } from "next/navigation"; import { AssignmentButtons } from "./AssignmentButtons"; import { useAuthoritativeUpdates } from "@/app/course/[courseName]/utils/useAuthoritativeUpdates"; +import { extractLabelValue } from "@/models/local/assignment/utils/markdownUtils"; export default function EditAssignment({ moduleName, @@ -64,8 +65,9 @@ export default function EditAssignment({ return; } + const name = extractLabelValue(text, "Name"); const updatedAssignment: LocalAssignment = - localAssignmentMarkdown.parseMarkdown(text); + localAssignmentMarkdown.parseMarkdown(text, name); if ( localAssignmentMarkdown.toMarkdown(assignment) !== localAssignmentMarkdown.toMarkdown(updatedAssignment) diff --git a/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx b/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx index 032ca6f..c71fca5 100644 --- a/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx +++ b/src/app/course/[courseName]/modules/[moduleName]/quiz/[quizName]/EditQuiz.tsx @@ -14,6 +14,7 @@ import { useUpdateQuizMutation, } from "@/hooks/localCourse/quizHooks"; import { useAuthoritativeUpdates } from "../../../../utils/useAuthoritativeUpdates"; +import { extractLabelValue } from "@/models/local/assignment/utils/markdownUtils"; const helpString = `QUESTION REFERENCE --- @@ -85,12 +86,19 @@ export default function EditQuiz({ return; } try { + const name = extractLabelValue(text, "Name"); if ( quizMarkdownUtils.toMarkdown(quiz) !== - quizMarkdownUtils.toMarkdown(quizMarkdownUtils.parseMarkdown(text)) + quizMarkdownUtils.toMarkdown( + quizMarkdownUtils.parseMarkdown(text, name) + ) ) { if (clientIsAuthoritative) { - const updatedQuiz = quizMarkdownUtils.parseMarkdown(text); + const updatedName = extractLabelValue(text, "Name"); + const updatedQuiz = quizMarkdownUtils.parseMarkdown( + text, + updatedName + ); await updateQuizMutation .mutateAsync({ quiz: updatedQuiz, diff --git a/src/models/local/assignment/utils/assignmentMarkdownParser.ts b/src/models/local/assignment/utils/assignmentMarkdownParser.ts index 698c49e..a99b5b9 100644 --- a/src/models/local/assignment/utils/assignmentMarkdownParser.ts +++ b/src/models/local/assignment/utils/assignmentMarkdownParser.ts @@ -47,7 +47,6 @@ const parseIndividualRubricItemMarkdown = (rawMarkdown: string) => { }; const parseSettings = (input: string) => { - const name = extractLabelValue(input, "Name"); const rawLockAt = extractLabelValue(input, "LockAt"); const rawDueAt = extractLabelValue(input, "DueAt"); const assignmentGroupName = extractLabelValue(input, "AssignmentGroupName"); @@ -58,7 +57,6 @@ const parseSettings = (input: string) => { const lockAt = verifyDateStringOrUndefined(rawLockAt); return { - name, assignmentGroupName, submissionTypes, fileUploadExtensions, @@ -110,10 +108,10 @@ const parseRubricMarkdown = (rawMarkdown: string) => { export const assignmentMarkdownParser = { parseRubricMarkdown, - parseMarkdown(input: string): LocalAssignment { + parseMarkdown(input: string, name: string): LocalAssignment { const settingsString = input.split("---")[0]; const { - name, + // name, assignmentGroupName, submissionTypes, fileUploadExtensions, diff --git a/src/models/local/quiz/utils/quizMarkdownUtils.ts b/src/models/local/quiz/utils/quizMarkdownUtils.ts index 7c0606b..50b1aaa 100644 --- a/src/models/local/quiz/utils/quizMarkdownUtils.ts +++ b/src/models/local/quiz/utils/quizMarkdownUtils.ts @@ -40,8 +40,7 @@ const parseNumberOrThrow = (value: string, label: string): number => { } return parsed; }; -const getQuizWithOnlySettings = (settings: string): LocalQuiz => { - const name = extractLabelValue(settings, "Name"); +const getQuizWithOnlySettings = (settings: string, name: string): LocalQuiz => { const rawShuffleAnswers = extractLabelValue(settings, "ShuffleAnswers"); const shuffleAnswers = parseBooleanOrThrow( @@ -136,10 +135,10 @@ Description: ${quiz.description} ${questionMarkdown}`; }, - parseMarkdown(input: string): LocalQuiz { + parseMarkdown(input: string, name: string): LocalQuiz { const splitInput = input.split("---\n"); const settings = splitInput[0]; - const quizWithoutQuestions = getQuizWithOnlySettings(settings); + const quizWithoutQuestions = getQuizWithOnlySettings(settings, name); const rawQuestions = splitInput.slice(1); const questions = rawQuestions diff --git a/src/models/local/tests/assignmentMarkdown.test.ts b/src/models/local/tests/assignmentMarkdown.test.ts index be92620..c5574b6 100644 --- a/src/models/local/tests/assignmentMarkdown.test.ts +++ b/src/models/local/tests/assignmentMarkdown.test.ts @@ -6,8 +6,9 @@ import { assignmentMarkdownParser } from "../assignment/utils/assignmentMarkdown describe("AssignmentMarkdownTests", () => { it("can parse assignment settings", () => { + const name = "test assignment"; const assignment: LocalAssignment = { - name: "test assignment", + name, description: "here is the description", dueAt: "08/21/2023 23:59:00", lockAt: "08/21/2023 23:59:00", @@ -22,15 +23,18 @@ describe("AssignmentMarkdownTests", () => { const assignmentMarkdown = assignmentMarkdownSerializer.toMarkdown(assignment); - const parsedAssignment = - assignmentMarkdownParser.parseMarkdown(assignmentMarkdown); + const parsedAssignment = assignmentMarkdownParser.parseMarkdown( + assignmentMarkdown, + name + ); expect(parsedAssignment).toEqual(assignment); }); it("assignment with empty rubric can be parsed", () => { + const name = "test assignment"; const assignment: LocalAssignment = { - name: "test assignment", + name, description: "here is the description", dueAt: "08/21/2023 23:59:00", lockAt: "08/21/2023 23:59:00", @@ -43,14 +47,15 @@ describe("AssignmentMarkdownTests", () => { const assignmentMarkdown = assignmentMarkdownSerializer.toMarkdown(assignment); const parsedAssignment = - assignmentMarkdownParser.parseMarkdown(assignmentMarkdown); + assignmentMarkdownParser.parseMarkdown(assignmentMarkdown, name); expect(parsedAssignment).toEqual(assignment); }); it("assignment with empty submission types can be parsed", () => { + const name = "test assignment"; const assignment: LocalAssignment = { - name: "test assignment", + name, description: "here is the description", dueAt: "08/21/2023 23:59:00", lockAt: "08/21/2023 23:59:00", @@ -66,14 +71,15 @@ describe("AssignmentMarkdownTests", () => { const assignmentMarkdown = assignmentMarkdownSerializer.toMarkdown(assignment); const parsedAssignment = - assignmentMarkdownParser.parseMarkdown(assignmentMarkdown); + assignmentMarkdownParser.parseMarkdown(assignmentMarkdown, name); expect(parsedAssignment).toEqual(assignment); }); it("assignment without lockAt date can be parsed", () => { + const name = "test assignment"; const assignment: LocalAssignment = { - name: "test assignment", + name, description: "here is the description", dueAt: "08/21/2023 23:59:00", lockAt: undefined, @@ -89,14 +95,15 @@ describe("AssignmentMarkdownTests", () => { const assignmentMarkdown = assignmentMarkdownSerializer.toMarkdown(assignment); const parsedAssignment = - assignmentMarkdownParser.parseMarkdown(assignmentMarkdown); + assignmentMarkdownParser.parseMarkdown(assignmentMarkdown, name); expect(parsedAssignment).toEqual(assignment); }); it("assignment without description can be parsed", () => { + const name = "test assignment"; const assignment: LocalAssignment = { - name: "test assignment", + name, description: "", dueAt: "08/21/2023 23:59:00", lockAt: "08/21/2023 23:59:00", @@ -112,14 +119,15 @@ describe("AssignmentMarkdownTests", () => { const assignmentMarkdown = assignmentMarkdownSerializer.toMarkdown(assignment); const parsedAssignment = - assignmentMarkdownParser.parseMarkdown(assignmentMarkdown); + assignmentMarkdownParser.parseMarkdown(assignmentMarkdown, name); expect(parsedAssignment).toEqual(assignment); }); it("assignments can have three dashes", () => { + const name = "test assignment"; const assignment: LocalAssignment = { - name: "test assignment", + name, description: "test assignment\n---\nsomestuff", dueAt: "08/21/2023 23:59:00", lockAt: "08/21/2023 23:59:00", @@ -132,14 +140,15 @@ describe("AssignmentMarkdownTests", () => { const assignmentMarkdown = assignmentMarkdownSerializer.toMarkdown(assignment); const parsedAssignment = - assignmentMarkdownParser.parseMarkdown(assignmentMarkdown); + assignmentMarkdownParser.parseMarkdown(assignmentMarkdown, name); expect(parsedAssignment).toEqual(assignment); }); it("assignments can restrict upload types", () => { + const name = "test assignment"; const assignment: LocalAssignment = { - name: "test assignment", + name, description: "here is the description", dueAt: "08/21/2023 23:59:00", lockAt: "08/21/2023 23:59:00", @@ -152,7 +161,7 @@ describe("AssignmentMarkdownTests", () => { const assignmentMarkdown = assignmentMarkdownSerializer.toMarkdown(assignment); const parsedAssignment = - assignmentMarkdownParser.parseMarkdown(assignmentMarkdown); + assignmentMarkdownParser.parseMarkdown(assignmentMarkdown, name); expect(parsedAssignment).toEqual(assignment); }); diff --git a/src/models/local/tests/quizMarkdown/matchingAnswerErrors.test.ts b/src/models/local/tests/quizMarkdown/matchingAnswerErrors.test.ts index ae5d9c9..9c9c74f 100644 --- a/src/models/local/tests/quizMarkdown/matchingAnswerErrors.test.ts +++ b/src/models/local/tests/quizMarkdown/matchingAnswerErrors.test.ts @@ -3,8 +3,8 @@ import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils"; describe("Matching Answer Error Messages", () => { it("can parse matching question", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -18,8 +18,8 @@ question without answer `; - expect(() => quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz)).toThrowError( - /question type/ - ); + expect(() => + quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name) + ).toThrowError(/question type/); }); }); diff --git a/src/models/local/tests/quizMarkdown/matchingAnswers.test.ts b/src/models/local/tests/quizMarkdown/matchingAnswers.test.ts index 821c7dc..a75bb3e 100644 --- a/src/models/local/tests/quizMarkdown/matchingAnswers.test.ts +++ b/src/models/local/tests/quizMarkdown/matchingAnswers.test.ts @@ -5,8 +5,8 @@ import { quizQuestionMarkdownUtils } from "@/models/local/quiz/utils/quizQuestio describe("MatchingTests", () => { it("can parse matching question", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -22,7 +22,7 @@ Match the following terms & definitions ^ keyword - reserved word that has special meaning in a program (e.g. class, void, static, etc.) `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.questionType).toBe(QuestionType.MATCHING); @@ -33,8 +33,8 @@ Match the following terms & definitions }); it("can create markdown for matching question", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -50,7 +50,7 @@ Match the following terms & definitions ^ keyword - reserved word that has special meaning in a program (e.g. class, void, static, etc.) `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const questionMarkdown = quizQuestionMarkdownUtils.toMarkdown( quiz.questions[0] ); @@ -65,8 +65,8 @@ Match the following terms & definitions }); it("whitespace is optional", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -80,13 +80,13 @@ Match the following terms & definitions ^statement - a single command to be executed `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); expect(quiz.questions[0].answers[0].text).toBe("statement"); }); it("can have distractors", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -101,15 +101,15 @@ Match the following terms & definitions ^ - this is the distractor `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); expect(quiz.questions[0].matchDistractors).toEqual([ "this is the distractor", ]); }); it("can have distractors and be persisted", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -124,7 +124,7 @@ Match the following terms & definitions ^ - this is the distractor `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); expect(quizMarkdown).toContain( diff --git a/src/models/local/tests/quizMarkdown/multipleAnswers.test.ts b/src/models/local/tests/quizMarkdown/multipleAnswers.test.ts index 5fd9257..f8e40fc 100644 --- a/src/models/local/tests/quizMarkdown/multipleAnswers.test.ts +++ b/src/models/local/tests/quizMarkdown/multipleAnswers.test.ts @@ -41,8 +41,8 @@ oneline question }); it("can parse question with multiple answers", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -64,7 +64,7 @@ Which events are triggered when the user clicks on an input field? --- `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.points).toBe(1); @@ -79,8 +79,8 @@ Which events are triggered when the user clicks on an input field? }); it("can parse question with multiple answers without a space in false answers", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -96,7 +96,7 @@ Which events are triggered when the user clicks on an input field? [] submit `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.answers.length).toBe(2); @@ -105,8 +105,8 @@ Which events are triggered when the user clicks on an input field? }); it("can parse question with multiple answers without a space in false answers other example", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -124,7 +124,7 @@ Which tool(s) will let you: create a database migration or reverse-engineer an e [*] dotnet ef command line interface `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.answers.length).toBe(3); diff --git a/src/models/local/tests/quizMarkdown/quizDeterministicChecks.test.ts b/src/models/local/tests/quizMarkdown/quizDeterministicChecks.test.ts index 01b62f5..e81a0e0 100644 --- a/src/models/local/tests/quizMarkdown/quizDeterministicChecks.test.ts +++ b/src/models/local/tests/quizMarkdown/quizDeterministicChecks.test.ts @@ -6,8 +6,9 @@ import { QuestionType } from "@/models/local/quiz/localQuizQuestion"; // Test suite for deterministic checks on LocalQuiz describe("QuizDeterministicChecks", () => { it("SerializationIsDeterministic_EmptyQuiz", () => { + const name = "Test Quiz"; const quiz: LocalQuiz = { - name: "Test Quiz", + name, description: "quiz description", lockAt: "08/21/2023 23:59:00", dueAt: "08/21/2023 23:59:00", @@ -20,14 +21,15 @@ describe("QuizDeterministicChecks", () => { }; const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); - const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown); + const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown, name); expect(parsedQuiz).toEqual(quiz); }); it("SerializationIsDeterministic_ShowCorrectAnswers", () => { + const name = "Test Quiz"; const quiz: LocalQuiz = { - name: "Test Quiz", + name, description: "quiz description", lockAt: "08/21/2023 23:59:00", dueAt: "08/21/2023 23:59:00", @@ -40,14 +42,15 @@ describe("QuizDeterministicChecks", () => { }; const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); - const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown); + const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown, name); expect(parsedQuiz).toEqual(quiz); }); it("SerializationIsDeterministic_ShortAnswer", () => { + const name = "Test Quiz"; const quiz: LocalQuiz = { - name: "Test Quiz", + name, description: "quiz description", lockAt: "08/21/2023 23:59:00", dueAt: "08/21/2023 23:59:00", @@ -68,14 +71,15 @@ describe("QuizDeterministicChecks", () => { }; const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); - const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown); + const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown, name); expect(parsedQuiz).toEqual(quiz); }); it("SerializationIsDeterministic_Essay", () => { + const name = "Test Quiz"; const quiz: LocalQuiz = { - name: "Test Quiz", + name, description: "quiz description", lockAt: "08/21/2023 23:59:00", dueAt: "08/21/2023 23:59:00", @@ -96,14 +100,15 @@ describe("QuizDeterministicChecks", () => { }; const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); - const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown); + const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown, name); expect(parsedQuiz).toEqual(quiz); }); it("SerializationIsDeterministic_MultipleAnswer", () => { + const name = "Test Quiz"; const quiz: LocalQuiz = { - name: "Test Quiz", + name, description: "quiz description", lockAt: "08/21/2023 23:59:00", dueAt: "08/21/2023 23:59:00", @@ -127,14 +132,15 @@ describe("QuizDeterministicChecks", () => { }; const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); - const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown); + const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown, name); expect(parsedQuiz).toEqual(quiz); }); it("SerializationIsDeterministic_MultipleChoice", () => { + const name = "Test Quiz"; const quiz: LocalQuiz = { - name: "Test Quiz", + name, description: "quiz description", lockAt: "08/21/2023 23:59:00", dueAt: "08/21/2023 23:59:00", @@ -159,14 +165,15 @@ describe("QuizDeterministicChecks", () => { }; const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); - const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown); + const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown, name); expect(parsedQuiz).toEqual(quiz); }); it("SerializationIsDeterministic_Matching", () => { + const name = "Test Quiz"; const quiz: LocalQuiz = { - name: "Test Quiz", + name, description: "quiz description", lockAt: "08/21/2023 23:59:00", dueAt: "08/21/2023 23:59:00", @@ -191,7 +198,7 @@ describe("QuizDeterministicChecks", () => { }; const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz); - const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown); + const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown, name); expect(parsedQuiz).toEqual(quiz); }); diff --git a/src/models/local/tests/quizMarkdown/quizMarkdown.test.ts b/src/models/local/tests/quizMarkdown/quizMarkdown.test.ts index 79d35f7..c1d25e2 100644 --- a/src/models/local/tests/quizMarkdown/quizMarkdown.test.ts +++ b/src/models/local/tests/quizMarkdown/quizMarkdown.test.ts @@ -37,8 +37,8 @@ this is my description in markdown }); it("can parse markdown quiz with no questions", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -51,7 +51,7 @@ description --- `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const expectedDescription = ` this is the @@ -67,8 +67,8 @@ description`; it("can parse markdown quiz with password", () => { const password = "this-is-the-password"; + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz Password: ${password} ShuffleAnswers: true OneQuestionAtATime: false @@ -82,14 +82,14 @@ description --- `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); expect(quiz.password).toBe(password); }); it("can parse markdown quiz and configure to show correct answers", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false ShowCorrectAnswers: false @@ -103,14 +103,14 @@ description --- `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); expect(quiz.showCorrectAnswers).toBe(false); }); it("can parse quiz with questions", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -135,7 +135,7 @@ b) false endline`; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.questionType).toBe(QuestionType.MULTIPLE_CHOICE); @@ -149,8 +149,8 @@ b) false }); it("can parse multiple questions", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -170,7 +170,7 @@ Points: 2 b) false `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.points).toBe(1); expect(firstQuestion.questionType).toBe(QuestionType.MULTIPLE_ANSWERS); @@ -181,8 +181,8 @@ b) false }); it("short answer to markdown is correct", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -197,7 +197,7 @@ Which events are triggered when the user clicks on an input field? short answer `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; const questionMarkdown = @@ -209,8 +209,8 @@ short_answer`; }); it("negative points is allowed", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -226,14 +226,14 @@ Which events are triggered when the user clicks on an input field? short answer `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.points).toBe(-4); }); it("floating point points is allowed", () => { + const name = "Test Quiz"; const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -249,7 +249,7 @@ Which events are triggered when the user clicks on an input field? short answer `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.points).toBe(4.56); }); diff --git a/src/models/local/tests/quizMarkdown/testAnswer.test.ts b/src/models/local/tests/quizMarkdown/testAnswer.test.ts index 3422776..c4d1e2e 100644 --- a/src/models/local/tests/quizMarkdown/testAnswer.test.ts +++ b/src/models/local/tests/quizMarkdown/testAnswer.test.ts @@ -5,8 +5,8 @@ import { describe, it, expect } from "vitest"; describe("TextAnswerTests", () => { it("can parse essay", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -21,7 +21,7 @@ Which events are triggered when the user clicks on an input field? essay `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.points).toBe(1); @@ -30,8 +30,8 @@ essay }); it("can parse short answer", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -46,7 +46,7 @@ Which events are triggered when the user clicks on an input field? short answer `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; expect(firstQuestion.points).toBe(1); @@ -55,8 +55,9 @@ short answer }); it("short answer to markdown is correct", () => { + + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -71,7 +72,7 @@ Which events are triggered when the user clicks on an input field? short answer `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; const questionMarkdown = @@ -83,8 +84,8 @@ short_answer`; }); it("essay question to markdown is correct", () => { + const name = "Test Quiz" const rawMarkdownQuiz = ` -Name: Test Quiz ShuffleAnswers: true OneQuestionAtATime: false DueAt: 08/21/2023 23:59:00 @@ -99,7 +100,7 @@ Which events are triggered when the user clicks on an input field? essay `; - const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); + const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); const firstQuestion = quiz.questions[0]; const questionMarkdown = @@ -128,7 +129,7 @@ essay`; // short_answer= // `; -// const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz); +// const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz, name); // const firstQuestion = quiz.questions[0]; diff --git a/src/services/canvas/canvasModuleService.ts b/src/services/canvas/canvasModuleService.ts index 43784ba..bdf5253 100644 --- a/src/services/canvas/canvasModuleService.ts +++ b/src/services/canvas/canvasModuleService.ts @@ -1,7 +1,7 @@ import { CanvasModuleItem } from "@/models/canvas/modules/canvasModuleItems"; import { CanvasPage } from "@/models/canvas/pages/canvasPageModel"; import { axiosClient } from "../axiosUtils"; -import { canvasApi } from "./canvasServiceUtils"; +import { canvasApi, paginatedRequest } from "./canvasServiceUtils"; import { CanvasModule } from "@/models/canvas/modules/canvasModule"; export const canvasModuleService = { @@ -49,8 +49,8 @@ export const canvasModuleService = { async getCourseModules(canvasCourseId: number) { const url = `${canvasApi}/courses/${canvasCourseId}/modules`; - const response = await axiosClient.get(url); - return response.data; + const response = await paginatedRequest({ url }); + return response }, async createModule(canvasCourseId: number, moduleName: string) { diff --git a/src/services/fileStorage/assignmentsFileStorageService.ts b/src/services/fileStorage/assignmentsFileStorageService.ts index 2bca34e..df1fda3 100644 --- a/src/services/fileStorage/assignmentsFileStorageService.ts +++ b/src/services/fileStorage/assignmentsFileStorageService.ts @@ -34,8 +34,9 @@ const getAssignment = async ( assignmentName + ".md" ); const rawFile = (await fs.readFile(filePath, "utf-8")).replace(/\r\n/g, "\n"); - return localAssignmentMarkdown.parseMarkdown(rawFile); + return localAssignmentMarkdown.parseMarkdown(rawFile, assignmentName); }; + export const assignmentsFileStorageService = { getAssignmentNames, getAssignment, @@ -72,7 +73,6 @@ export const assignmentsFileStorageService = { assignmentMarkdownSerializer.toMarkdown(assignment); console.log(`Saving assignment ${filePath}`); - await fs.writeFile(filePath, assignmentMarkdown); }, async delete({ diff --git a/src/services/fileStorage/courseItemFileStorageService.ts b/src/services/fileStorage/courseItemFileStorageService.ts index 53de5fa..29f3fa5 100644 --- a/src/services/fileStorage/courseItemFileStorageService.ts +++ b/src/services/fileStorage/courseItemFileStorageService.ts @@ -56,11 +56,12 @@ const getItem = async ( const rawFile = (await fs.readFile(filePath, "utf-8")).replace(/\r\n/g, "\n"); if (type === "Assignment") { return localAssignmentMarkdown.parseMarkdown( - rawFile + rawFile, + name ) as CourseItemReturnType; } else if (type === "Quiz") { return localQuizMarkdownUtils.parseMarkdown( - rawFile + rawFile, name ) as CourseItemReturnType; } else if (type === "Page") { return localPageMarkdownUtils.parseMarkdown( diff --git a/src/services/tests/fileStorageParsingErrors.test.ts b/src/services/tests/fileStorageParsingErrors.test.ts index 3232b33..e56b763 100644 --- a/src/services/tests/fileStorageParsingErrors.test.ts +++ b/src/services/tests/fileStorageParsingErrors.test.ts @@ -98,7 +98,7 @@ SubmissionTypes: AllowedFileUploadExtensions: - pdf --- -description +this is the test description ## Rubric - 2pts: animation has at least 5 transition states `; diff --git a/vitest.config.ts b/vitest.config.ts index 860c858..827fca5 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,8 +1,14 @@ -import { loadEnvConfig } from "@next/env"; +import nextEnv from "@next/env"; import { defineConfig } from "vitest/config"; import react from "@vitejs/plugin-react"; -loadEnvConfig(process.cwd()); +// hack from https://github.com/vercel/next.js/issues/68091 +if (nextEnv && "loadEnvConfig" in nextEnv) { + nextEnv.loadEnvConfig(process.cwd()); +} else { + // eslint-disable-next-line + require("@next/env").loadEnvConfig(process.cwd()); +} export default defineConfig({ plugins: [react()],