Skip to content

Commit c72c921

Browse files
committed
fix: search workspace for cached Rokt users
1 parent 5a022cd commit c72c921

2 files changed

Lines changed: 135 additions & 1 deletion

File tree

src/Rokt-Kit.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,8 @@ class RoktKit implements KitInterface {
10051005
this.filters = roktFilters;
10061006
if (!roktFilters.filteredUser) {
10071007
console.warn('Rokt Kit: No filtered user has been set.');
1008+
} else {
1009+
this._workspaceSearchInFlightPromise = this.search(roktFilters.filteredUser);
10081010
}
10091011
}
10101012

@@ -1304,7 +1306,7 @@ class RoktKit implements KitInterface {
13041306
// network call. The current flag value still reflects the correct
13051307
// match status.
13061308
if (identitiesKey === this._workspaceLastSearchedIdentitiesKey) {
1307-
return Promise.resolve();
1309+
return this._workspaceSearchInFlightPromise || Promise.resolve();
13081310
}
13091311

13101312
// New / different identifier set → reset and re-search. Cache the key

test/src/tests.spec.ts

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,88 @@ describe('Rokt Forwarder', () => {
30493049
expect((window as any).mParticle.forwarder.userIdentifiedInWorkspace).toBe(true);
30503050
});
30513051

3052+
it('should search cached filtered user identities when the launcher initializes', async () => {
3053+
let receivedApiKey: any = null;
3054+
let receivedKnownIdentities: any = null;
3055+
let searchCallCount = 0;
3056+
(window as any).mParticle.Identity = {
3057+
search: (apiKey: any, knownIdentities: any, cb: any) => {
3058+
searchCallCount += 1;
3059+
receivedApiKey = apiKey;
3060+
receivedKnownIdentities = knownIdentities;
3061+
cb({ httpCode: 200, body: { mpid: '999' } });
3062+
},
3063+
};
3064+
(window as any).mParticle.Rokt.attachKit = async () => {};
3065+
(window as any).mParticle.Rokt.filters = {
3066+
userAttributeFilters: [],
3067+
filterUserAttributes: (attributes: any) => attributes,
3068+
filteredUser: makeUser(),
3069+
};
3070+
3071+
await (window as any).mParticle.forwarder.init(
3072+
{ accountId: '123456', workspaceIdSyncApiKey: WORKSPACE_API_KEY },
3073+
reportService.cb,
3074+
true,
3075+
null,
3076+
{},
3077+
);
3078+
3079+
await waitForCondition(() => searchCallCount === 1);
3080+
3081+
expect(receivedApiKey).toBe(WORKSPACE_API_KEY);
3082+
expect(receivedKnownIdentities).toEqual({ email: 'test@example.com' });
3083+
expect((window as any).mParticle.forwarder.userIdentifiedInWorkspace).toBe(true);
3084+
});
3085+
3086+
it('should not search cached filtered user identities when workspaceIdSyncApiKey is missing', async () => {
3087+
let searchCalled = false;
3088+
(window as any).mParticle.Identity = {
3089+
search: () => {
3090+
searchCalled = true;
3091+
},
3092+
};
3093+
(window as any).mParticle.Rokt.attachKit = async () => {};
3094+
(window as any).mParticle.Rokt.filters = {
3095+
userAttributeFilters: [],
3096+
filterUserAttributes: (attributes: any) => attributes,
3097+
filteredUser: makeUser(),
3098+
};
3099+
3100+
await (window as any).mParticle.forwarder.init({ accountId: '123456' }, reportService.cb, true, null, {});
3101+
await waitForCondition(() => (window as any).mParticle.forwarder.isInitialized);
3102+
3103+
expect(searchCalled).toBe(false);
3104+
expect((window as any).mParticle.forwarder.userIdentifiedInWorkspace).toBe(false);
3105+
});
3106+
3107+
it('should not search cached filtered user when it has no usable identifiers', async () => {
3108+
let searchCalled = false;
3109+
(window as any).mParticle.Identity = {
3110+
search: () => {
3111+
searchCalled = true;
3112+
},
3113+
};
3114+
(window as any).mParticle.Rokt.attachKit = async () => {};
3115+
(window as any).mParticle.Rokt.filters = {
3116+
userAttributeFilters: [],
3117+
filterUserAttributes: (attributes: any) => attributes,
3118+
filteredUser: makeUser({ getUserIdentities: () => ({ userIdentities: {} }) }),
3119+
};
3120+
3121+
await (window as any).mParticle.forwarder.init(
3122+
{ accountId: '123456', workspaceIdSyncApiKey: WORKSPACE_API_KEY },
3123+
reportService.cb,
3124+
true,
3125+
null,
3126+
{},
3127+
);
3128+
await waitForCondition(() => (window as any).mParticle.forwarder.isInitialized);
3129+
3130+
expect(searchCalled).toBe(false);
3131+
expect((window as any).mParticle.forwarder.userIdentifiedInWorkspace).toBe(false);
3132+
});
3133+
30523134
it('should not set userIdentifiedInWorkspace when search returns 404', async () => {
30533135
(window as any).mParticle.Identity = {
30543136
search: (_apiKey: any, _knownIdentities: any, cb: any) => {
@@ -3289,6 +3371,56 @@ describe('Rokt Forwarder', () => {
32893371
expect(launcherCalledWithAttributes.userIdentifiedInWorkspace).toBe(true);
32903372
});
32913373

3374+
it('should preserve an in-flight cached-user search when the same identity re-identifies', async () => {
3375+
let triggerSearchResponse: () => void = () => undefined;
3376+
let searchCallCount = 0;
3377+
(window as any).mParticle.Identity = {
3378+
search: (_apiKey: any, _knownIdentities: any, cb: any) => {
3379+
searchCallCount += 1;
3380+
triggerSearchResponse = () => cb({ httpCode: 200, body: { mpid: '999' } });
3381+
},
3382+
};
3383+
(window as any).mParticle.Rokt.attachKit = async () => {};
3384+
(window as any).mParticle.Rokt.filters = {
3385+
userAttributeFilters: [],
3386+
filterUserAttributes: (attributes: any) => attributes,
3387+
filteredUser: makeUser(),
3388+
};
3389+
3390+
await (window as any).mParticle.forwarder.init(
3391+
{ accountId: '123456', workspaceIdSyncApiKey: WORKSPACE_API_KEY },
3392+
reportService.cb,
3393+
true,
3394+
null,
3395+
{},
3396+
);
3397+
await waitForCondition(() => searchCallCount === 1);
3398+
3399+
// A same-identity onUserIdentified while the cached-user search is
3400+
// still in flight should dedupe the network call without replacing the
3401+
// promise selectPlacements needs to wait on.
3402+
(window as any).mParticle.forwarder.onUserIdentified(makeUser());
3403+
expect(searchCallCount).toBe(1);
3404+
3405+
let launcherCalledWithAttributes: any = null;
3406+
(window as any).mParticle.forwarder.launcher = {
3407+
selectPlacements: (opts: any) => {
3408+
launcherCalledWithAttributes = opts.attributes;
3409+
return { context: { sessionId: Promise.resolve('test-session') } };
3410+
},
3411+
};
3412+
3413+
const placementPromise = (window as any).mParticle.forwarder.selectPlacements({
3414+
identifier: 'test-placement',
3415+
attributes: {},
3416+
});
3417+
3418+
triggerSearchResponse();
3419+
await placementPromise;
3420+
3421+
expect(launcherCalledWithAttributes.userIdentifiedInWorkspace).toBe(true);
3422+
});
3423+
32923424
it('should reset userIdentifiedInWorkspace on onLogoutComplete', async () => {
32933425
(window as any).mParticle.Identity = {
32943426
search: (_apiKey: any, _knownIdentities: any, cb: any) => {

0 commit comments

Comments
 (0)