11import ApiEndpoints from './api-endpoints' ;
22import { BASE_URL as DEFAULT_BASE_URL } from './constants' ;
3+ import EnhancedSdkToken from './enhanced-sdk-token' ;
34
45describe ( 'ApiEndpoints' , ( ) => {
56 it ( 'should append query parameters to the URL' , ( ) => {
67 const apiEndpoints = new ApiEndpoints ( {
7- baseUrl : 'http ://api.example.com' ,
8+ baseUrl : 'https ://api.example.com' ,
89 queryParams : {
910 apiKey : '12345' ,
1011 sdkVersion : 'foobar' ,
1112 sdkName : 'ExampleSDK' ,
1213 } ,
1314 } ) ;
1415 expect ( apiEndpoints . endpoint ( '/data' ) . toString ( ) ) . toEqual (
15- 'http ://api.example.com/data?apiKey=12345&sdkVersion=foobar&sdkName=ExampleSDK' ,
16+ 'https ://api.example.com/data?apiKey=12345&sdkVersion=foobar&sdkName=ExampleSDK' ,
1617 ) ;
1718 expect ( apiEndpoints . ufcEndpoint ( ) . toString ( ) ) . toEqual (
18- 'http ://api.example.com/flag-config/v1/config?apiKey=12345&sdkVersion=foobar&sdkName=ExampleSDK' ,
19+ 'https ://api.example.com/flag-config/v1/config?apiKey=12345&sdkVersion=foobar&sdkName=ExampleSDK' ,
1920 ) ;
2021 } ) ;
2122
@@ -42,4 +43,121 @@ describe('ApiEndpoints', () => {
4243 `${ DEFAULT_BASE_URL } /flag-config/v1/config` ,
4344 ) ;
4445 } ) ;
46+
47+ describe ( 'Base URL determination' , ( ) => {
48+ it ( 'should use custom baseUrl when provided' , ( ) => {
49+ const customBaseUrl = 'https://custom-domain.com' ;
50+ const endpoints = new ApiEndpoints ( { baseUrl : customBaseUrl } ) ;
51+ expect ( endpoints . endpoint ( '' ) ) . toContain ( customBaseUrl ) ;
52+ } ) ;
53+
54+ it ( 'should use subdomain from SDK token when valid' , ( ) => {
55+ // This token has cs=test-subdomain
56+ const sdkToken = 'abc.Y3M9dGVzdC1zdWJkb21haW4=' ;
57+ const endpoints = new ApiEndpoints ( { sdkToken : new EnhancedSdkToken ( sdkToken ) } ) ;
58+ expect ( endpoints . getEffectiveBaseUrl ( ) ) . toBe ( 'https://test-subdomain.fscdn.eppo.cloud/api' ) ;
59+ } ) ;
60+
61+ it ( 'should prefer custom baseUrl over SDK token subdomain' , ( ) => {
62+ const customBaseUrl = 'https://custom-domain.com' ;
63+ // This token has cs=test-subdomain
64+ const sdkToken = 'abc.Y3M9dGVzdC1zdWJkb21haW4=' ;
65+ const endpoints = new ApiEndpoints ( {
66+ baseUrl : customBaseUrl ,
67+ sdkToken : new EnhancedSdkToken ( sdkToken ) ,
68+ } ) ;
69+ expect ( endpoints . getEffectiveBaseUrl ( ) ) . toBe ( customBaseUrl ) ;
70+ } ) ;
71+
72+ it ( 'should fallback to DEFAULT_BASE_URL when SDK token has no subdomain' , ( ) => {
73+ // This token has no cs parameter
74+ const sdkToken = 'abc.ZWg9ZXZlbnQtaG9zdG5hbWU=' ;
75+ const endpoints = new ApiEndpoints ( { sdkToken : new EnhancedSdkToken ( sdkToken ) } ) ;
76+ expect ( endpoints . getEffectiveBaseUrl ( ) ) . toBe ( DEFAULT_BASE_URL ) ;
77+ } ) ;
78+
79+ it ( 'should fallback to DEFAULT_BASE_URL when SDK token is invalid' , ( ) => {
80+ const invalidToken = new EnhancedSdkToken ( 'invalid-token' ) ;
81+ const endpoints = new ApiEndpoints ( { sdkToken : invalidToken } ) ;
82+ expect ( endpoints . getEffectiveBaseUrl ( ) ) . toBe ( DEFAULT_BASE_URL ) ;
83+ } ) ;
84+ } ) ;
85+
86+ describe ( 'Endpoint URL construction' , ( ) => {
87+ it ( 'should use effective base URL for UFC endpoint' , ( ) => {
88+ // This token has cs=test-subdomain
89+ const sdkToken = 'abc.Y3M9dGVzdC1zdWJkb21haW4=' ;
90+ const endpoints = new ApiEndpoints ( { sdkToken : new EnhancedSdkToken ( sdkToken ) } ) ;
91+
92+ expect ( endpoints . ufcEndpoint ( ) ) . toContain (
93+ 'https://test-subdomain.fscdn.eppo.cloud/api/flag-config/v1/config' ,
94+ ) ;
95+ } ) ;
96+
97+ it ( 'should use effective base URL for bandit parameters endpoint' , ( ) => {
98+ // This token has cs=test-subdomain
99+ const sdkToken = 'abc.Y3M9dGVzdC1zdWJkb21haW4=' ;
100+ const endpoints = new ApiEndpoints ( { sdkToken : new EnhancedSdkToken ( sdkToken ) } ) ;
101+
102+ expect ( endpoints . banditParametersEndpoint ( ) ) . toContain (
103+ 'https://test-subdomain.fscdn.eppo.cloud/api/flag-config/v1/bandits' ,
104+ ) ;
105+ } ) ;
106+
107+ it ( 'should use the sub-domain and default base URL for precomputed flags endpoint' , ( ) => {
108+ // This token has cs=test-subdomain
109+ const sdkToken = 'abc.Y3M9dGVzdC1zdWJkb21haW4=' ;
110+ const endpoints = new ApiEndpoints ( {
111+ sdkToken : new EnhancedSdkToken ( sdkToken ) ,
112+ defaultUrl : 'default.eppo.cloud' ,
113+ } ) ;
114+
115+ expect ( endpoints . precomputedFlagsEndpoint ( ) ) . toContain ( 'default.eppo.cloud' ) ;
116+ expect ( endpoints . precomputedFlagsEndpoint ( ) ) . toContain ( 'test-subdomain' ) ;
117+ } ) ;
118+
119+ it ( 'should handle slash management between base URL and resource' , ( ) => {
120+ const baseUrlWithSlash = 'https://domain.com/' ;
121+ const baseUrlWithoutSlash = 'https://domain.com' ;
122+ const resourceWithSlash = '/resource' ;
123+ const resourceWithoutSlash = 'resource' ;
124+
125+ const endpoints1 = new ApiEndpoints ( { baseUrl : baseUrlWithSlash } ) ;
126+ const endpoints2 = new ApiEndpoints ( { baseUrl : baseUrlWithoutSlash } ) ;
127+
128+ // Test all combinations to ensure we avoid double slashes and always have one slash
129+ expect ( endpoints1 . endpoint ( resourceWithSlash ) ) . toBe ( 'https://domain.com/resource' ) ;
130+ expect ( endpoints1 . endpoint ( resourceWithoutSlash ) ) . toBe ( 'https://domain.com/resource' ) ;
131+ expect ( endpoints2 . endpoint ( resourceWithSlash ) ) . toBe ( 'https://domain.com/resource' ) ;
132+ expect ( endpoints2 . endpoint ( resourceWithoutSlash ) ) . toBe ( 'https://domain.com/resource' ) ;
133+ } ) ;
134+ } ) ;
135+
136+ describe ( 'Query parameter handling' , ( ) => {
137+ it ( 'should append query parameters to endpoint URLs' , ( ) => {
138+ const queryParams = { apiKey : 'test-key' , sdkName : 'js-sdk' , sdkVersion : '1.0.0' } ;
139+ const endpoints = new ApiEndpoints ( { queryParams } ) ;
140+
141+ const url = endpoints . ufcEndpoint ( ) ;
142+
143+ expect ( url ) . toContain ( '?' ) ;
144+ expect ( url ) . toContain ( 'apiKey=test-key' ) ;
145+ expect ( url ) . toContain ( 'sdkName=js-sdk' ) ;
146+ expect ( url ) . toContain ( 'sdkVersion=1.0.0' ) ;
147+ } ) ;
148+
149+ it ( 'should properly encode query parameters with special characters' , ( ) => {
150+ const queryParams = {
151+ apiKey : 'test-key' ,
152+ sdkName : 'value with spaces' ,
153+ sdkVersion : 'a+b=c&d' ,
154+ } ;
155+ const endpoints = new ApiEndpoints ( { queryParams } ) ;
156+
157+ const url = endpoints . ufcEndpoint ( ) ;
158+
159+ expect ( url ) . toContain ( 'sdkName=value+with+spaces' ) ;
160+ expect ( url ) . toContain ( 'sdkVersion=a%2Bb%3Dc%26d' ) ;
161+ } ) ;
162+ } ) ;
45163} ) ;
0 commit comments