test: cover the drug form lookups and the static prescription check - #671
Merged
Conversation
Two features had no test coverage at all. Drug form lookups (GET /drugs/resources/<drug>/<segment>[/<hospital>], GET /drugs/frequencies, GET /lists/routes): the catalogues the prescription drug form loads before it can be rendered. Covers the full unit/frequency catalogue and its ordering, the counts carried over from the drug's aggregated history (including the segment filter), the hospital route variant, an unknown drug, the empty routes/intervals of the non-complete mode, the transcription fields read from memory, the map-routes parsing (configured, absent and malformed entries) and the permission gates. Static prescription check (POST /static/prescriptions/status): the endpoint an external system calls to check a prescription on behalf of one of its own users, identified by external id. Covers the happy path (status, attribution to the origin user and the audit flagged as serviceUser), undoing a check, and every rejection: unknown, inactive, foreign-schema, unauthorized-segment and read-only origin users, unknown prescription, unchanged status, and the RUN_AS/authentication gates. The memory helper snapshots and restores whatever the schema already held, and both files clean their own rows, so the suite stays re-runnable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJNm2wnqhhzgxa3bx8NSpS
There was a problem hiding this comment.
This PR adds comprehensive test coverage for two features that previously had none: drug form lookup endpoints and static prescription checking. The test implementations are solid with proper cleanup, isolation, and re-runnability. No defects found that would block merge.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
The ordering assertion compared the response against Python's sorted(), which is codepoint order and put 'UI'/'Un' before the lowercase units. That only holds under a C collation: CI initialises PostgreSQL with en_US.utf8, where the same ORDER BY description returns mcg, mg, mg/ml, ml, UI, Un. Ordering by description is the database's, so compare the catalogue tail of the response against what the database itself returns for the same table. The assertion still pins that the service preserves that order and appends the catalogue after the previously prescribed entries, and it now holds under either collation. Verified against both a C.UTF-8 and an en-US collated database: 2323 passed on each. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJNm2wnqhhzgxa3bx8NSpS
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.
Increases test coverage on two features that had none. Tests only — no production code changes.
Drug form lookups —
tests/integration/test_drug_form_resources.py(17 tests)The catalogues the prescription drug form loads before it can be rendered:
GET /drugs/resources/<idDrug>/<idSegment>[/<idHospital>],GET /drugs/frequenciesand
GET /lists/routes.previously prescribed id comes back twice (history entry with the count, catalogue
entry with zero) and that history from another segment is ignored
/<idHospital>variant returning the same payload as the two-segment routeroutesandintervalsstaying empty outside thecompletemodeextraFields/removeFieldsread from thetranscription-fieldsandtranscription-remove-fieldsmemories, and the empty casemap-routesparsing: configured entries, absent memory, and malformed entries skippedREAD_PRESCRIPTIONon the drug endpoints,READ_BASIC_FEATURESon/lists/routes)Static prescription check —
tests/integration/test_static_prescription_status.py(14 tests)POST /static/prescriptions/status— the endpoint an external system calls to check aprescription on behalf of one of its own users, identified by external id. The caller
authenticates as a
SERVICE_INTEGRATOR(RUN_AS).service integrator, and audited with
serviceUser: true0origin user without segment authorization, origin user without
WRITE_PRESCRIPTION,unknown prescription, and a status that does not change the prescription
RUN_ASpermission gate and the authentication gateTest hygiene
Both files clean their own rows and are re-runnable: the drug fixture reuses the
reserved
>= 90000id range already wiped bytests/conftest.py::_cleanup, the originusers use the
test%@example.compattern and drop their ownusuario_autorizacaorows,and the memory helper snapshots and restores whatever the schema already held instead of
deleting seed data.
Verification
Full suite against a local PostgreSQL loaded from
noharm-ai/database(the same SQLfiles CI uses): 2323 passed (2292 before), and green on a second consecutive run to
confirm re-runnability.
ruff check .passes.Note (no change made)
While covering
static_check, one behaviour stood out and was deliberately leftuntested rather than pinned down: when
idOriginUseris absent from the payload, thelookup becomes
User.external IS NULL, which matches whichever seed user comes backfirst — so a caller omitting the field can end up running as an arbitrary user. It is
non-deterministic, so no test asserts it. Worth a look separately if you agree it's a
hole.
🤖 Generated with Claude Code
https://claude.ai/code/session_01HJNm2wnqhhzgxa3bx8NSpS
Generated by Claude Code