@@ -19,12 +19,23 @@ let act;
19
19
let assertConsoleErrorDev ;
20
20
let assertLog ;
21
21
let root ;
22
+ let JSDOM ;
22
23
23
24
describe ( 'ReactDOMFiber' , ( ) => {
24
25
let container ;
25
26
26
27
beforeEach ( ( ) => {
27
28
jest . resetModules ( ) ;
29
+
30
+ // JSDOM needs to be setup with a TextEncoder and TextDecoder when used standalone
31
+ // https://github.com/jsdom/jsdom/issues/2524
32
+ ( ( ) => {
33
+ const { TextEncoder, TextDecoder} = require ( 'util' ) ;
34
+ global . TextEncoder = TextEncoder ;
35
+ global . TextDecoder = TextDecoder ;
36
+ JSDOM = require ( 'jsdom' ) . JSDOM ;
37
+ } ) ( ) ;
38
+
28
39
React = require ( 'react' ) ;
29
40
ReactDOM = require ( 'react-dom' ) ;
30
41
PropTypes = require ( 'prop-types' ) ;
@@ -1272,4 +1283,48 @@ describe('ReactDOMFiber', () => {
1272
1283
} ) ;
1273
1284
expect ( didCallOnChange ) . toBe ( true ) ;
1274
1285
} ) ;
1286
+
1287
+ it ( 'should restore selection in the correct window' , async ( ) => {
1288
+ // creating new JSDOM instance to get a second window as window.open is not implemented
1289
+ // https://github.com/jsdom/jsdom/blob/c53efc81e75f38a0558fbf3ed75d30b78b4c4898/lib/jsdom/browser/Window.js#L987
1290
+ const { window : newWindow } = new JSDOM ( '' ) ;
1291
+ // creating a new container since the default cleanup expects the existing container to be in the document
1292
+ const newContainer = newWindow . document . createElement ( 'div' ) ;
1293
+ newWindow . document . body . appendChild ( newContainer ) ;
1294
+ root = ReactDOMClient . createRoot ( newContainer ) ;
1295
+
1296
+ const Test = ( ) => {
1297
+ const [ reverse , setReverse ] = React . useState ( false ) ;
1298
+ const [ items ] = React . useState ( ( ) => [ 'a' , 'b' , 'c' ] ) ;
1299
+ const onClick = ( ) => {
1300
+ setReverse ( true ) ;
1301
+ } ;
1302
+
1303
+ // shuffle the items so that the react commit needs to restore focus
1304
+ // to the correct element after commit
1305
+ const itemsToRender = reverse ? items . reverse ( ) : items ;
1306
+
1307
+ return (
1308
+ < div >
1309
+ { itemsToRender . map ( item => (
1310
+ < button onClick = { onClick } key = { item } id = { item } >
1311
+ { item }
1312
+ </ button >
1313
+ ) ) }
1314
+ </ div >
1315
+ ) ;
1316
+ } ;
1317
+
1318
+ await act ( ( ) => {
1319
+ root . render ( < Test /> ) ;
1320
+ } ) ;
1321
+
1322
+ newWindow . document . getElementById ( 'a' ) . focus ( ) ;
1323
+ await act ( ( ) => {
1324
+ newWindow . document . getElementById ( 'a' ) . click ( ) ;
1325
+ } ) ;
1326
+
1327
+ expect ( newWindow . document . activeElement ) . not . toBe ( newWindow . document . body ) ;
1328
+ expect ( newWindow . document . activeElement . innerHTML ) . toBe ( 'a' ) ;
1329
+ } ) ;
1275
1330
} ) ;
0 commit comments