@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/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.5",
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": "150079539789fe0b61fa78dd9337788a4c176cb2"
52
+ "gitHead": "0995af7e2bea55f101f3b4a6606e471e02ecb021"
53
53
  }
@@ -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
- { variation: "treatment", range: [0, 100000] },
1099
+ {
1100
+ variation: "treatment",
1101
+ range: [0, 100000],
1102
+ },
835
1103
  ],
836
1104
  },
837
1105
  ],
838
1106
  },
839
1107
  ],
840
- attributes: [],
841
- segments: [],
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
  });