1
- /**
2
- * @jest -environment jsdom
3
- */
4
- import axios from 'axios' ;
5
1
import * as td from 'testdouble' ;
6
- import mock , { MockResponse } from 'xhr-mock' ;
7
2
8
3
import {
9
4
IAssignmentTestCase ,
@@ -19,16 +14,11 @@ import { IAssignmentLogger } from '../assignment-logger';
19
14
import { IConfigurationStore } from '../configuration-store' ;
20
15
import { MAX_EVENT_QUEUE_SIZE , POLL_INTERVAL_MS , POLL_JITTER_PCT } from '../constants' ;
21
16
import FlagConfigurationRequestor from '../flag-configuration-requestor' ;
22
- import HttpClient from '../http-client' ;
17
+ import FetchHttpClient from '../http-client' ;
23
18
import { Flag , VariationType } from '../interfaces' ;
24
19
25
20
import EppoClient , { FlagConfigurationRequestParameters , checkTypeMatch } from './eppo-client' ;
26
21
27
- // eslint-disable-next-line @typescript-eslint/no-var-requires
28
- const packageJson = require ( '../../package.json' ) ;
29
-
30
- const flagEndpoint = / f l a g - c o n f i g \/ v 1 \/ c o n f i g * / ;
31
-
32
22
class TestConfigurationStore implements IConfigurationStore {
33
23
private store : Record < string , string > = { } ;
34
24
private _isInitialized = false ;
@@ -53,39 +43,37 @@ class TestConfigurationStore implements IConfigurationStore {
53
43
return this . _isInitialized ;
54
44
}
55
45
}
56
- export async function init ( configurationStore : IConfigurationStore ) {
57
- const axiosInstance = axios . create ( {
58
- baseURL : 'http://127.0.0.1:4000' ,
59
- timeout : 1000 ,
60
- } ) ;
61
-
62
- const httpClient = new HttpClient ( axiosInstance , {
63
- apiKey : 'dummy' ,
64
- sdkName : 'js-client-sdk-common' ,
65
- sdkVersion : packageJson . version ,
66
- } ) ;
67
46
47
+ export async function init ( configurationStore : IConfigurationStore ) {
48
+ const httpClient = new FetchHttpClient (
49
+ 'http://127.0.0.1:4000' ,
50
+ {
51
+ apiKey : 'dummy' ,
52
+ sdkName : 'js-client-sdk-common' ,
53
+ sdkVersion : '1.0.0' ,
54
+ } ,
55
+ 1000 ,
56
+ ) ;
68
57
const configurationRequestor = new FlagConfigurationRequestor ( configurationStore , httpClient ) ;
69
58
await configurationRequestor . fetchAndStoreConfigurations ( ) ;
70
59
}
71
60
72
61
describe ( 'EppoClient E2E test' , ( ) => {
73
- const storage = new TestConfigurationStore ( ) ;
62
+ global . fetch = jest . fn ( ( ) => {
63
+ const ufc = readMockUFCResponse ( MOCK_UFC_RESPONSE_FILE ) ;
74
64
75
- beforeAll ( async ( ) => {
76
- mock . setup ( ) ;
77
- mock . get ( flagEndpoint , ( _req , res ) => {
78
- const ufc = readMockUFCResponse ( MOCK_UFC_RESPONSE_FILE ) ;
79
- return res . status ( 200 ) . body ( JSON . stringify ( ufc ) ) ;
65
+ return Promise . resolve ( {
66
+ ok : true ,
67
+ status : 200 ,
68
+ json : ( ) => Promise . resolve ( ufc ) ,
80
69
} ) ;
70
+ } ) as jest . Mock ;
71
+ const storage = new TestConfigurationStore ( ) ;
81
72
73
+ beforeAll ( async ( ) => {
82
74
await init ( storage ) ;
83
75
} ) ;
84
76
85
- afterAll ( ( ) => {
86
- mock . teardown ( ) ;
87
- } ) ;
88
-
89
77
const flagKey = 'mock-flag' ;
90
78
91
79
const variationA = {
@@ -225,6 +213,22 @@ describe('EppoClient E2E test', () => {
225
213
} ) ;
226
214
227
215
describe ( 'UFC General Test Cases' , ( ) => {
216
+ beforeAll ( async ( ) => {
217
+ global . fetch = jest . fn ( ( ) => {
218
+ return Promise . resolve ( {
219
+ ok : true ,
220
+ status : 200 ,
221
+ json : ( ) => Promise . resolve ( readMockUFCResponse ( MOCK_UFC_RESPONSE_FILE ) ) ,
222
+ } ) ;
223
+ } ) as jest . Mock ;
224
+
225
+ await init ( storage ) ;
226
+ } ) ;
227
+
228
+ afterAll ( ( ) => {
229
+ jest . restoreAllMocks ( ) ;
230
+ } ) ;
231
+
228
232
it . each ( readAssignmentTestData ( ) ) (
229
233
'test variation assignment splits' ,
230
234
async ( { flag, variationType, defaultValue, subjects } : IAssignmentTestCase ) => {
@@ -261,19 +265,20 @@ describe('EppoClient E2E test', () => {
261
265
} ) ;
262
266
263
267
describe ( 'UFC Obfuscated Test Cases' , ( ) => {
264
- const storage = new TestConfigurationStore ( ) ;
265
-
266
268
beforeAll ( async ( ) => {
267
- mock . setup ( ) ;
268
- mock . get ( flagEndpoint , ( _req , res ) => {
269
- const ufc = readMockUFCResponse ( OBFUSCATED_MOCK_UFC_RESPONSE_FILE ) ;
270
- return res . status ( 200 ) . body ( JSON . stringify ( ufc ) ) ;
271
- } ) ;
269
+ global . fetch = jest . fn ( ( ) => {
270
+ return Promise . resolve ( {
271
+ ok : true ,
272
+ status : 200 ,
273
+ json : ( ) => Promise . resolve ( readMockUFCResponse ( OBFUSCATED_MOCK_UFC_RESPONSE_FILE ) ) ,
274
+ } ) ;
275
+ } ) as jest . Mock ;
276
+
272
277
await init ( storage ) ;
273
278
} ) ;
274
279
275
280
afterAll ( ( ) => {
276
- mock . teardown ( ) ;
281
+ jest . restoreAllMocks ( ) ;
277
282
} ) ;
278
283
279
284
it . each ( readAssignmentTestData ( ) ) (
@@ -575,32 +580,33 @@ describe('EppoClient E2E test', () => {
575
580
576
581
describe ( 'Eppo Client constructed with configuration request parameters' , ( ) => {
577
582
let client : EppoClient ;
578
- let storage : IConfigurationStore ;
583
+ let thisStorage : IConfigurationStore ;
579
584
let requestConfiguration : FlagConfigurationRequestParameters ;
580
- let mockServerResponseFunc : ( res : MockResponse ) => MockResponse ;
581
585
582
- const ufcBody = JSON . stringify ( readMockUFCResponse ( MOCK_UFC_RESPONSE_FILE ) ) ;
583
586
const flagKey = 'numeric_flag' ;
584
587
const subject = 'alice' ;
585
588
const pi = 3.1415926 ;
586
589
587
590
const maxRetryDelay = POLL_INTERVAL_MS * POLL_JITTER_PCT ;
588
591
589
- beforeAll ( ( ) => {
590
- mock . setup ( ) ;
591
- mock . get ( flagEndpoint , ( _req , res ) => {
592
- return mockServerResponseFunc ( res ) ;
593
- } ) ;
592
+ beforeAll ( async ( ) => {
593
+ global . fetch = jest . fn ( ( ) => {
594
+ return Promise . resolve ( {
595
+ ok : true ,
596
+ status : 200 ,
597
+ json : ( ) => Promise . resolve ( readMockUFCResponse ( MOCK_UFC_RESPONSE_FILE ) ) ,
598
+ } ) ;
599
+ } ) as jest . Mock ;
594
600
} ) ;
595
601
596
- beforeEach ( ( ) => {
597
- storage = new TestConfigurationStore ( ) ;
602
+ beforeEach ( async ( ) => {
598
603
requestConfiguration = {
599
604
apiKey : 'dummy key' ,
600
605
sdkName : 'js-client-sdk-common' ,
601
- sdkVersion : packageJson . version ,
606
+ sdkVersion : '1.0.0' ,
602
607
} ;
603
- mockServerResponseFunc = ( res ) => res . status ( 200 ) . body ( ufcBody ) ;
608
+
609
+ thisStorage = new TestConfigurationStore ( ) ;
604
610
605
611
// We only want to fake setTimeout() and clearTimeout()
606
612
jest . useFakeTimers ( {
@@ -629,11 +635,11 @@ describe('EppoClient E2E test', () => {
629
635
} ) ;
630
636
631
637
afterAll ( ( ) => {
632
- mock . teardown ( ) ;
638
+ jest . restoreAllMocks ( ) ;
633
639
} ) ;
634
640
635
641
it ( 'Fetches initial configuration with parameters in constructor' , async ( ) => {
636
- client = new EppoClient ( storage , requestConfiguration ) ;
642
+ client = new EppoClient ( thisStorage , requestConfiguration ) ;
637
643
client . setIsGracefulFailureMode ( false ) ;
638
644
// no configuration loaded
639
645
let variation = client . getNumericAssignment ( flagKey , subject , { } , 123.4 ) ;
@@ -645,7 +651,7 @@ describe('EppoClient E2E test', () => {
645
651
} ) ;
646
652
647
653
it ( 'Fetches initial configuration with parameters provided later' , async ( ) => {
648
- client = new EppoClient ( storage ) ;
654
+ client = new EppoClient ( thisStorage ) ;
649
655
client . setIsGracefulFailureMode ( false ) ;
650
656
client . setConfigurationRequestParameters ( requestConfiguration ) ;
651
657
// no configuration loaded
@@ -662,22 +668,33 @@ describe('EppoClient E2E test', () => {
662
668
{ pollAfterSuccessfulInitialization : true } ,
663
669
] ) ( 'retries initial configuration request with config %p' , async ( configModification ) => {
664
670
let callCount = 0 ;
665
- mockServerResponseFunc = ( res ) => {
671
+
672
+ global . fetch = jest . fn ( ( ) => {
666
673
if ( ++ callCount === 1 ) {
667
- // Throw an error for the first call
668
- return res . status ( 500 ) ;
674
+ // Simulate an error for the first call
675
+ return Promise . resolve ( {
676
+ ok : false ,
677
+ status : 500 ,
678
+ json : ( ) => Promise . reject ( new Error ( 'Server error' ) ) ,
679
+ } ) ;
669
680
} else {
670
- // Return a mock object for subsequent calls
671
- return res . status ( 200 ) . body ( ufcBody ) ;
681
+ // Return a successful response for subsequent calls
682
+ return Promise . resolve ( {
683
+ ok : true ,
684
+ status : 200 ,
685
+ json : ( ) => {
686
+ return readMockUFCResponse ( MOCK_UFC_RESPONSE_FILE ) ;
687
+ } ,
688
+ } ) ;
672
689
}
673
- } ;
690
+ } ) as jest . Mock ;
674
691
675
692
const { pollAfterSuccessfulInitialization } = configModification ;
676
693
requestConfiguration = {
677
694
...requestConfiguration ,
678
695
pollAfterSuccessfulInitialization,
679
696
} ;
680
- client = new EppoClient ( storage , requestConfiguration ) ;
697
+ client = new EppoClient ( thisStorage , requestConfiguration ) ;
681
698
client . setIsGracefulFailureMode ( false ) ;
682
699
// no configuration loaded
683
700
let variation = client . getNumericAssignment ( flagKey , subject , { } , 0.0 ) ;
@@ -711,15 +728,24 @@ describe('EppoClient E2E test', () => {
711
728
{ pollAfterFailedInitialization : true , throwOnFailedInitialization : true } ,
712
729
] ) ( 'initial configuration request fails with config %p' , async ( configModification ) => {
713
730
let callCount = 0 ;
714
- mockServerResponseFunc = ( res ) => {
731
+
732
+ global . fetch = jest . fn ( ( ) => {
715
733
if ( ++ callCount === 1 ) {
716
- // Throw an error for initialization call
717
- return res . status ( 500 ) ;
734
+ // Simulate an error for the first call
735
+ return Promise . resolve ( {
736
+ ok : false ,
737
+ status : 500 ,
738
+ json : ( ) => Promise . reject ( new Error ( 'Server error' ) ) ,
739
+ } as Response ) ;
718
740
} else {
719
- // Return a mock object for subsequent calls
720
- return res . status ( 200 ) . body ( ufcBody ) ;
741
+ // Return a successful response for subsequent calls
742
+ return Promise . resolve ( {
743
+ ok : true ,
744
+ status : 200 ,
745
+ json : ( ) => Promise . resolve ( readMockUFCResponse ( MOCK_UFC_RESPONSE_FILE ) ) ,
746
+ } as Response ) ;
721
747
}
722
- } ;
748
+ } ) ;
723
749
724
750
const { pollAfterFailedInitialization, throwOnFailedInitialization } = configModification ;
725
751
@@ -733,7 +759,7 @@ describe('EppoClient E2E test', () => {
733
759
throwOnFailedInitialization,
734
760
pollAfterFailedInitialization,
735
761
} ;
736
- client = new EppoClient ( storage , requestConfiguration ) ;
762
+ client = new EppoClient ( thisStorage , requestConfiguration ) ;
737
763
client . setIsGracefulFailureMode ( false ) ;
738
764
// no configuration loaded
739
765
expect ( client . getNumericAssignment ( flagKey , subject , { } , 0.0 ) ) . toBe ( 0.0 ) ;
0 commit comments