posthog-node 3.4.0 → 3.5.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.
- package/CHANGELOG.md +5 -0
- package/lib/index.cjs.js +182 -72
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.esm.js +182 -72
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +2 -1
- package/lib/posthog-node/src/posthog-node.d.ts +1 -0
- package/package.json +1 -1
- package/src/feature-flags.ts +10 -6
- package/src/posthog-node.ts +99 -19
- package/test/extensions/sentry-integration.spec.ts +2 -0
- package/test/feature-flags.spec.ts +17 -2
- package/test/posthog-node.spec.ts +407 -10
|
@@ -51,7 +51,9 @@ describe('PostHog Node.js', () => {
|
|
|
51
51
|
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
52
52
|
posthog.capture({ distinctId: '123', event: 'test-event', properties: { foo: 'bar' }, groups: { org: 123 } })
|
|
53
53
|
|
|
54
|
+
await waitForPromises()
|
|
54
55
|
jest.runOnlyPendingTimers()
|
|
56
|
+
|
|
55
57
|
const batchEvents = getLastBatchEvents()
|
|
56
58
|
expect(batchEvents).toEqual([
|
|
57
59
|
{
|
|
@@ -76,6 +78,7 @@ describe('PostHog Node.js', () => {
|
|
|
76
78
|
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
77
79
|
posthog.capture({ distinctId: '123', event: 'test-event', properties: { foo: 'bar' }, groups: { org: 123 } })
|
|
78
80
|
|
|
81
|
+
await waitForPromises()
|
|
79
82
|
jest.runOnlyPendingTimers()
|
|
80
83
|
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
81
84
|
expect.objectContaining({
|
|
@@ -98,6 +101,7 @@ describe('PostHog Node.js', () => {
|
|
|
98
101
|
groups: { other_group: 'x' },
|
|
99
102
|
})
|
|
100
103
|
|
|
104
|
+
await waitForPromises()
|
|
101
105
|
jest.runOnlyPendingTimers()
|
|
102
106
|
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
103
107
|
expect.objectContaining({
|
|
@@ -173,6 +177,7 @@ describe('PostHog Node.js', () => {
|
|
|
173
177
|
it('should allow overriding timestamp', async () => {
|
|
174
178
|
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
175
179
|
posthog.capture({ event: 'custom-time', distinctId: '123', timestamp: new Date('2021-02-03') })
|
|
180
|
+
await waitForPromises()
|
|
176
181
|
jest.runOnlyPendingTimers()
|
|
177
182
|
const batchEvents = getLastBatchEvents()
|
|
178
183
|
expect(batchEvents).toMatchObject([
|
|
@@ -194,6 +199,7 @@ describe('PostHog Node.js', () => {
|
|
|
194
199
|
disableGeoip: false,
|
|
195
200
|
})
|
|
196
201
|
|
|
202
|
+
await waitForPromises()
|
|
197
203
|
jest.runOnlyPendingTimers()
|
|
198
204
|
const batchEvents = getLastBatchEvents()
|
|
199
205
|
expect(batchEvents?.[0].properties).toEqual({
|
|
@@ -212,7 +218,9 @@ describe('PostHog Node.js', () => {
|
|
|
212
218
|
})
|
|
213
219
|
client.capture({ distinctId: '123', event: 'test-event', properties: { foo: 'bar' }, groups: { org: 123 } })
|
|
214
220
|
|
|
221
|
+
await waitForPromises()
|
|
215
222
|
jest.runOnlyPendingTimers()
|
|
223
|
+
|
|
216
224
|
let batchEvents = getLastBatchEvents()
|
|
217
225
|
expect(batchEvents?.[0].properties).toEqual({
|
|
218
226
|
$groups: { org: 123 },
|
|
@@ -229,6 +237,7 @@ describe('PostHog Node.js', () => {
|
|
|
229
237
|
disableGeoip: true,
|
|
230
238
|
})
|
|
231
239
|
|
|
240
|
+
await waitForPromises()
|
|
232
241
|
jest.runOnlyPendingTimers()
|
|
233
242
|
batchEvents = getLastBatchEvents()
|
|
234
243
|
console.warn(batchEvents)
|
|
@@ -248,6 +257,7 @@ describe('PostHog Node.js', () => {
|
|
|
248
257
|
disableGeoip: false,
|
|
249
258
|
})
|
|
250
259
|
|
|
260
|
+
await waitForPromises()
|
|
251
261
|
jest.runOnlyPendingTimers()
|
|
252
262
|
batchEvents = getLastBatchEvents()
|
|
253
263
|
expect(batchEvents?.[0].properties).toEqual({
|
|
@@ -286,6 +296,7 @@ describe('PostHog Node.js', () => {
|
|
|
286
296
|
|
|
287
297
|
afterEach(() => {
|
|
288
298
|
posthog.debug(false)
|
|
299
|
+
jest.useFakeTimers()
|
|
289
300
|
})
|
|
290
301
|
|
|
291
302
|
it('should shutdown cleanly', async () => {
|
|
@@ -321,6 +332,45 @@ describe('PostHog Node.js', () => {
|
|
|
321
332
|
jest.useFakeTimers()
|
|
322
333
|
logSpy.mockRestore()
|
|
323
334
|
})
|
|
335
|
+
|
|
336
|
+
it('should shutdown cleanly with pending capture flag promises', async () => {
|
|
337
|
+
posthog = new PostHog('TEST_API_KEY', {
|
|
338
|
+
host: 'http://example.com',
|
|
339
|
+
fetchRetryCount: 0,
|
|
340
|
+
flushAt: 4,
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
const logSpy = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
344
|
+
jest.useRealTimers()
|
|
345
|
+
posthog.debug(true)
|
|
346
|
+
|
|
347
|
+
for (let i = 0; i < 10; i++) {
|
|
348
|
+
posthog.capture({ event: 'test-event', distinctId: `${i}`, sendFeatureFlags: true })
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
await posthog.shutdownAsync()
|
|
352
|
+
// all capture calls happen during shutdown
|
|
353
|
+
const batchEvents = getLastBatchEvents()
|
|
354
|
+
expect(batchEvents?.length).toEqual(2)
|
|
355
|
+
expect(batchEvents?.[batchEvents?.length - 1]).toMatchObject({
|
|
356
|
+
// last event in batch
|
|
357
|
+
distinct_id: '9',
|
|
358
|
+
event: 'test-event',
|
|
359
|
+
library: 'posthog-node',
|
|
360
|
+
library_version: '1.2.3',
|
|
361
|
+
properties: {
|
|
362
|
+
$lib: 'posthog-node',
|
|
363
|
+
$lib_version: '1.2.3',
|
|
364
|
+
$geoip_disable: true,
|
|
365
|
+
},
|
|
366
|
+
timestamp: expect.any(String),
|
|
367
|
+
type: 'capture',
|
|
368
|
+
})
|
|
369
|
+
expect(10).toEqual(logSpy.mock.calls.filter((call) => call[1].includes('capture')).length)
|
|
370
|
+
expect(3).toEqual(logSpy.mock.calls.filter((call) => call[1].includes('flush')).length)
|
|
371
|
+
jest.useFakeTimers()
|
|
372
|
+
logSpy.mockRestore()
|
|
373
|
+
})
|
|
324
374
|
})
|
|
325
375
|
|
|
326
376
|
describe('groupIdentify', () => {
|
|
@@ -384,8 +434,79 @@ describe('PostHog Node.js', () => {
|
|
|
384
434
|
'feature-variant': 2,
|
|
385
435
|
}
|
|
386
436
|
|
|
437
|
+
const multivariateFlag = {
|
|
438
|
+
id: 1,
|
|
439
|
+
name: 'Beta Feature',
|
|
440
|
+
key: 'beta-feature-local',
|
|
441
|
+
is_simple_flag: false,
|
|
442
|
+
active: true,
|
|
443
|
+
rollout_percentage: 100,
|
|
444
|
+
filters: {
|
|
445
|
+
groups: [
|
|
446
|
+
{
|
|
447
|
+
properties: [{ key: 'email', type: 'person', value: 'test@posthog.com', operator: 'exact' }],
|
|
448
|
+
rollout_percentage: 100,
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
rollout_percentage: 50,
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
multivariate: {
|
|
455
|
+
variants: [
|
|
456
|
+
{ key: 'first-variant', name: 'First Variant', rollout_percentage: 50 },
|
|
457
|
+
{ key: 'second-variant', name: 'Second Variant', rollout_percentage: 25 },
|
|
458
|
+
{ key: 'third-variant', name: 'Third Variant', rollout_percentage: 25 },
|
|
459
|
+
],
|
|
460
|
+
},
|
|
461
|
+
payloads: { 'first-variant': 'some-payload', 'third-variant': { a: 'json' } },
|
|
462
|
+
},
|
|
463
|
+
}
|
|
464
|
+
const basicFlag = {
|
|
465
|
+
id: 1,
|
|
466
|
+
name: 'Beta Feature',
|
|
467
|
+
key: 'person-flag',
|
|
468
|
+
is_simple_flag: true,
|
|
469
|
+
active: true,
|
|
470
|
+
filters: {
|
|
471
|
+
groups: [
|
|
472
|
+
{
|
|
473
|
+
properties: [
|
|
474
|
+
{
|
|
475
|
+
key: 'region',
|
|
476
|
+
operator: 'exact',
|
|
477
|
+
value: ['USA'],
|
|
478
|
+
type: 'person',
|
|
479
|
+
},
|
|
480
|
+
],
|
|
481
|
+
rollout_percentage: 100,
|
|
482
|
+
},
|
|
483
|
+
],
|
|
484
|
+
payloads: { true: 300 },
|
|
485
|
+
},
|
|
486
|
+
}
|
|
487
|
+
const falseFlag = {
|
|
488
|
+
id: 1,
|
|
489
|
+
name: 'Beta Feature',
|
|
490
|
+
key: 'false-flag',
|
|
491
|
+
is_simple_flag: true,
|
|
492
|
+
active: true,
|
|
493
|
+
filters: {
|
|
494
|
+
groups: [
|
|
495
|
+
{
|
|
496
|
+
properties: [],
|
|
497
|
+
rollout_percentage: 0,
|
|
498
|
+
},
|
|
499
|
+
],
|
|
500
|
+
payloads: { true: 300 },
|
|
501
|
+
},
|
|
502
|
+
}
|
|
503
|
+
|
|
387
504
|
mockedFetch.mockImplementation(
|
|
388
|
-
apiImplementation({
|
|
505
|
+
apiImplementation({
|
|
506
|
+
decideFlags: mockFeatureFlags,
|
|
507
|
+
decideFlagPayloads: mockFeatureFlagPayloads,
|
|
508
|
+
localFlags: { flags: [multivariateFlag, basicFlag, falseFlag] },
|
|
509
|
+
})
|
|
389
510
|
)
|
|
390
511
|
|
|
391
512
|
posthog = new PostHog('TEST_API_KEY', {
|
|
@@ -430,15 +551,14 @@ describe('PostHog Node.js', () => {
|
|
|
430
551
|
sendFeatureFlags: true,
|
|
431
552
|
})
|
|
432
553
|
|
|
554
|
+
jest.runOnlyPendingTimers()
|
|
555
|
+
await waitForPromises()
|
|
556
|
+
|
|
433
557
|
expect(mockedFetch).toHaveBeenCalledWith(
|
|
434
558
|
'http://example.com/decide/?v=3',
|
|
435
559
|
expect.objectContaining({ method: 'POST' })
|
|
436
560
|
)
|
|
437
561
|
|
|
438
|
-
jest.runOnlyPendingTimers()
|
|
439
|
-
|
|
440
|
-
await waitForPromises()
|
|
441
|
-
|
|
442
562
|
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
443
563
|
expect.objectContaining({
|
|
444
564
|
distinct_id: 'distinct_id',
|
|
@@ -464,6 +584,113 @@ describe('PostHog Node.js', () => {
|
|
|
464
584
|
)
|
|
465
585
|
})
|
|
466
586
|
|
|
587
|
+
it('captures feature flags with locally evaluated flags', async () => {
|
|
588
|
+
mockedFetch.mockClear()
|
|
589
|
+
mockedFetch.mockClear()
|
|
590
|
+
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
591
|
+
|
|
592
|
+
posthog = new PostHog('TEST_API_KEY', {
|
|
593
|
+
host: 'http://example.com',
|
|
594
|
+
flushAt: 1,
|
|
595
|
+
fetchRetryCount: 0,
|
|
596
|
+
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
jest.runOnlyPendingTimers()
|
|
600
|
+
await waitForPromises()
|
|
601
|
+
|
|
602
|
+
posthog.capture({
|
|
603
|
+
distinctId: 'distinct_id',
|
|
604
|
+
event: 'node test event',
|
|
605
|
+
})
|
|
606
|
+
|
|
607
|
+
expect(mockedFetch).toHaveBeenCalledWith(...anyLocalEvalCall)
|
|
608
|
+
// no decide call
|
|
609
|
+
expect(mockedFetch).not.toHaveBeenCalledWith(
|
|
610
|
+
'http://example.com/decide/?v=3',
|
|
611
|
+
expect.objectContaining({ method: 'POST' })
|
|
612
|
+
)
|
|
613
|
+
|
|
614
|
+
jest.runOnlyPendingTimers()
|
|
615
|
+
|
|
616
|
+
await waitForPromises()
|
|
617
|
+
|
|
618
|
+
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
619
|
+
expect.objectContaining({
|
|
620
|
+
distinct_id: 'distinct_id',
|
|
621
|
+
event: 'node test event',
|
|
622
|
+
properties: expect.objectContaining({
|
|
623
|
+
$active_feature_flags: ['beta-feature-local'],
|
|
624
|
+
'$feature/beta-feature-local': 'third-variant',
|
|
625
|
+
'$feature/false-flag': false,
|
|
626
|
+
$lib: 'posthog-node',
|
|
627
|
+
$lib_version: '1.2.3',
|
|
628
|
+
$geoip_disable: true,
|
|
629
|
+
}),
|
|
630
|
+
})
|
|
631
|
+
)
|
|
632
|
+
expect(
|
|
633
|
+
Object.prototype.hasOwnProperty.call(getLastBatchEvents()?.[0].properties, '$feature/beta-feature-local')
|
|
634
|
+
).toBe(true)
|
|
635
|
+
expect(Object.prototype.hasOwnProperty.call(getLastBatchEvents()?.[0].properties, '$feature/beta-feature')).toBe(
|
|
636
|
+
false
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
await posthog.shutdownAsync()
|
|
640
|
+
})
|
|
641
|
+
|
|
642
|
+
it('doesnt add flag properties when locally evaluated flags are empty', async () => {
|
|
643
|
+
mockedFetch.mockClear()
|
|
644
|
+
expect(mockedFetch).toHaveBeenCalledTimes(0)
|
|
645
|
+
mockedFetch.mockImplementation(
|
|
646
|
+
apiImplementation({ decideFlags: { a: false, b: 'true' }, decideFlagPayloads: {}, localFlags: { flags: [] } })
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
posthog = new PostHog('TEST_API_KEY', {
|
|
650
|
+
host: 'http://example.com',
|
|
651
|
+
flushAt: 1,
|
|
652
|
+
fetchRetryCount: 0,
|
|
653
|
+
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
654
|
+
})
|
|
655
|
+
|
|
656
|
+
posthog.capture({
|
|
657
|
+
distinctId: 'distinct_id',
|
|
658
|
+
event: 'node test event',
|
|
659
|
+
})
|
|
660
|
+
|
|
661
|
+
jest.runOnlyPendingTimers()
|
|
662
|
+
await waitForPromises()
|
|
663
|
+
|
|
664
|
+
expect(mockedFetch).toHaveBeenCalledWith(...anyLocalEvalCall)
|
|
665
|
+
// no decide call
|
|
666
|
+
expect(mockedFetch).not.toHaveBeenCalledWith(
|
|
667
|
+
'http://example.com/decide/?v=3',
|
|
668
|
+
expect.objectContaining({ method: 'POST' })
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
jest.runOnlyPendingTimers()
|
|
672
|
+
|
|
673
|
+
await waitForPromises()
|
|
674
|
+
|
|
675
|
+
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
676
|
+
expect.objectContaining({
|
|
677
|
+
distinct_id: 'distinct_id',
|
|
678
|
+
event: 'node test event',
|
|
679
|
+
properties: expect.objectContaining({
|
|
680
|
+
$lib: 'posthog-node',
|
|
681
|
+
$lib_version: '1.2.3',
|
|
682
|
+
$geoip_disable: true,
|
|
683
|
+
}),
|
|
684
|
+
})
|
|
685
|
+
)
|
|
686
|
+
expect(
|
|
687
|
+
Object.prototype.hasOwnProperty.call(getLastBatchEvents()?.[0].properties, '$feature/beta-feature-local')
|
|
688
|
+
).toBe(false)
|
|
689
|
+
expect(Object.prototype.hasOwnProperty.call(getLastBatchEvents()?.[0].properties, '$feature/beta-feature')).toBe(
|
|
690
|
+
false
|
|
691
|
+
)
|
|
692
|
+
})
|
|
693
|
+
|
|
467
694
|
it('captures feature flags with same geoip setting as capture', async () => {
|
|
468
695
|
mockedFetch.mockClear()
|
|
469
696
|
mockedFetch.mockClear()
|
|
@@ -482,19 +709,19 @@ describe('PostHog Node.js', () => {
|
|
|
482
709
|
disableGeoip: false,
|
|
483
710
|
})
|
|
484
711
|
|
|
712
|
+
await waitForPromises()
|
|
713
|
+
jest.runOnlyPendingTimers()
|
|
714
|
+
|
|
485
715
|
expect(mockedFetch).toHaveBeenCalledWith(
|
|
486
716
|
'http://example.com/decide/?v=3',
|
|
487
717
|
expect.objectContaining({ method: 'POST', body: expect.not.stringContaining('geoip_disable') })
|
|
488
718
|
)
|
|
489
719
|
|
|
490
|
-
jest.runOnlyPendingTimers()
|
|
491
|
-
|
|
492
|
-
await waitForPromises()
|
|
493
|
-
|
|
494
720
|
expect(getLastBatchEvents()?.[0].properties).toEqual({
|
|
495
721
|
$active_feature_flags: ['feature-1', 'feature-2', 'feature-variant'],
|
|
496
722
|
'$feature/feature-1': true,
|
|
497
723
|
'$feature/feature-2': true,
|
|
724
|
+
'$feature/disabled-flag': false,
|
|
498
725
|
'$feature/feature-variant': 'variant',
|
|
499
726
|
$lib: 'posthog-node',
|
|
500
727
|
$lib_version: '1.2.3',
|
|
@@ -534,14 +761,16 @@ describe('PostHog Node.js', () => {
|
|
|
534
761
|
personalApiKey: 'TEST_PERSONAL_API_KEY',
|
|
535
762
|
maxCacheSize: 10,
|
|
536
763
|
fetchRetryCount: 0,
|
|
764
|
+
flushAt: 1,
|
|
537
765
|
})
|
|
538
766
|
|
|
539
767
|
expect(Object.keys(posthog.distinctIdHasSentFlagCalls).length).toEqual(0)
|
|
540
768
|
|
|
541
|
-
for (let i = 0; i <
|
|
769
|
+
for (let i = 0; i < 100; i++) {
|
|
542
770
|
const distinctId = `some-distinct-id${i}`
|
|
543
771
|
await posthog.getFeatureFlag('beta-feature', distinctId)
|
|
544
772
|
|
|
773
|
+
await waitForPromises()
|
|
545
774
|
jest.runOnlyPendingTimers()
|
|
546
775
|
|
|
547
776
|
const batchEvents = getLastBatchEvents()
|
|
@@ -566,6 +795,8 @@ describe('PostHog Node.js', () => {
|
|
|
566
795
|
})
|
|
567
796
|
|
|
568
797
|
it('$feature_flag_called is called appropriately when querying flags', async () => {
|
|
798
|
+
mockedFetch.mockClear()
|
|
799
|
+
|
|
569
800
|
const flags = {
|
|
570
801
|
flags: [
|
|
571
802
|
{
|
|
@@ -596,12 +827,19 @@ describe('PostHog Node.js', () => {
|
|
|
596
827
|
fetchRetryCount: 0,
|
|
597
828
|
})
|
|
598
829
|
|
|
830
|
+
jest.runOnlyPendingTimers()
|
|
831
|
+
|
|
599
832
|
expect(
|
|
600
833
|
await posthog.getFeatureFlag('beta-feature', 'some-distinct-id', {
|
|
601
834
|
personProperties: { region: 'USA', name: 'Aloha' },
|
|
602
835
|
})
|
|
603
836
|
).toEqual(true)
|
|
837
|
+
|
|
838
|
+
// TRICKY: There's now an extra step before events are queued, so need to wait for that to resolve
|
|
604
839
|
jest.runOnlyPendingTimers()
|
|
840
|
+
await waitForPromises()
|
|
841
|
+
await posthog.flushAsync()
|
|
842
|
+
|
|
605
843
|
expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
|
|
606
844
|
|
|
607
845
|
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
@@ -628,6 +866,8 @@ describe('PostHog Node.js', () => {
|
|
|
628
866
|
})
|
|
629
867
|
).toEqual(true)
|
|
630
868
|
jest.runOnlyPendingTimers()
|
|
869
|
+
await waitForPromises()
|
|
870
|
+
await posthog.flushAsync()
|
|
631
871
|
|
|
632
872
|
expect(mockedFetch).not.toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
|
|
633
873
|
|
|
@@ -640,6 +880,8 @@ describe('PostHog Node.js', () => {
|
|
|
640
880
|
})
|
|
641
881
|
).toEqual(true)
|
|
642
882
|
jest.runOnlyPendingTimers()
|
|
883
|
+
await waitForPromises()
|
|
884
|
+
await posthog.flushAsync()
|
|
643
885
|
expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
|
|
644
886
|
|
|
645
887
|
expect(getLastBatchEvents()?.[0]).toEqual(
|
|
@@ -667,6 +909,8 @@ describe('PostHog Node.js', () => {
|
|
|
667
909
|
})
|
|
668
910
|
).toEqual(true)
|
|
669
911
|
jest.runOnlyPendingTimers()
|
|
912
|
+
await waitForPromises()
|
|
913
|
+
await posthog.flushAsync()
|
|
670
914
|
expect(mockedFetch).not.toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
|
|
671
915
|
|
|
672
916
|
// # called for different flag, falls back to decide, should call capture again
|
|
@@ -677,6 +921,8 @@ describe('PostHog Node.js', () => {
|
|
|
677
921
|
})
|
|
678
922
|
).toEqual('decide-value')
|
|
679
923
|
jest.runOnlyPendingTimers()
|
|
924
|
+
await waitForPromises()
|
|
925
|
+
await posthog.flushAsync()
|
|
680
926
|
// one to decide, one to batch
|
|
681
927
|
expect(mockedFetch).toHaveBeenCalledWith(...anyDecideCall)
|
|
682
928
|
expect(mockedFetch).toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
|
|
@@ -705,6 +951,8 @@ describe('PostHog Node.js', () => {
|
|
|
705
951
|
})
|
|
706
952
|
).toEqual(true)
|
|
707
953
|
jest.runOnlyPendingTimers()
|
|
954
|
+
await waitForPromises()
|
|
955
|
+
await posthog.flushAsync()
|
|
708
956
|
// call decide, but not batch
|
|
709
957
|
expect(mockedFetch).toHaveBeenCalledWith(...anyDecideCall)
|
|
710
958
|
expect(mockedFetch).not.toHaveBeenCalledWith('http://example.com/batch/', expect.any(Object))
|
|
@@ -750,5 +998,154 @@ describe('PostHog Node.js', () => {
|
|
|
750
998
|
expect.objectContaining({ method: 'POST', body: expect.not.stringContaining('geoip_disable') })
|
|
751
999
|
)
|
|
752
1000
|
})
|
|
1001
|
+
|
|
1002
|
+
it('should add default person & group properties for feature flags', async () => {
|
|
1003
|
+
await posthog.getFeatureFlag('random_key', 'some_id', {
|
|
1004
|
+
groups: { company: 'id:5', instance: 'app.posthog.com' },
|
|
1005
|
+
personProperties: { x1: 'y1' },
|
|
1006
|
+
groupProperties: { company: { x: 'y' } },
|
|
1007
|
+
})
|
|
1008
|
+
jest.runOnlyPendingTimers()
|
|
1009
|
+
|
|
1010
|
+
expect(mockedFetch).toHaveBeenCalledWith(
|
|
1011
|
+
'http://example.com/decide/?v=3',
|
|
1012
|
+
expect.objectContaining({
|
|
1013
|
+
body: JSON.stringify({
|
|
1014
|
+
token: 'TEST_API_KEY',
|
|
1015
|
+
distinct_id: 'some_id',
|
|
1016
|
+
groups: { company: 'id:5', instance: 'app.posthog.com' },
|
|
1017
|
+
person_properties: {
|
|
1018
|
+
$current_distinct_id: 'some_id',
|
|
1019
|
+
x1: 'y1',
|
|
1020
|
+
},
|
|
1021
|
+
group_properties: {
|
|
1022
|
+
company: { $group_key: 'id:5', x: 'y' },
|
|
1023
|
+
instance: { $group_key: 'app.posthog.com' },
|
|
1024
|
+
},
|
|
1025
|
+
geoip_disable: true,
|
|
1026
|
+
}),
|
|
1027
|
+
})
|
|
1028
|
+
)
|
|
1029
|
+
|
|
1030
|
+
mockedFetch.mockClear()
|
|
1031
|
+
|
|
1032
|
+
await posthog.getFeatureFlag('random_key', 'some_id', {
|
|
1033
|
+
groups: { company: 'id:5', instance: 'app.posthog.com' },
|
|
1034
|
+
personProperties: { $current_distinct_id: 'override' },
|
|
1035
|
+
groupProperties: { company: { $group_key: 'group_override' } },
|
|
1036
|
+
})
|
|
1037
|
+
jest.runOnlyPendingTimers()
|
|
1038
|
+
|
|
1039
|
+
expect(mockedFetch).toHaveBeenCalledWith(
|
|
1040
|
+
'http://example.com/decide/?v=3',
|
|
1041
|
+
expect.objectContaining({
|
|
1042
|
+
body: JSON.stringify({
|
|
1043
|
+
token: 'TEST_API_KEY',
|
|
1044
|
+
distinct_id: 'some_id',
|
|
1045
|
+
groups: { company: 'id:5', instance: 'app.posthog.com' },
|
|
1046
|
+
person_properties: {
|
|
1047
|
+
$current_distinct_id: 'override',
|
|
1048
|
+
},
|
|
1049
|
+
group_properties: {
|
|
1050
|
+
company: { $group_key: 'group_override' },
|
|
1051
|
+
instance: { $group_key: 'app.posthog.com' },
|
|
1052
|
+
},
|
|
1053
|
+
geoip_disable: true,
|
|
1054
|
+
}),
|
|
1055
|
+
})
|
|
1056
|
+
)
|
|
1057
|
+
|
|
1058
|
+
mockedFetch.mockClear()
|
|
1059
|
+
|
|
1060
|
+
// test nones
|
|
1061
|
+
await posthog.getAllFlagsAndPayloads('some_id', {
|
|
1062
|
+
groups: undefined,
|
|
1063
|
+
personProperties: undefined,
|
|
1064
|
+
groupProperties: undefined,
|
|
1065
|
+
})
|
|
1066
|
+
|
|
1067
|
+
jest.runOnlyPendingTimers()
|
|
1068
|
+
|
|
1069
|
+
expect(mockedFetch).toHaveBeenCalledWith(
|
|
1070
|
+
'http://example.com/decide/?v=3',
|
|
1071
|
+
expect.objectContaining({
|
|
1072
|
+
body: JSON.stringify({
|
|
1073
|
+
token: 'TEST_API_KEY',
|
|
1074
|
+
distinct_id: 'some_id',
|
|
1075
|
+
groups: {},
|
|
1076
|
+
person_properties: {
|
|
1077
|
+
$current_distinct_id: 'some_id',
|
|
1078
|
+
},
|
|
1079
|
+
group_properties: {},
|
|
1080
|
+
geoip_disable: true,
|
|
1081
|
+
}),
|
|
1082
|
+
})
|
|
1083
|
+
)
|
|
1084
|
+
|
|
1085
|
+
mockedFetch.mockClear()
|
|
1086
|
+
await posthog.getAllFlags('some_id', {
|
|
1087
|
+
groups: { company: 'id:5' },
|
|
1088
|
+
personProperties: undefined,
|
|
1089
|
+
groupProperties: undefined,
|
|
1090
|
+
})
|
|
1091
|
+
jest.runOnlyPendingTimers()
|
|
1092
|
+
|
|
1093
|
+
expect(mockedFetch).toHaveBeenCalledWith(
|
|
1094
|
+
'http://example.com/decide/?v=3',
|
|
1095
|
+
expect.objectContaining({
|
|
1096
|
+
body: JSON.stringify({
|
|
1097
|
+
token: 'TEST_API_KEY',
|
|
1098
|
+
distinct_id: 'some_id',
|
|
1099
|
+
groups: { company: 'id:5' },
|
|
1100
|
+
person_properties: {
|
|
1101
|
+
$current_distinct_id: 'some_id',
|
|
1102
|
+
},
|
|
1103
|
+
group_properties: { company: { $group_key: 'id:5' } },
|
|
1104
|
+
geoip_disable: true,
|
|
1105
|
+
}),
|
|
1106
|
+
})
|
|
1107
|
+
)
|
|
1108
|
+
|
|
1109
|
+
mockedFetch.mockClear()
|
|
1110
|
+
await posthog.getFeatureFlagPayload('random_key', 'some_id', undefined)
|
|
1111
|
+
jest.runOnlyPendingTimers()
|
|
1112
|
+
|
|
1113
|
+
expect(mockedFetch).toHaveBeenCalledWith(
|
|
1114
|
+
'http://example.com/decide/?v=3',
|
|
1115
|
+
expect.objectContaining({
|
|
1116
|
+
body: JSON.stringify({
|
|
1117
|
+
token: 'TEST_API_KEY',
|
|
1118
|
+
distinct_id: 'some_id',
|
|
1119
|
+
groups: {},
|
|
1120
|
+
person_properties: {
|
|
1121
|
+
$current_distinct_id: 'some_id',
|
|
1122
|
+
},
|
|
1123
|
+
group_properties: {},
|
|
1124
|
+
geoip_disable: true,
|
|
1125
|
+
}),
|
|
1126
|
+
})
|
|
1127
|
+
)
|
|
1128
|
+
|
|
1129
|
+
mockedFetch.mockClear()
|
|
1130
|
+
|
|
1131
|
+
await posthog.isFeatureEnabled('random_key', 'some_id')
|
|
1132
|
+
jest.runOnlyPendingTimers()
|
|
1133
|
+
|
|
1134
|
+
expect(mockedFetch).toHaveBeenCalledWith(
|
|
1135
|
+
'http://example.com/decide/?v=3',
|
|
1136
|
+
expect.objectContaining({
|
|
1137
|
+
body: JSON.stringify({
|
|
1138
|
+
token: 'TEST_API_KEY',
|
|
1139
|
+
distinct_id: 'some_id',
|
|
1140
|
+
groups: {},
|
|
1141
|
+
person_properties: {
|
|
1142
|
+
$current_distinct_id: 'some_id',
|
|
1143
|
+
},
|
|
1144
|
+
group_properties: {},
|
|
1145
|
+
geoip_disable: true,
|
|
1146
|
+
}),
|
|
1147
|
+
})
|
|
1148
|
+
)
|
|
1149
|
+
})
|
|
753
1150
|
})
|
|
754
1151
|
})
|