prefab-cloud-ruby 1.8.7 → 1.8.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -238,6 +238,131 @@ class TestCriteriaEvaluator < Minitest::Test
238
238
  assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { email: 'example@hotmail.com' })).unwrapped_value
239
239
  end
240
240
 
241
+ def test_prop_starts_with_one_of
242
+ config = PrefabProto::Config.new(
243
+ key: KEY,
244
+ rows: [
245
+ DEFAULT_ROW,
246
+ PrefabProto::ConfigRow.new(
247
+ project_env_id: PROJECT_ENV_ID,
248
+ values: [
249
+ PrefabProto::ConditionalValue.new(
250
+ criteria: [
251
+ PrefabProto::Criterion.new(
252
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_STARTS_WITH_ONE_OF,
253
+ value_to_match: string_list(['one', 'two']),
254
+ property_name: 'user.testProperty'
255
+ )
256
+ ],
257
+ value: DESIRED_VALUE_CONFIG
258
+ )
259
+ ]
260
+ )
261
+ ]
262
+ )
263
+
264
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
265
+ namespace: nil)
266
+
267
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
268
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'three dogs' })).unwrapped_value
269
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { testProperty: 'one tree' })).unwrapped_value
270
+ end
271
+
272
+ def test_prop_does_not_start_with_one_of
273
+ config = PrefabProto::Config.new(
274
+ key: KEY,
275
+ rows: [
276
+ DEFAULT_ROW,
277
+ PrefabProto::ConfigRow.new(
278
+ project_env_id: PROJECT_ENV_ID,
279
+ values: [
280
+ PrefabProto::ConditionalValue.new(
281
+ criteria: [
282
+ PrefabProto::Criterion.new(
283
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_DOES_NOT_START_WITH_ONE_OF,
284
+ value_to_match: string_list(['one', 'two']),
285
+ property_name: 'user.testProperty'
286
+ )
287
+ ],
288
+ value: DESIRED_VALUE_CONFIG
289
+ )
290
+ ]
291
+ )
292
+ ]
293
+ )
294
+
295
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
296
+ namespace: nil)
297
+
298
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
299
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { testProperty: 'three dogs' })).unwrapped_value
300
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'one tree' })).unwrapped_value
301
+ end
302
+
303
+
304
+ def test_prop_contains_one_of
305
+ config = PrefabProto::Config.new(
306
+ key: KEY,
307
+ rows: [
308
+ DEFAULT_ROW,
309
+ PrefabProto::ConfigRow.new(
310
+ project_env_id: PROJECT_ENV_ID,
311
+ values: [
312
+ PrefabProto::ConditionalValue.new(
313
+ criteria: [
314
+ PrefabProto::Criterion.new(
315
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_CONTAINS_ONE_OF,
316
+ value_to_match: string_list(['one', 'two']),
317
+ property_name: 'user.testProperty'
318
+ )
319
+ ],
320
+ value: DESIRED_VALUE_CONFIG
321
+ )
322
+ ]
323
+ )
324
+ ]
325
+ )
326
+
327
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
328
+ namespace: nil)
329
+
330
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
331
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'three dogs' })).unwrapped_value
332
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { testProperty: 'see one tree' })).unwrapped_value
333
+ end
334
+
335
+ def test_prop_does_not_contain_one_of
336
+ config = PrefabProto::Config.new(
337
+ key: KEY,
338
+ rows: [
339
+ DEFAULT_ROW,
340
+ PrefabProto::ConfigRow.new(
341
+ project_env_id: PROJECT_ENV_ID,
342
+ values: [
343
+ PrefabProto::ConditionalValue.new(
344
+ criteria: [
345
+ PrefabProto::Criterion.new(
346
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_DOES_NOT_CONTAIN_ONE_OF,
347
+ value_to_match: string_list(['one', 'two']),
348
+ property_name: 'user.testProperty'
349
+ )
350
+ ],
351
+ value: DESIRED_VALUE_CONFIG
352
+ )
353
+ ]
354
+ )
355
+ ]
356
+ )
357
+
358
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
359
+ namespace: nil)
360
+
361
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
362
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { testProperty: 'three dogs' })).unwrapped_value
363
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'see one tree' })).unwrapped_value
364
+ end
365
+
241
366
  def test_in_seg
242
367
  segment_key = 'segment_key'
243
368
 
@@ -683,6 +808,266 @@ class TestCriteriaEvaluator < Minitest::Test
683
808
  assert_equal 'ghi', evaluator.evaluate(context).unwrapped_value
684
809
  end
685
810
 
811
+ def test_prop_regex_matches
812
+ config = PrefabProto::Config.new(
813
+ key: KEY,
814
+ rows: [
815
+ DEFAULT_ROW,
816
+ PrefabProto::ConfigRow.new(
817
+ project_env_id: PROJECT_ENV_ID,
818
+ values: [
819
+ PrefabProto::ConditionalValue.new(
820
+ criteria: [
821
+ PrefabProto::Criterion.new(
822
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_MATCHES,
823
+ value_to_match: PrefabProto::ConfigValue.new(string: "a+b+"),
824
+ property_name: 'user.testProperty'
825
+ )
826
+ ],
827
+ value: DESIRED_VALUE_CONFIG
828
+ )
829
+ ]
830
+ )
831
+ ]
832
+ )
833
+
834
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
835
+ namespace: nil)
836
+
837
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
838
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'abc' })).unwrapped_value
839
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { testProperty: 'aabb' })).unwrapped_value
840
+ end
841
+
842
+ def test_prop_regex_does_not_match
843
+ config = PrefabProto::Config.new(
844
+ key: KEY,
845
+ rows: [
846
+ DEFAULT_ROW,
847
+ PrefabProto::ConfigRow.new(
848
+ project_env_id: PROJECT_ENV_ID,
849
+ values: [
850
+ PrefabProto::ConditionalValue.new(
851
+ criteria: [
852
+ PrefabProto::Criterion.new(
853
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_DOES_NOT_MATCH,
854
+ value_to_match: PrefabProto::ConfigValue.new(string: "a+b+"),
855
+ property_name: 'user.testProperty'
856
+ )
857
+ ],
858
+ value: DESIRED_VALUE_CONFIG
859
+ )
860
+ ]
861
+ )
862
+ ]
863
+ )
864
+
865
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
866
+ namespace: nil)
867
+
868
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context({})).unwrapped_value
869
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: { testProperty: 'abc' })).unwrapped_value
870
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'aabb' })).unwrapped_value
871
+ end
872
+
873
+ def test_prop_regex_does_not_match_returns_false_bad_regex
874
+ config = PrefabProto::Config.new(
875
+ key: KEY,
876
+ rows: [
877
+ DEFAULT_ROW,
878
+ PrefabProto::ConfigRow.new(
879
+ project_env_id: PROJECT_ENV_ID,
880
+ values: [
881
+ PrefabProto::ConditionalValue.new(
882
+ criteria: [
883
+ PrefabProto::Criterion.new(
884
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_DOES_NOT_MATCH,
885
+ value_to_match: PrefabProto::ConfigValue.new(string: "[a+b+"),
886
+ property_name: 'user.testProperty'
887
+ )
888
+ ],
889
+ value: DESIRED_VALUE_CONFIG
890
+ )
891
+ ]
892
+ )
893
+ ]
894
+ )
895
+
896
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
897
+ namespace: nil)
898
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
899
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'abc' })).unwrapped_value
900
+
901
+ assert_stderr [ "warning: character class has duplicated range: /^[a+b+$/" ]
902
+ end
903
+
904
+
905
+ def test_prop_regex_match_returns_false_bad_regex
906
+ config = PrefabProto::Config.new(
907
+ key: KEY,
908
+ rows: [
909
+ DEFAULT_ROW,
910
+ PrefabProto::ConfigRow.new(
911
+ project_env_id: PROJECT_ENV_ID,
912
+ values: [
913
+ PrefabProto::ConditionalValue.new(
914
+ criteria: [
915
+ PrefabProto::Criterion.new(
916
+ operator: PrefabProto::Criterion::CriterionOperator::PROP_MATCHES,
917
+ value_to_match: PrefabProto::ConfigValue.new(string: "[a+b+"),
918
+ property_name: 'user.testProperty'
919
+ )
920
+ ],
921
+ value: DESIRED_VALUE_CONFIG
922
+ )
923
+ ]
924
+ )
925
+ ]
926
+ )
927
+
928
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
929
+ namespace: nil)
930
+
931
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
932
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: { testProperty: 'abc' })).unwrapped_value
933
+
934
+ assert_stderr [ "warning: character class has duplicated range: /^[a+b+$/" ]
935
+ end
936
+
937
+ def test_less_than_works
938
+ config = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_LESS_THAN, property_name: 'user.age', value_to_match: 10)
939
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
940
+ namespace: nil)
941
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
942
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 10})).unwrapped_value
943
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 9})).unwrapped_value
944
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 9.5})).unwrapped_value
945
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 10.1})).unwrapped_value
946
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "9"})).unwrapped_value
947
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "9.2"})).unwrapped_value
948
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "not a number"})).unwrapped_value
949
+ end
950
+
951
+ def test_less_or_equal_to_works
952
+ config = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_LESS_THAN_OR_EQUAL, property_name: 'user.age', value_to_match: 10)
953
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
954
+ namespace: nil)
955
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
956
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 10})).unwrapped_value
957
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 9})).unwrapped_value
958
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 9.5})).unwrapped_value
959
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 10.1})).unwrapped_value
960
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "9"})).unwrapped_value
961
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "not a number"})).unwrapped_value
962
+ end
963
+
964
+
965
+ def test_greater_than_works
966
+ config = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_GREATER_THAN, property_name: 'user.age', value_to_match: 10)
967
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
968
+ namespace: nil)
969
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
970
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 10})).unwrapped_value
971
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 9})).unwrapped_value
972
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 9.5})).unwrapped_value
973
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 10.1})).unwrapped_value
974
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 12})).unwrapped_value
975
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "19"})).unwrapped_value
976
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "not a number"})).unwrapped_value
977
+ end
978
+
979
+ def test_greater_than_or_equal_to_works
980
+ config = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_GREATER_THAN_OR_EQUAL, property_name: 'user.age', value_to_match: 10)
981
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
982
+ namespace: nil)
983
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
984
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 10})).unwrapped_value
985
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 9})).unwrapped_value
986
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: 9.5})).unwrapped_value
987
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 10.1})).unwrapped_value
988
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user: {age: 12})).unwrapped_value
989
+
990
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "19"})).unwrapped_value
991
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user: {age: "not a number"})).unwrapped_value
992
+ end
993
+
994
+ def test_date_before_works
995
+ date = "2024-12-01T00:00:00Z"
996
+ millis = Time.iso8601(date).utc.to_i * 1000
997
+ config_with_string = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_BEFORE, property_name: 'user.joinDate', value_to_match: date)
998
+ evaluator_with_string_config = Prefab::CriteriaEvaluator.new(config_with_string, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
999
+ namespace: nil)
1000
+ config_with_millis = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_BEFORE, property_name: 'user.joinDate', value_to_match: millis)
1001
+ evaluator_with_millis_config = Prefab::CriteriaEvaluator.new(config_with_millis, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
1002
+ namespace: nil)
1003
+ assert_equal DEFAULT_VALUE, evaluator_with_millis_config.evaluate(context({})).unwrapped_value
1004
+ assert_equal DESIRED_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: millis-10000})).unwrapped_value
1005
+ assert_equal DESIRED_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: "2024-11-01T00:00:00Z"})).unwrapped_value
1006
+ assert_equal DEFAULT_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: millis+10000})).unwrapped_value
1007
+ assert_equal DEFAULT_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: "2024-12-02T00:00:00Z"})).unwrapped_value
1008
+
1009
+ assert_equal DEFAULT_VALUE, evaluator_with_string_config.evaluate(context({})).unwrapped_value
1010
+ assert_equal DESIRED_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: millis-10000})).unwrapped_value
1011
+ assert_equal DESIRED_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: "2024-11-01T00:00:00Z"})).unwrapped_value
1012
+ assert_equal DEFAULT_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: millis+10000})).unwrapped_value
1013
+ assert_equal DEFAULT_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: "2024-12-02T00:00:00Z"})).unwrapped_value
1014
+ end
1015
+
1016
+ def test_date_after_works
1017
+ date = "2024-12-01T00:00:00Z"
1018
+ millis = Time.iso8601(date).utc.to_i * 1000
1019
+ config_with_string = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_AFTER, property_name: 'user.joinDate', value_to_match: date)
1020
+ evaluator_with_string_config = Prefab::CriteriaEvaluator.new(config_with_string, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
1021
+ namespace: nil)
1022
+ config_with_millis = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_AFTER, property_name: 'user.joinDate', value_to_match: millis)
1023
+ evaluator_with_millis_config = Prefab::CriteriaEvaluator.new(config_with_millis, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client,
1024
+ namespace: nil)
1025
+ assert_equal DEFAULT_VALUE, evaluator_with_millis_config.evaluate(context({})).unwrapped_value
1026
+ assert_equal DEFAULT_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: millis-10000})).unwrapped_value
1027
+ assert_equal DEFAULT_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: "2024-11-01T00:00:00Z"})).unwrapped_value
1028
+ assert_equal DESIRED_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: millis+10000})).unwrapped_value
1029
+ assert_equal DESIRED_VALUE, evaluator_with_millis_config.evaluate(context(user: {joinDate: "2024-12-02T00:00:00Z"})).unwrapped_value
1030
+
1031
+ assert_equal DEFAULT_VALUE, evaluator_with_string_config.evaluate(context({})).unwrapped_value
1032
+ assert_equal DEFAULT_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: millis-10000})).unwrapped_value
1033
+ assert_equal DEFAULT_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: "2024-11-01T00:00:00Z"})).unwrapped_value
1034
+ assert_equal DESIRED_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: millis+10000})).unwrapped_value
1035
+ assert_equal DESIRED_VALUE, evaluator_with_string_config.evaluate(context(user: {joinDate: "2024-12-02T00:00:00Z"})).unwrapped_value
1036
+ end
1037
+
1038
+ def test_semver_less_than
1039
+ config = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_SEMVER_LESS_THAN, property_name: 'user.version', value_to_match: "2.0.0")
1040
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client, namespace: nil)
1041
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
1042
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "nonsense"})).unwrapped_value
1043
+
1044
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user:{version: "1.0.0"})).unwrapped_value
1045
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "2.0.0"})).unwrapped_value
1046
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "3.0.0"})).unwrapped_value
1047
+ end
1048
+
1049
+ def test_semver_equal_to
1050
+ config = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_SEMVER_EQUAL, property_name: 'user.version', value_to_match: "2.0.0")
1051
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client, namespace: nil)
1052
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
1053
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "nonsense"})).unwrapped_value
1054
+
1055
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "1.0.0"})).unwrapped_value
1056
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user:{version: "2.0.0"})).unwrapped_value
1057
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "3.0.0"})).unwrapped_value
1058
+ end
1059
+
1060
+ def test_semver_greater_than
1061
+ config = create_prefab_config(operator: PrefabProto::Criterion::CriterionOperator::PROP_SEMVER_GREATER_THAN, property_name: 'user.version', value_to_match: "2.0.0")
1062
+ evaluator = Prefab::CriteriaEvaluator.new(config, project_env_id: PROJECT_ENV_ID, resolver: nil, base_client: @base_client, namespace: nil)
1063
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context({})).unwrapped_value
1064
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "nonsense"})).unwrapped_value
1065
+
1066
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "1.0.0"})).unwrapped_value
1067
+ assert_equal DEFAULT_VALUE, evaluator.evaluate(context(user:{version: "2.0.0"})).unwrapped_value
1068
+ assert_equal DESIRED_VALUE, evaluator.evaluate(context(user:{version: "3.0.0"})).unwrapped_value
1069
+ end
1070
+
686
1071
  private
687
1072
 
688
1073
  def string_list(values)
@@ -719,4 +1104,55 @@ class TestCriteriaEvaluator < Minitest::Test
719
1104
  'fake-base-client-instance_hash'
720
1105
  end
721
1106
  end
1107
+
1108
+
1109
+ def create_prefab_config(
1110
+ key: KEY,
1111
+ project_env_id: PROJECT_ENV_ID,
1112
+ operator:,
1113
+ value_to_match:,
1114
+ property_name:,
1115
+ desired_value_config: DESIRED_VALUE_CONFIG
1116
+ )
1117
+ PrefabProto::Config.new(
1118
+ key: key,
1119
+ rows: [
1120
+ DEFAULT_ROW,
1121
+ PrefabProto::ConfigRow.new(
1122
+ project_env_id: project_env_id,
1123
+ values: [
1124
+ PrefabProto::ConditionalValue.new(
1125
+ criteria: [
1126
+ PrefabProto::Criterion.new(
1127
+ operator: operator,
1128
+ value_to_match: build_config_value(value_to_match),
1129
+ property_name: property_name
1130
+ )
1131
+ ],
1132
+ value: desired_value_config
1133
+ )
1134
+ ]
1135
+ )
1136
+ ]
1137
+ )
1138
+ end
1139
+
1140
+ def build_config_value(value)
1141
+ case value
1142
+ when Integer
1143
+ PrefabProto::ConfigValue.new(int: value)
1144
+ when Float
1145
+ PrefabProto::ConfigValue.new(double: value)
1146
+ when String
1147
+ PrefabProto::ConfigValue.new(string: value)
1148
+ when Array
1149
+ if value.all? { |v| v.is_a?(String) }
1150
+ PrefabProto::ConfigValue.new(string_list: PrefabProto::StringList.new(values: value))
1151
+ else
1152
+ raise ArgumentError, "Unsupported array type: Only arrays of strings are supported."
1153
+ end
1154
+ else
1155
+ raise ArgumentError, "Unsupported value type: #{value.class}"
1156
+ end
1157
+ end
722
1158
  end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'test_helper'
5
+
6
+ module Prefab
7
+ class FixedSizeHashTest < Minitest::Test
8
+ def setup
9
+ @max_size = 3
10
+ @hash = FixedSizeHash.new(@max_size)
11
+ end
12
+
13
+ def test_acts_like_a_regular_hash_when_under_max_size
14
+ @hash[:a] = 1
15
+ @hash[:b] = 2
16
+
17
+ assert_equal 1, @hash[:a]
18
+ assert_equal 2, @hash[:b]
19
+ assert_equal 2, @hash.size
20
+ end
21
+
22
+ def test_enforces_max_size_by_evicting_first_added_item
23
+ @hash[:a] = 1
24
+ @hash[:b] = 2
25
+ @hash[:c] = 3
26
+ assert_equal @max_size, @hash.size
27
+
28
+ @hash[:d] = 4
29
+ assert_equal @max_size, @hash.size
30
+ assert_nil @hash[:a] # First item should be evicted
31
+ assert_equal 4, @hash[:d]
32
+ end
33
+
34
+ def test_updating_existing_key_does_not_trigger_eviction
35
+ @hash[:a] = 1
36
+ @hash[:b] = 2
37
+ @hash[:c] = 3
38
+
39
+ @hash[:b] = 'new value' # Update existing key
40
+
41
+ assert_equal @max_size, @hash.size
42
+ assert_equal 1, @hash[:a] # First item should still be present
43
+ assert_equal 'new value', @hash[:b]
44
+ assert_equal 3, @hash[:c]
45
+ end
46
+
47
+ def test_handles_nil_values
48
+ @hash[:a] = nil
49
+ @hash[:b] = 2
50
+ @hash[:c] = 3
51
+ @hash[:d] = 4
52
+
53
+ assert_nil @hash[:a] # First item should be evicted
54
+ assert_equal 4, @hash[:d]
55
+ end
56
+
57
+ def test_preserves_hash_methods
58
+ @hash[:a] = 1
59
+ @hash[:b] = 2
60
+
61
+ assert_equal [:a, :b], @hash.keys
62
+ assert_equal [1, 2], @hash.values
63
+ assert @hash.key?(:a)
64
+ refute @hash.key?(:z)
65
+ end
66
+
67
+ def test_handles_string_keys
68
+ @hash['a'] = 1
69
+ @hash['b'] = 2
70
+ @hash['c'] = 3
71
+ @hash['d'] = 4
72
+
73
+ assert_nil @hash['a'] # First item should be evicted
74
+ assert_equal 4, @hash['d']
75
+ end
76
+
77
+ def test_handles_object_keys
78
+ key1 = Object.new
79
+ key2 = Object.new
80
+ key3 = Object.new
81
+ key4 = Object.new
82
+
83
+ @hash[key1] = 1
84
+ @hash[key2] = 2
85
+ @hash[key3] = 3
86
+ @hash[key4] = 4
87
+
88
+ assert_nil @hash[key1] # First item should be evicted
89
+ assert_equal 4, @hash[key4]
90
+ end
91
+
92
+ def test_can_be_initialized_empty
93
+ assert_equal 0, @hash.size
94
+ end
95
+
96
+ def test_enumerable_methods
97
+ @hash[:a] = 1
98
+ @hash[:b] = 2
99
+
100
+ mapped = @hash.map { |k, v| [k, v * 2] }.to_h
101
+ assert_equal({ a: 2, b: 4 }, mapped)
102
+
103
+ filtered = @hash.select { |_, v| v > 1 }
104
+ assert_equal({ b: 2 }, filtered.to_h)
105
+ end
106
+
107
+ def test_clear_maintains_max_size_constraint
108
+ @hash[:a] = 1
109
+ @hash[:b] = 2
110
+ @hash.clear
111
+
112
+ assert_equal 0, @hash.size
113
+
114
+ # Should still enforce max size after clear
115
+ (@max_size + 1).times { |i| @hash[i] = i }
116
+ assert_equal @max_size, @hash.size
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,108 @@
1
+ require 'test_helper'
2
+ class TestSemanticVersion < Minitest::Test
3
+ def test_parse_valid_version
4
+ version = SemanticVersion.parse('1.2.3')
5
+ assert_equal 1, version.major
6
+ assert_equal 2, version.minor
7
+ assert_equal 3, version.patch
8
+ assert_nil version.prerelease
9
+ assert_nil version.build_metadata
10
+ end
11
+
12
+ def test_parse_version_with_prerelease
13
+ version = SemanticVersion.parse('1.2.3-alpha.1')
14
+ assert_equal 1, version.major
15
+ assert_equal 2, version.minor
16
+ assert_equal 3, version.patch
17
+ assert_equal 'alpha.1', version.prerelease
18
+ assert_nil version.build_metadata
19
+ end
20
+
21
+ def test_parse_version_with_build_metadata
22
+ version = SemanticVersion.parse('1.2.3+build.123')
23
+ assert_equal 1, version.major
24
+ assert_equal 2, version.minor
25
+ assert_equal 3, version.patch
26
+ assert_nil version.prerelease
27
+ assert_equal 'build.123', version.build_metadata
28
+ end
29
+
30
+ def test_parse_full_version
31
+ version = SemanticVersion.parse('1.2.3-alpha.1+build.123')
32
+ assert_equal 1, version.major
33
+ assert_equal 2, version.minor
34
+ assert_equal 3, version.patch
35
+ assert_equal 'alpha.1', version.prerelease
36
+ assert_equal 'build.123', version.build_metadata
37
+ end
38
+
39
+ def test_parse_invalid_version
40
+ assert_raises(ArgumentError) { SemanticVersion.parse('invalid') }
41
+ assert_raises(ArgumentError) { SemanticVersion.parse('1.2') }
42
+ assert_raises(ArgumentError) { SemanticVersion.parse('1.2.3.4') }
43
+ assert_raises(ArgumentError) { SemanticVersion.parse('') }
44
+ end
45
+
46
+ def test_parse_quietly
47
+ assert_nil SemanticVersion.parse_quietly('invalid')
48
+ refute_nil SemanticVersion.parse_quietly('1.2.3')
49
+ end
50
+
51
+ def test_to_string
52
+ assert_equal '1.2.3', SemanticVersion.parse('1.2.3').to_s
53
+ assert_equal '1.2.3-alpha.1', SemanticVersion.parse('1.2.3-alpha.1').to_s
54
+ assert_equal '1.2.3+build.123', SemanticVersion.parse('1.2.3+build.123').to_s
55
+ assert_equal '1.2.3-alpha.1+build.123', SemanticVersion.parse('1.2.3-alpha.1+build.123').to_s
56
+ end
57
+
58
+ def test_equality
59
+ v1 = SemanticVersion.parse('1.2.3')
60
+ v2 = SemanticVersion.parse('1.2.3')
61
+ v3 = SemanticVersion.parse('1.2.4')
62
+ v4 = SemanticVersion.parse('1.2.3-alpha')
63
+ v5 = SemanticVersion.parse('1.2.3+build.123')
64
+
65
+ assert_equal v1, v2
66
+ refute_equal v1, v3
67
+ refute_equal v1, v4
68
+ assert_equal v1, v5 # build metadata is ignored in equality
69
+ end
70
+
71
+ def test_comparison
72
+ versions = [
73
+ '1.0.0-alpha',
74
+ '1.0.0-alpha.1',
75
+ '1.0.0-beta.2',
76
+ '1.0.0-beta.11',
77
+ '1.0.0-rc.1',
78
+ '1.0.0',
79
+ '2.0.0',
80
+ '2.1.0',
81
+ '2.1.1'
82
+ ].map { |v| SemanticVersion.parse(v) }
83
+
84
+ # Test that each version is less than the next version
85
+ (versions.length - 1).times do |i|
86
+ assert versions[i] < versions[i + 1], "Expected #{versions[i]} < #{versions[i + 1]}"
87
+ end
88
+ end
89
+
90
+ def test_prerelease_comparison
91
+ # Test specific prerelease comparison cases
92
+ cases = [
93
+ ['1.0.0-alpha', '1.0.0-alpha.1', -1],
94
+ ['1.0.0-alpha.1', '1.0.0-alpha.beta', -1],
95
+ ['1.0.0-alpha.beta', '1.0.0-beta', -1],
96
+ ['1.0.0-beta', '1.0.0-beta.2', -1],
97
+ ['1.0.0-beta.2', '1.0.0-beta.11', -1],
98
+ ['1.0.0-beta.11', '1.0.0-rc.1', -1],
99
+ ['1.0.0-rc.1', '1.0.0', -1]
100
+ ]
101
+
102
+ cases.each do |v1_str, v2_str, expected|
103
+ v1 = SemanticVersion.parse(v1_str)
104
+ v2 = SemanticVersion.parse(v2_str)
105
+ assert_equal expected, (v1 <=> v2), "Expected #{v1} <=> #{v2} to be #{expected}"
106
+ end
107
+ end
108
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'test_helper'
4
4
  require 'webrick'
5
+ require 'ostruct'
5
6
 
6
7
  class TestSSEConfigClient < Minitest::Test
7
8
  def test_client