66 StandardResolutionReasons ,
77 ProviderEvents ,
88 ProviderStatus ,
9+ ErrorCode ,
910} from '@openfeature/server-sdk' ;
1011import { Flagsmith , Flags , BaseFlag } from 'flagsmith-nodejs' ;
1112import { FlagsmithProviderError } from './exceptions' ;
@@ -157,11 +158,18 @@ describe('FlagsmithOpenFeatureProvider', () => {
157158 expect ( result . reason ) . toBe ( StandardResolutionReasons . DISABLED ) ;
158159 } ) ;
159160
160- it ( 'should throw TypeMismatchError when flag value type does not match requested type' , async ( ) => {
161+ it ( 'should return default value with error details when flag value type does not match requested type' , async ( ) => {
161162 mockFlags . getFlag . mockReturnValue ( mockFlagData . jsonValidFlag ) ;
162- await expect (
163- useBooleanConfigProvider . resolveBooleanEvaluation ( 'disabled-flag' , false , evaluationContext , loggerMock ) ,
164- ) . rejects . toThrow ( TypeMismatchError ) ;
163+ const result = await useBooleanConfigProvider . resolveBooleanEvaluation (
164+ 'disabled-flag' ,
165+ false ,
166+ evaluationContext ,
167+ loggerMock ,
168+ ) ;
169+ expect ( result . value ) . toBe ( false ) ;
170+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
171+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
172+ expect ( result . errorMessage ) . toContain ( 'is not of type boolean' ) ;
165173 } ) ;
166174
167175 describe ( 'useFlagsmithDefaults' , ( ) => {
@@ -330,16 +338,23 @@ describe('FlagsmithOpenFeatureProvider', () => {
330338 ) . rejects . toThrow ( FlagsmithProviderError ) ;
331339 } ) ;
332340
333- it ( 'should throw TypeMismatchError when flag value type does not match requested type' , async ( ) => {
341+ it ( 'should return default value with error details when flag value type does not match requested type' , async ( ) => {
334342 const booleanConfigProvider = new FlagsmithOpenFeatureProvider ( mockFlagsmith , {
335343 returnValueForDisabledFlags : false ,
336344 useFlagsmithDefaults : false ,
337345 useBooleanConfigValue : true ,
338346 } ) ;
339347 mockFlags . getFlag . mockReturnValue ( mockFlagData . stringFlag ) ;
340- await expect (
341- booleanConfigProvider . resolveBooleanEvaluation ( 'test-flag' , false , evaluationContext , loggerMock ) ,
342- ) . rejects . toThrow ( TypeMismatchError ) ;
348+ const result = await booleanConfigProvider . resolveBooleanEvaluation (
349+ 'test-flag' ,
350+ false ,
351+ evaluationContext ,
352+ loggerMock ,
353+ ) ;
354+ expect ( result . value ) . toBe ( false ) ;
355+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
356+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
357+ expect ( result . errorMessage ) . toContain ( 'is not of type boolean' ) ;
343358 } ) ;
344359
345360 it ( 'should return false when flag value is numeric 0' , async ( ) => {
@@ -400,15 +415,22 @@ describe('FlagsmithOpenFeatureProvider', () => {
400415 ) . rejects . toThrow ( FlagsmithProviderError ) ;
401416 } ) ;
402417
403- it ( 'should throw TypeMismatchError when flag value is undefined' , async ( ) => {
418+ it ( 'should return default value with error details when flag value is undefined' , async ( ) => {
404419 mockFlags . getFlag . mockReturnValue ( {
405420 enabled : true ,
406421 value : undefined ,
407422 isDefault : false ,
408423 } as BaseFlag ) ;
409- await expect (
410- defaultProvider . resolveStringEvaluation ( 'test-flag' , '' , evaluationContext , loggerMock ) ,
411- ) . rejects . toThrow ( TypeMismatchError ) ;
424+ const result = await defaultProvider . resolveStringEvaluation (
425+ 'test-flag' ,
426+ 'default-string' ,
427+ evaluationContext ,
428+ loggerMock ,
429+ ) ;
430+ expect ( result . value ) . toBe ( 'default-string' ) ;
431+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
432+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
433+ expect ( result . errorMessage ) . toContain ( 'is not of type string' ) ;
412434 } ) ;
413435
414436 it ( 'should return a string when flag value is number' , async ( ) => {
@@ -434,22 +456,26 @@ describe('FlagsmithOpenFeatureProvider', () => {
434456 expect ( result . reason ) . toBe ( StandardResolutionReasons . TARGETING_MATCH ) ;
435457 } ) ;
436458
437- it ( 'should return a number when flag value is a number as string ' , async ( ) => {
459+ it ( 'should return default value with error details when flag value is not a valid number ' , async ( ) => {
438460 mockFlags . getFlag . mockReturnValue ( mockFlagData . stringFlag ) ;
439- await expect (
440- defaultProvider . resolveNumberEvaluation ( 'test-flag' , 0 , evaluationContext , loggerMock ) ,
441- ) . rejects . toThrow ( TypeMismatchError ) ;
461+ const result = await defaultProvider . resolveNumberEvaluation ( 'test-flag' , 42 , evaluationContext , loggerMock ) ;
462+ expect ( result . value ) . toBe ( 42 ) ;
463+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
464+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
465+ expect ( result . errorMessage ) . toContain ( 'is not of type number' ) ;
442466 } ) ;
443467
444- it ( 'should throw TypeMismatchError when flag value is undefined ' , async ( ) => {
468+ it ( 'should return default value with error details when flag value is not a valid number string ' , async ( ) => {
445469 mockFlags . getFlag . mockReturnValue ( {
446470 enabled : true ,
447471 value : 'not-a-number' ,
448472 isDefault : false ,
449473 } ) ;
450- await expect (
451- defaultProvider . resolveNumberEvaluation ( 'test-flag' , 0 , evaluationContext , loggerMock ) ,
452- ) . rejects . toThrow ( TypeMismatchError ) ;
474+ const result = await defaultProvider . resolveNumberEvaluation ( 'test-flag' , 99 , evaluationContext , loggerMock ) ;
475+ expect ( result . value ) . toBe ( 99 ) ;
476+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
477+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
478+ expect ( result . errorMessage ) . toContain ( 'is not of type number' ) ;
453479 } ) ;
454480
455481 it ( 'should return a number when flag value is a string with whitespace' , async ( ) => {
@@ -472,22 +498,38 @@ describe('FlagsmithOpenFeatureProvider', () => {
472498 expect ( result . reason ) . toBe ( StandardResolutionReasons . TARGETING_MATCH ) ;
473499 } ) ;
474500
475- it ( 'should throw TypeMismatchError when flag value is invalid JSON' , async ( ) => {
501+ it ( 'should return default value with error details when flag value is invalid JSON' , async ( ) => {
476502 mockFlags . getFlag . mockReturnValue ( mockFlagData . jsonInvalidFlag ) ;
477- await expect (
478- defaultProvider . resolveObjectEvaluation ( 'test-flag' , { } , evaluationContext , loggerMock ) ,
479- ) . rejects . toThrow ( TypeMismatchError ) ;
503+ const defaultObj = { default : true } ;
504+ const result = await defaultProvider . resolveObjectEvaluation (
505+ 'test-flag' ,
506+ defaultObj ,
507+ evaluationContext ,
508+ loggerMock ,
509+ ) ;
510+ expect ( result . value ) . toEqual ( defaultObj ) ;
511+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
512+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
513+ expect ( result . errorMessage ) . toContain ( 'is not of type object' ) ;
480514 } ) ;
481515
482- it ( 'should throw TypeMismatchError when flag value is undefined' , async ( ) => {
516+ it ( 'should return default value with error details when flag value is undefined' , async ( ) => {
483517 mockFlags . getFlag . mockReturnValue ( {
484518 enabled : true ,
485519 value : undefined ,
486520 isDefault : false ,
487521 } as BaseFlag ) ;
488- await expect (
489- defaultProvider . resolveObjectEvaluation ( 'test-flag' , { } , evaluationContext , loggerMock ) ,
490- ) . rejects . toThrow ( TypeMismatchError ) ;
522+ const defaultObj = { fallback : 'value' } ;
523+ const result = await defaultProvider . resolveObjectEvaluation (
524+ 'test-flag' ,
525+ defaultObj ,
526+ evaluationContext ,
527+ loggerMock ,
528+ ) ;
529+ expect ( result . value ) . toEqual ( defaultObj ) ;
530+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
531+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
532+ expect ( result . errorMessage ) . toContain ( 'is not of type object' ) ;
491533 } ) ;
492534 } ) ;
493535
@@ -512,16 +554,18 @@ describe('FlagsmithOpenFeatureProvider', () => {
512554 ) ;
513555 } ) ;
514556
515- it ( 'should throw TypeMismatchError when flag value type does not match requested type' , async ( ) => {
557+ it ( 'should return default value with error details when flag value type does not match requested type' , async ( ) => {
516558 const provider = new FlagsmithOpenFeatureProvider ( mockFlagsmith , {
517559 returnValueForDisabledFlags : false ,
518560 useFlagsmithDefaults : false ,
519561 useBooleanConfigValue : true ,
520562 } ) ;
521563 mockFlags . getFlag . mockReturnValue ( mockFlagData . stringFlag ) ;
522- await expect (
523- provider . resolveBooleanEvaluation ( 'test-flag' , false , evaluationContext , loggerMock ) ,
524- ) . rejects . toThrow ( TypeMismatchError ) ;
564+ const result = await provider . resolveBooleanEvaluation ( 'test-flag' , false , evaluationContext , loggerMock ) ;
565+ expect ( result . value ) . toBe ( false ) ;
566+ expect ( result . reason ) . toBe ( StandardResolutionReasons . ERROR ) ;
567+ expect ( result . errorCode ) . toBe ( ErrorCode . TYPE_MISMATCH ) ;
568+ expect ( result . errorMessage ) . toContain ( 'is not of type boolean' ) ;
525569 } ) ;
526570 } ) ;
527571 } ) ;
0 commit comments