@@ -230,7 +230,6 @@ describe('ref swapping', () => {
230230 expect ( refHopsAround . refs . divThreeRef ) . toEqual ( thirdDiv ) ;
231231 } ) ;
232232
233-
234233 it ( 'always has a value for this.refs' , ( ) => {
235234 class Component extends React . Component {
236235 render ( ) {
@@ -392,3 +391,91 @@ describe('string refs between fiber and stack', () => {
392391 }
393392 } ) ;
394393} ) ;
394+
395+ describe ( 'root level refs' , ( ) => {
396+ it ( 'attaches and detaches root refs in stack' , ( ) => {
397+ assertForRenderer ( 'ReactDOM' ) ;
398+ } ) ;
399+
400+ it ( 'attaches and detaches root refs in fiber' , ( ) => {
401+ assertForRenderer ( 'ReactDOMFiber' ) ;
402+ } ) ;
403+
404+ const assertForRenderer = ( which ) => {
405+ const Renderer = require ( which ) ;
406+ spyOn ( console , 'error' ) ;
407+ var inst = null ;
408+
409+ // host node
410+ var ref = jest . fn ( value => inst = value ) ;
411+ var container = document . createElement ( 'div' ) ;
412+ var result = Renderer . render ( < div ref = { ref } /> , container ) ;
413+ expect ( ref ) . toHaveBeenCalledTimes ( 1 ) ;
414+ expect ( ref . mock . calls [ 0 ] [ 0 ] ) . toBeInstanceOf ( HTMLDivElement ) ;
415+ expect ( result ) . toBe ( ref . mock . calls [ 0 ] [ 0 ] ) ;
416+ Renderer . unmountComponentAtNode ( container ) ;
417+ expect ( ref ) . toHaveBeenCalledTimes ( 2 ) ;
418+ expect ( ref . mock . calls [ 1 ] [ 0 ] ) . toBe ( null ) ;
419+
420+ // composite
421+ class Comp extends React . Component {
422+ method ( ) {
423+ return true ;
424+ }
425+ render ( ) {
426+ return < div > Comp</ div > ;
427+ }
428+ }
429+
430+ inst = null ;
431+ ref = jest . fn ( value => inst = value ) ;
432+ result = Renderer . render ( < Comp ref = { ref } /> , container ) ;
433+
434+ expect ( ref ) . toHaveBeenCalledTimes ( 1 ) ;
435+ expect ( inst ) . toBeInstanceOf ( Comp ) ;
436+ expect ( result ) . toBe ( inst ) ;
437+
438+ // ensure we have the correct instance
439+ expect ( result . method ( ) ) . toBe ( true ) ;
440+ expect ( inst . method ( ) ) . toBe ( true ) ;
441+
442+ Renderer . unmountComponentAtNode ( container ) ;
443+ expect ( ref ) . toHaveBeenCalledTimes ( 2 ) ;
444+ expect ( ref . mock . calls [ 1 ] [ 0 ] ) . toBe ( null ) ;
445+
446+ if ( which === 'ReactDOMFiber' ) {
447+ // fragment
448+ inst = null ;
449+ ref = jest . fn ( value => inst = value ) ;
450+ var divInst = null ;
451+ var ref2 = jest . fn ( value => divInst = value ) ;
452+ result = Renderer . render ( [
453+ < Comp ref = { ref } /> ,
454+ 5 ,
455+ < div ref = { ref2 } > Hello</ div > ,
456+ ] , container ) ;
457+
458+ // first call should be `Comp`
459+ expect ( ref ) . toHaveBeenCalledTimes ( 1 ) ;
460+ expect ( ref . mock . calls [ 0 ] [ 0 ] ) . toBeInstanceOf ( Comp ) ;
461+ expect ( result ) . toBe ( ref . mock . calls [ 0 ] [ 0 ] ) ;
462+
463+ expect ( ref2 ) . toHaveBeenCalledTimes ( 1 ) ;
464+ expect ( divInst ) . toBeInstanceOf ( HTMLDivElement ) ;
465+ expect ( result ) . not . toBe ( divInst ) ;
466+ Renderer . unmountComponentAtNode ( container ) ;
467+ expect ( ref ) . toHaveBeenCalledTimes ( 2 ) ;
468+ expect ( ref . mock . calls [ 1 ] [ 0 ] ) . toBe ( null ) ;
469+ expect ( ref2 ) . toHaveBeenCalledTimes ( 2 ) ;
470+ expect ( ref2 . mock . calls [ 1 ] [ 0 ] ) . toBe ( null ) ;
471+
472+ // null
473+ result = Renderer . render ( null , container ) ;
474+ expect ( result ) . toBe ( null ) ;
475+
476+ // primitives
477+ // result = Renderer.render(5, container);
478+ // expect(result).toBe('5');
479+ }
480+ } ;
481+ } ) ;
0 commit comments