mirror of
https://github.com/alexmickelson/canvasManagement.git
synced 2026-03-26 07:38:33 -06:00
moving v2 to top level
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils";
|
||||
|
||||
describe("Matching Answer Error Messages", () => {
|
||||
it("can parse matching question", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description:
|
||||
---
|
||||
|
||||
question without answer
|
||||
|
||||
`;
|
||||
|
||||
expect(() => quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz)).toThrowError(
|
||||
/question type/
|
||||
);
|
||||
});
|
||||
});
|
||||
134
src/models/local/tests/quizMarkdown/matchingAnswers.test.ts
Normal file
134
src/models/local/tests/quizMarkdown/matchingAnswers.test.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { QuestionType } from "../../quiz/localQuizQuestion";
|
||||
import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils";
|
||||
import { quizQuestionMarkdownUtils } from "@/models/local/quiz/utils/quizQuestionMarkdownUtils";
|
||||
|
||||
describe("MatchingTests", () => {
|
||||
it("can parse matching question", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description:
|
||||
---
|
||||
Match the following terms & definitions
|
||||
|
||||
^ statement - a single command to be executed
|
||||
^ identifier - name of a variable
|
||||
^ keyword - reserved word that has special meaning in a program (e.g. class, void, static, etc.)
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.questionType).toBe(QuestionType.MATCHING);
|
||||
expect(firstQuestion.text).not.toContain("statement");
|
||||
expect(firstQuestion.answers[0].matchedText).toBe(
|
||||
"a single command to be executed"
|
||||
);
|
||||
});
|
||||
|
||||
it("can create markdown for matching question", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description:
|
||||
---
|
||||
Match the following terms & definitions
|
||||
|
||||
^ statement - a single command to be executed
|
||||
^ identifier - name of a variable
|
||||
^ keyword - reserved word that has special meaning in a program (e.g. class, void, static, etc.)
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const questionMarkdown = quizQuestionMarkdownUtils.toMarkdown(
|
||||
quiz.questions[0]
|
||||
);
|
||||
const expectedMarkdown = `Points: 1
|
||||
Match the following terms & definitions
|
||||
|
||||
^ statement - a single command to be executed
|
||||
^ identifier - name of a variable
|
||||
^ keyword - reserved word that has special meaning in a program (e.g. class, void, static, etc.)`;
|
||||
|
||||
expect(questionMarkdown).toContain(expectedMarkdown);
|
||||
});
|
||||
|
||||
it("whitespace is optional", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description:
|
||||
---
|
||||
Match the following terms & definitions
|
||||
|
||||
^statement - a single command to be executed
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
expect(quiz.questions[0].answers[0].text).toBe("statement");
|
||||
});
|
||||
|
||||
it("can have distractors", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description:
|
||||
---
|
||||
Match the following terms & definitions
|
||||
|
||||
^ statement - a single command to be executed
|
||||
^ - this is the distractor
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
expect(quiz.questions[0].matchDistractors).toEqual([
|
||||
"this is the distractor",
|
||||
]);
|
||||
});
|
||||
|
||||
it("can have distractors and be persisted", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description:
|
||||
---
|
||||
Match the following terms & definitions
|
||||
|
||||
^ statement - a single command to be executed
|
||||
^ - this is the distractor
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
|
||||
expect(quizMarkdown).toContain(
|
||||
"^ statement - a single command to be executed\n^ - this is the distractor"
|
||||
);
|
||||
});
|
||||
});
|
||||
181
src/models/local/tests/quizMarkdown/multipleAnswers.test.ts
Normal file
181
src/models/local/tests/quizMarkdown/multipleAnswers.test.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { LocalQuiz } from "../../quiz/localQuiz";
|
||||
import { QuestionType } from "../../quiz/localQuizQuestion";
|
||||
import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils";
|
||||
import { quizQuestionMarkdownUtils } from "@/models/local/quiz/utils/quizQuestionMarkdownUtils";
|
||||
|
||||
describe("MultipleAnswersTests", () => {
|
||||
it("quiz markdown includes multiple answer question", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "desc",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: false,
|
||||
showCorrectAnswers: false,
|
||||
localAssignmentGroupName: "someId",
|
||||
allowedAttempts: -1,
|
||||
questions: [
|
||||
{
|
||||
text: "oneline question",
|
||||
points: 1,
|
||||
questionType: QuestionType.MULTIPLE_ANSWERS,
|
||||
answers: [
|
||||
{ correct: true, text: "true" },
|
||||
{ correct: true, text: "false" },
|
||||
{ correct: false, text: "neither" },
|
||||
],
|
||||
matchDistractors: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const markdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const expectedQuestionString = `Points: 1
|
||||
oneline question
|
||||
[*] true
|
||||
[*] false
|
||||
[ ] neither`;
|
||||
expect(markdown).toContain(expectedQuestionString);
|
||||
});
|
||||
|
||||
it("can parse question with multiple answers", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
[*] click
|
||||
[*] focus
|
||||
[*] mousedown
|
||||
[ ] submit
|
||||
[ ] change
|
||||
[ ] mouseout
|
||||
[ ] keydown
|
||||
---
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.points).toBe(1);
|
||||
expect(firstQuestion.questionType).toBe(QuestionType.MULTIPLE_ANSWERS);
|
||||
expect(firstQuestion.text).toContain(
|
||||
"Which events are triggered when the user clicks on an input field?"
|
||||
);
|
||||
expect(firstQuestion.answers[0].text).toBe("click");
|
||||
expect(firstQuestion.answers[0].correct).toBe(true);
|
||||
expect(firstQuestion.answers[3].correct).toBe(false);
|
||||
expect(firstQuestion.answers[3].text).toBe("submit");
|
||||
});
|
||||
|
||||
it("can parse question with multiple answers without a space in false answers", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
[*] click
|
||||
[] submit
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.answers.length).toBe(2);
|
||||
expect(firstQuestion.answers[0].correct).toBe(true);
|
||||
expect(firstQuestion.answers[1].correct).toBe(false);
|
||||
});
|
||||
|
||||
it("can parse question with multiple answers without a space in false answers other example", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Points: 1
|
||||
Which tool(s) will let you: create a database migration or reverse-engineer an existing database
|
||||
[] swagger
|
||||
[] a .http file
|
||||
[*] dotnet ef command line interface
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.answers.length).toBe(3);
|
||||
expect(firstQuestion.answers[0].correct).toBe(false);
|
||||
expect(firstQuestion.answers[1].correct).toBe(false);
|
||||
expect(firstQuestion.answers[2].correct).toBe(true);
|
||||
});
|
||||
|
||||
it("can use braces in answer for multiple answer", () => {
|
||||
const rawMarkdownQuestion = `
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
[*] \`int[] theThing()\`
|
||||
[ ] keydown
|
||||
`;
|
||||
|
||||
const question = quizQuestionMarkdownUtils.parseMarkdown(
|
||||
rawMarkdownQuestion,
|
||||
0
|
||||
);
|
||||
|
||||
expect(question.answers[0].text).toBe("`int[] theThing()`");
|
||||
expect(question.answers.length).toBe(2);
|
||||
});
|
||||
|
||||
it("can use braces in answer for multiple answer with multiline", () => {
|
||||
const rawMarkdownQuestion = `
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
[*]
|
||||
\`\`\`
|
||||
int[] myNumbers = new int[] { };
|
||||
DoSomething(ref myNumbers);
|
||||
static void DoSomething(ref int[] numbers)
|
||||
{
|
||||
// do something
|
||||
}
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
const question = quizQuestionMarkdownUtils.parseMarkdown(
|
||||
rawMarkdownQuestion,
|
||||
0
|
||||
);
|
||||
|
||||
expect(question.answers[0].text).toBe(`\`\`\`
|
||||
int[] myNumbers = new int[] { };
|
||||
DoSomething(ref myNumbers);
|
||||
static void DoSomething(ref int[] numbers)
|
||||
{
|
||||
// do something
|
||||
}
|
||||
\`\`\``);
|
||||
expect(question.answers.length).toBe(1);
|
||||
});
|
||||
});
|
||||
75
src/models/local/tests/quizMarkdown/multipleChoice.test.ts
Normal file
75
src/models/local/tests/quizMarkdown/multipleChoice.test.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { LocalQuiz } from "../../quiz/localQuiz";
|
||||
import { LocalQuizQuestion, QuestionType } from "../../quiz/localQuizQuestion";
|
||||
import { LocalQuizQuestionAnswer } from "../../quiz/localQuizQuestionAnswer";
|
||||
import { quizMarkdownUtils } from "@/models/local/quiz/utils/quizMarkdownUtils";
|
||||
import { quizQuestionMarkdownUtils } from "@/models/local/quiz/utils/quizQuestionMarkdownUtils";
|
||||
|
||||
describe("MultipleChoiceTests", () => {
|
||||
it("quiz markdown includes multiple choice question", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "desc",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: false,
|
||||
showCorrectAnswers: false,
|
||||
localAssignmentGroupName: "someId",
|
||||
allowedAttempts: -1,
|
||||
questions: [
|
||||
{
|
||||
points: 2,
|
||||
text: `
|
||||
\`some type\` of question
|
||||
|
||||
with many
|
||||
|
||||
\`\`\`
|
||||
lines
|
||||
\`\`\`
|
||||
`,
|
||||
questionType: QuestionType.MULTIPLE_CHOICE,
|
||||
answers: [
|
||||
{ correct: true, text: "true" },
|
||||
{ correct: false, text: "false\n\nendline" },
|
||||
],
|
||||
matchDistractors: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const markdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const expectedQuestionString = `
|
||||
Points: 2
|
||||
|
||||
\`some type\` of question
|
||||
|
||||
with many
|
||||
|
||||
\`\`\`
|
||||
lines
|
||||
\`\`\`
|
||||
|
||||
*a) true
|
||||
b) false
|
||||
|
||||
endline`;
|
||||
expect(markdown).toContain(expectedQuestionString);
|
||||
});
|
||||
|
||||
it("letter optional for multiple choice", () => {
|
||||
const questionMarkdown = `
|
||||
Points: 2
|
||||
\`some type\` of question
|
||||
*) true
|
||||
) false
|
||||
`;
|
||||
|
||||
const question = quizQuestionMarkdownUtils.parseMarkdown(
|
||||
questionMarkdown,
|
||||
0
|
||||
);
|
||||
expect(question.answers.length).toBe(2);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,198 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { LocalQuiz } from "../../quiz/localQuiz";
|
||||
import { quizMarkdownUtils } from "../../quiz/utils/quizMarkdownUtils";
|
||||
import { QuestionType } from "@/models/local/quiz/localQuizQuestion";
|
||||
|
||||
// Test suite for deterministic checks on LocalQuiz
|
||||
describe("QuizDeterministicChecks", () => {
|
||||
it("SerializationIsDeterministic_EmptyQuiz", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "quiz description",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: true,
|
||||
localAssignmentGroupName: "Assignments",
|
||||
questions: [],
|
||||
allowedAttempts: -1,
|
||||
showCorrectAnswers: true,
|
||||
};
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown);
|
||||
|
||||
expect(parsedQuiz).toEqual(quiz);
|
||||
});
|
||||
|
||||
it("SerializationIsDeterministic_ShowCorrectAnswers", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "quiz description",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
showCorrectAnswers: false,
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: true,
|
||||
localAssignmentGroupName: "Assignments",
|
||||
questions: [],
|
||||
allowedAttempts: -1,
|
||||
};
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown);
|
||||
|
||||
expect(parsedQuiz).toEqual(quiz);
|
||||
});
|
||||
|
||||
it("SerializationIsDeterministic_ShortAnswer", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "quiz description",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: true,
|
||||
localAssignmentGroupName: "Assignments",
|
||||
questions: [
|
||||
{
|
||||
text: "test short answer",
|
||||
questionType: QuestionType.SHORT_ANSWER,
|
||||
points: 1,
|
||||
answers: [],
|
||||
matchDistractors: [],
|
||||
},
|
||||
],
|
||||
allowedAttempts: -1,
|
||||
showCorrectAnswers: true,
|
||||
};
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown);
|
||||
|
||||
expect(parsedQuiz).toEqual(quiz);
|
||||
});
|
||||
|
||||
it("SerializationIsDeterministic_Essay", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "quiz description",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: true,
|
||||
localAssignmentGroupName: "Assignments",
|
||||
questions: [
|
||||
{
|
||||
text: "test essay",
|
||||
questionType: QuestionType.ESSAY,
|
||||
points: 1,
|
||||
matchDistractors: [],
|
||||
answers: [],
|
||||
},
|
||||
],
|
||||
allowedAttempts: -1,
|
||||
showCorrectAnswers: true,
|
||||
};
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown);
|
||||
|
||||
expect(parsedQuiz).toEqual(quiz);
|
||||
});
|
||||
|
||||
it("SerializationIsDeterministic_MultipleAnswer", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "quiz description",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: true,
|
||||
localAssignmentGroupName: "Assignments",
|
||||
questions: [
|
||||
{
|
||||
text: "test multiple answer",
|
||||
questionType: QuestionType.MULTIPLE_ANSWERS,
|
||||
points: 1,
|
||||
matchDistractors: [],
|
||||
answers: [
|
||||
{ text: "yes", correct: true },
|
||||
{ text: "no", correct: true },
|
||||
],
|
||||
},
|
||||
],
|
||||
allowedAttempts: -1,
|
||||
showCorrectAnswers: true,
|
||||
};
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown);
|
||||
|
||||
expect(parsedQuiz).toEqual(quiz);
|
||||
});
|
||||
|
||||
it("SerializationIsDeterministic_MultipleChoice", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "quiz description",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: true,
|
||||
password: undefined,
|
||||
localAssignmentGroupName: "Assignments",
|
||||
questions: [
|
||||
{
|
||||
text: "test multiple choice",
|
||||
questionType: QuestionType.MULTIPLE_CHOICE,
|
||||
points: 1,
|
||||
matchDistractors: [],
|
||||
answers: [
|
||||
{ text: "yes", correct: true },
|
||||
{ text: "no", correct: false },
|
||||
],
|
||||
},
|
||||
],
|
||||
allowedAttempts: -1,
|
||||
showCorrectAnswers: true,
|
||||
};
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown);
|
||||
|
||||
expect(parsedQuiz).toEqual(quiz);
|
||||
});
|
||||
|
||||
it("SerializationIsDeterministic_Matching", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: "quiz description",
|
||||
lockAt: "08/21/2023 23:59:00",
|
||||
dueAt: "08/21/2023 23:59:00",
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: true,
|
||||
password: undefined,
|
||||
localAssignmentGroupName: "Assignments",
|
||||
questions: [
|
||||
{
|
||||
text: "test matching",
|
||||
questionType: QuestionType.MATCHING,
|
||||
points: 1,
|
||||
matchDistractors: [],
|
||||
answers: [
|
||||
{ text: "yes", correct: true, matchedText: "testing yes" },
|
||||
{ text: "no", correct: true, matchedText: "testing no" },
|
||||
],
|
||||
},
|
||||
],
|
||||
allowedAttempts: -1,
|
||||
showCorrectAnswers: true,
|
||||
};
|
||||
|
||||
const quizMarkdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
const parsedQuiz = quizMarkdownUtils.parseMarkdown(quizMarkdown);
|
||||
|
||||
expect(parsedQuiz).toEqual(quiz);
|
||||
});
|
||||
});
|
||||
256
src/models/local/tests/quizMarkdown/quizMarkdown.test.ts
Normal file
256
src/models/local/tests/quizMarkdown/quizMarkdown.test.ts
Normal file
@@ -0,0 +1,256 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { LocalQuiz } from "../../quiz/localQuiz";
|
||||
import { quizMarkdownUtils } from "../../quiz/utils/quizMarkdownUtils";
|
||||
import { QuestionType } from "@/models/local/quiz/localQuizQuestion";
|
||||
import { quizQuestionMarkdownUtils } from "@/models/local/quiz/utils/quizQuestionMarkdownUtils";
|
||||
|
||||
// Test suite for QuizMarkdown
|
||||
describe("QuizMarkdownTests", () => {
|
||||
it("can serialize quiz to markdown", () => {
|
||||
const quiz: LocalQuiz = {
|
||||
name: "Test Quiz",
|
||||
description: `
|
||||
# quiz description
|
||||
|
||||
this is my description in markdown
|
||||
|
||||
\`here is code\`
|
||||
`,
|
||||
lockAt: new Date(8640000000000000).toISOString(), // DateTime.MaxValue equivalent in TypeScript
|
||||
dueAt: new Date(8640000000000000).toISOString(),
|
||||
shuffleAnswers: true,
|
||||
oneQuestionAtATime: false,
|
||||
localAssignmentGroupName: "someId",
|
||||
allowedAttempts: -1,
|
||||
showCorrectAnswers: false,
|
||||
questions: [],
|
||||
};
|
||||
|
||||
const markdown = quizMarkdownUtils.toMarkdown(quiz);
|
||||
|
||||
expect(markdown).toContain("Name: Test Quiz");
|
||||
expect(markdown).toContain(quiz.description);
|
||||
expect(markdown).toContain("ShuffleAnswers: true");
|
||||
expect(markdown).toContain("OneQuestionAtATime: false");
|
||||
expect(markdown).toContain("AssignmentGroup: someId");
|
||||
expect(markdown).toContain("AllowedAttempts: -1");
|
||||
});
|
||||
|
||||
it("can parse markdown quiz with no questions", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
|
||||
const expectedDescription = `
|
||||
this is the
|
||||
multi line
|
||||
description`;
|
||||
|
||||
expect(quiz.name).toBe("Test Quiz");
|
||||
expect(quiz.shuffleAnswers).toBe(true);
|
||||
expect(quiz.oneQuestionAtATime).toBe(false);
|
||||
expect(quiz.allowedAttempts).toBe(-1);
|
||||
expect(quiz.description.trim()).toBe(expectedDescription.trim());
|
||||
});
|
||||
|
||||
it("can parse markdown quiz with password", () => {
|
||||
const password = "this-is-the-password";
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
Password: ${password}
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
|
||||
expect(quiz.password).toBe(password);
|
||||
});
|
||||
|
||||
it("can parse markdown quiz and configure to show correct answers", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
ShowCorrectAnswers: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
|
||||
expect(quiz.showCorrectAnswers).toBe(false);
|
||||
});
|
||||
|
||||
it("can parse quiz with questions", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Points: 2
|
||||
\`some type\` of question
|
||||
|
||||
with many
|
||||
|
||||
\`\`\`
|
||||
lines
|
||||
\`\`\`
|
||||
|
||||
*a) true
|
||||
b) false
|
||||
|
||||
endline`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.questionType).toBe(QuestionType.MULTIPLE_CHOICE);
|
||||
expect(firstQuestion.points).toBe(2);
|
||||
expect(firstQuestion.text).toContain("```");
|
||||
expect(firstQuestion.text).toContain("`some type` of question");
|
||||
expect(firstQuestion.answers[0].text).toBe("true");
|
||||
expect(firstQuestion.answers[0].correct).toBe(true);
|
||||
expect(firstQuestion.answers[1].correct).toBe(false);
|
||||
expect(firstQuestion.answers[1].text).toContain("endline");
|
||||
});
|
||||
|
||||
it("can parse multiple questions", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
[*] click
|
||||
---
|
||||
Points: 2
|
||||
\`some type\` of question
|
||||
*a) true
|
||||
b) false
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
expect(firstQuestion.points).toBe(1);
|
||||
expect(firstQuestion.questionType).toBe(QuestionType.MULTIPLE_ANSWERS);
|
||||
|
||||
const secondQuestion = quiz.questions[1];
|
||||
expect(secondQuestion.points).toBe(2);
|
||||
expect(secondQuestion.questionType).toBe(QuestionType.MULTIPLE_CHOICE);
|
||||
});
|
||||
|
||||
it("short answer to markdown is correct", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
short answer
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
const questionMarkdown =
|
||||
quizQuestionMarkdownUtils.toMarkdown(firstQuestion);
|
||||
const expectedMarkdown = `Points: 1
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
short_answer`;
|
||||
expect(questionMarkdown).toContain(expectedMarkdown);
|
||||
});
|
||||
|
||||
it("negative points is allowed", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Points: -4
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
short answer
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
expect(firstQuestion.points).toBe(-4);
|
||||
});
|
||||
|
||||
it("floating point points is allowed", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Points: 4.56
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
short answer
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
expect(firstQuestion.points).toBe(4.56);
|
||||
});
|
||||
});
|
||||
137
src/models/local/tests/quizMarkdown/testAnswer.test.ts
Normal file
137
src/models/local/tests/quizMarkdown/testAnswer.test.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { QuestionType } from "../../quiz/localQuizQuestion";
|
||||
import { quizMarkdownUtils } from "../../quiz/utils/quizMarkdownUtils";
|
||||
import { quizQuestionMarkdownUtils } from "../../quiz/utils/quizQuestionMarkdownUtils";
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
describe("TextAnswerTests", () => {
|
||||
it("can parse essay", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
essay
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.points).toBe(1);
|
||||
expect(firstQuestion.questionType).toBe(QuestionType.ESSAY);
|
||||
expect(firstQuestion.text).not.toContain("essay");
|
||||
});
|
||||
|
||||
it("can parse short answer", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
short answer
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
expect(firstQuestion.points).toBe(1);
|
||||
expect(firstQuestion.questionType).toBe(QuestionType.SHORT_ANSWER);
|
||||
expect(firstQuestion.text).not.toContain("short answer");
|
||||
});
|
||||
|
||||
it("short answer to markdown is correct", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
short answer
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
const questionMarkdown =
|
||||
quizQuestionMarkdownUtils.toMarkdown(firstQuestion);
|
||||
const expectedMarkdown = `Points: 1
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
short_answer`;
|
||||
expect(questionMarkdown).toContain(expectedMarkdown);
|
||||
});
|
||||
|
||||
it("essay question to markdown is correct", () => {
|
||||
const rawMarkdownQuiz = `
|
||||
Name: Test Quiz
|
||||
ShuffleAnswers: true
|
||||
OneQuestionAtATime: false
|
||||
DueAt: 08/21/2023 23:59:00
|
||||
LockAt: 08/21/2023 23:59:00
|
||||
AssignmentGroup: Assignments
|
||||
AllowedAttempts: -1
|
||||
Description: this is the
|
||||
multi line
|
||||
description
|
||||
---
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
essay
|
||||
`;
|
||||
|
||||
const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
const firstQuestion = quiz.questions[0];
|
||||
|
||||
const questionMarkdown =
|
||||
quizQuestionMarkdownUtils.toMarkdown(firstQuestion);
|
||||
const expectedMarkdown = `Points: 1
|
||||
Which events are triggered when the user clicks on an input field?
|
||||
essay`;
|
||||
expect(questionMarkdown).toContain(expectedMarkdown);
|
||||
});
|
||||
|
||||
// it("Can parse short answer with auto graded answers", () => {
|
||||
// const rawMarkdownQuiz = `
|
||||
// Name: Test Quiz
|
||||
// ShuffleAnswers: true
|
||||
// OneQuestionAtATime: false
|
||||
// DueAt: 08/21/2023 23:59:00
|
||||
// LockAt: 08/21/2023 23:59:00
|
||||
// AssignmentGroup: Assignments
|
||||
// AllowedAttempts: -1
|
||||
// Description: this is the
|
||||
// multi line
|
||||
// description
|
||||
// ---
|
||||
// Which events are triggered when the user clicks on an input field?
|
||||
// *a) test
|
||||
// short_answer=
|
||||
// `;
|
||||
|
||||
// const quiz = quizMarkdownUtils.parseMarkdown(rawMarkdownQuiz);
|
||||
// const firstQuestion = quiz.questions[0];
|
||||
|
||||
|
||||
// expect(firstQuestion.questionType).toBe(QuestionType.SHORT_ANSWER_WITH_ANSWERS)
|
||||
// });
|
||||
});
|
||||
Reference in New Issue
Block a user