Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0420f9a
Add Dynamic and Static review mappings; Add necessary fields for Dyna…
darrinj22 Mar 29, 2026
a42df31
Move review strategy mapping rendering to AssignmentEditPage.tsx
darrinj22 Mar 30, 2026
fcdcaee
restore changes from AssignmentEditor.tsx to main
darrinj22 Mar 30, 2026
ab6a63d
Merge pull request #15 from MATTMINWIN/djhanse2/review_strategy_mappi…
darrinj22 Mar 30, 2026
79a5fa7
Implemented skeleton of static strategy
Mar 30, 2026
98f4c83
Revert Changes
Mar 30, 2026
3ae8223
Revert "Merge pull request #15 from MATTMINWIN/djhanse2/review_strate…
darrinj22 Mar 31, 2026
6ce97f0
Merge pull request #16 from MATTMINWIN/revert-pr-ab6a63d
darrinj22 Mar 31, 2026
9b01db4
Moved Review Strategy Mapping changes back into AssignmentEditor.tsx
darrinj22 Mar 31, 2026
354205c
Merge pull request #17 from MATTMINWIN/djhanse2/AssignmentEditPage_Re…
darrinj22 Mar 31, 2026
ebf0c2c
Allow assignment updates to persist to backend by normalizing assignm…
darrinj22 Mar 31, 2026
333308d
Merge pull request #18 from MATTMINWIN/djhanse2/persist_changes
darrinj22 Mar 31, 2026
4ef9dcf
Pushing new Static Page Changes
Mar 31, 2026
c0ad53d
Merge pull request #19 from MATTMINWIN/mmnguye5/merge_static_changes
MATTMINWIN Mar 31, 2026
4ba1249
added calibration specific tasks to static review mapping
darrinj22 Mar 31, 2026
53cfd92
Merge pull request #20 from MATTMINWIN/djhanse2/static-calibration-re…
darrinj22 Mar 31, 2026
978bf81
unit tests
darrinj22 Mar 31, 2026
d34ba94
Merge pull request #21 from MATTMINWIN/djhanse2/review-mapping-tests
darrinj22 Mar 31, 2026
885800e
Updating UI for static review assignment
Apr 3, 2026
d49f05f
Merge pull request #22 from MATTMINWIN/zobrook2/ui_updates
z0brooks Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 117 additions & 9 deletions src/pages/Assignments/AssignmentEditor.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { render, screen, within } from "@testing-library/react";
import { fireEvent, render, screen, within } from "@testing-library/react";
import "@testing-library/jest-dom";
import { vi, beforeEach, describe, expect, it } from "vitest";
import AssignmentEditor from "./AssignmentEditor";
Expand Down Expand Up @@ -95,8 +95,121 @@ describe("AssignmentEditor rubrics tab", () => {

});

describe("AssignmentEditor review strategy calibration behavior", () => {
beforeEach(() => {
loaderData = { ...baseAssignment, calibration_for_training: false, is_calibrated: false };
sendRequestMock.mockClear();
dispatchMock.mockClear();
});

it("shows uncalibrated label and calibrated field in Static strategy when calibration is enabled", () => {
render(<AssignmentEditor mode="update" />);

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));
expect(
screen.getByText("Number of reviews each reviewer is required to do")
).toBeInTheDocument();
expect(screen.queryByText("Number of calibrated reviews")).not.toBeInTheDocument();

fireEvent.click(screen.getByRole("tab", { name: /General/i }));
fireEvent.click(screen.getByLabelText("Calibration for training?"));

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));
expect(
screen.getByText("Number of uncalibrated reviews each reviewer is required to do")
).toBeInTheDocument();
expect(screen.getByText("Number of calibrated reviews")).toBeInTheDocument();
});

it("keeps calibrated field hidden in Static strategy when calibration is disabled", () => {
render(<AssignmentEditor mode="update" />);

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));

expect(
screen.getByText("Number of reviews each reviewer is required to do")
).toBeInTheDocument();
expect(screen.queryByText("Number of uncalibrated reviews each reviewer is required to do")).not.toBeInTheDocument();
expect(screen.queryByText("Number of calibrated reviews")).not.toBeInTheDocument();
});
});

describe("AssignmentEditor review mapping strategy behavior", () => {
beforeEach(() => {
loaderData = {
...baseAssignment,
calibration_for_training: false,
is_calibrated: false,
has_topics: false,
};
sendRequestMock.mockClear();
dispatchMock.mockClear();
});

it("maps legacy Auto-Selected strategy to Dynamic UI fields", () => {
loaderData = { ...loaderData, review_strategy: "Auto-Selected" };
render(<AssignmentEditor mode="update" />);

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));

expect(screen.getByText("Number of reviews each reviewer is required to do")).toBeInTheDocument();
expect(screen.getByText("Max. number of reviews each reviewer is allowed to do")).toBeInTheDocument();
expect(screen.queryByText("Round Robin Assignment")).not.toBeInTheDocument();
});

it("maps legacy Instructor-Selected strategy to Static UI fields", () => {
loaderData = { ...loaderData, review_strategy: "Instructor-Selected" };
render(<AssignmentEditor mode="update" />);

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));

expect(screen.getByText("Round Robin Assignment")).toBeInTheDocument();
expect(screen.getByText("Random Assignment")).toBeInTheDocument();
expect(screen.getByText("Upload Spreadsheet Assignment")).toBeInTheDocument();
});

it("shows upload input and hides required-review fields when static upload strategy is selected", () => {
render(<AssignmentEditor mode="update" />);

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));
fireEvent.click(screen.getByLabelText("Upload Spreadsheet Assignment"));

const uploadInput = document.querySelector('input[name="spreadsheetFile"]');
expect(uploadInput).toBeInTheDocument();
expect(screen.queryByText("Number of reviews each reviewer is required to do")).not.toBeInTheDocument();
expect(
screen.queryByText("Assign reviewers to review projects that have not yet been submitted")
).not.toBeInTheDocument();
});

it("shows review topic threshold only for Dynamic strategy when assignment has topics", () => {
loaderData = { ...loaderData, review_strategy: "Dynamic", has_topics: true };
render(<AssignmentEditor mode="update" />);

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));

expect(screen.getByText("Review topic threshold (k):")).toBeInTheDocument();
});

it("shows team-based review controls in Dynamic strategy only when has teams is enabled", () => {
loaderData = { ...loaderData, review_strategy: "Dynamic", has_teams: false };
render(<AssignmentEditor mode="update" />);

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));
expect(screen.queryByText("Is reviewing role based?")).not.toBeInTheDocument();
expect(screen.queryByText("Are reviews to be done by teams?")).not.toBeInTheDocument();

fireEvent.click(screen.getByRole("tab", { name: /General/i }));
fireEvent.click(screen.getByLabelText("Has teams?"));

fireEvent.click(screen.getByRole("tab", { name: /Review strategy/i }));
expect(screen.getByText("Is reviewing role based?")).toBeInTheDocument();
expect(screen.getByText("Are reviews to be done by teams?")).toBeInTheDocument();
});
});

describe("transformAssignmentRequest", () => {
it("builds assignment_questionnaires_attributes for selected rounds", () => {
it("does not include unsupported questionnaire nested attributes", () => {
const values: IAssignmentFormValues = {
id: 1,
name: "Test Assignment",
Expand Down Expand Up @@ -125,10 +238,7 @@ describe("transformAssignmentRequest", () => {

const payload = JSON.parse(transformAssignmentRequest(values));

expect(payload.assignment.assignment_questionnaires_attributes).toEqual([
{ id: 10, questionnaire_id: 101, used_in_round: 1 },
{ questionnaire_id: 102, used_in_round: 2 },
]);
expect(payload.assignment.assignment_questionnaires_attributes).toBeUndefined();
expect(payload.assignment.vary_by_round).toBe(true);
expect(payload.assignment.rounds_of_reviews).toBe(2);
});
Expand Down Expand Up @@ -161,9 +271,7 @@ describe("transformAssignmentRequest", () => {

const payload = JSON.parse(transformAssignmentRequest(values));

expect(payload.assignment.assignment_questionnaires_attributes).toEqual([
{ id: 99, questionnaire_id: 201, used_in_round: 1 },
]);
expect(payload.assignment.assignment_questionnaires_attributes).toBeUndefined();
});

it("sets vary_by_round to false when checkbox is unchecked", () => {
Expand Down
Loading