@@ -316,6 +316,90 @@ function defineTest(f: Fixture) {
316316 editor . reset ( )
317317 await expect ( locator ) . toContainText ( '[dep: 1]' )
318318 } )
319+
320+ test ( 'shared hmr basic' , async ( { page } ) => {
321+ await page . goto ( f . url ( ) )
322+ await waitForHydration ( page )
323+ await using _ = await expectNoReload ( page )
324+
325+ // Test initial state
326+ await expect ( page . getByTestId ( 'test-hmr-shared-server' ) ) . toContainText (
327+ '(shared1, shared2)' ,
328+ )
329+ await expect ( page . getByTestId ( 'test-hmr-shared-client' ) ) . toContainText (
330+ '(shared1, shared2)' ,
331+ )
332+
333+ // Test 1: Component HMR (shared1.tsx)
334+ const editor1 = f . createEditor ( 'src/routes/hmr-shared/shared1.tsx' )
335+ editor1 . edit ( ( s ) => s . replace ( 'shared1' , 'shared1-edit' ) )
336+
337+ // Verify both server and client components updated
338+ await expect ( page . getByTestId ( 'test-hmr-shared-server' ) ) . toContainText (
339+ '(shared1-edit, shared2)' ,
340+ )
341+ await expect ( page . getByTestId ( 'test-hmr-shared-client' ) ) . toContainText (
342+ '(shared1-edit, shared2)' ,
343+ )
344+
345+ editor1 . reset ( )
346+ await expect ( page . getByTestId ( 'test-hmr-shared-server' ) ) . toContainText (
347+ '(shared1, shared2)' ,
348+ )
349+ await expect ( page . getByTestId ( 'test-hmr-shared-client' ) ) . toContainText (
350+ '(shared1, shared2)' ,
351+ )
352+
353+ // Test 2: Non-component HMR (shared2.tsx)
354+ const editor2 = f . createEditor ( 'src/routes/hmr-shared/shared2.tsx' )
355+ editor2 . edit ( ( s ) => s . replace ( 'shared2' , 'shared2-edit' ) )
356+
357+ // Verify both server and client components updated
358+ await expect ( page . getByTestId ( 'test-hmr-shared-server' ) ) . toContainText (
359+ '(shared1, shared2-edit)' ,
360+ )
361+ await expect ( page . getByTestId ( 'test-hmr-shared-client' ) ) . toContainText (
362+ '(shared1, shared2-edit)' ,
363+ )
364+
365+ editor2 . reset ( )
366+ await expect ( page . getByTestId ( 'test-hmr-shared-server' ) ) . toContainText (
367+ '(shared1, shared2)' ,
368+ )
369+ await expect ( page . getByTestId ( 'test-hmr-shared-client' ) ) . toContainText (
370+ '(shared1, shared2)' ,
371+ )
372+ } )
373+
374+ // for this use case to work, server refetch/render and client hmr needs to applied atomically
375+ // at the same time. Next.js doesn't seem to support this either.
376+ // https://github.com/hi-ogawa/reproductions/tree/main/next-rsc-hmr-shared-module
377+ test ( 'shared hmr not atomic' , async ( { page } ) => {
378+ await page . goto ( f . url ( ) )
379+ await waitForHydration ( page )
380+ await expect ( page . getByTestId ( 'test-hmr-shared-atomic' ) ) . toContainText (
381+ 'ok (test-shared)' ,
382+ )
383+
384+ // non-atomic update causes an error
385+ const editor = f . createEditor ( 'src/routes/hmr-shared/atomic/shared.tsx' )
386+ editor . edit ( ( s ) => s . replace ( 'test-shared' , 'test-shared-edit' ) )
387+ await expect ( page . getByTestId ( 'test-hmr-shared-atomic' ) ) . toContainText (
388+ 'ErrorBoundary' ,
389+ )
390+
391+ await page . reload ( )
392+ await expect ( page . getByText ( 'ok (test-shared-edit)' ) ) . toBeVisible ( )
393+
394+ // non-atomic update causes an error
395+ editor . reset ( )
396+ await expect ( page . getByTestId ( 'test-hmr-shared-atomic' ) ) . toContainText (
397+ 'ErrorBoundary' ,
398+ )
399+
400+ await page . reload ( )
401+ await expect ( page . getByText ( 'ok (test-shared)' ) ) . toBeVisible ( )
402+ } )
319403 } )
320404
321405 test ( 'css @js' , async ( { page } ) => {
0 commit comments