From f53a88730a03d9837097195ae4e4a82ff90026b8 Mon Sep 17 00:00:00 2001 From: Woyken <13166802+Woyken@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:24:03 +0300 Subject: [PATCH 1/4] fix(solid-router): RouteProvider Wrap and Match InnerWrap support propagating context to their children --- packages/solid-router/src/Matches.tsx | 34 ++++--- packages/solid-router/src/RouterProvider.tsx | 19 ++-- packages/solid-router/tests/Matches.test.tsx | 99 +++++++++++++++++++ .../tests/RouterProvider.test.tsx | 35 +++++++ 4 files changed, 161 insertions(+), 26 deletions(-) create mode 100644 packages/solid-router/tests/RouterProvider.test.tsx diff --git a/packages/solid-router/src/Matches.tsx b/packages/solid-router/src/Matches.tsx index cf83c6b506..f9fa1d34f7 100644 --- a/packages/solid-router/src/Matches.tsx +++ b/packages/solid-router/src/Matches.tsx @@ -38,27 +38,27 @@ declare module '@tanstack/router-core' { export function Matches() { const router = useRouter() - const pendingElement = router.options.defaultPendingComponent ? ( - - ) : null - // Do not render a root Suspense during SSR or hydrating from SSR const ResolvedSuspense = router.isServer || (typeof document !== 'undefined' && router.ssr) ? SafeFragment : Solid.Suspense - const inner = ( - - {!router.isServer && } - - - ) + const OptionalWrapper = router.options.InnerWrap || SafeFragment - return router.options.InnerWrap ? ( - {inner} - ) : ( - inner + return ( + + + ) : null + } + > + {!router.isServer && } + + + ) } @@ -74,8 +74,10 @@ function MatchesInner() { select: (s) => s.loadedAt, }) - const matchComponent = () => - matchId() ? : null + const matchComponent = () => { + const id = matchId() + return id ? : null + } return ( diff --git a/packages/solid-router/src/RouterProvider.tsx b/packages/solid-router/src/RouterProvider.tsx index 1f579a0a4f..7fee86bcf7 100644 --- a/packages/solid-router/src/RouterProvider.tsx +++ b/packages/solid-router/src/RouterProvider.tsx @@ -1,5 +1,6 @@ import { Matches } from './Matches' import { getRouterContext } from './routerContext' +import { SafeFragment } from './SafeFragment' import type * as Solid from 'solid-js' import type { AnyRouter, @@ -29,17 +30,15 @@ export function RouterContextProvider< const routerContext = getRouterContext() - const provider = ( - - {children()} - - ) - - if (router.options.Wrap) { - return {provider} - } + const OptionalWrapper = router.options.Wrap || SafeFragment - return provider + return ( + + + {children()} + + + ) } export function RouterProvider< diff --git a/packages/solid-router/tests/Matches.test.tsx b/packages/solid-router/tests/Matches.test.tsx index b7242fed00..0dca4bc661 100644 --- a/packages/solid-router/tests/Matches.test.tsx +++ b/packages/solid-router/tests/Matches.test.tsx @@ -1,15 +1,18 @@ import { expect, test } from 'vitest' import { fireEvent, render, screen } from '@solidjs/testing-library' +import { createContext, useContext } from 'solid-js' import { Link, Outlet, RouterProvider, + createMemoryHistory, createRootRoute, createRoute, createRouter, isMatch, useMatches, } from '../src' +import { sleep } from './utils' const rootRoute = createRootRoute() @@ -122,3 +125,99 @@ test('when filtering useMatches by loaderData', async () => { expect(await screen.findByText('Incorrect Matches -')).toBeInTheDocument() }) + +test('Matches provides InnerWrap context to route components', async () => { + const rootRoute = createRootRoute({ + component: () => { + const contextValue = useContext(ctx) + expect(contextValue, 'Context is not provided').not.toBeUndefined() + + return
{contextValue}
+ }, + }) + + const routeTree = rootRoute.addChildren([]) + const router = createRouter({ + routeTree, + }) + + const ctx = createContext() + + const screen = render(() => ( + { + return ( + + {props.children} + + ) + }} + /> + )) + + const indexElem = await screen.findByText('context-for-children') + expect(indexElem).toBeInTheDocument() +}) + +test('Matches provides InnerWrap context to defaultPendingComponent', async () => { + const rootRoute = createRootRoute({}) + const indexRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/', + component: () => { + return ( +
+ link to home +
+ ) + }, + }) + + const homeRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/home', + loader: () => sleep(300), + component: () =>
Home page
, + }) + + const routeTree = rootRoute.addChildren([homeRoute, indexRoute]) + const router = createRouter({ + routeTree, + history: createMemoryHistory({ + initialEntries: ['/'], + }), + }) + + const ctx = createContext() + + const screen = render(() => ( + { + const contextValue = useContext(ctx) + expect(contextValue, 'Context is not provided').not.toBeUndefined() + + return
{contextValue}
+ }} + InnerWrap={(props) => { + return ( + + {props.children} + + ) + }} + /> + )) + + const linkToHome = await screen.findByRole('link', { + name: 'link to home', + }) + expect(linkToHome).toBeInTheDocument() + + fireEvent.click(linkToHome) + + const indexElem = await screen.findByText('context-for-default-pending') + expect(indexElem).toBeInTheDocument() +}) diff --git a/packages/solid-router/tests/RouterProvider.test.tsx b/packages/solid-router/tests/RouterProvider.test.tsx new file mode 100644 index 0000000000..a6f0d49cdf --- /dev/null +++ b/packages/solid-router/tests/RouterProvider.test.tsx @@ -0,0 +1,35 @@ +import { describe, expect, it } from 'vitest' +import { render, screen } from '@solidjs/testing-library' +import { createContext, useContext } from 'solid-js' +import { + createRootRoute, + createRouter, +} from '../src' +import { RouterProvider } from '../src/RouterProvider' + +describe('RouterProvider', () => { + it('should provide context through RouterProvider Wrap', async () => { + const rootRoute = createRootRoute({ + component: () => { + const contextValue = useContext(ctx) + expect(contextValue, "Context is not provided").not.toBeUndefined() + + return
{contextValue}
+ }, + }) + + const routeTree = rootRoute.addChildren([]) + const router = createRouter({ + routeTree, + }) + + const ctx = createContext() + + render(() => { + return {props.children} + }} />) + + const indexElem = await screen.findByText('findMe') + expect(indexElem).toBeInTheDocument() + }) +}) From 966534a8f2ac12d6a2f70f206394fce2f2888ef5 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 13:31:06 +0000 Subject: [PATCH 2/4] ci: apply automated fixes --- .../solid-router/tests/RouterProvider.test.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/solid-router/tests/RouterProvider.test.tsx b/packages/solid-router/tests/RouterProvider.test.tsx index a6f0d49cdf..a74f5fc0f5 100644 --- a/packages/solid-router/tests/RouterProvider.test.tsx +++ b/packages/solid-router/tests/RouterProvider.test.tsx @@ -1,10 +1,7 @@ import { describe, expect, it } from 'vitest' import { render, screen } from '@solidjs/testing-library' import { createContext, useContext } from 'solid-js' -import { - createRootRoute, - createRouter, -} from '../src' +import { createRootRoute, createRouter } from '../src' import { RouterProvider } from '../src/RouterProvider' describe('RouterProvider', () => { @@ -12,7 +9,7 @@ describe('RouterProvider', () => { const rootRoute = createRootRoute({ component: () => { const contextValue = useContext(ctx) - expect(contextValue, "Context is not provided").not.toBeUndefined() + expect(contextValue, 'Context is not provided').not.toBeUndefined() return
{contextValue}
}, @@ -25,9 +22,14 @@ describe('RouterProvider', () => { const ctx = createContext() - render(() => { - return {props.children} - }} />) + render(() => ( + { + return {props.children} + }} + /> + )) const indexElem = await screen.findByText('findMe') expect(indexElem).toBeInTheDocument() From ec9296e5d4dec12d9976fc8e449b2c3c4da42593 Mon Sep 17 00:00:00 2001 From: Woyken <13166802+Woyken@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:55:26 +0300 Subject: [PATCH 3/4] rename rendered screen to app --- packages/solid-router/tests/Matches.test.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/solid-router/tests/Matches.test.tsx b/packages/solid-router/tests/Matches.test.tsx index 0dca4bc661..6f0f865a1b 100644 --- a/packages/solid-router/tests/Matches.test.tsx +++ b/packages/solid-router/tests/Matches.test.tsx @@ -143,7 +143,7 @@ test('Matches provides InnerWrap context to route components', async () => { const ctx = createContext() - const screen = render(() => ( + const app = render(() => ( { @@ -156,7 +156,7 @@ test('Matches provides InnerWrap context to route components', async () => { /> )) - const indexElem = await screen.findByText('context-for-children') + const indexElem = await app.findByText('context-for-children') expect(indexElem).toBeInTheDocument() }) @@ -191,7 +191,7 @@ test('Matches provides InnerWrap context to defaultPendingComponent', async () = const ctx = createContext() - const screen = render(() => ( + const app = render(() => ( )) - const linkToHome = await screen.findByRole('link', { + const linkToHome = await app.findByRole('link', { name: 'link to home', }) expect(linkToHome).toBeInTheDocument() fireEvent.click(linkToHome) - const indexElem = await screen.findByText('context-for-default-pending') + const indexElem = await app.findByText('context-for-default-pending') expect(indexElem).toBeInTheDocument() }) From ee016969d1f4117a83448b39c953d2f65aa559fb Mon Sep 17 00:00:00 2001 From: Woyken <13166802+Woyken@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:56:43 +0300 Subject: [PATCH 4/4] cleanup nitpicks for RouterProvider test --- packages/solid-router/tests/RouterProvider.test.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/solid-router/tests/RouterProvider.test.tsx b/packages/solid-router/tests/RouterProvider.test.tsx index a74f5fc0f5..2bc3395515 100644 --- a/packages/solid-router/tests/RouterProvider.test.tsx +++ b/packages/solid-router/tests/RouterProvider.test.tsx @@ -1,11 +1,13 @@ import { describe, expect, it } from 'vitest' -import { render, screen } from '@solidjs/testing-library' +import { render } from '@solidjs/testing-library' import { createContext, useContext } from 'solid-js' import { createRootRoute, createRouter } from '../src' import { RouterProvider } from '../src/RouterProvider' describe('RouterProvider', () => { it('should provide context through RouterProvider Wrap', async () => { + const ctx = createContext() + const rootRoute = createRootRoute({ component: () => { const contextValue = useContext(ctx) @@ -20,9 +22,7 @@ describe('RouterProvider', () => { routeTree, }) - const ctx = createContext() - - render(() => ( + const app = render(() => ( { @@ -31,7 +31,7 @@ describe('RouterProvider', () => { /> )) - const indexElem = await screen.findByText('findMe') + const indexElem = await app.findByText('findMe') expect(indexElem).toBeInTheDocument() }) })