@@ -229,6 +229,8 @@ describe('Apps Plugin - upload', () => {
229229 version_id : 'v123' ,
230230 application_id : 'app123' ,
231231 app_builder_id : 'builder123' ,
232+ app_builder_url :
233+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
232234 } as any ) ;
233235
234236 const { errors, warnings } = await uploadArchive ( archive , context , logger ) ;
@@ -248,7 +250,30 @@ describe('Apps Plugin - upload', () => {
248250 onRetry : expect . any ( Function ) ,
249251 } ) ;
250252 expect ( mockLogFn ) . toHaveBeenCalledWith (
251- expect . stringContaining ( 'Your application is available at' ) ,
253+ expect . stringContaining (
254+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
255+ ) ,
256+ 'info' ,
257+ ) ;
258+ } ) ;
259+
260+ test ( 'Should use app_builder_url from upload response' , async ( ) => {
261+ doAuthenticatedRequestMock . mockResolvedValueOnce ( {
262+ version_id : 'v123' ,
263+ application_id : 'app123' ,
264+ app_builder_id : 'builder123' ,
265+ app_builder_url :
266+ 'https://dd.datad0g.com/app-builder/apps/edit/builder123?viewMode=preview' ,
267+ } as any ) ;
268+
269+ await uploadArchive ( archive , context , logger ) ;
270+
271+ // Uses the exact URL from the response — proves it's not reconstructed from
272+ // context.site (datadoghq.com), which would produce a different domain.
273+ expect ( mockLogFn ) . toHaveBeenCalledWith (
274+ expect . stringContaining (
275+ 'https://dd.datad0g.com/app-builder/apps/edit/builder123?viewMode=preview' ,
276+ ) ,
252277 'info' ,
253278 ) ;
254279 } ) ;
@@ -258,6 +283,8 @@ describe('Apps Plugin - upload', () => {
258283 version_id : 'v123' ,
259284 application_id : 'app123' ,
260285 app_builder_id : 'builder123' ,
286+ app_builder_url :
287+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
261288 } as any ) ;
262289
263290 const { errors, warnings } = await uploadArchive (
@@ -286,8 +313,12 @@ describe('Apps Plugin - upload', () => {
286313 version_id : 'v123' ,
287314 application_id : 'app123' ,
288315 app_builder_id : 'builder123' ,
316+ app_builder_url :
317+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
289318 } )
290- . mockResolvedValueOnce ( { } ) ;
319+ . mockResolvedValueOnce ( {
320+ app_builder_url : 'https://app.datadoghq.com/app-builder/apps/builder123' ,
321+ } ) ;
291322
292323 const { errors, warnings } = await uploadArchive ( archive , context , logger ) ;
293324
@@ -301,10 +332,72 @@ describe('Apps Plugin - upload', () => {
301332 getData : expect . any ( Function ) ,
302333 onRetry : expect . any ( Function ) ,
303334 } ) ;
304- expect ( mockLogFn ) . toHaveBeenCalledWith (
305- expect . stringContaining ( 'Your application is available at' ) ,
306- 'info' ,
335+ // Pin down which log is which by its distinguishing message prefix — proves not
336+ // just that a matching call exists somewhere, but that the upload log specifically
337+ // carries ?viewMode=preview and the release log specifically doesn't.
338+ const uploadLog = mockLogFn . mock . calls . find ( ( [ message ] ) =>
339+ message . startsWith ( 'Your application is available at' ) ,
340+ ) ;
341+ const releaseLog = mockLogFn . mock . calls . find ( ( [ message ] ) =>
342+ message . startsWith ( 'Published uploaded version' ) ,
343+ ) ;
344+ expect ( uploadLog ?. [ 0 ] ) . toContain (
345+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
346+ ) ;
347+ expect ( releaseLog ?. [ 0 ] ) . toContain (
348+ 'https://app.datadoghq.com/app-builder/apps/builder123' ,
349+ ) ;
350+ expect ( releaseLog ?. [ 0 ] ) . not . toContain ( '?viewMode' ) ;
351+ } ) ;
352+
353+ test ( 'Should use app_builder_url from release response' , async ( ) => {
354+ doAuthenticatedRequestMock
355+ . mockResolvedValueOnce ( {
356+ version_id : 'v123' ,
357+ application_id : 'app123' ,
358+ app_builder_id : 'builder123' ,
359+ app_builder_url :
360+ 'https://dd.datad0g.com/app-builder/apps/edit/builder123?viewMode=preview' ,
361+ } )
362+ . mockResolvedValueOnce ( {
363+ app_builder_url : 'https://dd.datad0g.com/app-builder/apps/builder123' ,
364+ } ) ;
365+
366+ await uploadArchive ( archive , context , logger ) ;
367+
368+ // Match the release log by its distinguishing message prefix — proves the
369+ // published URL reflects the custom domain from the release response (not
370+ // context.site) and carries no ?viewMode (unlike the upload log).
371+ const releaseLog = mockLogFn . mock . calls . find ( ( [ message ] ) =>
372+ message . startsWith ( 'Published uploaded version' ) ,
373+ ) ;
374+ expect ( releaseLog ?. [ 0 ] ) . toContain ( 'https://dd.datad0g.com/app-builder/apps/builder123' ) ;
375+ expect ( releaseLog ?. [ 0 ] ) . not . toContain ( '?viewMode' ) ;
376+ } ) ;
377+
378+ test ( 'Should degrade gracefully when release response has no app_builder_url' , async ( ) => {
379+ doAuthenticatedRequestMock
380+ . mockResolvedValueOnce ( {
381+ version_id : 'v123' ,
382+ application_id : 'app123' ,
383+ app_builder_id : 'builder123' ,
384+ app_builder_url :
385+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
386+ } )
387+ // Simulates an older backend that doesn't yet return app_builder_url.
388+ . mockResolvedValueOnce ( { } ) ;
389+
390+ const { errors, warnings } = await uploadArchive ( archive , context , logger ) ;
391+
392+ expect ( errors ) . toHaveLength ( 0 ) ;
393+ expect ( warnings ) . toHaveLength ( 0 ) ;
394+ const releaseLog = mockLogFn . mock . calls . find ( ( [ message ] ) =>
395+ message . startsWith ( 'Published uploaded version' ) ,
307396 ) ;
397+ expect ( releaseLog ?. [ 0 ] ) . toContain ( 'to live.' ) ;
398+ // No second line with a URL — degrades to the plain message instead of
399+ // logging "undefined" or throwing on a missing app_builder_url.
400+ expect ( releaseLog ?. [ 0 ] ) . not . toContain ( '\n' ) ;
308401 } ) ;
309402
310403 test . each ( [ 'false' , '0' , 'False' , 'FALSE' , 'off' , 'no' ] ) (
@@ -317,6 +410,8 @@ describe('Apps Plugin - upload', () => {
317410 version_id : 'v123' ,
318411 application_id : 'app123' ,
319412 app_builder_id : 'builder123' ,
413+ app_builder_url :
414+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
320415 } ) ;
321416
322417 const { errors } = await uploadArchive ( archive , context , logger ) ;
@@ -342,6 +437,8 @@ describe('Apps Plugin - upload', () => {
342437 version_id : 'v123' ,
343438 application_id : 'app123' ,
344439 app_builder_id : 'builder123' ,
440+ app_builder_url :
441+ 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview' ,
345442 } ) ;
346443
347444 const { errors, warnings } = await uploadArchive ( archive , context , logger ) ;
0 commit comments