From 0111539d89763b7acc96cace7ce9e2540e49e07a Mon Sep 17 00:00:00 2001 From: Sunita Prajapati Date: Wed, 26 Feb 2025 11:55:57 +0530 Subject: [PATCH 1/3] fix: BackgroundFlushPolicy doesn't flush the Application Backgrounded event --- .../flushPolicies/background-flush-policy.ts | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/packages/core/src/flushPolicies/background-flush-policy.ts b/packages/core/src/flushPolicies/background-flush-policy.ts index 397a5142d..8f58fecac 100644 --- a/packages/core/src/flushPolicies/background-flush-policy.ts +++ b/packages/core/src/flushPolicies/background-flush-policy.ts @@ -1,8 +1,4 @@ -import { - AppState, - AppStateStatus, - NativeEventSubscription, -} from 'react-native'; +import { NativeEventSubscription } from 'react-native'; import type { SegmentEvent } from '../types'; import { FlushPolicyBase } from './types'; @@ -11,25 +7,17 @@ import { FlushPolicyBase } from './types'; */ export class BackgroundFlushPolicy extends FlushPolicyBase { private appStateSubscription?: NativeEventSubscription; - private appState: AppStateStatus = AppState.currentState; start() { - this.appStateSubscription = AppState.addEventListener( - 'change', - (nextAppState) => { - if ( - this.appState === 'active' && - ['inactive', 'background'].includes(nextAppState) - ) { - // When the app goes into the background we will trigger a flush - this.shouldFlush.value = true; - } - } - ); + //no-op } onEvent(_event: SegmentEvent): void { - // Nothing to do + console.log('inside onEvent', _event); + if ('event' in _event && _event.event === 'Application Backgrounded') { + console.log({ _event }); // is logged properly on background + this.shouldFlush.value = true; + } } end(): void { From 993c7cd48d6aabb9fc64a232fdddb4cad5fe1106 Mon Sep 17 00:00:00 2001 From: Sunita Prajapati Date: Mon, 3 Mar 2025 11:52:08 +0530 Subject: [PATCH 2/3] fix: BackgroundFlushPolicy doesn't flush the Application Backgrounded --- .../internal/handleAppStateChange.test.ts | 4 +-- packages/core/src/analytics.ts | 4 +-- .../__tests__/background-flush-policy.test.ts | 21 ++++++++++-- .../flushPolicies/background-flush-policy.ts | 33 +++++++++++++++---- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/packages/core/src/__tests__/internal/handleAppStateChange.test.ts b/packages/core/src/__tests__/internal/handleAppStateChange.test.ts index d1ec68b44..65a3ae110 100644 --- a/packages/core/src/__tests__/internal/handleAppStateChange.test.ts +++ b/packages/core/src/__tests__/internal/handleAppStateChange.test.ts @@ -163,7 +163,7 @@ describe('SegmentClient #handleAppStateChange', () => { // @ts-ignore expect(client.appState).toBe('background'); - expect(mockPlugin.execute).not.toHaveBeenCalled(); + expect(mockPlugin.execute).toHaveBeenCalledTimes(1); }); it('sends an event when unknown => inactive', async () => { @@ -173,6 +173,6 @@ describe('SegmentClient #handleAppStateChange', () => { // @ts-ignore expect(client.appState).toBe('inactive'); - expect(mockPlugin.execute).not.toHaveBeenCalled(); + expect(mockPlugin.execute).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/core/src/analytics.ts b/packages/core/src/analytics.ts index 374b4b9e6..1eca79be2 100644 --- a/packages/core/src/analytics.ts +++ b/packages/core/src/analytics.ts @@ -718,8 +718,8 @@ export class SegmentClient { void this.process(event); this.logger.info('TRACK (Application Opened) event saved', event); } else if ( - this.appState === 'active' && - ['inactive', 'background'].includes(nextAppState) + (this.appState === 'active' || this.appState === 'unknown') && // Check if appState is 'active' or 'unknown' //redundant condition need to check without this + ['inactive', 'background'].includes(nextAppState) // Check if next app state is 'inactive' or 'background' ) { const event = createTrackEvent({ event: 'Application Backgrounded', diff --git a/packages/core/src/flushPolicies/__tests__/background-flush-policy.test.ts b/packages/core/src/flushPolicies/__tests__/background-flush-policy.test.ts index 45ab22c7c..0e822088b 100644 --- a/packages/core/src/flushPolicies/__tests__/background-flush-policy.test.ts +++ b/packages/core/src/flushPolicies/__tests__/background-flush-policy.test.ts @@ -2,6 +2,14 @@ import { AppState, AppStateStatus } from 'react-native'; import { BackgroundFlushPolicy } from '../background-flush-policy'; describe('BackgroundFlushPolicy', () => { + beforeEach(() => { + jest.useFakeTimers(); // Mock timers + }); + + afterEach(() => { + jest.useRealTimers(); // Restore real timers + }); + it('triggers a flush when reaching limit', () => { let updateCallback = (_val: AppStateStatus) => { return; @@ -14,6 +22,7 @@ describe('BackgroundFlushPolicy', () => { return { remove: jest.fn() }; }); + AppState.currentState = 'active'; const policy = new BackgroundFlushPolicy(); policy.start(); const observer = jest.fn(); @@ -21,15 +30,21 @@ describe('BackgroundFlushPolicy', () => { policy.shouldFlush.onChange(observer); expect(addSpy).toHaveBeenCalledTimes(1); + updateCallback('inactive'); + jest.advanceTimersByTime(2000); + + console.log('Observer calls:', observer.mock.calls); + expect(observer).toHaveBeenCalledWith(true); + observer.mockClear(); updateCallback('background'); + jest.advanceTimersByTime(2000); // Simulate timer triggering expect(observer).toHaveBeenCalledWith(true); observer.mockClear(); updateCallback('active'); + jest.advanceTimersByTime(2000); expect(observer).not.toHaveBeenCalled(); - - updateCallback('inactive'); - expect(observer).toHaveBeenCalledWith(true); + observer.mockClear(); }); }); diff --git a/packages/core/src/flushPolicies/background-flush-policy.ts b/packages/core/src/flushPolicies/background-flush-policy.ts index 8f58fecac..d9ea48395 100644 --- a/packages/core/src/flushPolicies/background-flush-policy.ts +++ b/packages/core/src/flushPolicies/background-flush-policy.ts @@ -1,4 +1,8 @@ -import { NativeEventSubscription } from 'react-native'; +import { + AppState, + AppStateStatus, + NativeEventSubscription, +} from 'react-native'; import type { SegmentEvent } from '../types'; import { FlushPolicyBase } from './types'; @@ -7,17 +11,32 @@ import { FlushPolicyBase } from './types'; */ export class BackgroundFlushPolicy extends FlushPolicyBase { private appStateSubscription?: NativeEventSubscription; + private appState: AppStateStatus = AppState.currentState; start() { - //no-op + this.appStateSubscription = AppState.addEventListener( + 'change', + (nextAppState) => { + if ( + ['active', 'inactive'].includes(this.appState) && + ['inactive', 'background'].includes(nextAppState) + ) { + console.log('inside if condition'); + setTimeout(() => { + this.shouldFlush.value = true; + }, 2000); + } + this.appState = nextAppState; + } + ); } onEvent(_event: SegmentEvent): void { - console.log('inside onEvent', _event); - if ('event' in _event && _event.event === 'Application Backgrounded') { - console.log({ _event }); // is logged properly on background - this.shouldFlush.value = true; - } + //if ('event' in _event && _event.event === 'Application Backgrounded') { + // setTimeout(() => { + // this.shouldFlush.value = true; + // }, 2000); + // } } end(): void { From 67f317c1fac45ac5c10a0667e463b36064e3a208 Mon Sep 17 00:00:00 2001 From: Sunita Prajapati Date: Mon, 3 Mar 2025 12:40:42 +0530 Subject: [PATCH 3/3] refactor: removed unnecessary console --- packages/core/src/flushPolicies/background-flush-policy.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core/src/flushPolicies/background-flush-policy.ts b/packages/core/src/flushPolicies/background-flush-policy.ts index d9ea48395..0556c69d7 100644 --- a/packages/core/src/flushPolicies/background-flush-policy.ts +++ b/packages/core/src/flushPolicies/background-flush-policy.ts @@ -21,7 +21,6 @@ export class BackgroundFlushPolicy extends FlushPolicyBase { ['active', 'inactive'].includes(this.appState) && ['inactive', 'background'].includes(nextAppState) ) { - console.log('inside if condition'); setTimeout(() => { this.shouldFlush.value = true; }, 2000);