flip_fab 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +29 -0
  3. data/example/rails_app/Gemfile +2 -19
  4. data/example/rails_app/app/assets/javascripts/application.js +0 -1
  5. data/example/rails_app/app/controllers/beavers_controller.rb +11 -12
  6. data/example/rails_app/bin/rails +1 -1
  7. data/example/rails_app/config.ru +1 -1
  8. data/example/rails_app/config/environments/development.rb +1 -1
  9. data/example/rails_app/config/environments/test.rb +2 -2
  10. data/example/rails_app/config/initializers/cookies_serializer.rb +1 -1
  11. data/example/rails_app/db/schema.rb +5 -7
  12. data/example/rails_app/spec/rails_helper.rb +2 -2
  13. data/example/rails_app/spec/spec_helper.rb +0 -1
  14. data/example/rails_app/test/controllers/beavers_controller_test.rb +12 -12
  15. data/flip_fab.gemspec +9 -8
  16. data/lib/flip_fab.rb +3 -3
  17. data/lib/flip_fab/contextual_feature.rb +11 -17
  18. data/lib/flip_fab/cookie_persistence.rb +11 -16
  19. data/lib/flip_fab/feature.rb +2 -3
  20. data/lib/flip_fab/features_by_name.rb +4 -4
  21. data/lib/flip_fab/helper.rb +0 -1
  22. data/lib/flip_fab/persistence.rb +2 -3
  23. data/lib/flip_fab/version.rb +1 -1
  24. data/script/cibuild +10 -0
  25. data/spec/lib/flip_fab/contextual_feature_spec.rb +47 -56
  26. data/spec/lib/flip_fab/cookie_persistence_spec.rb +40 -43
  27. data/spec/lib/flip_fab/feature_spec.rb +6 -9
  28. data/spec/lib/flip_fab/features_by_name_spec.rb +3 -6
  29. data/spec/lib/flip_fab/helper_spec.rb +35 -38
  30. data/spec/lib/flip_fab/persistence_spec.rb +2 -5
  31. data/spec/lib/flip_fab_spec.rb +11 -15
  32. data/spec/spec_helper.rb +47 -49
  33. data/spec/support/test_app.rb +2 -2
  34. data/spec/support/test_context.rb +1 -1
  35. data/spec/support/test_multiple_persistence.rb +2 -3
  36. data/spec/support/test_persistence.rb +2 -3
  37. data/spec/support/test_rack_context.rb +3 -3
  38. metadata +38 -25
  39. data/example/rails_app/README.rdoc +0 -28
  40. data/example/rails_app/config/rabbit_feed.yml +0 -8
  41. data/example/rails_app/config/unicorn.rb +0 -4
@@ -1,6 +1,5 @@
1
1
  module FlipFab
2
2
  module Helper
3
-
4
3
  def features
5
4
  @features ||= FlipFab.features.with_context self
6
5
  end
@@ -1,9 +1,8 @@
1
1
  module FlipFab
2
2
  class Persistence
3
-
4
3
  attr_reader :feature_name, :context
5
4
 
6
- def initialize feature_name, context
5
+ def initialize(feature_name, context)
7
6
  @feature_name = feature_name
8
7
  @context = context
9
8
  end
@@ -12,7 +11,7 @@ module FlipFab
12
11
  raise NotImplementedError
13
12
  end
14
13
 
15
- def write state
14
+ def write(state)
16
15
  raise NotImplementedError
17
16
  end
18
17
  end
@@ -1,3 +1,3 @@
1
1
  module FlipFab
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'.freeze
3
3
  end
@@ -0,0 +1,10 @@
1
+ #!/bin/sh
2
+
3
+ # script/cibuild: Setup environment for CI to run tests. This is primarily
4
+ # designed to run on the continuous integration server.
5
+
6
+ set -e
7
+
8
+ cd "$(dirname "$0")/.."
9
+ bundle exec rubocop --fail-level warning
10
+
@@ -1,15 +1,14 @@
1
1
  module FlipFab
2
2
  describe ContextualFeature do
3
- let(:override) { }
3
+ let(:override) {}
4
4
  let(:default) { :disabled }
5
5
  let(:persistence_adapters) { [TestPersistence] }
6
- let(:feature) { Feature.new :example_feature, { default: default, persistence_adapters: persistence_adapters } }
7
- let(:feature_states) {{ example_feature: :enabled }}
8
- let(:context) { TestContext.new feature_states, { 'example_feature' => override } }
9
- subject{ described_class.new feature, context }
6
+ let(:feature) { Feature.new :example_feature, default: default, persistence_adapters: persistence_adapters }
7
+ let(:feature_states) { { example_feature: :enabled } }
8
+ let(:context) { TestContext.new feature_states, 'example_feature' => override }
9
+ subject { described_class.new feature, context }
10
10
 
11
11
  describe '.new' do
12
-
13
12
  it 'assigns the feature' do
14
13
  expect(subject.feature).to eq(feature)
15
14
  end
@@ -22,23 +21,22 @@ module FlipFab
22
21
  let(:override) { 'disabled' }
23
22
 
24
23
  it 'persists the override' do
25
- expect{ subject }.to change{ feature_states }.from({ example_feature: :enabled }).to({ example_feature: :disabled })
24
+ expect { subject }.to change { feature_states }.from(example_feature: :enabled).to(example_feature: :disabled)
26
25
  end
27
26
 
28
27
  context 'when the override provided is not one of enabled or disabled, it does not persist the override' do
29
28
  let(:override) { '' }
30
29
 
31
30
  it 'does not persist the override' do
32
- expect{ subject }.not_to change{ feature_states }.from({ example_feature: :enabled })
31
+ expect { subject }.not_to change { feature_states }.from(example_feature: :enabled)
33
32
  end
34
33
  end
35
34
  end
36
35
  end
37
36
 
38
37
  describe '#enabled?' do
39
-
40
38
  context 'when the feature is enabled in the adapter' do
41
- let(:feature_states) {{ example_feature: :enabled }}
39
+ let(:feature_states) { { example_feature: :enabled } }
42
40
 
43
41
  it 'returns true' do
44
42
  expect(subject.enabled?).to be_truthy
@@ -54,7 +52,7 @@ module FlipFab
54
52
  end
55
53
 
56
54
  context 'when the feature is disabled in the adapter' do
57
- let(:feature_states) {{ example_feature: :disabled }}
55
+ let(:feature_states) { { example_feature: :disabled } }
58
56
 
59
57
  it 'returns false' do
60
58
  expect(subject.enabled?).to be_falsey
@@ -62,7 +60,7 @@ module FlipFab
62
60
  end
63
61
 
64
62
  context 'when the feature is not specified in the adapter' do
65
- let(:feature_states) {{ }}
63
+ let(:feature_states) { {} }
66
64
 
67
65
  context 'when the default is :enabled' do
68
66
  let(:default) { :enabled }
@@ -85,7 +83,7 @@ module FlipFab
85
83
  let(:persistence_adapters) { [TestPersistence, TestMultiplePersistence] }
86
84
 
87
85
  context 'when the first adapter has enabled and the second adapter has nil' do
88
- let(:feature_states) {{ example_feature: :enabled, different_example_feature: nil }}
86
+ let(:feature_states) { { example_feature: :enabled, different_example_feature: nil } }
89
87
 
90
88
  it 'returns true' do
91
89
  expect(subject.enabled?).to be_truthy
@@ -93,7 +91,7 @@ module FlipFab
93
91
  end
94
92
 
95
93
  context 'when the first adapter has nil and the second adapter has enabled' do
96
- let(:feature_states) {{ example_feature: nil, different_example_feature: :enabled }}
94
+ let(:feature_states) { { example_feature: nil, different_example_feature: :enabled } }
97
95
 
98
96
  it 'returns true' do
99
97
  expect(subject.enabled?).to be_truthy
@@ -101,7 +99,7 @@ module FlipFab
101
99
  end
102
100
 
103
101
  context 'when the first adapter has disabled and the second adapter has enabled' do
104
- let(:feature_states) {{ example_feature: :disabled, different_example_feature: :enabled }}
102
+ let(:feature_states) { { example_feature: :disabled, different_example_feature: :enabled } }
105
103
 
106
104
  it 'returns false' do
107
105
  expect(subject.enabled?).to be_falsey
@@ -111,9 +109,8 @@ module FlipFab
111
109
  end
112
110
 
113
111
  describe '#disabled?' do
114
-
115
112
  context 'when #enabled? returns true' do
116
- let(:feature_states) {{ example_feature: :enabled }}
113
+ let(:feature_states) { { example_feature: :enabled } }
117
114
 
118
115
  it 'returns false' do
119
116
  expect(subject.disabled?).to be_falsey
@@ -121,7 +118,7 @@ module FlipFab
121
118
  end
122
119
 
123
120
  context 'when #enabled? returns false' do
124
- let(:feature_states) {{ example_feature: :disabled }}
121
+ let(:feature_states) { { example_feature: :disabled } }
125
122
 
126
123
  it 'returns true' do
127
124
  expect(subject.disabled?).to be_truthy
@@ -130,34 +127,30 @@ module FlipFab
130
127
  end
131
128
 
132
129
  describe '#state=' do
133
-
134
130
  context 'when the provided value is not :enabled or :disabled' do
135
-
136
131
  it 'raises' do
137
- expect{ subject.state = '' }.to raise_error 'Invalid state provided: ``, possible states are :enabled, :disabled'
138
- expect{ subject.state = 'enabled' }.to raise_error 'Invalid state provided: `enabled`, possible states are :enabled, :disabled'
132
+ expect { subject.state = '' }.to raise_error 'Invalid state provided: ``, possible states are :enabled, :disabled'
133
+ expect { subject.state = 'enabled' }.to raise_error 'Invalid state provided: `enabled`, possible states are :enabled, :disabled'
139
134
  end
140
135
  end
141
136
 
142
137
  context 'when the provided value is :enabled or :disabled' do
143
-
144
138
  it 'changes the state of the feature' do
145
- expect{ subject.state = :disabled }.to change{subject.enabled?}.from(true).to(false)
146
- expect{ subject.state = :enabled }.to change{subject.enabled?}.from(false).to(true)
139
+ expect { subject.state = :disabled }.to change { subject.enabled? }.from(true).to(false)
140
+ expect { subject.state = :enabled }.to change { subject.enabled? }.from(false).to(true)
147
141
  end
148
142
  end
149
143
  end
150
144
 
151
145
  describe '#enable' do
152
-
153
146
  context 'when the state has been overridden' do
154
147
  let(:override) { 'disabled' }
155
148
 
156
149
  context 'and the persistence adapter has the opposite state' do
157
- let(:feature_states) {{ example_feature: :disabled }}
150
+ let(:feature_states) { { example_feature: :disabled } }
158
151
 
159
152
  it 'does not change the state of the feature' do
160
- expect{subject.enable}.not_to change{subject.enabled?}.from(false)
153
+ expect { subject.enable }.not_to change { subject.enabled? }.from(false)
161
154
  end
162
155
 
163
156
  it 'does not persist the state in the adapter' do
@@ -169,14 +162,14 @@ module FlipFab
169
162
 
170
163
  context 'when there are multiple persistence adapters' do
171
164
  let(:persistence_adapters) { [TestPersistence, TestMultiplePersistence] }
172
- let(:feature_states) {{ example_feature: :disabled, different_example_feature: :disabled }}
165
+ let(:feature_states) { { example_feature: :disabled, different_example_feature: :disabled } }
173
166
 
174
167
  it 'changes the state of the feature' do
175
- expect{subject.enable}.to change{subject.enabled?}.from(false).to(true)
168
+ expect { subject.enable }.to change { subject.enabled? }.from(false).to(true)
176
169
  end
177
170
 
178
171
  it 'persists the state in the adapters' do
179
- expect{ subject.enable }.to change{ feature_states }.from({ example_feature: :disabled, different_example_feature: :disabled }).to({ example_feature: :enabled, different_example_feature: :enabled })
172
+ expect { subject.enable }.to change { feature_states }.from(example_feature: :disabled, different_example_feature: :disabled).to(example_feature: :enabled, different_example_feature: :enabled)
180
173
  end
181
174
  end
182
175
 
@@ -184,37 +177,37 @@ module FlipFab
184
177
  let(:persistence_adapters) { [TestPersistence] }
185
178
 
186
179
  context 'and the persistence adapter has the same state' do
187
- let(:feature_states) {{ example_feature: :enabled }}
180
+ let(:feature_states) { { example_feature: :enabled } }
188
181
 
189
182
  it 'does not change the state of the feature' do
190
- expect{subject.enable}.not_to change{subject.enabled?}.from(true)
183
+ expect { subject.enable }.not_to change { subject.enabled? }.from(true)
191
184
  end
192
185
  end
193
186
 
194
187
  context 'and the persistence adapter has the opposite state' do
195
- let(:feature_states) {{ example_feature: :disabled }}
188
+ let(:feature_states) { { example_feature: :disabled } }
196
189
 
197
190
  it 'changes the state of the feature' do
198
- expect{subject.enable}.to change{subject.enabled?}.from(false).to(true)
191
+ expect { subject.enable }.to change { subject.enabled? }.from(false).to(true)
199
192
  end
200
193
 
201
194
  it 'persists the state in the adapter' do
202
- expect{ subject.enable }.to change{ feature_states }.from({ example_feature: :disabled }).to({ example_feature: :enabled })
195
+ expect { subject.enable }.to change { feature_states }.from(example_feature: :disabled).to(example_feature: :enabled)
203
196
  end
204
197
  end
205
198
 
206
199
  context 'and the persistence adapter has no state' do
207
- let(:feature_states) {{ }}
200
+ let(:feature_states) { {} }
208
201
 
209
202
  context 'and the feature is disabled' do
210
203
  let(:default) { :disabled }
211
204
 
212
205
  it 'changes the state of the feature' do
213
- expect{subject.enable}.to change{subject.enabled?}.from(false).to(true)
206
+ expect { subject.enable }.to change { subject.enabled? }.from(false).to(true)
214
207
  end
215
208
 
216
209
  it 'persists the state in the adapter' do
217
- expect{ subject.enable }.to change{ feature_states }.from({ }).to({ example_feature: :enabled })
210
+ expect { subject.enable }.to change { feature_states }.from({}).to(example_feature: :enabled)
218
211
  end
219
212
  end
220
213
 
@@ -222,11 +215,11 @@ module FlipFab
222
215
  let(:default) { :enabled }
223
216
 
224
217
  it 'does not change the state of the feature' do
225
- expect{subject.enable}.not_to change{subject.enabled?}.from(true)
218
+ expect { subject.enable }.not_to change { subject.enabled? }.from(true)
226
219
  end
227
220
 
228
221
  it 'persists the state in the adapter' do
229
- expect{ subject.enable }.to change{ feature_states }.from({ }).to({ example_feature: :enabled })
222
+ expect { subject.enable }.to change { feature_states }.from({}).to(example_feature: :enabled)
230
223
  end
231
224
  end
232
225
  end
@@ -238,7 +231,7 @@ module FlipFab
238
231
  let(:default) { :enabled }
239
232
 
240
233
  it 'does not change the state of the feature' do
241
- expect{subject.enable}.not_to change{subject.enabled?}.from(true)
234
+ expect { subject.enable }.not_to change { subject.enabled? }.from(true)
242
235
  end
243
236
  end
244
237
 
@@ -246,24 +239,22 @@ module FlipFab
246
239
  let(:default) { :disabled }
247
240
 
248
241
  it 'changes the state of the feature' do
249
- expect{subject.enable}.to change{subject.enabled?}.from(false).to(true)
242
+ expect { subject.enable }.to change { subject.enabled? }.from(false).to(true)
250
243
  end
251
244
  end
252
245
  end
253
246
  end
254
247
  end
255
248
 
256
-
257
249
  describe '#disable' do
258
-
259
250
  context 'when the state has been overridden' do
260
251
  let(:override) { 'enabled' }
261
252
 
262
253
  context 'and the persistence adapter has the opposite state' do
263
- let(:feature_states) {{ example_feature: :enabled }}
254
+ let(:feature_states) { { example_feature: :enabled } }
264
255
 
265
256
  it 'does not change the state of the feature' do
266
- expect{subject.disable}.not_to change{subject.disabled?}.from(false)
257
+ expect { subject.disable }.not_to change { subject.disabled? }.from(false)
267
258
  end
268
259
 
269
260
  it 'does not persist the state in the adapter' do
@@ -277,18 +268,18 @@ module FlipFab
277
268
  let(:persistence_adapters) { [TestPersistence] }
278
269
 
279
270
  context 'and the persistence adapter has the same state' do
280
- let(:feature_states) {{ example_feature: :disabled }}
271
+ let(:feature_states) { { example_feature: :disabled } }
281
272
 
282
273
  it 'does not change the state of the feature' do
283
- expect{subject.disable}.not_to change{subject.disabled?}.from(true)
274
+ expect { subject.disable }.not_to change { subject.disabled? }.from(true)
284
275
  end
285
276
  end
286
277
 
287
278
  context 'and the persistence adapter has the opposite state' do
288
- let(:feature_states) {{ example_feature: :enabled }}
279
+ let(:feature_states) { { example_feature: :enabled } }
289
280
 
290
281
  it 'changes the state of the feature' do
291
- expect{subject.disable}.to change{subject.disabled?}.from(false).to(true)
282
+ expect { subject.disable }.to change { subject.disabled? }.from(false).to(true)
292
283
  end
293
284
 
294
285
  it 'persists the state in the adapter' do
@@ -298,13 +289,13 @@ module FlipFab
298
289
  end
299
290
 
300
291
  context 'and the persistence adapter has no state' do
301
- let(:feature_states) {{ }}
292
+ let(:feature_states) { {} }
302
293
 
303
294
  context 'and the feature is enabled' do
304
295
  let(:default) { :enabled }
305
296
 
306
297
  it 'changes the state of the feature' do
307
- expect{subject.disable}.to change{subject.disabled?}.from(false).to(true)
298
+ expect { subject.disable }.to change { subject.disabled? }.from(false).to(true)
308
299
  end
309
300
 
310
301
  it 'persists the state in the adapter' do
@@ -317,7 +308,7 @@ module FlipFab
317
308
  let(:default) { :disabled }
318
309
 
319
310
  it 'does not change the state of the feature' do
320
- expect{subject.disable}.not_to change{subject.disabled?}.from(true)
311
+ expect { subject.disable }.not_to change { subject.disabled? }.from(true)
321
312
  end
322
313
 
323
314
  it 'persists the state in the adapter' do
@@ -334,7 +325,7 @@ module FlipFab
334
325
  let(:default) { :disabled }
335
326
 
336
327
  it 'does not change the state of the feature' do
337
- expect{subject.disable}.not_to change{subject.disabled?}.from(true)
328
+ expect { subject.disable }.not_to change { subject.disabled? }.from(true)
338
329
  end
339
330
  end
340
331
 
@@ -342,7 +333,7 @@ module FlipFab
342
333
  let(:default) { :enabled }
343
334
 
344
335
  it 'changes the state of the feature' do
345
- expect{subject.disable}.to change{subject.disabled?}.from(false).to(true)
336
+ expect { subject.disable }.to change { subject.disabled? }.from(false).to(true)
346
337
  end
347
338
  end
348
339
  end
@@ -3,66 +3,63 @@ require 'timecop'
3
3
 
4
4
  module FlipFab
5
5
  describe CookiePersistence do
6
- let(:cookies) { }
6
+ let(:cookies) {}
7
7
  let(:context) { TestRackContext.new cookies, 'simplybusiness.co.uk' }
8
8
  before { FlipFab.define_feature :example_feature }
9
9
  after { FlipFab.features.clear }
10
- subject{ described_class.new :example_feature, context }
10
+ subject { described_class.new :example_feature, context }
11
11
 
12
- it 'runs the feature' do
13
- feature
14
- end
15
-
16
- step 'the host is :host' do |host|
17
- @host = host
18
- end
12
+ feature do
13
+ step 'the host is :host' do |host|
14
+ @host = host
15
+ end
19
16
 
20
- step 'the feature name is :feature_name' do |feature_name|
21
- @feature_name = feature_name
22
- end
17
+ step 'the feature name is :feature_name' do |feature_name|
18
+ @feature_name = feature_name
19
+ end
23
20
 
24
- step 'the time is :current_time' do |current_time|
25
- Timecop.freeze(Time.parse current_time)
26
- end
21
+ step 'the time is :current_time' do |current_time|
22
+ Timecop.freeze(Time.parse(current_time))
23
+ end
27
24
 
28
- step 'the state of the feature is :feature_state' do |feature_state|
29
- @feature_state = feature_state
30
- end
25
+ step 'the state of the feature is :feature_state' do |feature_state|
26
+ @feature_state = feature_state
27
+ end
31
28
 
32
- step 'I persist the feature state in a cookie' do
33
- context = TestRackContext.new '', @host
34
- (described_class.new @feature_name, context).write @feature_state
35
- @cookie = context.response_cookies
36
- end
29
+ step 'I persist the feature state in a cookie' do
30
+ context = TestRackContext.new '', @host
31
+ (described_class.new @feature_name, context).write @feature_state
32
+ @cookie = context.response_cookies
33
+ end
37
34
 
38
- step 'the cookie has the path :path' do |path|
39
- expect(@cookie).to match(/path=#{path};/)
40
- end
35
+ step 'the cookie has the path :path' do |path|
36
+ expect(@cookie).to match(/path=#{path};/)
37
+ end
41
38
 
42
- step 'the cookie has the domain :domain' do |domain|
43
- if domain == ''
44
- expect(@cookie).not_to match(/domain/)
45
- else
46
- expect(@cookie).to match(/domain=#{domain};/)
39
+ step 'the cookie has the domain :domain' do |domain|
40
+ if domain == ''
41
+ expect(@cookie).not_to match(/domain/)
42
+ else
43
+ expect(@cookie).to match(/domain=#{domain};/)
44
+ end
47
45
  end
48
- end
49
46
 
50
- step 'the cookie has the name :name' do |name|
51
- expect(@cookie).to match(/\A#{name}.*/)
52
- end
47
+ step 'the cookie has the name :name' do |name|
48
+ expect(@cookie).to match(/\A#{name}.*/)
49
+ end
53
50
 
54
- step 'the cookie expires at :expiration' do |expiration|
55
- expect(@cookie).to match(/expires=#{expiration}\Z/)
56
- end
51
+ step 'the cookie expires at :expiration' do |expiration|
52
+ expect(@cookie).to match(/expires=#{expiration}\Z/)
53
+ end
57
54
 
58
- step 'the cookie value is :value' do |value|
59
- expect(@cookie).to match(/\=#{value};/)
55
+ step 'the cookie value is :value' do |value|
56
+ expect(@cookie).to match(/\=#{value};/)
57
+ end
60
58
  end
61
59
 
62
60
  describe '#read' do
63
-
64
61
  context 'when there is no existing cookie' do
65
- let(:cookies) { }
62
+ let(:cookies) {}
66
63
 
67
64
  it 'returns nil' do
68
65
  expect(subject.read).to be_nil
@@ -83,7 +80,7 @@ module FlipFab
83
80
  after { Timecop.return }
84
81
 
85
82
  it 'saves the feature state' do
86
- expect{ subject.write :enabled }.to change{ context.response_cookies }.from(nil).to('flip_fab.example_feature=enabled; domain=.simplybusiness.co.uk; path=/; expires=Tue, 01 Jan 1991 00:00:00 -0000')
83
+ expect { subject.write :enabled }.to change { context.response_cookies }.from(nil).to('flip_fab.example_feature=enabled; domain=.simplybusiness.co.uk; path=/; expires=Tue, 01 Jan 1991 00:00:00 -0000')
87
84
  end
88
85
  end
89
86
  end