From 167a4bba6ca0218e9ff144b2883c274aaedba500 Mon Sep 17 00:00:00 2001 From: sunlei Date: Thu, 18 Jun 2026 03:17:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=9D=E7=95=99=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=A9=BA=E5=AD=97=E7=AC=A6=E4=B8=B2=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/qqbot-config.service.ts | 2 +- .../plugin-host-bridge.spec.ts | 59 +++++++++++++++---- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/modules/qqbot/core/application/config/qqbot-config.service.ts b/src/modules/qqbot/core/application/config/qqbot-config.service.ts index 2cc44aa..30a5e38 100644 --- a/src/modules/qqbot/core/application/config/qqbot-config.service.ts +++ b/src/modules/qqbot/core/application/config/qqbot-config.service.ts @@ -48,7 +48,7 @@ export class QqbotConfigService { const record = await this.configRepository.findOne({ where: { configKey }, }); - return record?.configValue || undefined; + return record?.configValue ?? undefined; } /** diff --git a/test/modules/qqbot/plugin-platform/plugin-host-bridge.spec.ts b/test/modules/qqbot/plugin-platform/plugin-host-bridge.spec.ts index 4de1c6c..1e8f350 100644 --- a/test/modules/qqbot/plugin-platform/plugin-host-bridge.spec.ts +++ b/test/modules/qqbot/plugin-platform/plugin-host-bridge.spec.ts @@ -27,16 +27,9 @@ describe('QQBot plugin host bridge', () => { SAMPLE_TOKEN: 'token-1', SAMPLE_EMPTY: undefined, }; - const configService = { - /** - * Reads the fixture config value requested by a plugin host call. - * @param configKey - Package-owned config key from the host call arguments. - * @returns Stored fixture value or `undefined` when the key is absent. - */ - getConfigValue: jest.fn( - async (configKey: string) => configValues[configKey], - ), - } as unknown as QqbotConfigService; + const configService = new QqbotConfigService( + createConfigRepository(configValues), + ); const dictService = { getDictByKey: jest.fn(), getDictItemsByKey: jest.fn(), @@ -84,6 +77,23 @@ describe('QQBot plugin host bridge', () => { }); }); + it('preserves configured empty string values in config snapshots', async () => { + configValues.SAMPLE_EMPTY = ''; + + await expect( + bridge.handleHostCall(createDescriptor(), { + args: { keys: ['SAMPLE_EMPTY'] }, + method: 'getConfigMany', + pluginKey: 'sample', + }), + ).resolves.toEqual({ + ok: true, + value: { + SAMPLE_EMPTY: '', + }, + }); + }); + it('rejects JSON reads that try to escape the package root', async () => { await expect( bridge.handleHostCall(createDescriptor(), { @@ -195,3 +205,32 @@ describe('QQBot plugin host bridge', () => { }; } }); + +/** + * Creates a minimal config repository that lets QqbotConfigService read fixture values through its real raw-value method. + * @param values - Config key/value fixture; absent keys behave like missing records. + * @returns Repository-shaped fixture used by QqbotConfigService in host bridge tests. + */ +function createConfigRepository( + values: Record, +): ConstructorParameters[0] { + /** + * Finds one QQBot config fixture using the TypeORM `where.configKey` query shape. + * @param query - TypeORM-style lookup object produced by QqbotConfigService. + * @returns Fixture record with the stored config value, or `null` when the key is not present. + */ + const findOne = async (query: { where?: { configKey?: string } }) => { + const configKey = query.where?.configKey; + if ( + !configKey || + !Object.prototype.hasOwnProperty.call(values, configKey) + ) { + return null; + } + return { configValue: values[configKey] }; + }; + + return { + findOne: jest.fn(findOne), + } as unknown as ConstructorParameters[0]; +}