@@ -22,29 +22,44 @@ import {instrumentUserEvent} from '../instrumentedEnv/userEventIntegration';
22
22
import { initializeOrg } from './initializeOrg' ;
23
23
24
24
interface ProviderOptions {
25
+ /**
26
+ * Do not shim the router use{Routes,Router,Navigate,Location} functions, and
27
+ * instead allow them to work as normal, rendering inside of a memory router.
28
+ *
29
+ * Wehn enabling this passing a `router` object *will do nothing*!
30
+ */
31
+ disableRouterMocks ?: boolean ;
25
32
/**
26
33
* Sets the OrganizationContext. You may pass null to provide no organization
27
34
*/
28
35
organization ?: Partial < Organization > | null ;
29
36
/**
30
- * Sets the RouterContext
37
+ * Sets the RouterContext.
31
38
*/
32
39
router ?: Partial < InjectedRouter > ;
33
40
}
34
41
35
42
interface Options extends ProviderOptions , rtl . RenderOptions { }
36
43
37
- function makeAllTheProviders ( providers : ProviderOptions ) {
44
+ function makeAllTheProviders ( options : ProviderOptions ) {
38
45
const { organization, router} = initializeOrg ( {
39
- organization : providers . organization === null ? undefined : providers . organization ,
40
- router : providers . router ,
46
+ organization : options . organization === null ? undefined : options . organization ,
47
+ router : options . router ,
41
48
} ) ;
42
49
43
50
// In some cases we may want to not provide an organization at all
44
- const optionalOrganization = providers . organization === null ? null : organization ;
51
+ const optionalOrganization = options . organization === null ? null : organization ;
45
52
46
53
return function ( { children} : { children ?: React . ReactNode } ) {
47
54
const content = (
55
+ < OrganizationContext . Provider value = { optionalOrganization } >
56
+ < GlobalDrawer > { children } </ GlobalDrawer >
57
+ </ OrganizationContext . Provider >
58
+ ) ;
59
+
60
+ const wrappedContent = options . disableRouterMocks ? (
61
+ content
62
+ ) : (
48
63
< RouteContext . Provider
49
64
value = { {
50
65
router,
@@ -53,41 +68,41 @@ function makeAllTheProviders(providers: ProviderOptions) {
53
68
routes : router . routes ,
54
69
} }
55
70
>
56
- < OrganizationContext . Provider value = { optionalOrganization } >
57
- < GlobalDrawer > { children } </ GlobalDrawer >
58
- </ OrganizationContext . Provider >
71
+ { content }
59
72
</ RouteContext . Provider >
60
73
) ;
61
74
75
+ const history = createMemoryHistory ( ) ;
76
+
62
77
// Inject legacy react-router 3 style router mocked navigation functions
63
78
// into the memory history used in react router 6
64
79
//
65
80
// TODO(epurkhiser): In a world without react-router 3 we should figure out
66
81
// how to write our tests in a simpler way without all these shims
67
-
68
- const history = createMemoryHistory ( ) ;
69
- Object . defineProperty ( history , 'location' , { get : ( ) => router . location } ) ;
70
- history . replace = router . replace ;
71
- history . push = ( path : any ) => {
72
- if ( typeof path === 'object' && path . search ) {
73
- path . query = qs . parse ( path . search ) ;
74
- delete path . search ;
75
- delete path . hash ;
76
- delete path . state ;
77
- delete path . key ;
78
- }
79
-
80
- // XXX(epurkhiser): This is a hack for react-router 3 to 6. react-router
81
- // 6 will not convert objects into strings before pushing. We can detect
82
- // this by looking for an empty hash, which we normally do not set for
83
- // our browserHistory.push calls
84
- if ( typeof path === 'object' && path . hash === '' ) {
85
- const queryString = path . query ? qs . stringify ( path . query ) : null ;
86
- path = ` ${ path . pathname } ${ queryString ? `? ${ queryString } ` : '' } ` ;
87
- }
88
-
89
- router . push ( path ) ;
90
- } ;
82
+ if ( ! options . disableRouterMocks ) {
83
+ Object . defineProperty ( history , 'location' , { get : ( ) => router . location } ) ;
84
+ history . replace = router . replace ;
85
+ history . push = ( path : any ) => {
86
+ if ( typeof path === 'object' && path . search ) {
87
+ path . query = qs . parse ( path . search ) ;
88
+ delete path . search ;
89
+ delete path . hash ;
90
+ delete path . state ;
91
+ delete path . key ;
92
+ }
93
+
94
+ // XXX(epurkhiser): This is a hack for react-router 3 to 6. react-router
95
+ // 6 will not convert objects into strings before pushing. We can detect
96
+ // this by looking for an empty hash, which we normally do not set for
97
+ // our browserHistory.push calls
98
+ if ( typeof path === 'object' && path . hash === '' ) {
99
+ const queryString = path . query ? qs . stringify ( path . query ) : null ;
100
+ path = ` ${ path . pathname } ${ queryString ? `? ${ queryString } ` : '' } ` ;
101
+ }
102
+
103
+ router . push ( path ) ;
104
+ } ;
105
+ }
91
106
92
107
// By default react-router 6 catches exceptions and displays the stack
93
108
// trace. For tests we want them to bubble out
@@ -98,7 +113,7 @@ function makeAllTheProviders(providers: ProviderOptions) {
98
113
const routes : RouteObject [ ] = [
99
114
{
100
115
path : '*' ,
101
- element : content ,
116
+ element : wrappedContent ,
102
117
errorElement : < ErrorBoundary /> ,
103
118
} ,
104
119
] ;
@@ -132,11 +147,12 @@ function makeAllTheProviders(providers: ProviderOptions) {
132
147
*/
133
148
function render (
134
149
ui : React . ReactElement ,
135
- { router, organization, ...rtlOptions } : Options = { }
150
+ { router, organization, disableRouterMocks , ...rtlOptions } : Options = { }
136
151
) {
137
152
const AllTheProviders = makeAllTheProviders ( {
138
153
organization,
139
154
router,
155
+ disableRouterMocks,
140
156
} ) ;
141
157
142
158
return rtl . render ( ui , { wrapper : AllTheProviders , ...rtlOptions } ) ;
0 commit comments