Skip to content

fix : added max length guards to question add-to-session validator (issue #1403) - #1408

Open
tmdeveloper007 wants to merge 3 commits into
Canopus-Labs:mainfrom
tmdeveloper007:fix/1403-question-validator-max-length
Open

fix : added max length guards to question add-to-session validator (issue #1403)#1408
tmdeveloper007 wants to merge 3 commits into
Canopus-Labs:mainfrom
tmdeveloper007:fix/1403-question-validator-max-length

Conversation

@tmdeveloper007

@tmdeveloper007 tmdeveloper007 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Summary of What Has Been Done

Added .max() guards to the questions array items in addQuestionToSessionSchema in backend/Input_validators/ValidateQuestions.js:

  • questions[].question: max 5000 characters
  • questions[].answer: max 10000 characters

Changes Made

  • Modified backend/Input_validators/ValidateQuestions.js: Added .max() Zod validators to question and answer fields
  • Added backend/tests/questionValidator.maxLength.unit.test.js: 7 unit tests covering max-length boundary cases

Impact it Made

  • Prevents users from storing arbitrarily large question/answer content
  • Reduces storage and memory overhead on the server
  • Aligns with the note field limit used in other parts of the application

Closes #1403

Note: Please assign this PR to the tmdeveloper007 account.

Adds maximum-length validation for flashcard, session, and session-question fields. Adds unit tests for boundary and rejection cases.

Ready to merge.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds maximum-length validation to flashcard, question, and session schemas. New Vitest suites verify accepted boundaries, rejected oversized values, required fields, and flashcard category defaults.

Changes

Input validation limits

Layer / File(s) Summary
Schema maximum-length rules
backend/Input_validators/ValidateFlashcard.js, backend/Input_validators/ValidateQuestions.js, backend/Input_validators/ValidateSession.js
Flashcard, question, and session fields now enforce maximum text lengths while retaining required and default behavior.
Boundary and rejection tests
backend/tests/flashcardValidator.maxLength.unit.test.js, backend/tests/questionValidator.maxLength.unit.test.js, backend/tests/sessionValidator.maxLength.unit.test.js
Vitest coverage checks valid inputs, exact limits, oversized values, required fields, and category defaulting.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • Canopus-Labs/PrepPilot issue 1401 — Covers maximum-length guards for flashcard question, answer, and category fields.
  • Canopus-Labs/PrepPilot issue 1402 — Covers maximum-length guards for session fields and matching tests.

Possibly related PRs

  • Canopus-Labs/PrepPilot#1406 — Contains the same flashcard schema and tests, while this PR also updates question and session validation.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The flashcard and session validator changes are not required by linked issue #1403, which only scopes the question add-to-session validator. Move the flashcard and session validator changes to separate issues, or update the linked issue scope and acceptance criteria to include them.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: maximum-length guards for the question add-to-session validator in issue #1403.
Linked Issues check ✅ Passed The changes satisfy issue #1403 by adding the required 5,000-character question and 10,000-character answer limits while retaining minimum-length checks.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/tests/flashcardValidator.maxLength.unit.test.js`:
- Around line 18-100: Update the validator tests to use a vi.fn() next callback
and verify middleware continuation: in
backend/tests/flashcardValidator.maxLength.unit.test.js lines 18-100,
backend/tests/questionValidator.maxLength.unit.test.js lines 18-88, and
backend/tests/sessionValidator.maxLength.unit.test.js lines 18-110, assert next
is called once for every valid-input test and is not called for every
invalid-input test, while preserving the existing response assertions.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a90b2407-2f12-405e-bafa-c7bfca79b265

📥 Commits

Reviewing files that changed from the base of the PR and between 8acb5b8 and 1e91450.

📒 Files selected for processing (6)
  • backend/Input_validators/ValidateFlashcard.js
  • backend/Input_validators/ValidateQuestions.js
  • backend/Input_validators/ValidateSession.js
  • backend/tests/flashcardValidator.maxLength.unit.test.js
  • backend/tests/questionValidator.maxLength.unit.test.js
  • backend/tests/sessionValidator.maxLength.unit.test.js

Comment on lines +18 to +100
it("accepts question and answer within max length", () => {
const req = makeReq({
question: "What is polymorphism?",
answer: "Polymorphism allows objects of different types to be treated as instances of the same type.",
category: "OOP",
});
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
// If validation passes, res.status is not called
expect(res.status).not.toHaveBeenCalled();
});

it("rejects question exceeding 5000 characters", () => {
const req = makeReq({
question: "A".repeat(5001),
answer: "Short answer",
});
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({ success: false, message: "Validation failed" })
);
});

it("rejects answer exceeding 5000 characters", () => {
const req = makeReq({
question: "Short question",
answer: "B".repeat(5001),
});
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({ success: false, message: "Validation failed" })
);
});

it("rejects category exceeding 100 characters", () => {
const req = makeReq({
question: "Q",
answer: "A",
category: "C".repeat(101),
});
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
expect(res.status).toHaveBeenCalledWith(400);
expect(res.json).toHaveBeenCalledWith(
expect.objectContaining({ success: false, message: "Validation failed" })
);
});

it("accepts question and answer at exact boundary (5000 chars)", () => {
const req = makeReq({
question: "Q".repeat(5000),
answer: "A".repeat(5000),
});
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
expect(res.status).not.toHaveBeenCalled();
});

it("rejects empty question", () => {
const req = makeReq({ question: "", answer: "A" });
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
expect(res.status).toHaveBeenCalledWith(400);
});

it("rejects empty answer", () => {
const req = makeReq({ question: "Q", answer: "" });
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
expect(res.status).toHaveBeenCalledWith(400);
});

it("defaults category to 'General' when omitted", () => {
const req = makeReq({ question: "Q", answer: "A" });
const res = makeRes();
validateCreateFlashcard(req, res, () => {});
expect(res.status).not.toHaveBeenCalled();
expect(req.body.category).toBe("General");
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Assert middleware continuation behavior.

Each test passes an anonymous next callback. The tests cannot detect a valid request that does not call next(). They also cannot detect an invalid request that calls next() after it sends the 400 response.

  • backend/tests/flashcardValidator.maxLength.unit.test.js#L18-L100: use const next = vi.fn() and assert next is called once for valid input and not called for invalid input.
  • backend/tests/questionValidator.maxLength.unit.test.js#L18-L88: use const next = vi.fn() and assert next is called once for valid input and not called for invalid input.
  • backend/tests/sessionValidator.maxLength.unit.test.js#L18-L110: use const next = vi.fn() and assert next is called once for valid input and not called for invalid input.
📍 Affects 3 files
  • backend/tests/flashcardValidator.maxLength.unit.test.js#L18-L100 (this comment)
  • backend/tests/questionValidator.maxLength.unit.test.js#L18-L88
  • backend/tests/sessionValidator.maxLength.unit.test.js#L18-L110
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/tests/flashcardValidator.maxLength.unit.test.js` around lines 18 -
100, Update the validator tests to use a vi.fn() next callback and verify
middleware continuation: in
backend/tests/flashcardValidator.maxLength.unit.test.js lines 18-100,
backend/tests/questionValidator.maxLength.unit.test.js lines 18-88, and
backend/tests/sessionValidator.maxLength.unit.test.js lines 18-110, assert next
is called once for every valid-input test and is not called for every
invalid-input test, while preserving the existing response assertions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix : add max length guards to question add-to-session validator

1 participant