Repository navigation
test(studio): lock the split view's server render and hydration - #413
Open
Deodat-Lawson wants to merge 2 commits into
Open
Deodat-Lawson wants to merge 2 commits into
Deodat-Lawson wants to merge 2 commits into
Conversation
StudioSplitView made its per-tab portal hosts with document.createElement during render, so any server render of it threw "document is not defined". /dev/studio-tabs returned 500 in `next dev` since #409. The product route is not affected today only because WorkspaceShell renders a loading page until the Better Auth session resolves, and that never happens on the server. The panes now portal in only when there is a document, read with useSyncExternalStore: false on the server and during hydration, true in the browser. A client-side mount (the product path) still gets its panes on the first render. A hydrated one gets them straight after, which cannot mismatch because they were never in the server's HTML. Tabs still move between columns as the same node, with their state intact. Tests: a node-environment renderToString test (jsdom supplies `document` and would hide this bug), plus a jsdom test that hydrates server markup and then moves a pane between columns. All three fail without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_2d2e3577-ac02-4434-ad45-0242e569ec88) |
…2dc5d main fixed the same server-render crash independently in 76ed6c3 (split panes): a `mounted` flag, set in an effect, now gates the memoised PanePortals. Resolved StudioSplitView.tsx to main's version and dropped this branch's useSyncExternalStore flag, so there is one fix, not two. The tests stay, ported to main's API (rowLayout, renderEmpty, the split, zoom and resize callbacks, "pane N of M" strip names). main had no server-render coverage, and removing its `mounted &&` gate fails all three. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch had an error being deployed
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.
Summary
StudioSplitView. Since feat(studio): split the workspace centre into columns of tabs #409 it built its per-tab portal hosts withdocument.createElementduring render, so any server render threwReferenceError: document is not defined.GET /dev/studio-tabsreturned 500 onnext dev.mountedflag set inuseEffectnow gates the memoisedPanePortals. When resolving conflicts I took main's component as-is, so there is one fix, not two. This PR now changes no source code.__tests__/StudioSplitView.ssr.test.tsx(new,@jest-environment node):renderToStringsucceeds with nodocument, draws both panes' strips and leaves pane content out of the markup.__tests__/StudioSplitView.test.tsx(one new case): server-renders,hydrateRoots the markup with nothing logged, then moves Chat to the other pane and checks it's the same element with its draft and a single mount.Related
Follow-up to #409. Covers the server-render path of the fix in 76ed6c3.
Checklist
pnpm checkpasses (lint + typecheck): not run repo-wide.tsc --noEmitforapps/webandeslinton the touched files both exit 0.pnpm --filter @launchstack/web testpasses: ran thedocuments/_workspacesuite only (34 suites, 326 tests, all pass).packages/core/changed): N/A, tests only/dev/studio-tabsreturns 200 on the merged tree.Testing
{mounted && <PanePortals … />}gate temporarily removed, all three new tests fail; with it in place, all 20StudioSplitViewtests pass.curl -s -o /dev/null -w "%{http_code}" http://localhost:3011/dev/studio-tabsreturns200on the merged branch.Notes for reviewers
WorkspaceShellrenders<LoadingPage />until the Better Auth session resolves, and that never happens on the server. Only the auth-free dev harness crashed. These tests make the component's own SSR safety explicit instead of relying on that check.documentand would hide this class of bug.react-dom/server.nodeis imported because the browser build needs aTextEncoderthat jsdom lacks.react@18.3.1, whose server renderer warns "useLayoutEffect does nothing on the server"; the app runs Next's bundled React 19.2 canary, which doesn't. Both tests filter exactly that message and fail on anything else logged.mountedin auseEffect, so on a plain client-side mount (the product path) the first commit has no pane content. Panes appear a frame later. This branch originally useduseSyncExternalStore(noop, () => true, () => false), which is false on the server and during hydration but true on a client-side mount, so panes render in the first commit. The difference is one frame on first mount; happy to follow up if wanted.🤖 Generated with Claude Code
Note
Low Risk
Test-only changes that lock in SSR/hydration behavior for the documents workspace split view, with no production logic in this diff.
Overview
Adds regression tests so
StudioSplitViewcan be server-rendered without touchingdocument, and so client hydration still preserves pane DOM/state when tabs move between columns.A new Node/Jest SSR suite (
StudioSplitView.ssr.test.tsx) runsrenderToStringwith nodocument, asserts render completes without console errors (aside from filtered React 18useLayoutEffectwarnings), and checks the HTML includes the tab strips but not pane body content.The existing jsdom suite is refactored with a shared
viewOfhelper, and gains a hydrate-then-move case: server markup is injected,hydrateRootruns cleanly, pane content appears after hydration, and moving Chat to another column keeps the same element, draft value, and mount count.Reviewed by Cursor Bugbot for commit 29c8a94. Bugbot is set up for automated code reviews on this repo. Configure here.