posthog-node 2.6.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,8 @@ const mockedFetch = jest.mocked(fetch, true)
12
12
  const getLastBatchEvents = (): any[] | undefined => {
13
13
  expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.objectContaining({ method: 'POST' }))
14
14
 
15
- const call = mockedFetch.mock.calls.find((x) => (x[0] as string).includes('/batch/'))
15
+ // reverse mock calls array to get the last call
16
+ const call = mockedFetch.mock.calls.reverse().find((x) => (x[0] as string).includes('/batch/'))
16
17
  if (!call) {
17
18
  return undefined
18
19
  }
@@ -27,6 +28,7 @@ describe('PostHog Node.js', () => {
27
28
  beforeEach(() => {
28
29
  posthog = new PostHog('TEST_API_KEY', {
29
30
  host: 'http://example.com',
31
+ fetchRetryCount: 0,
30
32
  })
31
33
 
32
34
  mockedFetch.mockResolvedValue({
@@ -51,14 +53,21 @@ describe('PostHog Node.js', () => {
51
53
 
52
54
  jest.runOnlyPendingTimers()
53
55
  const batchEvents = getLastBatchEvents()
54
- expect(batchEvents).toMatchObject([
56
+ expect(batchEvents).toEqual([
55
57
  {
56
58
  distinct_id: '123',
57
59
  event: 'test-event',
58
60
  properties: {
59
61
  $groups: { org: 123 },
60
62
  foo: 'bar',
63
+ $geoip_disable: true,
64
+ $lib: 'posthog-node',
65
+ $lib_version: '1.2.3',
61
66
  },
67
+ timestamp: expect.any(String),
68
+ type: 'capture',
69
+ library: 'posthog-node',
70
+ library_version: '1.2.3',
62
71
  },
63
72
  ])
64
73
  })
@@ -97,6 +106,7 @@ describe('PostHog Node.js', () => {
97
106
  properties: expect.objectContaining({
98
107
  $groups: { other_group: 'x' },
99
108
  foo: 'bar',
109
+ $geoip_disable: true,
100
110
  }),
101
111
  library: 'posthog-node',
102
112
  library_version: '1.2.3',
@@ -117,6 +127,7 @@ describe('PostHog Node.js', () => {
117
127
  $set: {
118
128
  foo: 'bar',
119
129
  },
130
+ $geoip_disable: true,
120
131
  },
121
132
  },
122
133
  ])
@@ -135,6 +146,7 @@ describe('PostHog Node.js', () => {
135
146
  $set: {
136
147
  foo: 'other',
137
148
  },
149
+ $geoip_disable: true,
138
150
  },
139
151
  },
140
152
  ])
@@ -152,6 +164,7 @@ describe('PostHog Node.js', () => {
152
164
  properties: {
153
165
  distinct_id: '123',
154
166
  alias: '1234',
167
+ $geoip_disable: true,
155
168
  },
156
169
  },
157
170
  ])
@@ -170,6 +183,83 @@ describe('PostHog Node.js', () => {
170
183
  },
171
184
  ])
172
185
  })
186
+
187
+ it('should respect disableGeoip setting if passed in', async () => {
188
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
189
+ posthog.capture({
190
+ distinctId: '123',
191
+ event: 'test-event',
192
+ properties: { foo: 'bar' },
193
+ groups: { org: 123 },
194
+ disableGeoip: false,
195
+ })
196
+
197
+ jest.runOnlyPendingTimers()
198
+ const batchEvents = getLastBatchEvents()
199
+ expect(batchEvents?.[0].properties).toEqual({
200
+ $groups: { org: 123 },
201
+ foo: 'bar',
202
+ $lib: 'posthog-node',
203
+ $lib_version: '1.2.3',
204
+ })
205
+ })
206
+
207
+ it('should use default is set, and override on specific disableGeoip calls', async () => {
208
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
209
+ const client = new PostHog('TEST_API_KEY', {
210
+ host: 'http://example.com',
211
+ disableGeoip: false,
212
+ })
213
+ client.debug()
214
+ client.capture({ distinctId: '123', event: 'test-event', properties: { foo: 'bar' }, groups: { org: 123 } })
215
+
216
+ jest.runOnlyPendingTimers()
217
+ let batchEvents = getLastBatchEvents()
218
+ expect(batchEvents?.[0].properties).toEqual({
219
+ $groups: { org: 123 },
220
+ foo: 'bar',
221
+ $lib: 'posthog-node',
222
+ $lib_version: '1.2.3',
223
+ })
224
+
225
+ client.capture({
226
+ distinctId: '123',
227
+ event: 'test-event',
228
+ properties: { foo: 'bar' },
229
+ groups: { org: 123 },
230
+ disableGeoip: true,
231
+ })
232
+
233
+ jest.runOnlyPendingTimers()
234
+ batchEvents = getLastBatchEvents()
235
+ console.warn(batchEvents)
236
+ expect(batchEvents?.[0].properties).toEqual({
237
+ $groups: { org: 123 },
238
+ foo: 'bar',
239
+ $lib: 'posthog-node',
240
+ $lib_version: '1.2.3',
241
+ $geoip_disable: true,
242
+ })
243
+
244
+ client.capture({
245
+ distinctId: '123',
246
+ event: 'test-event',
247
+ properties: { foo: 'bar' },
248
+ groups: { org: 123 },
249
+ disableGeoip: false,
250
+ })
251
+
252
+ jest.runOnlyPendingTimers()
253
+ batchEvents = getLastBatchEvents()
254
+ expect(batchEvents?.[0].properties).toEqual({
255
+ $groups: { org: 123 },
256
+ foo: 'bar',
257
+ $lib: 'posthog-node',
258
+ $lib_version: '1.2.3',
259
+ })
260
+
261
+ await client.shutdownAsync()
262
+ })
173
263
  })
174
264
 
175
265
  describe('shutdown', () => {
@@ -177,8 +267,7 @@ describe('PostHog Node.js', () => {
177
267
  // a serverless posthog configuration
178
268
  posthog = new PostHog('TEST_API_KEY', {
179
269
  host: 'http://example.com',
180
- flushAt: 1,
181
- flushInterval: 0,
270
+ fetchRetryCount: 0,
182
271
  })
183
272
 
184
273
  mockedFetch.mockImplementation(async () => {
@@ -201,6 +290,12 @@ describe('PostHog Node.js', () => {
201
290
  })
202
291
 
203
292
  it('should shutdown cleanly', async () => {
293
+ posthog = new PostHog('TEST_API_KEY', {
294
+ host: 'http://example.com',
295
+ fetchRetryCount: 0,
296
+ flushAt: 1,
297
+ })
298
+
204
299
  const logSpy = jest.spyOn(global.console, 'log')
205
300
  jest.useRealTimers()
206
301
  // using debug mode to check console.log output
@@ -230,9 +325,10 @@ describe('PostHog Node.js', () => {
230
325
  })
231
326
 
232
327
  describe('groupIdentify', () => {
233
- it('should identify group with unique id', () => {
328
+ it('should identify group with unique id', async () => {
234
329
  posthog.groupIdentify({ groupType: 'posthog', groupKey: 'team-1', properties: { analytics: true } })
235
330
  jest.runOnlyPendingTimers()
331
+ await posthog.flushAsync()
236
332
  const batchEvents = getLastBatchEvents()
237
333
  expect(batchEvents).toMatchObject([
238
334
  {
@@ -243,12 +339,13 @@ describe('PostHog Node.js', () => {
243
339
  $group_key: 'team-1',
244
340
  $group_set: { analytics: true },
245
341
  $lib: 'posthog-node',
342
+ $geoip_disable: true,
246
343
  },
247
344
  },
248
345
  ])
249
346
  })
250
347
 
251
- it('should allow passing optional distinctID to identify group', () => {
348
+ it('should allow passing optional distinctID to identify group', async () => {
252
349
  posthog.groupIdentify({
253
350
  groupType: 'posthog',
254
351
  groupKey: 'team-1',
@@ -256,6 +353,7 @@ describe('PostHog Node.js', () => {
256
353
  distinctId: '123',
257
354
  })
258
355
  jest.runOnlyPendingTimers()
356
+ await posthog.flushAsync()
259
357
  const batchEvents = getLastBatchEvents()
260
358
  expect(batchEvents).toMatchObject([
261
359
  {
@@ -266,6 +364,7 @@ describe('PostHog Node.js', () => {
266
364
  $group_key: 'team-1',
267
365
  $group_set: { analytics: true },
268
366
  $lib: 'posthog-node',
367
+ $geoip_disable: true,
269
368
  },
270
369
  },
271
370
  ])
@@ -292,7 +391,7 @@ describe('PostHog Node.js', () => {
292
391
 
293
392
  posthog = new PostHog('TEST_API_KEY', {
294
393
  host: 'http://example.com',
295
- // flushAt: 1,
394
+ fetchRetryCount: 0,
296
395
  })
297
396
  })
298
397
 
@@ -302,6 +401,10 @@ describe('PostHog Node.js', () => {
302
401
  'variant'
303
402
  )
304
403
  expect(mockedFetch).toHaveBeenCalledTimes(1)
404
+ expect(mockedFetch).toHaveBeenCalledWith(
405
+ 'http://example.com/decide/?v=3',
406
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
407
+ )
305
408
  })
306
409
 
307
410
  it('should do isFeatureEnabled', async () => {
@@ -319,6 +422,7 @@ describe('PostHog Node.js', () => {
319
422
  posthog = new PostHog('TEST_API_KEY', {
320
423
  host: 'http://example.com',
321
424
  flushAt: 1,
425
+ fetchRetryCount: 0,
322
426
  })
323
427
 
324
428
  posthog.capture({
@@ -347,12 +451,58 @@ describe('PostHog Node.js', () => {
347
451
  '$feature/feature-variant': 'variant',
348
452
  $lib: 'posthog-node',
349
453
  $lib_version: '1.2.3',
454
+ $geoip_disable: true,
350
455
  }),
351
456
  })
352
457
  )
353
458
 
354
459
  // no calls to `/local_evaluation`
355
460
 
461
+ expect(mockedFetch).not.toHaveBeenCalledWith(...anyLocalEvalCall)
462
+ expect(mockedFetch).toHaveBeenCalledWith(
463
+ 'http://example.com/decide/?v=3',
464
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
465
+ )
466
+ })
467
+
468
+ it('captures feature flags with same geoip setting as capture', async () => {
469
+ mockedFetch.mockClear()
470
+ mockedFetch.mockClear()
471
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
472
+
473
+ posthog = new PostHog('TEST_API_KEY', {
474
+ host: 'http://example.com',
475
+ flushAt: 1,
476
+ fetchRetryCount: 0,
477
+ })
478
+
479
+ posthog.capture({
480
+ distinctId: 'distinct_id',
481
+ event: 'node test event',
482
+ sendFeatureFlags: true,
483
+ disableGeoip: false,
484
+ })
485
+
486
+ expect(mockedFetch).toHaveBeenCalledWith(
487
+ 'http://example.com/decide/?v=3',
488
+ expect.objectContaining({ method: 'POST', body: expect.not.stringContaining('geoip_disable') })
489
+ )
490
+
491
+ jest.runOnlyPendingTimers()
492
+
493
+ await waitForPromises()
494
+
495
+ expect(getLastBatchEvents()?.[0].properties).toEqual({
496
+ $active_feature_flags: ['feature-1', 'feature-2', 'feature-variant'],
497
+ '$feature/feature-1': true,
498
+ '$feature/feature-2': true,
499
+ '$feature/feature-variant': 'variant',
500
+ $lib: 'posthog-node',
501
+ $lib_version: '1.2.3',
502
+ })
503
+
504
+ // no calls to `/local_evaluation`
505
+
356
506
  expect(mockedFetch).not.toHaveBeenCalledWith(...anyLocalEvalCall)
357
507
  })
358
508
 
@@ -384,6 +534,7 @@ describe('PostHog Node.js', () => {
384
534
  host: 'http://example.com',
385
535
  personalApiKey: 'TEST_PERSONAL_API_KEY',
386
536
  maxCacheSize: 10,
537
+ fetchRetryCount: 0,
387
538
  })
388
539
 
389
540
  expect(Object.keys(posthog.distinctIdHasSentFlagCalls).length).toEqual(0)
@@ -442,6 +593,7 @@ describe('PostHog Node.js', () => {
442
593
  host: 'http://example.com',
443
594
  personalApiKey: 'TEST_PERSONAL_API_KEY',
444
595
  maxCacheSize: 10,
596
+ fetchRetryCount: 0,
445
597
  })
446
598
 
447
599
  expect(
@@ -462,6 +614,7 @@ describe('PostHog Node.js', () => {
462
614
  $lib: 'posthog-node',
463
615
  $lib_version: '1.2.3',
464
616
  locally_evaluated: true,
617
+ $geoip_disable: true,
465
618
  }),
466
619
  })
467
620
  )
@@ -482,6 +635,7 @@ describe('PostHog Node.js', () => {
482
635
  await posthog.getFeatureFlag('beta-feature', 'some-distinct-id2', {
483
636
  groups: { x: 'y' },
484
637
  personProperties: { region: 'USA', name: 'Aloha' },
638
+ disableGeoip: false,
485
639
  })
486
640
  ).toEqual(true)
487
641
  jest.runOnlyPendingTimers()
@@ -491,16 +645,16 @@ describe('PostHog Node.js', () => {
491
645
  expect.objectContaining({
492
646
  distinct_id: 'some-distinct-id2',
493
647
  event: '$feature_flag_called',
494
- properties: expect.objectContaining({
495
- $feature_flag: 'beta-feature',
496
- $feature_flag_response: true,
497
- $lib: 'posthog-node',
498
- $lib_version: '1.2.3',
499
- locally_evaluated: true,
500
- $groups: { x: 'y' },
501
- }),
502
648
  })
503
649
  )
650
+ expect(getLastBatchEvents()?.[0].properties).toEqual({
651
+ $feature_flag: 'beta-feature',
652
+ $feature_flag_response: true,
653
+ $lib: 'posthog-node',
654
+ $lib_version: '1.2.3',
655
+ locally_evaluated: true,
656
+ $groups: { x: 'y' },
657
+ })
504
658
  mockedFetch.mockClear()
505
659
 
506
660
  // # called for different user, but send configuration is false, so should NOT call capture again
@@ -559,6 +713,10 @@ describe('PostHog Node.js', () => {
559
713
  posthog.getFeatureFlagPayload('feature-variant', '123', 'variant', { groups: { org: '123' } })
560
714
  ).resolves.toEqual(2)
561
715
  expect(mockedFetch).toHaveBeenCalledTimes(1)
716
+ expect(mockedFetch).toHaveBeenCalledWith(
717
+ 'http://example.com/decide/?v=3',
718
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
719
+ )
562
720
  })
563
721
 
564
722
  it('should do getFeatureFlagPayloads without matchValue', async () => {
@@ -568,5 +726,26 @@ describe('PostHog Node.js', () => {
568
726
  ).resolves.toEqual(2)
569
727
  expect(mockedFetch).toHaveBeenCalledTimes(1)
570
728
  })
729
+
730
+ it('should do getFeatureFlags with geoip disabled and enabled', async () => {
731
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
732
+ await expect(
733
+ posthog.getFeatureFlagPayload('feature-variant', '123', 'variant', { groups: { org: '123' } })
734
+ ).resolves.toEqual(2)
735
+ expect(mockedFetch).toHaveBeenCalledTimes(1)
736
+ expect(mockedFetch).toHaveBeenCalledWith(
737
+ 'http://example.com/decide/?v=3',
738
+ expect.objectContaining({ method: 'POST', body: expect.stringContaining('"geoip_disable":true') })
739
+ )
740
+
741
+ mockedFetch.mockClear()
742
+
743
+ await expect(posthog.isFeatureEnabled('feature-variant', '123', { disableGeoip: false })).resolves.toEqual(true)
744
+ expect(mockedFetch).toHaveBeenCalledTimes(1)
745
+ expect(mockedFetch).toHaveBeenCalledWith(
746
+ 'http://example.com/decide/?v=3',
747
+ expect.objectContaining({ method: 'POST', body: expect.not.stringContaining('geoip_disable') })
748
+ )
749
+ })
571
750
  })
572
751
  })