Skip to content

[FSSDK-10090] Refactor ODP integration #920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Apr 5, 2024
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fix segment manager tests
  • Loading branch information
raju-opti committed Mar 28, 2024
commit cd5dbad11e9bbffc1abb05fc29c3c3635faf7c8d
73 changes: 36 additions & 37 deletions tests/odpSegmentManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ describe('OdpSegmentManager', () => {
const mockLogHandler = mock<LogHandler>();
const mockRequestHandler = mock<RequestHandler>();

let manager: OdpSegmentManager;
let odpConfig: OdpConfig;
const apiManager = new MockOdpSegmentApiManager(instance(mockRequestHandler), instance(mockLogHandler));

let options: Array<OptimizelySegmentOption> = [];
Expand All @@ -57,111 +55,112 @@ describe('OdpSegmentManager', () => {
const validTestOdpConfig = new OdpConfig('valid-key', 'host', 'pixel-url', ['new-customer']);
const invalidTestOdpConfig = new OdpConfig('invalid-key', 'host', 'pixel-url', ['new-customer']);

const getSegmentsCache = () => {
return new LRUCache<string, string[]>({
maxSize: 1000,
timeout: 1000,
});
}

beforeEach(() => {
resetCalls(mockLogHandler);
resetCalls(mockRequestHandler);

const API_KEY = 'test-api-key';
const API_HOST = 'https://odp.example.com';
const PIXEL_URL = 'https://odp.pixel.com';
odpConfig = new OdpConfig(API_KEY, API_HOST, PIXEL_URL, []);
const segmentsCache = new LRUCache<string, string[]>({
maxSize: 1000,
timeout: 1000,
});

manager = new OdpSegmentManager(odpConfig, segmentsCache, apiManager);
});

it('should fetch segments successfully on cache miss.', async () => {
odpConfig.update(validTestOdpConfig);
setCache(userKey, '123', ['a']);
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, validTestOdpConfig);
setCache(manager, userKey, '123', ['a']);

const segments = await manager.fetchQualifiedSegments(userKey, userValue, options);
expect(segments).toEqual(['new-customer']);
});

it('should fetch segments successfully on cache hit.', async () => {
odpConfig.update(validTestOdpConfig);
setCache(userKey, userValue, ['a']);
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, validTestOdpConfig);
setCache(manager, userKey, userValue, ['a']);

const segments = await manager.fetchQualifiedSegments(userKey, userValue, options);
expect(segments).toEqual(['a']);
});

it('should throw an error when fetching segments returns an error.', async () => {
odpConfig.update(invalidTestOdpConfig);
it('should return null when fetching segments returns an error.', async () => {
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, invalidTestOdpConfig);

const segments = await manager.fetchQualifiedSegments(userKey, userValue, []);
expect(segments).toBeNull;
});

it('should ignore the cache if the option enum is included in the options array.', async () => {
odpConfig.update(validTestOdpConfig);
setCache(userKey, userValue, ['a']);
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, validTestOdpConfig);
setCache(manager, userKey, userValue, ['a']);
options = [OptimizelySegmentOption.IGNORE_CACHE];

const segments = await manager.fetchQualifiedSegments(userKey, userValue, options);
expect(segments).toEqual(['new-customer']);
expect(cacheCount()).toBe(1);
expect(cacheCount(manager)).toBe(1);
});

it('should ignore the cache if the option string is included in the options array.', async () => {
odpConfig.update(validTestOdpConfig);
setCache(userKey, userValue, ['a']);
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, validTestOdpConfig);
setCache(manager,userKey, userValue, ['a']);
// @ts-ignore
options = ['IGNORE_CACHE'];

const segments = await manager.fetchQualifiedSegments(userKey, userValue, options);
expect(segments).toEqual(['new-customer']);
expect(cacheCount()).toBe(1);
expect(cacheCount(manager)).toBe(1);
});

it('should reset the cache if the option enum is included in the options array.', async () => {
odpConfig.update(validTestOdpConfig);
setCache(userKey, userValue, ['a']);
setCache(userKey, '123', ['a']);
setCache(userKey, '456', ['a']);
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, validTestOdpConfig);
setCache(manager, userKey, userValue, ['a']);
setCache(manager, userKey, '123', ['a']);
setCache(manager, userKey, '456', ['a']);
options = [OptimizelySegmentOption.RESET_CACHE];

const segments = await manager.fetchQualifiedSegments(userKey, userValue, options);
expect(segments).toEqual(['new-customer']);
expect(peekCache(userKey, userValue)).toEqual(segments);
expect(cacheCount()).toBe(1);
expect(peekCache(manager, userKey, userValue)).toEqual(segments);
expect(cacheCount(manager)).toBe(1);
});

it('should reset the cache if the option string is included in the options array.', async () => {
odpConfig.update(validTestOdpConfig);
setCache(userKey, userValue, ['a']);
setCache(userKey, '123', ['a']);
setCache(userKey, '456', ['a']);
// @ts-ignore
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, validTestOdpConfig);
setCache(manager, userKey, userValue, ['a']);
setCache(manager, userKey, '123', ['a']);
setCache(manager, userKey, '456', ['a']);
// @ts-ignore
options = ['RESET_CACHE'];

const segments = await manager.fetchQualifiedSegments(userKey, userValue, options);
expect(segments).toEqual(['new-customer']);
expect(peekCache(userKey, userValue)).toEqual(segments);
expect(cacheCount()).toBe(1);
expect(peekCache(manager, userKey, userValue)).toEqual(segments);
expect(cacheCount(manager)).toBe(1);
});

it('should make a valid cache key.', () => {
const manager = new OdpSegmentManager(getSegmentsCache(), apiManager, mockLogHandler, validTestOdpConfig);
expect('vuid-$-test-user').toBe(manager.makeCacheKey(userKey, userValue));
});

// Utility Functions

function setCache(userKey: string, userValue: string, value: string[]) {
function setCache(manager: OdpSegmentManager, userKey: string, userValue: string, value: string[]) {
const cacheKey = manager.makeCacheKey(userKey, userValue);
manager.segmentsCache.save({
key: cacheKey,
value,
});
}

function peekCache(userKey: string, userValue: string): string[] | null {
function peekCache(manager: OdpSegmentManager, userKey: string, userValue: string): string[] | null {
const cacheKey = manager.makeCacheKey(userKey, userValue);
return (manager.segmentsCache as LRUCache<string, string[]>).peek(cacheKey);
}

const cacheCount = () => (manager.segmentsCache as LRUCache<string, string[]>).map.size;
const cacheCount = (manager: OdpSegmentManager) => (manager.segmentsCache as LRUCache<string, string[]>).map.size;
});