Repository navigation
test(stories): add a story of the whole chat - #127
TheGreatAxios merged 7 commits into
Conversation
Compose the new chat family from the shared samples into one story, in both scroll policies: a conversation with agent steps, approvals and generated images, a prompt input with its toolbar and attachments, the conversation map and history window, and a panel with a thread tab. A browser spec drives the story to check that sending settles, approvals keep keyboard focus after they fold, and attachments move into the sent message.
260ee19 to
22da640
Compare
TheGreatAxios
left a comment
There was a problem hiding this comment.
Automated multi-agent review: independent review + second-agent validation; only confirmed items listed. The story itself is genuinely strong; the e2e spec under it has one blocking structural error.
-
blocking (verified against Ladle 5.1.1 itself — package contents + routing source)
e2e/full-chat.spec.ts:9-11— the spec drives Storybook URLs (/iframe.html?id=…&viewMode=story&globals=theme:light, waits forbody.sb-show-main) at a Ladle server. Ladle ships exactly one HTML file (lib/app/index.html, noiframe.html), ignoresid/viewMode/globalsparams, has nosb-show-mainclass ever, and its own comment inplaywright.config.tscalls it "the Ladle stories build" — so all five tests fail at the firstgoto, permanently, in CI. Fix: use the sibling spec's real Ladle scheme —page.goto(\${STORIES}/?story=chat-full-chat--${story}&mode=preview&theme=light`)and wait for[data-storyloaded](the story idschat-full-chat--settle/--stickare already in correct Ladle format) — then rerunbun run build && bun run test:e2e`. -
should-fix (plan gap)
stories/chat/full-chat.stories.tsx:473-486— the Sources family never composes: the story'scase "sources"branch is dead code because the only sample carrying asourcespart (shortChat) is never mounted, while task 15's objective is "prove every family composes". Give one mounted answer asourcespart. -
minor (process) no
e2e/fixtures.tsxentry, while the plan requires one entry per scenario and every sibling spec follows that contract. Defensible here (the composition lives in the story and the axe sweep hits the same server) — but say so in the PR body rather than silently dropping it. -
minor (flake)
e2e/full-chat.spec.ts:133-141— Stop is clicked on a live label that exists for a single 120 ms replay frame, from inside apage.waitForFunction(..., { polling: "raf" })side effect; one missed frame = permanent false condition = 30 s timeout despite a clean settle. Poll read-only (expect.pollon the trigger text) and click via locator. -
nits —
onOpen={(image, opener) => …}misnames an index (the prop hands over(index, opener); rename toindex,:470); approved tool outputs are hardcoded"Done"(:~308) — vary or derive them; attached files are never openable (viewerItemsOfonly mapsimagekinds and message-tileAttachmentPreviewgets noonOpen— story-coverage follow-up);MODELS/MODES/attachment refusal copy is duplicated fromprompt-input.stories.tsx/attachments.stories.tsxand already diverged (2 vs 3 models;MAX_FILESvs literal20) — hoist tosamples/.
22da640 to
be03ac7
Compare
be03ac7 to
4f86f25
Compare
|
Thanks for the review. Here's what happened to each point. On the blocking itemThis repo runs Storybook 10, not Ladle (see Fixed1. The Sources component never appeared in the whole-chat story (should-fix)
2. The Stop test was flaky (minor)
3. Nits
Not changed, and why
Also in this PRA Commits: |
163203b to
92e2515
Compare
TheGreatAxios
left a comment
There was a problem hiding this comment.
Review · Request changes
Adds a story of the whole chat. Stop and unmount do clear the replay timer in the story. The e2e does not prove that.
Findings
-
e2e/full-chat.spec.ts:164— Stop can pass while the next frame is still scheduled.playTurnemits the running frame and queues the next one 120ms later (play-turn.ts:183).stopAnswerappliesstopped()synchronously (full-chat.stories.tsx:1194-1205), so "1 failed",data-status="sent", and the tool'serrorare already true beforepage.clock.resume(). Resume unpauses and does not advance that 120ms, anddata-status="sent"is also the natural last frame. Droppingstop.current?.()and keeping the state update still goes green if the expects finish inside the step. After Stop,runForseveralREPLAY_STEP_MSand assert the tool is stillerror. -
e2e/full-chat.spec.ts:191— The "4 replies" expect does not wait for the streamed answer.sendappends the user reply andplayTurnemits the empty streaming frame in the same turn (full-chat.stories.tsx:988-996,play-turn.ts:185). The parent count isthreadReplies.length, so it becomes 4 before any timer. AplayTurnthat emits once and returns would still pass. Wait for the reply text before asserting the count.
92e2515 to
7c44aa4
Compare
The Stop test resumed the page clock right after Stop. That lets the clock run in real time, so a replay frame that Stop failed to cancel could land after the asserts and the test still passed. Move the paused clock on by a full run of frames first, so any leaked frame lands before the asserts. The thread reply test checked for "4 replies" as soon as the reply was sent. The count reaches 4 with the answer's first, empty frame, so it passed even if the answer never streamed. Wait for the answer's text first, which also shows the final frame replaces the streaming one.
7c44aa4 to
761b6be
Compare
|
Thanks for the review. Both tests are tightened. The story itself is unchanged, because its behaviour was already right. 1. The Stop test could pass with the next frame still scheduled (test gap)
2. The "4 replies" check didn't wait for the answer (test gap)
Tests for both: I ran both specs against a broken copy of the story. In that copy, Stop doesn't cancel the replay and the thread answer never streams past its first frame.
Commit: |
The composer's refusal line is a status region, but empty:hidden took it out of the accessibility tree while it had no text. A refused file then brought the region and its text in the same update, which screen readers generally do not announce. The line now stays mounted with its reserved height, as in the Attachments story, so the refusal is read out as a change to it.
The recent samples were spaced 30 seconds apart after the long history, whose last message sits 7 minutes before the story's now. Seventeen steps ran past now, so the last answers read "in 30s" and "in 2m", and a message sent from the box read as older than the one above it. The step now divides the gap between the history and now, so every message sits before now, in order.
Sent file tiles were keyed by name, but two files of one name and different sizes are both accepted, so a message could hold two tiles with the same key. They are now keyed by position and name.
761b6be to
4cead3f
Compare
Round 3 fixesA fresh review pass over the stack turned up the points below; each is fixed in a new commit at the end of this branch, and the stack is rebased onto it.
|
4cead3f to
7718fd3
Compare
Superseded by the completed stacked review; blocking fixes were addressed and the rebased stack is being landed.
|
Triage: Fail @pratikbuilds, please address the following:
Stacked on #126: only this pull request's own changes were checked. Notes:
Triage will request changes. |
Compose the new chat family from the shared samples into one story, in both scroll policies: a conversation with agent steps, approvals and generated images, a prompt input with its toolbar and attachments, the conversation map and history window, and a panel with a thread tab. A browser spec drives the story to check that sending settles, approvals keep keyboard focus after they fold, and attachments move into the sent message.
Stacked on #126: review only this commit. Part of #94.
Notes for review
Verification
bun run typecheckandbun run linton its own (the stack is checked commit by commit).bun run check,bun run build,bun run dep-guard,bun run contrast-testandbun run test:e2e(Playwright specs and the Storybook axe sweep in light and dark) pass.Closes #109