@@ -8,10 +8,10 @@ import {
8
8
getRedboxSource ,
9
9
} from 'next-test-utils'
10
10
import type { Request , Response } from 'playwright'
11
- import fs from 'fs-extra'
12
- import nodeFs from 'fs'
13
- import { join } from 'path'
11
+ import fs from 'node:fs/promises'
12
+ import { join } from 'node:path'
14
13
import { outdent } from 'outdent'
14
+ import { setTimeout } from 'node:timers/promises'
15
15
16
16
const GENERIC_RSC_ERROR =
17
17
'Error: An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.'
@@ -540,10 +540,10 @@ describe('app-dir action handling', () => {
540
540
// this triggers a revalidate + redirect in a client component
541
541
await browser . elementById ( 'redirect-revalidate-client' ) . click ( )
542
542
await retry ( async ( ) => {
543
+ expect ( await browser . url ( ) ) . toBe ( `${ next . url } /revalidate?foo=bar` )
544
+
543
545
const newJustPutIt = await browser . elementById ( 'justputit' ) . text ( )
544
546
expect ( newJustPutIt ) . not . toBe ( initialJustPutit )
545
-
546
- expect ( await browser . url ( ) ) . toBe ( `${ next . url } /revalidate?foo=bar` )
547
547
} )
548
548
549
549
// this triggers a revalidate + redirect in a server component
@@ -963,16 +963,21 @@ describe('app-dir action handling', () => {
963
963
if ( isNextStart ) {
964
964
it ( 'should not expose action content in sourcemaps' , async ( ) => {
965
965
// We check all sourcemaps in the `static` folder for sensitive information given that chunking
966
- const sourcemaps = nodeFs
967
- . readdirSync ( join ( next . testDir , '.next' , 'static' ) , {
966
+ const sourcemaps = await fs
967
+ . readdir ( join ( next . testDir , '.next' , 'static' ) , {
968
968
recursive : true ,
969
969
encoding : 'utf8' ,
970
970
} )
971
- . filter ( ( f ) => f . endsWith ( '.js.map' ) )
972
- . map ( ( f ) =>
973
- nodeFs . readFileSync ( join ( next . testDir , '.next' , 'static' , f ) , {
974
- encoding : 'utf8' ,
975
- } )
971
+ . then ( ( files ) =>
972
+ Promise . all (
973
+ files
974
+ . filter ( ( f ) => f . endsWith ( '.js.map' ) )
975
+ . map ( ( f ) =>
976
+ fs . readFile ( join ( next . testDir , '.next' , 'static' , f ) , {
977
+ encoding : 'utf8' ,
978
+ } )
979
+ )
980
+ )
976
981
)
977
982
978
983
expect ( sourcemaps ) . not . toBeEmpty ( )
@@ -1046,23 +1051,22 @@ describe('app-dir action handling', () => {
1046
1051
it ( 'should bundle external libraries if they are on the action layer' , async ( ) => {
1047
1052
await next . fetch ( '/client' )
1048
1053
const pageBundle = await fs . readFile (
1049
- join ( next . testDir , '.next' , 'server' , 'app' , 'client' , 'page.js' )
1054
+ join ( next . testDir , '.next' , 'server' , 'app' , 'client' , 'page.js' ) ,
1055
+ { encoding : 'utf8' }
1050
1056
)
1051
1057
if ( isTurbopack ) {
1052
- const chunkPaths = pageBundle
1053
- . toString ( )
1054
- . matchAll ( / l o a d C h u n k \( " ( [ ^ " ] * ) " \) / g)
1055
- // @ts -ignore
1058
+ const chunkPaths = pageBundle . matchAll ( / l o a d C h u n k \( " ( [ ^ " ] * ) " \) / g)
1056
1059
const reads = [ ...chunkPaths ] . map ( async ( match ) => {
1057
1060
const bundle = await fs . readFile (
1058
- join ( next . testDir , '.next' , ...match [ 1 ] . split ( / [ \\ / ] / g) )
1061
+ join ( next . testDir , '.next' , ...match [ 1 ] . split ( / [ \\ / ] / g) ) ,
1062
+ { encoding : 'utf8' }
1059
1063
)
1060
- return bundle . toString ( ) . includes ( 'node_modules/nanoid/index.js' )
1064
+ return bundle . includes ( 'node_modules/nanoid/index.js' )
1061
1065
} )
1062
1066
1063
1067
expect ( await Promise . all ( reads ) ) . toContain ( true )
1064
1068
} else {
1065
- expect ( pageBundle . toString ( ) ) . toContain ( 'node_modules/nanoid/index.js' )
1069
+ expect ( pageBundle ) . toContain ( 'node_modules/nanoid/index.js' )
1066
1070
}
1067
1071
} )
1068
1072
}
@@ -1526,7 +1530,7 @@ describe('app-dir action handling', () => {
1526
1530
const browser = await next . browser ( '/revalidate' )
1527
1531
await browser . refresh ( )
1528
1532
1529
- const thankYouNext = await browser . elementByCss ( '#thankyounext' ) . text ( )
1533
+ const original = await browser . elementByCss ( '#thankyounext' ) . text ( )
1530
1534
1531
1535
await browser . elementByCss ( '#another' ) . click ( )
1532
1536
await retry ( async ( ) => {
@@ -1535,47 +1539,54 @@ describe('app-dir action handling', () => {
1535
1539
)
1536
1540
} )
1537
1541
1538
- const newThankYouNext = await browser
1539
- . elementByCss ( '#thankyounext' )
1540
- . text ( )
1541
-
1542
- // Should be the same number although in serverless
1543
- // it might be eventually consistent
1542
+ // Should be the same number although in serverless it might be
1543
+ // eventually consistent.
1544
1544
if ( ! isNextDeploy ) {
1545
- expect ( thankYouNext ) . toEqual ( newThankYouNext )
1545
+ await retry ( async ( ) => {
1546
+ const another = await browser . elementByCss ( '#thankyounext' ) . text ( )
1547
+ expect ( another ) . toEqual ( original )
1548
+ } )
1546
1549
}
1547
1550
1548
1551
await browser . elementByCss ( '#back' ) . click ( )
1549
-
1550
- // Should be different
1551
- let revalidatedThankYouNext
1552
1552
await retry ( async ( ) => {
1553
- switch ( type ) {
1554
- case 'tag' :
1555
- await browser . elementByCss ( '#revalidate-thankyounext' ) . click ( )
1556
- break
1557
- case 'path' :
1558
- await browser . elementByCss ( '#revalidate-path' ) . click ( )
1559
- break
1560
- default :
1561
- throw new Error ( `Invalid type: ${ type } ` )
1562
- }
1553
+ expect ( await browser . elementByCss ( '#title' ) . text ( ) ) . toBe ( 'revalidate' )
1554
+ } )
1563
1555
1564
- revalidatedThankYouNext = await browser
1565
- . elementByCss ( '#thankyounext' )
1566
- . text ( )
1556
+ switch ( type ) {
1557
+ case 'tag' :
1558
+ await browser . elementByCss ( '#revalidate-thankyounext' ) . click ( )
1559
+ break
1560
+ case 'path' :
1561
+ await browser . elementByCss ( '#revalidate-path' ) . click ( )
1562
+ break
1563
+ default :
1564
+ throw new Error ( `Invalid type: ${ type } ` )
1565
+ }
1567
1566
1568
- expect ( thankYouNext ) . not . toBe ( revalidatedThankYouNext )
1567
+ // Give some time for it to be revalidated.
1568
+ if ( isNextDeploy ) {
1569
+ await setTimeout ( 5000 )
1570
+ }
1571
+
1572
+ // Should be different
1573
+ let revalidated
1574
+ await retry ( async ( ) => {
1575
+ revalidated = await browser . elementByCss ( '#thankyounext' ) . text ( )
1576
+ expect ( revalidated ) . not . toBe ( original )
1569
1577
} )
1570
1578
1571
1579
await browser . elementByCss ( '#another' ) . click ( )
1580
+ await retry ( async ( ) => {
1581
+ expect ( await browser . elementByCss ( '#title' ) . text ( ) ) . toBe (
1582
+ 'another route'
1583
+ )
1584
+ } )
1572
1585
1573
1586
// The other page should be revalidated too
1574
1587
await retry ( async ( ) => {
1575
- const newThankYouNext = await browser
1576
- . elementByCss ( '#thankyounext' )
1577
- . text ( )
1578
- expect ( revalidatedThankYouNext ) . toBe ( newThankYouNext )
1588
+ const another = await browser . elementByCss ( '#thankyounext' ) . text ( )
1589
+ expect ( another ) . toBe ( revalidated )
1579
1590
} )
1580
1591
}
1581
1592
)
0 commit comments