diff --git a/src/mockBatchCreator.ts b/src/mockBatchCreator.ts index dfb050c3..73776ec3 100644 --- a/src/mockBatchCreator.ts +++ b/src/mockBatchCreator.ts @@ -6,11 +6,26 @@ import { convertEvents } from './sdkToEventsApiConverter'; import * as EventsApi from '@mparticle/event-models'; import { Batch } from '@mparticle/event-models'; import { IMPSideloadedKit } from './sideloadedKit'; +import { IStore, SDKConfig } from './store'; const mockFunction = function() { return null; }; export default class _BatchValidator { + private configOverride?: Partial>; + private storeOverride?: Partial>; + + constructor({ + configOverride = {}, + storeOverride = {} + }: { + configOverride?: Partial>, + storeOverride?: Partial> + } = {}) { + this.configOverride = configOverride + this.storeOverride = storeOverride + } + private getMPInstance() { return ({ // Certain Helper, Store, and Identity properties need to be mocked to be used in the `returnBatch` method @@ -87,7 +102,9 @@ export default class _BatchValidator { SDKConfig: { isDevelopmentMode: false, onCreateBatch: mockFunction, + omitBatchTimestamp: this.configOverride?.omitBatchTimestamp, }, + batchTimestampUnixtimeMsOverride: this.storeOverride?.batchTimestampUnixtimeMsOverride }, config: null, eCommerce: null, diff --git a/src/sdkRuntimeModels.ts b/src/sdkRuntimeModels.ts index 9f6c5a9c..021f9e3b 100644 --- a/src/sdkRuntimeModels.ts +++ b/src/sdkRuntimeModels.ts @@ -250,6 +250,7 @@ export interface SDKInitConfig workspaceToken?: string; isDevelopmentMode?: boolean; + omitBatchTimestamp?: boolean; // https://go.mparticle.com/work/SQDSDKS-6460 identityCallback?: IdentityCallback; diff --git a/src/sdkToEventsApiConverter.ts b/src/sdkToEventsApiConverter.ts index f4c51b31..e5b2a9ea 100644 --- a/src/sdkToEventsApiConverter.ts +++ b/src/sdkToEventsApiConverter.ts @@ -56,10 +56,25 @@ export function convertEvents( currentConsentState = user.getConsentState(); } + // determine what timestamp, if any, to use for the batch + const { omitBatchTimestamp } = mpInstance._Store.SDKConfig; + const { batchTimestampUnixtimeMsOverride } = mpInstance._Store; + + let timestamp_unixtime_ms: number | null + + if (batchTimestampUnixtimeMsOverride) { + timestamp_unixtime_ms = batchTimestampUnixtimeMsOverride; + } else if (omitBatchTimestamp) { + timestamp_unixtime_ms = null; + } else { + timestamp_unixtime_ms = new Date().getTime(); + } + + const upload: EventsApi.Batch = { source_request_id: mpInstance._Helpers.generateUniqueId(), mpid, - timestamp_unixtime_ms: new Date().getTime(), + timestamp_unixtime_ms, environment: lastEvent.Debug ? EventsApi.BatchEnvironmentEnum.development : EventsApi.BatchEnvironmentEnum.production, diff --git a/src/store.ts b/src/store.ts index d48158e1..ea09c12f 100644 --- a/src/store.ts +++ b/src/store.ts @@ -89,6 +89,7 @@ export interface SDKConfig { webviewBridgeName?: string; workspaceToken?: string; requiredWebviewBridgeName?: string; + omitBatchTimestamp?: boolean; } function createSDKConfig(config: SDKInitConfig): SDKConfig { @@ -182,6 +183,7 @@ export interface IStore { integrationDelayTimeoutStart: number; // UNIX Timestamp webviewBridgeEnabled?: boolean; wrapperSDKInfo: WrapperSDKInfo; + batchTimestampUnixtimeMsOverride?: number persistenceData?: IPersistenceMinified; @@ -477,6 +479,10 @@ export default function Store( this.SDKConfig.onCreateBatch = undefined; } } + + if (config.hasOwnProperty('omitBatchTimestamp')) { + this.SDKConfig.omitBatchTimestamp = config.omitBatchTimestamp; + } } this._getFromPersistence = (mpid: MPID, key: string): T | null => { diff --git a/test/src/tests-mockBatchCreator.ts b/test/src/tests-mockBatchCreator.ts index e9115460..ecdc9a06 100644 --- a/test/src/tests-mockBatchCreator.ts +++ b/test/src/tests-mockBatchCreator.ts @@ -3,19 +3,21 @@ import { BaseEvent } from '../../src/sdkRuntimeModels'; import { expect } from 'chai'; describe('Create a batch from a base event', () => { - const batchValidator = new _BatchValidator(); const baseEvent: BaseEvent = { messageType: 4, name: 'testEvent' } - + it('creates a batch with base event ', done => { + const now = new Date().getTime(); + const batchValidator = new _BatchValidator() + let batch = batchValidator.returnBatch(baseEvent); expect(batch).to.have.property('environment').equal('production'); expect(batch).to.have.property('source_request_id').equal('mockId'); expect(batch).to.have.property('mpid').equal('0'); - expect(batch).to.have.property('timestamp_unixtime_ms') + expect(batch).to.have.property('timestamp_unixtime_ms').greaterThanOrEqual(now); expect(batch).to.have.property('mp_deviceid'); expect(batch).to.have.property('sdk_version') expect(batch).to.have.property('application_info'); @@ -47,7 +49,7 @@ describe('Create a batch from a base event', () => { batch = batchValidator.returnBatch(baseEvent); expect(batch.events[0].data).to.have.property('custom_attributes'); expect(batch.events[0].data.custom_attributes).to.have.property('attrFoo', 'attrBar'); - + baseEvent.customFlags = { flagFoo: 'flagBar' } batch = batchValidator.returnBatch(baseEvent); expect(batch.events[0].data).to.have.property('custom_flags'); @@ -55,4 +57,48 @@ describe('Create a batch from a base event', () => { done(); }); + + [undefined, null, false, true].forEach(omitBatchTimestamp => { + it(`respects an omitBatchTimestamp config value of ${omitBatchTimestamp}`, done => { + const now = new Date().getTime(); + const batchValidator = new _BatchValidator({ + configOverride: {omitBatchTimestamp} + }); + + const batch = batchValidator.returnBatch(baseEvent); + + if (omitBatchTimestamp) { + expect(batch).to.have.property('timestamp_unixtime_ms', null); + } else { + expect(batch).to.have.property('timestamp_unixtime_ms').greaterThanOrEqual(now); + } + + done(); + }); + }) + + it(`can use a batch timestamp override value`, done => { + const oneDayAgo = new Date().getTime() - (24 * 3600 * 1000); + const batchValidator = new _BatchValidator({ + storeOverride: {batchTimestampUnixtimeMsOverride: oneDayAgo} + }); + const batch = batchValidator.returnBatch(baseEvent); + + expect(batch).to.have.property('timestamp_unixtime_ms').greaterThanOrEqual(oneDayAgo); + + done(); + }); + + it(`a batch timestamp override takes precedence over the sdk config`, done => { + const oneDayAgo = new Date().getTime() - (24 * 3600 * 1000); + const batchValidator = new _BatchValidator({ + configOverride: {omitBatchTimestamp: true}, + storeOverride: {batchTimestampUnixtimeMsOverride: oneDayAgo}} + ); + const batch = batchValidator.returnBatch(baseEvent); + + expect(batch).to.have.property('timestamp_unixtime_ms').greaterThanOrEqual(oneDayAgo); + + done(); + }); }); \ No newline at end of file