flipper 0.10.2 → 0.11.0.beta1
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.
- 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
data/lib/flipper/typecast.rb
CHANGED
data/lib/flipper/types/actor.rb
CHANGED
@@ -9,12 +9,10 @@ module Flipper
|
|
9
9
|
attr_reader :thing
|
10
10
|
|
11
11
|
def initialize(thing)
|
12
|
-
if thing.nil?
|
13
|
-
raise ArgumentError.new("thing cannot be nil")
|
14
|
-
end
|
12
|
+
raise ArgumentError, 'thing cannot be nil' if thing.nil?
|
15
13
|
|
16
14
|
unless thing.respond_to?(:flipper_id)
|
17
|
-
raise ArgumentError
|
15
|
+
raise ArgumentError, "#{thing.inspect} must respond to flipper_id, but does not"
|
18
16
|
end
|
19
17
|
|
20
18
|
@thing = thing
|
data/lib/flipper/types/group.rb
CHANGED
@@ -5,7 +5,8 @@ module Flipper
|
|
5
5
|
value = Typecast.to_integer(value)
|
6
6
|
|
7
7
|
if value < 0 || value > 100
|
8
|
-
raise ArgumentError,
|
8
|
+
raise ArgumentError,
|
9
|
+
"value must be a positive number less than or equal to 100, but was #{value}"
|
9
10
|
end
|
10
11
|
|
11
12
|
@value = value
|
data/lib/flipper/version.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
{
|
2
|
+
"key": "my_feature",
|
3
|
+
"state": "on",
|
4
|
+
"gates": [
|
5
|
+
{
|
6
|
+
"key": "boolean",
|
7
|
+
"name": "boolean",
|
8
|
+
"value": "true"
|
9
|
+
},
|
10
|
+
{
|
11
|
+
"key": "groups",
|
12
|
+
"name": "group",
|
13
|
+
"value": []
|
14
|
+
},
|
15
|
+
{
|
16
|
+
"key": "actors",
|
17
|
+
"name": "actor",
|
18
|
+
"value": []
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"key": "percentage_of_actors",
|
22
|
+
"name": "percentage_of_actors",
|
23
|
+
"value": null
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"key": "percentage_of_time",
|
27
|
+
"name": "percentage_of_time",
|
28
|
+
"value": null
|
29
|
+
}
|
30
|
+
]
|
31
|
+
}
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'flipper/adapters/http'
|
3
|
+
require 'flipper/adapters/pstore'
|
4
|
+
require 'flipper/spec/shared_adapter_specs'
|
5
|
+
require 'rack/handler/webrick'
|
6
|
+
|
7
|
+
FLIPPER_SPEC_API_PORT = ENV.fetch('FLIPPER_SPEC_API_PORT', 9001).to_i
|
8
|
+
|
9
|
+
RSpec.describe Flipper::Adapters::Http do
|
10
|
+
context 'adapter' do
|
11
|
+
subject do
|
12
|
+
described_class.new(uri: URI("http://localhost:#{FLIPPER_SPEC_API_PORT}"))
|
13
|
+
end
|
14
|
+
|
15
|
+
before :all do
|
16
|
+
dir = FlipperRoot.join('tmp').tap(&:mkpath)
|
17
|
+
log_path = dir.join('flipper_adapters_http_spec.log')
|
18
|
+
@pstore_file = dir.join('flipper.pstore')
|
19
|
+
@pstore_file.unlink if @pstore_file.exist?
|
20
|
+
|
21
|
+
api_adapter = Flipper::Adapters::PStore.new(@pstore_file)
|
22
|
+
flipper_api = Flipper.new(api_adapter)
|
23
|
+
app = Flipper::Api.app(flipper_api)
|
24
|
+
server_options = {
|
25
|
+
Port: FLIPPER_SPEC_API_PORT,
|
26
|
+
StartCallback: -> { @started = true },
|
27
|
+
Logger: WEBrick::Log.new(log_path.to_s, WEBrick::Log::INFO),
|
28
|
+
AccessLog: [
|
29
|
+
[log_path.open('w'), WEBrick::AccessLog::COMBINED_LOG_FORMAT],
|
30
|
+
],
|
31
|
+
}
|
32
|
+
@server = WEBrick::HTTPServer.new(server_options)
|
33
|
+
@server.mount '/', Rack::Handler::WEBrick, app
|
34
|
+
|
35
|
+
Thread.new { @server.start }
|
36
|
+
Timeout.timeout(1) { :wait until @started }
|
37
|
+
end
|
38
|
+
|
39
|
+
after :all do
|
40
|
+
@server.shutdown if @server
|
41
|
+
end
|
42
|
+
|
43
|
+
before(:each) do
|
44
|
+
@pstore_file.unlink if @pstore_file.exist?
|
45
|
+
end
|
46
|
+
|
47
|
+
it_should_behave_like 'a flipper adapter'
|
48
|
+
|
49
|
+
it "can enable and disable unregistered group" do
|
50
|
+
flipper = Flipper.new(subject)
|
51
|
+
expect(flipper[:search].enable_group(:some_made_up_group)).to be(true)
|
52
|
+
expect(flipper[:search].groups_value).to eq(Set["some_made_up_group"])
|
53
|
+
|
54
|
+
expect(flipper[:search].disable_group(:some_made_up_group)).to be(true)
|
55
|
+
expect(flipper[:search].groups_value).to eq(Set.new)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "sends default headers" do
|
60
|
+
headers = {
|
61
|
+
'Accept' => 'application/json',
|
62
|
+
'Content-Type' => 'application/json',
|
63
|
+
'User-Agent' => 'Flipper HTTP Adapter v0.10.2',
|
64
|
+
}
|
65
|
+
stub_request(:get, "http://app.com/flipper/features/feature_panel")
|
66
|
+
.with(headers: headers)
|
67
|
+
.to_return(status: 404, body: "", headers: {})
|
68
|
+
|
69
|
+
adapter = described_class.new(uri: URI('http://app.com/flipper'))
|
70
|
+
adapter.get(flipper[:feature_panel])
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#get" do
|
74
|
+
it "raises error when not successful response" do
|
75
|
+
stub_request(:get, "http://app.com/flipper/features/feature_panel")
|
76
|
+
.to_return(status: 503, body: "", headers: {})
|
77
|
+
|
78
|
+
adapter = described_class.new(uri: URI('http://app.com/flipper'))
|
79
|
+
expect do
|
80
|
+
adapter.get(flipper[:feature_panel])
|
81
|
+
end.to raise_error(Flipper::Adapters::Http::Error)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#get_multi" do
|
86
|
+
it "raises error when not successful response" do
|
87
|
+
stub_request(:get, "http://app.com/flipper/features?keys=feature_panel")
|
88
|
+
.to_return(status: 503, body: "", headers: {})
|
89
|
+
|
90
|
+
adapter = described_class.new(uri: URI('http://app.com/flipper'))
|
91
|
+
expect do
|
92
|
+
adapter.get_multi([flipper[:feature_panel]])
|
93
|
+
end.to raise_error(Flipper::Adapters::Http::Error)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "#features" do
|
98
|
+
it "raises error when not successful response" do
|
99
|
+
stub_request(:get, "http://app.com/flipper/features")
|
100
|
+
.to_return(status: 503, body: "", headers: {})
|
101
|
+
|
102
|
+
adapter = described_class.new(uri: URI('http://app.com/flipper'))
|
103
|
+
expect do
|
104
|
+
adapter.features
|
105
|
+
end.to raise_error(Flipper::Adapters::Http::Error)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe 'configuration' do
|
110
|
+
let(:options) do
|
111
|
+
{
|
112
|
+
uri: URI('http://app.com/mount-point'),
|
113
|
+
headers: { 'X-Custom-Header' => 'foo' },
|
114
|
+
basic_auth_username: 'username',
|
115
|
+
basic_auth_password: 'password',
|
116
|
+
read_timeout: 100,
|
117
|
+
open_timeout: 40,
|
118
|
+
}
|
119
|
+
end
|
120
|
+
subject { described_class.new(options) }
|
121
|
+
let(:feature) { flipper[:feature_panel] }
|
122
|
+
|
123
|
+
before do
|
124
|
+
stub_request(:get, %r{\Ahttp://app.com*}).to_return(body: fixture_file('feature.json'))
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'allows client to set request headers' do
|
128
|
+
subject.get(feature)
|
129
|
+
expect(
|
130
|
+
a_request(:get, 'http://app.com/mount-point/features/feature_panel')
|
131
|
+
.with(headers: { 'X-Custom-Header' => 'foo' })
|
132
|
+
).to have_been_made.once
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'allows client to set basic auth' do
|
136
|
+
subject.get(feature)
|
137
|
+
expect(
|
138
|
+
a_request(:get, 'http://app.com/mount-point/features/feature_panel')
|
139
|
+
.with(basic_auth: %w(username password))
|
140
|
+
).to have_been_made.once
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def fixture_file(name)
|
145
|
+
fixtures_path = File.expand_path('../../../fixtures', __FILE__)
|
146
|
+
File.new(fixtures_path + '/' + name)
|
147
|
+
end
|
148
|
+
end
|
@@ -13,13 +13,13 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
13
13
|
let(:gate) { feature.gate(:percentage_of_actors) }
|
14
14
|
let(:thing) { flipper.actors(22) }
|
15
15
|
|
16
|
-
subject
|
17
|
-
described_class.new(adapter, :
|
18
|
-
|
16
|
+
subject do
|
17
|
+
described_class.new(adapter, instrumenter: instrumenter)
|
18
|
+
end
|
19
19
|
|
20
20
|
it_should_behave_like 'a flipper adapter'
|
21
21
|
|
22
|
-
it
|
22
|
+
it 'forwards missing methods to underlying adapter' do
|
23
23
|
adapter = Class.new do
|
24
24
|
def foo
|
25
25
|
:foo
|
@@ -29,14 +29,14 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
29
29
|
expect(instrumented.foo).to eq(:foo)
|
30
30
|
end
|
31
31
|
|
32
|
-
describe
|
33
|
-
it
|
32
|
+
describe '#name' do
|
33
|
+
it 'is instrumented' do
|
34
34
|
expect(subject.name).to be(:instrumented)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
describe
|
39
|
-
it
|
38
|
+
describe '#get' do
|
39
|
+
it 'records instrumentation' do
|
40
40
|
result = subject.get(feature)
|
41
41
|
|
42
42
|
event = instrumenter.events.last
|
@@ -49,8 +49,8 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
describe
|
53
|
-
it
|
52
|
+
describe '#enable' do
|
53
|
+
it 'records instrumentation' do
|
54
54
|
result = subject.enable(feature, gate, thing)
|
55
55
|
|
56
56
|
event = instrumenter.events.last
|
@@ -64,8 +64,8 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
describe
|
68
|
-
it
|
67
|
+
describe '#disable' do
|
68
|
+
it 'records instrumentation' do
|
69
69
|
result = subject.disable(feature, gate, thing)
|
70
70
|
|
71
71
|
event = instrumenter.events.last
|
@@ -79,8 +79,8 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
-
describe
|
83
|
-
it
|
82
|
+
describe '#add' do
|
83
|
+
it 'records instrumentation' do
|
84
84
|
result = subject.add(feature)
|
85
85
|
|
86
86
|
event = instrumenter.events.last
|
@@ -93,8 +93,8 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
describe
|
97
|
-
it
|
96
|
+
describe '#remove' do
|
97
|
+
it 'records instrumentation' do
|
98
98
|
result = subject.remove(feature)
|
99
99
|
|
100
100
|
event = instrumenter.events.last
|
@@ -107,8 +107,8 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
-
describe
|
111
|
-
it
|
110
|
+
describe '#clear' do
|
111
|
+
it 'records instrumentation' do
|
112
112
|
result = subject.clear(feature)
|
113
113
|
|
114
114
|
event = instrumenter.events.last
|
@@ -121,8 +121,8 @@ RSpec.describe Flipper::Adapters::Instrumented do
|
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
|
-
describe
|
125
|
-
it
|
124
|
+
describe '#features' do
|
125
|
+
it 'records instrumentation' do
|
126
126
|
result = subject.features
|
127
127
|
|
128
128
|
event = instrumenter.events.last
|
@@ -13,7 +13,7 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
13
13
|
|
14
14
|
it_should_behave_like 'a flipper adapter'
|
15
15
|
|
16
|
-
it
|
16
|
+
it 'forwards missing methods to underlying adapter' do
|
17
17
|
adapter = Class.new do
|
18
18
|
def foo
|
19
19
|
:foo
|
@@ -23,14 +23,14 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
23
23
|
expect(memoizable.foo).to eq(:foo)
|
24
24
|
end
|
25
25
|
|
26
|
-
describe
|
27
|
-
it
|
26
|
+
describe '#name' do
|
27
|
+
it 'is instrumented' do
|
28
28
|
expect(subject.name).to be(:memoizable)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe
|
33
|
-
it
|
32
|
+
describe '#memoize=' do
|
33
|
+
it 'sets value' do
|
34
34
|
subject.memoize = true
|
35
35
|
expect(subject.memoizing?).to eq(true)
|
36
36
|
|
@@ -38,44 +38,44 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
38
38
|
expect(subject.memoizing?).to eq(false)
|
39
39
|
end
|
40
40
|
|
41
|
-
it
|
41
|
+
it 'clears the local cache' do
|
42
42
|
subject.cache['some'] = 'thing'
|
43
43
|
subject.memoize = true
|
44
44
|
expect(subject.cache).to be_empty
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
describe
|
49
|
-
it
|
48
|
+
describe '#memoizing?' do
|
49
|
+
it 'returns true if enabled' do
|
50
50
|
subject.memoize = true
|
51
51
|
expect(subject.memoizing?).to eq(true)
|
52
52
|
end
|
53
53
|
|
54
|
-
it
|
54
|
+
it 'returns false if disabled' do
|
55
55
|
subject.memoize = false
|
56
56
|
expect(subject.memoizing?).to eq(false)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
describe
|
61
|
-
context
|
60
|
+
describe '#get' do
|
61
|
+
context 'with memoization enabled' do
|
62
62
|
before do
|
63
63
|
subject.memoize = true
|
64
64
|
end
|
65
65
|
|
66
|
-
it
|
66
|
+
it 'memoizes feature' do
|
67
67
|
feature = flipper[:stats]
|
68
68
|
result = subject.get(feature)
|
69
69
|
expect(cache[feature.key]).to be(result)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
context
|
73
|
+
context 'with memoization disabled' do
|
74
74
|
before do
|
75
75
|
subject.memoize = false
|
76
76
|
end
|
77
77
|
|
78
|
-
it
|
78
|
+
it 'returns result' do
|
79
79
|
feature = flipper[:stats]
|
80
80
|
result = subject.get(feature)
|
81
81
|
adapter_result = adapter.get(feature)
|
@@ -84,30 +84,30 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
|
-
describe
|
88
|
-
context
|
87
|
+
describe '#get_multi' do
|
88
|
+
context 'with memoization enabled' do
|
89
89
|
before do
|
90
90
|
subject.memoize = true
|
91
91
|
end
|
92
92
|
|
93
|
-
it
|
94
|
-
names = %i
|
93
|
+
it 'memoizes feature' do
|
94
|
+
names = %i(stats shiny)
|
95
95
|
features = names.map { |name| flipper[name] }
|
96
96
|
results = subject.get_multi(features)
|
97
97
|
features.each do |feature|
|
98
|
-
expect(cache[feature.key]).
|
98
|
+
expect(cache[feature.key]).not_to be(nil)
|
99
99
|
expect(cache[feature.key]).to be(results[feature.key])
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
context
|
104
|
+
context 'with memoization disabled' do
|
105
105
|
before do
|
106
106
|
subject.memoize = false
|
107
107
|
end
|
108
108
|
|
109
|
-
it
|
110
|
-
names = %i
|
109
|
+
it 'returns result' do
|
110
|
+
names = %i(stats shiny)
|
111
111
|
features = names.map { |name| flipper[name] }
|
112
112
|
result = subject.get_multi(features)
|
113
113
|
adapter_result = adapter.get_multi(features)
|
@@ -116,27 +116,27 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
describe
|
120
|
-
context
|
119
|
+
describe '#enable' do
|
120
|
+
context 'with memoization enabled' do
|
121
121
|
before do
|
122
122
|
subject.memoize = true
|
123
123
|
end
|
124
124
|
|
125
|
-
it
|
125
|
+
it 'unmemoizes feature' do
|
126
126
|
feature = flipper[:stats]
|
127
127
|
gate = feature.gate(:boolean)
|
128
|
-
cache[feature.key] = {:
|
128
|
+
cache[feature.key] = { some: 'thing' }
|
129
129
|
subject.enable(feature, gate, flipper.bool)
|
130
130
|
expect(cache[feature.key]).to be_nil
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
context
|
134
|
+
context 'with memoization disabled' do
|
135
135
|
before do
|
136
136
|
subject.memoize = false
|
137
137
|
end
|
138
138
|
|
139
|
-
it
|
139
|
+
it 'returns result' do
|
140
140
|
feature = flipper[:stats]
|
141
141
|
gate = feature.gate(:boolean)
|
142
142
|
result = subject.enable(feature, gate, flipper.bool)
|
@@ -146,27 +146,27 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
149
|
-
describe
|
150
|
-
context
|
149
|
+
describe '#disable' do
|
150
|
+
context 'with memoization enabled' do
|
151
151
|
before do
|
152
152
|
subject.memoize = true
|
153
153
|
end
|
154
154
|
|
155
|
-
it
|
155
|
+
it 'unmemoizes feature' do
|
156
156
|
feature = flipper[:stats]
|
157
157
|
gate = feature.gate(:boolean)
|
158
|
-
cache[feature.key] = {:
|
158
|
+
cache[feature.key] = { some: 'thing' }
|
159
159
|
subject.disable(feature, gate, flipper.bool)
|
160
160
|
expect(cache[feature.key]).to be_nil
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
-
context
|
164
|
+
context 'with memoization disabled' do
|
165
165
|
before do
|
166
166
|
subject.memoize = false
|
167
167
|
end
|
168
168
|
|
169
|
-
it
|
169
|
+
it 'returns result' do
|
170
170
|
feature = flipper[:stats]
|
171
171
|
gate = feature.gate(:boolean)
|
172
172
|
result = subject.disable(feature, gate, flipper.bool)
|
@@ -176,13 +176,13 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
-
describe
|
180
|
-
context
|
179
|
+
describe '#features' do
|
180
|
+
context 'with memoization enabled' do
|
181
181
|
before do
|
182
182
|
subject.memoize = true
|
183
183
|
end
|
184
184
|
|
185
|
-
it
|
185
|
+
it 'memoizes features' do
|
186
186
|
flipper[:stats].enable
|
187
187
|
flipper[:search].disable
|
188
188
|
result = subject.features
|
@@ -190,92 +190,92 @@ RSpec.describe Flipper::Adapters::Memoizable do
|
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
|
-
context
|
193
|
+
context 'with memoization disabled' do
|
194
194
|
before do
|
195
195
|
subject.memoize = false
|
196
196
|
end
|
197
197
|
|
198
|
-
it
|
198
|
+
it 'returns result' do
|
199
199
|
expect(subject.features).to eq(adapter.features)
|
200
200
|
end
|
201
201
|
end
|
202
202
|
end
|
203
203
|
|
204
|
-
describe
|
205
|
-
context
|
204
|
+
describe '#add' do
|
205
|
+
context 'with memoization enabled' do
|
206
206
|
before do
|
207
207
|
subject.memoize = true
|
208
208
|
end
|
209
209
|
|
210
|
-
it
|
211
|
-
cache[features_key] = {:
|
210
|
+
it 'unmemoizes the known features' do
|
211
|
+
cache[features_key] = { some: 'thing' }
|
212
212
|
subject.add(flipper[:stats])
|
213
213
|
expect(cache).to be_empty
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
-
context
|
217
|
+
context 'with memoization disabled' do
|
218
218
|
before do
|
219
219
|
subject.memoize = false
|
220
220
|
end
|
221
221
|
|
222
|
-
it
|
222
|
+
it 'returns result' do
|
223
223
|
expect(subject.add(flipper[:stats])).to eq(adapter.add(flipper[:stats]))
|
224
224
|
end
|
225
225
|
end
|
226
226
|
end
|
227
227
|
|
228
|
-
describe
|
229
|
-
context
|
228
|
+
describe '#remove' do
|
229
|
+
context 'with memoization enabled' do
|
230
230
|
before do
|
231
231
|
subject.memoize = true
|
232
232
|
end
|
233
233
|
|
234
|
-
it
|
235
|
-
cache[features_key] = {:
|
234
|
+
it 'unmemoizes the known features' do
|
235
|
+
cache[features_key] = { some: 'thing' }
|
236
236
|
subject.remove(flipper[:stats])
|
237
237
|
expect(cache).to be_empty
|
238
238
|
end
|
239
239
|
|
240
|
-
it
|
240
|
+
it 'unmemoizes the feature' do
|
241
241
|
feature = flipper[:stats]
|
242
|
-
cache[feature.key] = {:
|
242
|
+
cache[feature.key] = { some: 'thing' }
|
243
243
|
subject.remove(feature)
|
244
244
|
expect(cache[feature.key]).to be_nil
|
245
245
|
end
|
246
246
|
end
|
247
247
|
|
248
|
-
context
|
248
|
+
context 'with memoization disabled' do
|
249
249
|
before do
|
250
250
|
subject.memoize = false
|
251
251
|
end
|
252
252
|
|
253
|
-
it
|
253
|
+
it 'returns result' do
|
254
254
|
expect(subject.remove(flipper[:stats])).to eq(adapter.remove(flipper[:stats]))
|
255
255
|
end
|
256
256
|
end
|
257
257
|
end
|
258
258
|
|
259
|
-
describe
|
260
|
-
context
|
259
|
+
describe '#clear' do
|
260
|
+
context 'with memoization enabled' do
|
261
261
|
before do
|
262
262
|
subject.memoize = true
|
263
263
|
end
|
264
264
|
|
265
|
-
it
|
265
|
+
it 'unmemoizes feature' do
|
266
266
|
feature = flipper[:stats]
|
267
|
-
cache[feature.key] = {:
|
267
|
+
cache[feature.key] = { some: 'thing' }
|
268
268
|
subject.clear(feature)
|
269
269
|
expect(cache[feature.key]).to be_nil
|
270
270
|
end
|
271
271
|
end
|
272
272
|
|
273
|
-
context
|
273
|
+
context 'with memoization disabled' do
|
274
274
|
before do
|
275
275
|
subject.memoize = false
|
276
276
|
end
|
277
277
|
|
278
|
-
it
|
278
|
+
it 'returns result' do
|
279
279
|
feature = flipper[:stats]
|
280
280
|
expect(subject.clear(feature)).to eq(adapter.clear(feature))
|
281
281
|
end
|