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
data/lib/flipper/toggle.rb
CHANGED
@@ -13,16 +13,22 @@ module Flipper
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def enable(thing)
|
16
|
-
|
16
|
+
add_feature_to_set
|
17
17
|
end
|
18
18
|
|
19
19
|
def disable(thing)
|
20
|
-
|
20
|
+
add_feature_to_set
|
21
21
|
end
|
22
22
|
|
23
23
|
def value
|
24
24
|
raise 'Not implemented'
|
25
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def add_feature_to_set
|
30
|
+
adapter.feature_add key.prefix
|
31
|
+
end
|
26
32
|
end
|
27
33
|
end
|
28
34
|
|
@@ -2,15 +2,15 @@ module Flipper
|
|
2
2
|
module Toggles
|
3
3
|
class Boolean < Toggle
|
4
4
|
def enable(thing)
|
5
|
-
|
5
|
+
super
|
6
|
+
adapter.write key, thing.value
|
6
7
|
end
|
7
8
|
|
8
9
|
def disable(thing)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
adapter.delete "#{gate.key_prefix}#{Gate::Separator}#{Gates::PercentageOfRandom::Key}"
|
10
|
+
super
|
11
|
+
feature.gates.each do |gate|
|
12
|
+
gate.adapter.delete gate.key
|
13
|
+
end
|
14
14
|
end
|
15
15
|
|
16
16
|
def value
|
data/lib/flipper/toggles/set.rb
CHANGED
@@ -2,11 +2,13 @@ module Flipper
|
|
2
2
|
module Toggles
|
3
3
|
class Set < Toggle
|
4
4
|
def enable(thing)
|
5
|
-
|
5
|
+
super
|
6
|
+
adapter.set_add key, thing.value
|
6
7
|
end
|
7
8
|
|
8
9
|
def disable(thing)
|
9
|
-
|
10
|
+
super
|
11
|
+
adapter.set_delete key, thing.value
|
10
12
|
end
|
11
13
|
|
12
14
|
def value
|
@@ -2,11 +2,13 @@ module Flipper
|
|
2
2
|
module Toggles
|
3
3
|
class Value < Toggle
|
4
4
|
def enable(thing)
|
5
|
-
|
5
|
+
super
|
6
|
+
adapter.write key, thing.value
|
6
7
|
end
|
7
8
|
|
8
9
|
def disable(thing)
|
9
|
-
|
10
|
+
super
|
11
|
+
adapter.delete key
|
10
12
|
end
|
11
13
|
|
12
14
|
def value
|
data/lib/flipper/type.rb
CHANGED
data/lib/flipper/types/actor.rb
CHANGED
@@ -4,7 +4,6 @@ module Flipper
|
|
4
4
|
def self.wrappable?(thing)
|
5
5
|
thing.is_a?(Flipper::Types::Actor) ||
|
6
6
|
thing.respond_to?(:identifier) ||
|
7
|
-
thing.respond_to?(:id) ||
|
8
7
|
thing.respond_to?(:to_i)
|
9
8
|
end
|
10
9
|
|
@@ -24,19 +23,15 @@ module Flipper
|
|
24
23
|
@thing = thing
|
25
24
|
@identifier = if thing.respond_to?(:identifier)
|
26
25
|
thing.identifier
|
27
|
-
elsif thing.respond_to?(:id)
|
28
|
-
thing.id
|
29
26
|
else
|
30
27
|
thing
|
31
28
|
end.to_i
|
32
29
|
end
|
33
30
|
|
34
|
-
def
|
31
|
+
def value
|
35
32
|
@identifier
|
36
33
|
end
|
37
34
|
|
38
|
-
alias_method :disabled_value, :enabled_value
|
39
|
-
|
40
35
|
def respond_to?(*args)
|
41
36
|
super || @thing.respond_to?(*args)
|
42
37
|
end
|
data/lib/flipper/types/group.rb
CHANGED
data/lib/flipper/version.rb
CHANGED
@@ -3,8 +3,9 @@ require 'flipper/adapter'
|
|
3
3
|
require 'flipper/adapters/memory'
|
4
4
|
|
5
5
|
describe Flipper::Adapter do
|
6
|
-
let(:local_cache)
|
7
|
-
let(:adapter)
|
6
|
+
let(:local_cache) { {} }
|
7
|
+
let(:adapter) { Flipper::Adapters::Memory.new }
|
8
|
+
let(:features_key) { described_class::FeaturesKey }
|
8
9
|
|
9
10
|
subject { described_class.new(adapter, local_cache) }
|
10
11
|
|
@@ -280,4 +281,47 @@ describe Flipper::Adapter do
|
|
280
281
|
(subject == described_class.new(adapter)).should be_true
|
281
282
|
end
|
282
283
|
end
|
284
|
+
|
285
|
+
describe "#features" do
|
286
|
+
context "with no features enabled/disabled" do
|
287
|
+
it "defaults to empty set" do
|
288
|
+
subject.features.should eq(Set.new)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
context "with features enabled and disabled" do
|
293
|
+
before do
|
294
|
+
subject.set_add(features_key, 'stats')
|
295
|
+
subject.set_add(features_key, 'cache')
|
296
|
+
subject.set_add(features_key, 'search')
|
297
|
+
end
|
298
|
+
|
299
|
+
it "returns set of feature names" do
|
300
|
+
subject.features.should be_instance_of(Set)
|
301
|
+
subject.features.sort.should eq(['cache', 'search', 'stats'])
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
describe "#feature_add" do
|
307
|
+
context "with string name" do
|
308
|
+
before do
|
309
|
+
subject.feature_add('search')
|
310
|
+
end
|
311
|
+
|
312
|
+
it "adds string to set" do
|
313
|
+
subject.set_members(features_key).should include('search')
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context "with symbol name" do
|
318
|
+
before do
|
319
|
+
subject.feature_add(:search)
|
320
|
+
end
|
321
|
+
|
322
|
+
it "adds string to set" do
|
323
|
+
subject.set_members(features_key).should include('search')
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
283
327
|
end
|
@@ -11,11 +11,11 @@ describe Flipper::Adapters::Memoized do
|
|
11
11
|
subject { described_class.new(adapter, cache) }
|
12
12
|
|
13
13
|
def read_key(key)
|
14
|
-
source[key]
|
14
|
+
source[key.to_s]
|
15
15
|
end
|
16
16
|
|
17
17
|
def write_key(key, value)
|
18
|
-
source[key] = value
|
18
|
+
source[key.to_s] = value
|
19
19
|
end
|
20
20
|
|
21
21
|
it_should_behave_like 'a flipper adapter'
|
@@ -8,11 +8,11 @@ describe Flipper::Adapters::Memory do
|
|
8
8
|
subject { described_class.new(source) }
|
9
9
|
|
10
10
|
def read_key(key)
|
11
|
-
source[key]
|
11
|
+
source[key.to_s]
|
12
12
|
end
|
13
13
|
|
14
14
|
def write_key(key, value)
|
15
|
-
source[key] = value
|
15
|
+
source[key.to_s] = value
|
16
16
|
end
|
17
17
|
|
18
18
|
it_should_behave_like 'a flipper adapter'
|
data/spec/flipper/dsl_spec.rb
CHANGED
@@ -117,15 +117,6 @@ describe Flipper::DSL do
|
|
117
117
|
end
|
118
118
|
|
119
119
|
describe "#actor" do
|
120
|
-
context "for something that responds to id" do
|
121
|
-
it "returns actor instance with identifier set to id" do
|
122
|
-
user = Struct.new(:id).new(23)
|
123
|
-
actor = subject.actor(user)
|
124
|
-
actor.should be_instance_of(Flipper::Types::Actor)
|
125
|
-
actor.identifier.should eq(23)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
120
|
context "for something that responds to identifier" do
|
130
121
|
it "returns actor instance with identifier set to id" do
|
131
122
|
user = Struct.new(:identifier).new(45)
|
@@ -135,15 +126,6 @@ describe Flipper::DSL do
|
|
135
126
|
end
|
136
127
|
end
|
137
128
|
|
138
|
-
context "for something that responds to identifier and id" do
|
139
|
-
it "returns actor instance with identifier set to identifier" do
|
140
|
-
user = Struct.new(:id, :identifier).new(1, 50)
|
141
|
-
actor = subject.actor(user)
|
142
|
-
actor.should be_instance_of(Flipper::Types::Actor)
|
143
|
-
actor.identifier.should eq(50)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
129
|
context "for a number" do
|
148
130
|
it "returns actor instance with identifer set to number" do
|
149
131
|
actor = subject.actor(33)
|
@@ -173,6 +155,10 @@ describe Flipper::DSL do
|
|
173
155
|
it "sets value" do
|
174
156
|
@result.value.should eq(5)
|
175
157
|
end
|
158
|
+
|
159
|
+
it "is aliased to percentage_of_random" do
|
160
|
+
@result.should eq(subject.percentage_of_random(@result.value))
|
161
|
+
end
|
176
162
|
end
|
177
163
|
|
178
164
|
describe "#actors" do
|
@@ -187,5 +173,33 @@ describe Flipper::DSL do
|
|
187
173
|
it "sets value" do
|
188
174
|
@result.value.should eq(17)
|
189
175
|
end
|
176
|
+
|
177
|
+
it "is aliased to percentage_of_actors" do
|
178
|
+
@result.should eq(subject.percentage_of_actors(@result.value))
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe "#features" do
|
183
|
+
context "with no features enabled/disabled" do
|
184
|
+
it "defaults to empty set" do
|
185
|
+
subject.features.should eq(Set.new)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context "with features enabled and disabled" do
|
190
|
+
before do
|
191
|
+
subject[:stats].enable
|
192
|
+
subject[:cache].enable
|
193
|
+
subject[:search].disable
|
194
|
+
end
|
195
|
+
|
196
|
+
it "returns set of feature instances" do
|
197
|
+
subject.features.should be_instance_of(Set)
|
198
|
+
subject.features.each do |feature|
|
199
|
+
feature.should be_instance_of(Flipper::Feature)
|
200
|
+
end
|
201
|
+
subject.features.map(&:name).map(&:to_s).sort.should eq(['cache', 'search', 'stats'])
|
202
|
+
end
|
203
|
+
end
|
190
204
|
end
|
191
205
|
end
|
@@ -8,388 +8,19 @@ describe Flipper::Feature do
|
|
8
8
|
let(:source) { {} }
|
9
9
|
let(:adapter) { Flipper::Adapters::Memory.new(source) }
|
10
10
|
|
11
|
-
let(:actor_key) { Flipper::Gates::Actor::Key }
|
12
|
-
let(:boolean_key) { Flipper::Gates::Boolean::Key }
|
13
|
-
let(:group_key) { Flipper::Gates::Group::Key }
|
14
|
-
|
15
|
-
let(:admin_group) { Flipper.group(:admins) }
|
16
|
-
let(:dev_group) { Flipper.group(:devs) }
|
17
|
-
|
18
|
-
let(:admin_thing) { double 'Non Flipper Thing', :identifier => 1, :admin? => true, :dev? => false }
|
19
|
-
let(:dev_thing) { double 'Non Flipper Thing', :identifier => 10, :admin? => false, :dev? => true }
|
20
|
-
|
21
|
-
let(:pitt) { Flipper::Types::Actor.new(1) }
|
22
|
-
let(:clooney) { Flipper::Types::Actor.new(10) }
|
23
|
-
|
24
|
-
let(:five_percent_of_actors) { Flipper::Types::PercentageOfActors.new(5) }
|
25
|
-
let(:percentage_of_actors_key) { Flipper::Gates::PercentageOfActors::Key }
|
26
|
-
|
27
|
-
let(:five_percent_of_random) { Flipper::Types::PercentageOfRandom.new(5) }
|
28
|
-
let(:percentage_of_random_key) { Flipper::Gates::PercentageOfRandom::Key }
|
29
|
-
|
30
|
-
before do
|
31
|
-
Flipper.register(:admins) { |thing| thing.admin? }
|
32
|
-
Flipper.register(:devs) { |thing| thing.dev? }
|
33
|
-
end
|
34
|
-
|
35
11
|
it "initializes with name and adapter" do
|
36
12
|
feature = described_class.new(:search, adapter)
|
37
13
|
feature.name.should eq(:search)
|
38
14
|
feature.adapter.should eq(Flipper::Adapter.wrap(adapter))
|
39
15
|
end
|
40
16
|
|
41
|
-
describe "#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
it "enables feature for all" do
|
48
|
-
subject.enabled?.should be_true
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "with a group" do
|
53
|
-
before do
|
54
|
-
subject.enable(admin_group)
|
55
|
-
end
|
56
|
-
|
57
|
-
it "enables feature for non flipper thing in group" do
|
58
|
-
subject.enabled?(admin_thing).should be_true
|
59
|
-
end
|
60
|
-
|
61
|
-
it "does not enable feature for non flipper thing in other group" do
|
62
|
-
subject.enabled?(dev_thing).should be_false
|
63
|
-
end
|
64
|
-
|
65
|
-
it "enables feature for flipper actor in group" do
|
66
|
-
subject.enabled?(Flipper::Types::Actor.new(admin_thing)).should be_true
|
67
|
-
end
|
68
|
-
|
69
|
-
it "does not enable for flipper actor not in group" do
|
70
|
-
subject.enabled?(Flipper::Types::Actor.new(dev_thing)).should be_false
|
71
|
-
end
|
72
|
-
|
73
|
-
it "does not enable feature for all" do
|
74
|
-
subject.enabled?.should be_false
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
context "with an actor" do
|
79
|
-
before do
|
80
|
-
subject.enable(pitt)
|
81
|
-
end
|
82
|
-
|
83
|
-
it "enables feature for actor" do
|
84
|
-
subject.enabled?(pitt).should be_true
|
85
|
-
end
|
86
|
-
|
87
|
-
it "does not enable feature for other actors" do
|
88
|
-
subject.enabled?(clooney).should be_false
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
context "with a percentage of actors" do
|
93
|
-
before do
|
94
|
-
subject.enable(five_percent_of_actors)
|
95
|
-
end
|
96
|
-
|
97
|
-
it "enables feature for actor within percentage" do
|
98
|
-
subject.enabled?(pitt).should be_true
|
99
|
-
end
|
100
|
-
|
101
|
-
it "does not enable feature for actors not within percentage" do
|
102
|
-
subject.enabled?(clooney).should be_false
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
context "with a percentage of time" do
|
107
|
-
before do
|
108
|
-
@gate = Flipper::Gates::PercentageOfRandom.new(subject)
|
109
|
-
Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
|
110
|
-
subject.enable(five_percent_of_random)
|
111
|
-
end
|
112
|
-
|
113
|
-
it "enables feature for time within percentage" do
|
114
|
-
@gate.stub(:rand => 0.04)
|
115
|
-
subject.enabled?.should be_true
|
116
|
-
end
|
117
|
-
|
118
|
-
it "does not enable feature for time not within percentage" do
|
119
|
-
@gate.stub(:rand => 0.10)
|
120
|
-
subject.enabled?.should be_false
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
context "with argument that has no gate" do
|
125
|
-
it "raises error" do
|
126
|
-
thing = Object.new
|
127
|
-
expect {
|
128
|
-
subject.enable(thing)
|
129
|
-
}.to raise_error(Flipper::GateNotFound, "Could not find gate for #{thing.inspect}")
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
describe "#disable" do
|
135
|
-
context "with no arguments" do
|
136
|
-
before do
|
137
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{group_key}", admin_group.name)
|
138
|
-
subject.disable
|
139
|
-
end
|
140
|
-
|
141
|
-
it "disables feature" do
|
142
|
-
subject.enabled?.should be_false
|
143
|
-
end
|
144
|
-
|
145
|
-
it "disables feature for non flipper thing in previously enabled groups" do
|
146
|
-
subject.enabled?(admin_thing).should be_false
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
context "with a group" do
|
151
|
-
before do
|
152
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{group_key}", dev_group.name)
|
153
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{group_key}", admin_group.name)
|
154
|
-
subject.disable(admin_group)
|
155
|
-
end
|
156
|
-
|
157
|
-
it "disables the feature for non flipper thing in the group" do
|
158
|
-
subject.enabled?(admin_thing).should be_false
|
159
|
-
end
|
160
|
-
|
161
|
-
it "does not disable feature for non flipper thing in other groups" do
|
162
|
-
subject.enabled?(dev_thing).should be_true
|
163
|
-
end
|
164
|
-
|
165
|
-
it "disables feature for flipper actor in group" do
|
166
|
-
subject.enabled?(Flipper::Types::Actor.new(admin_thing)).should be_false
|
167
|
-
end
|
168
|
-
|
169
|
-
it "does not disable feature for flipper actor in other groups" do
|
170
|
-
subject.enabled?(Flipper::Types::Actor.new(dev_thing)).should be_true
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
context "with an actor" do
|
175
|
-
before do
|
176
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{actor_key}", pitt.identifier)
|
177
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{actor_key}", clooney.identifier)
|
178
|
-
subject.disable(pitt)
|
179
|
-
end
|
180
|
-
|
181
|
-
it "disables feature for actor" do
|
182
|
-
subject.enabled?(pitt).should be_false
|
183
|
-
end
|
184
|
-
|
185
|
-
it "does not disable feature for other actors" do
|
186
|
-
subject.enabled?(clooney).should be_true
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
context "with a percentage of actors" do
|
191
|
-
before do
|
192
|
-
subject.disable(five_percent_of_actors)
|
193
|
-
end
|
194
|
-
|
195
|
-
it "disables feature for actor within percentage" do
|
196
|
-
subject.enabled?(pitt).should be_false
|
197
|
-
end
|
198
|
-
|
199
|
-
it "disables feature for actors not within percentage" do
|
200
|
-
subject.enabled?(clooney).should be_false
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
context "with a percentage of time" do
|
205
|
-
before do
|
206
|
-
@gate = Flipper::Gates::PercentageOfRandom.new(subject)
|
207
|
-
Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
|
208
|
-
subject.disable(five_percent_of_random)
|
209
|
-
end
|
210
|
-
|
211
|
-
it "disables feature for time within percentage" do
|
212
|
-
@gate.stub(:rand => 0.04)
|
213
|
-
subject.enabled?.should be_false
|
214
|
-
end
|
215
|
-
|
216
|
-
it "disables feature for time not within percentage" do
|
217
|
-
@gate.stub(:rand => 0.10)
|
218
|
-
subject.enabled?.should be_false
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
context "with argument that has no gate" do
|
223
|
-
it "raises error" do
|
224
|
-
thing = Object.new
|
225
|
-
expect {
|
226
|
-
subject.disable(thing)
|
227
|
-
}.to raise_error(Flipper::GateNotFound, "Could not find gate for #{thing.inspect}")
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
describe "#enabled?" do
|
233
|
-
context "with no arguments" do
|
234
|
-
it "defaults to false" do
|
235
|
-
subject.enabled?.should be_false
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
context "with no arguments, but boolean enabled" do
|
240
|
-
before do
|
241
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{boolean_key}", true)
|
242
|
-
end
|
243
|
-
|
244
|
-
it "returns true" do
|
245
|
-
subject.enabled?.should be_true
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
context "for actor in enabled group" do
|
250
|
-
before do
|
251
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{group_key}", admin_group.name)
|
252
|
-
end
|
253
|
-
|
254
|
-
it "returns true" do
|
255
|
-
subject.enabled?(Flipper::Types::Actor.new(admin_thing)).should be_true
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
context "for actor in disbled group" do
|
260
|
-
it "returns false" do
|
261
|
-
subject.enabled?(Flipper::Types::Actor.new(dev_thing)).should be_false
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
context "for enabled actor" do
|
266
|
-
before do
|
267
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{actor_key}", pitt.identifier)
|
268
|
-
end
|
269
|
-
|
270
|
-
it "returns true" do
|
271
|
-
subject.enabled?(pitt).should be_true
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
context "for not enabled actor" do
|
276
|
-
it "returns false" do
|
277
|
-
subject.enabled?(clooney).should be_false
|
278
|
-
end
|
279
|
-
|
280
|
-
it "returns true if boolean enabled" do
|
281
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{boolean_key}", true)
|
282
|
-
subject.enabled?(clooney).should be_true
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
context "for actor in percentage of actors enabled" do
|
287
|
-
before do
|
288
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{percentage_of_actors_key}", five_percent_of_actors.value)
|
289
|
-
end
|
290
|
-
|
291
|
-
it "returns true" do
|
292
|
-
subject.enabled?(pitt).should be_true
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
context "for actor not in percentage of actors enabled" do
|
297
|
-
before do
|
298
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{percentage_of_actors_key}", five_percent_of_actors.value)
|
299
|
-
end
|
300
|
-
|
301
|
-
it "returns false" do
|
302
|
-
subject.enabled?(clooney).should be_false
|
303
|
-
end
|
304
|
-
|
305
|
-
it "returns true if boolean enabled" do
|
306
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{boolean_key}", true)
|
307
|
-
subject.enabled?(clooney).should be_true
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
context "during enabled percentage of time" do
|
312
|
-
before do
|
313
|
-
@gate = Flipper::Gates::PercentageOfRandom.new(subject)
|
314
|
-
@gate.stub(:rand => 0.04)
|
315
|
-
Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
|
316
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{percentage_of_random_key}", five_percent_of_random.value)
|
317
|
-
end
|
318
|
-
|
319
|
-
it "returns true" do
|
320
|
-
subject.enabled?.should be_true
|
321
|
-
subject.enabled?(nil).should be_true
|
322
|
-
subject.enabled?(pitt).should be_true
|
323
|
-
subject.enabled?(admin_thing).should be_true
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
context "during not enabled percentage of time" do
|
328
|
-
before do
|
329
|
-
@gate = Flipper::Gates::PercentageOfRandom.new(subject)
|
330
|
-
@gate.stub(:rand => 0.10)
|
331
|
-
Flipper::Gates::PercentageOfRandom.should_receive(:new).and_return(@gate)
|
332
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{percentage_of_random_key}", five_percent_of_random.value)
|
333
|
-
end
|
334
|
-
|
335
|
-
it "returns false" do
|
336
|
-
subject.enabled?.should be_false
|
337
|
-
subject.enabled?(nil).should be_false
|
338
|
-
subject.enabled?(pitt).should be_false
|
339
|
-
subject.enabled?(admin_thing).should be_false
|
340
|
-
end
|
341
|
-
|
342
|
-
it "returns true if boolean enabled" do
|
343
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{boolean_key}", true)
|
344
|
-
subject.enabled?.should be_true
|
345
|
-
subject.enabled?(nil).should be_true
|
346
|
-
subject.enabled?(pitt).should be_true
|
347
|
-
subject.enabled?(admin_thing).should be_true
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
context "for a non flipper thing" do
|
352
|
-
before do
|
353
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{group_key}", admin_group.name)
|
354
|
-
end
|
355
|
-
|
356
|
-
it "returns true if in enabled group" do
|
357
|
-
subject.enabled?(admin_thing).should be_true
|
358
|
-
end
|
359
|
-
|
360
|
-
it "returns false if not in enabled group" do
|
361
|
-
subject.enabled?(dev_thing).should be_false
|
362
|
-
end
|
363
|
-
|
364
|
-
it "returns true if boolean enabled" do
|
365
|
-
adapter.write("#{subject.name}#{Flipper::Gate::Separator}#{boolean_key}", true)
|
366
|
-
subject.enabled?(admin_thing).should be_true
|
367
|
-
subject.enabled?(dev_thing).should be_true
|
368
|
-
end
|
369
|
-
end
|
370
|
-
|
371
|
-
context "for a non flipper thing that does not respond to something in group block" do
|
372
|
-
let(:actor) { double('Actor') }
|
373
|
-
|
374
|
-
before do
|
375
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{group_key}", admin_group.name)
|
376
|
-
end
|
377
|
-
|
378
|
-
it "returns false" do
|
379
|
-
expect { subject.enabled?(actor) }.to raise_error
|
380
|
-
end
|
381
|
-
end
|
382
|
-
|
383
|
-
context "for a non flipper thing when group in adapter, but not defined in code" do
|
384
|
-
let(:actor) { double('Actor') }
|
385
|
-
|
386
|
-
before do
|
387
|
-
adapter.set_add("#{subject.name}#{Flipper::Gate::Separator}#{group_key}", :support)
|
388
|
-
end
|
389
|
-
|
390
|
-
it "returns false" do
|
391
|
-
subject.enabled?(actor).should be_false
|
17
|
+
describe "#gates" do
|
18
|
+
it "returns array of gates" do
|
19
|
+
subject.gates.should be_instance_of(Array)
|
20
|
+
subject.gates.each do |gate|
|
21
|
+
gate.should be_a(Flipper::Gate)
|
392
22
|
end
|
23
|
+
subject.gates.size.should be(5)
|
393
24
|
end
|
394
25
|
end
|
395
26
|
|
@@ -402,21 +33,4 @@ describe Flipper::Feature do
|
|
402
33
|
subject.disabled?.should be_true
|
403
34
|
end
|
404
35
|
end
|
405
|
-
|
406
|
-
context "enabling multiple groups, disabling everything, then enabling one group" do
|
407
|
-
before do
|
408
|
-
subject.enable(admin_group)
|
409
|
-
subject.enable(dev_group)
|
410
|
-
subject.disable
|
411
|
-
subject.enable(admin_group)
|
412
|
-
end
|
413
|
-
|
414
|
-
it "enables feature for object in enabled group" do
|
415
|
-
subject.enabled?(admin_thing).should be_true
|
416
|
-
end
|
417
|
-
|
418
|
-
it "does not enable feature for object in not enabled group" do
|
419
|
-
subject.enabled?(dev_thing).should be_false
|
420
|
-
end
|
421
|
-
end
|
422
36
|
end
|