Skip to content

Commit 4c64b0d

Browse files
committed
test: add unit test for handling identify failure before initialization
This commit will also fix this issue
1 parent 0d640bf commit 4c64b0d

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

packages/sdk/browser/__tests__/BrowserClient.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,4 +463,42 @@ describe('given a mock platform for a BrowserClient', () => {
463463
error: identifyError,
464464
});
465465
});
466+
467+
it('resolves waitForInitialization with failed status when identify fails before waitForInitialization is called', async () => {
468+
const errorPlatform = makeBasicPlatform();
469+
const identifyError = new Error('Network error');
470+
471+
// Mock fetch to reject with an error
472+
errorPlatform.requests.fetch = jest.fn((_url: string, _options: any) =>
473+
Promise.reject(identifyError),
474+
) as any;
475+
476+
const client = makeClient(
477+
'client-side-id',
478+
AutoEnvAttributes.Disabled,
479+
{ streaming: false, logger, diagnosticOptOut: true, sendEvents: false, fetchGoals: false },
480+
errorPlatform,
481+
);
482+
483+
// Start identify which will fail BEFORE waitForInitialization is called
484+
const identifyPromise = client.identify({ key: 'user-key', kind: 'user' });
485+
486+
await jest.advanceTimersByTimeAsync(4000); // trigger all poll retries
487+
488+
// Wait for identify to fail
489+
await expect(identifyPromise).resolves.toEqual({
490+
status: 'error',
491+
error: identifyError,
492+
});
493+
494+
// Now call waitForInitialization AFTER identify has already failed
495+
// It should return the failed status immediately, not timeout
496+
const waitPromise = client.waitForInitialization({ timeout: 10 });
497+
498+
// Verify that waitForInitialization returns immediately with failed status
499+
await expect(waitPromise).resolves.toEqual({
500+
status: 'failed',
501+
error: identifyError,
502+
});
503+
});
466504
});

packages/sdk/browser/src/BrowserClient.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class BrowserClientImpl extends LDClientImpl {
4242
private readonly _plugins?: LDPlugin[];
4343
private _initializedPromise?: Promise<LDWaitForInitializationResult>;
4444
private _initResolve?: (result: LDWaitForInitializationResult) => void;
45-
private _isInitialized: boolean = false;
45+
private _initializeResult?: LDWaitForInitializationResult;
4646

4747
constructor(
4848
clientSideId: string,
@@ -224,10 +224,11 @@ class BrowserClientImpl extends LDClientImpl {
224224
}
225225
const res = await super.identifyResult(context, identifyOptionsWithUpdatedDefaults);
226226
if (res.status === 'completed') {
227-
this._isInitialized = true;
228-
this._initResolve?.({ status: 'complete' });
227+
this._initializeResult = { status: 'complete' };
228+
this._initResolve?.(this._initializeResult);
229229
} else if (res.status === 'error') {
230-
this._initResolve?.({ status: 'failed', error: res.error });
230+
this._initializeResult = { status: 'failed', error: res.error };
231+
this._initResolve?.(this._initializeResult);
231232
}
232233

233234
this._goalManager?.startTracking();
@@ -250,10 +251,9 @@ class BrowserClientImpl extends LDClientImpl {
250251
return this._promiseWithTimeout(this._initializedPromise, timeout);
251252
}
252253

253-
if (this._isInitialized) {
254-
return Promise.resolve({
255-
status: 'complete',
256-
});
254+
// If initialization has already completed (successfully or failed), return the result immediately
255+
if (this._initializeResult) {
256+
return Promise.resolve(this._initializeResult);
257257
}
258258

259259
if (!this._initializedPromise) {

0 commit comments

Comments
 (0)