From 6537e5f8c1447d77d8071456bd8b0bec7f475719 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 1 Apr 2026 15:40:31 +0200 Subject: [PATCH] cli: fix type errors and test for embedded-postgres Fix implicit any types in startEmbeddedDb callbacks, replace the re-export type declaration with an inline type definition for the embedded-postgres module, and update runBackend tests to mock the config loading and use async timer advancement. Signed-off-by: Patrik Oldsberg Made-with: Cursor --- .../src/lib/runner/runBackend.test.ts | 73 +++++++++---------- .../src/lib/runner/startEmbeddedDb.ts | 6 +- packages/cli-module-build/src/types.d.ts | 18 ++++- 3 files changed, 55 insertions(+), 42 deletions(-) diff --git a/packages/cli-module-build/src/lib/runner/runBackend.test.ts b/packages/cli-module-build/src/lib/runner/runBackend.test.ts index 2b97ae352c..b4193cad52 100644 --- a/packages/cli-module-build/src/lib/runner/runBackend.test.ts +++ b/packages/cli-module-build/src/lib/runner/runBackend.test.ts @@ -49,6 +49,24 @@ jest.mock('ctrlc-windows', () => ({ ctrlc: jest.fn(), })); +jest.mock('@backstage/config-loader', () => ({ + ConfigSources: { + default: () => ({ + readConfigData: async function* readConfigData() { + yield { configs: [] }; + }, + }), + }, +})); + +jest.mock('@backstage/config', () => ({ + ConfigReader: { + fromConfigs: () => ({ + getOptionalString: () => undefined, + }), + }, +})); + describe('runBackend', () => { let originalEnv: NodeJS.ProcessEnv; let originalPlatform: string; @@ -82,92 +100,73 @@ describe('runBackend', () => { }); describe('--no-node-snapshot argument handling', () => { - it('should pass --no-node-snapshot when NODE_OPTIONS is not set', () => { + it('should pass --no-node-snapshot when NODE_OPTIONS is not set', async () => { delete process.env.NODE_OPTIONS; - runBackend({ - entry: 'src/index', - }); + runBackend({ entry: 'src/index' }); - // Fast-forward past the debounce delay (100ms) - jest.advanceTimersByTime(100); + await jest.advanceTimersByTimeAsync(100); expect(mockSpawn).toHaveBeenCalled(); const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; expect(spawnArgs).toContain('--no-node-snapshot'); }); - it('should pass --no-node-snapshot when NODE_OPTIONS exists without --node-snapshot', () => { + it('should pass --no-node-snapshot when NODE_OPTIONS exists without --node-snapshot', async () => { process.env.NODE_OPTIONS = '--max-old-space-size=4096'; - runBackend({ - entry: 'src/index', - }); + runBackend({ entry: 'src/index' }); - // Fast-forward past the debounce delay (100ms) - jest.advanceTimersByTime(100); + await jest.advanceTimersByTimeAsync(100); expect(mockSpawn).toHaveBeenCalled(); const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; expect(spawnArgs).toContain('--no-node-snapshot'); }); - it('should not pass --no-node-snapshot when --node-snapshot already exists in NODE_OPTIONS', () => { + it('should not pass --no-node-snapshot when --node-snapshot already exists in NODE_OPTIONS', async () => { process.env.NODE_OPTIONS = '--node-snapshot --max-old-space-size=4096'; - runBackend({ - entry: 'src/index', - }); + runBackend({ entry: 'src/index' }); - // Fast-forward past the debounce delay (100ms) - jest.advanceTimersByTime(100); + await jest.advanceTimersByTimeAsync(100); expect(mockSpawn).toHaveBeenCalled(); const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; expect(spawnArgs).not.toContain('--no-node-snapshot'); }); - it('should not pass --no-node-snapshot when --node-snapshot exists in the middle of NODE_OPTIONS', () => { + it('should not pass --no-node-snapshot when --node-snapshot exists in the middle of NODE_OPTIONS', async () => { process.env.NODE_OPTIONS = '--max-old-space-size=4096 --node-snapshot --inspect'; - runBackend({ - entry: 'src/index', - }); + runBackend({ entry: 'src/index' }); - // Fast-forward past the debounce delay (100ms) - jest.advanceTimersByTime(100); + await jest.advanceTimersByTimeAsync(100); expect(mockSpawn).toHaveBeenCalled(); const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; expect(spawnArgs).not.toContain('--no-node-snapshot'); }); - it('should pass --no-node-snapshot even with trailing spaces in NODE_OPTIONS', () => { + it('should pass --no-node-snapshot even with trailing spaces in NODE_OPTIONS', async () => { process.env.NODE_OPTIONS = '--max-old-space-size=4096 '; - runBackend({ - entry: 'src/index', - }); + runBackend({ entry: 'src/index' }); - // Fast-forward past the debounce delay (100ms) - jest.advanceTimersByTime(100); + await jest.advanceTimersByTimeAsync(100); expect(mockSpawn).toHaveBeenCalled(); const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; expect(spawnArgs).toContain('--no-node-snapshot'); }); - it('should pass --no-node-snapshot alongside other option args like --inspect', () => { + it('should pass --no-node-snapshot alongside other option args like --inspect', async () => { delete process.env.NODE_OPTIONS; - runBackend({ - entry: 'src/index', - inspectEnabled: true, - }); + runBackend({ entry: 'src/index', inspectEnabled: true }); - // Fast-forward past the debounce delay (100ms) - jest.advanceTimersByTime(100); + await jest.advanceTimersByTimeAsync(100); expect(mockSpawn).toHaveBeenCalled(); const spawnArgs = mockSpawn.mock.calls[0][1] as string[]; diff --git a/packages/cli-module-build/src/lib/runner/startEmbeddedDb.ts b/packages/cli-module-build/src/lib/runner/startEmbeddedDb.ts index 85de29cda2..607a371003 100644 --- a/packages/cli-module-build/src/lib/runner/startEmbeddedDb.ts +++ b/packages/cli-module-build/src/lib/runner/startEmbeddedDb.ts @@ -16,7 +16,7 @@ import os from 'node:os'; import fs from 'fs-extra'; -import { resolve as resolvePath } from 'path'; +import { resolve as resolvePath } from 'node:path'; import { getPortPromise } from 'portfinder'; export async function startEmbeddedDb() { @@ -42,8 +42,8 @@ export async function startEmbeddedDb() { password, port, persistent: false, - onError(_messageOrError) {}, - onLog(_message) {}, + onError(_messageOrError: unknown) {}, + onLog(_message: unknown) {}, }); // Create the cluster config files diff --git a/packages/cli-module-build/src/types.d.ts b/packages/cli-module-build/src/types.d.ts index 2e30114f10..18f1c9c11a 100644 --- a/packages/cli-module-build/src/types.d.ts +++ b/packages/cli-module-build/src/types.d.ts @@ -14,7 +14,21 @@ * limitations under the License. */ -// It's missing a types entry point, but has types in dist declare module 'embedded-postgres' { - export { default } from 'embedded-postgres/dist/index'; + export interface EmbeddedPostgresOptions { + databaseDir: string; + user: string; + password: string; + port: number; + persistent: boolean; + onError?: (messageOrError: unknown) => void; + onLog?: (message: unknown) => void; + } + + export default class EmbeddedPostgres { + constructor(options: EmbeddedPostgresOptions); + initialise(): Promise; + start(): Promise; + stop(): Promise; + } }