test(surveys): 1467 - cover admin crud, validators, and upsert - #1478
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #1467
backend/tests/test_surveys_admin.py— admin survey CRUD, question CRUD, reorder, andmanage_surveyspermission-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=Falsecreates a second row, anonymous submits are never upserted).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. Inbackend/community/_surveys.py,reorder_survey_questions(path.../questions/order/) was registered afterupdate_survey_question/delete_survey_question(path.../questions/{question_id}/). Django resolves URL patterns in registration order, and thequestion_idpath segment matches any string — so"order"matched the{question_id}/pattern first, which only allows PATCH/DELETE, and the request 405'd before ever reachingreorder_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 thefix(surveys)commit.Local verification
Backend: ran the new test files directly —
test_surveys_admin.py+test_survey_validators.py(84 passed) andtest_surveys_public.py(10 passed, includes the upsert tests) — then the fullmake agent-testsuite: 2290 passed. The only 7 failures are pre-existing, environmental, and unrelated to surveys:test_sse.py(needs realpg_notify, SQLite returns 503),test_poll_finalize_race.pyandtest_rsvp_capacity_race.py(need realselect_for_updaterow locking) — these are documented in the Makefile as SQLite-vs-Postgres gaps in local dev.make agent-lint(ruff) andmake agent-typecheckboth 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-testsuite 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 umbrellamake agent-ciwere 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 pathsbackend/tests/test_survey_validators.py— each validator + required enforcement +_build_survey_answersbackend/tests/test_surveys_public.py— one-response-per-user upsert behaviorfrontend/src/screens/surveys/SurveyScreen.test.tsx,SurveyBuilderScreen.test.tsx,SurveyResponsesScreen.test.tsx/surveys/{id}/questions/...agent-frontend-lintandagent-ciwere not run locally for this branch