Skip to content

feat: remove * and fix crash; refactor useParseRouter hook and add tests#2780

Merged
wwwillchen merged 1 commit intodyad-sh:mainfrom
wwwillchen-bot:agent--1771960379784-1771959504
Feb 24, 2026
Merged

feat: remove * and fix crash; refactor useParseRouter hook and add tests#2780
wwwillchen merged 1 commit intodyad-sh:mainfrom
wwwillchen-bot:agent--1771960379784-1771959504

Conversation

@wwwillchen-bot
Copy link
Copy Markdown
Collaborator

@wwwillchen-bot wwwillchen-bot commented Feb 24, 2026

Summary

  • Refactor useParseRouter hook to improve code organization and maintainability
  • Add comprehensive unit tests for the useParseRouter hook covering navigation state parsing, route matching, and edge cases

Test plan

  • Run npm test to verify all 842 tests pass
  • The new tests in src/__tests__/useParseRouter.test.ts cover various navigation scenarios

πŸ€– Generated with Claude Code


Open with Devin

- Refactor useParseRouter to improve code organization
- Add comprehensive unit tests for useParseRouter hook
- Test navigation state parsing, route matching, and edge cases

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@wwwillchen-bot wwwillchen-bot requested a review from a team February 24, 2026 19:06
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @wwwillchen-bot, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the modularity and testability of the useParseRouter hook. By extracting core route parsing and label generation functionalities into dedicated, exported utility functions, the codebase becomes more organized and easier to maintain. The addition of extensive unit tests for these new utilities ensures the robustness and correctness of the routing logic across different frameworks like React Router and Next.js.

Highlights

  • Refactoring: Refactored the useParseRouter hook by extracting internal route parsing and label building logic into separate, exported utility functions.
  • New Utilities: Introduced three new exported functions: buildRouteLabel for creating human-readable labels, parseRoutesFromRouterFile for parsing React Router configurations, and parseRoutesFromNextFiles for handling Next.js file-based routing.
  • Testing: Added comprehensive unit tests for the newly extracted buildRouteLabel, parseRoutesFromRouterFile, and parseRoutesFromNextFiles functions, covering various routing scenarios and edge cases.
  • Bug Fix/Improvement: Modified parseRoutesFromRouterFile to explicitly skip wildcard routes (* and /*) to prevent potential 'Invalid URL TypeError' issues.
Changelog
  • src/tests/useParseRouter.test.ts
    • Added new unit tests for buildRouteLabel function, verifying correct label generation for various path formats.
    • Added new unit tests for parseRoutesFromRouterFile function, covering parsing of React Router JSX, handling of single quotes, duplicate routes, and exclusion of wildcard routes.
    • Added new unit tests for parseRoutesFromNextFiles function, including tests for Next.js pages router (skipping API routes, special files, and dynamic routes) and app router (handling src/app directory, skipping dynamic segments, and route groups).
  • src/hooks/useParseRouter.ts
    • Extracted the buildLabel helper function into a new exported utility buildRouteLabel.
    • Extracted the setFromRouterFile logic into a new exported utility parseRoutesFromRouterFile.
    • Extracted the setFromNextFiles logic into a new exported utility parseRoutesFromNextFiles.
    • Updated the useEffect hook within useParseRouter to call the newly exported parseRoutesFromNextFiles and parseRoutesFromRouterFile functions.
    • Modified parseRoutesFromRouterFile to filter out wildcard routes (* and /*) to prevent Invalid URL TypeError.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with πŸ‘ and πŸ‘Ž on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@wwwillchen
Copy link
Copy Markdown
Collaborator

@BugBot run

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 24, 2026

Greptile Summary

Refactored useParseRouter hook to extract parsing logic into three testable functions and added comprehensive unit tests.

Key changes:

  • Extracted buildRouteLabel, parseRoutesFromRouterFile, and parseRoutesFromNextFiles as standalone exported functions for better testability
  • Added filtering for wildcard routes (* and /*) that previously caused 'Invalid URL' TypeErrors when clicked
  • Created 225 lines of tests covering all parsing functions with edge cases

Testing:
All parsing logic is now isolated and tested separately, including:

  • React Router parsing with various quote styles and attribute orders
  • Next.js pages router with special file handling (_app.tsx, API routes, dynamic routes)
  • Next.js app router with route groups and src/app variants
  • Edge cases like duplicate routes, null content, and empty results

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The refactoring extracts inline logic into well-tested pure functions without changing behavior, and adds important bug fix for wildcard routes. Comprehensive test coverage validates all edge cases.
  • No files require special attention

Important Files Changed

Filename Overview
src/hooks/useParseRouter.ts Refactored parsing logic into three exported functions (buildRouteLabel, parseRoutesFromRouterFile, parseRoutesFromNextFiles), added wildcard route filtering to prevent TypeError
src/tests/useParseRouter.test.ts Comprehensive test coverage for all three parsing functions, including edge cases like wildcards, dynamic routes, Next.js app router, and route groups

Last reviewed commit: 43be00a

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request successfully refactors the useParseRouter hook by extracting the route parsing logic into three well-defined, exported functions: buildRouteLabel, parseRoutesFromRouterFile, and parseRoutesFromNextFiles. This significantly improves the code's organization, readability, and testability. The addition of comprehensive unit tests for these new functions ensures their correctness and covers various scenarios, including edge cases for both React Router and Next.js file-based routing. This is a positive change for the maintainability of the codebase. The specific comments address minor improvements in regex robustness and code conciseness.


try {
const parsedRoutes: ParsedRoute[] = [];
const routePathsRegex = /<Route\s+(?:[^>]*\s+)?path=["']([^"']+)["']/g;
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.

medium

The regular expression used to extract path attributes in parseRoutesFromRouterFile might be brittle. If a <Route> element contains other attributes that include the string "path=" or if the element prop itself contains a > character before the path attribute, the current regex might misinterpret the path. A more precise regex that explicitly looks for path as an attribute within the tag could improve robustness and prevent potential parsing errors.

Suggested change
const routePathsRegex = /<Route\s+(?:[^>]*\s+)?path=["']([^"']+)["']/g;
const routePathsRegex = /<Route\s+[^>]*?path=["']([^"']+)["'][^>]*?>/g;

Comment on lines +95 to +105
lower === "app/page.tsx" ||
lower === "app/page.jsx" ||
lower === "app/page.js" ||
lower === "app/page.mdx" ||
lower === "app/page.ts" ||
lower === "src/app/page.tsx" ||
lower === "src/app/page.jsx" ||
lower === "src/app/page.js" ||
lower === "src/app/page.mdx" ||
lower === "src/app/page.ts"
) {
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.

medium

The condition for checking app/page.tsx and its variants is quite verbose. This can be simplified using a regular expression for better readability and maintainability.

    if (
      /^(?:src\/)?app\/page\.(?:tsx|jsx|js|mdx|ts)$/i.test(lower)
    ) {

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

βœ… Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 43be00a6ec

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with πŸ‘.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

const path = match[1];
// Skip wildcard/catch-all routes like "*" - they are not valid navigation targets
// and cause 'Invalid URL' TypeError when clicked
if (path === "*" || path === "/*") continue;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep root catch-all routes navigable

The new filter in parseRoutesFromRouterFile drops both "*" and "/*", but only bare "*" is the invalid case for preview navigation (navigateToRoute builds origin + path, so "/*" becomes a valid URL like http://host/*). Excluding "/*" removes the only top-level route in common React Router setups such as <Route path="/*" .../>, leaving the quick-route dropdown empty (it falls back to the β€œLoading routes...” state) even though parsing succeeded.

Useful? React with πŸ‘Β / πŸ‘Ž.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files

Confidence score: 3/5

  • Potential runtime throw in buildRouteLabel when paths are only dynamic segments (e.g., /:id) could break label generation and impact routing UI.
  • Given a concrete, user-impacting edge case with medium severity, this carries some merge risk despite being localized.
  • Pay close attention to src/hooks/useParseRouter.ts - guard .replace after .pop() to avoid undefined crashes.
Prompt for AI agents (all issues)

Check if these issues are valid β€” if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/hooks/useParseRouter.ts">

<violation number="1" location="src/hooks/useParseRouter.ts:21">
P2: `buildRouteLabel` can throw when a route path contains only dynamic segments (e.g., `/:id`) because the second `.replace` runs on `undefined` after `.pop()` returns nothing. Guard the second replace or fall back earlier to avoid runtime errors when parsing routes.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

.filter((segment) => segment && !segment.startsWith(":"))
.pop()
?.replace(/[-_]/g, " ")
.replace(/^\w/, (c) => c.toUpperCase()) || path;
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 24, 2026

Choose a reason for hiding this comment

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

P2: buildRouteLabel can throw when a route path contains only dynamic segments (e.g., /:id) because the second .replace runs on undefined after .pop() returns nothing. Guard the second replace or fall back earlier to avoid runtime errors when parsing routes.

Prompt for AI agents
Check if this issue is valid β€” if so, understand the root cause and fix it. At src/hooks/useParseRouter.ts, line 21:

<comment>`buildRouteLabel` can throw when a route path contains only dynamic segments (e.g., `/:id`) because the second `.replace` runs on `undefined` after `.pop()` returns nothing. Guard the second replace or fall back earlier to avoid runtime errors when parsing routes.</comment>

<file context>
@@ -7,6 +7,127 @@ export interface ParsedRoute {
+        .filter((segment) => segment && !segment.startsWith(":"))
+        .pop()
+        ?.replace(/[-_]/g, " ")
+        .replace(/^\w/, (c) => c.toUpperCase()) || path;
+}
+
</file context>
Suggested change
.replace(/^\w/, (c) => c.toUpperCase()) || path;
?.replace(/^\w/, (c) => c.toUpperCase()) || path;
Fix with Cubic

@github-actions
Copy link
Copy Markdown
Contributor

πŸ” Dyadbot Code Review Summary

Verdict: βœ… YES - Ready to merge

Reviewed by 3 independent agents: Correctness Expert, Code Health Expert, UX Wizard.

This is a clean refactoring PR that extracts internal hook functions into testable utilities with good test coverage. The only behavioral change (filtering wildcard routes) is an improvement that fixes a TypeError.

Issues Summary

No HIGH or MEDIUM issues found.

🟒 Low Priority Notes (4 items)
  • Misleading test name - src/__tests__/useParseRouter.test.ts:89 - Test "should handle path attribute before element" actually tests exact attribute before path, not element before path. The regex [^>]* cannot match past a > inside JSX like <Home />, so element-before-path is not actually supported. Consider renaming to accurately describe what it tests.
  • Wildcard filtering is a behavioral change - src/hooks/useParseRouter.ts:42-44 - The original code did not filter wildcard routes (*, /*). The new code adds this filtering, which is an improvement (fixes Invalid URL TypeError), but should be noted in the PR description as a bug fix rather than purely a refactor.
  • Verbose root page detection - src/hooks/useParseRouter.ts:93-105 - The 10-branch || chain checking root page files could be replaced with a single regex like /^(?:src\/)?app\/page\.(?:js|jsx|ts|tsx|mdx)$/i. Inherited from old code, good to simplify in a follow-up.
  • Missing "why" comment for including dynamic param routes - src/hooks/useParseRouter.ts:42-48 - Wildcard routes are filtered with a clear comment explaining why, but there's no corresponding comment explaining why dynamic param routes (:id) are intentionally kept. The asymmetry could confuse future maintainers.
🚫 Dropped False Positives (5 items)
  • Regex limitation with JSX before path - Dropped: Pre-existing behavior carried over 1:1 from original code, not introduced by this PR
  • Case-sensitive startsWith vs case-insensitive regex - Dropped: File paths from Next.js conventions are always lowercase; too theoretical to matter
  • Dynamic routes shown as clickable navigation targets - Dropped: Pre-existing behavior, not a regression from this refactor
  • buildRouteLabel raw path fallback - Dropped: Pre-existing edge case for paths with only dynamic segments
  • "Loading routes..." empty state - Dropped: Consuming component behavior, out of scope for this PR

Generated by Dyadbot multi-agent code review

@github-actions github-actions bot added the needs-human:review-issue ai agent flagged an issue that requires human review label Feb 24, 2026
@wwwillchen wwwillchen changed the title feat: refactor useParseRouter hook and add tests feat: remove * and fix crash; refactor useParseRouter hook and add tests Feb 24, 2026
@wwwillchen wwwillchen merged commit 374bebc into dyad-sh:main Feb 24, 2026
9 of 11 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🎭 Playwright Test Results

βœ… All tests passed!

OS Passed Flaky Skipped
🍎 macOS 361 2 115
πŸͺŸ Windows 363 4 115

Total: 724 tests passed (6 flaky) (230 skipped)

⚠️ Flaky Tests

🍎 macOS

  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > node.js install flow (passed after 1 retry)

πŸͺŸ Windows

  • chat_mode.spec.ts > chat mode selector - ask mode (passed after 2 retries)
  • chat_tabs.spec.ts > right-click context menu: Close tabs to the right (passed after 1 retry)
  • context_manage.spec.ts > manage context - exclude paths with smart context (passed after 1 retry)
  • setup_flow.spec.ts > Setup Flow > setup banner shows correct state when node.js is installed (passed after 1 retry)

πŸ“Š View full report

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

Labels

needs-human:review-issue ai agent flagged an issue that requires human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants