Skip to content

Import Review Browser Smoke

Scope

This opt-in smoke verifies the browser-facing P4-003 route path without changing the default gateway route table. It opens the real import editor page, seeds the same browser auth and organization state that the frontend reads, edits the first question through the Teacher UI, applies an answer and score, saves through the visible Lưu lại control, reloads the editor, and checks the persisted review payload observed through Gateway.

The browser runner adds ?teacherImportReviewGateway=native to its editor URL. Without that explicit client opt-in, the same editor route remains local and does not call the non-default owner candidate.

For a native DOCX Fast review, package media is read only through the scoped adapter GET /api/exam-import/docx-fast-jobs/{id}/temp-draft/assets/{assetId}/content. The review component fetches it with the current Gateway bearer token and organization header, then renders the returned Blob URL. A bare <img> cannot send the browser's locally stored bearer token. The reviewed parse payload still keeps its canonical /api/storage/media-assets/{assetId}/content reference for the downstream Question Bank flow; the scoped adapter is limited to the unapproved native review surface.

Required Runtime

Start these processes before live mode:

  • Next.js web app, default WEB_BASE_URL=http://localhost:3000
  • API gateway, default GATEWAY_BASE_URL=http://localhost:8085
  • docx-import-service, default target from deploy/gateway/routes.import-review-roundtrip-native-localhost-example.json
  • gateway route table: GATEWAY_ROUTE_TABLE=deploy/gateway/routes.import-review-roundtrip-native-localhost-example.json

Use an existing completed import job with a parse result. The smoke does not create jobs and does not approve imports.

Run

Static self-test:

bash
cd go-platform
IMPORT_REVIEW_BROWSER_SELF_TEST=1 make test-import-review-browser

Live browser mode:

bash
cd go-platform
IMPORT_REVIEW_BROWSER_JOB_ID=<completed-job-id> \
IMPORT_REVIEW_BROWSER_AUTHORIZATION='Bearer <teacher-or-admin-token>' \
IMPORT_REVIEW_BROWSER_ORGANIZATION_ID=<org-id> \
IMPORT_REVIEW_BROWSER_EXPECT_NATIVE_ASSET=1 \
IMPORT_REVIEW_BROWSER_EXPECT_NATIVE_IMAGE=1 \
IMPORT_REVIEW_BROWSER_EXPECT_NATIVE_FORMULA=1 \
make test-import-review-browser

Useful optional variables:

  • IMPORT_REVIEW_BROWSER_HEADLESS=0 to see Chromium.
  • IMPORT_REVIEW_BROWSER_TARGET_TYPE=ESSAY to control the marker written to the first question.
  • IMPORT_REVIEW_BROWSER_QUESTION_TEXT, IMPORT_REVIEW_BROWSER_QUESTION_SCORE, and IMPORT_REVIEW_BROWSER_ANSWER to control the browser-edited first-question values.
  • IMPORT_REVIEW_BROWSER_INCLUDE_TEMP_DRAFT_TOKEN=1 to include the native materialized-{jobId} token when present.
  • IMPORT_REVIEW_BROWSER_EXPECT_NATIVE_ASSET=1 when the selected job has a materialized package asset. The smoke selects the first question that has media, requires the scoped media route header and a successful Gateway response, then returns to question 1 for the review save/reload assertions.
  • IMPORT_REVIEW_BROWSER_EXPECT_NATIVE_IMAGE=1 when that first media asset is an image. It requires EXPECT_NATIVE_ASSET=1 and verifies that the editor renders the asset through a Blob URL.
  • IMPORT_REVIEW_BROWSER_EXPECT_NATIVE_FORMULA=1 when the job contains a native formula. The smoke selects the first formula-bearing question, checks its literal LaTeX and source_kind in the read-only Teacher review panel, captures formula-preview.png, and verifies the same formula id, LaTeX, and source kind after the review reload.
  • IMPORT_REVIEW_BROWSER_ARTIFACT_DIR=output/playwright/<name> to control artifact output.

Assertions

The smoke fails unless:

  • the route table has exam-import-job-detail as native_read
  • the route table has exam-import-review-save as native_write
  • the route table has exam-import-docx-fast-asset-content as native_read, requires authentication, and matches only the job-scoped temp-draft asset content path
  • the browser observes X-Hoctapaz-Gateway-Route: exam-import-job-detail for GET /api/exam-import/jobs/{id}
  • the browser observes X-Hoctapaz-Gateway-Route: exam-import-review-save for PATCH /api/exam-import/jobs/{id}/review
  • when the supplied job has native media, the browser observes X-Hoctapaz-Gateway-Route: exam-import-docx-fast-asset-content and renders the fetched media from a Blob URL
  • when native formula proof is requested, the Teacher review panel displays the formula's LaTeX and source kind without injecting parser-supplied formula HTML and the selected formula survives the persisted review reload
  • after reload, the detail payload still contains questionTypeManualOverride=true, questionTypeReviewed=true, and questionTypeAutoDetected=false
  • after reload, the first question retains the browser-edited text, escaped HTML, answer, score, and scoring-rule max score

Live artifacts are written under output/playwright/ and include the initial detail payload, review body, review response, reloaded detail payload, and full-page screenshots. Formula-enabled runs also include native-formula-preview.json and formula-preview.png.

Rollback

Switch GATEWAY_ROUTE_TABLE back to deploy/gateway/routes.json, remove the native route-table entries, or set them to legacy_proxy. This smoke does not modify runtime state beyond the reviewed parse payload for the supplied job.

Isolated Live Rehearsal (2026-07-13)

The current Teacher UI, local API Gateway, IAM, and DOCX Import Service were started in an isolated Compose project. The Gateway listened on a separate local port with deploy/gateway/routes.import-review-roundtrip-native-localhost-example.json; the default route table was not changed. A newly registered teacher opened a completed 28-question Physics job in the real editor, which loaded its detail through Gateway instead of the editor's former demo fixture.

The smoke observed exam-import-job-detail for the initial and reloaded GET requests and exam-import-review-save for the PATCH request. The reloaded payload retained questionTypeManualOverride=true, questionTypeReviewed=true, and questionTypeAutoDetected=false. The local artifact directory contains the initial/reloaded payloads, review request and response, plus a 1280x3825 editor screenshot:

text
output/playwright/import-review-browser-isolated-20260713/

The browser runner now seeds the same versioned Gateway session shape checked by the frontend router and imports @playwright/test, the workspace's direct Playwright dependency. This is local non-default route evidence only. The Compose volumes, local Gateway, and Teacher UI are removed after the check; it does not promote public/default traffic.

Isolated Media Rehearsal (2026-07-14)

DOCX_PHYSICS_GATEWAY_ATTEMPT_LOCAL_POSTGRES_CONFIRM=local-postgres make test-docx-physics-attempt-local-postgres now creates fresh IAM, Document, Import, Question Bank, Exam, and Attempt PostgreSQL databases; starts a separate Teacher Vite process and a randomly assigned Gateway proof port in 18000-18999; and removes the runtime on exit. Before the existing approval and attempt proof, it seeds one unapproved 28-question Physics DOCX Fast job through sourceAssetId and runs this browser smoke against it.

The browser selected formula-bearing question 4 and displayed R=8,31J/mol.K with source kind mtef-ole, then reloaded the same formula id, LaTeX, and source kind after saving question 1. It also selected question 7, the first question with materialized media, and observed 200 image/png and X-Hoctapaz-Gateway-Route: exam-import-docx-fast-asset-content for the scoped asset request. It rendered the authenticated media as a Blob URL, returned to question 1, saved the visible review edits, and reloaded the preserved review payload. Evidence is under:

text
output/qa/docx-physics-gateway-attempt-local-postgres-20260714181852/

This confirms the current Teacher Import Review media and formula-provenance workflow against the non-default disposable Gateway table. It does not prove visual equivalence to Word/MathType, use a shared legacy object store, change deploy/gateway/routes.json, or establish default/public route promotion.

Go-platform documentation is generated from repository Markdown.