prefab-cloud-ruby 0.5.0 → 0.7.0

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.
@@ -0,0 +1,46 @@
1
+ require 'prefab-cloud-ruby'
2
+ require 'rack'
3
+ require 'base64'
4
+ require 'json'
5
+
6
+ handler = Rack::Handler::Thin
7
+
8
+ #
9
+ # This is a very lightweight server that allows the compliance harness to excercise the prefab client
10
+ #
11
+ class RackApp
12
+ def call(env)
13
+ props = CGI::parse(env["QUERY_STRING"])
14
+ props = JSON.parse(Base64.decode64(props["props"][0]))
15
+
16
+ key = props["key"]
17
+ namespace = props["namespace"]
18
+ environment = props["environment"]
19
+ user_key = props["user_key"]
20
+ is_feature_flag = !props["feature_flag"].nil?
21
+
22
+ client = Prefab::Client.new(
23
+ api_key: "1-#{environment}-local_development_api_key", #sets environment
24
+ namespace: namespace,
25
+ )
26
+
27
+ puts "Key #{key}"
28
+ puts "User #{user_key}"
29
+ puts "Environment #{environment}"
30
+ puts "Namespace #{namespace}"
31
+ puts "Props! #{props}"
32
+ puts "is_feature_flag! #{is_feature_flag}"
33
+
34
+ if is_feature_flag
35
+ puts "EVALFF #{key} #{user_key}"
36
+ rtn = client.feature_flag_client.get(key, user_key, []).to_s
37
+ else
38
+ rtn = client.config_client.get(key).to_s
39
+ end
40
+ puts "return #{rtn}"
41
+
42
+ [200, { "Content-Type" => "text/plain" }, rtn]
43
+ end
44
+ end
45
+
46
+ handler.run RackApp.new
@@ -16,26 +16,26 @@ class TestConfigLoader < Minitest::Test
16
16
 
17
17
  def test_highwater
18
18
  assert_equal 0, @loader.highwater_mark
19
- @loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
19
+ @loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
20
20
  assert_equal 1, @loader.highwater_mark
21
21
 
22
- @loader.set(Prefab::ConfigDelta.new(id: 5, key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
22
+ @loader.set(Prefab::ConfigDelta.new(id: 5, key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
23
23
  assert_equal 5, @loader.highwater_mark
24
- @loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
24
+ @loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
25
25
  assert_equal 5, @loader.highwater_mark
26
26
  end
27
27
 
28
28
  def test_keeps_most_recent
29
29
  assert_equal 0, @loader.highwater_mark
30
- @loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", value: Prefab::ConfigValue.new(int: 1)))
30
+ @loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", default: Prefab::ConfigValue.new(int: 1)))
31
31
  assert_equal 1, @loader.highwater_mark
32
32
  should_be :int, 1, "sample_int"
33
33
 
34
- @loader.set(Prefab::ConfigDelta.new(id: 4, key: "sample_int", value: Prefab::ConfigValue.new(int: 4)))
34
+ @loader.set(Prefab::ConfigDelta.new(id: 4, key: "sample_int", default: Prefab::ConfigValue.new(int: 4)))
35
35
  assert_equal 4, @loader.highwater_mark
36
36
  should_be :int, 4, "sample_int"
37
37
 
38
- @loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", value: Prefab::ConfigValue.new(int: 2)))
38
+ @loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", default: Prefab::ConfigValue.new(int: 2)))
39
39
  assert_equal 4, @loader.highwater_mark
40
40
  should_be :int, 4, "sample_int"
41
41
  end
@@ -43,13 +43,13 @@ class TestConfigLoader < Minitest::Test
43
43
  def test_api_precedence
44
44
  should_be :int, 123, "sample_int"
45
45
 
46
- @loader.set(Prefab::ConfigDelta.new(key: "sample_int", value: Prefab::ConfigValue.new(int: 456)))
46
+ @loader.set(Prefab::ConfigDelta.new(key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
47
47
  should_be :int, 456, "sample_int"
48
48
  end
49
49
 
50
50
  def test_api_deltas
51
51
  val = Prefab::ConfigValue.new(int: 456)
52
- delta = Prefab::ConfigDelta.new(key: "sample_int", value: val)
52
+ delta = Prefab::ConfigDelta.new(key: "sample_int", default: val)
53
53
  @loader.set(delta)
54
54
 
55
55
  deltas = Prefab::ConfigDeltas.new
@@ -59,10 +59,10 @@ class TestConfigLoader < Minitest::Test
59
59
 
60
60
  def test_loading_tombstones_removes_entries
61
61
  val = Prefab::ConfigValue.new(int: 456)
62
- delta = Prefab::ConfigDelta.new(key: "sample_int", value: val)
62
+ delta = Prefab::ConfigDelta.new(key: "sample_int", default: val)
63
63
  @loader.set(delta)
64
64
 
65
- delta = Prefab::ConfigDelta.new(key: "sample_int", value: nil)
65
+ delta = Prefab::ConfigDelta.new(key: "sample_int", default: nil)
66
66
  @loader.set(delta)
67
67
 
68
68
  deltas = Prefab::ConfigDeltas.new
@@ -72,8 +72,8 @@ class TestConfigLoader < Minitest::Test
72
72
  private
73
73
 
74
74
  def should_be(type, value, key)
75
- assert_equal type, @loader.calc_config[key].type
76
- assert_equal value, @loader.calc_config[key].send(type)
75
+ assert_equal type, @loader.calc_config[key].default.type
76
+ assert_equal value, @loader.calc_config[key].default.send(type)
77
77
  end
78
78
 
79
79
  end
@@ -6,17 +6,46 @@ class TestConfigResolver < Minitest::Test
6
6
  @loader = MockConfigLoader.new
7
7
 
8
8
  loaded_values = {
9
- "projectA:key" => Prefab::ConfigValue.new(string: "valueA"),
10
- "key" => Prefab::ConfigValue.new(string: "value_none"),
11
- "projectB:key" => Prefab::ConfigValue.new(string: "valueB"),
12
- "projectB.subprojectX:key" => Prefab::ConfigValue.new(string: "projectB.subprojectX"),
13
- "projectB.subprojectY:key" => Prefab::ConfigValue.new(string: "projectB.subprojectY"),
14
- "projectB:key2" => Prefab::ConfigValue.new(string: "valueB2")
9
+ "key" => Prefab::ConfigDelta.new(
10
+ key: "key",
11
+ default: Prefab::ConfigValue.new(string: "value_no_env_default"),
12
+ envs: [{
13
+ environment: "test",
14
+ default: Prefab::ConfigValue.new(string: "value_none"),
15
+ namespace_values: [
16
+ {
17
+ namespace: "projectA",
18
+ config_value: Prefab::ConfigValue.new(string: "valueA")
19
+ },
20
+ {
21
+ namespace: "projectB",
22
+ config_value: Prefab::ConfigValue.new(string: "valueB")
23
+ },
24
+ {
25
+ namespace: "projectB.subprojectX",
26
+ config_value: Prefab::ConfigValue.new(string: "projectB.subprojectX")
27
+ },
28
+ {
29
+ namespace: "projectB.subprojectY",
30
+ config_value: Prefab::ConfigValue.new(string: "projectB.subprojectY")
31
+ },
32
+ ]
33
+ }]
34
+ ),
35
+ "key2" => Prefab::ConfigDelta.new(
36
+ key: "key2",
37
+ default: Prefab::ConfigValue.new(string: "valueB2"),
38
+ )
15
39
  }
16
40
 
17
41
  @loader.stub :calc_config, loaded_values do
18
- @resolver = Prefab::ConfigResolver.new(MockBaseClient.new, @loader)
19
- assert_equal "value_none", @resolver.get("key")
42
+
43
+ @resolverA = resolver_for_namespace("", @loader, environment: "some_other_env")
44
+ assert_equal "value_no_env_default", @resolverA.get("key")
45
+
46
+ ## below here in the test env
47
+ @resolverA = resolver_for_namespace("", @loader)
48
+ assert_equal "value_none", @resolverA.get("key")
20
49
 
21
50
  @resolverA = resolver_for_namespace("projectA", @loader)
22
51
  assert_equal "valueA", @resolverA.get("key")
@@ -27,7 +56,10 @@ class TestConfigResolver < Minitest::Test
27
56
  @resolverBX = resolver_for_namespace("projectB.subprojectX", @loader)
28
57
  assert_equal "projectB.subprojectX", @resolverBX.get("key")
29
58
 
30
- @resolverUndefinedSubProject = resolver_for_namespace("projectB.subprojectX:subsubQ", @loader)
59
+ @resolverBX = resolver_for_namespace("projectB.subprojectX", @loader)
60
+ assert_equal "valueB2", @resolverBX.get("key2")
61
+
62
+ @resolverUndefinedSubProject = resolver_for_namespace("projectB.subprojectX.subsubQ", @loader)
31
63
  assert_equal "projectB.subprojectX", @resolverBX.get("key")
32
64
 
33
65
  @resolverBX = resolver_for_namespace("projectC", @loader)
@@ -40,30 +72,69 @@ class TestConfigResolver < Minitest::Test
40
72
  @loader = MockConfigLoader.new
41
73
  @loader.stub :calc_config, {} do
42
74
  resolver = Prefab::ConfigResolver.new(MockBaseClient.new, @loader)
43
- assert resolver.send(:starts_with_ns?, "", "a")
44
- assert resolver.send(:starts_with_ns?, "a", "a")
45
- assert resolver.send(:starts_with_ns?, "a", "a.b")
46
- assert !resolver.send(:starts_with_ns?, "a.b", "a")
47
-
48
- assert resolver.send(:starts_with_ns?, "corp", "corp.proj.proja")
49
- assert resolver.send(:starts_with_ns?, "corp.proj", "corp.proj.proja")
50
- assert resolver.send(:starts_with_ns?, "corp.proj.proja", "corp.proj.proja")
51
- assert !resolver.send(:starts_with_ns?, "corp.proj.projb", "corp.proj.proja")
52
-
53
- # corp:a:b is not a real delimited namespace
54
- assert !resolver.send(:starts_with_ns?, "corp", "corp:a:b")
55
- assert resolver.send(:starts_with_ns?, "foo", "foo.baz")
56
- assert resolver.send(:starts_with_ns?, "foo.baz", "foo.baz")
57
- assert !resolver.send(:starts_with_ns?, "foo.baz", "foo.bazz")
75
+ assert_equal [true, 0], resolver.send(:starts_with_ns?, "", "a")
76
+ assert_equal [true, 1], resolver.send(:starts_with_ns?, "a", "a")
77
+ assert_equal [true, 1], resolver.send(:starts_with_ns?, "a", "a.b")
78
+ assert_equal [false, 2], resolver.send(:starts_with_ns?, "a.b", "a")
79
+
80
+ assert_equal [true, 1], resolver.send(:starts_with_ns?, "corp", "corp.proj.proja")
81
+ assert_equal [true, 2], resolver.send(:starts_with_ns?, "corp.proj", "corp.proj.proja")
82
+ assert_equal [true, 3], resolver.send(:starts_with_ns?, "corp.proj.proja", "corp.proj.proja")
83
+ assert_equal [false, 3], resolver.send(:starts_with_ns?, "corp.proj.projb", "corp.proj.proja")
84
+
85
+ # corp_equal [true, 1:,a:b is not a real delimited namespace[0
86
+ assert_equal [false, 1], resolver.send(:starts_with_ns?, "corp", "corp:a:b")
87
+ assert_equal [true, 1], resolver.send(:starts_with_ns?, "foo", "foo.baz")
88
+ assert_equal [true, 2], resolver.send(:starts_with_ns?, "foo.baz", "foo.baz")
89
+ assert_equal [false, 2], resolver.send(:starts_with_ns?, "foo.baz", "foo.bazz")
90
+ end
91
+ end
92
+
93
+ def test_special_ff_variant_copying
94
+ @loader = MockConfigLoader.new
95
+ loaded_values = {
96
+ "ff" => Prefab::ConfigDelta.new(
97
+ key: "ff",
98
+ default: Prefab::ConfigValue.new(feature_flag: Prefab::FeatureFlag.new(
99
+ variants: [
100
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
101
+ Prefab::FeatureFlagVariant.new(string: "default"),
102
+ Prefab::FeatureFlagVariant.new(string: "env"),
103
+ ],
104
+ inactive_variant_idx: 0,
105
+ default: Prefab::VariantDistribution.new(variant_idx: 1)
106
+ )),
107
+ envs: [
108
+ Prefab::EnvironmentValues.new(
109
+ environment: "test",
110
+ default: Prefab::ConfigValue.new(feature_flag: Prefab::FeatureFlag.new(
111
+ inactive_variant_idx: 0,
112
+ default: Prefab::VariantDistribution.new(variant_idx: 2)))
113
+ )
114
+ ]
115
+ )
116
+ }
117
+ @loader.stub :calc_config, loaded_values do
118
+ resolver = Prefab::ConfigResolver.new(MockBaseClient.new, @loader)
119
+ ff = resolver.get("ff")
120
+ assert_equal 3, ff.variants.size
121
+ assert_equal %w(inactive default env), ff.variants.map(&:string)
58
122
  end
59
123
  end
60
124
 
61
125
  # colons are not allowed in keys, but verify behavior anyway
62
- def test_keys_with_colons
126
+ def test_key_and_namespaces_with_colons
63
127
  @loader = MockConfigLoader.new
128
+
64
129
  loaded_values = {
65
- "Key:With:Colons" => Prefab::ConfigValue.new(string: "value"),
66
- "proj:apikey" => Prefab::ConfigValue.new(string: "v2")
130
+ "Key:With:Colons" => Prefab::ConfigDelta.new(
131
+ key: "Key:With:Colons",
132
+ default: Prefab::ConfigValue.new(string: "value"),
133
+ ),
134
+ "proj:apikey" => Prefab::ConfigDelta.new(
135
+ key: "proj:apikey",
136
+ default: Prefab::ConfigValue.new(string: "v2"),
137
+ )
67
138
  }
68
139
 
69
140
  @loader.stub :calc_config, loaded_values do
@@ -72,37 +143,36 @@ class TestConfigResolver < Minitest::Test
72
143
  assert_nil r.get("apikey")
73
144
 
74
145
  r = resolver_for_namespace("proj", @loader)
75
- assert_equal "v2", r.get("apikey")
146
+ assert_nil r.get("apikey")
76
147
 
77
148
  r = resolver_for_namespace("", @loader)
78
149
  assert_nil r.get("apikey")
79
150
 
80
-
81
151
  @resolverKeyWith = resolver_for_namespace("Ket:With", @loader)
82
152
  assert_nil @resolverKeyWith.get("Colons")
83
153
  assert_nil @resolverKeyWith.get("With:Colons")
84
- assert_nil @resolverKeyWith.get("Key:With:Colons")
154
+ assert_equal "value", @resolverKeyWith.get("Key:With:Colons")
85
155
 
86
156
  @resolverKeyWithExtra = resolver_for_namespace("Key:With:Extra", @loader)
87
157
  puts @resolverKeyWithExtra.to_s
88
158
  assert_nil @resolverKeyWithExtra.get("Colons")
89
159
  assert_nil @resolverKeyWithExtra.get("With:Colons")
90
- assert_nil @resolverKeyWithExtra.get("Key:With:Colons")
160
+ assert_equal "value", @resolverKeyWithExtra.get("Key:With:Colons")
91
161
 
92
162
  @resolverKey = resolver_for_namespace("Key", @loader)
93
- assert_equal "value", @resolverKey.get("With:Colons")
163
+ assert_nil @resolverKey.get("With:Colons")
94
164
  assert_nil @resolverKey.get("Colons")
95
- assert_nil @resolverKey.get("Key:With:Colons")
165
+ assert_equal "value", @resolverKey.get("Key:With:Colons")
96
166
 
97
167
  @resolverWithProperlySegmentedNamespace = resolver_for_namespace("Key.With.Extra", @loader)
98
168
  assert_nil @resolverWithProperlySegmentedNamespace.get("Colons")
99
- assert_equal "value", @resolverWithProperlySegmentedNamespace.get("With:Colons")
100
- assert_nil @resolverWithProperlySegmentedNamespace.get("Key:With:Colons")
169
+ assert_nil @resolverWithProperlySegmentedNamespace.get("With:Colons")
170
+ assert_equal "value", @resolverWithProperlySegmentedNamespace.get("Key:With:Colons")
101
171
  end
102
172
  end
103
173
 
104
- def resolver_for_namespace(namespace, loader)
105
- Prefab::ConfigResolver.new(MockBaseClient.new(namespace: namespace), loader)
174
+ def resolver_for_namespace(namespace, loader, environment: "test")
175
+ Prefab::ConfigResolver.new(MockBaseClient.new(namespace: namespace, environment: environment), loader)
106
176
  end
107
177
 
108
178
  end
@@ -2,63 +2,219 @@ require 'test_helper'
2
2
 
3
3
  class TestFeatureFlagClient < Minitest::Test
4
4
 
5
+ def setup
6
+ super
7
+ @mock_base_client = MockBaseClient.new
8
+ @client = Prefab::FeatureFlagClient.new(@mock_base_client)
9
+ Prefab::FeatureFlagClient.send(:public, :is_on?) #publicize for testing
10
+ Prefab::FeatureFlagClient.send(:public, :segment_match?) #publicize for testing
11
+ end
12
+
5
13
  def test_pct
6
- client = Prefab::FeatureFlagClient.new(MockBaseClient.new)
7
- Prefab::FeatureFlagClient.send(:public, :is_on?)
8
14
  feature = "FlagName"
9
- flag = Prefab::FeatureFlag.new( pct: 0.5)
15
+
16
+ flag = Prefab::FeatureFlag.new(
17
+ active: true,
18
+ variants: [
19
+ Prefab::FeatureFlagVariant.new(bool: false),
20
+ Prefab::FeatureFlagVariant.new(bool: true)
21
+ ],
22
+ inactive_variant_idx: 0,
23
+ default: Prefab::VariantDistribution.new(variant_weights:
24
+ Prefab::VariantWeights.new(weights: [
25
+ Prefab::VariantWeight.new(weight: 500,
26
+ variant_idx: 1),
27
+ Prefab::VariantWeight.new(weight: 500,
28
+ variant_idx: 0),
29
+ ]
30
+ )
31
+ )
32
+ )
10
33
 
11
34
  assert_equal false,
12
- client.is_on?(feature, "hashes high", [], flag)
35
+ @client.evaluate(feature, "hashes high", [], flag)
36
+ assert_equal true,
37
+ @client.evaluate(feature, "hashes low", [], flag)
38
+ end
13
39
 
40
+ def test_basic_active_inactive
41
+ feature = "FlagName"
42
+ flag = Prefab::FeatureFlag.new(
43
+ active: true,
44
+ variants: [
45
+ Prefab::FeatureFlagVariant.new(bool: false),
46
+ Prefab::FeatureFlagVariant.new(bool: true)
47
+ ],
48
+ inactive_variant_idx: 0,
49
+ default: Prefab::VariantDistribution.new(variant_idx: 1)
50
+ )
51
+ assert_equal true,
52
+ @client.evaluate(feature, "hashes high", [], flag)
14
53
  assert_equal true,
15
- client.is_on?(feature, "hashes low", [], flag)
54
+ @client.evaluate(feature, "hashes low", [], flag)
55
+
56
+ flag = Prefab::FeatureFlag.new(
57
+ active: false,
58
+ variants: [
59
+ Prefab::FeatureFlagVariant.new(bool: false),
60
+ Prefab::FeatureFlagVariant.new(bool: true)
61
+ ],
62
+ inactive_variant_idx: 0,
63
+ default: Prefab::VariantDistribution.new(variant_idx: 1)
64
+ )
65
+ assert_equal false,
66
+ @client.evaluate(feature, "hashes high", [], flag)
67
+ assert_equal false,
68
+ @client.evaluate(feature, "hashes low", [], flag)
16
69
  end
17
70
 
71
+ def test_user_targets
18
72
 
19
- def test_off
20
- client = Prefab::FeatureFlagClient.new(MockBaseClient.new)
21
- Prefab::FeatureFlagClient.send(:public, :is_on?)
22
73
  feature = "FlagName"
23
- flag = Prefab::FeatureFlag.new(pct: 0)
74
+ flag = Prefab::FeatureFlag.new(
75
+ active: true,
76
+ variants: [
77
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
78
+ Prefab::FeatureFlagVariant.new(string: "user target"),
79
+ Prefab::FeatureFlagVariant.new(string: "default"),
80
+ ],
81
+ inactive_variant_idx: 0,
82
+ user_targets: [
83
+ variant_idx: 1,
84
+ identifiers: ["user:1", "user:3"]
85
+ ],
86
+ default: Prefab::VariantDistribution.new(variant_idx: 2)
87
+ )
24
88
 
25
- assert_equal false,
26
- client.is_on?(feature, "hashes high", [], flag)
89
+ assert_equal "user target",
90
+ @client.evaluate(feature, "user:1", [], flag)
91
+ assert_equal "default",
92
+ @client.evaluate(feature, "user:2", [], flag)
93
+ assert_equal "user target",
94
+ @client.evaluate(feature, "user:3", [], flag)
95
+ end
96
+
97
+ def test_inclusion_rule
98
+ feature = "FlagName"
99
+ flag = Prefab::FeatureFlag.new(
100
+ active: true,
101
+ variants: [
102
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
103
+ Prefab::FeatureFlagVariant.new(string: "rule target"),
104
+ Prefab::FeatureFlagVariant.new(string: "default"),
105
+ ],
106
+ inactive_variant_idx: 0,
107
+ rules: [Prefab::Rule.new(
108
+ distribution: Prefab::VariantDistribution.new(variant_idx: 1),
109
+ criteria: Prefab::Criteria.new(
110
+ operator: "IN",
111
+ values: ["user:1"]
112
+ )
113
+ )],
114
+ default: Prefab::VariantDistribution.new(variant_idx: 2)
115
+ )
116
+
117
+ assert_equal "rule target",
118
+ @client.evaluate(feature, "user:1", [], flag)
119
+ assert_equal "default",
120
+ @client.evaluate(feature, "user:2", [], flag)
27
121
 
28
- assert_equal false,
29
- client.is_on?(feature, "hashes low", [], flag)
30
122
  end
31
123
 
124
+ def test_segment_match?
125
+ segment = Prefab::Segment.new(
126
+ name: "Beta Group",
127
+ includes: ["user:1", "user:5"],
128
+ excludes: ["user:1", "user:2"]
129
+ )
130
+ assert_equal false, @client.segment_match?(segment, "user:0", {})
131
+ assert_equal false, @client.segment_match?(segment, "user:1", {})
132
+ assert_equal false, @client.segment_match?(segment, "user:2", {})
133
+ assert_equal true, @client.segment_match?(segment, "user:5", {})
134
+ end
135
+
136
+ def test_segments
137
+ segment_key = "prefab-segment-beta-group"
138
+ @mock_base_client.mock_this_config(segment_key,
139
+ Prefab::Segment.new(
140
+ name: "Beta Group",
141
+ includes: ["user:1"]
142
+ )
143
+ )
32
144
 
33
- def test_on
34
- client = Prefab::FeatureFlagClient.new(MockBaseClient.new)
35
- Prefab::FeatureFlagClient.send(:public, :is_on?)
36
145
  feature = "FlagName"
37
- flag = Prefab::FeatureFlag.new(pct: 1)
146
+ flag = Prefab::FeatureFlag.new(
147
+ active: true,
148
+ variants: [
149
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
150
+ Prefab::FeatureFlagVariant.new(string: "rule target"),
151
+ Prefab::FeatureFlagVariant.new(string: "default"),
152
+ ],
153
+ inactive_variant_idx: 0,
154
+ rules: [Prefab::Rule.new(
155
+ distribution: Prefab::VariantDistribution.new(variant_idx: 1),
156
+ criteria: Prefab::Criteria.new(
157
+ operator: "IN_SEG",
158
+ values: [segment_key]
159
+ )
160
+ )],
161
+ default: Prefab::VariantDistribution.new(variant_idx: 2)
162
+ )
38
163
 
39
- assert_equal true,
40
- client.is_on?(feature, "hashes high", [], flag)
164
+ assert_equal "rule target",
165
+ @client.evaluate(feature, "user:1", [], flag)
166
+ assert_equal "default",
167
+ @client.evaluate(feature, "user:2", [], flag)
41
168
 
42
- assert_equal true,
43
- client.is_on?(feature, "hashes low", [], flag)
44
169
  end
45
170
 
46
- def test_whitelist
47
- client = Prefab::FeatureFlagClient.new(MockBaseClient.new)
48
- Prefab::FeatureFlagClient.send(:public, :is_on?)
171
+ def test_in_multiple_segments_has_or_behavior
172
+ segment_key_one = "prefab-segment-segment-1"
173
+ @mock_base_client.mock_this_config(segment_key_one,
174
+ Prefab::Segment.new(
175
+ name: "Segment-1",
176
+ includes: ["user:1", "user:2"],
177
+ excludes: ["user:3"]
178
+ )
179
+ )
180
+ segment_key_two = "prefab-segment-segment-2"
181
+ @mock_base_client.mock_this_config(segment_key_two,
182
+ Prefab::Segment.new(
183
+ name: "Segment-2",
184
+ includes: ["user:3", "user:4"],
185
+ excludes: ["user:2"]
186
+ )
187
+ )
188
+
49
189
  feature = "FlagName"
50
- flag = Prefab::FeatureFlag.new(pct: 0, whitelisted: ["beta", "user:1", "user:3"])
190
+ flag = Prefab::FeatureFlag.new(
191
+ active: true,
192
+ variants: [
193
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
194
+ Prefab::FeatureFlagVariant.new(string: "rule target"),
195
+ Prefab::FeatureFlagVariant.new(string: "default"),
196
+ ],
197
+ inactive_variant_idx: 0,
198
+ rules: [Prefab::Rule.new(
199
+ distribution: Prefab::VariantDistribution.new(variant_idx: 1),
200
+ criteria: Prefab::Criteria.new(
201
+ operator: "IN_SEG",
202
+ values: [segment_key_one, segment_key_two]
203
+ )
204
+ )],
205
+ default: Prefab::VariantDistribution.new(variant_idx: 2)
206
+ )
51
207
 
52
- assert_equal false,
53
- client.is_on?(feature, "anything", [], flag)
54
- assert_equal true,
55
- client.is_on?(feature, "anything", ["beta"], flag)
56
- assert_equal true,
57
- client.is_on?(feature, "anything", ["alpha", "beta"], flag)
58
- assert_equal true,
59
- client.is_on?(feature, "anything", ["alpha", "user:1"], flag)
60
- assert_equal false,
61
- client.is_on?(feature, "anything", ["alpha", "user:2"], flag)
208
+ assert_equal "rule target",
209
+ @client.evaluate(feature, "user:1", [], flag)
210
+ assert_equal "rule target",
211
+ @client.evaluate(feature, "user:2", [], flag), "matches segment 1"
212
+ assert_equal "rule target",
213
+ @client.evaluate(feature, "user:3", [], flag)
214
+ assert_equal "rule target",
215
+ @client.evaluate(feature, "user:4", [], flag)
216
+ assert_equal "default",
217
+ @client.evaluate(feature, "user:5", [], flag)
62
218
 
63
219
  end
64
220
  end
data/test/test_helper.rb CHANGED
@@ -2,19 +2,29 @@ require 'minitest/autorun'
2
2
  require 'prefab-cloud-ruby'
3
3
 
4
4
  class MockBaseClient
5
- attr_reader :namespace, :logger
5
+ attr_reader :namespace, :logger, :environment
6
6
 
7
- def initialize(namespace: "")
7
+ def initialize(environment: "test", namespace: "")
8
+ @environment = environment
8
9
  @namespace = namespace
9
10
  @logger = Logger.new($stdout)
11
+ @config_values = {}
10
12
  end
11
13
 
12
- def account_id
14
+ def project_id
13
15
  1
14
16
  end
15
17
 
16
18
  def log_internal level, message
17
19
  end
20
+
21
+ def mock_this_config key, config_value
22
+ @config_values[key] = config_value
23
+ end
24
+
25
+ def get(key)
26
+ @config_values[key]
27
+ end
18
28
  end
19
29
 
20
30
  class MockConfigLoader