Skip to content

console: render environment-not-ready flow in the standard layout - #38087

Open
jubrad wants to merge 4 commits into
MaterializeInc:mainfrom
jubrad:console-unify-environment-not-ready
Open

console: render environment-not-ready flow in the standard layout#38087
jubrad wants to merge 4 commits into
MaterializeInc:mainfrom
jubrad:console-unify-environment-not-ready

Conversation

@jubrad

@jubrad jubrad commented Aug 6, 2026

Copy link
Copy Markdown
Member

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 BaseLayout with those links visible, so the two states were inconsistent.

Changes

  • Render EnvironmentNotReadyRoutes inside BaseLayout, 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 accountOnly nav 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 BaseLayout prop. 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 RegionReadyToast component. Its unmount cleanup reads the unstable toast reference through a ref rather than an eslint-disable, which the react-compiler lint 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 crashed even during the boot window. A freshly provisioned environmentd can respond with errors before it is fully initialized, and since isEnvironmentReady counts crashed as ready, one transient error routed users into a console that could not serve queries yet. SQL errors now get the same maxBootDuration grace 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

  • Adds a test asserting the Admin nav group (App Passwords, Usage & Billing) renders on the enable-region page with no enabled environment, and that region-scoped items stay hidden.
  • Adds a test asserting the welcome dialog stays suppressed on the tutorial page once a region is healthy.
  • Adds health probe tests: SQL error within the boot window reports booting, after the window reports crashed. The test provider wrapper now nests ToastProvider inside the router to match the app, so toasts can render router Links.

Checklist

  • This PR has adequate test coverage / QA involvement has been duly considered. (trigger-ci for additional test/nightly runs)
  • This PR has an associated up-to-date design doc, is a design doc (template), or is sufficiently small to not require a design.
  • If this PR evolves an existing $T ⇔ Proto$T mapping (possibly in a backwards-incompatible way), then it is tagged with a T-proto label.
  • If this PR will require changes to cloud orchestration or tests, there is a companion cloud PR to account for those changes that is tagged with the release-blocker label (example).
  • If this PR includes major user-facing behavior changes, I have pinged the relevant PM to schedule a changelog post.

🤖 Generated with Claude Code

image

@jubrad
jubrad force-pushed the console-unify-environment-not-ready branch from cda8d88 to fac2428 Compare August 6, 2026 18:32
@jubrad
jubrad marked this pull request as ready for review August 6, 2026 19:01
@jubrad
jubrad requested a review from a team as a code owner August 6, 2026 19:01
@jubrad
jubrad requested a review from leedqin August 6, 2026 19:01
@jubrad
jubrad force-pushed the console-unify-environment-not-ready branch 2 times, most recently from 6191cc2 to 61ce9f9 Compare August 7, 2026 03:20
Comment on lines +132 to +134
expect(
screen.queryByTestId("welcome-dialog-close-button"),
).not.toBeInTheDocument();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this test actually does anything. Probably have to wait a bit more

Suggested change
expect(
screen.queryByTestId("welcome-dialog-close-button"),
).not.toBeInTheDocument();
await expect(
screen.queryByTestId("welcome-dialog-close-button"),
).rejects.toThrow();

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks!

jubrad and others added 4 commits August 7, 2026 10:18
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>
@jubrad
jubrad force-pushed the console-unify-environment-not-ready branch from 61ce9f9 to 87b677d Compare August 7, 2026 15:18
@jubrad
jubrad requested a review from def- August 7, 2026 15:21

@def- def- left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No further complaints from QA side

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants