Skip to content
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

[FSSDK-9607] add pixelUrl to OdpConfig #888

Merged
merged 4 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
19 changes: 18 additions & 1 deletion lib/core/odp/odp_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ export class OdpConfig {
return this._apiKey;
}

/**
* Url for sending events via pixel.
* @private
*/
private _pixelUrl: string;

/**
* Getter to retrieve the ODP pixel URL
* @public
*/
get pixelUrl(): string {
return this._pixelUrl;
}

/**
* All ODP segments used in the current datafile (associated with apiHost/apiKey).
* @private
Expand All @@ -59,9 +73,10 @@ export class OdpConfig {
return this._segmentsToCheck;
}

constructor(apiKey?: string, apiHost?: string, segmentsToCheck?: string[]) {
constructor(apiKey?: string, apiHost?: string, pixelUrl?: string, segmentsToCheck?: string[]) {
this._apiKey = apiKey ?? '';
this._apiHost = apiHost ?? '';
this._pixelUrl = pixelUrl ?? '';
this._segmentsToCheck = segmentsToCheck ?? [];
}

Expand All @@ -76,6 +91,7 @@ export class OdpConfig {
} else {
if (config.apiKey) this._apiKey = config.apiKey;
if (config.apiHost) this._apiHost = config.apiHost;
if (config.pixelUrl) this._pixelUrl = config.pixelUrl;
if (config.segmentsToCheck) this._segmentsToCheck = config.segmentsToCheck;

return true;
Expand All @@ -98,6 +114,7 @@ export class OdpConfig {
return (
this._apiHost === configToCompare._apiHost &&
this._apiKey === configToCompare._apiKey &&
this._pixelUrl === configToCompare._pixelUrl &&
checkArrayEquality(this.segmentsToCheck, configToCompare._segmentsToCheck)
);
}
Expand Down
6 changes: 3 additions & 3 deletions lib/core/odp/odp_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface IOdpManager {

eventManager: IOdpEventManager | undefined;

updateSettings({ apiKey, apiHost, segmentsToCheck }: OdpConfig): boolean;
updateSettings({ apiKey, apiHost, pixelUrl, segmentsToCheck }: OdpConfig): boolean;

close(): void;

Expand Down Expand Up @@ -97,7 +97,7 @@ export abstract class OdpManager implements IOdpManager {
/**
* Provides a method to update ODP Manager's ODP Config API Key, API Host, and Audience Segments
*/
updateSettings({ apiKey, apiHost, segmentsToCheck }: OdpConfig): boolean {
updateSettings({ apiKey, apiHost, pixelUrl, segmentsToCheck }: OdpConfig): boolean {
if (!this.enabled) {
return false;
}
Expand All @@ -114,7 +114,7 @@ export abstract class OdpManager implements IOdpManager {

this.eventManager.flush();

const newConfig = new OdpConfig(apiKey, apiHost, segmentsToCheck);
const newConfig = new OdpConfig(apiKey, apiHost, pixelUrl, segmentsToCheck);
const configDidUpdate = this.odpConfig.update(newConfig);

if (configDidUpdate) {
Expand Down
9 changes: 9 additions & 0 deletions lib/core/project_config/index.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,10 @@ describe('lib/core/project_config', function() {
assert.exists(config.hostForOdp);
});

it('should populate the pixelUrl value from the odp integration', () => {
assert.exists(config.pixelUrlForOdp);
});

it('should contain all expected unique odp segments in allSegments', () => {
assert.equal(config.allSegments.length, 3);
assert.deepEqual(config.allSegments, ['odp-segment-1', 'odp-segment-2', 'odp-segment-3']);
Expand Down Expand Up @@ -848,6 +852,11 @@ describe('lib/core/project_config', function() {
assert.equal(config.hostForOdp, 'https://api.zaius.com');
});

it('should populate the pixelUrl value from the odp integration', () => {
assert.exists(config.pixelUrlForOdp);
assert.equal(config.pixelUrlForOdp, 'https://jumbe.zaius.com');
});

it('should contain all expected unique odp segments in all segments', () => {
assert.equal(config.allSegments.length, 0);
});
Expand Down
5 changes: 5 additions & 0 deletions lib/core/project_config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export interface ProjectConfig {
integrationKeyMap?: { [key: string]: Integration };
publicKeyForOdp?: string;
hostForOdp?: string;
pixelUrlForOdp?: string;
allSegments: string[];
}

Expand Down Expand Up @@ -203,6 +204,10 @@ export const createProjectConfig = function(datafileObj?: JSON, datafileStr: str
if (integration.host && !projectConfig.hostForOdp) {
projectConfig.hostForOdp = integration.host;
}

if (integration.pixelUrl && !projectConfig.pixelUrlForOdp) {
projectConfig.pixelUrlForOdp = integration.pixelUrl;
}
}
});
}
Expand Down
3 changes: 3 additions & 0 deletions lib/core/project_config/project_config_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ var schemaDefinition = {
},
publicKey: {
type: 'string'
},
pixelUrl: {
type: 'string'
}
andrewleap-optimizely marked this conversation as resolved.
Show resolved Hide resolved
}
}
Expand Down
5 changes: 3 additions & 2 deletions lib/index.browser.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ describe('javascript-sdk (Browser)', function() {

client.sendOdpEvent('test', '', new Map([['eamil', '[email protected]']]), new Map([['key', 'value']]));
clock.tick(10000);

const eventRequestUrl = new URL(fakeRequestHandler.makeRequest.lastCall.args[0]);
const searchParams = eventRequestUrl.searchParams;

Expand Down Expand Up @@ -1116,8 +1116,9 @@ describe('javascript-sdk (Browser)', function() {
clock.tick(100);

let publicKey = datafile.integrations[0].publicKey;
let pixelHost = datafile.integrations[0].pixelUrl;

const pixelApiEndpoint = 'https://jumbe.zaius.com/v2/zaius.gif';
const pixelApiEndpoint = `${pixelHost}/v2/zaius.gif`;
andrewleap-optimizely marked this conversation as resolved.
Show resolved Hide resolved
let requestEndpoint = new URL(requestParams.get('endpoint'));
assert.equal(requestEndpoint.origin + requestEndpoint.pathname, pixelApiEndpoint);
assert.equal(requestParams.get('method'), 'GET');
Expand Down
8 changes: 4 additions & 4 deletions lib/optimizely/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export default class Optimizely implements Client {
NotificationRegistry.getNotificationCenter(config.sdkKey)?.sendNotifications(
NOTIFICATION_TYPES.OPTIMIZELY_CONFIG_UPDATE
);

this.updateOdpSettings();
});

Expand Down Expand Up @@ -186,7 +186,7 @@ export default class Optimizely implements Client {
if (config.odpManager?.initPromise) {
dependentPromises.push(config.odpManager.initPromise);
}

this.readyPromise = Promise.all(dependentPromises).then(promiseResults => {
// If no odpManager exists yet, creates a new one
if (config.odpManager != null) {
Expand Down Expand Up @@ -1678,13 +1678,13 @@ export default class Optimizely implements Client {
}

/**
* Updates ODP Config with most recent ODP key, host, and segments from the project config
* Updates ODP Config with most recent ODP key, host, pixelUrl, and segments from the project config
*/
private updateOdpSettings(): void {
const projectConfig = this.projectConfigManager.getConfig();
if (this.odpManager != null && projectConfig != null) {
this.odpManager.updateSettings(
new OdpConfig(projectConfig.publicKeyForOdp, projectConfig.hostForOdp, projectConfig.allSegments)
new OdpConfig(projectConfig.publicKeyForOdp, projectConfig.hostForOdp, projectConfig.pixelUrlForOdp, projectConfig.allSegments)
);
}
}
Expand Down
6 changes: 3 additions & 3 deletions lib/plugins/odp/event_api_manager/index.browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export class BrowserOdpEventApiManager extends OdpEventApiManager {
if (!this.odpConfig?.isReady()) {
throw new Error(ODP_CONFIG_NOT_READY_MESSAGE);
}
const apiHost = this.odpConfig.apiHost;
const pixelApiEndpoint = new URL(pixelApiPath, apiHost.replace('api', 'jumbe')).href;
const pixelUrl = this.odpConfig.pixelUrl;
andrewleap-optimizely marked this conversation as resolved.
Show resolved Hide resolved
const pixelApiEndpoint = new URL(pixelApiPath, pixelUrl).href;
andrewleap-optimizely marked this conversation as resolved.
Show resolved Hide resolved
return pixelApiEndpoint;
}

Expand All @@ -33,7 +33,7 @@ export class BrowserOdpEventApiManager extends OdpEventApiManager {
this.getLogger().log(LogLevel.ERROR, ODP_CONFIG_NOT_READY_MESSAGE);
throw new Error(ODP_CONFIG_NOT_READY_MESSAGE);
}

// this cannot be cached cause OdpConfig is mutable
// and can be updated in place and it is done so in odp
// manager. We should make OdpConfig immutable and
Expand Down
1 change: 1 addition & 0 deletions lib/shared_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ export interface Integration {
key: string;
host?: string;
publicKey?: string;
pixelUrl?: string;
}

export interface TrafficAllocation {
Expand Down
4 changes: 4 additions & 0 deletions lib/tests/test_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -3225,11 +3225,13 @@ var odpIntegratedConfigWithSegments = {
key: 'odp',
host: 'https://api.zaius.com',
publicKey: 'W4WzcEs-ABgXorzY7h1LCQ',
pixelUrl: 'https://jumbe.zaius.com',
},
{
key: 'odp',
host: 'https://api.zzzzaius.com',
publicKey: 'W4WzcEs-ABgXorzssssY7h1LCQ',
pixelUrl: 'https://jumbe.zzzzaius.com',
},
{
key: 'odp',
Expand Down Expand Up @@ -3359,6 +3361,7 @@ var odpIntegratedConfigWithoutSegments = {
key: 'odp',
host: 'https://api.zaius.com',
publicKey: 'W4WzcEs-ABgXorzY7h1LCQ',
pixelUrl: 'https://jumbe.zaius.com',
},
{
key: 'odp',
Expand Down Expand Up @@ -3394,6 +3397,7 @@ var odpIntegratedConfigWithoutKey = {
{
host: 'https://api.zaius.com',
publicKey: 'W4WzcEs-ABgXorzY7h1LCQ',
pixelUrl: 'https://jumbe.zaius.com',
},
],
revision: '100',
Expand Down
6 changes: 4 additions & 2 deletions tests/odpEventApiManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ const ODP_EVENTS = [

const API_KEY = 'test-api-key';
const API_HOST = 'https://odp.example.com';
const PIXEL_URL = 'https://odp.pixel.com';

const odpConfig = new OdpConfig(API_KEY, API_HOST, []);
const odpConfig = new OdpConfig(API_KEY, API_HOST, PIXEL_URL, []);

describe('NodeOdpEventApiManager', () => {
let mockLogger: LogHandler;
Expand Down Expand Up @@ -133,9 +134,10 @@ describe('NodeOdpEventApiManager', () => {
const updatedOdpConfig = new OdpConfig(
'updated-key',
'https://updatedhost.test',
'https://updatedpixel.test',
['updated-seg'],
)

manager.updateSettings(updatedOdpConfig);
await manager.sendEvents(ODP_EVENTS);

Expand Down
16 changes: 10 additions & 6 deletions tests/odpEventManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { UserAgentInfo } from '../lib/core/odp/user_agent_info';

const API_KEY = 'test-api-key';
const API_HOST = 'https://odp.example.com';
const PIXEL_URL = 'https://odp.pixel.com';
const MOCK_IDEMPOTENCE_ID = 'c1dc758e-f095-4f09-9b49-172d74c53880';
const EVENTS: OdpEvent[] = [
new OdpEvent(
Expand Down Expand Up @@ -145,7 +146,7 @@ describe('OdpEventManager', () => {
beforeAll(() => {
mockLogger = mock<LogHandler>();
mockApiManager = mock<IOdpEventApiManager>();
odpConfig = new OdpConfig(API_KEY, API_HOST, []);
odpConfig = new OdpConfig(API_KEY, API_HOST, PIXEL_URL, []);
logger = instance(mockLogger);
apiManager = instance(mockApiManager);
});
Expand All @@ -159,7 +160,7 @@ describe('OdpEventManager', () => {
when(mockApiManager.sendEvents(anything())).thenResolve(false);
when(mockApiManager.updateSettings(anything())).thenReturn(undefined);

const apiManager = instance(mockApiManager);
const apiManager = instance(mockApiManager);

const eventManager = new OdpEventManager({
odpConfig,
Expand All @@ -172,12 +173,12 @@ describe('OdpEventManager', () => {
const [passedConfig] = capture(mockApiManager.updateSettings).last();
expect(passedConfig).toEqual(odpConfig);
});

it('should update api manager setting with updatetd odp config on updateSettings', () => {
when(mockApiManager.sendEvents(anything())).thenResolve(false);
when(mockApiManager.updateSettings(anything())).thenReturn(undefined);

const apiManager = instance(mockApiManager);
const apiManager = instance(mockApiManager);

const eventManager = new OdpEventManager({
odpConfig,
Expand All @@ -190,9 +191,10 @@ describe('OdpEventManager', () => {
const updatedOdpConfig = new OdpConfig(
'updated-key',
'https://updatedhost.test',
'https://pixel.test',
['updated-seg'],
)

eventManager.updateSettings(updatedOdpConfig);

verify(mockApiManager.updateSettings(anything())).twice();
Expand Down Expand Up @@ -541,13 +543,15 @@ describe('OdpEventManager', () => {
});
const apiKey = 'testing-api-key';
const apiHost = 'https://some.other.example.com';
const pixelUrl = 'https://some.other.pixel.com';
const segmentsToCheck = ['empty-cart', '1-item-cart'];
const differentOdpConfig = new OdpConfig(apiKey, apiHost, segmentsToCheck);
const differentOdpConfig = new OdpConfig(apiKey, apiHost, pixelUrl, segmentsToCheck);

eventManager.updateSettings(differentOdpConfig);

expect(eventManager['odpConfig'].apiKey).toEqual(apiKey);
expect(eventManager['odpConfig'].apiHost).toEqual(apiHost);
expect(eventManager['odpConfig'].pixelUrl).toEqual(pixelUrl);
expect(eventManager['odpConfig'].segmentsToCheck).toContain(Array.from(segmentsToCheck)[0]);
expect(eventManager['odpConfig'].segmentsToCheck).toContain(Array.from(segmentsToCheck)[1]);
});
Expand Down
12 changes: 7 additions & 5 deletions tests/odpManager.browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,19 @@ import { OdpEvent } from '../lib/core/odp/odp_event';

const keyA = 'key-a';
const hostA = 'host-a';
const pixelA = 'pixel-a';
const segmentsA = ['a'];
const userA = 'fs-user-a';
const vuidA = 'vuid_a';
const odpConfigA = new OdpConfig(keyA, hostA, segmentsA);
const odpConfigA = new OdpConfig(keyA, hostA, pixelA, segmentsA);

const keyB = 'key-b';
const hostB = 'host-b';
const pixelB = 'pixel-b';
const segmentsB = ['b'];
const userB = 'fs-user-b';
const vuidB = 'vuid_b';
const odpConfigB = new OdpConfig(keyB, hostB, segmentsB);
const odpConfigB = new OdpConfig(keyB, hostB, pixelB, segmentsB);

describe('OdpManager', () => {
let odpConfig: OdpConfig;
Expand Down Expand Up @@ -122,7 +124,7 @@ describe('OdpManager', () => {

verify(mockLogger.log(LogLevel.INFO, LOG_MESSAGES.ODP_DISABLED)).once();

browserOdpManager.updateSettings(new OdpConfig('valid', 'host', []));
browserOdpManager.updateSettings(new OdpConfig('valid', 'host', 'pixel-url', []));
expect(browserOdpManager.odpConfig).toBeUndefined;

await browserOdpManager.fetchQualifiedSegments('vuid_user1', []);
Expand Down Expand Up @@ -201,7 +203,7 @@ describe('OdpManager', () => {
},
});

const didUpdateA = browserOdpManager.updateSettings(new OdpConfig(keyA, hostA, segmentsA));
const didUpdateA = browserOdpManager.updateSettings(new OdpConfig(keyA, hostA, pixelA, segmentsA));
expect(didUpdateA).toBe(true);

browserOdpManager.fetchQualifiedSegments(vuidA);
Expand All @@ -213,7 +215,7 @@ describe('OdpManager', () => {
const fetchQualifiedSegmentsArgsA = capture(mockSegmentApiManager.fetchSegments).last();
expect(fetchQualifiedSegmentsArgsA).toStrictEqual([keyA, hostA, ODP_USER_KEY.VUID, vuidA, segmentsA]);

const didUpdateB = browserOdpManager.updateSettings(new OdpConfig(keyB, hostB, segmentsB));
const didUpdateB = browserOdpManager.updateSettings(new OdpConfig(keyB, hostB, pixelB, segmentsB));
expect(didUpdateB).toBe(true);

browserOdpManager.fetchQualifiedSegments(vuidB);
Expand Down
Loading
Loading