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.
- data/Guardfile +3 -8
- data/README.md +26 -38
- data/examples/percentage_of_actors.rb +17 -12
- data/examples/percentage_of_random.rb +3 -7
- data/lib/flipper.rb +8 -1
- data/lib/flipper/adapter.rb +2 -208
- data/lib/flipper/adapters/decorator.rb +9 -0
- data/lib/flipper/adapters/instrumented.rb +92 -0
- data/lib/flipper/adapters/memoizable.rb +88 -0
- data/lib/flipper/adapters/memory.rb +89 -7
- data/lib/flipper/adapters/operation_logger.rb +31 -45
- data/lib/flipper/decorator.rb +6 -0
- data/lib/flipper/dsl.rb +29 -2
- data/lib/flipper/feature.rb +83 -49
- data/lib/flipper/gate.rb +24 -41
- data/lib/flipper/gates/actor.rb +24 -24
- data/lib/flipper/gates/boolean.rb +28 -15
- data/lib/flipper/gates/group.rb +25 -34
- data/lib/flipper/gates/percentage_of_actors.rb +21 -13
- data/lib/flipper/gates/percentage_of_random.rb +20 -12
- data/lib/flipper/instrumentation/log_subscriber.rb +14 -22
- data/lib/flipper/middleware/memoizer.rb +23 -0
- data/lib/flipper/spec/shared_adapter_specs.rb +141 -92
- data/lib/flipper/types/boolean.rb +5 -1
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapters/instrumented_spec.rb +92 -0
- data/spec/flipper/adapters/memoizable_spec.rb +184 -0
- data/spec/flipper/adapters/memory_spec.rb +1 -11
- data/spec/flipper/adapters/operation_logger_spec.rb +93 -0
- data/spec/flipper/dsl_spec.rb +18 -43
- data/spec/flipper/feature_spec.rb +25 -9
- data/spec/flipper/gate_spec.rb +8 -20
- data/spec/flipper/gates/actor_spec.rb +6 -14
- data/spec/flipper/gates/boolean_spec.rb +80 -13
- data/spec/flipper/gates/group_spec.rb +8 -18
- data/spec/flipper/gates/percentage_of_actors_spec.rb +12 -28
- data/spec/flipper/gates/percentage_of_random_spec.rb +6 -14
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +15 -8
- data/spec/flipper/instrumentation/metriks_subscriber_spec.rb +3 -6
- data/spec/flipper/middleware/{local_cache_spec.rb → memoizer_spec.rb} +25 -55
- data/spec/flipper/types/boolean_spec.rb +13 -3
- data/spec/flipper_spec.rb +7 -0
- data/spec/helper.rb +21 -3
- data/spec/integration_spec.rb +115 -116
- metadata +17 -27
- data/lib/flipper/adapters/memoized.rb +0 -55
- data/lib/flipper/key.rb +0 -38
- data/lib/flipper/middleware/local_cache.rb +0 -36
- data/lib/flipper/toggle.rb +0 -54
- data/lib/flipper/toggles/boolean.rb +0 -54
- data/lib/flipper/toggles/set.rb +0 -25
- data/lib/flipper/toggles/value.rb +0 -25
- data/spec/flipper/adapter_spec.rb +0 -463
- data/spec/flipper/adapters/memoized_spec.rb +0 -93
- data/spec/flipper/key_spec.rb +0 -23
- data/spec/flipper/toggle_spec.rb +0 -22
- data/spec/flipper/toggles/boolean_spec.rb +0 -40
- data/spec/flipper/toggles/set_spec.rb +0 -35
- 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
|
-
|
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.
|
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.
|
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/
|
3
|
+
require 'flipper/middleware/memoizer'
|
4
4
|
require 'flipper/adapters/operation_logger'
|
5
5
|
require 'flipper/adapters/memory'
|
6
6
|
|
7
|
-
describe Flipper::Middleware::
|
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
|
-
|
40
|
-
adapter.
|
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.
|
53
|
+
flipper.adapter.memoizing?.should be_true
|
81
54
|
body.close
|
82
|
-
flipper.adapter.
|
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.
|
63
|
+
flipper.adapter.cache['hello'] = 'world'
|
92
64
|
body.close
|
93
|
-
flipper.adapter.
|
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 "
|
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.
|
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 "
|
6
|
-
|
7
|
-
|
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.
|
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.
|
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
|
data/spec/integration_spec.rb
CHANGED
@@ -2,16 +2,17 @@ require 'helper'
|
|
2
2
|
require 'flipper/feature'
|
3
3
|
require 'flipper/adapters/memory'
|
4
4
|
|
5
|
-
describe Flipper
|
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(:
|
14
|
-
let(:
|
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) {
|
23
|
-
let(:five_percent_of_random) {
|
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 =
|
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
|
-
|
42
|
+
feature.enabled?.should be_true
|
46
43
|
end
|
47
44
|
|
48
45
|
it "adds feature to set of features" do
|
49
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
76
|
+
feature.enabled?.should be_false
|
80
77
|
end
|
81
78
|
|
82
79
|
it "adds feature to set of features" do
|
83
|
-
|
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 =
|
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
|
-
|
94
|
+
feature.enabled?(pitt).should be_true
|
98
95
|
end
|
99
96
|
|
100
97
|
it "does not enable feature for other actors" do
|
101
|
-
|
98
|
+
feature.enabled?(clooney).should be_false
|
102
99
|
end
|
103
100
|
|
104
101
|
it "adds feature to set of features" do
|
105
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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 =
|
135
|
-
|
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
|
-
|
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
|
-
|
146
|
+
feature.enabled?.should be_false
|
151
147
|
end
|
152
148
|
|
153
149
|
it "adds feature to set of features" do
|
154
|
-
|
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
|
-
|
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 =
|
168
|
+
@gate = feature.gate(:percentage_of_random)
|
173
169
|
@gate.stub(:rand => 0.04)
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
@result =
|
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
|
-
|
183
|
+
feature.enabled?.should be_false
|
188
184
|
end
|
189
185
|
|
190
186
|
it "disables for individual actor" do
|
191
|
-
|
187
|
+
feature.enabled?(pitt).should be_false
|
192
188
|
end
|
193
189
|
|
194
190
|
it "disables actor in group" do
|
195
|
-
|
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
|
-
|
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
|
-
|
204
|
+
feature.enabled?(pitt).should be_false
|
209
205
|
end
|
210
206
|
|
211
207
|
it "adds feature to set of features" do
|
212
|
-
|
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
|
-
|
219
|
-
|
220
|
-
@result =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
251
|
-
|
252
|
-
@result =
|
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
|
-
|
256
|
+
feature.enabled?(pitt).should be_false
|
261
257
|
end
|
262
258
|
|
263
259
|
it "does not disable feature for other actors" do
|
264
|
-
|
260
|
+
feature.enabled?(clooney).should be_true
|
265
261
|
end
|
266
262
|
|
267
263
|
it "adds feature to set of features" do
|
268
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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 =
|
298
|
-
|
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
|
-
|
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
|
-
|
308
|
+
feature.enabled?.should be_false
|
314
309
|
end
|
315
310
|
|
316
311
|
it "adds feature to set of features" do
|
317
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
335
|
+
feature.enable
|
341
336
|
end
|
342
337
|
|
343
338
|
it "returns true" do
|
344
|
-
|
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
|
-
|
345
|
+
feature.enable admin_group
|
351
346
|
end
|
352
347
|
|
353
348
|
it "returns true" do
|
354
|
-
|
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
|
-
|
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
|
-
|
363
|
+
feature.enable pitt
|
367
364
|
end
|
368
365
|
|
369
366
|
it "returns true" do
|
370
|
-
|
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
|
-
|
373
|
+
feature.enabled?(clooney).should be_false
|
377
374
|
end
|
378
375
|
|
379
376
|
it "returns true if boolean enabled" do
|
380
|
-
|
381
|
-
|
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
|
-
|
384
|
+
# ensure percentage of random returns enabled percentage
|
385
|
+
@gate = feature.gate(:percentage_of_random)
|
388
386
|
@gate.stub(:rand => 0.04)
|
389
|
-
|
390
|
-
|
387
|
+
|
388
|
+
feature.enable five_percent_of_random
|
391
389
|
end
|
392
390
|
|
393
391
|
it "returns true" do
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
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
|
-
|
401
|
+
# ensure percentage of random returns not enabled percentage
|
402
|
+
@gate = feature.gate(:percentage_of_random)
|
404
403
|
@gate.stub(:rand => 0.10)
|
405
|
-
|
406
|
-
|
404
|
+
|
405
|
+
feature.enable five_percent_of_random
|
407
406
|
end
|
408
407
|
|
409
408
|
it "returns false" do
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
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
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
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
|
-
|
426
|
+
feature.enable admin_group
|
428
427
|
end
|
429
428
|
|
430
429
|
it "returns true if in enabled group" do
|
431
|
-
|
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
|
-
|
434
|
+
feature.enabled?(dev_thing).should be_false
|
436
435
|
end
|
437
436
|
|
438
437
|
it "returns true if boolean enabled" do
|
439
|
-
|
440
|
-
|
441
|
-
|
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
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
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
|
-
|
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
|
-
|
458
|
+
feature.enabled?(dev_thing).should be_false
|
460
459
|
end
|
461
460
|
end
|
462
461
|
end
|