Summary
The frontend has form validation on ballot creation, voter upload,
and vote submission pages, but the validation rules and error messages
do not match what the backend enforces. A voter can submit a form that
passes frontend validation but fails at the backend with an unclear
error, leaving them confused about what went wrong. Frontend validation
should mirror backend validation exactly so users get consistent,
actionable feedback.
Background
For example, the vote submission form may accept a token of any length
on the frontend, but the backend requires exactly 32 bytes (64 hex
characters). A voter enters an incorrect token, sees no frontend error,
submits, and gets a cryptic backend error. The error messages are also
inconsistent — frontend says "Token invalid" but backend says "Invalid
token format".
Scope
Frontend
- Audit all form validation in:
- Ballot creation form (
POST /api/ballots)
- Voter list upload (
POST /api/eligibility)
- Vote submission form (
POST /api/votes)
- Token input field
- Compare each form's validation rules against the corresponding
backend endpoint's validation in backend/src/middleware/validate.ts
- Update frontend validation to match backend exactly:
- Token must be 64 hex characters (32 bytes)
- Ballot title must be 3-200 characters
- Deadline must be in the future
- Vote option must be a valid option from the ballot
- Voter email must be a valid email format
- Sync error messages between frontend and backend:
- If backend returns error code
INVALID_TOKEN, frontend should
show the exact same message: "Token must be 64 hex characters"
- If backend returns
BALLOT_CLOSED, frontend should show
"Voting for this ballot has closed"
- Add a validation utilities file
frontend/src/utils/validate.ts
that exports validation functions and error messages imported
from a shared constants file
Backend
- Create
backend/src/constants/validationMessages.ts that exports
all validation error messages as constants
- Export validation functions that the frontend can reuse
Tests
- Test each form field with:
- Valid input (passes)
- Invalid input (fails with correct error message)
- Boundary cases (min/max length, edge values)
- Verify frontend error message matches backend error message exactly
Relevant Files
frontend/src/components/BallotForm.tsx
frontend/src/components/VoterUploadForm.tsx
frontend/src/pages/VoteForm.tsx
frontend/src/utils/validate.ts (new)
backend/src/middleware/validate.ts
backend/src/constants/validationMessages.ts (new)
frontend/src/tests/forms.test.ts
Acceptance Criteria
Out of Scope
- Real-time validation as user types — validation on submit only
- Backend response error message changes — frontend adapts to current backend
Note for Contributors
This is about consistency and user experience. When a frontend shows
"Invalid token format" and the user submits anyway and gets a different
error from the backend, trust is broken. Make them match exactly. The
frontend should catch as many errors as possible so the user knows
immediately what to fix.
Summary
The frontend has form validation on ballot creation, voter upload,
and vote submission pages, but the validation rules and error messages
do not match what the backend enforces. A voter can submit a form that
passes frontend validation but fails at the backend with an unclear
error, leaving them confused about what went wrong. Frontend validation
should mirror backend validation exactly so users get consistent,
actionable feedback.
Background
For example, the vote submission form may accept a token of any length
on the frontend, but the backend requires exactly 32 bytes (64 hex
characters). A voter enters an incorrect token, sees no frontend error,
submits, and gets a cryptic backend error. The error messages are also
inconsistent — frontend says "Token invalid" but backend says "Invalid
token format".
Scope
Frontend
POST /api/ballots)POST /api/eligibility)POST /api/votes)backend endpoint's validation in
backend/src/middleware/validate.tsINVALID_TOKEN, frontend shouldshow the exact same message: "Token must be 64 hex characters"
BALLOT_CLOSED, frontend should show"Voting for this ballot has closed"
frontend/src/utils/validate.tsthat exports validation functions and error messages imported
from a shared constants file
Backend
backend/src/constants/validationMessages.tsthat exportsall validation error messages as constants
Tests
Relevant Files
frontend/src/components/BallotForm.tsxfrontend/src/components/VoterUploadForm.tsxfrontend/src/pages/VoteForm.tsxfrontend/src/utils/validate.ts(new)backend/src/middleware/validate.tsbackend/src/constants/validationMessages.ts(new)frontend/src/tests/forms.test.tsAcceptance Criteria
frontend and backend
Out of Scope
Note for Contributors
This is about consistency and user experience. When a frontend shows
"Invalid token format" and the user submits anyway and gets a different
error from the backend, trust is broken. Make them match exactly. The
frontend should catch as many errors as possible so the user knows
immediately what to fix.