flipper 0.8.0 → 0.9.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afbd6c749fed154fc4f131d9a100b6f475d5963c
4
- data.tar.gz: 28a2fb5f3bf64365f003399cc6287e823da4ae23
3
+ metadata.gz: 61e55bc67bc9d28868981582af136a9d57546713
4
+ data.tar.gz: d8d9cd17434a08805be919c60d4072eeceb31342
5
5
  SHA512:
6
- metadata.gz: 9edcf82bb9e5e600ff797c726aef6bb59c96f9ce86a5ccdc085048553c7d7112b45eb8cdf37782660f0b7d793a2f1abe4a2886d186aac06b721e80ef917bbc18
7
- data.tar.gz: c0f9f0df3475ba5adee9467512fce9580d32b9398497389173cc9fb12ed5d853d9e26c6e8e4d1c98f8cfd5a4dcc3d61014bd5f366f4af0f2fd1466b432eb5852
6
+ metadata.gz: ce7c808ec096c1b1af7336a81b390f465b02d8b06c2eca86295b275ca0fa04d32ee6058f9dfc5a2c17150bad0a1c010522d70c97104480f51d7514086990cf16
7
+ data.tar.gz: 92ffbd0d092b4d4661dbe139fcfb969c878db4674aa791a4b5e7311cfe7cd724d2c1eba1199b3dd7a9dd65b75912b0fbf39009340951c5a4f05303e9e573be15
data/Changelog.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## master
2
+
3
+ * Moves SharedAdapterTests module to Flipper::Test::SharedAdapterTests to avoid clobbering anything top level in apps that use Flipper
4
+ * Memoizable, Instrumented and OperationLogger now delegate any missing methods to the original adapter. This was lost with the removal of the official decorator in 0.8, but is actually useful functionality for these "wrapping" adapters.
5
+ * Instrumenting adapters is now off by default. Use Flipper::Adapters::Instrumented.new(adapter) to instrument adapters and maintain the old functionality.
6
+
1
7
  ## 0.8
2
8
 
3
9
  * removed Flipper::Decorator and Flipper::Adapters::Decorator in favor of just calling methods on wrapped adapter
data/docs/Adapters.md CHANGED
@@ -29,10 +29,13 @@ The basic API for an adapter is this:
29
29
  * `enable(feature, gate, thing)` - Enable a gate for a thing.
30
30
  * `disable(feature, gate, thing)` - Disable a gate for a thing.
31
31
 
32
- If you would like to make your own adapter, there are shared adapter specs that you can use to verify that you have everything working correctly.
32
+ If you would like to make your own adapter, there are shared adapter specs (RSpec) and tests (MiniTest) that you can use to verify that you have everything working correctly.
33
33
 
34
+ ### RSpec
34
35
  For example, here is what the in-memory adapter spec looks like:
35
36
 
37
+ `spec/flipper/adapters/memory_spec.rb`
38
+
36
39
  ```ruby
37
40
  require 'helper'
38
41
  require 'flipper/adapters/memory'
@@ -51,6 +54,37 @@ describe Flipper::Adapters::Memory do
51
54
  end
52
55
  ```
53
56
 
57
+ ### MiniTest
58
+
59
+ Here is what an in-memory adapter MiniTest looks like:
60
+
61
+ `test/adapters/memory_test.rb`
62
+
63
+ ```ruby
64
+ require 'test_helper'
65
+ require 'flipper/adapters/memory'
66
+
67
+ class MemoryTest < MiniTest::Test
68
+ prepend SharedAdapterTests
69
+
70
+ def setup
71
+ # Any code here will run before each test
72
+ @adapter = Flipper::Adapters::Memory.new
73
+ end
74
+
75
+ def teardown
76
+ # Any code here will run after each test
77
+ end
78
+ end
79
+ ```
80
+ 1. Create a file under `test/adapters` that inherits from MiniTest::Test.
81
+
82
+ 2. `prepend SharedAdapterTests`.
83
+
84
+ 3. Initialize an instance variable `@adapter` referencing an instance of the adapter.
85
+
86
+ 4. Add any code to run before each test in a `setup` method and any code to run after each test in a `teardown` method.
87
+
54
88
  A good place to start when creating your own adapter is to copy one of the adapters mentioned above and replace the client specific code with whatever client you are attempting to adapt.
55
89
 
56
90
  I would also recommend setting `fail_fast = true` in your RSpec configuration as that will just give you one failure at a time to work through. It is also handy to have the shared adapter spec file open.
@@ -1,10 +1,11 @@
1
+ require 'delegate'
1
2
  require 'flipper/instrumenters/noop'
2
3
 
3
4
  module Flipper
4
5
  module Adapters
5
6
  # Internal: Adapter that wraps another adapter and instruments all adapter
6
7
  # operations. Used by flipper dsl to provide instrumentatin for flipper.
7
- class Instrumented
8
+ class Instrumented < SimpleDelegator
8
9
  include ::Flipper::Adapter
9
10
 
10
11
  # Private: The name of instrumentation events.
@@ -24,6 +25,7 @@ module Flipper
24
25
  # :instrumenter - What to use to instrument all the things.
25
26
  #
26
27
  def initialize(adapter, options = {})
28
+ super(adapter)
27
29
  @adapter = adapter
28
30
  @name = :instrumented
29
31
  @instrumenter = options.fetch(:instrumenter, Instrumenters::Noop)
@@ -1,9 +1,11 @@
1
+ require 'delegate'
2
+
1
3
  module Flipper
2
4
  module Adapters
3
5
  # Internal: Adapter that wraps another adapter with the ability to memoize
4
6
  # adapter calls in memory. Used by flipper dsl and the memoizer middleware
5
7
  # to make it possible to memoize adapter calls for the duration of a request.
6
- class Memoizable
8
+ class Memoizable < SimpleDelegator
7
9
  include ::Flipper::Adapter
8
10
 
9
11
  FeaturesKey = :flipper_features
@@ -19,6 +21,7 @@ module Flipper
19
21
 
20
22
  # Public
21
23
  def initialize(adapter, cache = nil)
24
+ super(adapter)
22
25
  @adapter = adapter
23
26
  @name = :memoizable
24
27
  @cache = cache || {}
@@ -1,9 +1,11 @@
1
+ require 'delegate'
2
+
1
3
  module Flipper
2
4
  module Adapters
3
5
  # Public: Adapter that wraps another adapter and stores the operations.
4
6
  #
5
7
  # Useful in tests to verify calls and such. Never use outside of testing.
6
- class OperationLogger
8
+ class OperationLogger < SimpleDelegator
7
9
  include ::Flipper::Adapter
8
10
 
9
11
  Operation = Struct.new(:type, :args)
@@ -26,6 +28,7 @@ module Flipper
26
28
 
27
29
  # Public
28
30
  def initialize(adapter, operations = nil)
31
+ super(adapter)
29
32
  @adapter = adapter
30
33
  @name = :operation_logger
31
34
  @operations = operations || []
data/lib/flipper/dsl.rb CHANGED
@@ -1,4 +1,3 @@
1
- require 'flipper/adapters/instrumented'
2
1
  require 'flipper/adapters/memoizable'
3
2
  require 'flipper/instrumenters/noop'
4
3
 
@@ -17,13 +16,8 @@ module Flipper
17
16
  # :instrumenter - What should be used to instrument all the things.
18
17
  def initialize(adapter, options = {})
19
18
  @instrumenter = options.fetch(:instrumenter, Instrumenters::Noop)
20
-
21
- instrumented = Adapters::Instrumented.new(adapter, {
22
- :instrumenter => @instrumenter,
23
- })
24
- memoized = Adapters::Memoizable.new(instrumented)
19
+ memoized = Adapters::Memoizable.new(adapter)
25
20
  @adapter = memoized
26
-
27
21
  @memoized_features = {}
28
22
  end
29
23
 
@@ -7,7 +7,7 @@ require 'flipper/instrumenters/noop'
7
7
  module Flipper
8
8
  class Feature
9
9
  # Private: The name of feature instrumentation events.
10
- InstrumentationName = "feature_operation.#{InstrumentationNamespace}"
10
+ InstrumentationName = "feature_operation.#{InstrumentationNamespace}".freeze
11
11
 
12
12
  # Public: The name of the feature.
13
13
  attr_reader :name
@@ -4,13 +4,13 @@ module Flipper
4
4
  class GateValues
5
5
  # Private: Array of instance variables that are readable through the []
6
6
  # instance method.
7
- LegitIvars = Set.new([
8
- "boolean",
9
- "actors",
10
- "groups",
11
- "percentage_of_time",
12
- "percentage_of_actors",
13
- ]).freeze
7
+ LegitIvars = {
8
+ "boolean" => "@boolean",
9
+ "actors" => "@actors",
10
+ "groups" => "@groups",
11
+ "percentage_of_time" => "@percentage_of_time",
12
+ "percentage_of_actors" => "@percentage_of_actors",
13
+ }.freeze
14
14
 
15
15
  attr_reader :boolean
16
16
  attr_reader :actors
@@ -27,8 +27,9 @@ module Flipper
27
27
  end
28
28
 
29
29
  def [](key)
30
- return nil unless LegitIvars.include?(key.to_s)
31
- instance_variable_get("@#{key}")
30
+ if ivar = LegitIvars[key.to_s]
31
+ instance_variable_get(ivar)
32
+ end
32
33
  end
33
34
 
34
35
  def eql?(other)
@@ -71,9 +71,11 @@ module Flipper
71
71
  update_timer "flipper.adapter.#{adapter_name}.#{operation}"
72
72
  end
73
73
 
74
+ QUESTION_MARK = "?".freeze
75
+
74
76
  # Private
75
77
  def strip_trailing_question_mark(operation)
76
- operation.to_s.chomp('?')
78
+ operation.to_s.chomp(QUESTION_MARK)
77
79
  end
78
80
  end
79
81
  end
@@ -1,249 +1,253 @@
1
- module SharedAdapterTests
2
- def setup
3
- super
4
- @flipper = Flipper.new(@adapter)
5
- @actor_class = Struct.new(:flipper_id)
6
- @feature = @flipper[:stats]
7
- @boolean_gate = @feature.gate(:boolean)
8
- @group_gate = @feature.gate(:group)
9
- @actor_gate = @feature.gate(:actor)
10
- @actors_gate = @feature.gate(:percentage_of_actors)
11
- @time_gate = @feature.gate(:percentage_of_time)
12
-
13
- Flipper.register(:admins) do |actor|
14
- actor.respond_to?(:admin?) && actor.admin?
1
+ module Flipper
2
+ module Test
3
+ module SharedAdapterTests
4
+ def setup
5
+ super
6
+ @flipper = Flipper.new(@adapter)
7
+ @actor_class = Struct.new(:flipper_id)
8
+ @feature = @flipper[:stats]
9
+ @boolean_gate = @feature.gate(:boolean)
10
+ @group_gate = @feature.gate(:group)
11
+ @actor_gate = @feature.gate(:actor)
12
+ @actors_gate = @feature.gate(:percentage_of_actors)
13
+ @time_gate = @feature.gate(:percentage_of_time)
14
+
15
+ Flipper.register(:admins) do |actor|
16
+ actor.respond_to?(:admin?) && actor.admin?
17
+ end
18
+
19
+ Flipper.register(:early_access) { |actor|
20
+ actor.respond_to?(:early_access?) && actor.early_access?
21
+ }
22
+ end
23
+
24
+ def teardown
25
+ super
26
+ Flipper.unregister_groups
27
+ end
28
+
29
+ def test_has_name_that_is_a_symbol
30
+ refute_empty @adapter.name
31
+ assert_kind_of Symbol, @adapter.name
32
+ end
33
+
34
+ def test_has_included_the_flipper_adapter_module
35
+ assert_includes @adapter.class.ancestors, Flipper::Adapter
36
+ end
37
+
38
+ def test_returns_correct_default_values_for_gates_if_none_are_enabled
39
+ expected = {
40
+ :boolean => nil,
41
+ :groups => Set.new,
42
+ :actors => Set.new,
43
+ :percentage_of_actors => nil,
44
+ :percentage_of_time => nil,
45
+ }
46
+ assert_equal expected, @adapter.get(@feature)
47
+ end
48
+
49
+ def test_can_enable_disable_and_get_value_for_boolean_gate
50
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
51
+ assert_equal 'true', @adapter.get(@feature)[:boolean]
52
+ assert_equal true, @adapter.disable(@feature, @boolean_gate, @flipper.boolean(false))
53
+ assert_equal nil, @adapter.get(@feature)[:boolean]
54
+ end
55
+
56
+ def test_fully_disables_all_enabled_things_when_boolean_gate_disabled
57
+ actor_22 = @actor_class.new('22')
58
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
59
+ assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
60
+ assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
61
+ assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
62
+ assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
63
+ assert_equal true, @adapter.disable(@feature, @boolean_gate, @flipper.boolean(false))
64
+ expected = {
65
+ :boolean => nil,
66
+ :groups => Set.new,
67
+ :actors => Set.new,
68
+ :percentage_of_actors => nil,
69
+ :percentage_of_time => nil,
70
+ }
71
+ assert_equal expected, @adapter.get(@feature)
72
+ end
73
+
74
+ def test_can_enable_disable_get_value_for_group_gate
75
+ assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
76
+ assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:early_access))
77
+
78
+ result = @adapter.get(@feature)
79
+ assert_equal Set['admins', 'early_access'], result[:groups]
80
+
81
+ assert_equal true, @adapter.disable(@feature, @group_gate, @flipper.group(:early_access))
82
+ result = @adapter.get(@feature)
83
+ assert_equal Set['admins'], result[:groups]
84
+
85
+ assert_equal true, @adapter.disable(@feature, @group_gate, @flipper.group(:admins))
86
+ result = @adapter.get(@feature)
87
+ assert_equal Set.new, result[:groups]
88
+ end
89
+
90
+ def test_can_enable_disable_and_get_value_for_an_actor_gate
91
+ actor_22 = @actor_class.new('22')
92
+ actor_asdf = @actor_class.new('asdf')
93
+
94
+ assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
95
+ assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_asdf))
96
+
97
+ result = @adapter.get(@feature)
98
+ assert_equal Set['22', 'asdf'], result[:actors]
99
+
100
+ assert true, @adapter.disable(@feature, @actor_gate, @flipper.actor(actor_22))
101
+ result = @adapter.get(@feature)
102
+ assert_equal Set['asdf'], result[:actors]
103
+
104
+ assert_equal true, @adapter.disable(@feature, @actor_gate, @flipper.actor(actor_asdf))
105
+ result = @adapter.get(@feature)
106
+ assert_equal Set.new, result[:actors]
107
+ end
108
+
109
+ def test_can_enable_disable_get_value_for_percentage_of_actors_gate
110
+ assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(15))
111
+ result = @adapter.get(@feature)
112
+ assert_equal '15', result[:percentage_of_actors]
113
+
114
+ assert_equal true, @adapter.disable(@feature, @actors_gate, @flipper.actors(0))
115
+ result = @adapter.get(@feature)
116
+ assert_equal '0', result[:percentage_of_actors]
117
+ end
118
+
119
+ def test_can_enable_percentage_of_actors_gate_many_times_and_consistently_return_values
120
+ (1..100).each do |percentage|
121
+ assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(percentage))
122
+ result = @adapter.get(@feature)
123
+ assert_equal percentage.to_s, result[:percentage_of_actors]
124
+ end
125
+ end
126
+
127
+ def test_can_disable_percentage_of_actors_gate_many_times_and_consistently_return_values
128
+ (1..100).each do |percentage|
129
+ assert_equal true, @adapter.disable(@feature, @actors_gate, @flipper.actors(percentage))
130
+ result = @adapter.get(@feature)
131
+ assert_equal percentage.to_s, result[:percentage_of_actors]
132
+ end
133
+ end
134
+
135
+ def test_can_enable_disable_and_get_value_for_percentage_of_time_gate
136
+ assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(10))
137
+ result = @adapter.get(@feature)
138
+ assert_equal '10', result[:percentage_of_time]
139
+
140
+ assert_equal true, @adapter.disable(@feature, @time_gate, @flipper.time(0))
141
+ result = @adapter.get(@feature)
142
+ assert_equal '0', result[:percentage_of_time]
143
+ end
144
+
145
+ def test_can_enable_percentage_of_time_gate_many_times_and_consistently_return_values
146
+ (1..100).each do |percentage|
147
+ assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(percentage))
148
+ result = @adapter.get(@feature)
149
+ assert_equal percentage.to_s, result[:percentage_of_time]
150
+ end
151
+ end
152
+
153
+ def test_can_disable_percentage_of_time_gate_many_times_and_consistently_return_values
154
+ (1..100).each do |percentage|
155
+ assert_equal true, @adapter.disable(@feature, @time_gate, @flipper.time(percentage))
156
+ result = @adapter.get(@feature)
157
+ assert_equal percentage.to_s, result[:percentage_of_time]
158
+ end
159
+ end
160
+
161
+ def test_converts_boolean_value_to_a_string
162
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
163
+ result = @adapter.get(@feature)
164
+ assert_equal 'true', result[:boolean]
165
+ end
166
+
167
+ def test_converts_the_actor_value_to_a_string
168
+ assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(@actor_class.new(22)))
169
+ result = @adapter.get(@feature)
170
+ assert_equal Set['22'], result[:actors]
171
+ end
172
+
173
+ def test_converts_group_value_to_a_string
174
+ assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
175
+ result = @adapter.get(@feature)
176
+ assert_equal Set['admins'], result[:groups]
177
+ end
178
+
179
+ def test_converts_percentage_of_time_integer_value_to_a_string
180
+ assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(10))
181
+ result = @adapter.get(@feature)
182
+ assert_equal '10', result[:percentage_of_time]
183
+ end
184
+
185
+ def test_converts_percentage_of_actors_integer_value_to_a_string
186
+ assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(10))
187
+ result = @adapter.get(@feature)
188
+ assert_equal '10', result[:percentage_of_actors]
189
+ end
190
+
191
+ def test_can_add_remove_and_list_known_features
192
+ assert_equal Set.new, @adapter.features
193
+
194
+ assert_equal true, @adapter.add(@flipper[:stats])
195
+ assert_equal Set['stats'], @adapter.features
196
+
197
+ assert_equal true, @adapter.add(@flipper[:search])
198
+ assert_equal Set['stats', 'search'], @adapter.features
199
+
200
+ assert_equal true, @adapter.remove(@flipper[:stats])
201
+ assert_equal Set['search'], @adapter.features
202
+
203
+ assert_equal true, @adapter.remove(@flipper[:search])
204
+ assert_equal Set.new, @adapter.features
205
+ end
206
+
207
+ def test_clears_all_the_gate_values_for_the_feature_on_remove
208
+ actor_22 = @actor_class.new('22')
209
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
210
+ assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
211
+ assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
212
+ assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
213
+ assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
214
+
215
+ assert_equal true, @adapter.remove(@feature)
216
+
217
+ assert_equal @adapter.get(@feature), {
218
+ :boolean => nil,
219
+ :groups => Set.new,
220
+ :actors => Set.new,
221
+ :percentage_of_actors => nil,
222
+ :percentage_of_time => nil,
223
+ }
224
+ end
225
+
226
+ def test_can_clear_all_the_gate_values_for_a_feature
227
+ actor_22 = @actor_class.new('22')
228
+ @adapter.add(@feature)
229
+ assert_includes @adapter.features, @feature.key
230
+
231
+ assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
232
+ assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
233
+ assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
234
+ assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
235
+ assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
236
+
237
+ assert_equal true, @adapter.clear(@feature)
238
+ assert_includes @adapter.features, @feature.key
239
+ assert_equal @adapter.get(@feature), {
240
+ :boolean => nil,
241
+ :groups => Set.new,
242
+ :actors => Set.new,
243
+ :percentage_of_actors => nil,
244
+ :percentage_of_time => nil,
245
+ }
246
+ end
247
+
248
+ def test_does_not_complain_clearing_a_feature_that_does_not_exist_in_adapter
249
+ assert_equal true, @adapter.clear(@flipper[:stats])
250
+ end
15
251
  end
16
-
17
- Flipper.register(:early_access) { |actor|
18
- actor.respond_to?(:early_access?) && actor.early_access?
19
- }
20
- end
21
-
22
- def teardown
23
- super
24
- Flipper.unregister_groups
25
- end
26
-
27
- def test_has_name_that_is_a_symbol
28
- refute_empty @adapter.name
29
- assert_kind_of Symbol, @adapter.name
30
- end
31
-
32
- def test_has_included_the_flipper_adapter_module
33
- assert_includes @adapter.class.ancestors, Flipper::Adapter
34
- end
35
-
36
- def test_returns_correct_default_values_for_gates_if_none_are_enabled
37
- expected = {
38
- :boolean => nil,
39
- :groups => Set.new,
40
- :actors => Set.new,
41
- :percentage_of_actors => nil,
42
- :percentage_of_time => nil,
43
- }
44
- assert_equal expected, @adapter.get(@feature)
45
- end
46
-
47
- def test_can_enable_disable_and_get_value_for_boolean_gate
48
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
49
- assert_equal 'true', @adapter.get(@feature)[:boolean]
50
- assert_equal true, @adapter.disable(@feature, @boolean_gate, @flipper.boolean(false))
51
- assert_equal nil, @adapter.get(@feature)[:boolean]
52
- end
53
-
54
- def test_fully_disables_all_enabled_things_when_boolean_gate_disabled
55
- actor_22 = @actor_class.new('22')
56
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
57
- assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
58
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
59
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
60
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
61
- assert_equal true, @adapter.disable(@feature, @boolean_gate, @flipper.boolean(false))
62
- expected = {
63
- :boolean => nil,
64
- :groups => Set.new,
65
- :actors => Set.new,
66
- :percentage_of_actors => nil,
67
- :percentage_of_time => nil,
68
- }
69
- assert_equal expected, @adapter.get(@feature)
70
- end
71
-
72
- def test_can_enable_disable_get_value_for_group_gate
73
- assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
74
- assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:early_access))
75
-
76
- result = @adapter.get(@feature)
77
- assert_equal Set['admins', 'early_access'], result[:groups]
78
-
79
- assert_equal true, @adapter.disable(@feature, @group_gate, @flipper.group(:early_access))
80
- result = @adapter.get(@feature)
81
- assert_equal Set['admins'], result[:groups]
82
-
83
- assert_equal true, @adapter.disable(@feature, @group_gate, @flipper.group(:admins))
84
- result = @adapter.get(@feature)
85
- assert_equal Set.new, result[:groups]
86
- end
87
-
88
- def test_can_enable_disable_and_get_value_for_an_actor_gate
89
- actor_22 = @actor_class.new('22')
90
- actor_asdf = @actor_class.new('asdf')
91
-
92
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
93
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_asdf))
94
-
95
- result = @adapter.get(@feature)
96
- assert_equal Set['22', 'asdf'], result[:actors]
97
-
98
- assert true, @adapter.disable(@feature, @actor_gate, @flipper.actor(actor_22))
99
- result = @adapter.get(@feature)
100
- assert_equal Set['asdf'], result[:actors]
101
-
102
- assert_equal true, @adapter.disable(@feature, @actor_gate, @flipper.actor(actor_asdf))
103
- result = @adapter.get(@feature)
104
- assert_equal Set.new, result[:actors]
105
- end
106
-
107
- def test_can_enable_disable_get_value_for_percentage_of_actors_gate
108
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(15))
109
- result = @adapter.get(@feature)
110
- assert_equal '15', result[:percentage_of_actors]
111
-
112
- assert_equal true, @adapter.disable(@feature, @actors_gate, @flipper.actors(0))
113
- result = @adapter.get(@feature)
114
- assert_equal '0', result[:percentage_of_actors]
115
- end
116
-
117
- def test_can_enable_percentage_of_actors_gate_many_times_and_consistently_return_values
118
- (1..100).each do |percentage|
119
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(percentage))
120
- result = @adapter.get(@feature)
121
- assert_equal percentage.to_s, result[:percentage_of_actors]
122
- end
123
- end
124
-
125
- def test_can_disable_percentage_of_actors_gate_many_times_and_consistently_return_values
126
- (1..100).each do |percentage|
127
- assert_equal true, @adapter.disable(@feature, @actors_gate, @flipper.actors(percentage))
128
- result = @adapter.get(@feature)
129
- assert_equal percentage.to_s, result[:percentage_of_actors]
130
- end
131
- end
132
-
133
- def test_can_enable_disable_and_get_value_for_percentage_of_time_gate
134
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(10))
135
- result = @adapter.get(@feature)
136
- assert_equal '10', result[:percentage_of_time]
137
-
138
- assert_equal true, @adapter.disable(@feature, @time_gate, @flipper.time(0))
139
- result = @adapter.get(@feature)
140
- assert_equal '0', result[:percentage_of_time]
141
- end
142
-
143
- def test_can_enable_percentage_of_time_gate_many_times_and_consistently_return_values
144
- (1..100).each do |percentage|
145
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(percentage))
146
- result = @adapter.get(@feature)
147
- assert_equal percentage.to_s, result[:percentage_of_time]
148
- end
149
- end
150
-
151
- def test_can_disable_percentage_of_time_gate_many_times_and_consistently_return_values
152
- (1..100).each do |percentage|
153
- assert_equal true, @adapter.disable(@feature, @time_gate, @flipper.time(percentage))
154
- result = @adapter.get(@feature)
155
- assert_equal percentage.to_s, result[:percentage_of_time]
156
- end
157
- end
158
-
159
- def test_converts_boolean_value_to_a_string
160
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
161
- result = @adapter.get(@feature)
162
- assert_equal 'true', result[:boolean]
163
- end
164
-
165
- def test_converts_the_actor_value_to_a_string
166
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(@actor_class.new(22)))
167
- result = @adapter.get(@feature)
168
- assert_equal Set['22'], result[:actors]
169
- end
170
-
171
- def test_converts_group_value_to_a_string
172
- assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
173
- result = @adapter.get(@feature)
174
- assert_equal Set['admins'], result[:groups]
175
- end
176
-
177
- def test_converts_percentage_of_time_integer_value_to_a_string
178
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(10))
179
- result = @adapter.get(@feature)
180
- assert_equal '10', result[:percentage_of_time]
181
- end
182
-
183
- def test_converts_percentage_of_actors_integer_value_to_a_string
184
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(10))
185
- result = @adapter.get(@feature)
186
- assert_equal '10', result[:percentage_of_actors]
187
- end
188
-
189
- def test_can_add_remove_and_list_known_features
190
- assert_equal Set.new, @adapter.features
191
-
192
- assert_equal true, @adapter.add(@flipper[:stats])
193
- assert_equal Set['stats'], @adapter.features
194
-
195
- assert_equal true, @adapter.add(@flipper[:search])
196
- assert_equal Set['stats', 'search'], @adapter.features
197
-
198
- assert_equal true, @adapter.remove(@flipper[:stats])
199
- assert_equal Set['search'], @adapter.features
200
-
201
- assert_equal true, @adapter.remove(@flipper[:search])
202
- assert_equal Set.new, @adapter.features
203
- end
204
-
205
- def test_clears_all_the_gate_values_for_the_feature_on_remove
206
- actor_22 = @actor_class.new('22')
207
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
208
- assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
209
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
210
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
211
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
212
-
213
- assert_equal true, @adapter.remove(@feature)
214
-
215
- assert_equal @adapter.get(@feature), {
216
- :boolean => nil,
217
- :groups => Set.new,
218
- :actors => Set.new,
219
- :percentage_of_actors => nil,
220
- :percentage_of_time => nil,
221
- }
222
- end
223
-
224
- def test_can_clear_all_the_gate_values_for_a_feature
225
- actor_22 = @actor_class.new('22')
226
- @adapter.add(@feature)
227
- assert_includes @adapter.features, @feature.key
228
-
229
- assert_equal true, @adapter.enable(@feature, @boolean_gate, @flipper.boolean)
230
- assert_equal true, @adapter.enable(@feature, @group_gate, @flipper.group(:admins))
231
- assert_equal true, @adapter.enable(@feature, @actor_gate, @flipper.actor(actor_22))
232
- assert_equal true, @adapter.enable(@feature, @actors_gate, @flipper.actors(25))
233
- assert_equal true, @adapter.enable(@feature, @time_gate, @flipper.time(45))
234
-
235
- assert_equal true, @adapter.clear(@feature)
236
- assert_includes @adapter.features, @feature.key
237
- assert_equal @adapter.get(@feature), {
238
- :boolean => nil,
239
- :groups => Set.new,
240
- :actors => Set.new,
241
- :percentage_of_actors => nil,
242
- :percentage_of_time => nil,
243
- }
244
- end
245
-
246
- def test_does_not_complain_clearing_a_feature_that_does_not_exist_in_adapter
247
- assert_equal true, @adapter.clear(@flipper[:stats])
248
252
  end
249
253
  end
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0.beta1".freeze
3
3
  end
@@ -19,6 +19,16 @@ RSpec.describe Flipper::Adapters::Instrumented do
19
19
 
20
20
  it_should_behave_like 'a flipper adapter'
21
21
 
22
+ it "forwards missing methods to underlying adapter" do
23
+ adapter = Class.new do
24
+ def foo
25
+ :foo
26
+ end
27
+ end.new
28
+ instrumented = described_class.new(adapter)
29
+ expect(instrumented.foo).to eq(:foo)
30
+ end
31
+
22
32
  describe "#name" do
23
33
  it "is instrumented" do
24
34
  expect(subject.name).to be(:instrumented)
@@ -13,6 +13,16 @@ RSpec.describe Flipper::Adapters::Memoizable do
13
13
 
14
14
  it_should_behave_like 'a flipper adapter'
15
15
 
16
+ it "forwards missing methods to underlying adapter" do
17
+ adapter = Class.new do
18
+ def foo
19
+ :foo
20
+ end
21
+ end.new
22
+ memoizable = described_class.new(adapter)
23
+ expect(memoizable.foo).to eq(:foo)
24
+ end
25
+
16
26
  describe "#name" do
17
27
  it "is instrumented" do
18
28
  expect(subject.name).to be(:memoizable)
@@ -12,6 +12,16 @@ RSpec.describe Flipper::Adapters::OperationLogger do
12
12
 
13
13
  it_should_behave_like 'a flipper adapter'
14
14
 
15
+ it "forwards missing methods to underlying adapter" do
16
+ adapter = Class.new do
17
+ def foo
18
+ :foo
19
+ end
20
+ end.new
21
+ operation_logger = described_class.new(adapter)
22
+ expect(operation_logger.foo).to eq(:foo)
23
+ end
24
+
15
25
  describe "#get" do
16
26
  before do
17
27
  @feature = flipper[:stats]
@@ -25,13 +25,6 @@ RSpec.describe Flipper::DSL do
25
25
  dsl = described_class.new(adapter, :instrumenter => instrumenter)
26
26
  expect(dsl.instrumenter).to be(instrumenter)
27
27
  end
28
-
29
- it "passes overridden instrumenter to instrumented adapter" do
30
- dsl = described_class.new(adapter, :instrumenter => instrumenter)
31
- memoized = dsl.adapter
32
- instrumented = memoized.adapter
33
- expect(instrumented.instrumenter).to be(instrumenter)
34
- end
35
28
  end
36
29
  end
37
30
 
@@ -1,10 +1,14 @@
1
1
  require 'logger'
2
2
  require 'helper'
3
+ require 'flipper/adapters/instrumented'
3
4
  require 'flipper/adapters/memory'
4
5
  require 'flipper/instrumentation/log_subscriber'
5
6
 
6
7
  RSpec.describe Flipper::Instrumentation::LogSubscriber do
7
- let(:adapter) { Flipper::Adapters::Memory.new }
8
+ let(:adapter) {
9
+ memory = Flipper::Adapters::Memory.new
10
+ Flipper::Adapters::Instrumented.new(memory, :instrumenter => ActiveSupport::Notifications)
11
+ }
8
12
  let(:flipper) {
9
13
  Flipper.new(adapter, :instrumenter => ActiveSupport::Notifications)
10
14
  }
@@ -3,7 +3,10 @@ require 'flipper/adapters/memory'
3
3
  require 'flipper/instrumentation/metriks'
4
4
 
5
5
  RSpec.describe Flipper::Instrumentation::MetriksSubscriber do
6
- let(:adapter) { Flipper::Adapters::Memory.new }
6
+ let(:adapter) {
7
+ memory = Flipper::Adapters::Memory.new
8
+ Flipper::Adapters::Instrumented.new(memory, :instrumenter => ActiveSupport::Notifications)
9
+ }
7
10
  let(:flipper) {
8
11
  Flipper.new(adapter, :instrumenter => ActiveSupport::Notifications)
9
12
  }
@@ -5,7 +5,10 @@ require 'flipper/instrumentation/statsd'
5
5
  RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
6
6
  let(:statsd_client) { Statsd.new }
7
7
  let(:socket) { FakeUDPSocket.new }
8
- let(:adapter) { Flipper::Adapters::Memory.new }
8
+ let(:adapter) {
9
+ memory = Flipper::Adapters::Memory.new
10
+ Flipper::Adapters::Instrumented.new(memory, :instrumenter => ActiveSupport::Notifications)
11
+ }
9
12
  let(:flipper) {
10
13
  Flipper.new(adapter, :instrumenter => ActiveSupport::Notifications)
11
14
  }
@@ -2,7 +2,7 @@ require 'test_helper'
2
2
  require 'flipper/adapters/memory'
3
3
 
4
4
  class MemoryTest < MiniTest::Test
5
- prepend SharedAdapterTests
5
+ prepend Flipper::Test::SharedAdapterTests
6
6
 
7
7
  def setup
8
8
  @adapter = Flipper::Adapters::Memory.new
@@ -2,7 +2,7 @@ require 'test_helper'
2
2
  require 'flipper/adapters/pstore'
3
3
 
4
4
  class PstoreTest < MiniTest::Test
5
- prepend SharedAdapterTests
5
+ prepend Flipper::Test::SharedAdapterTests
6
6
 
7
7
  def setup
8
8
  dir = FlipperRoot.join("tmp").tap { |d| d.mkpath }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flipper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-21 00:00:00.000000000 Z
11
+ date: 2016-06-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Feature flipper is the act of enabling/disabling features in your application,
14
14
  ideally without re-deploying or changing anything in your code base. Flipper makes
@@ -133,9 +133,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
133
  version: '0'
134
134
  required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ">="
136
+ - - ">"
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: 1.3.1
139
139
  requirements: []
140
140
  rubyforge_project:
141
141
  rubygems_version: 2.4.5.1