@@ -112,20 +112,127 @@ describe('profile', () => {
112112 await expect ( result ) . rejects . toThrow ( 'Network error' )
113113 } )
114114
115- test ( 'throws error when response status is not 200' , async ( ) => {
115+ test ( 'passes the query string of the url separately from the path' , async ( ) => {
116+ // When
117+ await profile ( mockAdminSession , themeId , '/search?q=kw&page=2#results' )
118+
119+ // Then
120+ expect ( render ) . toHaveBeenCalledWith (
121+ expect . anything ( ) ,
122+ expect . objectContaining ( {
123+ path : '/search' ,
124+ query : [
125+ [ 'q' , 'kw' ] ,
126+ [ 'page' , '2' ] ,
127+ ] ,
128+ } ) ,
129+ )
130+ } )
131+
132+ test ( 'does not let the url override the storefront renderer query params' , async ( ) => {
133+ // When
134+ await profile ( mockAdminSession , themeId , '/collections/all?_fd=1&pb=1&page=2' )
135+
136+ // Then
137+ expect ( render ) . toHaveBeenCalledWith (
138+ expect . anything ( ) ,
139+ expect . objectContaining ( { path : '/collections/all' , query : [ [ 'page' , '2' ] ] } ) ,
140+ )
141+ } )
142+
143+ test ( 'uses only the path and query of an absolute url' , async ( ) => {
144+ // When
145+ await profile ( mockAdminSession , themeId , 'https://custom-domain.com/products/test?variant=1' )
146+
147+ // Then
148+ expect ( render ) . toHaveBeenCalledWith (
149+ expect . anything ( ) ,
150+ expect . objectContaining ( { path : '/products/test' , query : [ [ 'variant' , '1' ] ] } ) ,
151+ )
152+ } )
153+
154+ test ( 'suggests the redirect destination when the page redirects' , async ( ) => {
155+ // Given
156+ vi . mocked ( render ) . mockResolvedValue (
157+ new Response ( null , {
158+ status : 301 ,
159+ headers : { Location : 'https://custom-domain.com/de/pages/x?_fd=0&pb=0&view=full' } ,
160+ } ) ,
161+ )
162+
163+ // When
164+ const result = profile ( mockAdminSession , themeId , urlPath )
165+
166+ // Then
167+ await expect ( result ) . rejects . toThrow (
168+ new AbortError (
169+ `The page ${ urlPath } redirects (301) instead of rendering, so it can't be profiled.` ,
170+ 'It redirects to /de/pages/x?view=full. Run the command again with --url "/de/pages/x?view=full".' ,
171+ ) ,
172+ )
173+ } )
174+
175+ test ( 'suggests the storefront password when the page redirects to the password page' , async ( ) => {
176+ // Given
177+ vi . mocked ( render ) . mockResolvedValue ( new Response ( null , { status : 302 , headers : { Location : '/password' } } ) )
178+
179+ // When
180+ const result = profile ( mockAdminSession , themeId , '/' )
181+
182+ // Then
183+ await expect ( result ) . rejects . toThrow (
184+ new AbortError (
185+ "The page / redirects (302) instead of rendering, so it can't be profiled." ,
186+ "It redirects to the storefront password page, so the storefront password wasn't accepted. Run the command again with the correct --store-password." ,
187+ ) ,
188+ )
189+ } )
190+
191+ test ( 'reports a redirect without a location as an expected error' , async ( ) => {
192+ // Given
193+ vi . mocked ( render ) . mockResolvedValue ( new Response ( null , { status : 301 } ) )
194+
195+ // When
196+ const result = profile ( mockAdminSession , themeId , urlPath )
197+
198+ // Then
199+ await expect ( result ) . rejects . toThrow (
200+ new AbortError ( `The page ${ urlPath } redirects (301) instead of rendering, so it can't be profiled.` ) ,
201+ )
202+ } )
203+
204+ test ( 'reports a non-200 response as an expected error' , async ( ) => {
116205 // Given
117206 vi . mocked ( render ) . mockResolvedValue (
118207 new Response ( JSON . stringify ( { error : 'Some error message' } ) , {
119208 status : 404 ,
120- headers : new Headers ( { 'content-type' : 'application/json' } ) ,
209+ headers : new Headers ( { 'content-type' : 'application/json' , 'x-request-id' : 'request-id' } ) ,
121210 } ) ,
122211 )
123212
124213 // When
125214 const result = profile ( mockAdminSession , themeId , urlPath )
126215
127216 // Then
128- await expect ( result ) . rejects . toThrow ( 'Bad response: 404: {"error":"Some error message"}' )
217+ await expect ( result ) . rejects . toThrow (
218+ new AbortError (
219+ `Failed to profile ${ urlPath } . The storefront responded with 404 (x-request-id: request-id): {"error":"Some error message"}` ,
220+ ) ,
221+ )
222+ } )
223+
224+ test ( 'does not include a long non-JSON response body in the error' , async ( ) => {
225+ // Given
226+ const htmlPage = `<html><body>${ 'Server error. ' . repeat ( 20 ) } </body></html>`
227+ vi . mocked ( render ) . mockResolvedValue ( new Response ( htmlPage , { status : 500 } ) )
228+
229+ // When
230+ const result = profile ( mockAdminSession , themeId , urlPath )
231+
232+ // Then
233+ await expect ( result ) . rejects . toThrow (
234+ new AbortError ( `Failed to profile ${ urlPath } . The storefront responded with 500` ) ,
235+ )
129236 } )
130237
131238 test ( 'throws error when a password is used' , async ( ) => {
0 commit comments