11import * as React from 'react' ;
22import PropTypes from 'prop-types' ;
33import * as ReactDOMClient from 'react-dom/client' ;
4- import { BrowserRouter as Router , Routes , Route , Link } from 'react-router-dom' ;
4+ import { BrowserRouter as Router , Routes , Route , Link , useNavigate } from 'react-router-dom' ;
55import webfontloader from 'webfontloader' ;
66import { Globals } from '@react-spring/web' ;
77import TestViewer from './TestViewer' ;
@@ -11,6 +11,12 @@ Globals.assign({
1111 skipAnimation : true ,
1212} ) ;
1313
14+ window . muiFixture = {
15+ navigate : ( ) => {
16+ throw new Error ( `muiFixture.navigate is not ready` ) ;
17+ } ,
18+ } ;
19+
1420// Get all the fixtures specifically written for preventing visual regressions.
1521const importRegressionFixtures = require . context ( './fixtures' , true , / \. ( j s | t s | t s x ) $ / , 'lazy' ) ;
1622const regressionFixtures = [ ] ;
@@ -295,13 +301,13 @@ if (unusedBlacklistPatterns.size > 0) {
295301
296302const viewerRoot = document . getElementById ( 'test-viewer' ) ;
297303
298- function FixtureRenderer ( { component : FixtureComponent } ) {
304+ function FixtureRenderer ( { component : FixtureComponent , path } ) {
299305 const viewerReactRoot = React . useRef ( null ) ;
300306
301307 React . useLayoutEffect ( ( ) => {
302308 const renderTimeout = setTimeout ( ( ) => {
303309 const children = (
304- < TestViewer >
310+ < TestViewer path = { path } >
305311 < FixtureComponent />
306312 </ TestViewer >
307313 ) ;
@@ -320,38 +326,43 @@ function FixtureRenderer({ component: FixtureComponent }) {
320326 viewerReactRoot . current = null ;
321327 } ) ;
322328 } ;
323- } , [ FixtureComponent ] ) ;
329+ } , [ FixtureComponent , path ] ) ;
324330
325331 return null ;
326332}
327333
328334FixtureRenderer . propTypes = {
329335 component : PropTypes . elementType ,
336+ path : PropTypes . string . isRequired ,
330337} ;
331338
332- function App ( props ) {
333- const { fixtures } = props ;
334-
335- function computeIsDev ( ) {
336- if ( window . location . hash === '#dev' ) {
337- return true ;
338- }
339- if ( window . location . hash === '#no-dev' ) {
340- return false ;
341- }
342- return process . env . NODE_ENV === 'development' ;
343- }
344- const [ isDev , setDev ] = React . useState ( computeIsDev ) ;
345- React . useEffect ( ( ) => {
346- function handleHashChange ( ) {
347- setDev ( computeIsDev ( ) ) ;
348- }
349- window . addEventListener ( 'hashchange' , handleHashChange ) ;
350-
339+ function useHash ( ) {
340+ const subscribe = React . useCallback ( ( callback ) => {
341+ window . addEventListener ( 'hashchange' , callback ) ;
351342 return ( ) => {
352- window . removeEventListener ( 'hashchange' , handleHashChange ) ;
343+ window . removeEventListener ( 'hashchange' , callback ) ;
353344 } ;
354345 } , [ ] ) ;
346+ const getSnapshot = React . useCallback ( ( ) => window . location . hash , [ ] ) ;
347+ const getServerSnapshot = React . useCallback ( ( ) => '' , [ ] ) ;
348+ return React . useSyncExternalStore ( subscribe , getSnapshot , getServerSnapshot ) ;
349+ }
350+
351+ function computeIsDev ( hash ) {
352+ if ( hash === '#dev' ) {
353+ return true ;
354+ }
355+ if ( hash === '#no-dev' ) {
356+ return false ;
357+ }
358+ return process . env . NODE_ENV === 'development' ;
359+ }
360+
361+ function App ( props ) {
362+ const { fixtures } = props ;
363+
364+ const hash = useHash ( ) ;
365+ const isDev = computeIsDev ( hash ) ;
355366
356367 // Using <link rel="stylesheet" /> does not apply the google Roboto font in chromium headless/headfull.
357368 const [ fontState , setFontState ] = React . useState ( 'pending' ) ;
@@ -380,8 +391,13 @@ function App(props) {
380391 return `/${ fixture . suite } /${ fixture . name } ` ;
381392 }
382393
394+ const navigate = useNavigate ( ) ;
395+ React . useEffect ( ( ) => {
396+ window . muiFixture . navigate = navigate ;
397+ } , [ navigate ] ) ;
398+
383399 return (
384- < Router >
400+ < React . Fragment >
385401 < Routes >
386402 { fixtures . map ( ( fixture ) => {
387403 const path = computePath ( fixture ) ;
@@ -396,36 +412,43 @@ function App(props) {
396412 key = { path }
397413 exact
398414 path = { path }
399- element = { fixturePrepared ? < FixtureRenderer component = { FixtureComponent } /> : null }
415+ element = {
416+ fixturePrepared ? (
417+ < FixtureRenderer component = { FixtureComponent } path = { path } />
418+ ) : null
419+ }
400420 />
401421 ) ;
402422 } ) }
403423 </ Routes >
404424
405- < div hidden = { ! isDev } >
406- < div data-webfontloader = { fontState } > webfontloader: { fontState } </ div >
407- < p >
408- Devtools can be enabled by appending < code > #dev</ code > in the addressbar or disabled by
409- appending < code > #no-dev</ code > .
410- </ p >
411- < a href = "#no-dev" > Hide devtools</ a >
412- < details >
413- < summary id = "my-test-summary" > nav for all tests</ summary >
414- < nav id = "tests" >
415- < ol >
416- { fixtures . map ( ( fixture ) => {
417- const path = computePath ( fixture ) ;
418- return (
419- < li key = { path } >
420- < Link to = { path } > { path } </ Link >
421- </ li >
422- ) ;
423- } ) }
424- </ ol >
425- </ nav >
426- </ details >
427- </ div >
428- </ Router >
425+ { isDev ? (
426+ < div >
427+ < div data-webfontloader = { fontState } > webfontloader: { fontState } </ div >
428+ < p >
429+ Devtools can be enabled by appending < code > #dev</ code > in the addressbar or disabled by
430+ appending < code > #no-dev</ code > .
431+ </ p >
432+ < a href = "#no-dev" > Hide devtools</ a >
433+ < details >
434+ < summary id = "my-test-summary" > nav for all tests</ summary >
435+
436+ < nav id = "tests" >
437+ < ol >
438+ { fixtures . map ( ( fixture ) => {
439+ const path = computePath ( fixture ) ;
440+ return (
441+ < li key = { path } >
442+ < Link to = { path } > { path } </ Link >
443+ </ li >
444+ ) ;
445+ } ) }
446+ </ ol >
447+ </ nav >
448+ </ details >
449+ </ div >
450+ ) : null }
451+ </ React . Fragment >
429452 ) ;
430453}
431454
@@ -434,6 +457,10 @@ App.propTypes = {
434457} ;
435458
436459const container = document . getElementById ( 'react-root' ) ;
437- const children = < App fixtures = { regressionFixtures . concat ( demoFixtures ) } /> ;
460+ const children = (
461+ < Router >
462+ < App fixtures = { regressionFixtures . concat ( demoFixtures ) } /> { ' ' }
463+ </ Router >
464+ ) ;
438465const reactRoot = ReactDOMClient . createRoot ( container ) ;
439466reactRoot . render ( children ) ;
0 commit comments