flipper 0.4.0 → 0.5.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.
Files changed (59) hide show
  1. data/Guardfile +3 -8
  2. data/README.md +26 -38
  3. data/examples/percentage_of_actors.rb +17 -12
  4. data/examples/percentage_of_random.rb +3 -7
  5. data/lib/flipper.rb +8 -1
  6. data/lib/flipper/adapter.rb +2 -208
  7. data/lib/flipper/adapters/decorator.rb +9 -0
  8. data/lib/flipper/adapters/instrumented.rb +92 -0
  9. data/lib/flipper/adapters/memoizable.rb +88 -0
  10. data/lib/flipper/adapters/memory.rb +89 -7
  11. data/lib/flipper/adapters/operation_logger.rb +31 -45
  12. data/lib/flipper/decorator.rb +6 -0
  13. data/lib/flipper/dsl.rb +29 -2
  14. data/lib/flipper/feature.rb +83 -49
  15. data/lib/flipper/gate.rb +24 -41
  16. data/lib/flipper/gates/actor.rb +24 -24
  17. data/lib/flipper/gates/boolean.rb +28 -15
  18. data/lib/flipper/gates/group.rb +25 -34
  19. data/lib/flipper/gates/percentage_of_actors.rb +21 -13
  20. data/lib/flipper/gates/percentage_of_random.rb +20 -12
  21. data/lib/flipper/instrumentation/log_subscriber.rb +14 -22
  22. data/lib/flipper/middleware/memoizer.rb +23 -0
  23. data/lib/flipper/spec/shared_adapter_specs.rb +141 -92
  24. data/lib/flipper/types/boolean.rb +5 -1
  25. data/lib/flipper/version.rb +1 -1
  26. data/spec/flipper/adapters/instrumented_spec.rb +92 -0
  27. data/spec/flipper/adapters/memoizable_spec.rb +184 -0
  28. data/spec/flipper/adapters/memory_spec.rb +1 -11
  29. data/spec/flipper/adapters/operation_logger_spec.rb +93 -0
  30. data/spec/flipper/dsl_spec.rb +18 -43
  31. data/spec/flipper/feature_spec.rb +25 -9
  32. data/spec/flipper/gate_spec.rb +8 -20
  33. data/spec/flipper/gates/actor_spec.rb +6 -14
  34. data/spec/flipper/gates/boolean_spec.rb +80 -13
  35. data/spec/flipper/gates/group_spec.rb +8 -18
  36. data/spec/flipper/gates/percentage_of_actors_spec.rb +12 -28
  37. data/spec/flipper/gates/percentage_of_random_spec.rb +6 -14
  38. data/spec/flipper/instrumentation/log_subscriber_spec.rb +15 -8
  39. data/spec/flipper/instrumentation/metriks_subscriber_spec.rb +3 -6
  40. data/spec/flipper/middleware/{local_cache_spec.rb → memoizer_spec.rb} +25 -55
  41. data/spec/flipper/types/boolean_spec.rb +13 -3
  42. data/spec/flipper_spec.rb +7 -0
  43. data/spec/helper.rb +21 -3
  44. data/spec/integration_spec.rb +115 -116
  45. metadata +17 -27
  46. data/lib/flipper/adapters/memoized.rb +0 -55
  47. data/lib/flipper/key.rb +0 -38
  48. data/lib/flipper/middleware/local_cache.rb +0 -36
  49. data/lib/flipper/toggle.rb +0 -54
  50. data/lib/flipper/toggles/boolean.rb +0 -54
  51. data/lib/flipper/toggles/set.rb +0 -25
  52. data/lib/flipper/toggles/value.rb +0 -25
  53. data/spec/flipper/adapter_spec.rb +0 -463
  54. data/spec/flipper/adapters/memoized_spec.rb +0 -93
  55. data/spec/flipper/key_spec.rb +0 -23
  56. data/spec/flipper/toggle_spec.rb +0 -22
  57. data/spec/flipper/toggles/boolean_spec.rb +0 -40
  58. data/spec/flipper/toggles/set_spec.rb +0 -35
  59. data/spec/flipper/toggles/value_spec.rb +0 -55
@@ -38,16 +38,13 @@ describe Flipper::Instrumentation::MetriksSubscriber do
38
38
 
39
39
  it "updates adapter metrics when calls happen" do
40
40
  flipper[:stats].enable(user)
41
- # one for features and one for actors
42
- Metriks.timer("flipper.adapter.memory.set_add").count.should be(2)
41
+ Metriks.timer("flipper.adapter.memory.enable").count.should be(1)
43
42
 
44
43
  flipper[:stats].enabled?(user)
45
- Metriks.timer("flipper.adapter.memory.read").count.should be(1)
46
- # one for actors and one for groups
47
- Metriks.timer("flipper.adapter.memory.set_members").count.should be(2)
44
+ Metriks.timer("flipper.adapter.memory.get").count.should be(1)
48
45
 
49
46
  flipper[:stats].disable(user)
50
- Metriks.timer("flipper.adapter.memory.set_delete").count.should be(1)
47
+ Metriks.timer("flipper.adapter.memory.disable").count.should be(1)
51
48
  end
52
49
 
53
50
  it "updates gate metrics when calls happen" do
@@ -1,18 +1,12 @@
1
1
  require 'helper'
2
2
  require 'rack/test'
3
- require 'flipper/middleware/local_cache'
3
+ require 'flipper/middleware/memoizer'
4
4
  require 'flipper/adapters/operation_logger'
5
5
  require 'flipper/adapters/memory'
6
6
 
7
- describe Flipper::Middleware::LocalCache do
7
+ describe Flipper::Middleware::Memoizer do
8
8
  include Rack::Test::Methods
9
9
 
10
- class Enum < Struct.new(:iter)
11
- def each(&block)
12
- iter.call(&block)
13
- end
14
- end
15
-
16
10
  let(:source) { {} }
17
11
  let(:memory_adapter) { Flipper::Adapters::Memory.new(source) }
18
12
  let(:adapter) { Flipper::Adapters::OperationLogger.new(memory_adapter) }
@@ -36,8 +30,8 @@ describe Flipper::Middleware::LocalCache do
36
30
  end.to_app
37
31
  }
38
32
 
39
- before do
40
- adapter.reset
33
+ after do
34
+ flipper.adapter.memoize = nil
41
35
  end
42
36
 
43
37
  it "delegates" do
@@ -51,50 +45,42 @@ describe Flipper::Middleware::LocalCache do
51
45
  called.should be_true
52
46
  end
53
47
 
54
- it "enables memoization during delegation" do
55
- app = lambda { |env|
56
- flipper.adapter.using_local_cache?.should be_true
57
- [200, {}, nil]
58
- }
59
- middleware = described_class.new app, flipper
60
- middleware.call({})
61
- end
62
-
63
- it "enables local cache for body each" do
64
- app = lambda { |env|
65
- [200, {}, Enum.new(lambda { |&block|
66
- flipper.adapter.using_local_cache?.should be_true
67
- block.call "hello"
68
- })]
69
- }
70
- middleware = described_class.new app, flipper
71
- body = middleware.call({}).last
72
- body.each { |x| x.should eql('hello') }
73
- end
74
-
75
48
  it "disables local cache after body close" do
76
49
  app = lambda { |env| [200, {}, []] }
77
50
  middleware = described_class.new app, flipper
78
51
  body = middleware.call({}).last
79
52
 
80
- flipper.adapter.using_local_cache?.should be_true
53
+ flipper.adapter.memoizing?.should be_true
81
54
  body.close
82
- flipper.adapter.using_local_cache?.should be_false
55
+ flipper.adapter.memoizing?.should be_false
83
56
  end
84
57
 
85
58
  it "clears local cache after body close" do
86
59
  app = lambda { |env| [200, {}, []] }
87
60
  middleware = described_class.new app, flipper
88
61
  body = middleware.call({}).last
89
- flipper.adapter.local_cache['hello'] = 'world'
90
62
 
91
- flipper.adapter.local_cache.should_not be_empty
63
+ flipper.adapter.cache['hello'] = 'world'
92
64
  body.close
93
- flipper.adapter.local_cache.should be_empty
65
+ flipper.adapter.cache.should be_empty
66
+ end
67
+
68
+ it "clears the local cache with a successful request" do
69
+ flipper.adapter.cache['hello'] = 'world'
70
+ get '/'
71
+ flipper.adapter.cache.should be_empty
94
72
  end
95
73
 
96
- it "really does cache" do
74
+ it "clears the local cache even when the request raises an error" do
75
+ flipper.adapter.cache['hello'] = 'world'
76
+ get '/fail' rescue nil
77
+ flipper.adapter.cache.should be_empty
78
+ end
79
+
80
+ it "caches getting a feature for duration of request" do
97
81
  flipper[:stats].enable
82
+
83
+ # clear the log of operations
98
84
  adapter.reset
99
85
 
100
86
  app = lambda { |env|
@@ -104,28 +90,12 @@ describe Flipper::Middleware::LocalCache do
104
90
  flipper[:stats].enabled?
105
91
  flipper[:stats].enabled?
106
92
  flipper[:stats].enabled?
107
-
108
93
  [200, {}, []]
109
94
  }
95
+
110
96
  middleware = described_class.new app, flipper
111
97
  middleware.call({})
112
98
 
113
- adapter.operations.should eq([
114
- Flipper::Adapters::OperationLogger::Read.new("stats/boolean"),
115
- ])
116
- end
117
-
118
- context "with a successful request" do
119
- it "clears the local cache" do
120
- flipper.adapter.local_cache.should_receive(:clear).twice
121
- get '/'
122
- end
123
- end
124
-
125
- context "when the request raises an error" do
126
- it "clears the local cache" do
127
- flipper.adapter.local_cache.should_receive(:clear).once
128
- get '/fail' rescue nil
129
- end
99
+ adapter.count(:get).should be(1)
130
100
  end
131
101
  end
@@ -2,8 +2,18 @@ require 'helper'
2
2
  require 'flipper/types/boolean'
3
3
 
4
4
  describe Flipper::Types::Boolean do
5
- it "initializes with nothing" do
6
- switch = Flipper::Types::Boolean.new
7
- switch.should be_instance_of(Flipper::Types::Boolean)
5
+ it "defaults value to true" do
6
+ boolean = Flipper::Types::Boolean.new
7
+ boolean.value.should be(true)
8
+ end
9
+
10
+ it "allows overriding default value" do
11
+ boolean = Flipper::Types::Boolean.new(false)
12
+ boolean.value.should be(false)
13
+ end
14
+
15
+ it "returns true for nil value" do
16
+ boolean = Flipper::Types::Boolean.new(nil)
17
+ boolean.value.should be(true)
8
18
  end
9
19
  end
data/spec/flipper_spec.rb CHANGED
@@ -46,6 +46,13 @@ describe Flipper do
46
46
  end
47
47
  end
48
48
 
49
+ describe ".unregister_groups" do
50
+ it "clear group registry" do
51
+ Flipper.groups.should_receive(:clear)
52
+ Flipper.unregister_groups
53
+ end
54
+ end
55
+
49
56
  describe ".group" do
50
57
  context "for registered group" do
51
58
  before do
data/spec/helper.rb CHANGED
@@ -24,7 +24,7 @@ RSpec.configure do |config|
24
24
  config.run_all_when_everything_filtered = true
25
25
 
26
26
  config.before(:each) do
27
- Flipper.groups = nil
27
+ Flipper.unregister_groups
28
28
  end
29
29
  end
30
30
 
@@ -67,7 +67,7 @@ shared_examples_for 'a DSL feature' do
67
67
  end
68
68
 
69
69
  it "sets adapter" do
70
- feature.adapter.should eq(dsl.adapter)
70
+ feature.adapter.name.should eq(dsl.adapter.name)
71
71
  end
72
72
 
73
73
  it "sets instrumenter" do
@@ -75,6 +75,24 @@ shared_examples_for 'a DSL feature' do
75
75
  end
76
76
 
77
77
  it "memoizes the feature" do
78
- dsl.feature(:stats).should equal(feature)
78
+ dsl.send(method_name, :stats).should equal(feature)
79
+ end
80
+
81
+ it "raises argument error if not string or symbol" do
82
+ expect {
83
+ dsl.send(method_name, Object.new)
84
+ }.to raise_error(ArgumentError, /must be a String or Symbol/)
85
+ end
86
+ end
87
+
88
+ shared_examples_for "a DSL boolean method" do
89
+ it "returns boolean with value set" do
90
+ result = subject.send(method_name, true)
91
+ result.should be_instance_of(Flipper::Types::Boolean)
92
+ result.value.should be(true)
93
+
94
+ result = subject.send(method_name, false)
95
+ result.should be_instance_of(Flipper::Types::Boolean)
96
+ result.value.should be(false)
79
97
  end
80
98
  end
@@ -2,16 +2,17 @@ require 'helper'
2
2
  require 'flipper/feature'
3
3
  require 'flipper/adapters/memory'
4
4
 
5
- describe Flipper::Feature do
6
- subject { described_class.new(:search, adapter) }
7
-
8
- let(:actor_class) { Struct.new(:flipper_id) }
9
-
5
+ describe Flipper do
10
6
  let(:source) { {} }
11
7
  let(:adapter) { Flipper::Adapters::Memory.new(source) }
12
8
 
13
- let(:admin_group) { Flipper.group(:admins) }
14
- let(:dev_group) { Flipper.group(:devs) }
9
+ let(:flipper) { Flipper.new(adapter) }
10
+ let(:feature) { flipper[:search] }
11
+
12
+ let(:actor_class) { Struct.new(:flipper_id) }
13
+
14
+ let(:admin_group) { flipper.group(:admins) }
15
+ let(:dev_group) { flipper.group(:devs) }
15
16
 
16
17
  let(:admin_thing) { double 'Non Flipper Thing', :flipper_id => 1, :admin? => true, :dev? => false }
17
18
  let(:dev_thing) { double 'Non Flipper Thing', :flipper_id => 10, :admin? => false, :dev? => true }
@@ -19,22 +20,18 @@ describe Flipper::Feature do
19
20
  let(:pitt) { actor_class.new(1) }
20
21
  let(:clooney) { actor_class.new(10) }
21
22
 
22
- let(:five_percent_of_actors) { Flipper::Types::PercentageOfActors.new(5) }
23
- let(:five_percent_of_random) { Flipper::Types::PercentageOfRandom.new(5) }
23
+ let(:five_percent_of_actors) { flipper.actors(5) }
24
+ let(:five_percent_of_random) { flipper.random(5) }
24
25
 
25
26
  before do
26
27
  Flipper.register(:admins) { |thing| thing.admin? }
27
28
  Flipper.register(:devs) { |thing| thing.dev? }
28
29
  end
29
30
 
30
- after do
31
- Flipper.groups = nil
32
- end
33
-
34
31
  describe "#enable" do
35
32
  context "with no arguments" do
36
33
  before do
37
- @result = subject.enable
34
+ @result = feature.enable
38
35
  end
39
36
 
40
37
  it "returns true" do
@@ -42,17 +39,17 @@ describe Flipper::Feature do
42
39
  end
43
40
 
44
41
  it "enables feature for all" do
45
- subject.enabled?.should be_true
42
+ feature.enabled?.should be_true
46
43
  end
47
44
 
48
45
  it "adds feature to set of features" do
49
- adapter.set_members('features').should include('search')
46
+ flipper.features.map(&:name).should include(:search)
50
47
  end
51
48
  end
52
49
 
53
50
  context "with a group" do
54
51
  before do
55
- @result = subject.enable(admin_group)
52
+ @result = feature.enable(admin_group)
56
53
  end
57
54
 
58
55
  it "returns true" do
@@ -60,33 +57,33 @@ describe Flipper::Feature do
60
57
  end
61
58
 
62
59
  it "enables feature for non flipper thing in group" do
63
- subject.enabled?(admin_thing).should be_true
60
+ feature.enabled?(admin_thing).should be_true
64
61
  end
65
62
 
66
63
  it "does not enable feature for non flipper thing in other group" do
67
- subject.enabled?(dev_thing).should be_false
64
+ feature.enabled?(dev_thing).should be_false
68
65
  end
69
66
 
70
67
  it "enables feature for flipper actor in group" do
71
- subject.enabled?(Flipper::Types::Actor.new(admin_thing)).should be_true
68
+ feature.enabled?(flipper.actor(admin_thing)).should be_true
72
69
  end
73
70
 
74
71
  it "does not enable for flipper actor not in group" do
75
- subject.enabled?(Flipper::Types::Actor.new(dev_thing)).should be_false
72
+ feature.enabled?(flipper.actor(dev_thing)).should be_false
76
73
  end
77
74
 
78
75
  it "does not enable feature for all" do
79
- subject.enabled?.should be_false
76
+ feature.enabled?.should be_false
80
77
  end
81
78
 
82
79
  it "adds feature to set of features" do
83
- adapter.set_members('features').should include('search')
80
+ flipper.features.map(&:name).should include(:search)
84
81
  end
85
82
  end
86
83
 
87
84
  context "with an actor" do
88
85
  before do
89
- @result = subject.enable(pitt)
86
+ @result = feature.enable(pitt)
90
87
  end
91
88
 
92
89
  it "returns true" do
@@ -94,21 +91,21 @@ describe Flipper::Feature do
94
91
  end
95
92
 
96
93
  it "enables feature for actor" do
97
- subject.enabled?(pitt).should be_true
94
+ feature.enabled?(pitt).should be_true
98
95
  end
99
96
 
100
97
  it "does not enable feature for other actors" do
101
- subject.enabled?(clooney).should be_false
98
+ feature.enabled?(clooney).should be_false
102
99
  end
103
100
 
104
101
  it "adds feature to set of features" do
105
- adapter.set_members('features').should include('search')
102
+ flipper.features.map(&:name).should include(:search)
106
103
  end
107
104
  end
108
105
 
109
106
  context "with a percentage of actors" do
110
107
  before do
111
- @result = subject.enable(five_percent_of_actors)
108
+ @result = feature.enable(five_percent_of_actors)
112
109
  end
113
110
 
114
111
  it "returns true" do
@@ -118,22 +115,21 @@ describe Flipper::Feature do
118
115
  it "enables feature for actor within percentage" do
119
116
  enabled = (1..100).select { |i|
120
117
  thing = actor_class.new(i)
121
- subject.enabled?(thing)
118
+ feature.enabled?(thing)
122
119
  }.size
123
120
 
124
121
  enabled.should be_within(2).of(5)
125
122
  end
126
123
 
127
124
  it "adds feature to set of features" do
128
- adapter.set_members('features').should include('search')
125
+ flipper.features.map(&:name).should include(:search)
129
126
  end
130
127
  end
131
128
 
132
129
  context "with a percentage of random" do
133
130
  before do
134
- @gate = Flipper::Gates::PercentageOfRandom.new(subject)
135
- Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
136
- @result = subject.enable(five_percent_of_random)
131
+ @gate = feature.gate(:percentage_of_random)
132
+ @result = feature.enable(five_percent_of_random)
137
133
  end
138
134
 
139
135
  it "returns true" do
@@ -142,16 +138,16 @@ describe Flipper::Feature do
142
138
 
143
139
  it "enables feature for time within percentage" do
144
140
  @gate.stub(:rand => 0.04)
145
- subject.enabled?.should be_true
141
+ feature.enabled?.should be_true
146
142
  end
147
143
 
148
144
  it "does not enable feature for time not within percentage" do
149
145
  @gate.stub(:rand => 0.10)
150
- subject.enabled?.should be_false
146
+ feature.enabled?.should be_false
151
147
  end
152
148
 
153
149
  it "adds feature to set of features" do
154
- adapter.set_members('features').should include('search')
150
+ flipper.features.map(&:name).should include(:search)
155
151
  end
156
152
  end
157
153
 
@@ -159,7 +155,7 @@ describe Flipper::Feature do
159
155
  it "raises error" do
160
156
  thing = Object.new
161
157
  expect {
162
- subject.enable(thing)
158
+ feature.enable(thing)
163
159
  }.to raise_error(Flipper::GateNotFound, "Could not find gate for #{thing.inspect}")
164
160
  end
165
161
  end
@@ -169,14 +165,14 @@ describe Flipper::Feature do
169
165
  context "with no arguments" do
170
166
  before do
171
167
  # ensures that random gate is stubbed with result that would be true for pitt
172
- @gate = Flipper::Gates::PercentageOfRandom.new(subject)
168
+ @gate = feature.gate(:percentage_of_random)
173
169
  @gate.stub(:rand => 0.04)
174
- Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
175
- subject.enable admin_group
176
- subject.enable pitt
177
- subject.enable five_percent_of_actors
178
- subject.enable five_percent_of_random
179
- @result = subject.disable
170
+
171
+ feature.enable admin_group
172
+ feature.enable pitt
173
+ feature.enable five_percent_of_actors
174
+ feature.enable five_percent_of_random
175
+ @result = feature.disable
180
176
  end
181
177
 
182
178
  it "returns true" do
@@ -184,40 +180,40 @@ describe Flipper::Feature do
184
180
  end
185
181
 
186
182
  it "disables feature" do
187
- subject.enabled?.should be_false
183
+ feature.enabled?.should be_false
188
184
  end
189
185
 
190
186
  it "disables for individual actor" do
191
- subject.enabled?(pitt).should be_false
187
+ feature.enabled?(pitt).should be_false
192
188
  end
193
189
 
194
190
  it "disables actor in group" do
195
- subject.enabled?(admin_thing).should be_false
191
+ feature.enabled?(admin_thing).should be_false
196
192
  end
197
193
 
198
194
  it "disables actor in percentage of actors" do
199
195
  enabled = (1..100).select { |i|
200
196
  thing = actor_class.new(i)
201
- subject.enabled?(thing)
197
+ feature.enabled?(thing)
202
198
  }.size
203
199
 
204
200
  enabled.should be(0)
205
201
  end
206
202
 
207
203
  it "disables percentage of random" do
208
- subject.enabled?(pitt).should be_false
204
+ feature.enabled?(pitt).should be_false
209
205
  end
210
206
 
211
207
  it "adds feature to set of features" do
212
- adapter.set_members('features').should include('search')
208
+ flipper.features.map(&:name).should include(:search)
213
209
  end
214
210
  end
215
211
 
216
212
  context "with a group" do
217
213
  before do
218
- subject.enable dev_group
219
- subject.enable admin_group
220
- @result = subject.disable(admin_group)
214
+ feature.enable dev_group
215
+ feature.enable admin_group
216
+ @result = feature.disable(admin_group)
221
217
  end
222
218
 
223
219
  it "returns true" do
@@ -225,31 +221,31 @@ describe Flipper::Feature do
225
221
  end
226
222
 
227
223
  it "disables the feature for non flipper thing in the group" do
228
- subject.enabled?(admin_thing).should be_false
224
+ feature.enabled?(admin_thing).should be_false
229
225
  end
230
226
 
231
227
  it "does not disable feature for non flipper thing in other groups" do
232
- subject.enabled?(dev_thing).should be_true
228
+ feature.enabled?(dev_thing).should be_true
233
229
  end
234
230
 
235
231
  it "disables feature for flipper actor in group" do
236
- subject.enabled?(Flipper::Types::Actor.new(admin_thing)).should be_false
232
+ feature.enabled?(flipper.actor(admin_thing)).should be_false
237
233
  end
238
234
 
239
235
  it "does not disable feature for flipper actor in other groups" do
240
- subject.enabled?(Flipper::Types::Actor.new(dev_thing)).should be_true
236
+ feature.enabled?(flipper.actor(dev_thing)).should be_true
241
237
  end
242
238
 
243
239
  it "adds feature to set of features" do
244
- adapter.set_members('features').should include('search')
240
+ flipper.features.map(&:name).should include(:search)
245
241
  end
246
242
  end
247
243
 
248
244
  context "with an actor" do
249
245
  before do
250
- subject.enable pitt
251
- subject.enable clooney
252
- @result = subject.disable(pitt)
246
+ feature.enable pitt
247
+ feature.enable clooney
248
+ @result = feature.disable(pitt)
253
249
  end
254
250
 
255
251
  it "returns true" do
@@ -257,21 +253,21 @@ describe Flipper::Feature do
257
253
  end
258
254
 
259
255
  it "disables feature for actor" do
260
- subject.enabled?(pitt).should be_false
256
+ feature.enabled?(pitt).should be_false
261
257
  end
262
258
 
263
259
  it "does not disable feature for other actors" do
264
- subject.enabled?(clooney).should be_true
260
+ feature.enabled?(clooney).should be_true
265
261
  end
266
262
 
267
263
  it "adds feature to set of features" do
268
- adapter.set_members('features').should include('search')
264
+ flipper.features.map(&:name).should include(:search)
269
265
  end
270
266
  end
271
267
 
272
268
  context "with a percentage of actors" do
273
269
  before do
274
- @result = subject.disable(five_percent_of_actors)
270
+ @result = feature.disable(flipper.actors(0))
275
271
  end
276
272
 
277
273
  it "returns true" do
@@ -281,22 +277,21 @@ describe Flipper::Feature do
281
277
  it "disables feature" do
282
278
  enabled = (1..100).select { |i|
283
279
  thing = actor_class.new(i)
284
- subject.enabled?(thing)
280
+ feature.enabled?(thing)
285
281
  }.size
286
282
 
287
283
  enabled.should be(0)
288
284
  end
289
285
 
290
286
  it "adds feature to set of features" do
291
- adapter.set_members('features').should include('search')
287
+ flipper.features.map(&:name).should include(:search)
292
288
  end
293
289
  end
294
290
 
295
291
  context "with a percentage of time" do
296
292
  before do
297
- @gate = Flipper::Gates::PercentageOfRandom.new(subject)
298
- Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
299
- @result = subject.disable(five_percent_of_random)
293
+ @gate = feature.gate(:percentage_of_random)
294
+ @result = feature.disable(flipper.random(0))
300
295
  end
301
296
 
302
297
  it "returns true" do
@@ -305,16 +300,16 @@ describe Flipper::Feature do
305
300
 
306
301
  it "disables feature for time within percentage" do
307
302
  @gate.stub(:rand => 0.04)
308
- subject.enabled?.should be_false
303
+ feature.enabled?.should be_false
309
304
  end
310
305
 
311
306
  it "disables feature for time not within percentage" do
312
307
  @gate.stub(:rand => 0.10)
313
- subject.enabled?.should be_false
308
+ feature.enabled?.should be_false
314
309
  end
315
310
 
316
311
  it "adds feature to set of features" do
317
- adapter.set_members('features').should include('search')
312
+ flipper.features.map(&:name).should include(:search)
318
313
  end
319
314
  end
320
315
 
@@ -322,7 +317,7 @@ describe Flipper::Feature do
322
317
  it "raises error" do
323
318
  thing = Object.new
324
319
  expect {
325
- subject.disable(thing)
320
+ feature.disable(thing)
326
321
  }.to raise_error(Flipper::GateNotFound, "Could not find gate for #{thing.inspect}")
327
322
  end
328
323
  end
@@ -331,132 +326,136 @@ describe Flipper::Feature do
331
326
  describe "#enabled?" do
332
327
  context "with no arguments" do
333
328
  it "defaults to false" do
334
- subject.enabled?.should be_false
329
+ feature.enabled?.should be_false
335
330
  end
336
331
  end
337
332
 
338
333
  context "with no arguments, but boolean enabled" do
339
334
  before do
340
- subject.enable
335
+ feature.enable
341
336
  end
342
337
 
343
338
  it "returns true" do
344
- subject.enabled?.should be_true
339
+ feature.enabled?.should be_true
345
340
  end
346
341
  end
347
342
 
348
343
  context "for actor in enabled group" do
349
344
  before do
350
- subject.enable admin_group
345
+ feature.enable admin_group
351
346
  end
352
347
 
353
348
  it "returns true" do
354
- subject.enabled?(Flipper::Types::Actor.new(admin_thing)).should be_true
349
+ feature.enabled?(flipper.actor(admin_thing)).should be_true
350
+ feature.enabled?(admin_thing).should be_true
355
351
  end
356
352
  end
357
353
 
358
354
  context "for actor in disabled group" do
359
355
  it "returns false" do
360
- subject.enabled?(Flipper::Types::Actor.new(dev_thing)).should be_false
356
+ feature.enabled?(flipper.actor(dev_thing)).should be_false
357
+ feature.enabled?(dev_thing).should be_false
361
358
  end
362
359
  end
363
360
 
364
361
  context "for enabled actor" do
365
362
  before do
366
- subject.enable pitt
363
+ feature.enable pitt
367
364
  end
368
365
 
369
366
  it "returns true" do
370
- subject.enabled?(pitt).should be_true
367
+ feature.enabled?(pitt).should be_true
371
368
  end
372
369
  end
373
370
 
374
371
  context "for not enabled actor" do
375
372
  it "returns false" do
376
- subject.enabled?(clooney).should be_false
373
+ feature.enabled?(clooney).should be_false
377
374
  end
378
375
 
379
376
  it "returns true if boolean enabled" do
380
- subject.enable
381
- subject.enabled?(clooney).should be_true
377
+ feature.enable
378
+ feature.enabled?(clooney).should be_true
382
379
  end
383
380
  end
384
381
 
385
382
  context "during enabled percentage of time" do
386
383
  before do
387
- @gate = Flipper::Gates::PercentageOfRandom.new(subject)
384
+ # ensure percentage of random returns enabled percentage
385
+ @gate = feature.gate(:percentage_of_random)
388
386
  @gate.stub(:rand => 0.04)
389
- Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
390
- subject.enable five_percent_of_random
387
+
388
+ feature.enable five_percent_of_random
391
389
  end
392
390
 
393
391
  it "returns true" do
394
- subject.enabled?.should be_true
395
- subject.enabled?(nil).should be_true
396
- subject.enabled?(pitt).should be_true
397
- subject.enabled?(admin_thing).should be_true
392
+ feature.enabled?.should be_true
393
+ feature.enabled?(nil).should be_true
394
+ feature.enabled?(pitt).should be_true
395
+ feature.enabled?(admin_thing).should be_true
398
396
  end
399
397
  end
400
398
 
401
399
  context "during not enabled percentage of time" do
402
400
  before do
403
- @gate = Flipper::Gates::PercentageOfRandom.new(subject)
401
+ # ensure percentage of random returns not enabled percentage
402
+ @gate = feature.gate(:percentage_of_random)
404
403
  @gate.stub(:rand => 0.10)
405
- Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
406
- subject.enable five_percent_of_random
404
+
405
+ feature.enable five_percent_of_random
407
406
  end
408
407
 
409
408
  it "returns false" do
410
- subject.enabled?.should be_false
411
- subject.enabled?(nil).should be_false
412
- subject.enabled?(pitt).should be_false
413
- subject.enabled?(admin_thing).should be_false
409
+ feature.enabled?.should be_false
410
+ feature.enabled?(nil).should be_false
411
+ feature.enabled?(pitt).should be_false
412
+ feature.enabled?(admin_thing).should be_false
414
413
  end
415
414
 
416
415
  it "returns true if boolean enabled" do
417
- subject.enable
418
- subject.enabled?.should be_true
419
- subject.enabled?(nil).should be_true
420
- subject.enabled?(pitt).should be_true
421
- subject.enabled?(admin_thing).should be_true
416
+ feature.enable
417
+ feature.enabled?.should be_true
418
+ feature.enabled?(nil).should be_true
419
+ feature.enabled?(pitt).should be_true
420
+ feature.enabled?(admin_thing).should be_true
422
421
  end
423
422
  end
424
423
 
425
424
  context "for a non flipper thing" do
426
425
  before do
427
- subject.enable admin_group
426
+ feature.enable admin_group
428
427
  end
429
428
 
430
429
  it "returns true if in enabled group" do
431
- subject.enabled?(admin_thing).should be_true
430
+ feature.enabled?(admin_thing).should be_true
432
431
  end
433
432
 
434
433
  it "returns false if not in enabled group" do
435
- subject.enabled?(dev_thing).should be_false
434
+ feature.enabled?(dev_thing).should be_false
436
435
  end
437
436
 
438
437
  it "returns true if boolean enabled" do
439
- subject.enable
440
- subject.enabled?(admin_thing).should be_true
441
- subject.enabled?(dev_thing).should be_true
438
+ feature.enable
439
+ feature.enabled?(admin_thing).should be_true
440
+ feature.enabled?(dev_thing).should be_true
442
441
  end
443
442
  end
444
443
  end
445
444
 
446
445
  context "enabling multiple groups, disabling everything, then enabling one group" do
447
446
  before do
448
- subject.enable(admin_group)
449
- subject.enable(dev_group)
450
- subject.disable
451
- subject.enable(admin_group)
447
+ feature.enable(admin_group)
448
+ feature.enable(dev_group)
449
+ feature.disable
450
+ feature.enable(admin_group)
452
451
  end
453
452
 
454
453
  it "enables feature for object in enabled group" do
455
- subject.enabled?(admin_thing).should be_true
454
+ feature.enabled?(admin_thing).should be_true
456
455
  end
457
456
 
458
457
  it "does not enable feature for object in not enabled group" do
459
- subject.enabled?(dev_thing).should be_false
458
+ feature.enabled?(dev_thing).should be_false
460
459
  end
461
460
  end
462
461
  end