Skip to content

Commit

Permalink
no identity available new event
Browse files Browse the repository at this point in the history
  • Loading branch information
ashleysmithTTD committed Feb 14, 2025
1 parent 59856db commit f8b39dd
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 40 deletions.
8 changes: 4 additions & 4 deletions src/callbackManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ export type PayloadWithIdentity = {
};

export class CallbackManager {
private _getIdentity: () => Identity | null | undefined;
private _getIdentity: (isForCallback: boolean) => Identity | null | undefined;
private _logger: Logger;
private _sdk: SdkBase;
private _productName: string;
constructor(
sdk: SdkBase,
productName: string,
getIdentity: () => Identity | null | undefined,
getIdentity: (isForCallback: boolean) => Identity | null | undefined,
logger: Logger
) {
this._productName = productName;
Expand All @@ -44,7 +44,7 @@ export class CallbackManager {
this.safeRunCallback(c, EventType.SdkLoaded, {});
if (this._sentInit)
this.safeRunCallback(c, EventType.InitCompleted, {
identity: this._getIdentity() ?? null,
identity: this._getIdentity(true) ?? null,
});
}
return Array.prototype.push.apply(this._sdk.callbacks, args);
Expand All @@ -57,7 +57,7 @@ export class CallbackManager {

const enrichedPayload = {
...payload,
identity: this._getIdentity() ?? null,
identity: this._getIdentity(true) ?? null,
};
for (const callback of this._sdk.callbacks) {
this.safeRunCallback(callback, event, enrichedPayload);
Expand Down
96 changes: 69 additions & 27 deletions src/integrationTests/options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,15 +556,23 @@ describe('Store config UID2', () => {
});
});

describe('when no identity is sent in init', () => {
describe('calls the NoIdentityAvailable event', () => {
let handler: ReturnType<typeof jest.fn>;
beforeEach(() => {
handler = jest.fn();
uid2.callbacks.push(handler);
});
test('runs NoIdentityAvailable event', () => {

test('when init is called for the first time with no identity', () => {
uid2.init({});
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, { identity: null });
});
test('when init is already complete and called again with no identity', () => {
uid2.init({});
uid2.init({});
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, { identity: null });
});
test('when init is already complete and called again with an expired identity', () => {
uid2.init({});
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, { identity: null });
let expiredIdentity = makeIdentity({
Expand All @@ -578,55 +586,89 @@ describe('Store config UID2', () => {
identity: expiredIdentity,
});
});
test('runs NoIdentityAvailable event', () => {
test('when init is already complete but the existing identity is expired', () => {
let expiredIdentity = makeIdentity({
identity_expires: Date.now() - 100000,
refresh_expires: Date.now() - 100000,
});
uid2.init({
identity: expiredIdentity,
});
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {
identity: expiredIdentity,
});
uid2.init({});
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {
identity: expiredIdentity,
});
});
test('runs NoIdentityAvailable event', () => {
let expiredIdentity1 = makeIdentity({
identity_expires: Date.now() - 5000,
refresh_expires: Date.now() - 5000,
});
let expiredIdentity2 = makeIdentity({
identity_expires: Date.now() - 100000,
refresh_expires: Date.now() - 100000,
test('when identity is expired but refreshable', () => {
let expiredRefreshableIdentity = makeIdentity({
identity_expires: Date.now() - 10000,
refresh_expires: Date.now() + 10000,
});
uid2.init({
identity: expiredIdentity1,
uid2.setIdentity(expiredRefreshableIdentity);

// in this case, identity is temporarily unavailable but still unavailable
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {
identity: null,
});
uid2.init({ identity: expiredIdentity2 });
});
test('when login is required', () => {
uid2.isLoginRequired();

expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {
identity: expiredIdentity2,
identity: null,
});
});
test('runs NoIdentityAvailable event', () => {
uid2.init({});
let expiredIdentity = makeIdentity({
identity_expires: Date.now() - 5000,
refresh_expires: Date.now() - 5000,
test('when get identity returns null or get advertising token returns undefined', () => {
const nullIdentity = uid2.getIdentity();

expect(nullIdentity).toBeNull();
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {
identity: null,
});
uid2.setIdentity(expiredIdentity);
});
test('when there is no advertising token', () => {
const token = uid2.getAdvertisingToken();

expect(token).toBeUndefined();
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {
identity: null,
});
});
test('runs NoIdentityAvailable event', () => {
});

describe('does not call NoIdentityAvailable event', () => {
let handler: ReturnType<typeof jest.fn>;
beforeEach(() => {
handler = jest.fn();
uid2.callbacks.push(handler);
});

test('when setIdentity is run with a valid identity, should not call NoIdentityAvailable on set or get', () => {
uid2.init({});
let expiredIdentity = makeIdentity({
identity_expires: Date.now() - 5000,
refresh_expires: Date.now() - 5000,
let validIdentity = makeIdentity();
uid2.setIdentity(validIdentity);
expect(handler).not.toHaveBeenCalledWith(EventType.NoIdentityAvailable, {
identity: null,
});
uid2.setIdentity(expiredIdentity);
expect(handler).toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {

uid2.getIdentity();
expect(handler).not.toHaveBeenCalledWith(EventType.NoIdentityAvailable, {
identity: null,
});

uid2.getAdvertisingToken();
expect(handler).not.toHaveBeenCalledWith(EventType.NoIdentityAvailable, {
identity: null,
});
});
test('when identity is set with opted out identity', () => {
uid2.init({});
let optedOutIdentity = makeIdentity({ status: 'optout' });
uid2.setIdentity(optedOutIdentity);
expect(handler).not.toHaveBeenLastCalledWith(EventType.NoIdentityAvailable, {
identity: null,
});
});
Expand Down
23 changes: 14 additions & 9 deletions src/sdkBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export abstract class SdkBase {
this._callbackManager = new CallbackManager(
this,
this._product.name,
() => this.getIdentity(),
() => this.getIdentity(true),
this._logger
);
}
Expand Down Expand Up @@ -157,20 +157,25 @@ export abstract class SdkBase {
} else {
this.triggerRefreshOrSetTimer(validatedIdentity);
}
this._callbackManager.runCallbacks(EventType.IdentityUpdated, {});
} else {
this._callbackManager.runCallbacks(EventType.NoIdentityAvailable, {});
}
this.isIdentityAvailable();
}

public getIdentity(): Identity | null {
public getIdentity(isForCallback?: boolean): Identity | null {
const identity = this._identity ?? this.getIdentityNoInit();
return identity && !this.temporarilyUnavailable(identity) && !isOptoutIdentity(identity)
? identity
: null;
const isValid =
identity && !this.temporarilyUnavailable(identity) && !isOptoutIdentity(identity);
if (!isValid) {
if (!isForCallback) {
this._callbackManager.runCallbacks(EventType.NoIdentityAvailable, {});
}
return null;
} else {
return identity;
}
}

// When the SDK has been initialized, this function should return the token
// When the SDK has been initialized, this vfunction should return the token
// from the most recent refresh request, if there is a request, wait for the
// new token. Otherwise, returns a promise which will be resolved after init.
public getAdvertisingTokenAsync() {
Expand Down

0 comments on commit f8b39dd

Please sign in to comment.