-
Notifications
You must be signed in to change notification settings - Fork 57
feat: Add Rokt Wrapper #994
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
Changes from 2 commits
5dbfce4
113cbc9
fc08d1d
50566b4
b49cf13
6ba542a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| // https://docs.rokt.com/developers/integration-guides/web/library/attributes | ||
| export interface IRoktPartnerAttributes { | ||
| [key: string]: string | number | boolean | undefined | null; | ||
| } | ||
|
|
||
| // https://docs.rokt.com/developers/integration-guides/web/library/select-placements-options | ||
| export interface ISelectPlacementsOptions { | ||
| attributes: IRoktPartnerAttributes; | ||
| identifier?: string; | ||
alexs-mparticle marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| export interface ISelection { | ||
| placementId?: string; | ||
| status?: string; | ||
| error?: string; | ||
| } | ||
|
||
|
|
||
| export interface IRoktLauncher { | ||
| selectPlacements: (options: ISelectPlacementsOptions) => Promise<ISelection>; | ||
| } | ||
|
|
||
| export interface IRoktMessage { | ||
| methodName: string; | ||
| payload: any; | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. group with other rokt interfaces |
||
|
|
||
| export default class RoktManager { | ||
| private launcher: IRoktLauncher | null = null; | ||
rmi22186 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| private messageQueue: IRoktMessage[] = []; | ||
|
|
||
| constructor() { | ||
| this.launcher = null; | ||
| } | ||
|
|
||
| public attachLauncher(launcher: IRoktLauncher): Promise<void> { | ||
| return new Promise<void>((resolve) => { | ||
| if (!launcher) { | ||
| this.queueMessage({ | ||
| methodName: 'attachLauncher', | ||
| payload: launcher, | ||
| }); | ||
|
||
| } else { | ||
| this.setLauncher(launcher); | ||
| this.processMessageQueue(); | ||
| } | ||
| resolve(); | ||
|
||
| }); | ||
| } | ||
|
|
||
| public selectPlacements(options: ISelectPlacementsOptions): Promise<ISelection> { | ||
| if (!this.launcher) { | ||
| this.queueMessage({ | ||
| methodName: 'selectPlacements', | ||
| payload: options, | ||
| }); | ||
| return Promise.resolve({}); | ||
| } | ||
|
|
||
| try { | ||
| return this.launcher.selectPlacements(options); | ||
| } catch (error) { | ||
| return Promise.reject(error instanceof Error ? error : new Error('Unknown error occurred')); | ||
| } | ||
| } | ||
|
|
||
| private processMessageQueue(): void { | ||
| if (this.messageQueue.length > 0) { | ||
| this.messageQueue.forEach(async (message) => { | ||
| if (this.launcher && message.methodName in this.launcher) { | ||
| await (this.launcher[message.methodName] as Function)(message.payload); | ||
| } | ||
| }); | ||
| this.messageQueue = []; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| private queueMessage(message: IRoktMessage): void { | ||
| this.messageQueue.push(message); | ||
| } | ||
|
|
||
| private setLauncher(launcher: IRoktLauncher): void { | ||
| this.launcher = launcher; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,120 @@ | ||||||||||||||
| import RoktManager, { IRoktLauncher, ISelectPlacementsOptions } from "../../src/roktManager"; | ||||||||||||||
|
|
||||||||||||||
| describe('RoktManager', () => { | ||||||||||||||
| let roktManager: RoktManager; | ||||||||||||||
|
|
||||||||||||||
| beforeEach(() => { | ||||||||||||||
| roktManager = new RoktManager(); | ||||||||||||||
| }); | ||||||||||||||
|
|
||||||||||||||
| describe('constructor', () => { | ||||||||||||||
| it('should be initialized', () => { | ||||||||||||||
| expect(roktManager).toBeDefined(); | ||||||||||||||
| }); | ||||||||||||||
|
|
||||||||||||||
| it('should have a null launcher', () => { | ||||||||||||||
| expect(roktManager['launcher']).toBeNull(); | ||||||||||||||
| }); | ||||||||||||||
| }); | ||||||||||||||
|
|
||||||||||||||
| describe('#attachLauncher', () => { | ||||||||||||||
| it('should attach a launcher', () => { | ||||||||||||||
| const launcher = {} as IRoktLauncher; | ||||||||||||||
| roktManager.attachLauncher(launcher); | ||||||||||||||
| expect(roktManager['launcher']).not.toBeNull(); | ||||||||||||||
| }); | ||||||||||||||
|
|
||||||||||||||
| it('should queue the launcher method if no launcher is attached', () => { | ||||||||||||||
| roktManager.attachLauncher(null); | ||||||||||||||
| expect(roktManager['launcher']).toBeNull(); | ||||||||||||||
| expect(roktManager['messageQueue'].length).toBe(1); | ||||||||||||||
| expect(roktManager['messageQueue'][0].methodName).toBe('attachLauncher'); | ||||||||||||||
| expect(roktManager['messageQueue'][0].payload).toBe(null); | ||||||||||||||
| }); | ||||||||||||||
|
|
||||||||||||||
| it('should process the message queue if a launcher is attached', () => { | ||||||||||||||
| const launcher = jest.fn() as unknown as IRoktLauncher; | ||||||||||||||
|
|
||||||||||||||
| roktManager.attachLauncher(null); | ||||||||||||||
| expect(roktManager['launcher']).toBeNull(); | ||||||||||||||
| expect(roktManager['messageQueue'].length).toBe(1); | ||||||||||||||
| expect(roktManager['messageQueue'][0].methodName).toBe('attachLauncher'); | ||||||||||||||
| expect(roktManager['messageQueue'][0].payload).toBe(null); | ||||||||||||||
|
|
||||||||||||||
| roktManager.attachLauncher(launcher); | ||||||||||||||
| expect(roktManager['launcher']).not.toBeNull(); | ||||||||||||||
| expect(roktManager['messageQueue'].length).toBe(0); | ||||||||||||||
| }); | ||||||||||||||
| }); | ||||||||||||||
|
|
||||||||||||||
| describe('#selectPlacements', () => { | ||||||||||||||
| it('should call selectPlacements', () => { | ||||||||||||||
|
||||||||||||||
| it('should call selectPlacements', () => { | |
| it('should map a IRoktLauncher selectPlacement to a launcher selectPlacements call', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "map an IRoktLauncher selectPlacement" is too much of an implementation detail for this specific tests, but I agree that it should more explicit to referenc the launcher. I'll revise.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's a reason to make it unknown
| const launcher = { | |
| selectPlacements: jest.fn() | |
| } as unknown as IRoktLauncher; | |
| const launcher: IRoktLauncher = { | |
| selectPlacements: jest.fn() | |
| } |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| it('should call selectPlacements with any passed in attributes', () => { | |
| it('should call IRoktLauncher selectPlacements with any passed in attributes to roktManager.selectPlacements', () => { |
Uh oh!
There was an error while loading. Please reload this page.