diff --git a/.changeset/lazy-phones-worry.md b/.changeset/lazy-phones-worry.md new file mode 100644 index 0000000000..2c64f81f2c --- /dev/null +++ b/.changeset/lazy-phones-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-app-api': minor +--- + +Extensions in app-config now always affect ordering. Previously, only when enabling disabled extensions did they rise to the top. diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts index 82f274b960..8af2aef070 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.test.ts @@ -110,6 +110,12 @@ describe('resolveAppNodeSpecs', () => { ], }), ).toEqual([ + { + id: 'b', + extension: b, + attachTo: { id: 'derp', input: 'default' }, + disabled: false, + }, { id: 'test/a', extension: makeExt('test/a'), @@ -117,12 +123,6 @@ describe('resolveAppNodeSpecs', () => { source: pluginA, disabled: false, }, - { - id: 'b', - extension: b, - attachTo: { id: 'derp', input: 'default' }, - disabled: false, - }, ]); }); @@ -206,6 +206,70 @@ describe('resolveAppNodeSpecs', () => { ]); }); + it('should place config-mentioned instances in the order that they were listed, irrespective of if the extension was enabled or not originally', () => { + const a = makeExt('a', 'disabled'); + const b = makeExt('b', 'enabled'); + const c = makeExt('c', 'disabled'); + const d = makeExt('d', 'enabled'); + const e = makeExt('e', 'disabled'); + const f = makeExt('f', 'enabled'); + const g = makeExt('g', 'disabled'); + expect( + resolveAppNodeSpecs({ + features: [createPlugin({ id: 'empty', extensions: [] })], + builtinExtensions: [a, b, c, d, e, f, g], + parameters: [ + { id: 'e', disabled: false }, + { id: 'd', disabled: false }, + { id: 'c', disabled: false }, + ], + }), + ).toEqual([ + { + id: 'e', + extension: e, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, + { + id: 'd', + extension: d, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, + { + id: 'c', + extension: c, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, + { + id: 'a', + extension: a, + attachTo: { id: 'root', input: 'default' }, + disabled: true, + }, + { + id: 'b', + extension: b, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, + { + id: 'f', + extension: f, + attachTo: { id: 'root', input: 'default' }, + disabled: false, + }, + { + id: 'g', + extension: g, + attachTo: { id: 'root', input: 'default' }, + disabled: true, + }, + ]); + }); + it('should apply extension overrides', () => { const plugin = createPlugin({ id: 'test', diff --git a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts index f056e7a49e..e31c70025d 100644 --- a/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts +++ b/packages/frontend-app-api/src/tree/resolveAppNodeSpecs.ts @@ -184,6 +184,7 @@ export function resolveAppNodeSpecs(options: { ); } + const order = new Map(); for (const overrideParam of parameters) { const extensionId = overrideParam.id; @@ -193,11 +194,10 @@ export function resolveAppNodeSpecs(options: { ); } - const existingIndex = configuredExtensions.findIndex( + const existing = configuredExtensions.find( e => e.extension.id === extensionId, ); - if (existingIndex !== -1) { - const existing = configuredExtensions[existingIndex]; + if (existing) { if (overrideParam.attachTo) { existing.params.attachTo = overrideParam.attachTo; } @@ -209,18 +209,19 @@ export function resolveAppNodeSpecs(options: { Boolean(existing.params.disabled) !== Boolean(overrideParam.disabled) ) { existing.params.disabled = Boolean(overrideParam.disabled); - if (!existing.params.disabled) { - // bump - configuredExtensions.splice(existingIndex, 1); - configuredExtensions.push(existing); - } } + order.set(extensionId, existing); } else { throw new Error(`Extension ${extensionId} does not exist`); } } - return configuredExtensions.map(param => ({ + const orderedExtensions = [ + ...order.values(), + ...configuredExtensions.filter(e => !order.has(e.extension.id)), + ]; + + return orderedExtensions.map(param => ({ id: param.extension.id, attachTo: param.params.attachTo, extension: param.extension, diff --git a/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts b/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts index c180dc9719..dab8a9778a 100644 --- a/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createPlugin.test.ts @@ -187,7 +187,7 @@ describe('createPlugin', () => { await expect( screen.findByText( - 'Names: extension-1, extension-2-renamed, extension-3:child', + 'Names: extension-2-renamed, extension-1, extension-3:child', ), ).resolves.toBeInTheDocument(); });