Skip to content
Open
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

# production
/build
/dist

# misc
.DS_Store
Expand Down
89 changes: 88 additions & 1 deletion src/pages/Assignments/AssignmentEditor.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { render, screen, within } from "@testing-library/react";
import "@testing-library/jest-dom";
import { vi, beforeEach, describe, expect, it } from "vitest";
import AssignmentEditor from "./AssignmentEditor";
import { transformAssignmentRequest, IAssignmentFormValues } from "./AssignmentUtil";
import { transformAssignmentRequest, transformAssignmentResponse, IAssignmentFormValues } from "./AssignmentUtil";

// Mock useAPI to avoid real network calls
const sendRequestMock = vi.fn();
Expand Down Expand Up @@ -93,6 +93,40 @@ describe("AssignmentEditor rubrics tab", () => {
expect(allOptions).toContain("Unlinked Rubric");
});

it("uses distinct row keys for special rubric field names and control ids", () => {
render(<AssignmentEditor mode="update" />);

const getRow = (label: string) => {
const row = screen.getByText(label).closest("tr");
expect(row).not.toBeNull();
return row as HTMLElement;
};

const expectRubricFields = (
row: HTMLElement,
questionnaireName: string,
rowKey: number
) => {
const questionnaire = within(row).getByRole("combobox") as HTMLSelectElement;
const numericInputs = within(row).getAllByRole("spinbutton") as HTMLInputElement[];

expect(questionnaire.name).toBe(questionnaireName);
expect(questionnaire.id).toBe(`assignment-questionnaire_${rowKey}`);
expect(numericInputs.map((input) => input.name)).toEqual([
`weights[${rowKey}]`,
`notification_limits[${rowKey}]`,
]);
expect(numericInputs.map((input) => input.id)).toEqual([
`assignment-weight_${rowKey}`,
`assignment-notification_limit_${rowKey}`,
]);
};

expectRubricFields(getRow("Review round 2:"), "questionnaire_round_2", 2);
expectRubricFields(getRow("Author feedback:"), "author_feedback_questionnaire", 100);
expectRubricFields(getRow("Teammate review:"), "teammate_review_questionnaire", 101);
});

});

describe("transformAssignmentRequest", () => {
Expand Down Expand Up @@ -194,4 +228,57 @@ describe("transformAssignmentRequest", () => {

expect(payload.assignment.vary_by_round).toBe(false);
});

it("maps topic rubric variation to vary_by_topic", () => {
const values: IAssignmentFormValues = {
id: 1,
name: "Test Assignment",
directory_path: "assignment_1",
spec_location: "http://example.com",
private: false,
show_template_review: false,
require_quiz: false,
has_badge: false,
staggered_deadline: false,
is_calibrated: false,
review_rubric_varies_by_topic: true,
weights: [],
notification_limits: [],
use_date_updater: [],
submission_allowed: [],
review_allowed: [],
teammate_allowed: [],
metareview_allowed: [],
reminder: [],
};

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

expect(payload.assignment.vary_by_topic).toBe(true);
});
});

describe("transformAssignmentResponse", () => {
it("prefills topic rubric variation from vary_by_topic", () => {
const assignment = {
id: 1,
name: "Test Assignment",
directory_path: "assignment_1",
spec_location: "http://example.com",
private: false,
show_template_review: false,
require_quiz: false,
has_badge: false,
staggered_deadline: false,
is_calibrated: false,
vary_by_topic: true,
num_review_rounds: 1,
due_dates: [],
assignment_questionnaires: [],
};

const values = transformAssignmentResponse(JSON.stringify(assignment));

expect(values.review_rubric_varies_by_topic).toBe(true);
});
});
Loading