@@ -66,7 +66,7 @@ describe('rules configuration', () => {
6666 ) . toBe ( true ) ;
6767 } ) ;
6868
69- it ( 'omits a flag that uses an unsupported operator' , ( ) => {
69+ it ( 'preserves a flag with an unsupported operator and reports PARSE_ERROR ' , ( ) => {
7070 const source = buildRulesConfiguration ( ) ;
7171 const condition =
7272 source . flags [ 'dynamic-flag' ] . allocations [ 0 ] . rules ?. [ 0 ]
@@ -83,10 +83,25 @@ describe('rules configuration', () => {
8383 if ( prepared . status !== 'ready' ) {
8484 throw new Error ( prepared . errorMessage ) ;
8585 }
86- expect ( prepared . configuration . flags ) . toEqual ( { } ) ;
86+ expect ( prepared . configuration . flags ) . toHaveProperty ( 'dynamic-flag' ) ;
87+ expect (
88+ flaggingCoreRulesEngine . evaluate ( {
89+ configuration : prepared . configuration ,
90+ type : 'boolean' ,
91+ flagKey : 'dynamic-flag' ,
92+ defaultValue : false ,
93+ context : { targetingKey : 'user-1' } ,
94+ logger : getNoopRulesLogger ( )
95+ } )
96+ ) . toMatchObject ( {
97+ value : false ,
98+ reason : 'ERROR' ,
99+ errorCode : 'PARSE_ERROR' ,
100+ errorMessage : expect . stringContaining ( 'FUTURE_OPERATOR' )
101+ } ) ;
87102 } ) ;
88103
89- it ( 'omits a flag that contains an invalid regular expression' , ( ) => {
104+ it ( 'reports PARSE_ERROR for a flag with an invalid regular expression' , ( ) => {
90105 const source = buildRulesConfiguration ( ) ;
91106 const conditions =
92107 source . flags [ 'dynamic-flag' ] . allocations [ 0 ] . rules ?. [ 0 ] . conditions ;
@@ -105,10 +120,22 @@ describe('rules configuration', () => {
105120 if ( prepared . status !== 'ready' ) {
106121 throw new Error ( prepared . errorMessage ) ;
107122 }
108- expect ( prepared . configuration . flags ) . toEqual ( { } ) ;
123+ expect (
124+ flaggingCoreRulesEngine . evaluate ( {
125+ configuration : prepared . configuration ,
126+ type : 'boolean' ,
127+ flagKey : 'dynamic-flag' ,
128+ defaultValue : false ,
129+ context : { targetingKey : 'user-1' } ,
130+ logger : getNoopRulesLogger ( )
131+ } )
132+ ) . toMatchObject ( {
133+ errorCode : 'PARSE_ERROR' ,
134+ errorMessage : 'A regular expression condition is not valid.'
135+ } ) ;
109136 } ) ;
110137
111- it ( 'omits a flag whose split points to an absent variation' , ( ) => {
138+ it ( 'reports PARSE_ERROR when a split points to an absent variation' , ( ) => {
112139 const source = buildRulesConfiguration ( ) ;
113140 source . flags [ 'dynamic-flag' ] . allocations [ 0 ] . splits [ 0 ] . variationKey =
114141 'absent' ;
@@ -119,10 +146,22 @@ describe('rules configuration', () => {
119146 if ( prepared . status !== 'ready' ) {
120147 throw new Error ( prepared . errorMessage ) ;
121148 }
122- expect ( prepared . configuration . flags ) . toEqual ( { } ) ;
149+ expect (
150+ flaggingCoreRulesEngine . evaluate ( {
151+ configuration : prepared . configuration ,
152+ type : 'boolean' ,
153+ flagKey : 'dynamic-flag' ,
154+ defaultValue : false ,
155+ context : { targetingKey : 'user-1' } ,
156+ logger : getNoopRulesLogger ( )
157+ } )
158+ ) . toMatchObject ( {
159+ errorCode : 'PARSE_ERROR' ,
160+ errorMessage : 'A split has an invalid variation key.'
161+ } ) ;
123162 } ) ;
124163
125- it ( 'keeps valid flags when it omits an invalid flag ' , ( ) => {
164+ it ( 'keeps valid flags usable when another flag has a parse error ' , ( ) => {
126165 const source = buildRulesConfiguration ( ) ;
127166 const validFlag = buildRulesConfiguration ( ) . flags [ 'dynamic-flag' ] ;
128167 validFlag . key = 'valid-flag' ;
@@ -143,8 +182,46 @@ describe('rules configuration', () => {
143182 throw new Error ( prepared . errorMessage ) ;
144183 }
145184 expect ( Object . keys ( prepared . configuration . flags ) ) . toEqual ( [
185+ 'dynamic-flag' ,
146186 'valid-flag'
147187 ] ) ;
188+ expect (
189+ flaggingCoreRulesEngine . evaluate ( {
190+ configuration : prepared . configuration ,
191+ type : 'boolean' ,
192+ flagKey : 'valid-flag' ,
193+ defaultValue : false ,
194+ context : { targetingKey : 'user-1' , country : 'US' } ,
195+ logger : getNoopRulesLogger ( )
196+ } )
197+ ) . toMatchObject ( { value : true , errorCode : undefined } ) ;
198+ } ) ;
199+
200+ // TODO(FFL-2837): Replace this legacy JSON compatibility test with a
201+ // generated protobuf fixture after a flagging-core release contains
202+ // DataDog/openfeature-js-client#344 at or after `be0d886`.
203+ it ( 'keeps supported known data when an unknown field is present' , ( ) => {
204+ const source = buildRulesConfiguration ( ) ;
205+ ( source . flags [ 'dynamic-flag' ] as typeof source . flags [ 'dynamic-flag' ] & {
206+ futureField : string ;
207+ } ) . futureField = 'ignored' ;
208+
209+ const prepared = prepareRulesConfiguration ( source ) ;
210+
211+ expect ( prepared . status ) . toBe ( 'ready' ) ;
212+ if ( prepared . status !== 'ready' ) {
213+ throw new Error ( prepared . errorMessage ) ;
214+ }
215+ expect (
216+ flaggingCoreRulesEngine . evaluate ( {
217+ configuration : prepared . configuration ,
218+ type : 'boolean' ,
219+ flagKey : 'dynamic-flag' ,
220+ defaultValue : false ,
221+ context : { targetingKey : 'user-1' , country : 'US' } ,
222+ logger : getNoopRulesLogger ( )
223+ } )
224+ ) . toMatchObject ( { value : true , errorCode : undefined } ) ;
148225 } ) ;
149226
150227 it ( 'normalizes a real flagging-core evaluation' , ( ) => {
0 commit comments