Skip to content

Commit ac8c4d1

Browse files
authored
Fb/custom validator with scopemap (#13)
* cds 7 changes * tests for custom validator with scopeMap
1 parent 5666a0f commit ac8c4d1

File tree

5 files changed

+26
-11
lines changed

5 files changed

+26
-11
lines changed

example-cap-server/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
},
88
"dependencies": {
99
"@cap-js-community/feature-toggle-library": "file:../",
10-
"@sap/cds": "^6.8.4",
10+
"@sap/cds": "^7.0.0",
1111
"express": "^4.18.2"
1212
}
1313
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
@protocol: 'rest'
22
@impl: './../handler/check-service.js'
3+
@path: '/check'
34
service CheckService {
45
function priority() returns String;
56
}

example-cap-server/srv/service/feature-service.cds

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@protocol: 'rest'
22
@impl: './../handler/feature-service.js'
33
@(requires: 'authenticated-user')
4+
@path: '/feature'
45
// NOTE: in practice this needs proper security restrictions
56
service FeatureService {
67
type JSON {};

src/featureToggles.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ class FeatureToggles {
364364
validators.map(async (validator) => {
365365
const validatorName = validator.name || "anonymous";
366366
try {
367-
const validationErrorOrErrors = (await validator(value, scopeKey)) || [];
367+
const validationErrorOrErrors = (await validator(value, scopeMap, scopeKey)) || [];
368368
const validationErrors = Array.isArray(validationErrorOrErrors)
369369
? validationErrorOrErrors
370370
: [validationErrorOrErrors];
@@ -1251,9 +1251,11 @@ class FeatureToggles {
12511251
*
12521252
* The validator gets the new value and can do any number of checks on it. Returning anything falsy, like undefined,
12531253
* means the new value passes validation, otherwise the validator must return either a single {@link ValidationError},
1254-
* or a list of ValidationErrors.
1254+
* or a list of ValidationErrors. The validator will receive either no scoping information or both the scopeMap and
1255+
* scopeKey for reference.
12551256
*
12561257
* @param {boolean | number | string} newValue
1258+
* @param {Map<string, string>} [scopeMap] optional scopeMap for reference
12571259
* @param {string} [scopeKey] optional scopeKey for reference
12581260
* @returns {undefined | ValidationError | Array<ValidationError>} in case of failure a ValidationError, or an array
12591261
* of ValidationErrors, otherwise undefined

test/featureToggles.test.js

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -708,14 +708,25 @@ describe("feature toggles test", () => {
708708

709709
// NOTE: we get called twice here once for upstream to redis and once downstream from redis
710710
expect(validator).toHaveBeenCalledTimes(2);
711-
expect(validator).toHaveBeenNthCalledWith(1, newValue, SCOPE_ROOT_KEY);
712-
expect(validator).toHaveBeenNthCalledWith(2, newValue, SCOPE_ROOT_KEY);
711+
expect(validator).toHaveBeenNthCalledWith(1, newValue, undefined, SCOPE_ROOT_KEY);
712+
expect(validator).toHaveBeenNthCalledWith(2, newValue, undefined, SCOPE_ROOT_KEY);
713+
714+
// with scopes
715+
validator.mockClear();
716+
const testScopeMap = { domain: "value " };
717+
const testScopeKey = FeatureToggles.getScopeKey(testScopeMap);
718+
expect(await featureToggles.changeFeatureValue(FEATURE.B, 102, testScopeMap)).toBeUndefined();
719+
expect(await featureToggles.changeFeatureValue(FEATURE.C, newValue, testScopeMap)).toBeUndefined();
720+
721+
expect(validator).toHaveBeenCalledTimes(2);
722+
expect(validator).toHaveBeenNthCalledWith(1, newValue, testScopeMap, testScopeKey);
723+
expect(validator).toHaveBeenNthCalledWith(2, newValue, testScopeMap, testScopeKey);
713724

714725
// right toggle but failing
715726
validator.mockClear();
716727
const mockErrorMessage = "wrong input";
717728
validator.mockResolvedValueOnce({ errorMessage: mockErrorMessage });
718-
expect(await featureToggles.changeFeatureValue(FEATURE.B, 102)).toBeUndefined();
729+
expect(await featureToggles.changeFeatureValue(FEATURE.B, 103)).toBeUndefined();
719730
expect(await featureToggles.changeFeatureValue(FEATURE.C, newValue)).toMatchInlineSnapshot(`
720731
[
721732
{
@@ -726,7 +737,7 @@ describe("feature toggles test", () => {
726737
]
727738
`);
728739
expect(validator).toHaveBeenCalledTimes(1);
729-
expect(validator).toHaveBeenCalledWith(newValue, SCOPE_ROOT_KEY);
740+
expect(validator).toHaveBeenCalledWith(newValue, undefined, SCOPE_ROOT_KEY);
730741

731742
// right toggle but failing with messageValues
732743
validator.mockClear();
@@ -736,7 +747,7 @@ describe("feature toggles test", () => {
736747
errorMessage: mockErrorMessageWithValues,
737748
errorMessageValues: mockErrorMessageValues,
738749
});
739-
expect(await featureToggles.changeFeatureValue(FEATURE.B, 102)).toBeUndefined();
750+
expect(await featureToggles.changeFeatureValue(FEATURE.B, 104)).toBeUndefined();
740751
expect(await featureToggles.changeFeatureValue(FEATURE.C, newValue)).toMatchInlineSnapshot(`
741752
[
742753
{
@@ -751,7 +762,7 @@ describe("feature toggles test", () => {
751762
]
752763
`);
753764
expect(validator).toHaveBeenCalledTimes(1);
754-
expect(validator).toHaveBeenCalledWith(newValue, SCOPE_ROOT_KEY);
765+
expect(validator).toHaveBeenCalledWith(newValue, undefined, SCOPE_ROOT_KEY);
755766

756767
// right toggle but failing with multiple errors
757768
validator.mockClear();
@@ -768,7 +779,7 @@ describe("feature toggles test", () => {
768779
errorMessageValues: mockErrorMessageValues,
769780
},
770781
]);
771-
expect(await featureToggles.changeFeatureValue(FEATURE.B, 102)).toBeUndefined();
782+
expect(await featureToggles.changeFeatureValue(FEATURE.B, 105)).toBeUndefined();
772783
expect(await featureToggles.changeFeatureValue(FEATURE.C, newValue)).toMatchInlineSnapshot(`
773784
[
774785
{
@@ -788,7 +799,7 @@ describe("feature toggles test", () => {
788799
]
789800
`);
790801
expect(validator).toHaveBeenCalledTimes(1);
791-
expect(validator).toHaveBeenCalledWith(newValue, SCOPE_ROOT_KEY);
802+
expect(validator).toHaveBeenCalledWith(newValue, undefined, SCOPE_ROOT_KEY);
792803

793804
expect(loggerSpy.warning).not.toHaveBeenCalled();
794805
expect(loggerSpy.error).not.toHaveBeenCalled();

0 commit comments

Comments
 (0)