Skip to content

Commit 2e095c5

Browse files
artyorshkinyoklion
andauthored
fix: Requestor initialized with wrong withReasons and useReport config (#869)
**Requirements** - [ ] I have added test coverage for new or changed functionality - [ ] I have followed the repository's [pull request submission guidelines](../blob/main/CONTRIBUTING.md#submitting-pull-requests) - [ ] I have validated my changes against all supported platform versions **Related issues** #868 **Describe the solution you've provided** Provides Requestor configuration in correct order. **Describe alternatives you've considered** None. **Additional context** Fixes #868 Edit: in functions with many arguments, consider arguments with an object, so that it's more clear what values are assigned to which keys. --------- Co-authored-by: Ryan Lamb <4955475+kinyoklion@users.noreply.github.com>
1 parent 0b50153 commit 2e095c5

File tree

2 files changed

+209
-2
lines changed

2 files changed

+209
-2
lines changed

packages/sdk/react-native/__tests__/MobileDataManager.test.ts

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ describe('given a MobileDataManager with mocked dependencies', () => {
103103
close: eventSourceCloseMethod,
104104
})),
105105
fetch: mockedFetch,
106-
getEventSourceCapabilities: jest.fn(),
106+
getEventSourceCapabilities: jest.fn(() => ({
107+
customMethod: true,
108+
})),
107109
},
108110
storage: new PlatformStorage(config.logger),
109111
encoding: new PlatformEncoding(),
@@ -343,4 +345,209 @@ describe('given a MobileDataManager with mocked dependencies', () => {
343345
'[MobileDataManager] Identify called after data manager was closed.',
344346
);
345347
});
348+
349+
it('uses REPORT method and includes context in body when useReport is true', async () => {
350+
const useReportConfig = { ...config, useReport: true };
351+
mobileDataManager = new MobileDataManager(
352+
platform,
353+
flagManager,
354+
'test-credential',
355+
useReportConfig,
356+
rnConfig,
357+
() => ({
358+
pathGet(encoding: Encoding, _plainContextString: string): string {
359+
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
360+
},
361+
pathReport(_encoding: Encoding, _plainContextString: string): string {
362+
return `/msdk/evalx/context`;
363+
},
364+
pathPing(_encoding: Encoding, _plainContextString: string): string {
365+
throw new Error('Ping for polling unsupported.');
366+
},
367+
}),
368+
() => ({
369+
pathGet(encoding: Encoding, _plainContextString: string): string {
370+
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
371+
},
372+
pathReport(_encoding: Encoding, _plainContextString: string): string {
373+
return `/meval`;
374+
},
375+
pathPing(_encoding: Encoding, _plainContextString: string): string {
376+
return `/mping`;
377+
},
378+
}),
379+
baseHeaders,
380+
emitter,
381+
diagnosticsManager,
382+
);
383+
384+
const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
385+
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
386+
const identifyResolve = jest.fn();
387+
const identifyReject = jest.fn();
388+
389+
await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);
390+
391+
expect(platform.requests.createEventSource).toHaveBeenCalledWith(
392+
expect.anything(),
393+
expect.objectContaining({
394+
method: 'REPORT',
395+
body: JSON.stringify(Context.toLDContext(context)),
396+
headers: expect.objectContaining({
397+
'content-type': 'application/json',
398+
}),
399+
}),
400+
);
401+
});
402+
403+
it('includes withReasons query parameter when withReasons is true', async () => {
404+
const withReasonsConfig = { ...config, withReasons: true };
405+
mobileDataManager = new MobileDataManager(
406+
platform,
407+
flagManager,
408+
'test-credential',
409+
withReasonsConfig,
410+
rnConfig,
411+
() => ({
412+
pathGet(encoding: Encoding, _plainContextString: string): string {
413+
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
414+
},
415+
pathReport(_encoding: Encoding, _plainContextString: string): string {
416+
return `/msdk/evalx/context`;
417+
},
418+
pathPing(_encoding: Encoding, _plainContextString: string): string {
419+
throw new Error('Ping for polling unsupported.');
420+
},
421+
}),
422+
() => ({
423+
pathGet(encoding: Encoding, _plainContextString: string): string {
424+
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
425+
},
426+
pathReport(_encoding: Encoding, _plainContextString: string): string {
427+
return `/meval`;
428+
},
429+
pathPing(_encoding: Encoding, _plainContextString: string): string {
430+
return `/mping`;
431+
},
432+
}),
433+
baseHeaders,
434+
emitter,
435+
diagnosticsManager,
436+
);
437+
438+
const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
439+
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
440+
const identifyResolve = jest.fn();
441+
const identifyReject = jest.fn();
442+
443+
await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);
444+
445+
expect(platform.requests.createEventSource).toHaveBeenCalledWith(
446+
expect.stringContaining('?withReasons=true'),
447+
expect.anything(),
448+
);
449+
});
450+
451+
it('uses GET method and does not include context in body when useReport is false', async () => {
452+
const useReportConfig = { ...config, useReport: false };
453+
mobileDataManager = new MobileDataManager(
454+
platform,
455+
flagManager,
456+
'test-credential',
457+
useReportConfig,
458+
rnConfig,
459+
() => ({
460+
pathGet(encoding: Encoding, _plainContextString: string): string {
461+
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
462+
},
463+
pathReport(_encoding: Encoding, _plainContextString: string): string {
464+
return `/msdk/evalx/context`;
465+
},
466+
pathPing(_encoding: Encoding, _plainContextString: string): string {
467+
throw new Error('Ping for polling unsupported.');
468+
},
469+
}),
470+
() => ({
471+
pathGet(encoding: Encoding, _plainContextString: string): string {
472+
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
473+
},
474+
pathReport(_encoding: Encoding, _plainContextString: string): string {
475+
return `/meval`;
476+
},
477+
pathPing(_encoding: Encoding, _plainContextString: string): string {
478+
return `/mping`;
479+
},
480+
}),
481+
baseHeaders,
482+
emitter,
483+
diagnosticsManager,
484+
);
485+
486+
const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
487+
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
488+
const identifyResolve = jest.fn();
489+
const identifyReject = jest.fn();
490+
491+
await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);
492+
493+
expect(platform.requests.createEventSource).toHaveBeenCalledWith(
494+
expect.anything(),
495+
expect.objectContaining({
496+
headers: expect.not.objectContaining({
497+
'content-type': 'application/json',
498+
}),
499+
}),
500+
);
501+
expect((platform.requests.createEventSource as jest.Mock).mock.calls[0][1].method).not.toBe(
502+
'REPORT',
503+
);
504+
});
505+
506+
it('does not include withReasons query parameter when withReasons is false', async () => {
507+
const withReasonsConfig = { ...config, withReasons: false };
508+
mobileDataManager = new MobileDataManager(
509+
platform,
510+
flagManager,
511+
'test-credential',
512+
withReasonsConfig,
513+
rnConfig,
514+
() => ({
515+
pathGet(encoding: Encoding, _plainContextString: string): string {
516+
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
517+
},
518+
pathReport(_encoding: Encoding, _plainContextString: string): string {
519+
return `/msdk/evalx/context`;
520+
},
521+
pathPing(_encoding: Encoding, _plainContextString: string): string {
522+
throw new Error('Ping for polling unsupported.');
523+
},
524+
}),
525+
() => ({
526+
pathGet(encoding: Encoding, _plainContextString: string): string {
527+
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
528+
},
529+
pathReport(_encoding: Encoding, _plainContextString: string): string {
530+
return `/meval`;
531+
},
532+
pathPing(_encoding: Encoding, _plainContextString: string): string {
533+
return `/mping`;
534+
},
535+
}),
536+
baseHeaders,
537+
emitter,
538+
diagnosticsManager,
539+
);
540+
541+
const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
542+
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
543+
const identifyResolve = jest.fn();
544+
const identifyReject = jest.fn();
545+
546+
await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);
547+
548+
expect(platform.requests.createEventSource).toHaveBeenCalledWith(
549+
expect.not.stringContaining('withReasons=true'),
550+
expect.anything(),
551+
);
552+
});
346553
});

packages/sdk/react-native/src/MobileDataManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ export default class MobileDataManager extends BaseDataManager {
109109
this.platform.encoding!,
110110
this.baseHeaders,
111111
[],
112-
this.config.useReport,
113112
this.config.withReasons,
113+
this.config.useReport,
114114
);
115115

116116
this.updateProcessor?.close();

0 commit comments

Comments
 (0)