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