@@ -16,88 +16,159 @@ function normalizeCodeLocInfo(str) {
1616 )
1717}
1818
19- describe . each ( [ 'default' , 'babelrc' ] ) ( 'react-compiler %s' , ( variant ) => {
20- const dependencies = ( global as any ) . isNextDeploy
21- ? // `link` is incompatible with the npm version used when this test is deployed
22- {
23- 'reference-library' : 'file:./reference-library' ,
24- }
25- : {
26- 'reference-library' : 'link:./reference-library' ,
27- }
28- const { next, isNextDev } = nextTestSetup ( {
29- files :
30- variant === 'babelrc'
31- ? __dirname
32- : {
33- app : new FileRef ( join ( __dirname , 'app' ) ) ,
34- 'next.config.js' : new FileRef ( join ( __dirname , 'next.config.js' ) ) ,
35- 'reference-library' : new FileRef (
36- join ( __dirname , 'reference-library' )
37- ) ,
38- } ,
39-
40- dependencies : {
41- 'babel-plugin-react-compiler' : '19.1.0-rc.2' ,
42- ...dependencies ,
43- } ,
44- } )
45-
46- it ( 'should show an experimental warning' , async ( ) => {
47- await retry ( ( ) => {
48- expect ( next . cliOutput ) . toContain ( 'Experiments (use with caution)' )
49- expect ( stripAnsi ( next . cliOutput ) ) . toContain ( '✓ reactCompiler' )
19+ describe . each ( [ 'default' , 'babelrc' ] as const ) (
20+ 'react-compiler %s' ,
21+ ( variant ) => {
22+ const dependencies = ( global as any ) . isNextDeploy
23+ ? // `link` is incompatible with the npm version used when this test is deployed
24+ {
25+ 'reference-library' : 'file:./reference-library' ,
26+ }
27+ : {
28+ 'reference-library' : 'link:./reference-library' ,
29+ }
30+ const { next, isNextDev, isTurbopack } = nextTestSetup ( {
31+ files :
32+ variant === 'babelrc'
33+ ? __dirname
34+ : {
35+ app : new FileRef ( join ( __dirname , 'app' ) ) ,
36+ 'next.config.js' : new FileRef ( join ( __dirname , 'next.config.js' ) ) ,
37+ 'reference-library' : new FileRef (
38+ join ( __dirname , 'reference-library' )
39+ ) ,
40+ } ,
41+ // TODO: set only config instead once bundlers are consistent
42+ buildArgs : [ '--profile' ] ,
43+ dependencies : {
44+ 'babel-plugin-react-compiler' : '0.0.0-experimental-3fde738-20250918' ,
45+ ...dependencies ,
46+ } ,
47+ } )
48+
49+ it ( 'should show an experimental warning' , async ( ) => {
50+ await retry ( ( ) => {
51+ expect ( next . cliOutput ) . toContain ( 'Experiments (use with caution)' )
52+ expect ( stripAnsi ( next . cliOutput ) ) . toContain ( '✓ reactCompiler' )
53+ } )
5054 } )
51- } )
5255
53- it ( 'should render' , async ( ) => {
54- const browser = await next . browser ( '/' )
56+ it ( 'should memoize Components' , async ( ) => {
57+ const browser = await next . browser ( '/' )
58+
59+ expect ( await browser . eval ( 'window.staticChildRenders' ) ) . toEqual ( 1 )
60+ expect (
61+ await browser . elementByCss ( '[data-testid="parent-commits"]' ) . text ( )
62+ ) . toEqual ( 'Parent commits: 1' )
63+
64+ await browser . elementByCss ( 'button' ) . click ( )
65+ await browser . elementByCss ( 'button' ) . click ( )
66+ await browser . elementByCss ( 'button' ) . click ( )
67+
68+ expect ( await browser . eval ( 'window.staticChildRenders' ) ) . toEqual ( 1 )
69+ expect (
70+ await browser . elementByCss ( '[data-testid="parent-commits"]' ) . text ( )
71+ ) . toEqual ( 'Parent commits: 4' )
72+ } )
73+
74+ it ( 'should work with a library that uses the react-server condition' , async ( ) => {
75+ const outputIndex = next . cliOutput . length
76+ await next . render ( '/library-react-server' )
77+
78+ const cliOutput = stripAnsi ( next . cliOutput . slice ( outputIndex ) )
79+ expect ( cliOutput ) . not . toMatch ( / e r r o r / )
80+ } )
5581
56- await retry ( async ( ) => {
57- const text = await browser
58- . elementByCss ( '#react-compiler-enabled-message' )
82+ it ( 'should work with a library using use client' , async ( ) => {
83+ const outputIndex = next . cliOutput . length
84+ await next . render ( '/library-client' )
85+
86+ const cliOutput = stripAnsi ( next . cliOutput . slice ( outputIndex ) )
87+ expect ( cliOutput ) . not . toMatch ( / e r r o r / )
88+ } )
89+
90+ it ( 'should name functions in dev' , async ( ) => {
91+ const browser = await next . browser ( '/function-naming' )
92+ await browser . waitForElementByCss (
93+ '[data-testid="call-frame"][aria-busy="false"]' ,
94+ 5000
95+ )
96+
97+ const callFrame = await browser
98+ . elementByCss ( '[data-testid="call-frame"]' )
5999 . text ( )
60- expect ( text ) . toMatch ( / R e a c t c o m p i l e r i s e n a b l e d w i t h \d + m e m o s l o t s / )
100+ const functionName =
101+ variant === 'babelrc'
102+ ? // next/babel transpiles away arrow functions defeating the React Compiler naming
103+ 'PageUseEffect'
104+ : // expected naming heuristic from React Compiler. This may change in future.
105+ // Just make sure this is the heuristic from the React Compiler not something else.
106+ 'Page[useEffect()]'
107+ if ( isNextDev ) {
108+ if ( isTurbopack ) {
109+ // FIXME: https://linear.app/vercel/issue/NAR-351
110+ await expect ( browser ) . toDisplayCollapsedRedbox ( `
111+ {
112+ "description": "test-top-frame",
113+ "environmentLabel": null,
114+ "label": "Console Error",
115+ "source": null,
116+ "stack": [
117+ "<FIXME-file-protocol>",
118+ ],
119+ }
120+ ` )
121+ } else {
122+ await expect ( browser ) . toDisplayCollapsedRedbox ( `
123+ {
124+ "description": "test-top-frame",
125+ "environmentLabel": null,
126+ "label": "Console Error",
127+ "source": "app/function-naming/page.tsx (8:19) @ ${ functionName }
128+ > 8 | const error = new Error('test-top-frame')
129+ | ^",
130+ "stack": [
131+ "${ functionName } app/function-naming/page.tsx (8:19)",
132+ ],
133+ }
134+ ` )
135+ }
136+ // We care more about the sourcemapped frame in the Redbox.
137+ // This assertion is only here to show that the negative assertion below is valid.
138+ if ( variant === 'babelrc' ) {
139+ }
140+ expect ( normalizeCodeLocInfo ( callFrame ) ) . toEqual (
141+ ` at ${ functionName } (**)`
142+ )
143+ } else {
144+ expect ( normalizeCodeLocInfo ( callFrame ) ) . not . toEqual (
145+ ` at ${ functionName } (**)`
146+ )
147+ }
61148 } )
62- } )
63-
64- it ( 'should work with a library that uses the react-server condition' , async ( ) => {
65- const outputIndex = next . cliOutput . length
66- await next . render ( '/library-react-server' )
67-
68- const cliOutput = stripAnsi ( next . cliOutput . slice ( outputIndex ) )
69- expect ( cliOutput ) . not . toMatch ( / e r r o r / )
70- } )
71-
72- it ( 'should work with a library using use client' , async ( ) => {
73- const outputIndex = next . cliOutput . length
74- await next . render ( '/library-client' )
75-
76- const cliOutput = stripAnsi ( next . cliOutput . slice ( outputIndex ) )
77- expect ( cliOutput ) . not . toMatch ( / e r r o r / )
78- } )
79-
80- it ( 'throws if the React Compiler is used in a React Server environment' , async ( ) => {
81- const outputIndex = next . cliOutput . length
82- const browser = await next . browser ( '/library-missing-react-server' )
83-
84- const cliOutput = normalizeCodeLocInfo (
85- stripAnsi ( next . cliOutput . slice ( outputIndex ) )
86- )
87- if ( isNextDev ) {
88- // TODO(NDX-663): Unhelpful error message.
89- // Should say that the library should have a react-server entrypoint that doesn't use the React Compiler.
90- expect ( cliOutput ) . toContain (
91- '' +
92- "\n ⨯ TypeError: Cannot read properties of undefined (reading 'H')" +
93- // location not important. Just that this is the only frame.
94- // TODO: Stack should start at product code. Possible React limitation.
95- '\n at Container (**)' +
96- // Will just point to original file location
97- '\n 2 |'
149+
150+ it ( 'throws if the React Compiler is used in a React Server environment' , async ( ) => {
151+ const outputIndex = next . cliOutput . length
152+ const browser = await next . browser ( '/library-missing-react-server' )
153+
154+ const cliOutput = normalizeCodeLocInfo (
155+ stripAnsi ( next . cliOutput . slice ( outputIndex ) )
98156 )
157+ if ( isNextDev ) {
158+ // TODO(NDX-663): Unhelpful error message.
159+ // Should say that the library should have a react-server entrypoint that doesn't use the React Compiler.
160+ expect ( cliOutput ) . toContain (
161+ '' +
162+ "\n ⨯ TypeError: Cannot read properties of undefined (reading 'H')" +
163+ // location not important. Just that this is the only frame.
164+ // TODO: Stack should start at product code. Possible React limitation.
165+ '\n at Container (**)' +
166+ // Will just point to original file location
167+ '\n 2 |'
168+ )
99169
100- await assertHasRedbox ( browser )
101- }
102- } )
103- } )
170+ await assertHasRedbox ( browser )
171+ }
172+ } )
173+ }
174+ )
0 commit comments