Repository navigation
fix(react-core): render each instruction in its own paragraph - #1844
Sanilas-ai wants to merge 2 commits into
Conversation
joshunrau
left a comment
There was a problem hiding this comment.
Thanks for picking this up. The fix itself looks right: one paragraph per entry, whitespace-pre-line, and index keys are what the triage on #1812 asked for. Two things are needed before it can merge:
-
Add an end-to-end test. Every change here needs one in
testing/, and this PR has none. It matters for this fix in particular: happy-dom has no layout engine, so the unit tests can't check thatwhitespace-pre-linekeeps line breaks. Only a real browser can.testing/src/specs/playground.spec.tsalready renders instruments throughgeneratePlaygroundURL. Add a form there whoseclientDetails.instructionshas two entries, for example'Read each question.'and'Answer'+ newline +'honestly.'. That spec builds the instrument source in a template literal, so write the newline as\\n: a bare\nputs a raw line break inside a string literal and the instrument won't compile. Then assert that:- the overview shows each entry as its own element, using
getByText(..., { exact: true }). Withoutexact, Playwright matches substrings, so the old joined paragraph would pass too. - the second entry's
innerText()is'Answer\nhonestly.'. - after Begin, the instructions dialog shows the same two entries.
The info button that opens the dialog (
FormContent.tsx:55-57) has no accessible name, so the spec has nothing reliable to select it by. Give it a translatedaria-label; the dialog title'st({ en: 'Instructions', es: 'Instrucciones', fr: 'Instructions' })works. Then switchgetInfoButtoninFormContent.test.tsxtogetByRole('button', { name: 'Instructions' }). - the overview shows each entry as its own element, using
-
Render the instructions in one place.
FormContent.tsx:70-75andInstrumentOverview.tsx:51-56now have the same markup: the same classes, key and comment. This bug shows why that's a problem: both components had the samejoin(', '), and both needed the same fix. Please move it into one small internal component, e.g.packages/react-core/src/components/InstrumentInstructions/(InstrumentInstructions.tsx+index.ts). It takesinstructions: string[]and renders one<p className="whitespace-pre-line">per entry. Use it in both places, give it a unit test in its own__tests__/folder, and don't export it fromsrc/index.ts.
Reviewed at commit 221afa0.
Instrument instructions were joined with ', ' into a single paragraph in InstrumentOverview and the FormContent info dialog. Render one whitespace-pre-line <p> per entry instead, keyed by index since entries may repeat. Fixes DouglasNeuroInformatics#1812
Move the per-entry paragraphs into an internal InstrumentInstructions component used by both InstrumentOverview and FormContent, and give the instructions button an accessible name so it can be found by role. Add a playground end-to-end test: happy-dom has no layout engine, so only a real browser can check that whitespace-pre-line keeps an entry's line breaks, in the overview and in the instructions dialog.
221afa0 to
6689ddb
Compare
|
Thanks for the detailed review! Both points are done in 6689ddb, rebased on
Caveat: my CPU has no AVX, so the API's MongoDB can't start here. I ran the playground spec with only the playground server (details in the PR description). The full e2e run still needs CI or another machine. |
joshunrau
left a comment
There was a problem hiding this comment.
Thanks for the quick turnaround. Both points from the last review are done. The e2e test fails for the right reasons, using a useInnerText regex to get around Playwright's whitespace normalization was a good call, and the markup now lives in InstrumentInstructions. CI is green. Two small things are left, both from the second commit:
-
Update
packages/react-core/AGENTS.md. Lines 20-22 say exactly four components are deliberately left out ofsrc/index.ts:FormContent,InteractiveContent,FileInstrumentContentandInstrumentOverview.InstrumentInstructionsis now a fifth, so that statement is no longer true. The repo's rules say a change and its package'sAGENTS.mdmust never disagree. Please addInstrumentInstructionsto that list, with a few words saying it is an internal part ofFormContentandInstrumentOverview. -
Share the "Instructions" label in
FormContent.tsx. The newaria-label(lines 58-62) and the dialog title (lines 73-77) both write{ en: 'Instructions', es: 'Instrucciones', fr: 'Instructions' }inline. The repo prefers an inlinet()only for a string that is used once, and the triage on #1812 asked for one constant here. My earlier note pointed you at the dialog title'st()call; I should have said to share it. Please move the object into one module-level constant typedLocalizedText(the type is already imported in that file) and pass that constant tot()in both places.
Reviewed at commit 6689ddb.
Fixes #1812.
InstrumentOverviewand theFormContentinfo dialog joinedinstructionswith', ', so an instrument with several instructions (often full sentences) showed them as one comma-separated paragraph.Changes
packages/react-core/src/components/InstrumentInstructions/(InstrumentInstructions.tsx+index.ts, not exported fromsrc/index.ts). It takesinstructions: string[]and renders one<p className="... whitespace-pre-line">per entry. Plain paragraphs, not a list, as suggested in the issue;whitespace-pre-linekeeps line breaks inside an entry. The key is the index because entries may repeat.InstrumentOverview.tsxandFormContent.tsxboth render the instructions through it, so the markup lives in one place.FormContent.tsx: the info button that opens the instructions dialog now has a translatedaria-label(Instructions/Instrucciones/Instructions).FormContent.test.tsxfinds it withgetByRole('button', { name: 'Instructions' }).InstrumentInstructions/__tests__/InstrumentInstructions.test.tsx(one<p>per entry, repeated entries, line break kept withwhitespace-pre-line, empty list). TheInstrumentOverviewandFormContenttests assert each entry is its own<p>and the joined string is gone.testing/src/specs/playground.spec.tsrenders a form whoseclientDetails.instructionsis['Read each question.', 'Answer\nhonestly.']throughgeneratePlaygroundURL. It checks the overview and, after Begin, the instructions dialog: each entry is found withgetByText(..., { exact: true }), and the second entry's inner text isAnswer\nhonestly.. That check usestoHaveText(/^Answer\nhonestly\.$/, { useInnerText: true }), because a stringtoHaveTextnormalizes whitespace and would pass without the line break.Verification
packages/react-core:npx vitest run src/components: 29 files, 178 tests passed.pnpm lint(tsc+ eslint) is clean.testing:pnpm lint(gen:routes,tsc, eslint) is clean.main'sInstrumentOverview/FormContent(joined paragraph), it fails at theexactlookup ofRead each question.;whitespace-pre-lineremoved from the component, it fails at the inner-text check (received"Answer honestly.").setupproject can't run. I ran this spec with a local-only Playwright config that starts just the playground dev server and drops thesetupdependency (the playground tests don't touch the API). The fullpnpm test:e2estill needs to run on a machine with AVX or in CI.