Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 208 additions & 1 deletion packages/sdk/react-native/__tests__/MobileDataManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ describe('given a MobileDataManager with mocked dependencies', () => {
close: eventSourceCloseMethod,
})),
fetch: mockedFetch,
getEventSourceCapabilities: jest.fn(),
getEventSourceCapabilities: jest.fn(() => ({
customMethod: true,
})),
},
storage: new PlatformStorage(config.logger),
encoding: new PlatformEncoding(),
Expand Down Expand Up @@ -343,4 +345,209 @@ describe('given a MobileDataManager with mocked dependencies', () => {
'[MobileDataManager] Identify called after data manager was closed.',
);
});

it('uses REPORT method and includes context in body when useReport is true', async () => {
const useReportConfig = { ...config, useReport: true };
mobileDataManager = new MobileDataManager(
platform,
flagManager,
'test-credential',
useReportConfig,
rnConfig,
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/context`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
throw new Error('Ping for polling unsupported.');
},
}),
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/meval`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
return `/mping`;
},
}),
baseHeaders,
emitter,
diagnosticsManager,
);

const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
const identifyResolve = jest.fn();
const identifyReject = jest.fn();

await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);

expect(platform.requests.createEventSource).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
method: 'REPORT',
body: JSON.stringify(Context.toLDContext(context)),
headers: expect.objectContaining({
'content-type': 'application/json',
}),
}),
);
});

it('includes withReasons query parameter when withReasons is true', async () => {
const withReasonsConfig = { ...config, withReasons: true };
mobileDataManager = new MobileDataManager(
platform,
flagManager,
'test-credential',
withReasonsConfig,
rnConfig,
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/context`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
throw new Error('Ping for polling unsupported.');
},
}),
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/meval`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
return `/mping`;
},
}),
baseHeaders,
emitter,
diagnosticsManager,
);

const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
const identifyResolve = jest.fn();
const identifyReject = jest.fn();

await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);

expect(platform.requests.createEventSource).toHaveBeenCalledWith(
expect.stringContaining('?withReasons=true'),
expect.anything(),
);
});

it('uses GET method and does not include context in body when useReport is false', async () => {
const useReportConfig = { ...config, useReport: false };
mobileDataManager = new MobileDataManager(
platform,
flagManager,
'test-credential',
useReportConfig,
rnConfig,
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/context`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
throw new Error('Ping for polling unsupported.');
},
}),
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/meval`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
return `/mping`;
},
}),
baseHeaders,
emitter,
diagnosticsManager,
);

const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
const identifyResolve = jest.fn();
const identifyReject = jest.fn();

await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);

expect(platform.requests.createEventSource).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
headers: expect.not.objectContaining({
'content-type': 'application/json',
}),
}),
);
expect((platform.requests.createEventSource as jest.Mock).mock.calls[0][1].method).not.toBe(
'REPORT',
);
});

it('does not include withReasons query parameter when withReasons is false', async () => {
const withReasonsConfig = { ...config, withReasons: false };
mobileDataManager = new MobileDataManager(
platform,
flagManager,
'test-credential',
withReasonsConfig,
rnConfig,
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/contexts/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/msdk/evalx/context`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
throw new Error('Ping for polling unsupported.');
},
}),
() => ({
pathGet(encoding: Encoding, _plainContextString: string): string {
return `/meval/${base64UrlEncode(_plainContextString, encoding)}`;
},
pathReport(_encoding: Encoding, _plainContextString: string): string {
return `/meval`;
},
pathPing(_encoding: Encoding, _plainContextString: string): string {
return `/mping`;
},
}),
baseHeaders,
emitter,
diagnosticsManager,
);

const context = Context.fromLDContext({ kind: 'user', key: 'test-user' });
const identifyOptions: LDIdentifyOptions = { waitForNetworkResults: false };
const identifyResolve = jest.fn();
const identifyReject = jest.fn();

await mobileDataManager.identify(identifyResolve, identifyReject, context, identifyOptions);

expect(platform.requests.createEventSource).toHaveBeenCalledWith(
expect.not.stringContaining('withReasons=true'),
expect.anything(),
);
});
});
2 changes: 1 addition & 1 deletion packages/sdk/react-native/src/MobileDataManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ export default class MobileDataManager extends BaseDataManager {
this.platform.encoding!,
this.baseHeaders,
[],
this.config.useReport,
this.config.withReasons,
this.config.useReport,
);

this.updateProcessor?.close();
Expand Down
Loading