Skip to content

Commit 6d39f15

Browse files
committed
demo null value defaulting
Signed-off-by: Todd Baert <[email protected]>
1 parent c3c3d01 commit 6d39f15

File tree

5 files changed

+49
-12
lines changed

5 files changed

+49
-12
lines changed

libs/providers/ofrep-web/src/lib/ofrep-web-provider.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,14 @@ export class OFREPWebProvider implements Provider {
299299
};
300300
}
301301

302+
if (resolved.value === undefined || resolved.value === null) {
303+
return {
304+
value: defaultValue,
305+
flagMetadata: resolved.flagMetadata,
306+
reason: resolved.reason || StandardResolutionReasons.DEFAULT,
307+
};
308+
}
309+
302310
if (typeof resolved.value !== type) {
303311
return {
304312
value: defaultValue,

libs/providers/ofrep/src/lib/ofrep-provider.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ describe('OFREPProvider should', () => {
6060
);
6161
});
6262

63+
it.each([true, false])('returns default if value is null', async (defaultValue) => {
64+
await expect(provider.resolveBooleanEvaluation('my-null-value-flag', defaultValue, {})).resolves.toStrictEqual(
65+
expect.objectContaining({
66+
value: defaultValue,
67+
reason: 'DEFAULT',
68+
flagMetadata: expect.objectContaining(TEST_FLAG_METADATA),
69+
}),
70+
);
71+
});
72+
6373
it('throw OFREPApiUnauthorizedError on HTTP 401', async () => {
6474
await expect(provider.resolveBooleanEvaluation('my-flag', false, { expectedAuthHeader: 'secret' })).rejects.toThrow(
6575
OFREPApiUnauthorizedError,

libs/providers/ofrep/src/lib/ofrep-provider.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,11 @@ export class OFREPProvider implements Provider {
9494
return handleEvaluationError(result, defaultValue);
9595
}
9696

97-
if (typeof result.value.value !== typeof defaultValue) {
97+
if (
98+
result.value.value !== undefined &&
99+
result.value.value !== null &&
100+
typeof result.value.value !== typeof defaultValue
101+
) {
98102
return {
99103
value: defaultValue,
100104
reason: StandardResolutionReasons.ERROR,
@@ -104,6 +108,6 @@ export class OFREPProvider implements Provider {
104108
};
105109
}
106110

107-
return toResolutionDetails(result.value);
111+
return toResolutionDetails(result.value, defaultValue);
108112
}
109113
}

libs/shared/ofrep-core/src/lib/api/ofrep-api.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,22 @@ export function handleEvaluationError<T>(
191191

192192
export function toResolutionDetails<T extends EvaluationFlagValue>(
193193
result: EvaluationSuccessResponse,
194+
defaultValue: T,
194195
): ResolutionDetails<T> {
195-
return {
196-
value: result.value as T,
197-
variant: result.variant,
198-
reason: result.reason,
199-
flagMetadata: result.metadata && toFlagMetadata(result.metadata),
200-
};
196+
if (result.value === undefined || result.value === null) {
197+
return {
198+
value: defaultValue,
199+
reason: result.reason || StandardResolutionReasons.DEFAULT,
200+
flagMetadata: result.metadata && toFlagMetadata(result.metadata),
201+
};
202+
} else {
203+
return {
204+
value: result.value as T,
205+
variant: result.variant,
206+
reason: result.reason,
207+
flagMetadata: result.metadata && toFlagMetadata(result.metadata),
208+
};
209+
}
201210
}
202211

203212
export function toFlagMetadata(metadata: object): FlagMetadata {

libs/shared/ofrep-core/src/test/handlers.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,20 @@ export const handlers = [
121121
}
122122

123123
const scopeValue = new URL(info.request.url).searchParams.get('scope');
124+
const key = info.params.key;
125+
const reason = key.includes('null-value')
126+
? StandardResolutionReasons.DEFAULT
127+
: requestBody.context?.targetingKey
128+
? StandardResolutionReasons.TARGETING_MATCH
129+
: StandardResolutionReasons.STATIC;
130+
131+
const value = key.includes('null-value') ? null : true;
124132

125133
return HttpResponse.json<EvaluationResponse>({
126134
key: info.params.key,
127-
reason: requestBody.context?.targetingKey
128-
? StandardResolutionReasons.TARGETING_MATCH
129-
: StandardResolutionReasons.STATIC,
135+
reason,
130136
variant: scopeValue ? 'scoped' : 'default',
131-
value: true,
137+
value,
132138
metadata: TEST_FLAG_METADATA,
133139
});
134140
},

0 commit comments

Comments
 (0)