diff --git a/packages/shared/sdk-client/__tests__/HookRunner.test.ts b/packages/shared/sdk-client/__tests__/HookRunner.test.ts index 60ce7b7a1..bb8019bce 100644 --- a/packages/shared/sdk-client/__tests__/HookRunner.test.ts +++ b/packages/shared/sdk-client/__tests__/HookRunner.test.ts @@ -202,6 +202,33 @@ describe('given a hook runner and test hook', () => { ); }); + it('should log "unknown hook" when getMetadata returns an empty name', () => { + const errorHook: Hook = { + getMetadata: jest.fn().mockImplementation(() => ({ + name: '', + })), + beforeEvaluation: jest.fn().mockImplementation(() => { + throw new Error('Test error in beforeEvaluation'); + }), + afterEvaluation: jest.fn(), + }; + + const errorHookRunner = new HookRunner(logger, [errorHook]); + + errorHookRunner.withEvaluation('test-flag', { kind: 'user', key: 'user-123' }, false, () => ({ + value: true, + variationIndex: 1, + reason: { kind: 'OFF' }, + })); + + // Verify that the error was logged with the correct hook name + expect(logger.error).toHaveBeenCalledWith( + expect.stringContaining( + 'An error was encountered in "beforeEvaluation" of the "unknown hook" hook: Error: Test error in beforeEvaluation', + ), + ); + }); + it('should log the correct hook name when an error occurs', () => { // Modify the testHook to throw an error in beforeEvaluation testHook.beforeEvaluation = jest.fn().mockImplementation(() => { diff --git a/packages/shared/sdk-client/src/HookRunner.ts b/packages/shared/sdk-client/src/HookRunner.ts index d73277cc9..f7ea76891 100644 --- a/packages/shared/sdk-client/src/HookRunner.ts +++ b/packages/shared/sdk-client/src/HookRunner.ts @@ -29,9 +29,9 @@ function tryExecuteStage( } } -function getHookName(logger: LDLogger, hook?: Hook): string { +function getHookName(logger: LDLogger, hook: Hook): string { try { - return hook?.getMetadata().name ?? UNKNOWN_HOOK_NAME; + return hook.getMetadata().name || UNKNOWN_HOOK_NAME; } catch { logger.error(`Exception thrown getting metadata for hook. Unable to get hook name.`); return UNKNOWN_HOOK_NAME; @@ -58,14 +58,14 @@ function executeAfterEvaluation( logger: LDLogger, hooks: Hook[], hookContext: EvaluationSeriesContext, - updatedData: (EvaluationSeriesData | undefined)[], + updatedData: EvaluationSeriesData[], result: LDEvaluationDetail, ) { // This iterates in reverse, versus reversing a shallow copy of the hooks, // for efficiency. for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) { const hook = hooks[hookIndex]; - const data = updatedData[hookIndex] ?? {}; + const data = updatedData[hookIndex]; tryExecuteStage( logger, AFTER_EVALUATION_STAGE_NAME, @@ -96,14 +96,14 @@ function executeAfterIdentify( logger: LDLogger, hooks: Hook[], hookContext: IdentifySeriesContext, - updatedData: (IdentifySeriesData | undefined)[], + updatedData: IdentifySeriesData[], result: IdentifyResult, ) { // This iterates in reverse, versus reversing a shallow copy of the hooks, // for efficiency. for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) { const hook = hooks[hookIndex]; - const data = updatedData[hookIndex] ?? {}; + const data = updatedData[hookIndex]; tryExecuteStage( logger, AFTER_EVALUATION_STAGE_NAME, diff --git a/packages/shared/sdk-client/src/api/LDOptions.ts b/packages/shared/sdk-client/src/api/LDOptions.ts index 123bcd218..c88c608eb 100644 --- a/packages/shared/sdk-client/src/api/LDOptions.ts +++ b/packages/shared/sdk-client/src/api/LDOptions.ts @@ -1,4 +1,5 @@ import type { LDLogger } from '@launchdarkly/js-sdk-common'; + import { Hook } from './integrations/Hooks'; export interface LDOptions {