Skip to content

chore: stabilize tests#6492

Merged
schiller-manuel merged 3 commits intomainfrom
stabilize-tests
Feb 20, 2026
Merged

chore: stabilize tests#6492
schiller-manuel merged 3 commits intomainfrom
stabilize-tests

Conversation

@schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Jan 24, 2026

Summary by CodeRabbit

  • Tests
    • Simplified CSS module tests across React, Solid, and Vue to use direct immediate assertions instead of retry wrappers.
    • Removed per-test warmup that opened a real browser context and related retry scaffolding.
    • Added server readiness checks and a centralized dev-server pre-warm during test setup (only in dev mode).
    • Streamlined initialization for more deterministic style and navigation verifications.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 24, 2026

📝 Walkthrough

Walkthrough

Centralizes Vite dev-server warmup into shared global setup: adds waitForServer and preOptimizeDevServer helpers that pre-optimize dependencies via a headless browser when MODE=dev, and removes per-test warmup and retry scaffolding from React, Solid, and Vue CSS module specs.

Changes

Cohort / File(s) Summary
CSS Module Test Specs
e2e/react-start/css-modules/tests/css.spec.ts, e2e/solid-start/css-modules/tests/css.spec.ts, e2e/vue-start/css-modules/tests/css.spec.ts
Removed per-test beforeAll warmup that opened real browser contexts. Replaced retry-wrapped toPass/retry assertions with immediate style/visibility assertions and simplified navigation/wait logic.
Global Setup Helpers
e2e/react-start/css-modules/tests/setup/global.setup.ts, e2e/solid-start/css-modules/tests/setup/global.setup.ts, e2e/vue-start/css-modules/tests/setup/global.setup.ts
Added waitForServer(url) (polls up to 30s) and preOptimizeDevServer(baseURL) (launches headless Chromium, navigates routes, waits for selectors/network idle, ensures stable URL). setup() now computes test port/baseURL, waits for server readiness, and runs pre-optimization when MODE==='dev'. Attention: Chromium usage and server-poll timeout.

Sequence Diagram(s)

sequenceDiagram
  participant Setup as Test Global Setup
  participant Dev as Dev Server
  participant Browser as Headless Chromium
  participant Tests as E2E Test Runner

  Setup->>Dev: waitForServer(baseURL) (poll until 2xx/3xx)
  alt server reachable
    Setup->>Browser: preOptimizeDevServer(baseURL) (launch headless)
    Browser->>Dev: GET /, /modules, /sass-mixin, /quotes
    Dev-->>Browser: HTML + assets (triggers Vite dep optimization)
    Browser->>Browser: waitFor selectors & network idle
    Browser->>Setup: confirm stable URL/state
    Browser-->>Browser: close context
    Setup->>Tests: proceed with tests (no per-test warmup)
  else timeout
    Dev-->>Setup: no response -> throw timeout
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Suggested labels

package: react-router, package: solid-router, package: vue-router

Poem

🐰 I hopped through routes to warm the brew,

Launched a headless friend to see it through.
No more retries, just steady light—
Tests march on, all tidy and bright.
A carrot dance for CI tonight! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'chore: stabilize tests' directly reflects the main objective of the PR, which is to stabilize E2E tests across multiple frameworks by introducing dev server pre-warming and removing flaky retry-based assertions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stabilize-tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Jan 24, 2026

View your CI Pipeline Execution ↗ for commit edd68d9

Command Status Duration Result
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 37s View ↗
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 1m 12s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-20 00:09:50 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 24, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6492

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6492

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6492

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6492

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6492

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6492

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6492

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6492

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6492

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6492

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6492

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6492

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6492

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6492

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6492

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6492

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6492

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6492

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6492

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6492

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6492

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6492

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6492

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6492

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6492

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6492

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6492

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6492

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6492

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6492

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6492

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6492

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6492

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6492

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6492

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6492

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6492

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6492

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6492

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6492

commit: edd68d9

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@e2e/react-start/css-modules/tests/setup/global.setup.ts`:
- Around line 8-19: The waitForServer function currently only treats 2xx
responses as success and has no per-attempt timeout; update waitForServer to
create an AbortController for each fetch attempt, set a short per-attempt
timeout (e.g. 5s) that calls controller.abort(), and clear that timer after the
fetch completes; change the success condition from res.ok to accept any 2xx or
3xx status (status >= 200 && status < 400) so redirects count as a successful
server response, and ensure aborted/other fetch errors are caught and ignored so
the retry loop continues.

In `@e2e/solid-start/css-modules/tests/setup/global.setup.ts`:
- Around line 8-19: The waitForServer function can hang because fetch calls may
never resolve; modify waitForServer to create an AbortController for each
iteration, pass controller.signal into fetch(url, { redirect: 'manual', signal
}), and start a per-attempt timer (e.g., 2000–3000ms) that calls
controller.abort() when expired; ensure you clear the timer after fetch
completes and keep the existing try/catch so aborted or network errors are
ignored and the loop retries, then preserve the final timeout error behavior.

In `@e2e/vue-start/css-modules/tests/setup/global.setup.ts`:
- Around line 8-19: In waitForServer, add a per-attempt AbortController and a
short timeout (e.g., 2–5s) so each fetch call cannot hang indefinitely: for each
loop iteration create an AbortController, pass controller.signal to fetch(url, {
redirect: 'manual', signal }), set a timer to call controller.abort() after the
short interval, and clear that timer after the fetch finishes or throws; keep
the existing retry loop behavior and ensure aborted fetches are caught and
ignored as before before retrying.

Comment on lines 8 to 19
async function waitForServer(url: string) {
const start = Date.now()
while (Date.now() - start < 30_000) {
try {
const res = await fetch(url, { redirect: 'manual' })
if (res.ok) return
} catch {
// ignore
}
await new Promise((r) => setTimeout(r, 250))
}
throw new Error(`Timed out waiting for dev server at ${url}`)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n e2e/solid-start/css-modules/tests/setup/global.setup.ts | sed -n '1,30p'

Repository: TanStack/router

Length of output: 1211


🌐 Web query:

MDN fetch API res.ok status codes 3xx redirects

💡 Result:

  • Response.ok is only true for HTTP 200–299; 3xx (redirect) status codes are not “ok” (so ok === false for a 3xx response). [1]
  • In browsers, fetch() uses redirect: "follow" by default, so if the server returns a 3xx, fetch() typically follows the redirect and resolves with the final response (often 200), where response.ok may be true. You can detect that a redirect happened with response.redirected === true (and response.url will be the final URL). [2] [3]
  • You can control redirect handling with the request’s redirect mode: "follow" (default), "error", or "manual". Setting redirect: "error" is the recommended way to disallow redirects. [3] [4]

Sources:
[1] MDN: Response.ok — status in the range 200–299 https://developer.mozilla.org/en-US/docs/Web/API/Response/ok
[2] MDN: Response.redirected (detect redirects, final response.url) https://developer.mozilla.org/en-US/docs/Web/API/Response/redirected
[3] MDN: Request.redirect (follow/error/manual; default follow) https://developer.mozilla.org/en-US/docs/Web/API/Request/redirect
[4] MDN: fetch() resolves on HTTP error statuses; check ok/status https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch


Add per-attempt timeout to prevent hanging fetch calls in waitForServer.

With redirect: 'manual' in effect, a 3xx response is returned as-is and will fail the res.ok check, simply retrying rather than hanging. However, the fetch call itself can hang indefinitely if the server is unresponsive, stalling the loop. Add an abort timeout (e.g., 2–3 seconds) per fetch attempt to ensure robustness.

🛠️ Suggested fix
 async function waitForServer(url: string) {
   const start = Date.now()
   while (Date.now() - start < 30_000) {
+    const controller = new AbortController()
+    const timeout = setTimeout(() => controller.abort(), 2_000)
     try {
-      const res = await fetch(url, { redirect: 'manual' })
+      const res = await fetch(url, {
+        redirect: 'manual',
+        signal: controller.signal,
+      })
       if (res.ok) return
     } catch {
       // ignore
+    } finally {
+      clearTimeout(timeout)
     }
     await new Promise((r) => setTimeout(r, 250))
   }
   throw new Error(`Timed out waiting for dev server at ${url}`)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function waitForServer(url: string) {
const start = Date.now()
while (Date.now() - start < 30_000) {
try {
const res = await fetch(url, { redirect: 'manual' })
if (res.ok) return
} catch {
// ignore
}
await new Promise((r) => setTimeout(r, 250))
}
throw new Error(`Timed out waiting for dev server at ${url}`)
async function waitForServer(url: string) {
const start = Date.now()
while (Date.now() - start < 30_000) {
const controller = new AbortController()
const timeout = setTimeout(() => controller.abort(), 2_000)
try {
const res = await fetch(url, {
redirect: 'manual',
signal: controller.signal,
})
if (res.ok) return
} catch {
// ignore
} finally {
clearTimeout(timeout)
}
await new Promise((r) => setTimeout(r, 250))
}
throw new Error(`Timed out waiting for dev server at ${url}`)
}
🤖 Prompt for AI Agents
In `@e2e/solid-start/css-modules/tests/setup/global.setup.ts` around lines 8 - 19,
The waitForServer function can hang because fetch calls may never resolve;
modify waitForServer to create an AbortController for each iteration, pass
controller.signal into fetch(url, { redirect: 'manual', signal }), and start a
per-attempt timer (e.g., 2000–3000ms) that calls controller.abort() when
expired; ensure you clear the timer after fetch completes and keep the existing
try/catch so aborted or network errors are ignored and the loop retries, then
preserve the final timeout error behavior.

@schiller-manuel schiller-manuel merged commit 4ec6f50 into main Feb 20, 2026
5 of 6 checks passed
@schiller-manuel schiller-manuel deleted the stabilize-tests branch February 20, 2026 00:11
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@e2e/vue-start/css-modules/tests/setup/global.setup.ts`:
- Around line 14-19: In waitForServer, when fetching with redirect: 'manual' the
code currently only accepts res.ok (2xx) which rejects valid 3xx redirect
responses; update the success check in the try block (the fetch result handling
near the fetch call using controller.signal and redirect: 'manual') to accept
any 2xx or 3xx by changing the condition to check res.status >= 200 &&
res.status < 400 so redirects are treated as successful server readiness.

Comment on lines +14 to +19
const res = await fetch(url, {
redirect: 'manual',
signal: controller.signal,
})
if (res.ok) return
} catch {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check vue css-modules config for redirects (basePath/trailing slash)
rg -n "basepath|basePath|redirect|trailingSlash" e2e/vue-start/css-modules -A 3

# Compare waitForServer implementations across css-modules suites
echo "=== Comparing waitForServer across css-modules setups ==="
rg -n "waitForServer" e2e/*/css-modules/tests/setup/global.setup.ts -A 10 -B 2

Repository: TanStack/router

Length of output: 5278


🏁 Script executed:

#!/bin/bash
# Find config files in vue css-modules
fd -e "ts" -e "tsx" -e "json" -e "config" "e2e/vue-start/css-modules" | head -20

# Check for basePath/trailingSlash in config files
rg -n "basePath|trailingSlash" e2e/vue-start/css-modules -t ts -t json -t tsx

Repository: TanStack/router

Length of output: 492


🏁 Script executed:

#!/bin/bash
# Find config files in vue css-modules
fd . 'e2e/vue-start/css-modules' --type f | head -20

# Check for basePath/trailingSlash in config files
rg -n "basePath|trailingSlash" 'e2e/vue-start/css-modules' -t ts -t json

Repository: TanStack/router

Length of output: 876


🏁 Script executed:

#!/bin/bash
# Check vite.config.ts for base path config
cat -n 'e2e/vue-start/css-modules/vite.config.ts'

# Check router.tsx for any redirect-related config
cat -n 'e2e/vue-start/css-modules/src/router.tsx'

Repository: TanStack/router

Length of output: 892


🏁 Script executed:

#!/bin/bash
# Check if Solid css-modules also has the issue
cat -n 'e2e/solid-start/css-modules/vite.config.ts'

# Check the full waitForServer function in all three to see any differences
echo "=== Vue waitForServer full function ==="
sed -n '8,25p' 'e2e/vue-start/css-modules/tests/setup/global.setup.ts'

echo "=== React waitForServer full function ==="
sed -n '8,25p' 'e2e/react-start/css-modules/tests/setup/global.setup.ts'

Repository: TanStack/router

Length of output: 1715


Accept 2xx/3xx redirect responses for consistent server readiness checks.

The waitForServer function uses redirect: 'manual' to prevent automatic redirect following, but then only accepts 2xx responses with res.ok. A 3xx response won't satisfy this condition, causing needless retries even when the server is healthy. The React css-modules setup already uses if (res.status >= 200 && res.status < 400) return to handle this correctly—apply the same pattern for consistency and robustness across all frameworks.

🛠️ Suggested fix
-      if (res.ok) return
+      if (res.status >= 200 && res.status < 400) return
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/vue-start/css-modules/tests/setup/global.setup.ts` around lines 14 - 19,
In waitForServer, when fetching with redirect: 'manual' the code currently only
accepts res.ok (2xx) which rejects valid 3xx redirect responses; update the
success check in the try block (the fetch result handling near the fetch call
using controller.signal and redirect: 'manual') to accept any 2xx or 3xx by
changing the condition to check res.status >= 200 && res.status < 400 so
redirects are treated as successful server readiness.

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.

1 participant

Comments