@featurevisor/sdk 0.47.5 → 0.47.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintcache +1 -1
- package/CHANGELOG.md +16 -0
- package/coverage/clover.xml +331 -331
- package/coverage/coverage-final.json +8 -8
- package/coverage/lcov-report/bucket.ts.html +4 -4
- package/coverage/lcov-report/conditions.ts.html +11 -11
- package/coverage/lcov-report/datafileReader.ts.html +17 -17
- package/coverage/lcov-report/emitter.ts.html +11 -11
- package/coverage/lcov-report/feature.ts.html +41 -41
- package/coverage/lcov-report/index.html +32 -32
- package/coverage/lcov-report/instance.ts.html +358 -358
- package/coverage/lcov-report/logger.ts.html +13 -13
- package/coverage/lcov-report/segments.ts.html +15 -15
- package/coverage/lcov.info +549 -549
- package/dist/index.js.gz +0 -0
- package/package.json +2 -2
- package/src/instance.spec.ts +327 -4
package/dist/index.js.gz
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@featurevisor/sdk",
|
|
3
|
-
"version": "0.47.
|
|
3
|
+
"version": "0.47.7",
|
|
4
4
|
"description": "Featurevisor SDK for Node.js and the browser",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "lib/index.js",
|
|
@@ -49,5 +49,5 @@
|
|
|
49
49
|
"compare-versions": "^6.0.0-rc.1",
|
|
50
50
|
"murmurhash": "^2.0.1"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "0995af7e2bea55f101f3b4a6606e471e02ecb021"
|
|
53
53
|
}
|
package/src/instance.spec.ts
CHANGED
|
@@ -45,7 +45,7 @@ describe("sdk: instance", function () {
|
|
|
45
45
|
}, 0);
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
it("should resolve onReady method as Promise", function (done) {
|
|
48
|
+
it("should resolve onReady method as Promise when initialized synchronously", function (done) {
|
|
49
49
|
let readyCount = 0;
|
|
50
50
|
|
|
51
51
|
const sdk = createInstance({
|
|
@@ -71,6 +71,41 @@ describe("sdk: instance", function () {
|
|
|
71
71
|
}, 0);
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
+
it("should resolve onReady method as Promise, when fetching datafile remotely", function (done) {
|
|
75
|
+
let readyCount = 0;
|
|
76
|
+
|
|
77
|
+
const sdk = createInstance({
|
|
78
|
+
datafileUrl: "http://localhost:3000/datafile.json",
|
|
79
|
+
handleDatafileFetch: function () {
|
|
80
|
+
const content: DatafileContent = {
|
|
81
|
+
schemaVersion: "1",
|
|
82
|
+
revision: "1.0",
|
|
83
|
+
features: [],
|
|
84
|
+
attributes: [],
|
|
85
|
+
segments: [],
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return new Promise(function (resolve) {
|
|
89
|
+
setTimeout(function () {
|
|
90
|
+
resolve(content);
|
|
91
|
+
}, 10);
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
onReady: () => {
|
|
95
|
+
readyCount += 1;
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
setTimeout(() => {
|
|
100
|
+
sdk.onReady().then((f) => {
|
|
101
|
+
expect(f.isReady()).toEqual(true);
|
|
102
|
+
expect(readyCount).toEqual(1);
|
|
103
|
+
|
|
104
|
+
done();
|
|
105
|
+
});
|
|
106
|
+
}, 0);
|
|
107
|
+
});
|
|
108
|
+
|
|
74
109
|
it("should configure plain bucketBy", function () {
|
|
75
110
|
let capturedBucketKey = "";
|
|
76
111
|
|
|
@@ -393,6 +428,9 @@ describe("sdk: instance", function () {
|
|
|
393
428
|
test: {
|
|
394
429
|
enabled: true,
|
|
395
430
|
variation: "control",
|
|
431
|
+
variables: {
|
|
432
|
+
color: "red",
|
|
433
|
+
},
|
|
396
434
|
},
|
|
397
435
|
},
|
|
398
436
|
datafileUrl: "http://localhost:3000/datafile.json",
|
|
@@ -436,6 +474,11 @@ describe("sdk: instance", function () {
|
|
|
436
474
|
userId: "123",
|
|
437
475
|
}),
|
|
438
476
|
).toEqual("control");
|
|
477
|
+
expect(
|
|
478
|
+
sdk.getVariable("test", "color", {
|
|
479
|
+
userId: "123",
|
|
480
|
+
}),
|
|
481
|
+
).toEqual("red");
|
|
439
482
|
|
|
440
483
|
setTimeout(function () {
|
|
441
484
|
// still control after fetching datafile
|
|
@@ -463,6 +506,9 @@ describe("sdk: instance", function () {
|
|
|
463
506
|
test: {
|
|
464
507
|
enabled: true,
|
|
465
508
|
variation: "control",
|
|
509
|
+
variables: {
|
|
510
|
+
color: "red",
|
|
511
|
+
},
|
|
466
512
|
},
|
|
467
513
|
},
|
|
468
514
|
datafileUrl: "http://localhost:3000/datafile.json",
|
|
@@ -506,6 +552,11 @@ describe("sdk: instance", function () {
|
|
|
506
552
|
userId: "123",
|
|
507
553
|
}),
|
|
508
554
|
).toEqual("control");
|
|
555
|
+
expect(
|
|
556
|
+
sdk.getVariable("test", "color", {
|
|
557
|
+
userId: "123",
|
|
558
|
+
}),
|
|
559
|
+
).toEqual("red");
|
|
509
560
|
|
|
510
561
|
setTimeout(function () {
|
|
511
562
|
// treatment after fetching datafile
|
|
@@ -765,6 +816,166 @@ describe("sdk: instance", function () {
|
|
|
765
816
|
expect(deprecatedCount).toEqual(1);
|
|
766
817
|
});
|
|
767
818
|
|
|
819
|
+
it("should check if enabled for overridden flags from rules", function () {
|
|
820
|
+
const sdk = createInstance({
|
|
821
|
+
datafile: {
|
|
822
|
+
schemaVersion: "1",
|
|
823
|
+
revision: "1.0",
|
|
824
|
+
features: [
|
|
825
|
+
{
|
|
826
|
+
key: "test",
|
|
827
|
+
bucketBy: "userId",
|
|
828
|
+
traffic: [
|
|
829
|
+
{
|
|
830
|
+
key: "2",
|
|
831
|
+
segments: ["netherlands"],
|
|
832
|
+
percentage: 100000,
|
|
833
|
+
enabled: false,
|
|
834
|
+
allocation: [],
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
key: "1",
|
|
838
|
+
segments: "*",
|
|
839
|
+
percentage: 100000,
|
|
840
|
+
allocation: [],
|
|
841
|
+
},
|
|
842
|
+
],
|
|
843
|
+
},
|
|
844
|
+
],
|
|
845
|
+
attributes: [],
|
|
846
|
+
segments: [
|
|
847
|
+
{
|
|
848
|
+
key: "netherlands",
|
|
849
|
+
conditions: JSON.stringify([
|
|
850
|
+
{
|
|
851
|
+
attribute: "country",
|
|
852
|
+
operator: "equals",
|
|
853
|
+
value: "nl",
|
|
854
|
+
},
|
|
855
|
+
]),
|
|
856
|
+
},
|
|
857
|
+
],
|
|
858
|
+
},
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
expect(sdk.isEnabled("test", { userId: "user-123", country: "de" })).toEqual(true);
|
|
862
|
+
expect(sdk.isEnabled("test", { userId: "user-123", country: "nl" })).toEqual(false);
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
it("should check if enabled for mutually exclusive features", function () {
|
|
866
|
+
let bucketValue = 10000;
|
|
867
|
+
|
|
868
|
+
const sdk = createInstance({
|
|
869
|
+
configureBucketValue: function () {
|
|
870
|
+
return bucketValue;
|
|
871
|
+
},
|
|
872
|
+
|
|
873
|
+
datafile: {
|
|
874
|
+
schemaVersion: "1",
|
|
875
|
+
revision: "1.0",
|
|
876
|
+
features: [
|
|
877
|
+
{
|
|
878
|
+
key: "mutex",
|
|
879
|
+
bucketBy: "userId",
|
|
880
|
+
ranges: [[0, 50000]],
|
|
881
|
+
traffic: [{ key: "1", segments: "*", percentage: 50000, allocation: [] }],
|
|
882
|
+
},
|
|
883
|
+
],
|
|
884
|
+
attributes: [],
|
|
885
|
+
segments: [],
|
|
886
|
+
},
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
expect(sdk.isEnabled("test")).toEqual(false);
|
|
890
|
+
expect(sdk.isEnabled("test", { userId: "123" })).toEqual(false);
|
|
891
|
+
|
|
892
|
+
bucketValue = 40000;
|
|
893
|
+
expect(sdk.isEnabled("mutex", { userId: "123" })).toEqual(true);
|
|
894
|
+
|
|
895
|
+
bucketValue = 60000;
|
|
896
|
+
expect(sdk.isEnabled("mutex", { userId: "123" })).toEqual(false);
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
it("should get variation", function () {
|
|
900
|
+
const sdk = createInstance({
|
|
901
|
+
datafile: {
|
|
902
|
+
schemaVersion: "1",
|
|
903
|
+
revision: "1.0",
|
|
904
|
+
features: [
|
|
905
|
+
{
|
|
906
|
+
key: "test",
|
|
907
|
+
bucketBy: "userId",
|
|
908
|
+
variations: [{ value: "control" }, { value: "treatment" }],
|
|
909
|
+
force: [
|
|
910
|
+
{
|
|
911
|
+
conditions: [{ attribute: "userId", operator: "equals", value: "user-gb" }],
|
|
912
|
+
enabled: false,
|
|
913
|
+
},
|
|
914
|
+
{
|
|
915
|
+
segments: ["netherlands"],
|
|
916
|
+
enabled: false,
|
|
917
|
+
},
|
|
918
|
+
],
|
|
919
|
+
traffic: [
|
|
920
|
+
{
|
|
921
|
+
key: "1",
|
|
922
|
+
segments: "*",
|
|
923
|
+
percentage: 100000,
|
|
924
|
+
allocation: [
|
|
925
|
+
{ variation: "control", range: [0, 0] },
|
|
926
|
+
{ variation: "treatment", range: [0, 100000] },
|
|
927
|
+
],
|
|
928
|
+
},
|
|
929
|
+
],
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
key: "testWithNoVariation",
|
|
933
|
+
bucketBy: "userId",
|
|
934
|
+
traffic: [
|
|
935
|
+
{
|
|
936
|
+
key: "1",
|
|
937
|
+
segments: "*",
|
|
938
|
+
percentage: 100000,
|
|
939
|
+
allocation: [],
|
|
940
|
+
},
|
|
941
|
+
],
|
|
942
|
+
},
|
|
943
|
+
],
|
|
944
|
+
attributes: [],
|
|
945
|
+
segments: [
|
|
946
|
+
{
|
|
947
|
+
key: "netherlands",
|
|
948
|
+
conditions: JSON.stringify([
|
|
949
|
+
{
|
|
950
|
+
attribute: "country",
|
|
951
|
+
operator: "equals",
|
|
952
|
+
value: "nl",
|
|
953
|
+
},
|
|
954
|
+
]),
|
|
955
|
+
},
|
|
956
|
+
],
|
|
957
|
+
},
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
const context = {
|
|
961
|
+
userId: "123",
|
|
962
|
+
};
|
|
963
|
+
|
|
964
|
+
expect(sdk.getVariation("test", context)).toEqual("treatment");
|
|
965
|
+
expect(sdk.getVariation("test", { userId: "user-ch" })).toEqual("treatment");
|
|
966
|
+
|
|
967
|
+
// non existing
|
|
968
|
+
expect(sdk.getVariation("nonExistingFeature", context)).toEqual(undefined);
|
|
969
|
+
|
|
970
|
+
// disabled
|
|
971
|
+
expect(sdk.getVariation("test", { userId: "user-gb" })).toEqual(undefined);
|
|
972
|
+
expect(sdk.getVariation("test", { userId: "user-gb" })).toEqual(undefined);
|
|
973
|
+
expect(sdk.getVariation("test", { userId: "123", country: "nl" })).toEqual(undefined);
|
|
974
|
+
|
|
975
|
+
// no variation
|
|
976
|
+
expect(sdk.getVariation("testWithNoVariation", context)).toEqual(undefined);
|
|
977
|
+
});
|
|
978
|
+
|
|
768
979
|
it("should get variable", function () {
|
|
769
980
|
const sdk = createInstance({
|
|
770
981
|
datafile: {
|
|
@@ -790,6 +1001,11 @@ describe("sdk: instance", function () {
|
|
|
790
1001
|
type: "integer",
|
|
791
1002
|
defaultValue: 0,
|
|
792
1003
|
},
|
|
1004
|
+
{
|
|
1005
|
+
key: "price",
|
|
1006
|
+
type: "double",
|
|
1007
|
+
defaultValue: 9.99,
|
|
1008
|
+
},
|
|
793
1009
|
{
|
|
794
1010
|
key: "paymentMethods",
|
|
795
1011
|
type: "array",
|
|
@@ -820,25 +1036,101 @@ describe("sdk: instance", function () {
|
|
|
820
1036
|
{
|
|
821
1037
|
key: "showSidebar",
|
|
822
1038
|
value: true,
|
|
1039
|
+
overrides: [
|
|
1040
|
+
{
|
|
1041
|
+
segments: ["netherlands"],
|
|
1042
|
+
value: false,
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
conditions: [
|
|
1046
|
+
{
|
|
1047
|
+
attribute: "country",
|
|
1048
|
+
operator: "equals",
|
|
1049
|
+
value: "de",
|
|
1050
|
+
},
|
|
1051
|
+
],
|
|
1052
|
+
value: false,
|
|
1053
|
+
},
|
|
1054
|
+
],
|
|
823
1055
|
},
|
|
824
1056
|
],
|
|
825
1057
|
},
|
|
826
1058
|
],
|
|
1059
|
+
force: [
|
|
1060
|
+
{
|
|
1061
|
+
conditions: [{ attribute: "userId", operator: "equals", value: "user-ch" }],
|
|
1062
|
+
enabled: true,
|
|
1063
|
+
variation: "control",
|
|
1064
|
+
variables: {
|
|
1065
|
+
color: "red and white",
|
|
1066
|
+
},
|
|
1067
|
+
},
|
|
1068
|
+
{
|
|
1069
|
+
conditions: [{ attribute: "userId", operator: "equals", value: "user-gb" }],
|
|
1070
|
+
enabled: false,
|
|
1071
|
+
},
|
|
1072
|
+
],
|
|
827
1073
|
traffic: [
|
|
1074
|
+
// belgium
|
|
1075
|
+
{
|
|
1076
|
+
key: "2",
|
|
1077
|
+
segments: ["belgium"],
|
|
1078
|
+
percentage: 100000,
|
|
1079
|
+
allocation: [
|
|
1080
|
+
{ variation: "control", range: [0, 0] },
|
|
1081
|
+
{
|
|
1082
|
+
variation: "treatment",
|
|
1083
|
+
range: [0, 100000],
|
|
1084
|
+
},
|
|
1085
|
+
],
|
|
1086
|
+
variation: "control",
|
|
1087
|
+
variables: {
|
|
1088
|
+
color: "black",
|
|
1089
|
+
},
|
|
1090
|
+
},
|
|
1091
|
+
|
|
1092
|
+
// everyone
|
|
828
1093
|
{
|
|
829
1094
|
key: "1",
|
|
830
1095
|
segments: "*",
|
|
831
1096
|
percentage: 100000,
|
|
832
1097
|
allocation: [
|
|
833
1098
|
{ variation: "control", range: [0, 0] },
|
|
834
|
-
{
|
|
1099
|
+
{
|
|
1100
|
+
variation: "treatment",
|
|
1101
|
+
range: [0, 100000],
|
|
1102
|
+
},
|
|
835
1103
|
],
|
|
836
1104
|
},
|
|
837
1105
|
],
|
|
838
1106
|
},
|
|
839
1107
|
],
|
|
840
|
-
attributes: [
|
|
841
|
-
|
|
1108
|
+
attributes: [
|
|
1109
|
+
{ key: "userId", type: "string", capture: true },
|
|
1110
|
+
{ key: "country", type: "string" },
|
|
1111
|
+
],
|
|
1112
|
+
segments: [
|
|
1113
|
+
{
|
|
1114
|
+
key: "netherlands",
|
|
1115
|
+
conditions: JSON.stringify([
|
|
1116
|
+
{
|
|
1117
|
+
attribute: "country",
|
|
1118
|
+
operator: "equals",
|
|
1119
|
+
value: "nl",
|
|
1120
|
+
},
|
|
1121
|
+
]),
|
|
1122
|
+
},
|
|
1123
|
+
{
|
|
1124
|
+
key: "belgium",
|
|
1125
|
+
conditions: JSON.stringify([
|
|
1126
|
+
{
|
|
1127
|
+
attribute: "country",
|
|
1128
|
+
operator: "equals",
|
|
1129
|
+
value: "be",
|
|
1130
|
+
},
|
|
1131
|
+
]),
|
|
1132
|
+
},
|
|
1133
|
+
],
|
|
842
1134
|
},
|
|
843
1135
|
});
|
|
844
1136
|
|
|
@@ -847,16 +1139,40 @@ describe("sdk: instance", function () {
|
|
|
847
1139
|
};
|
|
848
1140
|
|
|
849
1141
|
expect(sdk.getVariation("test", context)).toEqual("treatment");
|
|
1142
|
+
expect(
|
|
1143
|
+
sdk.getVariation("test", {
|
|
1144
|
+
...context,
|
|
1145
|
+
country: "be",
|
|
1146
|
+
}),
|
|
1147
|
+
).toEqual("control");
|
|
1148
|
+
expect(sdk.getVariation("test", { userId: "user-ch" })).toEqual("control");
|
|
850
1149
|
|
|
851
1150
|
expect(sdk.getVariable("test", "color", context)).toEqual("red");
|
|
852
1151
|
expect(sdk.getVariableString("test", "color", context)).toEqual("red");
|
|
1152
|
+
expect(sdk.getVariable("test", "color", { ...context, country: "be" })).toEqual("black");
|
|
1153
|
+
expect(sdk.getVariable("test", "color", { userId: "user-ch" })).toEqual("red and white");
|
|
853
1154
|
|
|
854
1155
|
expect(sdk.getVariable("test", "showSidebar", context)).toEqual(true);
|
|
855
1156
|
expect(sdk.getVariableBoolean("test", "showSidebar", context)).toEqual(true);
|
|
1157
|
+
expect(
|
|
1158
|
+
sdk.getVariableBoolean("test", "showSidebar", {
|
|
1159
|
+
...context,
|
|
1160
|
+
country: "nl",
|
|
1161
|
+
}),
|
|
1162
|
+
).toEqual(false);
|
|
1163
|
+
expect(
|
|
1164
|
+
sdk.getVariableBoolean("test", "showSidebar", {
|
|
1165
|
+
...context,
|
|
1166
|
+
country: "de",
|
|
1167
|
+
}),
|
|
1168
|
+
).toEqual(false);
|
|
856
1169
|
|
|
857
1170
|
expect(sdk.getVariable("test", "count", context)).toEqual(0);
|
|
858
1171
|
expect(sdk.getVariableInteger("test", "count", context)).toEqual(0);
|
|
859
1172
|
|
|
1173
|
+
expect(sdk.getVariable("test", "price", context)).toEqual(9.99);
|
|
1174
|
+
expect(sdk.getVariableDouble("test", "price", context)).toEqual(9.99);
|
|
1175
|
+
|
|
860
1176
|
expect(sdk.getVariable("test", "paymentMethods", context)).toEqual(["paypal", "creditcard"]);
|
|
861
1177
|
expect(sdk.getVariableArray("test", "paymentMethods", context)).toEqual([
|
|
862
1178
|
"paypal",
|
|
@@ -880,5 +1196,12 @@ describe("sdk: instance", function () {
|
|
|
880
1196
|
nested: "value",
|
|
881
1197
|
},
|
|
882
1198
|
});
|
|
1199
|
+
|
|
1200
|
+
// non existing
|
|
1201
|
+
expect(sdk.getVariable("test", "nonExisting", context)).toEqual(undefined);
|
|
1202
|
+
expect(sdk.getVariable("nonExistingFeature", "nonExisting", context)).toEqual(undefined);
|
|
1203
|
+
|
|
1204
|
+
// disabled
|
|
1205
|
+
expect(sdk.getVariable("test", "color", { userId: "user-gb" })).toEqual(undefined);
|
|
883
1206
|
});
|
|
884
1207
|
});
|