Merge pull request #26374 from backstage/rugvip/disable
frontend-plugin-api: no longer require factory for extension overrides
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-test-utils': patch
|
||||
---
|
||||
|
||||
The extension tester will no longer unconditionally enable any additional extensions that have been added.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-plugin-api': patch
|
||||
---
|
||||
|
||||
The `factory` option is no longer required when overriding an extension.
|
||||
@@ -1323,7 +1323,7 @@ export type ExtensionDefinition<
|
||||
string}' is already defined in parent schema`;
|
||||
};
|
||||
};
|
||||
factory(
|
||||
factory?(
|
||||
originalFactory: (context?: {
|
||||
config?: T['config'];
|
||||
inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;
|
||||
|
||||
@@ -567,7 +567,7 @@ describe('createExtension', () => {
|
||||
},
|
||||
});
|
||||
|
||||
// @ts-expect-error - this should fail because string output should be merged?
|
||||
// @ts-expect-error
|
||||
const override2 = testExtension.override({
|
||||
output: [numberDataRef],
|
||||
factory(_, { inputs }) {
|
||||
@@ -681,6 +681,69 @@ describe('createExtension', () => {
|
||||
).toBe('foo-hello-override-world');
|
||||
});
|
||||
|
||||
it('should be able to disable extension with override', () => {
|
||||
const subject = createExtension({
|
||||
name: 'root',
|
||||
attachTo: { id: 'ignored', input: 'ignored' },
|
||||
inputs: {
|
||||
input: createExtensionInput([stringDataRef], {
|
||||
singleton: true,
|
||||
optional: true,
|
||||
}),
|
||||
},
|
||||
output: [stringDataRef.optional()],
|
||||
factory({ inputs }) {
|
||||
return inputs.input ?? [];
|
||||
},
|
||||
});
|
||||
|
||||
const attached = createExtension({
|
||||
attachTo: { id: 'root', input: 'input' },
|
||||
output: [stringDataRef],
|
||||
factory() {
|
||||
return [stringDataRef('test')];
|
||||
},
|
||||
});
|
||||
|
||||
expect(
|
||||
createExtensionTester(subject).add(attached).get(stringDataRef),
|
||||
).toBe('test');
|
||||
|
||||
expect(
|
||||
createExtensionTester(subject)
|
||||
.add(attached.override({ disabled: true }))
|
||||
.get(stringDataRef),
|
||||
).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should complain when overriding with incompatible output', () => {
|
||||
const testExtension = createExtension({
|
||||
namespace: 'test',
|
||||
attachTo: { id: 'root', input: 'blob' },
|
||||
output: [stringDataRef],
|
||||
factory() {
|
||||
return [stringDataRef('0')];
|
||||
},
|
||||
});
|
||||
|
||||
// @ts-expect-error - override output is incompatible with factory
|
||||
const override = testExtension.override({
|
||||
output: [numberDataRef],
|
||||
factory() {
|
||||
return [stringDataRef('1')];
|
||||
},
|
||||
});
|
||||
expect(override).toBeDefined();
|
||||
|
||||
expect(() =>
|
||||
testExtension.override({
|
||||
output: [numberDataRef],
|
||||
}),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Refused to override output without also overriding factory"`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should be able to override input values', () => {
|
||||
const outputRef = createExtensionDataRef<unknown>().with({
|
||||
id: 'output',
|
||||
|
||||
@@ -191,7 +191,7 @@ export type ExtensionDefinition<
|
||||
string}' is already defined in parent schema`;
|
||||
};
|
||||
};
|
||||
factory(
|
||||
factory?(
|
||||
originalFactory: (context?: {
|
||||
config?: T['config'];
|
||||
inputs?: ResolveInputValueOverrides<NonNullable<T['inputs']>>;
|
||||
@@ -518,6 +518,15 @@ export function createExtension<
|
||||
UFactoryOutput
|
||||
>;
|
||||
|
||||
// TODO(Rugvip): Making this a type check would be optimal, but it seems
|
||||
// like it's tricky to add that and still have the type
|
||||
// inference work correctly for the factory output.
|
||||
if (overrideOptions.output && !overrideOptions.factory) {
|
||||
throw new Error(
|
||||
'Refused to override output without also overriding factory',
|
||||
);
|
||||
}
|
||||
|
||||
return createExtension({
|
||||
kind: newOptions.kind,
|
||||
namespace: newOptions.namespace,
|
||||
|
||||
@@ -213,11 +213,17 @@ export class ExtensionTester<UOutput extends AnyExtensionDataRef> {
|
||||
const [subject, ...rest] = this.#extensions;
|
||||
|
||||
const extensionsConfig: JsonArray = [
|
||||
...rest.map(extension => ({
|
||||
[extension.id]: {
|
||||
config: extension.config,
|
||||
},
|
||||
})),
|
||||
...rest.flatMap(extension =>
|
||||
extension.config
|
||||
? [
|
||||
{
|
||||
[extension.id]: {
|
||||
config: extension.config,
|
||||
},
|
||||
},
|
||||
]
|
||||
: [],
|
||||
),
|
||||
{
|
||||
[subject.id]: {
|
||||
config: subject.config,
|
||||
|
||||
Reference in New Issue
Block a user