@@ -192,12 +192,12 @@ describe('getUIExtensionPayload', () => {
192192 assets : {
193193 tools : {
194194 name : 'tools' ,
195- url : 'http://tunnel-url.com/extensions/devUUID/assets/tools.json' ,
195+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/ tools.json' ,
196196 lastUpdated : expect . any ( Number ) ,
197197 } ,
198198 instructions : {
199199 name : 'instructions' ,
200- url : 'http://tunnel-url.com/extensions/devUUID/assets/instructions.md' ,
200+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/ instructions.md' ,
201201 lastUpdated : expect . any ( Number ) ,
202202 } ,
203203 } ,
@@ -241,12 +241,12 @@ describe('getUIExtensionPayload', () => {
241241 assets : {
242242 main : {
243243 name : 'main' ,
244- url : 'http://tunnel-url.com/extensions/devUUID/assets/test-ui-extension .js' ,
244+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/main .js' ,
245245 lastUpdated : expect . any ( Number ) ,
246246 } ,
247247 should_render : {
248248 name : 'should_render' ,
249- url : 'http://tunnel-url.com/extensions/devUUID/assets/test-ui-extension-conditions .js' ,
249+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/should_render .js' ,
250250 lastUpdated : expect . any ( Number ) ,
251251 } ,
252252 } ,
@@ -295,12 +295,12 @@ describe('getUIExtensionPayload', () => {
295295 assets : {
296296 main : {
297297 name : 'main' ,
298- url : 'http://tunnel-url.com/extensions/devUUID/assets/dist/test-ui-extension .js' ,
298+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/main .js' ,
299299 lastUpdated : expect . any ( Number ) ,
300300 } ,
301301 should_render : {
302302 name : 'should_render' ,
303- url : 'http://tunnel-url.com/extensions/devUUID/assets/dist/test-ui-extension-conditions .js' ,
303+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/should_render .js' ,
304304 lastUpdated : expect . any ( Number ) ,
305305 } ,
306306 } ,
@@ -309,6 +309,205 @@ describe('getUIExtensionPayload', () => {
309309 } )
310310 } )
311311
312+ test ( 'emits a distinct URL per extension point even when built assets share a filepath' , async ( ) => {
313+ await inTemporaryDirectory ( async ( tmpDir ) => {
314+ const uiExtension = await testUIExtension ( {
315+ directory : tmpDir ,
316+ configuration : {
317+ name : 'test-ui-extension' ,
318+ type : 'ui_extension' ,
319+ extension_points : [
320+ { target : 'TARGET_A' , module : './src/ExtensionPointA.js' } ,
321+ { target : 'TARGET_B' , module : './src/ExtensionPointB.js' } ,
322+ ] ,
323+ } ,
324+ devUUID : 'devUUID' ,
325+ } )
326+
327+ await setupBuildOutput (
328+ uiExtension ,
329+ tmpDir ,
330+ {
331+ TARGET_A : { main : 'dist/main.js' } ,
332+ TARGET_B : { main : 'dist/main.js' } ,
333+ } ,
334+ { } ,
335+ )
336+
337+ const resolver = new Map < string , string > ( )
338+ const got = await getUIExtensionPayload (
339+ uiExtension ,
340+ tmpDir ,
341+ {
342+ ...createMockOptions ( tmpDir , [ uiExtension ] ) ,
343+ currentDevelopmentPayload : { hidden : true , status : 'success' } ,
344+ } ,
345+ resolver ,
346+ )
347+
348+ expect ( got . extensionPoints ) . toMatchObject ( [
349+ {
350+ target : 'TARGET_A' ,
351+ assets : {
352+ main : { name : 'main' , url : 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_A/main.js' } ,
353+ } ,
354+ } ,
355+ {
356+ target : 'TARGET_B' ,
357+ assets : {
358+ main : { name : 'main' , url : 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_B/main.js' } ,
359+ } ,
360+ } ,
361+ ] )
362+ expect ( resolver . get ( 'TARGET_A/main.js' ) ) . toBe ( 'dist/main.js' )
363+ expect ( resolver . get ( 'TARGET_B/main.js' ) ) . toBe ( 'dist/main.js' )
364+ } )
365+ } )
366+
367+ test ( 'emits a directory-prefix URL and per-file resolver entries when the config points at a folder' , async ( ) => {
368+ await inTemporaryDirectory ( async ( tmpDir ) => {
369+ const uiExtension = await testUIExtension ( {
370+ directory : tmpDir ,
371+ configuration : {
372+ name : 'test-ui-extension' ,
373+ type : 'ui_extension' ,
374+ extension_points : [
375+ {
376+ target : 'CUSTOM_EXTENSION_POINT' ,
377+ module : './src/ExtensionPointA.js' ,
378+ assets : './assets' ,
379+ } ,
380+ ] ,
381+ } ,
382+ devUUID : 'devUUID' ,
383+ } )
384+
385+ await setupBuildOutput (
386+ uiExtension ,
387+ tmpDir ,
388+ { CUSTOM_EXTENSION_POINT : { assets : [ 'foo.json' , 'subdir/bar.png' ] } } ,
389+ { 'foo.json' : '{}' , 'subdir/bar.png' : 'stub' } ,
390+ )
391+
392+ const extensionOutputPath = uiExtension . getOutputPathForDirectory ( tmpDir )
393+ const buildDirectory = extname ( extensionOutputPath ) ? dirname ( extensionOutputPath ) : extensionOutputPath
394+ await writeFile ( joinPath ( buildDirectory , 'foo.json' ) , '{}' )
395+ await mkdir ( joinPath ( buildDirectory , 'subdir' ) )
396+ await writeFile ( joinPath ( buildDirectory , 'subdir/bar.png' ) , 'stub' )
397+
398+ const resolver = new Map < string , string > ( )
399+ const got = await getUIExtensionPayload (
400+ uiExtension ,
401+ tmpDir ,
402+ {
403+ ...createMockOptions ( tmpDir , [ uiExtension ] ) ,
404+ currentDevelopmentPayload : { hidden : true , status : 'success' } ,
405+ } ,
406+ resolver ,
407+ )
408+
409+ expect ( got . extensionPoints ) . toMatchObject ( [
410+ {
411+ target : 'CUSTOM_EXTENSION_POINT' ,
412+ assets : {
413+ assets : {
414+ name : 'assets' ,
415+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/assets/' ,
416+ lastUpdated : expect . any ( Number ) ,
417+ } ,
418+ } ,
419+ } ,
420+ ] )
421+ expect ( resolver . get ( 'CUSTOM_EXTENSION_POINT/assets/foo.json' ) ) . toBe ( 'foo.json' )
422+ expect ( resolver . get ( 'CUSTOM_EXTENSION_POINT/assets/subdir/bar.png' ) ) . toBe ( 'subdir/bar.png' )
423+ } )
424+ } )
425+
426+ test ( 'emits distinct directory URLs per extension point when two targets share the same assets folder' , async ( ) => {
427+ await inTemporaryDirectory ( async ( tmpDir ) => {
428+ const uiExtension = await testUIExtension ( {
429+ directory : tmpDir ,
430+ configuration : {
431+ name : 'test-ui-extension' ,
432+ type : 'ui_extension' ,
433+ extension_points : [
434+ { target : 'TARGET_A' , module : './src/ExtensionPointA.js' , assets : './assets' } ,
435+ { target : 'TARGET_B' , module : './src/ExtensionPointB.js' , assets : './assets' } ,
436+ ] ,
437+ } ,
438+ devUUID : 'devUUID' ,
439+ } )
440+
441+ await setupBuildOutput (
442+ uiExtension ,
443+ tmpDir ,
444+ {
445+ TARGET_A : { assets : [ 'foo.json' ] } ,
446+ TARGET_B : { assets : [ 'foo.json' ] } ,
447+ } ,
448+ { 'foo.json' : '{}' } ,
449+ )
450+ const extensionOutputPath = uiExtension . getOutputPathForDirectory ( tmpDir )
451+ const buildDirectory = extname ( extensionOutputPath ) ? dirname ( extensionOutputPath ) : extensionOutputPath
452+ await writeFile ( joinPath ( buildDirectory , 'foo.json' ) , '{}' )
453+
454+ const resolver = new Map < string , string > ( )
455+ const got = await getUIExtensionPayload (
456+ uiExtension ,
457+ tmpDir ,
458+ {
459+ ...createMockOptions ( tmpDir , [ uiExtension ] ) ,
460+ currentDevelopmentPayload : { hidden : true , status : 'success' } ,
461+ } ,
462+ resolver ,
463+ )
464+
465+ expect ( got . extensionPoints ) . toMatchObject ( [
466+ {
467+ target : 'TARGET_A' ,
468+ assets : { assets : { url : 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_A/assets/' } } ,
469+ } ,
470+ {
471+ target : 'TARGET_B' ,
472+ assets : { assets : { url : 'http://tunnel-url.com/extensions/devUUID/assets/TARGET_B/assets/' } } ,
473+ } ,
474+ ] )
475+ // Both targets' resolver entries point at the same output-relative file.
476+ expect ( resolver . get ( 'TARGET_A/assets/foo.json' ) ) . toBe ( 'foo.json' )
477+ expect ( resolver . get ( 'TARGET_B/assets/foo.json' ) ) . toBe ( 'foo.json' )
478+ } )
479+ } )
480+
481+ test ( 'clears stale resolver entries on each payload regeneration' , async ( ) => {
482+ await inTemporaryDirectory ( async ( tmpDir ) => {
483+ const uiExtension = await testUIExtension ( {
484+ directory : tmpDir ,
485+ configuration : {
486+ name : 'test-ui-extension' ,
487+ type : 'ui_extension' ,
488+ extension_points : [ { target : 'CUSTOM_EXTENSION_POINT' , module : './src/ExtensionPointA.js' } ] ,
489+ } ,
490+ devUUID : 'devUUID' ,
491+ } )
492+
493+ await setupBuildOutput ( uiExtension , tmpDir , { CUSTOM_EXTENSION_POINT : { main : 'dist/main.js' } } , { } )
494+
495+ const resolver = new Map < string , string > ( [ [ 'STALE_TARGET/main.js' , 'stale.js' ] ] )
496+ await getUIExtensionPayload (
497+ uiExtension ,
498+ tmpDir ,
499+ {
500+ ...createMockOptions ( tmpDir , [ uiExtension ] ) ,
501+ currentDevelopmentPayload : { hidden : true , status : 'success' } ,
502+ } ,
503+ resolver ,
504+ )
505+
506+ expect ( resolver . has ( 'STALE_TARGET/main.js' ) ) . toBe ( false )
507+ expect ( resolver . get ( 'CUSTOM_EXTENSION_POINT/main.js' ) ) . toBe ( 'dist/main.js' )
508+ } )
509+ } )
510+
312511 test ( 'maps intents from manifest.json to asset payloads' , async ( ) => {
313512 await inTemporaryDirectory ( async ( tmpDir ) => {
314513 const uiExtension = await testUIExtension ( {
@@ -351,7 +550,7 @@ describe('getUIExtensionPayload', () => {
351550 action : 'create' ,
352551 schema : {
353552 name : 'schema' ,
354- url : 'http://tunnel-url.com/extensions/devUUID/assets/intents/create- schema.json' ,
553+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/ intents/0/ schema.json' ,
355554 lastUpdated : expect . any ( Number ) ,
356555 } ,
357556 } ,
@@ -360,7 +559,7 @@ describe('getUIExtensionPayload', () => {
360559 action : 'update' ,
361560 schema : {
362561 name : 'schema' ,
363- url : 'http://tunnel-url.com/extensions/devUUID/assets/intents/update- schema.json' ,
562+ url : 'http://tunnel-url.com/extensions/devUUID/assets/CUSTOM_EXTENSION_POINT/ intents/1/ schema.json' ,
364563 lastUpdated : expect . any ( Number ) ,
365564 } ,
366565 } ,
@@ -461,7 +660,7 @@ describe('getUIExtensionPayload', () => {
461660 assets : {
462661 tools : {
463662 name : 'tools' ,
464- url : 'http://tunnel-url.com/extensions/devUUID/assets/tools.json' ,
663+ url : 'http://tunnel-url.com/extensions/devUUID/assets/admin.app.intent.link/ tools.json' ,
465664 lastUpdated : expect . any ( Number ) ,
466665 } ,
467666 } ,
0 commit comments