Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit 9586a7a

Browse files
authored
fix: merge context to preserve plugin injected properties (segmentio#487)
1 parent 686f73f commit 9586a7a

File tree

4 files changed

+50
-4
lines changed

4 files changed

+50
-4
lines changed

example/ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,4 +466,4 @@ SPEC CHECKSUMS:
466466

467467
PODFILE CHECKSUM: 0c7eb82d495ca56953c50916b7b49e7512632eb6
468468

469-
COCOAPODS: 1.11.2
469+
COCOAPODS: 1.11.3

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"dependencies": {
4848
"@react-native-async-storage/async-storage": "^1.15.17",
4949
"@segment/sovran-react-native": "^0.2.6",
50+
"deepmerge": "^4.2.2",
5051
"js-base64": "^3.7.2",
5152
"nanoid": "^3.1.25"
5253
},

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { getMockLogger } from '../__helpers__/mockLogger';
33
import * as context from '../../context';
44
import { MockSegmentStore } from '../__helpers__/mockSegmentStore';
55
import { Context, EventType } from '../../types';
6+
import deepmerge from 'deepmerge';
67

78
jest
89
.spyOn(Date.prototype, 'toISOString')
@@ -161,4 +162,47 @@ describe('internal #checkInstalledVersion', () => {
161162
type: EventType.TrackEvent,
162163
});
163164
});
165+
166+
it('merges context and preserves context injected by plugins during configure', async () => {
167+
const injectedContextByPlugins = {
168+
device: {
169+
adTrackingEnabled: true,
170+
advertisingId: 'mock-advertising-id',
171+
},
172+
};
173+
174+
const store = new MockSegmentStore({
175+
context: {
176+
...currentContext,
177+
...injectedContextByPlugins,
178+
},
179+
});
180+
181+
client = new SegmentClient({
182+
...clientArgs,
183+
store,
184+
});
185+
186+
const newContext = {
187+
...currentContext, // Just adding the full object to prevent TS complaining about missing properties
188+
app: {
189+
version: '1.5',
190+
build: '2',
191+
name: 'Test',
192+
namespace: 'Test',
193+
},
194+
device: {
195+
manufacturer: 'Apple',
196+
model: 'iPhone',
197+
name: 'iPhone',
198+
type: 'iOS',
199+
},
200+
};
201+
jest.spyOn(context, 'getContext').mockResolvedValueOnce(newContext);
202+
await client.init();
203+
204+
expect(store.context.get()).toEqual(
205+
deepmerge(newContext, injectedContextByPlugins)
206+
);
207+
});
164208
});

packages/core/src/analytics.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { AppState, AppStateStatus } from 'react-native';
21
import type { Unsubscribe } from '@segment/sovran-react-native';
2+
import deepmerge from 'deepmerge';
3+
import { AppState, AppStateStatus } from 'react-native';
34
import { getContext } from './context';
4-
55
import {
66
applyRawEventData,
77
createAliasEvent,
@@ -566,7 +566,8 @@ export class SegmentClient {
566566

567567
const previousContext = this.store.context.get();
568568

569-
this.store.context.set(context);
569+
// Only overwrite the previous context values to preserve any values that are added by enrichment plugins like IDFA
570+
this.store.context.set(deepmerge(previousContext ?? {}, context));
570571

571572
if (!this.config.trackAppLifecycleEvents) {
572573
return;

0 commit comments

Comments
 (0)