9
9
} from "@testing-library/react" ;
10
10
import "@testing-library/jest-dom" ;
11
11
import type { FormMethod , Router , RouterInit } from "@remix-run/router" ;
12
+ import { joinPaths } from "@remix-run/router" ;
12
13
import type { RouteObject } from "react-router" ;
13
14
import {
14
15
Await ,
@@ -20,6 +21,7 @@ import {
20
21
createMemoryRouter ,
21
22
createRoutesFromElements ,
22
23
defer ,
24
+ redirect ,
23
25
useActionData ,
24
26
useAsyncError ,
25
27
useAsyncValue ,
@@ -158,6 +160,116 @@ describe("<DataMemoryRouter>", () => {
158
160
` ) ;
159
161
} ) ;
160
162
163
+ it ( "prepends basename to loader/action redirects" , async ( ) => {
164
+ let { container } = render (
165
+ < DataMemoryRouter
166
+ basename = "/my/base/path"
167
+ initialEntries = { [ "/my/base/path" ] }
168
+ >
169
+ < Route path = "/" element = { < Root /> } >
170
+ < Route path = "thing" loader = { ( ) => redirect ( "/other" ) } />
171
+ < Route path = "other" element = { < h1 > Other</ h1 > } />
172
+ </ Route >
173
+ </ DataMemoryRouter >
174
+ ) ;
175
+
176
+ function Root ( ) {
177
+ return (
178
+ < >
179
+ < MemoryNavigate to = "/thing" > Link to thing</ MemoryNavigate >
180
+ < Outlet />
181
+ </ >
182
+ ) ;
183
+ }
184
+
185
+ expect ( getHtml ( container ) ) . toMatchInlineSnapshot ( `
186
+ "<div>
187
+ <a
188
+ href=\\"/my/base/path/thing\\"
189
+ >
190
+ Link to thing
191
+ </a>
192
+ </div>"
193
+ ` ) ;
194
+
195
+ fireEvent . click ( screen . getByText ( "Link to thing" ) ) ;
196
+ await waitFor ( ( ) => screen . getByText ( "Other" ) ) ;
197
+ expect ( getHtml ( container ) ) . toMatchInlineSnapshot ( `
198
+ "<div>
199
+ <a
200
+ href=\\"/my/base/path/thing\\"
201
+ >
202
+ Link to thing
203
+ </a>
204
+ <h1>
205
+ Other
206
+ </h1>
207
+ </div>"
208
+ ` ) ;
209
+ } ) ;
210
+
211
+ it ( "supports relative routing in loader/action redirects" , async ( ) => {
212
+ let { container } = render (
213
+ < DataMemoryRouter
214
+ basename = "/my/base/path"
215
+ initialEntries = { [ "/my/base/path" ] }
216
+ >
217
+ < Route path = "/" element = { < Root /> } >
218
+ < Route path = "parent" element = { < Parent /> } >
219
+ < Route path = "child" loader = { ( ) => redirect ( "../other" ) } />
220
+ < Route path = "other" element = { < h2 > Other</ h2 > } />
221
+ </ Route >
222
+ </ Route >
223
+ </ DataMemoryRouter >
224
+ ) ;
225
+
226
+ function Root ( ) {
227
+ return (
228
+ < >
229
+ < MemoryNavigate to = "/parent/child" > Link to child</ MemoryNavigate >
230
+ < Outlet />
231
+ </ >
232
+ ) ;
233
+ }
234
+
235
+ function Parent ( ) {
236
+ return (
237
+ < >
238
+ < h1 > Parent</ h1 >
239
+ < Outlet />
240
+ </ >
241
+ ) ;
242
+ }
243
+
244
+ expect ( getHtml ( container ) ) . toMatchInlineSnapshot ( `
245
+ "<div>
246
+ <a
247
+ href=\\"/my/base/path/parent/child\\"
248
+ >
249
+ Link to child
250
+ </a>
251
+ </div>"
252
+ ` ) ;
253
+
254
+ fireEvent . click ( screen . getByText ( "Link to child" ) ) ;
255
+ await waitFor ( ( ) => screen . getByText ( "Parent" ) ) ;
256
+ expect ( getHtml ( container ) ) . toMatchInlineSnapshot ( `
257
+ "<div>
258
+ <a
259
+ href=\\"/my/base/path/parent/child\\"
260
+ >
261
+ Link to child
262
+ </a>
263
+ <h1>
264
+ Parent
265
+ </h1>
266
+ <h2>
267
+ Other
268
+ </h2>
269
+ </div>"
270
+ ` ) ;
271
+ } ) ;
272
+
161
273
it ( "renders with hydration data" , async ( ) => {
162
274
let { container } = render (
163
275
< DataMemoryRouter
@@ -2817,6 +2929,11 @@ function MemoryNavigate({
2817
2929
} ) {
2818
2930
let dataRouterContext = React . useContext ( DataRouterContext ) ;
2819
2931
2932
+ let basename = dataRouterContext ?. basename ;
2933
+ if ( basename && basename !== "/" ) {
2934
+ to = to === "/" ? basename : joinPaths ( [ basename , to ] ) ;
2935
+ }
2936
+
2820
2937
let onClickHandler = React . useCallback (
2821
2938
async ( event : React . MouseEvent ) => {
2822
2939
event . preventDefault ( ) ;
0 commit comments