console: render environment-not-ready flow in the standard layout - #38087
console: render environment-not-ready flow in the standard layout#38087jubrad wants to merge 4 commits into
Conversation
cda8d88 to
fac2428
Compare
6191cc2 to
61ce9f9
Compare
| expect( | ||
| screen.queryByTestId("welcome-dialog-close-button"), | ||
| ).not.toBeInTheDocument(); |
There was a problem hiding this comment.
I don't think this test actually does anything. Probably have to wait a bit more
| expect( | |
| screen.queryByTestId("welcome-dialog-close-button"), | |
| ).not.toBeInTheDocument(); | |
| await expect( | |
| screen.queryByTestId("welcome-dialog-close-button"), | |
| ).rejects.toThrow(); |
There was a problem hiding this comment.
Good catch, this test was asserting nothing. Confirmed by mutation testing: with hideWelcomeDialog removed from BaseLayout, the test still passed.
The cause is that the dialog mounts asynchronously (WelcomeDialogContent flips showModal in an effect, and Chakra portals it in), so the synchronous queryByTestId ran before it ever had a chance to appear.
Your instinct to use .rejects.toThrow() was right, it just needs findByTestId rather than queryByTestId since the latter returns an element-or-null rather than a promise. Also passing an explicit 2s timeout, because the suite-wide asyncUtilTimeout is 10s and this negative assertion would otherwise burn the whole budget (the test went from 10.1s to 2.1s).
Now verified in both directions: fails without hideWelcomeDialog, passes with it. I mutation tested the two nav assertions in this file the same way and they do fail correctly when accountOnlyNav is removed.
The environment-not-ready flow used a stripped custom layout with no navigation, so users without an enabled environment could not see or reach account-scoped pages like App Passwords, License, or Usage & Billing. A blocked or trial-expired organization, by contrast, already rendered the full BaseLayout with those links visible, making the two states inconsistent. Render EnvironmentNotReadyRoutes inside BaseLayout instead. The nav already handles the no-environment state: region-scoped items hide via HideIfEnvironmentDisabled while account-scoped Admin items carry forceShow, so new users now get the same chrome as everyone else. The logo links back to the enable-region flow while no environment is ready. The welcome dialog is suppressed in this flow via a new BaseLayout prop. It pops the moment a region becomes healthy and would cover the flow's own region-ready affordances, blocking the tutorial's "Open console" button (caught by the e2e suite). The region-ready toast is preserved in a headless RegionReadyToast component. Its unmount cleanup reads the unstable toast reference through a ref instead of an eslint-disable, which the react-compiler lint rule no longer accepts. The custom layout file is deleted. Adds tests asserting the Admin nav group renders on the enable-region page with no enabled environment while region-scoped items stay hidden, and that the welcome dialog stays suppressed once a region is healthy. The test provider wrapper now nests ToastProvider inside the router to match the app, so toasts can render router Links. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The environment health probe treated a SQL-level error response as an immediate "crashed", while connection failures got a grace window of maxBootDuration after the region was enabled. A freshly provisioned environmentd can respond with errors before it has fully initialized, and the region API only reports provisioning state, not whether environmentd is serving queries, so the probe is the only readiness signal. Since isEnvironmentReady counts "crashed" as ready and EnableRegion routes crashed environments to the console home, one transient error during boot dropped users into a console that could not serve queries yet. Treat SQL errors like connection failures: "booting" within the boot window, "crashed" after it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The nav in the environment-not-ready flow was gated on environment health, so a transient health reading could flash the full sidebar and object-creation entry points while nothing was usable yet. Gate it on the flow instead: a new accountOnly nav mode renders only the account-scoped (forceShow) items and hides the Create New button, and EnvironmentNotReadyRoutes turns it on. The full sidebar appears only once the user leaves the flow for a working console. Also restyle the tutorial slides to center in the layout's content area like the enable-region page, instead of the absolute viewport positioning they used under the old standalone layout. Adds a test asserting the nav stays account-only in this flow even when the environment reports crashed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A slide click can be swallowed when the environment flips to healthy mid-transition: the async environment atoms re-resolve, the slide content suspends for a frame, and the click lands on a detached anchor, leaving the page on the same slide. Observed as webkit timeouts on a different slide each run. Verify each click landed on the next slide's heading and retry the click when it didn't, and give the clicks a generous timeout for loaded CI workers while at it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
61ce9f9 to
87b677d
Compare
def-
left a comment
There was a problem hiding this comment.
No further complaints from QA side
Motivation
The environment-not-ready flow used a stripped custom layout with no navigation, so users without an enabled environment could not see or reach account-scoped pages like App Passwords, License, or Usage & Billing. A blocked or trial-expired organization, by contrast, already renders the full
BaseLayoutwith those links visible, so the two states were inconsistent.Changes
Render
EnvironmentNotReadyRoutesinsideBaseLayout, so users without an enabled environment get the standard chrome (error boundary, suspense fallback, footer) and can reach account-scoped pages.The nav in this flow is account-only via a new
accountOnlynav mode: only the Admin group renders, and the Create New button is hidden. Gating on the route rather than environment health means a transient health reading can never flash the full sidebar mid-boot. The full sidebar appears once the user continues to a working console.The waiting page (the "We're creating your environment" slides with the "Open console" button) is restyled to center in the layout's content area like the enable-region page, replacing the absolute viewport positioning from the old standalone layout.
Suppress the welcome dialog in this flow via a new
BaseLayoutprop. It pops the moment a region becomes healthy and its modal covered the tutorial's "Open console" button (caught by the e2e suite).Preserve the region-ready toast in a headless
RegionReadyToastcomponent. Its unmount cleanup reads the unstable toast reference through a ref rather than aneslint-disable, which thereact-compilerlint rule no longer accepts.Delete the custom
Layout.tsx(EnvironmentNotReadyLayout,EnvironmentNotReadyStatus).The logo already links back to the enable-region flow while no environment is ready (
/redirects there), so no extra nav entry was added.Fix the environment health probe treating SQL-level errors as an immediate
crashedeven during the boot window. A freshly provisioned environmentd can respond with errors before it is fully initialized, and sinceisEnvironmentReadycountscrashedas ready, one transient error routed users into a console that could not serve queries yet. SQL errors now get the samemaxBootDurationgrace as connection failures.Harden the onboarding slide clicks in the e2e suite: a click can be swallowed when the environment flips to healthy mid-transition (the slide content suspends for a frame and the anchor detaches), leaving the page on the same slide. Each click now verifies the next slide's heading appeared and retries when it didn't.
Tests
booting, after the window reportscrashed. The test provider wrapper now nestsToastProviderinside the router to match the app, so toasts can render routerLinks.Checklist
$T ⇔ Proto$Tmapping (possibly in a backwards-incompatible way), then it is tagged with aT-protolabel.🤖 Generated with Claude Code