Skip to content

test(surveys): 1467 - cover admin crud, validators, and upsert - #1478

Merged
leahpeker merged 5 commits into
mainfrom
chore-survey-test-coverage
Sep 14, 2026
Merged

leahpeker merged 5 commits into
mainfrom
chore-survey-test-coverage

Conversation

@leahpeker

Copy link
Copy Markdown
Collaborator

Summary

Closes #1467

  • backend/tests/test_surveys_admin.py — admin survey CRUD, question CRUD, reorder, and manage_surveys permission-denied paths (all 10 admin endpoints, audited).
  • backend/tests/test_survey_validators.py — unit tests for every _validate_* answer validator plus _validate_survey_answers (required enforcement) and _build_survey_answers.
  • backend/tests/test_surveys_public.py — added one-response-per-user upsert coverage (first submit creates, second submit updates in place and returns 200, one_response_per_user=False creates a second row, anonymous submits are never upserted).
  • Vitest: SurveyScreen.test.tsx (required validation blocks submit, first-time submit posts answers, "update response" label + preloaded answer when already responded), SurveyBuilderScreen.test.tsx (reorder calls the PUT endpoint with the new order, delete asks for confirmation and only calls DELETE on confirm), SurveyResponsesScreen.test.tsx (response table renders text, checkbox, and datetime-poll answers).

Bug fix

While writing the reorder tests I found a genuine production bug: PUT /api/community/surveys/{id}/questions/order/ was returning 405 for every request. In backend/community/_surveys.py, reorder_survey_questions (path .../questions/order/) was registered after update_survey_question / delete_survey_question (path .../questions/{question_id}/). Django resolves URL patterns in registration order, and the question_id path segment matches any string — so "order" matched the {question_id}/ pattern first, which only allows PATCH/DELETE, and the request 405'd before ever reaching reorder_survey_questions. This means reordering survey questions in the admin UI has been completely broken.

Fixed by moving reorder_survey_questions's registration above the {question_id}/ routes (matching the existing safe pattern already used in _join_form.py). No behavior change beyond making the endpoint reachable — same permission check, same logic. See the fix(surveys) commit.

Local verification

Backend: ran the new test files directly — test_surveys_admin.py + test_survey_validators.py (84 passed) and test_surveys_public.py (10 passed, includes the upsert tests) — then the full make agent-test suite: 2290 passed. The only 7 failures are pre-existing, environmental, and unrelated to surveys: test_sse.py (needs real pg_notify, SQLite returns 503), test_poll_finalize_race.py and test_rsvp_capacity_race.py (need real select_for_update row locking) — these are documented in the Makefile as SQLite-vs-Postgres gaps in local dev. make agent-lint (ruff) and make agent-typecheck both passed clean.

Frontend: ran the 3 new vitest files directly — all 7 tests passed — and lint-checked them individually (clean). Also ran the full make agent-frontend-test suite to completion: 1282 passed, 1 skipped, 6 failures — all pre-existing timeouts in files unrelated to this change (PublicRsvpSection.test.tsx, CommentItem.test.tsx, EventFormHosts.test.tsx, EventRsvpQuestionDialog.test.tsx), caused by heavy CPU contention from many other concurrent worktree sessions running on the same machine at the time, not by anything in this PR.

Not verified locally: partway through, local CI runs were stopped by the coordinator (machine load from many concurrent sessions). As a result, the full repo-wide make agent-frontend-lint (eslint + prettier over the whole frontend) and the umbrella make agent-ci were not completed locally. GitHub Actions CI is the first full run of those two gates for this PR — please watch CI closely, particularly for lint/format issues outside the 3 new test files.

Test plan

  • backend/tests/test_surveys_admin.py — CRUD, question CRUD, reorder, permission-denied paths
  • backend/tests/test_survey_validators.py — each validator + required enforcement + _build_survey_answers
  • backend/tests/test_surveys_public.py — one-response-per-user upsert behavior
  • frontend/src/screens/surveys/SurveyScreen.test.tsx, SurveyBuilderScreen.test.tsx, SurveyResponsesScreen.test.tsx
  • Confirm the reorder-route fix doesn't regress anything else under /surveys/{id}/questions/...
  • Watch GitHub Actions CI closely — agent-frontend-lint and agent-ci were not run locally for this branch

leahpeker and others added 5 commits September 14, 2026 01:13
PUT .../questions/order/ was declared after the PATCH/DELETE
/{question_id}/ routes. Django resolves URL patterns in registration
order and the question_id path segment matches any string, so a
request to .../order/ matched the {question_id}/ pattern first (with
question_id="order") and 405'd instead of reaching
reorder_survey_questions. Found while writing admin survey tests
(Issue 1467) — reordering survey questions was completely broken.
Adds coverage for survey admin CRUD, question CRUD, reorder,
manage_surveys permission gating, the standalone answer validators,
and the one-response-per-user upsert behavior on the public submit
endpoint.
Vitest coverage for required-field validation and the update-response
label on SurveyScreen, reorder + delete-confirm on
SurveyBuilderScreen, and the responses table rendering text/checkbox/
datetime-poll answers on SurveyResponsesScreen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@leahpeker
leahpeker merged commit aa9f9ce into main Sep 14, 2026
3 checks passed
@leahpeker
leahpeker deleted the chore-survey-test-coverage branch September 14, 2026 17:36
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.

Cover survey admin CRUD, reorder, validators, and upsert with tests

1 participant