posthog-node 2.0.2 → 2.2.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.
@@ -1,21 +1,18 @@
1
1
  // import { PostHog } from '../'
2
2
  import { PostHog as PostHog } from '../src/posthog-node'
3
- jest.mock('undici')
4
- import undici from 'undici'
5
- import { decideImplementation, localEvaluationImplementation } from './feature-flags.spec'
3
+ jest.mock('../src/fetch')
4
+ import { fetch } from '../src/fetch'
5
+ import { anyDecideCall, anyLocalEvalCall, apiImplementation } from './feature-flags.spec'
6
6
  import { waitForPromises } from '../../posthog-core/test/test-utils/test-utils'
7
7
 
8
8
  jest.mock('../package.json', () => ({ version: '1.2.3' }))
9
9
 
10
- const mockedUndici = jest.mocked(undici, true)
10
+ const mockedFetch = jest.mocked(fetch, true)
11
11
 
12
12
  const getLastBatchEvents = (): any[] | undefined => {
13
- expect(mockedUndici.fetch).toHaveBeenCalledWith(
14
- 'http://example.com/batch/',
15
- expect.objectContaining({ method: 'POST' })
16
- )
13
+ expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.objectContaining({ method: 'POST' }))
17
14
 
18
- const call = mockedUndici.fetch.mock.calls.find((x) => (x[0] as string).includes('/batch/'))
15
+ const call = mockedFetch.mock.calls.find((x) => (x[0] as string).includes('/batch/'))
19
16
  if (!call) {
20
17
  return undefined
21
18
  }
@@ -32,7 +29,7 @@ describe('PostHog Node.js', () => {
32
29
  host: 'http://example.com',
33
30
  })
34
31
 
35
- mockedUndici.fetch.mockResolvedValue({
32
+ mockedFetch.mockResolvedValue({
36
33
  status: 200,
37
34
  text: () => Promise.resolve('ok'),
38
35
  json: () =>
@@ -49,7 +46,7 @@ describe('PostHog Node.js', () => {
49
46
 
50
47
  describe('core methods', () => {
51
48
  it('should capture an event to shared queue', async () => {
52
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(0)
49
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
53
50
  posthog.capture({ distinctId: '123', event: 'test-event', properties: { foo: 'bar' }, groups: { org: 123 } })
54
51
 
55
52
  jest.runOnlyPendingTimers()
@@ -67,7 +64,7 @@ describe('PostHog Node.js', () => {
67
64
  })
68
65
 
69
66
  it('shouldnt muddy subsequent capture calls', async () => {
70
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(0)
67
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
71
68
  posthog.capture({ distinctId: '123', event: 'test-event', properties: { foo: 'bar' }, groups: { org: 123 } })
72
69
 
73
70
  jest.runOnlyPendingTimers()
@@ -83,7 +80,7 @@ describe('PostHog Node.js', () => {
83
80
  library_version: '1.2.3',
84
81
  })
85
82
  )
86
- mockedUndici.fetch.mockClear()
83
+ mockedFetch.mockClear()
87
84
 
88
85
  posthog.capture({
89
86
  distinctId: '123',
@@ -108,7 +105,7 @@ describe('PostHog Node.js', () => {
108
105
  })
109
106
 
110
107
  it('should capture identify events on shared queue', async () => {
111
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(0)
108
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
112
109
  posthog.identify({ distinctId: '123', properties: { foo: 'bar' } })
113
110
  jest.runOnlyPendingTimers()
114
111
  const batchEvents = getLastBatchEvents()
@@ -124,7 +121,7 @@ describe('PostHog Node.js', () => {
124
121
  })
125
122
 
126
123
  it('should capture alias events on shared queue', async () => {
127
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(0)
124
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
128
125
  posthog.alias({ distinctId: '123', alias: '1234' })
129
126
  jest.runOnlyPendingTimers()
130
127
  const batchEvents = getLastBatchEvents()
@@ -149,7 +146,7 @@ describe('PostHog Node.js', () => {
149
146
  'feature-variant': 'variant',
150
147
  }
151
148
 
152
- mockedUndici.fetch.mockImplementation(decideImplementation(mockFeatureFlags))
149
+ mockedFetch.mockImplementation(apiImplementation({ decideFlags: mockFeatureFlags }))
153
150
 
154
151
  posthog = new PostHog('TEST_API_KEY', {
155
152
  host: 'http://example.com',
@@ -158,24 +155,24 @@ describe('PostHog Node.js', () => {
158
155
  })
159
156
 
160
157
  it('should do getFeatureFlag', async () => {
161
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(0)
158
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
162
159
  await expect(posthog.getFeatureFlag('feature-variant', '123', { groups: { org: '123' } })).resolves.toEqual(
163
160
  'variant'
164
161
  )
165
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(1)
162
+ expect(mockedFetch).toHaveBeenCalledTimes(1)
166
163
  })
167
164
 
168
165
  it('should do isFeatureEnabled', async () => {
169
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(0)
166
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
170
167
  await expect(posthog.isFeatureEnabled('feature-1', '123', { groups: { org: '123' } })).resolves.toEqual(true)
171
168
  await expect(posthog.isFeatureEnabled('feature-4', '123', { groups: { org: '123' } })).resolves.toEqual(false)
172
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(2)
169
+ expect(mockedFetch).toHaveBeenCalledTimes(2)
173
170
  })
174
171
 
175
172
  it('captures feature flags when no personal API key is present', async () => {
176
- mockedUndici.fetch.mockClear()
177
- mockedUndici.request.mockClear()
178
- expect(mockedUndici.fetch).toHaveBeenCalledTimes(0)
173
+ mockedFetch.mockClear()
174
+ mockedFetch.mockClear()
175
+ expect(mockedFetch).toHaveBeenCalledTimes(0)
179
176
 
180
177
  posthog = new PostHog('TEST_API_KEY', {
181
178
  host: 'http://example.com',
@@ -188,7 +185,7 @@ describe('PostHog Node.js', () => {
188
185
  sendFeatureFlags: true,
189
186
  })
190
187
 
191
- expect(mockedUndici.fetch).toHaveBeenCalledWith(
188
+ expect(mockedFetch).toHaveBeenCalledWith(
192
189
  'http://example.com/decide/?v=2',
193
190
  expect.objectContaining({ method: 'POST' })
194
191
  )
@@ -213,7 +210,8 @@ describe('PostHog Node.js', () => {
213
210
  )
214
211
 
215
212
  // no calls to `/local_evaluation`
216
- expect(mockedUndici.request).not.toHaveBeenCalled()
213
+
214
+ expect(mockedFetch).not.toHaveBeenCalledWith(...anyLocalEvalCall)
217
215
  })
218
216
 
219
217
  it('manages memory well when sending feature flags', async () => {
@@ -235,9 +233,10 @@ describe('PostHog Node.js', () => {
235
233
  },
236
234
  ],
237
235
  }
238
- mockedUndici.request.mockImplementation(localEvaluationImplementation(flags))
239
236
 
240
- mockedUndici.fetch.mockImplementation(decideImplementation({ 'beta-feature': 'decide-fallback-value' }))
237
+ mockedFetch.mockImplementation(
238
+ apiImplementation({ localFlags: flags, decideFlags: { 'beta-feature': 'decide-fallback-value' } })
239
+ )
241
240
 
242
241
  posthog = new PostHog('TEST_API_KEY', {
243
242
  host: 'http://example.com',
@@ -267,7 +266,7 @@ describe('PostHog Node.js', () => {
267
266
  }),
268
267
  },
269
268
  ])
270
- mockedUndici.fetch.mockClear()
269
+ mockedFetch.mockClear()
271
270
 
272
271
  expect(Object.keys(posthog.distinctIdHasSentFlagCalls).length <= 10).toEqual(true)
273
272
  }
@@ -292,9 +291,10 @@ describe('PostHog Node.js', () => {
292
291
  },
293
292
  ],
294
293
  }
295
- mockedUndici.request.mockImplementation(localEvaluationImplementation(flags))
296
294
 
297
- mockedUndici.fetch.mockImplementation(decideImplementation({ 'decide-flag': 'decide-value' }))
295
+ mockedFetch.mockImplementation(
296
+ apiImplementation({ localFlags: flags, decideFlags: { 'decide-flag': 'decide-value' } })
297
+ )
298
298
 
299
299
  posthog = new PostHog('TEST_API_KEY', {
300
300
  host: 'http://example.com',
@@ -308,7 +308,7 @@ describe('PostHog Node.js', () => {
308
308
  })
309
309
  ).toEqual(true)
310
310
  jest.runOnlyPendingTimers()
311
- expect(mockedUndici.fetch.mock.calls.length).toEqual(1)
311
+ expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
312
312
 
313
313
  expect(getLastBatchEvents()?.[0]).toEqual(
314
314
  expect.objectContaining({
@@ -323,7 +323,7 @@ describe('PostHog Node.js', () => {
323
323
  }),
324
324
  })
325
325
  )
326
- mockedUndici.fetch.mockClear()
326
+ mockedFetch.mockClear()
327
327
 
328
328
  // # called again for same user, shouldn't call capture again
329
329
  expect(
@@ -333,7 +333,7 @@ describe('PostHog Node.js', () => {
333
333
  ).toEqual(true)
334
334
  jest.runOnlyPendingTimers()
335
335
 
336
- expect(mockedUndici.fetch).not.toBeCalled()
336
+ expect(mockedFetch).not.toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
337
337
 
338
338
  // # called for different user, should call capture again
339
339
  expect(
@@ -343,7 +343,7 @@ describe('PostHog Node.js', () => {
343
343
  })
344
344
  ).toEqual(true)
345
345
  jest.runOnlyPendingTimers()
346
- expect(mockedUndici.fetch.mock.calls.length).toEqual(1)
346
+ expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
347
347
 
348
348
  expect(getLastBatchEvents()?.[0]).toEqual(
349
349
  expect.objectContaining({
@@ -359,7 +359,7 @@ describe('PostHog Node.js', () => {
359
359
  }),
360
360
  })
361
361
  )
362
- mockedUndici.fetch.mockClear()
362
+ mockedFetch.mockClear()
363
363
 
364
364
  // # called for different user, but send configuration is false, so should NOT call capture again
365
365
  expect(
@@ -369,7 +369,7 @@ describe('PostHog Node.js', () => {
369
369
  })
370
370
  ).toEqual(true)
371
371
  jest.runOnlyPendingTimers()
372
- expect(mockedUndici.fetch).not.toBeCalled()
372
+ expect(mockedFetch).not.toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
373
373
 
374
374
  // # called for different flag, falls back to decide, should call capture again
375
375
  expect(
@@ -380,7 +380,8 @@ describe('PostHog Node.js', () => {
380
380
  ).toEqual('decide-value')
381
381
  jest.runOnlyPendingTimers()
382
382
  // one to decide, one to batch
383
- expect(mockedUndici.fetch.mock.calls.length).toEqual(2)
383
+ expect(mockedFetch).toHaveBeenCalledWith(...anyDecideCall)
384
+ expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
384
385
 
385
386
  expect(getLastBatchEvents()?.[0]).toEqual(
386
387
  expect.objectContaining({
@@ -396,7 +397,7 @@ describe('PostHog Node.js', () => {
396
397
  }),
397
398
  })
398
399
  )
399
- mockedUndici.fetch.mockClear()
400
+ mockedFetch.mockClear()
400
401
 
401
402
  expect(
402
403
  await posthog.isFeatureEnabled('decide-flag', 'some-distinct-id2345', {
@@ -406,8 +407,8 @@ describe('PostHog Node.js', () => {
406
407
  ).toEqual(true)
407
408
  jest.runOnlyPendingTimers()
408
409
  // call decide, but not batch
409
- expect(mockedUndici.fetch).toBeCalledTimes(1)
410
- expect(mockedUndici.fetch.mock.calls.find((x) => (x[0] as string).includes('/batch/'))).toEqual(undefined)
410
+ expect(mockedFetch).toHaveBeenCalledWith(...anyDecideCall)
411
+ expect(mockedFetch).not.toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
411
412
  })
412
413
  })
413
414
  })