backend-test-utils: add update method for mockServices.rootConfig

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2025-08-20 12:30:02 +02:00
parent d0161c57b4
commit 4e2c23737e
6 changed files with 60 additions and 3 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/backend-test-utils': minor
---
The `mockServices.rootConfig()` instance now has an `update` method that can be used to test configuration subscriptions and updates.
+2
View File
@@ -71,6 +71,7 @@
"fs-extra": "^11.0.0",
"keyv": "^5.2.1",
"knex": "^3.0.0",
"lodash": "^4.17.21",
"mysql2": "^3.0.0",
"pg": "^8.11.3",
"pg-connection-string": "^2.3.0",
@@ -84,6 +85,7 @@
"devDependencies": {
"@backstage/cli": "workspace:^",
"@types/jest": "*",
"@types/lodash": "^4.14.151",
"@types/supertest": "^2.0.8",
"supertest": "^7.0.0"
}
+5 -1
View File
@@ -305,7 +305,11 @@ export namespace mockServices {
) => ServiceMock<PermissionsRegistryService>;
}
// (undocumented)
export function rootConfig(options?: rootConfig.Options): RootConfigService;
export function rootConfig(
options?: rootConfig.Options,
): RootConfigService & {
update(options: { data: JsonObject }): void;
};
// (undocumented)
export namespace rootConfig {
// (undocumented)
@@ -30,3 +30,37 @@ describe('mockServices', () => {
expect(mockServices[key].factory()).toEqual(expect.any(Object));
});
});
describe('mockServices.rootConfig()', () => {
it('should notify about updates', async () => {
const config = mockServices.rootConfig();
const fooConfig = config.getConfig('foo');
const rootListener = jest.fn();
const fooListener = jest.fn();
config.subscribe?.(rootListener);
fooConfig.subscribe?.(fooListener);
expect(rootListener).toHaveBeenCalledTimes(0);
expect(fooListener).toHaveBeenCalledTimes(0);
config.update({ data: { foo: { bar: 1, baz: 2 } } });
expect(rootListener).toHaveBeenCalledTimes(1);
expect(fooListener).toHaveBeenCalledTimes(1);
config.update({ data: { foo: { baz: 2, bar: 1 } } });
// Doesn't notify, no changes
expect(rootListener).toHaveBeenCalledTimes(1);
expect(fooListener).toHaveBeenCalledTimes(1);
config.update({ data: { foo: { bar: 1, baz: 2 }, unrelated: 'key' } });
// Notifies all listeners, even if an unrelated key was changed
expect(rootListener).toHaveBeenCalledTimes(2);
expect(fooListener).toHaveBeenCalledTimes(2);
});
});
@@ -58,6 +58,8 @@ import { MockEventsService } from './MockEventsService';
import { MockPermissionsService } from './MockPermissionsService';
import { simpleMock } from './simpleMock';
import { MockSchedulerService } from './MockSchedulerService';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { ObservableConfigProxy } from '../../../config-loader/src/sources/ObservableConfigProxy';
/** @internal */
function createLoggerMock() {
@@ -137,8 +139,16 @@ function simpleFactoryWithOptions<
* ```
*/
export namespace mockServices {
export function rootConfig(options?: rootConfig.Options): RootConfigService {
return new ConfigReader(options?.data, 'mock-config');
export function rootConfig(
options?: rootConfig.Options,
): RootConfigService & { update(options: { data: JsonObject }): void } {
const config = ObservableConfigProxy.create(new AbortController());
config.setConfig(new ConfigReader(options?.data ?? {}, 'mock-config'));
return Object.assign(config, {
update({ data }: { data: JsonObject }): void {
config.setConfig(new ConfigReader(data, 'mock-config'));
},
});
}
export namespace rootConfig {
export type Options = { data?: JsonObject };
+2
View File
@@ -2755,6 +2755,7 @@ __metadata:
"@types/express-serve-static-core": "npm:^4.17.5"
"@types/jest": "npm:*"
"@types/keyv": "npm:^4.2.0"
"@types/lodash": "npm:^4.14.151"
"@types/qs": "npm:^6.9.6"
"@types/supertest": "npm:^2.0.8"
better-sqlite3: "npm:^12.0.0"
@@ -2763,6 +2764,7 @@ __metadata:
fs-extra: "npm:^11.0.0"
keyv: "npm:^5.2.1"
knex: "npm:^3.0.0"
lodash: "npm:^4.17.21"
mysql2: "npm:^3.0.0"
pg: "npm:^8.11.3"
pg-connection-string: "npm:^2.3.0"