flipper 0.10.2 → 0.11.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +42 -0
- data/.rubocop_todo.yml +188 -0
- data/Changelog.md +10 -0
- data/Gemfile +6 -3
- data/README.md +4 -3
- data/Rakefile +13 -13
- data/docs/Adapters.md +2 -1
- data/docs/DockerCompose.md +6 -3
- data/docs/Gates.md +25 -3
- data/docs/Optimization.md +27 -5
- data/docs/api/README.md +73 -32
- data/docs/http/README.md +34 -0
- data/docs/read-only/README.md +22 -0
- data/examples/percentage_of_actors_group.rb +49 -0
- data/flipper.gemspec +15 -15
- data/lib/flipper.rb +2 -5
- data/lib/flipper/adapter.rb +10 -0
- data/lib/flipper/adapters/http.rb +147 -0
- data/lib/flipper/adapters/http/client.rb +83 -0
- data/lib/flipper/adapters/http/error.rb +14 -0
- data/lib/flipper/adapters/instrumented.rb +36 -36
- data/lib/flipper/adapters/memoizable.rb +2 -6
- data/lib/flipper/adapters/memory.rb +10 -9
- data/lib/flipper/adapters/operation_logger.rb +1 -1
- data/lib/flipper/adapters/pstore.rb +12 -11
- data/lib/flipper/adapters/read_only.rb +6 -6
- data/lib/flipper/dsl.rb +1 -3
- data/lib/flipper/feature.rb +11 -16
- data/lib/flipper/gate.rb +3 -3
- data/lib/flipper/gate_values.rb +6 -6
- data/lib/flipper/gates/group.rb +2 -2
- data/lib/flipper/gates/percentage_of_actors.rb +2 -2
- data/lib/flipper/instrumentation/log_subscriber.rb +2 -4
- data/lib/flipper/instrumentation/metriks.rb +1 -1
- data/lib/flipper/instrumentation/statsd.rb +1 -1
- data/lib/flipper/instrumentation/statsd_subscriber.rb +1 -3
- data/lib/flipper/instrumentation/subscriber.rb +11 -10
- data/lib/flipper/instrumenters/memory.rb +1 -5
- data/lib/flipper/instrumenters/noop.rb +1 -1
- data/lib/flipper/middleware/memoizer.rb +11 -27
- data/lib/flipper/middleware/setup_env.rb +44 -0
- data/lib/flipper/registry.rb +8 -10
- data/lib/flipper/spec/shared_adapter_specs.rb +45 -67
- data/lib/flipper/test/shared_adapter_test.rb +25 -31
- data/lib/flipper/typecast.rb +2 -2
- data/lib/flipper/types/actor.rb +2 -4
- data/lib/flipper/types/group.rb +1 -1
- data/lib/flipper/types/percentage.rb +2 -1
- data/lib/flipper/version.rb +1 -1
- data/spec/fixtures/feature.json +31 -0
- data/spec/flipper/adapters/http_spec.rb +148 -0
- data/spec/flipper/adapters/instrumented_spec.rb +20 -20
- data/spec/flipper/adapters/memoizable_spec.rb +59 -59
- data/spec/flipper/adapters/operation_logger_spec.rb +16 -16
- data/spec/flipper/adapters/pstore_spec.rb +6 -6
- data/spec/flipper/adapters/read_only_spec.rb +28 -34
- data/spec/flipper/dsl_spec.rb +73 -84
- data/spec/flipper/feature_check_context_spec.rb +27 -27
- data/spec/flipper/feature_spec.rb +186 -196
- data/spec/flipper/gate_spec.rb +11 -11
- data/spec/flipper/gate_values_spec.rb +46 -45
- data/spec/flipper/gates/actor_spec.rb +2 -2
- data/spec/flipper/gates/boolean_spec.rb +24 -23
- data/spec/flipper/gates/group_spec.rb +19 -19
- data/spec/flipper/gates/percentage_of_actors_spec.rb +10 -10
- data/spec/flipper/gates/percentage_of_time_spec.rb +2 -2
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +20 -20
- data/spec/flipper/instrumentation/metriks_subscriber_spec.rb +20 -20
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +11 -11
- data/spec/flipper/instrumenters/memory_spec.rb +5 -5
- data/spec/flipper/instrumenters/noop_spec.rb +6 -6
- data/spec/flipper/middleware/memoizer_spec.rb +83 -100
- data/spec/flipper/middleware/setup_env_spec.rb +76 -0
- data/spec/flipper/registry_spec.rb +35 -39
- data/spec/flipper/typecast_spec.rb +18 -18
- data/spec/flipper/types/actor_spec.rb +30 -29
- data/spec/flipper/types/boolean_spec.rb +8 -8
- data/spec/flipper/types/group_spec.rb +28 -28
- data/spec/flipper/types/percentage_spec.rb +14 -14
- data/spec/flipper_spec.rb +61 -54
- data/spec/helper.rb +26 -21
- data/spec/integration_spec.rb +121 -113
- data/spec/support/fake_udp_socket.rb +1 -1
- data/spec/support/spec_helpers.rb +32 -4
- data/test/adapters/pstore_test.rb +3 -3
- data/test/test_helper.rb +1 -1
- metadata +20 -5
@@ -12,7 +12,7 @@ RSpec.describe Flipper::Adapters::OperationLogger do
|
|
12
12
|
|
13
13
|
it_should_behave_like 'a flipper adapter'
|
14
14
|
|
15
|
-
it
|
15
|
+
it 'forwards missing methods to underlying adapter' do
|
16
16
|
adapter = Class.new do
|
17
17
|
def foo
|
18
18
|
:foo
|
@@ -22,22 +22,22 @@ RSpec.describe Flipper::Adapters::OperationLogger do
|
|
22
22
|
expect(operation_logger.foo).to eq(:foo)
|
23
23
|
end
|
24
24
|
|
25
|
-
describe
|
25
|
+
describe '#get' do
|
26
26
|
before do
|
27
27
|
@feature = flipper[:stats]
|
28
28
|
@result = subject.get(@feature)
|
29
29
|
end
|
30
30
|
|
31
|
-
it
|
31
|
+
it 'logs operation' do
|
32
32
|
expect(subject.count(:get)).to be(1)
|
33
33
|
end
|
34
34
|
|
35
|
-
it
|
35
|
+
it 'returns result' do
|
36
36
|
expect(@result).to eq(adapter.get(@feature))
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
describe
|
40
|
+
describe '#enable' do
|
41
41
|
before do
|
42
42
|
@feature = flipper[:stats]
|
43
43
|
@gate = @feature.gate(:boolean)
|
@@ -45,16 +45,16 @@ RSpec.describe Flipper::Adapters::OperationLogger do
|
|
45
45
|
@result = subject.enable(@feature, @gate, @thing)
|
46
46
|
end
|
47
47
|
|
48
|
-
it
|
48
|
+
it 'logs operation' do
|
49
49
|
expect(subject.count(:enable)).to be(1)
|
50
50
|
end
|
51
51
|
|
52
|
-
it
|
52
|
+
it 'returns result' do
|
53
53
|
expect(@result).to eq(adapter.enable(@feature, @gate, @thing))
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
describe
|
57
|
+
describe '#disable' do
|
58
58
|
before do
|
59
59
|
@feature = flipper[:stats]
|
60
60
|
@gate = @feature.gate(:boolean)
|
@@ -62,41 +62,41 @@ RSpec.describe Flipper::Adapters::OperationLogger do
|
|
62
62
|
@result = subject.disable(@feature, @gate, @thing)
|
63
63
|
end
|
64
64
|
|
65
|
-
it
|
65
|
+
it 'logs operation' do
|
66
66
|
expect(subject.count(:disable)).to be(1)
|
67
67
|
end
|
68
68
|
|
69
|
-
it
|
69
|
+
it 'returns result' do
|
70
70
|
expect(@result).to eq(adapter.disable(@feature, @gate, @thing))
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
describe
|
74
|
+
describe '#features' do
|
75
75
|
before do
|
76
76
|
flipper[:stats].enable
|
77
77
|
@result = subject.features
|
78
78
|
end
|
79
79
|
|
80
|
-
it
|
80
|
+
it 'logs operation' do
|
81
81
|
expect(subject.count(:features)).to be(1)
|
82
82
|
end
|
83
83
|
|
84
|
-
it
|
84
|
+
it 'returns result' do
|
85
85
|
expect(@result).to eq(adapter.features)
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
describe
|
89
|
+
describe '#add' do
|
90
90
|
before do
|
91
91
|
@feature = flipper[:stats]
|
92
92
|
@result = subject.add(@feature)
|
93
93
|
end
|
94
94
|
|
95
|
-
it
|
95
|
+
it 'logs operation' do
|
96
96
|
expect(subject.count(:add)).to be(1)
|
97
97
|
end
|
98
98
|
|
99
|
-
it
|
99
|
+
it 'returns result' do
|
100
100
|
expect(@result).to eq(adapter.add(@feature))
|
101
101
|
end
|
102
102
|
end
|
@@ -3,16 +3,16 @@ require 'flipper/adapters/pstore'
|
|
3
3
|
require 'flipper/spec/shared_adapter_specs'
|
4
4
|
|
5
5
|
RSpec.describe Flipper::Adapters::PStore do
|
6
|
-
subject
|
7
|
-
dir = FlipperRoot.join(
|
8
|
-
pstore_file = dir.join(
|
6
|
+
subject do
|
7
|
+
dir = FlipperRoot.join('tmp').tap(&:mkpath)
|
8
|
+
pstore_file = dir.join('flipper.pstore')
|
9
9
|
pstore_file.unlink if pstore_file.exist?
|
10
10
|
described_class.new(pstore_file)
|
11
|
-
|
11
|
+
end
|
12
12
|
|
13
13
|
it_should_behave_like 'a flipper adapter'
|
14
14
|
|
15
|
-
it
|
16
|
-
expect(described_class.new.path).to eq(
|
15
|
+
it 'defaults path to flipper.pstore' do
|
16
|
+
expect(described_class.new.path).to eq('flipper.pstore')
|
17
17
|
end
|
18
18
|
end
|
@@ -17,78 +17,72 @@ RSpec.describe Flipper::Adapters::ReadOnly do
|
|
17
17
|
subject { described_class.new(adapter) }
|
18
18
|
|
19
19
|
before do
|
20
|
-
Flipper.register(:admins)
|
20
|
+
Flipper.register(:admins) do |actor|
|
21
21
|
actor.respond_to?(:admin?) && actor.admin?
|
22
|
-
|
22
|
+
end
|
23
23
|
|
24
|
-
Flipper.register(:early_access)
|
24
|
+
Flipper.register(:early_access) do |actor|
|
25
25
|
actor.respond_to?(:early_access?) && actor.early_access?
|
26
|
-
|
26
|
+
end
|
27
27
|
end
|
28
28
|
|
29
29
|
after do
|
30
30
|
Flipper.unregister_groups
|
31
31
|
end
|
32
32
|
|
33
|
-
it
|
34
|
-
expect(subject.name).
|
33
|
+
it 'has name that is a symbol' do
|
34
|
+
expect(subject.name).not_to be_nil
|
35
35
|
expect(subject.name).to be_instance_of(Symbol)
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
38
|
+
it 'has included the flipper adapter module' do
|
39
39
|
expect(subject.class.ancestors).to include(Flipper::Adapter)
|
40
40
|
end
|
41
41
|
|
42
|
-
it
|
43
|
-
expect(subject.get(feature)).to eq(
|
44
|
-
:boolean => nil,
|
45
|
-
:groups => Set.new,
|
46
|
-
:actors => Set.new,
|
47
|
-
:percentage_of_actors => nil,
|
48
|
-
:percentage_of_time => nil,
|
49
|
-
})
|
42
|
+
it 'returns correct default values for the gates if none are enabled' do
|
43
|
+
expect(subject.get(feature)).to eq(subject.default_config)
|
50
44
|
end
|
51
45
|
|
52
|
-
it
|
53
|
-
|
46
|
+
it 'can get feature' do
|
47
|
+
actor22 = actor_class.new('22')
|
54
48
|
adapter.enable(feature, boolean_gate, flipper.boolean)
|
55
49
|
adapter.enable(feature, group_gate, flipper.group(:admins))
|
56
|
-
adapter.enable(feature, actor_gate, flipper.actor(
|
50
|
+
adapter.enable(feature, actor_gate, flipper.actor(actor22))
|
57
51
|
adapter.enable(feature, actors_gate, flipper.actors(25))
|
58
52
|
adapter.enable(feature, time_gate, flipper.time(45))
|
59
53
|
|
60
|
-
expect(subject.get(feature)).to eq(
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
:percentage_of_time => "45",
|
66
|
-
})
|
54
|
+
expect(subject.get(feature)).to eq(boolean: 'true',
|
55
|
+
groups: Set['admins'],
|
56
|
+
actors: Set['22'],
|
57
|
+
percentage_of_actors: '25',
|
58
|
+
percentage_of_time: '45')
|
67
59
|
end
|
68
60
|
|
69
|
-
it
|
61
|
+
it 'can get features' do
|
70
62
|
expect(subject.features).to eq(Set.new)
|
71
63
|
adapter.add(feature)
|
72
|
-
expect(subject.features).to eq(Set[
|
64
|
+
expect(subject.features).to eq(Set['stats'])
|
73
65
|
end
|
74
66
|
|
75
|
-
it
|
67
|
+
it 'raises error on add' do
|
76
68
|
expect { subject.add(feature) }.to raise_error(Flipper::Adapters::ReadOnly::WriteAttempted)
|
77
69
|
end
|
78
70
|
|
79
|
-
it
|
71
|
+
it 'raises error on remove' do
|
80
72
|
expect { subject.remove(feature) }.to raise_error(Flipper::Adapters::ReadOnly::WriteAttempted)
|
81
73
|
end
|
82
74
|
|
83
|
-
it
|
75
|
+
it 'raises on clear' do
|
84
76
|
expect { subject.clear(feature) }.to raise_error(Flipper::Adapters::ReadOnly::WriteAttempted)
|
85
77
|
end
|
86
78
|
|
87
|
-
it
|
88
|
-
expect { subject.enable(feature, boolean_gate, flipper.boolean) }
|
79
|
+
it 'raises error on enable' do
|
80
|
+
expect { subject.enable(feature, boolean_gate, flipper.boolean) }
|
81
|
+
.to raise_error(Flipper::Adapters::ReadOnly::WriteAttempted)
|
89
82
|
end
|
90
83
|
|
91
|
-
it
|
92
|
-
expect { subject.disable(feature, boolean_gate, flipper.boolean) }
|
84
|
+
it 'raises error on disable' do
|
85
|
+
expect { subject.disable(feature, boolean_gate, flipper.boolean) }
|
86
|
+
.to raise_error(Flipper::Adapters::ReadOnly::WriteAttempted)
|
93
87
|
end
|
94
88
|
end
|
data/spec/flipper/dsl_spec.rb
CHANGED
@@ -3,121 +3,110 @@ require 'flipper/dsl'
|
|
3
3
|
require 'flipper/adapters/memory'
|
4
4
|
|
5
5
|
RSpec.describe Flipper::DSL do
|
6
|
-
subject {
|
6
|
+
subject { described_class.new(adapter) }
|
7
7
|
|
8
8
|
let(:adapter) { Flipper::Adapters::Memory.new }
|
9
9
|
|
10
|
-
describe
|
11
|
-
it
|
10
|
+
describe '#initialize' do
|
11
|
+
it 'sets adapter' do
|
12
12
|
dsl = described_class.new(adapter)
|
13
13
|
expect(dsl.adapter).not_to be_nil
|
14
14
|
end
|
15
15
|
|
16
|
-
it
|
16
|
+
it 'defaults instrumenter to noop' do
|
17
17
|
dsl = described_class.new(adapter)
|
18
18
|
expect(dsl.instrumenter).to be(Flipper::Instrumenters::Noop)
|
19
19
|
end
|
20
20
|
|
21
|
-
context
|
22
|
-
let(:instrumenter) { double('Instrumentor', :
|
21
|
+
context 'with overriden instrumenter' do
|
22
|
+
let(:instrumenter) { double('Instrumentor', instrument: nil) }
|
23
23
|
|
24
|
-
it
|
25
|
-
dsl = described_class.new(adapter, :
|
24
|
+
it 'overrides default instrumenter' do
|
25
|
+
dsl = described_class.new(adapter, instrumenter: instrumenter)
|
26
26
|
expect(dsl.instrumenter).to be(instrumenter)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
describe
|
32
|
-
it_should_behave_like
|
31
|
+
describe '#feature' do
|
32
|
+
it_should_behave_like 'a DSL feature' do
|
33
33
|
let(:method_name) { :feature }
|
34
|
-
let(:instrumenter) { double('Instrumentor', :
|
34
|
+
let(:instrumenter) { double('Instrumentor', instrument: nil) }
|
35
35
|
let(:feature) { dsl.send(method_name, :stats) }
|
36
|
-
let(:dsl) {
|
36
|
+
let(:dsl) { described_class.new(adapter, instrumenter: instrumenter) }
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
describe
|
41
|
-
let(:instrumenter) { double('Instrumentor', :
|
42
|
-
let(:dsl) {
|
43
|
-
let(:names) { %i
|
40
|
+
describe '#preload' do
|
41
|
+
let(:instrumenter) { double('Instrumentor', instrument: nil) }
|
42
|
+
let(:dsl) { described_class.new(adapter, instrumenter: instrumenter) }
|
43
|
+
let(:names) { %i(stats shiny) }
|
44
44
|
let(:features) { dsl.preload(names) }
|
45
45
|
|
46
|
-
it
|
46
|
+
it 'returns array of features' do
|
47
47
|
expect(features).to all be_instance_of(Flipper::Feature)
|
48
48
|
end
|
49
49
|
|
50
|
-
it
|
50
|
+
it 'sets names' do
|
51
51
|
expect(features.map(&:name)).to eq(names)
|
52
52
|
end
|
53
53
|
|
54
|
-
it
|
54
|
+
it 'sets adapter' do
|
55
55
|
features.each do |feature|
|
56
56
|
expect(feature.adapter.name).to eq(dsl.adapter.name)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
it
|
60
|
+
it 'sets instrumenter' do
|
61
61
|
features.each do |feature|
|
62
62
|
expect(feature.instrumenter).to eq(dsl.instrumenter)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
-
it
|
66
|
+
it 'memoizes the feature' do
|
67
67
|
features.each do |feature|
|
68
68
|
expect(dsl.feature(feature.name)).to equal(feature)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
describe
|
74
|
-
it_should_behave_like
|
73
|
+
describe '#[]' do
|
74
|
+
it_should_behave_like 'a DSL feature' do
|
75
75
|
let(:method_name) { :[] }
|
76
|
-
let(:instrumenter) { double('Instrumentor', :
|
76
|
+
let(:instrumenter) { double('Instrumentor', instrument: nil) }
|
77
77
|
let(:feature) { dsl.send(method_name, :stats) }
|
78
|
-
let(:dsl) {
|
78
|
+
let(:dsl) { described_class.new(adapter, instrumenter: instrumenter) }
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
describe
|
83
|
-
it_should_behave_like
|
82
|
+
describe '#boolean' do
|
83
|
+
it_should_behave_like 'a DSL boolean method' do
|
84
84
|
let(:method_name) { :boolean }
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
describe
|
89
|
-
it_should_behave_like
|
88
|
+
describe '#bool' do
|
89
|
+
it_should_behave_like 'a DSL boolean method' do
|
90
90
|
let(:method_name) { :bool }
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
94
|
-
describe
|
95
|
-
context
|
94
|
+
describe '#group' do
|
95
|
+
context 'for registered group' do
|
96
96
|
before do
|
97
|
-
@group = Flipper.register(:admins) {
|
97
|
+
@group = Flipper.register(:admins) {}
|
98
98
|
end
|
99
99
|
|
100
|
-
it
|
101
|
-
expect(
|
102
|
-
|
103
|
-
|
104
|
-
it "always returns same instance for same name" do
|
105
|
-
expect(subject.group(:admins)).to equal(subject.group(:admins))
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
context "for unregistered group" do
|
110
|
-
it "raises error" do
|
111
|
-
expect {
|
112
|
-
subject.group(:admins)
|
113
|
-
}.to raise_error(Flipper::GroupNotRegistered)
|
100
|
+
it 'delegates to Flipper' do
|
101
|
+
expect(Flipper).to receive(:group).with(:admins).and_return(@group)
|
102
|
+
expect(subject.group(:admins)).to be(@group)
|
114
103
|
end
|
115
104
|
end
|
116
105
|
end
|
117
106
|
|
118
|
-
describe
|
119
|
-
context
|
120
|
-
it
|
107
|
+
describe '#actor' do
|
108
|
+
context 'for a thing' do
|
109
|
+
it 'returns actor instance' do
|
121
110
|
thing = Struct.new(:flipper_id).new(33)
|
122
111
|
actor = subject.actor(thing)
|
123
112
|
expect(actor).to be_instance_of(Flipper::Types::Actor)
|
@@ -125,85 +114,85 @@ RSpec.describe Flipper::DSL do
|
|
125
114
|
end
|
126
115
|
end
|
127
116
|
|
128
|
-
context
|
129
|
-
it
|
130
|
-
expect
|
117
|
+
context 'for nil' do
|
118
|
+
it 'raises argument error' do
|
119
|
+
expect do
|
131
120
|
subject.actor(nil)
|
132
|
-
|
121
|
+
end.to raise_error(ArgumentError)
|
133
122
|
end
|
134
123
|
end
|
135
124
|
|
136
|
-
context
|
137
|
-
it
|
138
|
-
expect
|
125
|
+
context 'for something that is not actor wrappable' do
|
126
|
+
it 'raises argument error' do
|
127
|
+
expect do
|
139
128
|
subject.actor(Object.new)
|
140
|
-
|
129
|
+
end.to raise_error(ArgumentError)
|
141
130
|
end
|
142
131
|
end
|
143
132
|
end
|
144
133
|
|
145
|
-
describe
|
134
|
+
describe '#time' do
|
146
135
|
before do
|
147
136
|
@result = subject.time(5)
|
148
137
|
end
|
149
138
|
|
150
|
-
it
|
139
|
+
it 'returns percentage of time' do
|
151
140
|
expect(@result).to be_instance_of(Flipper::Types::PercentageOfTime)
|
152
141
|
end
|
153
142
|
|
154
|
-
it
|
143
|
+
it 'sets value' do
|
155
144
|
expect(@result.value).to eq(5)
|
156
145
|
end
|
157
146
|
|
158
|
-
it
|
147
|
+
it 'is aliased to percentage_of_time' do
|
159
148
|
expect(@result).to eq(subject.percentage_of_time(@result.value))
|
160
149
|
end
|
161
150
|
end
|
162
151
|
|
163
|
-
describe
|
152
|
+
describe '#actors' do
|
164
153
|
before do
|
165
154
|
@result = subject.actors(17)
|
166
155
|
end
|
167
156
|
|
168
|
-
it
|
157
|
+
it 'returns percentage of actors' do
|
169
158
|
expect(@result).to be_instance_of(Flipper::Types::PercentageOfActors)
|
170
159
|
end
|
171
160
|
|
172
|
-
it
|
161
|
+
it 'sets value' do
|
173
162
|
expect(@result.value).to eq(17)
|
174
163
|
end
|
175
164
|
|
176
|
-
it
|
165
|
+
it 'is aliased to percentage_of_actors' do
|
177
166
|
expect(@result).to eq(subject.percentage_of_actors(@result.value))
|
178
167
|
end
|
179
168
|
end
|
180
169
|
|
181
|
-
describe
|
182
|
-
context
|
183
|
-
it
|
170
|
+
describe '#features' do
|
171
|
+
context 'with no features enabled/disabled' do
|
172
|
+
it 'defaults to empty set' do
|
184
173
|
expect(subject.features).to eq(Set.new)
|
185
174
|
end
|
186
175
|
end
|
187
176
|
|
188
|
-
context
|
177
|
+
context 'with features enabled and disabled' do
|
189
178
|
before do
|
190
179
|
subject[:stats].enable
|
191
180
|
subject[:cache].enable
|
192
181
|
subject[:search].disable
|
193
182
|
end
|
194
183
|
|
195
|
-
it
|
184
|
+
it 'returns set of feature instances' do
|
196
185
|
expect(subject.features).to be_instance_of(Set)
|
197
186
|
subject.features.each do |feature|
|
198
187
|
expect(feature).to be_instance_of(Flipper::Feature)
|
199
188
|
end
|
200
|
-
expect(subject.features.map(&:name).map(&:to_s).sort).to eq(
|
189
|
+
expect(subject.features.map(&:name).map(&:to_s).sort).to eq(%w(cache search stats))
|
201
190
|
end
|
202
191
|
end
|
203
192
|
end
|
204
193
|
|
205
|
-
describe
|
206
|
-
it
|
194
|
+
describe '#enable/disable' do
|
195
|
+
it 'enables and disables the feature' do
|
207
196
|
expect(subject[:stats].boolean_value).to eq(false)
|
208
197
|
subject.enable(:stats)
|
209
198
|
expect(subject[:stats].boolean_value).to eq(true)
|
@@ -213,35 +202,35 @@ RSpec.describe Flipper::DSL do
|
|
213
202
|
end
|
214
203
|
end
|
215
204
|
|
216
|
-
describe
|
217
|
-
it
|
205
|
+
describe '#enable_actor/disable_actor' do
|
206
|
+
it 'enables and disables the feature for actor' do
|
218
207
|
actor = Struct.new(:flipper_id).new(5)
|
219
208
|
|
220
209
|
expect(subject[:stats].actors_value).to be_empty
|
221
210
|
subject.enable_actor(:stats, actor)
|
222
|
-
expect(subject[:stats].actors_value).to eq(Set[
|
211
|
+
expect(subject[:stats].actors_value).to eq(Set['5'])
|
223
212
|
|
224
213
|
subject.disable_actor(:stats, actor)
|
225
214
|
expect(subject[:stats].actors_value).to be_empty
|
226
215
|
end
|
227
216
|
end
|
228
217
|
|
229
|
-
describe
|
230
|
-
it
|
218
|
+
describe '#enable_group/disable_group' do
|
219
|
+
it 'enables and disables the feature for group' do
|
231
220
|
actor = Struct.new(:flipper_id).new(5)
|
232
221
|
group = Flipper.register(:fives) { |actor| actor.flipper_id == 5 }
|
233
222
|
|
234
223
|
expect(subject[:stats].groups_value).to be_empty
|
235
224
|
subject.enable_group(:stats, :fives)
|
236
|
-
expect(subject[:stats].groups_value).to eq(Set[
|
225
|
+
expect(subject[:stats].groups_value).to eq(Set['fives'])
|
237
226
|
|
238
227
|
subject.disable_group(:stats, :fives)
|
239
228
|
expect(subject[:stats].groups_value).to be_empty
|
240
229
|
end
|
241
230
|
end
|
242
231
|
|
243
|
-
describe
|
244
|
-
it
|
232
|
+
describe '#enable_percentage_of_time/disable_percentage_of_time' do
|
233
|
+
it 'enables and disables the feature for percentage of time' do
|
245
234
|
expect(subject[:stats].percentage_of_time_value).to be(0)
|
246
235
|
subject.enable_percentage_of_time(:stats, 6)
|
247
236
|
expect(subject[:stats].percentage_of_time_value).to be(6)
|
@@ -251,8 +240,8 @@ RSpec.describe Flipper::DSL do
|
|
251
240
|
end
|
252
241
|
end
|
253
242
|
|
254
|
-
describe
|
255
|
-
it
|
243
|
+
describe '#enable_percentage_of_actors/disable_percentage_of_actors' do
|
244
|
+
it 'enables and disables the feature for percentage of time' do
|
256
245
|
expect(subject[:stats].percentage_of_actors_value).to be(0)
|
257
246
|
subject.enable_percentage_of_actors(:stats, 6)
|
258
247
|
expect(subject[:stats].percentage_of_actors_value).to be(6)
|
@@ -263,7 +252,7 @@ RSpec.describe Flipper::DSL do
|
|
263
252
|
end
|
264
253
|
|
265
254
|
describe '#remove' do
|
266
|
-
it
|
255
|
+
it 'removes the feature' do
|
267
256
|
subject.enable(:stats)
|
268
257
|
|
269
258
|
expect { subject.remove(:stats) }.to change { subject.enabled?(:stats) }.to(false)
|