diff --git a/src/apiClient.ts b/src/apiClient.ts index 508af368..ec4d8899 100644 --- a/src/apiClient.ts +++ b/src/apiClient.ts @@ -1,11 +1,12 @@ import Constants from './constants'; import Types from './types'; import { BatchUploader } from './batchUploader'; -import { MParticleUser, MParticleWebSDK, SDKEvent } from './sdkRuntimeModels'; +import { MParticleWebSDK, SDKEvent } from './sdkRuntimeModels'; import KitBlocker from './kitBlocking'; import { Dictionary, getRampNumber, isEmpty, parseNumber } from './utils'; import { IUploadObject } from './serverModel'; import { MPForwarder } from './forwarders.interfaces'; +import { IMParticleUser } from './identity-user-interfaces'; export type ForwardingStatsData = Dictionary; @@ -13,7 +14,7 @@ export interface IAPIClient { uploader: BatchUploader | null; queueEventForBatchUpload: (event: SDKEvent) => void; processQueuedEvents: () => void; - appendUserInfoToEvents: (user: MParticleUser, events: SDKEvent[]) => void; + appendUserInfoToEvents: (user: IMParticleUser, events: SDKEvent[]) => void; sendEventToServer: (event: SDKEvent, _options?: Dictionary) => void; sendSingleEventToServer: (event: SDKEvent) => void; sendBatchForwardingStatsToServer: ( diff --git a/src/batchUploader.ts b/src/batchUploader.ts index 46f86ed4..ea4b6606 100644 --- a/src/batchUploader.ts +++ b/src/batchUploader.ts @@ -1,21 +1,17 @@ import { Batch } from '@mparticle/event-models'; import Constants from './constants'; -import { - SDKEvent, - MParticleUser, - MParticleWebSDK, - SDKLoggerApi, -} from './sdkRuntimeModels'; +import { SDKEvent, MParticleWebSDK, SDKLoggerApi } from './sdkRuntimeModels'; import { convertEvents } from './sdkToEventsApiConverter'; import Types from './types'; import { getRampNumber, isEmpty } from './utils'; import { SessionStorageVault, LocalStorageVault } from './vault'; -import { +import { AsyncUploader, FetchUploader, XHRUploader, - fetchPayload + fetchPayload, } from './uploaders'; +import { IMParticleUser } from './identity-user-interfaces'; /** * BatchUploader contains all the logic to store/retrieve events and batches @@ -205,7 +201,7 @@ export class BatchUploader { */ private static createNewBatches( sdkEvents: SDKEvent[], - defaultUser: MParticleUser, + defaultUser: IMParticleUser, mpInstance: MParticleWebSDK ): Batch[] | null { if (!defaultUser || !sdkEvents || !sdkEvents.length) { diff --git a/src/consent.ts b/src/consent.ts index ed81bdbe..6ff45c21 100644 --- a/src/consent.ts +++ b/src/consent.ts @@ -4,10 +4,11 @@ import { GDPRConsentState, PrivacyConsentState, } from '@mparticle/web-sdk'; -import { MParticleUser, MParticleWebSDK } from './sdkRuntimeModels'; +import { MParticleWebSDK } from './sdkRuntimeModels'; import { Dictionary, isObject } from './utils'; import KitFilterHelper from './kitFilterHelper'; import Constants from './constants'; +import { IMParticleUser } from './identity-user-interfaces'; const { CCPAPurpose } = Constants; @@ -108,7 +109,7 @@ export interface IConsentState extends ConsentState { export interface IConsent { isEnabledForUserConsent: ( consentRules: IConsentRules, - user: MParticleUser + user: IMParticleUser ) => boolean; createPrivacyConsent: ICreatePrivacyConsentFunction; createConsentState: (consentState?: ConsentState) => ConsentState; @@ -123,7 +124,7 @@ export default function Consent(this: IConsent, mpInstance: MParticleWebSDK) { // forwarder should be initialized this.isEnabledForUserConsent = function( consentRules: IConsentRules, - user: MParticleUser + user: IMParticleUser ): boolean { if ( !consentRules || diff --git a/src/forwarders.interfaces.ts b/src/forwarders.interfaces.ts index ba019c2d..a38777c3 100644 --- a/src/forwarders.interfaces.ts +++ b/src/forwarders.interfaces.ts @@ -1,13 +1,12 @@ -import { - MParticleUser, - SDKEvent, - SDKEventCustomFlags, - SDKUserIdentity, -} from './sdkRuntimeModels'; +import { SDKEvent, SDKEventCustomFlags } from './sdkRuntimeModels'; import { Dictionary } from './utils'; import { IKitConfigs } from './configAPIClient'; -import { UserAttributes } from './persistence.interfaces'; import { IdentityApiData } from '@mparticle/web-sdk'; +import { + IMParticleUser, + ISDKUserIdentity, + UserAttributes, +} from './identity-user-interfaces'; // TODO: https://go.mparticle.com/work/SQDSDKS-6035 export type Kit = Dictionary; @@ -19,7 +18,7 @@ export interface UnregisteredKit { register(config): void; } -// The state of the kit after being added to forwarderConstructors in the CDN +// The state of the kit after being added to forwarderConstructors in the CDN // or after registered to SDKConfig.kits via NPM export interface RegisteredKit { constructor(): void; @@ -37,47 +36,50 @@ export interface ConfiguredKit testMode: boolean, trackerId: string | null, userAttributes: UserAttributes, - userIdentities: SDKUserIdentity, + userIdentities: ISDKUserIdentity, appVersion: string, appName: string, customFlags: SDKEventCustomFlags, clientId: string ): string; onIdentifyComplete( - user: MParticleUser, + user: IMParticleUser, filteredIdentityRequest: IdentityApiData ): string | KitMappedMethodFailure; onLoginComplete( - user: MParticleUser, + user: IMParticleUser, filteredIdentityRequest: IdentityApiData ): string | KitMappedMethodFailure; onLogoutComplete( - user: MParticleUser, + user: IMParticleUser, filteredIdentityRequest: IdentityApiData ): string | KitMappedMethodFailure; onModifyComplete( - user: MParticleUser, + user: IMParticleUser, filteredIdentityRequest: IdentityApiData ): string | KitMappedMethodFailure; - onUserIdentified(user: MParticleUser): string | KitMappedMethodFailure; + onUserIdentified(user: IMParticleUser): string | KitMappedMethodFailure; process(event: SDKEvent): string; setOptOut(isOptingOut: boolean): string | KitMappedMethodFailure; removeUserAttribute(key: string): string; - setUserAttribute(key: string, value:string): string; + setUserAttribute(key: string, value: string): string; // TODO: Convert type to enum during Identity migration // https://go.mparticle.com/work/SQDSDKS-5218 setUserIdentity(id: UserIdentityId, type: UserIdentityType): void; // TODO: https://go.mparticle.com/work/SQDSDKS-5156 - isSandbox: boolean; + isSandbox: boolean; hasSandbox: boolean; } export interface KitMappedMethodFailure { - error: string + error: string; } export type UserIdentityId = string; export type UserIdentityType = number; -export type forwardingStatsCallback = (forwarder: ConfiguredKit, event: SDKEvent) => void; \ No newline at end of file +export type forwardingStatsCallback = ( + forwarder: ConfiguredKit, + event: SDKEvent +) => void; diff --git a/src/identity-user-interfaces.ts b/src/identity-user-interfaces.ts new file mode 100644 index 00000000..94882503 --- /dev/null +++ b/src/identity-user-interfaces.ts @@ -0,0 +1,64 @@ +import { + AllUserAttributes, + IdentityCallback, + Product, + User, +} from '@mparticle/web-sdk'; +import { SDKIdentityTypeEnum } from './identity.interfaces'; +import { MessageType } from './types.interfaces'; +import { BaseEvent } from './sdkRuntimeModels'; + +// https://go.mparticle.com/work/SQDSDKS-5033 +// https://go.mparticle.com/work/SQDSDKS-6354 +export interface IMParticleUser extends User { + getAllUserAttributes(): any; + setUserTag(tagName: string, value?: any): void; + setUserAttribute(key: string, value: any): void; + getUserAudiences?(callback?: IdentityCallback): void; +} + +export interface ISDKUserIdentity { + Identity: string; + Type: number; +} + +export interface ISDKUserIdentityChanges { + New: ISDKUserIdentityChangeData; + Old: ISDKUserIdentityChangeData; +} + +export interface ISDKUserIdentityChangeData { + IdentityType: SDKIdentityTypeEnum; + Identity: string; + CreatedThisBatch: boolean; + // https://go.mparticle.com/work/SQDSDKS-6438 + Timestamp?: number; +} + +export interface IUserIdentityChangeEvent extends BaseEvent { + messageType: MessageType.UserIdentityChange; + userIdentityChanges: ISDKUserIdentityChanges; +} + +export interface ISDKUserAttributeChangeData { + UserAttributeName: string; + New: string; + Old: string; + Deleted: boolean; + IsNewAttribute: boolean; +} + +export interface IUserAttributeChangeEvent extends BaseEvent { + messageType: MessageType.UserAttributeChange; + userAttributeChanges: ISDKUserAttributeChangeData; +} + +export interface mParticleUserCart { + add(product: Product, logEvent: boolean): void; + remove(product: Product, logEvent: boolean): void; + clear(): void; + getCartProducts(): Product[]; +} + +// https://go.mparticle.com/work/SQDSDKS-5196 +export type UserAttributes = AllUserAttributes; diff --git a/src/identity-utils.ts b/src/identity-utils.ts index 88d7ef82..b70f110a 100644 --- a/src/identity-utils.ts +++ b/src/identity-utils.ts @@ -3,7 +3,7 @@ import { Dictionary, parseNumber, isObject, generateHash } from './utils'; import { BaseVault } from './vault'; import Types from './types'; import { IdentityApiData, UserIdentities, IdentityCallback } from '@mparticle/web-sdk'; -import { IdentityAPIMethod, MParticleWebSDK } from './sdkRuntimeModels'; +import { IdentityAPIMethod } from './identity.interfaces'; const { Identify, Modify, Login, Logout } = Constants.IdentityMethods; diff --git a/src/identity.interfaces.ts b/src/identity.interfaces.ts new file mode 100644 index 00000000..652f5c83 --- /dev/null +++ b/src/identity.interfaces.ts @@ -0,0 +1,205 @@ +import { + IdentityApiData, + IdentityCallback, + MPID, + UserIdentities, +} from '@mparticle/web-sdk'; +import AudienceManager from './audienceManager'; +import { ICachedIdentityCall, IKnownIdentities } from './identity-utils'; +import { BaseVault } from './vault'; +import { Dictionary, Environment, valueof } from './utils'; +import Constants from './constants'; +import { + IUserAttributeChangeEvent, + IUserIdentityChangeEvent, + IMParticleUser, + mParticleUserCart, +} from './identity-user-interfaces'; +const { platform, sdkVendor, sdkVersion, HTTPCodes } = Constants; + +export type IdentityPreProcessResult = { + valid: boolean; + error?: string; +}; + +export type IdentityAPIMethod = valueof; + +export enum SDKIdentityTypeEnum { + other = 'other', + customerId = 'customerid', + facebook = 'facebook', + twitter = 'twitter', + google = 'google', + microsoft = 'microsoft', + yahoo = 'yahoo', + email = 'email', + alias = 'alias', + facebookCustomAudienceId = 'facebookcustomaudienceid', + otherId2 = 'other2', + otherId3 = 'other3', + otherId4 = 'other4', + otherId5 = 'other5', + otherId6 = 'other6', + otherId7 = 'other7', + otherId8 = 'other8', + otherId9 = 'other9', + otherId10 = 'other10', + mobileNumber = 'mobile_number', + phoneNumber2 = 'phone_number_2', + phoneNumber3 = 'phone_number_3', +} + +export interface IIdentityAPIRequestData { + client_sdk: { + platform: typeof platform; + sdk_vendor: typeof sdkVendor; + sdk_version: typeof sdkVersion; + }; + context: string | null; + environment: Environment; + request_id: string; + reqest_timestamp_unixtime_ms: number; + previous_mpid: MPID | null; + known_identities: IKnownIdentities; +} + +export interface IIdentityAPIModifyRequestData + extends Omit< + IIdentityAPIRequestData, + 'known_identities' | 'previous_mpid' + > { + identity_changes: IIdentityAPIIdentityChangeData[]; +} + +export interface IIdentityAPIIdentityChangeData { + identity_type: SDKIdentityTypeEnum; + old_value: string; + new_value: string; +} + +export interface IIdentityRequest { + createIdentityRequest( + identityApiData: IdentityApiData, + platform: string, + sdkVendor: string, + sdkVersion: string, + deviceId: string, + context: string | null, + mpid: MPID + ): IIdentityAPIRequestData; + createModifyIdentityRequest( + currentUserIdentities: UserIdentities, + newUserIdentities: UserIdentities, + platform: string, + sdkVendor: string, + sdkVersion: string, + context: string | null + ): IIdentityAPIModifyRequestData; + createIdentityChanges( + previousIdentities: UserIdentities, + newIdentitie: UserIdentities + ): IIdentityAPIIdentityChangeData; + preProcessIdentityRequest( + identityApiData: IdentityApiData, + callback: IdentityCallback, + method: IdentityAPIMethod + ): IdentityPreProcessResult; +} + +export interface IAliasRequest { + destinationMpid: MPID; + sourceMpid: MPID; + startTime: number; + endTime: number; + scope?: string; +} + +export interface SDKIdentityApi { + HTTPCodes: typeof HTTPCodes; + identify?( + identityApiData?: IdentityApiData, + callback?: IdentityCallback + ): void; + login?( + identityApiData?: IdentityApiData, + callback?: IdentityCallback + ): void; + logout?( + identityApiData?: IdentityApiData, + callback?: IdentityCallback + ): void; + modify?( + identityApiData?: IdentityApiData, + callback?: IdentityCallback + ): void; + getCurrentUser?(): IMParticleUser; + getUser?(mpid: string): IMParticleUser; + getUsers?(): IMParticleUser[]; + aliasUsers?( + aliasRequest?: IAliasRequest, + callback?: IdentityCallback + ): void; + createAliasRequest?( + sourceUser: IMParticleUser, + destinationUser: IMParticleUser + ): IAliasRequest; +} + +export interface IIdentity { + audienceManager: AudienceManager; + idCache: BaseVault>; + + IdentityAPI: SDKIdentityApi; + IdentityRequest: IIdentityRequest; + + mParticleUser(mpid: MPID, IsLoggedIn: boolean): IMParticleUser; + + checkIdentitySwap( + previousMPID: MPID, + currentMPID: MPID, + currentSessionMPIDs?: MPID[] + ): void; + createUserAttributeChange( + key: string, + newValue: string, + previousUserAttributeValue: string, + isNewAttribute: boolean, + deleted: boolean, + user: IMParticleUser + ): IUserAttributeChangeEvent; + createUserIdentityChange( + identityType: SDKIdentityTypeEnum, + newIdentity: string, + oldIdentity: string, + newCreatedThisBatch: boolean, + userInMemory: IMParticleUser + ): IUserIdentityChangeEvent; + parseIdentityResponse( + xhr: XMLHttpRequest, + previousMPID: MPID, + callback: IdentityCallback, + identityApiData: IdentityApiData, + method: IdentityAPIMethod, + knownIdentities: UserIdentities, + parsingCachedResponse: boolean + ): void; + sendUserAttributeChangeEvent( + attributeKey: string, + newUserAttributeValue: string, + previousUserAttributeValue: string, + isNewAttribute: boolean, + deleted: boolean, + user: IMParticleUser + ): void; + sendUserIdentityChangeEvent( + newUserIdentities: UserIdentities, + method: IdentityAPIMethod, + mpid: MPID, + prevUserIdentities: UserIdentities + ): void; + + /** + * @deprecated + */ + mParticleUserCart(mpid: MPID): mParticleUserCart; +} diff --git a/src/identity.js b/src/identity.js index b2e9dba4..bb323eba 100644 --- a/src/identity.js +++ b/src/identity.js @@ -1272,6 +1272,7 @@ export default function Identity(mpInstance) { * @method getuserAudiences * @param {Function} [callback] A callback function that is invoked when the user audience request completes */ + // https://go.mparticle.com/work/SQDSDKS-6436 getUserAudiences: function(callback) { // user audience API is feature flagged if ( @@ -1829,6 +1830,7 @@ export default function Identity(mpInstance) { ) { var userIdentityChangeEvent; + // https://go.mparticle.com/work/SQDSDKS-6439 userIdentityChangeEvent = mpInstance._ServerModel.createEventObject({ messageType: Types.MessageType.UserIdentityChange, userIdentityChanges: { @@ -1883,6 +1885,7 @@ export default function Identity(mpInstance) { } var userAttributeChangeEvent; if (newValue !== previousUserAttributeValue) { + // https://go.mparticle.com/work/SQDSDKS-6439 userAttributeChangeEvent = mpInstance._ServerModel.createEventObject( { messageType: Types.MessageType.UserAttributeChange, diff --git a/src/persistence.interfaces.ts b/src/persistence.interfaces.ts index d85f510d..5fbe89f4 100644 --- a/src/persistence.interfaces.ts +++ b/src/persistence.interfaces.ts @@ -14,6 +14,7 @@ import { SessionAttributes, } from './store'; import { Dictionary } from './utils'; +import { UserAttributes } from './identity-user-interfaces'; export type CookieSyncDate = Dictionary; export type UploadsTable = Dictionary; @@ -22,10 +23,6 @@ export interface iForwardingStatsBatches { forwardingStatsEventQueue: ForwardingStatsData[]; } -// TODO: Migrate this to @types/mparticle__web-sdk -// https://go.mparticle.com/work/SQDSDKS-5196 -export type UserAttributes = AllUserAttributes; - export interface IGlobalStoreV2MinifiedKeys { sid: string; // Session ID ie: boolean; // Is Enabled diff --git a/src/sdkRuntimeModels.ts b/src/sdkRuntimeModels.ts index a3e92346..f3472b62 100644 --- a/src/sdkRuntimeModels.ts +++ b/src/sdkRuntimeModels.ts @@ -1,14 +1,9 @@ import * as EventsApi from '@mparticle/event-models'; import { DataPlanVersion } from '@mparticle/data-planning-models'; -import { - MPConfiguration, - IdentityApiData, - MPID, - Callback, -} from '@mparticle/web-sdk'; +import { MPConfiguration, MPID, Callback } from '@mparticle/web-sdk'; import { IStore } from './store'; import Validators from './validators'; -import { Dictionary, valueof } from './utils'; +import { Dictionary } from './utils'; import { IServerModel } from './serverModel'; import { IKitConfigs } from './configAPIClient'; import { SDKConsentApi, SDKConsentState } from './consent'; @@ -16,7 +11,13 @@ import { IPersistence } from './persistence.interfaces'; import { IMPSideloadedKit } from './sideloadedKit'; import { ISessionManager } from './sessionManager'; import { Kit, MPForwarder } from './forwarders.interfaces'; -import Constants from './constants'; +import { SDKIdentityApi } from './identity.interfaces'; +import { + ISDKUserAttributeChangeData, + ISDKUserIdentityChanges, + IMParticleUser, + ISDKUserIdentity, +} from './identity-user-interfaces'; // TODO: Resolve this with version in @mparticle/web-sdk export type SDKEventCustomFlags = Dictionary; @@ -27,7 +28,7 @@ export interface SDKEvent { EventName: string; EventCategory: number; UserAttributes?: { [key: string]: string | string[] | null }; - UserIdentities?: SDKUserIdentity[]; + UserIdentities?: ISDKUserIdentity[]; SourceMessageId: string; MPID: string; EventAttributes?: { [key: string]: string }; @@ -51,15 +52,12 @@ export interface SDKEvent { PromotionAction?: SDKPromotionAction; ProductImpressions?: SDKProductImpression[]; ShoppingCart?: SDKShoppingCart; - UserIdentityChanges?: SDKUserIdentityChangeData; - UserAttributeChanges?: SDKUserAttributeChangeData; + UserIdentityChanges?: ISDKUserIdentityChanges; + UserAttributeChanges?: ISDKUserAttributeChangeData; CurrencyCode: string; DataPlan?: SDKDataPlan; LaunchReferral?: string; } - -export type IdentityAPIMethod = valueof; - export interface SDKGeoLocation { lat: number | string; lng: number | string; @@ -70,11 +68,6 @@ export interface SDKDataPlan { PlanId?: string | null; } -export interface SDKUserIdentity { - Identity?: string; - Type: number; -} - export interface SDKShoppingCart { ProductList?: SDKProduct[]; } @@ -239,16 +232,6 @@ export interface DataPlanConfig { document?: DataPlanResult; // when the data plan comes from the server via /mparticle.js } -export interface SDKIdentityApi { - getCurrentUser(); - IdentityAPI; - identify; - login; - logout; - modify; - getUser(mpid: string): MParticleUser; -} - export interface SDKHelpersApi { canLog?(): boolean; createMainStorageName?(workspaceToken: string): string; @@ -271,7 +254,7 @@ export interface SDKHelpersApi { callback: Callback, code: string, body: string, - mParticleUser?: MParticleUser, + mParticleUser?: IMParticleUser, previousMpid?: MPID ): void; sanitizeAttributes?( @@ -304,35 +287,6 @@ export interface SDKConfigApi { onCreateBatch(batch: EventsApi.Batch): EventsApi.Batch; } -// FIXME: Resolve with User in @types/mparticle-web-sdk -// https://go.mparticle.com/work/SQDSDKS-5033 -export interface MParticleUser { - getMPID(): string; - getConsentState(): SDKConsentState; - getAllUserAttributes(): any; // FIXME; - getUserIdentities(): IdentityApiData; // FIXME: Is this correct? -} - -export interface SDKUserIdentityChangeData { - New: Identity; - Old: Identity; -} - -export interface Identity { - IdentityType: SDKIdentityTypeEnum; - Identity: string; - Timestamp: number; - CreatedThisBatch: boolean; -} - -export interface SDKUserAttributeChangeData { - UserAttributeName: string; - New: string; - Old: string; - Deleted: boolean; - IsNewAttribute: boolean; -} - export interface BaseEvent { messageType: number; name?: string; @@ -341,8 +295,8 @@ export interface BaseEvent { customFlags?: { [key: string]: string }; toEventAPIObject?(): SDKEvent; sourceMessageId?: string; - userAttributeChanges?: SDKUserAttributeChangeData; - userIdentityChanges?: SDKUserIdentityChangeData; + userAttributeChanges?: ISDKUserAttributeChangeData; + userIdentityChanges?: ISDKUserIdentityChanges; } export interface KitBlockerOptions { @@ -369,28 +323,3 @@ export interface DataPlanResult { }; error_message?: string; } - -export enum SDKIdentityTypeEnum { - other = 'other', - customerId = 'customerid', - facebook = 'facebook', - twitter = 'twitter', - google = 'google', - microsoft = 'microsoft', - yahoo = 'yahoo', - email = 'email', - alias = 'alias', - facebookCustomAudienceId = 'facebookcustomaudienceid', - otherId2 = 'other2', - otherId3 = 'other3', - otherId4 = 'other4', - otherId5 = 'other5', - otherId6 = 'other6', - otherId7 = 'other7', - otherId8 = 'other8', - otherId9 = 'other9', - otherId10 = 'other10', - mobileNumber = 'mobile_number', - phoneNumber2 = 'phone_number_2', - phoneNumber3 = 'phone_number_3', -} diff --git a/src/sdkToEventsApiConverter.ts b/src/sdkToEventsApiConverter.ts index cb32255a..97098477 100644 --- a/src/sdkToEventsApiConverter.ts +++ b/src/sdkToEventsApiConverter.ts @@ -3,10 +3,8 @@ import { SDKGeoLocation, SDKProduct, SDKPromotion, - SDKUserIdentity, SDKProductActionType, MParticleWebSDK, - SDKIdentityTypeEnum, } from './sdkRuntimeModels'; import * as EventsApi from '@mparticle/event-models'; import { @@ -16,6 +14,8 @@ import { } from './consent'; import Types from './types'; import { isEmpty } from './utils'; +import { ISDKUserIdentity } from './identity-user-interfaces'; +import { SDKIdentityTypeEnum } from './identity.interfaces'; export function convertEvents( mpid: string, @@ -151,7 +151,7 @@ export function convertCcpaConsentState( } export function convertUserIdentities( - sdkUserIdentities?: SDKUserIdentity[] + sdkUserIdentities?: ISDKUserIdentity[] ): EventsApi.BatchUserIdentities | null { if (!sdkUserIdentities || !sdkUserIdentities.length) { return null; @@ -407,8 +407,9 @@ export function convertShoppingCart( export function convertCommerceEvent( sdkEvent: SDKEvent ): EventsApi.CommerceEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let commerceEventData: EventsApi.CommerceEventData = { custom_flags: sdkEvent.CustomFlags, product_action: convertProductAction(sdkEvent), @@ -427,8 +428,9 @@ export function convertCommerceEvent( export function convertCrashReportEvent( sdkEvent: SDKEvent ): EventsApi.CrashReportEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let crashReportEventData: EventsApi.CrashReportEventData = { message: sdkEvent.EventName, }; @@ -442,8 +444,9 @@ export function convertCrashReportEvent( export function convertAST( sdkEvent: SDKEvent ): EventsApi.ApplicationStateTransitionEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let astEventData: EventsApi.ApplicationStateTransitionEventData = { application_transition_type: EventsApi @@ -463,8 +466,9 @@ export function convertAST( export function convertSessionEndEvent( sdkEvent: SDKEvent ): EventsApi.SessionEndEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let sessionEndEventData: EventsApi.SessionEndEventData = { session_duration_ms: sdkEvent.SessionLength, //note: External Events DTO does not support the session mpids array as of this time. @@ -480,8 +484,9 @@ export function convertSessionEndEvent( export function convertSessionStartEvent( sdkEvent: SDKEvent ): EventsApi.SessionStartEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let sessionStartEventData: EventsApi.SessionStartEventData = {}; sessionStartEventData = Object.assign( sessionStartEventData, @@ -496,8 +501,9 @@ export function convertSessionStartEvent( export function convertPageViewEvent( sdkEvent: SDKEvent ): EventsApi.ScreenViewEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let screenViewEventData: EventsApi.ScreenViewEventData = { custom_flags: sdkEvent.CustomFlags, screen_name: sdkEvent.EventName, @@ -510,8 +516,9 @@ export function convertPageViewEvent( } export function convertOptOutEvent(sdkEvent: SDKEvent): EventsApi.OptOutEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let optOutEventData: EventsApi.OptOutEventData = { is_opted_out: sdkEvent.OptOut, }; @@ -523,8 +530,9 @@ export function convertOptOutEvent(sdkEvent: SDKEvent): EventsApi.OptOutEvent { } export function convertCustomEvent(sdkEvent: SDKEvent): EventsApi.CustomEvent { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let customEventData: EventsApi.CustomEventData = { custom_event_type: convertSdkEventType( sdkEvent.EventCategory @@ -628,8 +636,9 @@ export function convertSDKLocation( export function convertUserAttributeChangeEvent( sdkEvent: SDKEvent ): EventsApi.UserAttributeChangeEvent | null { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let userAttributeChangeEvent: EventsApi.UserAttributeChangeEventData = { user_attribute_name: sdkEvent.UserAttributeChanges.UserAttributeName, new: sdkEvent.UserAttributeChanges.New, @@ -652,8 +661,9 @@ export function convertUserAttributeChangeEvent( export function convertUserIdentityChangeEvent( sdkEvent: SDKEvent ): EventsApi.UserIdentityChangeEvent | null { - const commonEventData: EventsApi.CommonEventData = - convertBaseEventData(sdkEvent); + const commonEventData: EventsApi.CommonEventData = convertBaseEventData( + sdkEvent + ); let userIdentityChangeEvent: EventsApi.UserIdentityChangeEventData = { new: { diff --git a/src/serverModel.ts b/src/serverModel.ts index 71cb92be..44e97f57 100644 --- a/src/serverModel.ts +++ b/src/serverModel.ts @@ -6,12 +6,10 @@ import Types from './types'; import Constants from './constants'; import { BaseEvent, - MParticleUser, MParticleWebSDK, SDKEvent, SDKGeoLocation, SDKProduct, - SDKUserIdentity, } from './sdkRuntimeModels'; import { parseNumber, @@ -27,6 +25,7 @@ import { IPrivacyV2DTO, SDKConsentState, } from './consent'; +import { IMParticleUser, ISDKUserIdentity } from './identity-user-interfaces'; const MessageType = Types.MessageType; const ApplicationTransitionType = Types.ApplicationTransitionType; @@ -48,7 +47,7 @@ export interface IServerV2DTO { n?: string; et?: number; ua?: Dictionary; - ui?: SDKUserIdentity[]; + ui?: ISDKUserIdentity[]; ia?: Dictionary>; str?: ServerSettings; sdk?: string; @@ -135,9 +134,9 @@ export interface IUploadObject extends SDKEvent { export interface IServerModel { convertEventToV2DTO: (event: IUploadObject) => IServerV2DTO; - createEventObject: (event: BaseEvent, user?: MParticleUser) => SDKEvent; + createEventObject: (event: BaseEvent, user?: IMParticleUser) => SDKEvent; convertToConsentStateV2DTO: (state: SDKConsentState) => IConsentStateV2DTO; - appendUserInfo: (user: MParticleUser, event: SDKEvent) => void; + appendUserInfo: (user: IMParticleUser, event: SDKEvent) => void; } // TODO: Make this a pure function that returns a new object @@ -199,7 +198,10 @@ export default function ServerModel( var self = this; // TODO: Can we refactor this to not mutate the event? - this.appendUserInfo = function(user: MParticleUser, event: SDKEvent): void { + this.appendUserInfo = function( + user: IMParticleUser, + event: SDKEvent + ): void { if (!event) { return; } @@ -230,7 +232,7 @@ export default function ServerModel( if (mpInstance._Helpers.isObject(dtoUserIdentities)) { if (Object.keys(dtoUserIdentities).length) { for (var key in dtoUserIdentities) { - var userIdentity: Partial = {}; + var userIdentity: Partial = {}; userIdentity.Identity = dtoUserIdentities[key]; userIdentity.Type = mpInstance._Helpers.parseNumber(key); validUserIdentities.push(userIdentity); @@ -292,7 +294,7 @@ export default function ServerModel( this.createEventObject = function( event: BaseEvent, - user?: MParticleUser + user?: IMParticleUser ): SDKEvent | IUploadObject { var uploadObject: Partial = {}; var eventObject: Partial = {}; diff --git a/src/sessionManager.ts b/src/sessionManager.ts index 8f2ba9d5..f0ecbbaf 100644 --- a/src/sessionManager.ts +++ b/src/sessionManager.ts @@ -1,9 +1,10 @@ import { MPID } from '@mparticle/web-sdk'; import Constants from './constants'; import { IPersistenceMinified } from './persistence.interfaces'; -import { MParticleUser, MParticleWebSDK } from './sdkRuntimeModels'; +import { MParticleWebSDK } from './sdkRuntimeModels'; import Types from './types'; import { generateDeprecationMessage } from './utils'; +import { IMParticleUser } from './identity-user-interfaces'; const { Messages } = Constants; @@ -86,7 +87,7 @@ export default function SessionManager( .generateUniqueId() .toUpperCase(); - const currentUser: MParticleUser = mpInstance.Identity.getCurrentUser(); + const currentUser: IMParticleUser = mpInstance.Identity.getCurrentUser(); const mpid: MPID = currentUser ? currentUser.getMPID() : null; if (mpid) { diff --git a/src/utils.ts b/src/utils.ts index 51af1c09..ac498097 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,6 +7,8 @@ type valueof = T[keyof T]; // Placeholder for Dictionary-like Types export type Dictionary = Record; +export type Environment = 'development' | 'production'; + const createCookieString = (value: string): string => replaceCommasWithPipes(replaceQuotesWithApostrophes(value)); diff --git a/src/validators.ts b/src/validators.ts index efe069ca..7a29cf5b 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -8,7 +8,7 @@ import { } from './utils'; import Constants from './constants'; import { IdentityApiData } from '@mparticle/web-sdk'; -import { IdentityAPIMethod } from './sdkRuntimeModels'; +import { IdentityAPIMethod } from './identity.interfaces'; type ValidationIdentitiesReturn = { valid: boolean; diff --git a/test/jest/identity.spec.ts b/test/jest/identity.spec.ts new file mode 100644 index 00000000..74c89860 --- /dev/null +++ b/test/jest/identity.spec.ts @@ -0,0 +1,216 @@ +import { + ISDKUserIdentityChangeData, + IUserAttributeChangeEvent, + IUserIdentityChangeEvent, +} from '../../src/identity-user-interfaces'; +import { + IIdentityAPIRequestData, + IdentityAPIMethod, + IdentityPreProcessResult, + IIdentityAPIModifyRequestData, + IAliasRequest, + SDKIdentityTypeEnum, + IIdentityAPIIdentityChangeData, +} from '../../src/identity.interfaces'; +import { MessageType } from '../../src/types.interfaces'; + +describe('Identity', () => { + describe('#types', () => { + it('defines IdentityAPIMethods', () => { + const identify: IdentityAPIMethod = 'identify'; + const login: IdentityAPIMethod = 'login'; + const logout: IdentityAPIMethod = 'logout'; + const modify: IdentityAPIMethod = 'modify'; + + expect(identify).toEqual('identify'); + expect(login).toEqual('login'); + expect(logout).toEqual('logout'); + expect(modify).toEqual('modify'); + }); + + it('defines IdentityPreProcessResult', () => { + const IdentityPreProcessResult: IdentityPreProcessResult = { + valid: true, + error: 'I AM ERROR', + }; + + expect(IdentityPreProcessResult).toBeDefined(); + }); + + it('defines SDKIdentityTypeEnum', () => { + const google: SDKIdentityTypeEnum = SDKIdentityTypeEnum.google; + const facebook: SDKIdentityTypeEnum = SDKIdentityTypeEnum.facebook; + const microsoft: SDKIdentityTypeEnum = + SDKIdentityTypeEnum.microsoft; + const customerId: SDKIdentityTypeEnum = + SDKIdentityTypeEnum.customerId; + const twitter: SDKIdentityTypeEnum = SDKIdentityTypeEnum.twitter; + const yahoo: SDKIdentityTypeEnum = SDKIdentityTypeEnum.yahoo; + const email: SDKIdentityTypeEnum = SDKIdentityTypeEnum.email; + const alias: SDKIdentityTypeEnum = SDKIdentityTypeEnum.alias; + const facebookCustomAudienceId: SDKIdentityTypeEnum = + SDKIdentityTypeEnum.facebookCustomAudienceId; + + const other: SDKIdentityTypeEnum = SDKIdentityTypeEnum.other; + const otherId2: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId2; + const otherId3: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId3; + const otherId4: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId4; + const otherId5: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId5; + const otherId6: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId6; + const otherId7: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId7; + const otherId8: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId8; + const otherId9: SDKIdentityTypeEnum = SDKIdentityTypeEnum.otherId9; + const otherId10: SDKIdentityTypeEnum = + SDKIdentityTypeEnum.otherId10; + + const mobileNumber: SDKIdentityTypeEnum = + SDKIdentityTypeEnum.mobileNumber; + const phoneNumber2: SDKIdentityTypeEnum = + SDKIdentityTypeEnum.phoneNumber2; + const phoneNumber3: SDKIdentityTypeEnum = + SDKIdentityTypeEnum.phoneNumber3; + + expect(google).toEqual('google'); + expect(facebook).toEqual('facebook'); + expect(microsoft).toEqual('microsoft'); + expect(customerId).toEqual('customerid'); + expect(twitter).toEqual('twitter'); + expect(yahoo).toEqual('yahoo'); + expect(email).toEqual('email'); + expect(alias).toEqual('alias'); + expect(facebookCustomAudienceId).toEqual( + 'facebookcustomaudienceid' + ); + + expect(other).toEqual('other'); + expect(otherId2).toEqual('other2'); + expect(otherId3).toEqual('other3'); + expect(otherId4).toEqual('other4'); + expect(otherId5).toEqual('other5'); + expect(otherId6).toEqual('other6'); + expect(otherId7).toEqual('other7'); + expect(otherId8).toEqual('other8'); + expect(otherId9).toEqual('other9'); + expect(otherId10).toEqual('other10'); + + expect(mobileNumber).toEqual('mobile_number'); + expect(phoneNumber2).toEqual('phone_number_2'); + expect(phoneNumber3).toEqual('phone_number_3'); + }); + }); + + describe('#interfaces', () => { + it('defines identity change data', () => { + const testIdentity: ISDKUserIdentityChangeData = { + IdentityType: SDKIdentityTypeEnum.google, + Identity: 'test identity', + Timestamp: Date.now(), + CreatedThisBatch: false, + }; + + expect(testIdentity).toBeDefined(); + }); + + it('defines identity api request data', () => { + const testIdentityApiRequest: IIdentityAPIRequestData = { + client_sdk: { + platform: 'web', + sdk_vendor: 'mparticle', + sdk_version: '1.0.0', + }, + context: 'test-context', + environment: 'development', + request_id: '123', + reqest_timestamp_unixtime_ms: Date.now(), + previous_mpid: null, + known_identities: { + email: 'user@mparticle.com', + }, + }; + + expect(testIdentityApiRequest).toBeDefined(); + }); + + it('defines identity api modify request data', () => { + const testIdentityApiModifyRequest: IIdentityAPIModifyRequestData = { + client_sdk: { + platform: 'web', + sdk_vendor: 'mparticle', + sdk_version: '1.0.0', + }, + context: 'test-context', + environment: 'development', + request_id: '123', + reqest_timestamp_unixtime_ms: Date.now(), + identity_changes: [ + { + identity_type: SDKIdentityTypeEnum.google, + old_value: 'old value', + new_value: 'new value', + }, + ], + }; + + expect(testIdentityApiModifyRequest).toBeDefined(); + }); + + it('defines identity api change data', () => { + const testIdentityApiChangeData: IIdentityAPIIdentityChangeData = { + identity_type: SDKIdentityTypeEnum.google, + old_value: 'old value', + new_value: 'new value', + }; + + expect(testIdentityApiChangeData).toBeDefined(); + }); + + it('defines user attribute change event', () => { + const testUserAttributeChangeEvent: IUserAttributeChangeEvent = { + messageType: MessageType.UserAttributeChange, + userAttributeChanges: { + UserAttributeName: 'foo', + New: 'new', + Old: 'old', + IsNewAttribute: true, + Deleted: false, + }, + }; + + expect(testUserAttributeChangeEvent).toBeDefined(); + }); + + it('defines user identity change event', () => { + const testAttributeChangeEvent: IUserIdentityChangeEvent = { + messageType: MessageType.UserIdentityChange, + userIdentityChanges: { + New: { + Identity: 'Google ID', + IdentityType: SDKIdentityTypeEnum.google, + CreatedThisBatch: true, + Timestamp: Date.now(), // optional + }, + Old: { + Identity: 'Facebook ID', + IdentityType: SDKIdentityTypeEnum.facebook, + CreatedThisBatch: false, + Timestamp: Date.now(), // optional + }, + }, + }; + + expect(testAttributeChangeEvent).toBeDefined(); + }); + + it('defines alias request', () => { + const testAliasRequest: IAliasRequest = { + destinationMpid: '123', + sourceMpid: '456', + startTime: Date.now(), + endTime: Date.now() + 1000, + scope: 'test-scope', + }; + + expect(testAliasRequest).toBeDefined(); + }); + }); +}); diff --git a/test/src/tests-apiClient.ts b/test/src/tests-apiClient.ts index af2bd57c..78fc8277 100644 --- a/test/src/tests-apiClient.ts +++ b/test/src/tests-apiClient.ts @@ -3,6 +3,7 @@ import Constants from '../../src/constants'; import { apiKey, MPConfig } from './config/constants'; import { MParticleWebSDK } from '../../src/sdkRuntimeModels'; import { expect } from 'chai'; +import { IMParticleUser } from '../../src/identity-user-interfaces'; declare global { interface Window { @@ -93,7 +94,7 @@ describe('Api Client', () => { getConsentState: () => { return consentState; }, - }; + } as IMParticleUser; }; mParticle diff --git a/test/src/tests-persistence.ts b/test/src/tests-persistence.ts index c8ea6e7c..f94d70b6 100644 --- a/test/src/tests-persistence.ts +++ b/test/src/tests-persistence.ts @@ -1506,17 +1506,17 @@ describe('persistence', () => { const storedConsentState = mParticle .getInstance() .Identity.getCurrentUser() - .getConsentState(); - storedConsentState.should.be.ok(); - storedConsentState - .getGDPRConsentState() - .should.have.property('foo purpose'); - storedConsentState - .getGDPRConsentState() - ['foo purpose'].should.have.property('Consented', true); - storedConsentState - .getGDPRConsentState() - ['foo purpose'].should.have.property('Timestamp', 10); + .getConsentState() as any; + expect(storedConsentState).to.be.ok; + expect(storedConsentState.getGDPRConsentState()).to.have.property( + 'foo purpose' + ); + expect( + storedConsentState.getGDPRConsentState()['foo purpose'] + ).to.have.property('Consented', true); + expect( + storedConsentState.getGDPRConsentState()['foo purpose'] + ).to.have.property('Timestamp', 10); done(); }); diff --git a/test/src/tests-runtimeToBatchEventsDTO.ts b/test/src/tests-runtimeToBatchEventsDTO.ts index cbb32563..607e393d 100644 --- a/test/src/tests-runtimeToBatchEventsDTO.ts +++ b/test/src/tests-runtimeToBatchEventsDTO.ts @@ -3,8 +3,8 @@ import { expect } from 'chai'; import Types from '../../src/types'; import { SDKEvent, MParticleWebSDK } from '../../src/sdkRuntimeModels'; import * as EventsApi from '@mparticle/event-models'; -import Utils from './config/utils'; -import { urls, MPConfig, apiKey } from './config/constants'; +import { MPConfig, apiKey } from './config/constants'; +import { IMParticleUser } from '../../src/identity-user-interfaces'; declare global { interface Window { @@ -66,7 +66,7 @@ describe('Old model to batch model conversion', () => { getConsentState: () => { return null; }, - }; + } as IMParticleUser; }; const publicEvent = { @@ -143,7 +143,7 @@ describe('Old model to batch model conversion', () => { getConsentState: () => { return null; }, - }; + } as IMParticleUser; }; const publicEvent = { messageType: Types.MessageType.PageEvent, @@ -236,7 +236,7 @@ describe('Old model to batch model conversion', () => { getConsentState: () => { return null; }, - }; + } as IMParticleUser; }; const publicEvent = { messageType: Types.MessageType.PageEvent, diff --git a/test/src/tests-serverModel.ts b/test/src/tests-serverModel.ts index bdbd2798..a1ddfa66 100644 --- a/test/src/tests-serverModel.ts +++ b/test/src/tests-serverModel.ts @@ -4,13 +4,14 @@ import { urls, testMPID, apiKey } from './config/constants'; import { expect } from 'chai'; import { IUploadObject } from '../../src/serverModel'; import { AllUserAttributes, IdentityApiData } from '@mparticle/web-sdk'; -import { BaseEvent, MParticleUser, SDKEvent } from '../../src/sdkRuntimeModels'; +import { BaseEvent, SDKEvent } from '../../src/sdkRuntimeModels'; import Constants from '../../src/constants'; import { SDKConsentState, SDKCCPAConsentState, SDKGDPRConsentState, } from '../../src/consent'; +import { IMParticleUser } from '../../src/identity-user-interfaces'; let mockServer; let initialEvent = {}; @@ -31,7 +32,7 @@ describe('ServerModel', () => { describe('#appendUserInfo', () => { it('should append User Identities and Attributes to event', () => { - const user = { + const user = ({ getUserIdentities: () => { return { userIdentities: { @@ -75,7 +76,7 @@ describe('ServerModel', () => { }, }; }, - } as unknown as MParticleUser; + } as unknown) as IMParticleUser; // TODO: We should move some of the event samples into a reusable module // or set up an event factory @@ -143,7 +144,7 @@ describe('ServerModel', () => { }); it('returns undefined if event is empty', () => { - expect(ServerModel.appendUserInfo({} as MParticleUser, null)).to.be + expect(ServerModel.appendUserInfo({} as IMParticleUser, null)).to.be .undefined; }); @@ -167,7 +168,10 @@ describe('ServerModel', () => { MPID: '123456', }; - ServerModel.appendUserInfo(user, event as SDKEvent); + ServerModel.appendUserInfo( + user as IMParticleUser, + event as SDKEvent + ); expect(event.MPID).to.equal('123456'); // Verify to make sure we didn't add anything unnecessary to the event @@ -194,7 +198,10 @@ describe('ServerModel', () => { MPID: '555666777', }; - ServerModel.appendUserInfo(user, event as SDKEvent); + ServerModel.appendUserInfo( + user as IMParticleUser, + event as SDKEvent + ); expect(event.MPID).to.equal('123456'); }); @@ -508,7 +515,7 @@ describe('ServerModel', () => { }, }; - const user = { + const user = ({ getUserIdentities: () => { return { userIdentities: { @@ -552,7 +559,7 @@ describe('ServerModel', () => { }, }; }, - } as unknown as MParticleUser; + } as unknown) as IMParticleUser; const actualEventObject = mParticle .getInstance() @@ -627,8 +634,14 @@ describe('ServerModel', () => { expect(actualEventObject.EventAttributes, 'EventAttributes').to.eql( { fooSessionAttr: 'session-foo', barSessionAttr: 'session-bar' } ); - expect(actualEventObject.EventAttributes, 'EventAttributes').to.not.have.property('fooEventAttr'); - expect(actualEventObject.EventAttributes, 'EventAttributes').to.not.have.property('barEventAttr'); + expect( + actualEventObject.EventAttributes, + 'EventAttributes' + ).to.not.have.property('fooEventAttr'); + expect( + actualEventObject.EventAttributes, + 'EventAttributes' + ).to.not.have.property('barEventAttr'); // A SessionEnd event resets currentSessionMPIDs and sessionStartDate. When a new session starts, these are filled again expect(mPStore.currentSessionMPIDs).to.eql([]); @@ -1490,7 +1503,7 @@ describe('ServerModel', () => { getConsentState: () => { return consentState; }, - }; + } as IMParticleUser; }; let sdkEvent = mParticle .getInstance() @@ -1513,7 +1526,7 @@ describe('ServerModel', () => { sdkEvent.should.be.ok; expect(sdkEvent.UserIdentities).to.eql([]); - const user = { + const user: IMParticleUser = ({ getUserIdentities: () => { return { userIdentities: { @@ -1536,7 +1549,7 @@ describe('ServerModel', () => { getConsentState: () => { return null; }, - }; + } as unknown) as IMParticleUser; const identityMapping = {}; identityMapping[Types.IdentityType.CustomerId] = '1234567'; @@ -1567,7 +1580,7 @@ describe('ServerModel', () => { sdkEvent.should.be.ok; expect(sdkEvent.UserAttributes).to.eql({}); const attributes = { foo: 'bar', 'foo-arr': ['bar1', 'bar2'] }; - const user: MParticleUser = { + const user: IMParticleUser = { getUserIdentities: (): IdentityApiData => ({ userIdentities: {}, }), @@ -1580,7 +1593,7 @@ describe('ServerModel', () => { getConsentState: () => { return null; }, - }; + } as IMParticleUser; mParticle.getInstance()._ServerModel.appendUserInfo(user, sdkEvent); expect(sdkEvent.UserAttributes).to.be.ok; @@ -1599,8 +1612,7 @@ describe('ServerModel', () => { // By default, all tests instances have 'testMPID' expect(sdkEvent.MPID).to.equal('testMPID'); - // TODO: this makes the compiler angry unless we make it hacky - const user: MParticleUser = { + const user: IMParticleUser = { getUserIdentities: () => { return ({ userIdentites: {}, @@ -1615,7 +1627,7 @@ describe('ServerModel', () => { getConsentState: () => { return null; }, - }; + } as IMParticleUser; mParticle.getInstance()._ServerModel.appendUserInfo(user, sdkEvent); expect(sdkEvent.MPID).to.equal('98765'); done(); @@ -1659,4 +1671,4 @@ describe('ServerModel', () => { done(); }); }); -}); \ No newline at end of file +});