Skip to content

Commit 08e541b

Browse files
fix: BackgroundFlushPolicy doesn't flush the Application Backgrounded (#1050)
1 parent b6b396a commit 08e541b

File tree

5 files changed

+38
-50
lines changed

5 files changed

+38
-50
lines changed

examples/E2E/e2e/main.e2e.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ describe('#mainTest', () => {
172172

173173
const platform = device.getPlatform();
174174

175-
expect(events).toHaveLength(platform === 'android' ? 4 : 3); // Track + Identify + App Launch (+ Backgrounded on Android)
175+
expect(events).toHaveLength(4); // Track + Identify + App Launch + Backgrounded on Android
176176
expect(events).toHaveEventWith({ type: 'identify', userId: 'user_2' });
177177
expect(events).toHaveEventWith({ type: 'track', userId: 'user_2' });
178178
expect(events).toHaveEventWith({

packages/core/src/__tests__/internal/handleAppStateChange.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ describe('SegmentClient #handleAppStateChange', () => {
163163
// @ts-ignore
164164
expect(client.appState).toBe('background');
165165

166-
expect(mockPlugin.execute).not.toHaveBeenCalled();
166+
expect(mockPlugin.execute).toHaveBeenCalledTimes(1);
167167
});
168168

169169
it('sends an event when unknown => inactive', async () => {
@@ -173,6 +173,6 @@ describe('SegmentClient #handleAppStateChange', () => {
173173
// @ts-ignore
174174
expect(client.appState).toBe('inactive');
175175

176-
expect(mockPlugin.execute).not.toHaveBeenCalled();
176+
expect(mockPlugin.execute).toHaveBeenCalledTimes(1);
177177
});
178178
});

packages/core/src/analytics.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,9 +732,10 @@ export class SegmentClient {
732732
void this.process(event);
733733
this.logger.info('TRACK (Application Opened) event saved', event);
734734
} else if (
735-
this.appState === 'active' &&
735+
(this.appState === 'active' || this.appState === 'unknown') && // Check if appState is 'active' or 'unknown'
736736
['inactive', 'background'].includes(nextAppState)
737737
) {
738+
// Check if next app state is 'inactive' or 'background'
738739
const event = createTrackEvent({
739740
event: 'Application Backgrounded',
740741
});
Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,39 @@
1-
import { AppState, AppStateStatus } from 'react-native';
21
import { BackgroundFlushPolicy } from '../background-flush-policy';
2+
import { FlushPolicyBase } from '../types';
3+
import { createTrackEvent } from '../../events';
34

45
describe('BackgroundFlushPolicy', () => {
5-
it('triggers a flush when reaching limit', () => {
6-
let updateCallback = (_val: AppStateStatus) => {
7-
return;
8-
};
6+
let policy: BackgroundFlushPolicy;
97

10-
const addSpy = jest
11-
.spyOn(AppState, 'addEventListener')
12-
.mockImplementation((_action, callback) => {
13-
updateCallback = callback;
14-
return { remove: jest.fn() };
15-
});
16-
17-
const policy = new BackgroundFlushPolicy();
18-
policy.start();
19-
const observer = jest.fn();
8+
beforeEach(() => {
9+
policy = new BackgroundFlushPolicy();
10+
});
2011

21-
policy.shouldFlush.onChange(observer);
12+
test('should be an instance of FlushPolicyBase', () => {
13+
expect(policy).toBeInstanceOf(FlushPolicyBase);
14+
});
2215

23-
expect(addSpy).toHaveBeenCalledTimes(1);
16+
test('start() should do nothing', () => {
17+
expect(policy.start()).toBeUndefined();
18+
});
2419

25-
updateCallback('background');
26-
expect(observer).toHaveBeenCalledWith(true);
27-
observer.mockClear();
20+
test('end() should do nothing', () => {
21+
expect(policy.end()).toBeUndefined();
22+
});
2823

29-
updateCallback('active');
30-
expect(observer).not.toHaveBeenCalled();
24+
test('onEvent() should set shouldFlush to true for "Application Backgrounded" event', () => {
25+
const event = createTrackEvent({
26+
event: 'Application Backgrounded',
27+
});
28+
policy.onEvent(event);
29+
expect(policy.shouldFlush.value).toBe(true);
30+
});
3131

32-
updateCallback('inactive');
33-
expect(observer).toHaveBeenCalledWith(true);
32+
test('onEvent() should not set shouldFlush for other events', () => {
33+
const event = createTrackEvent({
34+
event: 'Application Opened',
35+
});
36+
policy.onEvent(event);
37+
expect(policy.shouldFlush.value).toBeFalsy();
3438
});
3539
});
Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,21 @@
1-
import {
2-
AppState,
3-
AppStateStatus,
4-
NativeEventSubscription,
5-
} from 'react-native';
61
import type { SegmentEvent } from '../types';
72
import { FlushPolicyBase } from './types';
83

94
/**
105
* StatupFlushPolicy triggers a flush right away on client startup
116
*/
127
export class BackgroundFlushPolicy extends FlushPolicyBase {
13-
private appStateSubscription?: NativeEventSubscription;
14-
private appState: AppStateStatus = AppState.currentState;
15-
168
start() {
17-
this.appStateSubscription = AppState.addEventListener(
18-
'change',
19-
(nextAppState) => {
20-
if (
21-
this.appState === 'active' &&
22-
['inactive', 'background'].includes(nextAppState)
23-
) {
24-
// When the app goes into the background we will trigger a flush
25-
this.shouldFlush.value = true;
26-
}
27-
}
28-
);
9+
// Nothing to do
2910
}
3011

3112
onEvent(_event: SegmentEvent): void {
32-
// Nothing to do
13+
if ('event' in _event && _event.event === 'Application Backgrounded') {
14+
this.shouldFlush.value = true;
15+
}
3316
}
3417

3518
end(): void {
36-
this.appStateSubscription?.remove();
19+
// Nothing to do
3720
}
3821
}

0 commit comments

Comments
 (0)