1- import { Config , ConfigJson , ClientCacheState , EvaluationDetails , HookEvents , IConfigCatClient , IConfigCatClientSnapshot , Internals , prepareConfig , RefreshResult , SettingKeyValue , SettingTypeOf , SettingValue , User } from "@configcat/sdk" ;
1+ import { ClientCacheState , Config , ConfigJson , EvaluationDetails , HookEvents , IConfigCatClient , IConfigCatClientSnapshot , Internals , prepareConfig , RefreshErrorCode , RefreshResult , SettingKeyValue , SettingTypeOf , SettingValue , User } from "@configcat/sdk" ;
22import { isAllowedValue } from "@configcat/sdk/lib/esm/ProjectConfig.js" ;
33
44export class ConfigCatClientMockBase implements IConfigCatClient {
5- constructor (
6- public isOffline = false ) {
7- }
8-
9- getValueAsync < T extends SettingValue > ( key : string , defaultValue : T , user ?: User | undefined ) : Promise < SettingTypeOf < T > > {
10- throw new Error ( "Method not implemented." ) ;
11- }
12- getValueDetailsAsync < T extends SettingValue > ( key : string , defaultValue : T , user ?: User | undefined ) : Promise < EvaluationDetails < SettingTypeOf < T > > > {
13- throw new Error ( "Method not implemented." ) ;
14- }
15- getAllKeysAsync ( ) : Promise < string [ ] > {
16- throw new Error ( "Method not implemented." ) ;
17- }
18- getAllValuesAsync ( user ?: User | undefined ) : Promise < SettingKeyValue < SettingValue > [ ] > {
19- throw new Error ( "Method not implemented." ) ;
20- }
21- getAllValueDetailsAsync ( user ?: User | undefined ) : Promise < EvaluationDetails < SettingValue > [ ] > {
22- throw new Error ( "Method not implemented." ) ;
23- }
24- getKeyAndValueAsync ( variationId : string ) : Promise < SettingKeyValue < SettingValue > | null > {
25- throw new Error ( "Method not implemented." ) ;
26- }
27- forceRefreshAsync ( ) : Promise < RefreshResult > {
28- throw new Error ( "Method not implemented." ) ;
29- }
30- waitForReady ( ) : Promise < ClientCacheState > {
31- throw new Error ( "Method not implemented." ) ;
32- }
33- snapshot ( ) : IConfigCatClientSnapshot {
34- throw new Error ( "Method not implemented." ) ;
35- }
36- setDefaultUser ( defaultUser : User ) : void {
37- throw new Error ( "Method not implemented." ) ;
38- }
39- clearDefaultUser ( ) : void {
40- throw new Error ( "Method not implemented." ) ;
41- }
42- setOnline ( ) : void {
43- throw new Error ( "Method not implemented." ) ;
44- }
45- setOffline ( ) : void {
46- throw new Error ( "Method not implemented." ) ;
47- }
48- dispose ( ) : void {
49- throw new Error ( "Method not implemented." ) ;
50- }
51- addListener < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
52- throw new Error ( "Method not implemented." ) ;
53- }
54- on < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
55- throw new Error ( "Method not implemented." ) ;
56- }
57- once < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
58- throw new Error ( "Method not implemented." ) ;
59- }
60- removeListener < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
61- throw new Error ( "Method not implemented." ) ;
62- }
63- off < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
64- throw new Error ( "Method not implemented." ) ;
65- }
66- removeAllListeners ( eventName ?: keyof HookEvents | undefined ) : this {
67- throw new Error ( "Method not implemented." ) ;
68- }
69- listeners ( eventName : keyof HookEvents ) : Function [ ] {
70- throw new Error ( "Method not implemented." ) ;
71- }
72- listenerCount ( eventName : keyof HookEvents ) : number {
73- throw new Error ( "Method not implemented." ) ;
74- }
75- eventNames ( ) : ( keyof HookEvents ) [ ] {
76- throw new Error ( "Method not implemented." ) ;
77- }
5+ constructor (
6+ public isOffline = false ) {
7+ }
8+
9+ getValueAsync < T extends SettingValue > ( key : string , defaultValue : T , user ?: User ) : Promise < SettingTypeOf < T > > {
10+ throw new Error ( "Method not implemented." ) ;
11+ }
12+ getValueDetailsAsync < T extends SettingValue > ( key : string , defaultValue : T , user ?: User ) : Promise < EvaluationDetails < SettingTypeOf < T > > > {
13+ throw new Error ( "Method not implemented." ) ;
14+ }
15+ getAllKeysAsync ( ) : Promise < string [ ] > {
16+ throw new Error ( "Method not implemented." ) ;
17+ }
18+ getAllValuesAsync ( user ?: User ) : Promise < SettingKeyValue [ ] > {
19+ throw new Error ( "Method not implemented." ) ;
20+ }
21+ getAllValueDetailsAsync ( user ?: User ) : Promise < EvaluationDetails [ ] > {
22+ throw new Error ( "Method not implemented." ) ;
23+ }
24+ getKeyAndValueAsync ( variationId : string ) : Promise < SettingKeyValue | null > {
25+ throw new Error ( "Method not implemented." ) ;
26+ }
27+ forceRefreshAsync ( ) : Promise < RefreshResult > {
28+ throw new Error ( "Method not implemented." ) ;
29+ }
30+ waitForReady ( ) : Promise < ClientCacheState > {
31+ throw new Error ( "Method not implemented." ) ;
32+ }
33+ snapshot ( ) : IConfigCatClientSnapshot {
34+ throw new Error ( "Method not implemented." ) ;
35+ }
36+ setDefaultUser ( defaultUser : User ) : void {
37+ throw new Error ( "Method not implemented." ) ;
38+ }
39+ clearDefaultUser ( ) : void {
40+ throw new Error ( "Method not implemented." ) ;
41+ }
42+ setOnline ( ) : void {
43+ throw new Error ( "Method not implemented." ) ;
44+ }
45+ setOffline ( ) : void {
46+ throw new Error ( "Method not implemented." ) ;
47+ }
48+ dispose ( ) : void {
49+ throw new Error ( "Method not implemented." ) ;
50+ }
51+ addListener < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
52+ throw new Error ( "Method not implemented." ) ;
53+ }
54+ on < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
55+ throw new Error ( "Method not implemented." ) ;
56+ }
57+ once < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
58+ throw new Error ( "Method not implemented." ) ;
59+ }
60+ removeListener < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
61+ throw new Error ( "Method not implemented." ) ;
62+ }
63+ off < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
64+ throw new Error ( "Method not implemented." ) ;
65+ }
66+ removeAllListeners ( eventName ?: keyof HookEvents ) : this {
67+ throw new Error ( "Method not implemented." ) ;
68+ }
69+ listeners ( eventName : keyof HookEvents ) : Function [ ] {
70+ throw new Error ( "Method not implemented." ) ;
71+ }
72+ listenerCount ( eventName : keyof HookEvents ) : number {
73+ throw new Error ( "Method not implemented." ) ;
74+ }
75+ eventNames ( ) : ( keyof HookEvents ) [ ] {
76+ throw new Error ( "Method not implemented." ) ;
77+ }
7878}
7979
8080export class ConfigCatClientSnapshotMockBase implements IConfigCatClientSnapshot {
81- constructor (
82- public cacheState = ClientCacheState . NoFlagData ,
83- public fetchedConfig : Config | null = null ) {
84- }
85-
86- getAllKeys ( ) : readonly string [ ] {
87- throw new Error ( "Method not implemented." ) ;
88- }
89- getValue < T extends SettingValue > ( key : string , defaultValue : T , user ?: User | undefined ) : SettingTypeOf < T > {
90- throw new Error ( "Method not implemented." ) ;
91- }
92- getValueDetails < T extends SettingValue > ( key : string , defaultValue : T , user ?: User | undefined ) : EvaluationDetails < SettingTypeOf < T > > {
93- throw new Error ( "Method not implemented." ) ;
94- }
95- getKeyAndValue ( variationId : string ) : SettingKeyValue | null {
96- throw new Error ( "Method not implemented." ) ;
97- }
81+ constructor (
82+ public cacheState = ClientCacheState . NoFlagData ,
83+ public fetchedConfig : Config | null = null ) {
84+ }
85+
86+ getAllKeys ( ) : readonly string [ ] {
87+ throw new Error ( "Method not implemented." ) ;
88+ }
89+ getValue < T extends SettingValue > ( key : string , defaultValue : T , user ?: User ) : SettingTypeOf < T > {
90+ throw new Error ( "Method not implemented." ) ;
91+ }
92+ getValueDetails < T extends SettingValue > ( key : string , defaultValue : T , user ?: User ) : EvaluationDetails < SettingTypeOf < T > > {
93+ throw new Error ( "Method not implemented." ) ;
94+ }
95+ getKeyAndValue ( variationId : string ) : SettingKeyValue | null {
96+ throw new Error ( "Method not implemented." ) ;
97+ }
9898}
9999
100100export class SimpleValueConfigCatClientMock extends ConfigCatClientMockBase {
101- private readonly eventEmitter = new Internals . DefaultEventEmitter ( ) ;
102- private readonly readyPromise : Promise < ClientCacheState > ;
103- private signalReady : ( value : NonNullable < SettingValue > ) => void ;
104- private cacheState = ClientCacheState . NoFlagData ;
105- private currentValue : NonNullable < SettingValue > ;
106- private currentConfig : Config | null = null ;
107-
108- constructor ( private key : string ) {
109- super ( ) ;
110-
111- this . readyPromise = new Promise < NonNullable < SettingValue > > ( resolve => this . signalReady = resolve )
112- . then ( initialValue => {
113- this . currentValue = initialValue ;
114- this . currentConfig = createConfigFromValue ( this . key , initialValue ) ;
115- this . cacheState = ClientCacheState . HasUpToDateFlagData ;
116- ( this . eventEmitter as Internals . IEventEmitter < HookEvents > ) . emit ( "clientReady" , this . cacheState ) ;
117- return this . cacheState ;
118- } ) ;
119- }
120-
121- /** Call this method to simulate the `clientReady` event and to provide an initial feature flag value. */
122- async setReady ( initialValue : NonNullable < SettingValue > ) : Promise < void > {
123- this . signalReady ( initialValue ) ;
124-
125- // Allow async continuations to run.
126- await new Promise < void > ( resolve => setTimeout ( ( ) => resolve ( ) , 0 ) ) ;
127- }
128-
129- /** Call this method to simulate the `configChanged` event and to update the current feature flag value. */
130- changeValue ( newValue : NonNullable < SettingValue > ) : void {
131- if ( this . currentValue === newValue ) {
132- return ;
101+ private readonly eventEmitter = new Internals . DefaultEventEmitter ( ) ;
102+ private readonly readyPromise : Promise < ClientCacheState > ;
103+ private signalReady ! : ( value : NonNullable < SettingValue > ) => void ;
104+ private cacheState = ClientCacheState . NoFlagData ;
105+ private currentValue ! : NonNullable < SettingValue > ;
106+ private currentConfig : Config | null = null ;
107+
108+ constructor ( private readonly key : string ) {
109+ super ( ) ;
110+
111+ this . readyPromise = new Promise < NonNullable < SettingValue > > ( resolve => this . signalReady = resolve )
112+ . then ( initialValue => {
113+ this . currentValue = initialValue ;
114+ this . currentConfig = createConfigFromValue ( this . key , initialValue ) ;
115+ this . cacheState = ClientCacheState . HasUpToDateFlagData ;
116+ ( this . eventEmitter as Internals . IEventEmitter < HookEvents > ) . emit ( "clientReady" , this . cacheState ) ;
117+ return this . cacheState ;
118+ } ) ;
119+ }
120+
121+ /** Call this method to simulate the `clientReady` event and to provide an initial feature flag value. */
122+ async setReady ( initialValue : NonNullable < SettingValue > ) : Promise < void > {
123+ this . signalReady ( initialValue ) ;
124+
125+ // Allow async continuations to run.
126+ await new Promise < void > ( resolve => setTimeout ( ( ) => resolve ( ) , 0 ) ) ;
127+ }
128+
129+ /** Call this method to simulate the `configChanged` event and to update the current feature flag value. */
130+ changeValue ( newValue : NonNullable < SettingValue > ) : void {
131+ if ( this . currentValue === newValue ) {
132+ return ;
133+ }
134+
135+ this . currentValue = newValue ;
136+ this . currentConfig = createConfigFromValue ( this . key , newValue ) ;
137+ ( this . eventEmitter as Internals . IEventEmitter < HookEvents > ) . emit ( "configChanged" , this . currentConfig ) ;
138+ }
139+
140+ override async getValueAsync < T extends SettingValue > ( key : string , defaultValue : T , user ?: User ) : Promise < SettingTypeOf < T > > {
141+ await this . readyPromise ;
142+
143+ if ( key === this . key ) {
144+ return ( isValidSettingValue ( this . currentValue , defaultValue ) ? this . currentValue : defaultValue ) as SettingTypeOf < T > ;
145+ }
146+
147+ return super . getValueAsync ( key , defaultValue , user ) ;
148+ }
149+
150+ override snapshot ( ) {
151+ const client = this ;
152+
153+ return new ( class extends ConfigCatClientSnapshotMockBase {
154+ override getValue < T extends SettingValue > ( key : string , defaultValue : T , user ?: User ) : SettingTypeOf < T > {
155+ if ( key === client . key ) {
156+ return ( isValidSettingValue ( client . currentValue , defaultValue ) ? client . currentValue : defaultValue ) as SettingTypeOf < T > ;
133157 }
134158
135- this . currentValue = newValue ;
136- this . currentConfig = createConfigFromValue ( this . key , newValue ) ;
137- ( this . eventEmitter as Internals . IEventEmitter < HookEvents > ) . emit ( "configChanged" , this . currentConfig ) ;
138- }
159+ return super . getValue ( key , defaultValue , user ) ;
160+ }
139161
140- async getValueAsync < T extends SettingValue > ( key : string , defaultValue : T , user ?: User | undefined ) : Promise < SettingTypeOf < T > > {
141- await this . readyPromise ;
142-
143- if ( key === this . key ) {
144- return ( isValidSettingValue ( this . currentValue , defaultValue ) ? this . currentValue : defaultValue ) as SettingTypeOf < T > ;
162+ override getValueDetails < T extends SettingValue > ( key : string , defaultValue : T , user ?: User ) {
163+ if ( key === client . key ) {
164+ return isValidSettingValue ( client . currentValue , defaultValue )
165+ ? { key, value : client . currentValue , isDefaultValue : false , user } as EvaluationDetails < SettingTypeOf < T > >
166+ : { key , value : defaultValue , isDefaultValue : true , user , errorMessage : "Invalid setting type." } as EvaluationDetails < SettingTypeOf < T > > ;
145167 }
146168
147- return super . getValueAsync ( key , defaultValue , user ) ;
148- }
169+ return super . getValueDetails ( key , defaultValue , user ) ;
170+ }
171+ } ) ( this . cacheState , this . currentConfig ) ;
172+ }
149173
150- snapshot ( ) {
151- const client = this ;
174+ override waitForReady ( ) : Promise < ClientCacheState > {
175+ return this . readyPromise ;
176+ }
152177
153- return new ( class extends ConfigCatClientSnapshotMockBase {
154- getValue < T extends SettingValue > ( key : string , defaultValue : T , user ?: User | undefined ) : SettingTypeOf < T > {
155- if ( key === client . key ) {
156- return ( isValidSettingValue ( client . currentValue , defaultValue ) ? client . currentValue : defaultValue ) as SettingTypeOf < T > ;
157- }
178+ override on < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
179+ this . eventEmitter . on ( eventName , listener as ( ...args : any [ ] ) => void ) ;
180+ return this ;
181+ }
158182
159- return super . getValue ( key , defaultValue , user ) ;
160- }
161- } ) ( this . cacheState , this . currentConfig ) ;
162- }
163-
164- waitForReady ( ) : Promise < ClientCacheState > {
165- return this . readyPromise ;
166- }
167-
168- on < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
169- this . eventEmitter . on ( eventName , listener as ( ...args : any [ ] ) => void ) ;
170- return this ;
171- }
183+ override off < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
184+ this . eventEmitter . off ( eventName , listener as ( ...args : any [ ] ) => void ) ;
185+ return this ;
186+ }
172187
173- off < TEventName extends keyof HookEvents > ( eventName : TEventName , listener : ( ...args : HookEvents [ TEventName ] ) => void ) : this {
174- this . eventEmitter . off ( eventName , listener as ( ...args : any [ ] ) => void ) ;
175- return this ;
176- }
177- } ;
188+ override forceRefreshAsync ( ) : Promise < RefreshResult > {
189+ return Promise . resolve ( { isSuccess : true , errorCode : RefreshErrorCode . None } ) ;
190+ }
191+ }
178192
179193function createConfigFromValue ( key : string , value : NonNullable < SettingValue > ) : Config {
180- const [ settingType , settingValue ] : [ ConfigJson . SettingType , ConfigJson . SettingValue ] =
181- typeof value === "boolean" ? [ ConfigJson . SettingType . Boolean , { b : value } ] :
182- typeof value === "string" ? [ ConfigJson . SettingType . String , { s : value } ] :
183- Number . isInteger ( this . changeValue ) ? [ ConfigJson . SettingType . Int , { i : value } ] :
184- [ ConfigJson . SettingType . Double , { d : value } ] ;
185-
186- const configJson : Omit < ConfigJson . Config , "p" > = {
187- f : { [ key ] : { t : settingType , v : settingValue } as ConfigJson . SettingUnion }
188- } ;
194+ const [ settingType , settingValue ] : [ ConfigJson . SettingType , ConfigJson . SettingValue ] =
195+ typeof value === "boolean" ? [ ConfigJson . SettingType . Boolean , { b : value } ]
196+ : typeof value === "string" ? [ ConfigJson . SettingType . String , { s : value } ]
197+ : Number . isInteger ( value ) ? [ ConfigJson . SettingType . Int , { i : value } ]
198+ : [ ConfigJson . SettingType . Double , { d : value } ] ;
199+
200+ const configJson : Omit < ConfigJson . Config , "p" > = {
201+ f : { [ key ] : { t : settingType , v : settingValue } as ConfigJson . SettingUnion } ,
202+ } ;
189203
190- return prepareConfig ( configJson ) ;
204+ return prepareConfig ( configJson ) ;
191205}
192206
193207function isValidSettingValue ( settingValue : NonNullable < SettingValue > , defaultValue : SettingValue ) {
194- return defaultValue == null
195- ? isAllowedValue ( settingValue )
196- : typeof settingValue === typeof defaultValue ;
197- }
208+ return defaultValue == null
209+ ? isAllowedValue ( settingValue )
210+ : typeof settingValue === typeof defaultValue ;
211+ }
0 commit comments