Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
475efd9
test(auth): run auth e2e suite against tanstack start
jacobsfletch Jul 29, 2026
628648c
chore: wait for react commit before returning from goto
jacobsfletch Jul 29, 2026
d478506
better abstracts for page setup
jacobsfletch Jul 29, 2026
513c35e
chore: consolidate e2e page setup into test/__setup
jacobsfletch Jul 29, 2026
3d217be
chore: split test/__setup into e2e and int
jacobsfletch Jul 29, 2026
7767692
chore: reset the auth password through the API, not the admin UI
jacobsfletch Jul 29, 2026
a410ef8
chore: restore the default @payload-config path
jacobsfletch Jul 29, 2026
09c53c4
Merge branch 'main' into test/tanstack-auth-e2e
jacobsfletch Jul 29, 2026
41be548
fix refresh server fn e2e
jacobsfletch Jul 29, 2026
0bd8b30
chore: gate the hydration wait on the admin shell, not the view
jacobsfletch Jul 29, 2026
ce5364c
chore: detect the tanstack app from the page, not the environment
jacobsfletch Jul 30, 2026
a48b56b
chore: satisfy sort-objects in the auth password reset
jacobsfletch Jul 30, 2026
5ccd5bb
chore: keep the int setup in __helpers/shared
jacobsfletch Jul 30, 2026
be45bea
chore: ignore minified hydration errors in e2e console assertions
jacobsfletch Jul 30, 2026
820aca4
chore: keep the test hydration marker out of the shippable tanstack app
jacobsfletch Jul 30, 2026
7e4ab91
chore: correct the tanstack app dir comment in the test bootstrap
jacobsfletch Jul 30, 2026
8fd0439
chore: register a suite's tanstack server functions with the rsc envi…
jacobsfletch Jul 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/e2e.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ const nextSuites: TestConfig[] = [
*/
const tanstackSuites: TestConfig[] = [
{ file: '_community', framework: 'tanstack-start', optional: false, shards: 1 },
{ file: 'auth', framework: 'tanstack-start', optional: false, shards: 1 },
]

export default createE2EConfig([...nextSuites, ...tanstackSuites])
3 changes: 0 additions & 3 deletions app-tanstack/app/__root.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { withPayloadRoot } from '@payloadcms/tanstack-start/client'
import { createRootRoute, HeadContent, Scripts } from '@tanstack/react-router'

import { HydrationMarker } from '../components/HydrationMarker/index.js'

export const Route = createRootRoute({
head: () => ({
links: [
Expand Down Expand Up @@ -35,7 +33,6 @@ function MarketingRoot({ children }: { children: React.ReactNode }) {
</head>
<body>
{children}
<HydrationMarker />
<Scripts />
</body>
</html>
Expand Down
15 changes: 1 addition & 14 deletions app-tanstack/app/_payload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import '@payloadcms/ui/css/app.css'
// `(payload)/custom.css` so the shared "custom CSS" e2e passes on both adapters.
import './custom.css'

import { HydrationMarker } from '../components/HydrationMarker/index.js'
import { getLayoutDataFn, serverFunctionHandler } from './_payload/server.functions.js'

const { component: PayloadProviders, loader } = payloadLayoutRoute({
Expand All @@ -14,18 +13,6 @@ const { component: PayloadProviders, loader } = payloadLayoutRoute({
})

export const Route = createFileRoute('/_payload')({
component: PayloadLayout,
component: PayloadProviders,
loader,
})

// `withPayloadRoot` swaps `__root`'s shell (and its `<HydrationMarker />`) for the
// Payload admin document on `/admin` routes, so the marker must be re-mounted here
// for the Playwright hydration-wait wrapper to fire on admin pages.
function PayloadLayout() {
return (
<>
<PayloadProviders />
<HydrationMarker />
</>
)
}
20 changes: 0 additions & 20 deletions app-tanstack/components/HydrationMarker/index.tsx

This file was deleted.

40 changes: 40 additions & 0 deletions test/__helpers/components/HydrationMarker/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use client'

import { useRouterState } from '@tanstack/react-router'
import { useEffect } from 'react'

/**
* Publishes admin-route readiness on `window.__TANSTACK_HYDRATED__`, which the Playwright
* `goto`/`reload` wrapper installed by `initPage` waits for.
*
* Shell hydration is not a sufficient signal. `AdminPage` renders an RSC payload fetched by
* the route loader, so on a full document load the SSR'd view is torn down ~30ms in and
* re-mounted ~300ms later as different DOM nodes. An interaction landing in that window is
* lost outright — the element it targeted no longer exists — and unlike Next.js there is no
* dehydrated boundary for React to replay the event into.
*
* `status === 'idle'` with no in-flight load means loaders resolved and matches committed,
* i.e. the payload is mounted and owned by React. Tracking router state rather than latching
* on first mount also keeps the flag honest across subsequent navigations.
*
* Production users never see this marker; tests opt in via the Playwright wrapper and read
* the global directly.
*/
export function HydrationMarker() {
// `select` must return a primitive. `useRouterState` re-renders on every reference
// change, so returning an object here loops.
const isReady = useRouterState({
select: (state) => state.status === 'idle' && !state.isLoading && !state.isTransitioning,
})

useEffect(() => {
;(window as unknown as { __TANSTACK_HYDRATED__?: boolean }).__TANSTACK_HYDRATED__ = isReady
}, [isReady])

// Rendered rather than set on `window` so it is in the server HTML from the first byte. The
// Playwright wrapper needs to know it is driving the TanStack app *before* any script has
// run, since that is precisely when it has to decide whether to wait. Only the TanStack test
// apps render this, so it also stands in for `PAYLOAD_FRAMEWORK`, which the CLI runner sets
// but editor test runners do not.
return <div data-tanstack-app hidden />
}
Loading
Loading