SimpleDocReview / tests /README.md
Eric Putnam
Claude Opus 5 (1M context)
feat: deploy simpledocreview as a browser-only static space
3d968d9
|
Raw History Blame Contribute Delete
5.48 kB

Tests

This deployment repo would normally carry no tests β€” upstream has them, and a copy-and-push pipeline has little to verify. These exist because of one thing: overlay/sdr-api-core.js is a hand-written JavaScript port of upstream's 1,200-line Python server, and a port that drifts from the server it mirrors makes the Space lie about what the tool does.

Nothing else in the build would notice that drift. These two suites do.

node tests\parity\run-parity.mjs         # the port vs. the real app.py
node tests\browser\run-browser-check.mjs # the built site in a real browser

Both run automatically in scripts\deploy.ps1 before anything is pushed, since a Static Space goes live the instant the push lands.

parity/ β€” is the port the same program?

run-parity.mjs replays one 67-request workflow twice and diffs the results:

  • The reference. reference.py imports the vendored app.py from app/, points its storage at a temporary directory, replaces utc_now and uuid4 with counters, and serves it over real HTTP on a single-threaded server.
  • The port. run-parity.mjs loads overlay/sdr-api-core.js in Node with an in-memory store and the same counters.

Then it compares every response status, every response body, the SHA-256 of the downloaded bytes, the final record store, and the list of stored uploads.

Two details do most of the work:

  • Sequential timestamps and ids. Because the clock advances one second per call and ids count up from 1, the port has to call them the same number of times in the same order. A missing utc_now() or an extra uuid4() β€” easy to introduce, since Python builds its migration defaults dict eagerly and consumes an id whether it uses one or not β€” becomes a visible mismatch instead of a value nobody compares.
  • A JSON round-trip on every load and save. app.py re-reads its file per request, so a handler that mutates a record and then fails without saving throws the change away. The in-memory store copies on load and save for the same reason; handing out a live object would let those changes stick and hide the difference.

The corpus

corpus/ is committed and covers the rubric and the text pipeline:

File What it is for
clean-policy.md All six required sections, long enough, no findings
messy-draft.md Every placeholder form, two vague phrases, an overlong sentence, missing sections
tiny.txt Short-document and every missing-section finding at once
unicode.md Word counting across scripts, apostrophes, hyphens, and combining marks β€” where Python's Unicode-aware \w and JavaScript's ASCII \w would otherwise disagree
whitespace.txt Rejected: no readable text
notes.rtf Rejected: unsupported type

.corpus/ is generated by reference.py on each run and gitignored, because the fixtures are binary or encoding-specific: a deflated DOCX, a stored DOCX, a ZIP with no word/document.xml, a file that is not a ZIP at all, UTF-16 with a BOM, cp1252 with bytes that are not valid UTF-8, and an empty file.

corpus/** is marked -text in .gitattributes. One rubric rule counts characters between sentence terminators, so a CRLF checkout would change a finding.

Accepted divergences

ACCEPTED_DIVERGENCES in run-parity.mjs lists differences that are correct, each with its reason, and prints them on every run rather than dropping them. There is currently one: mimetypes.guess_type returns application/octet-stream for .docx on a Windows machine with no Office mapping, where the port always sends the real OOXML type.

Add to that list only for a difference you can justify in a sentence. Anything not on it fails the run.

browser/ β€” does it work as a page?

The parity suite runs the port in Node, so it says nothing about the parts between the port and the browser. run-browser-check.mjs serves the repository root over HTTP β€” plainly, with no SPA fallback, the way a Static Space does β€” opens it in headless Chromium through the DevTools protocol, and drives the real UI: upload, review, add a reviewer, assign, approve, download, reload.

It checks the things only a browser can prove:

  • both overlay scripts loaded, in order, before app.js ran
  • upstream's XMLHttpRequest calls are answered locally
  • IndexedDB keeps the workspace across a reload
  • the Download button produces a file instead of navigating to a path that does not exist on a static host
  • no console errors anywhere in the run

It talks the DevTools protocol directly instead of adding a browser-automation dependency this repo otherwise has no use for. It finds Edge or Chrome from the usual Windows install paths; set BROWSER to override, and pass --headed to watch it happen.

One quirk worth knowing: approving a document that still has findings goes through window.confirm, and an unanswered dialog blocks the renderer β€” including the evaluation waiting on it. The client accepts the dialog over CDP rather than stubbing confirm in the page, so the real code path runs.

When a test fails after an upstream change

That is the intended outcome, not a broken test. build-static.ps1 will already have refused to build for the same reason. Read the upstream diff, carry the behavior into overlay/sdr-api-core.js, re-run both suites, then acknowledge the change with .\scripts\build-static.ps1 -AcceptUpstreamChanges.