rollout 2.1.0 → 2.2.1

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/spec/rollout_spec.rb CHANGED
@@ -1,6 +1,6 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require "spec_helper"
2
2
 
3
- describe "Rollout" do
3
+ RSpec.describe "Rollout" do
4
4
  before do
5
5
  @redis = Redis.new
6
6
  @rollout = Rollout.new(@redis)
@@ -13,16 +13,16 @@ describe "Rollout" do
13
13
  end
14
14
 
15
15
  it "the feature is active for users for which the block evaluates to true" do
16
- @rollout.should be_active(:chat, stub(:id => 5))
16
+ expect(@rollout).to be_active(:chat, double(id: 5))
17
17
  end
18
18
 
19
19
  it "is not active for users for which the block evaluates to false" do
20
- @rollout.should_not be_active(:chat, stub(:id => 1))
20
+ expect(@rollout).not_to be_active(:chat, double(id: 1))
21
21
  end
22
22
 
23
23
  it "is not active if a group is found in Redis but not defined in Rollout" do
24
24
  @rollout.activate_group(:chat, :fake)
25
- @rollout.should_not be_active(:chat, stub(:id => 1))
25
+ expect(@rollout).not_to be_active(:chat, double(id: 1))
26
26
  end
27
27
  end
28
28
 
@@ -32,7 +32,7 @@ describe "Rollout" do
32
32
  end
33
33
 
34
34
  it "evaluates to true no matter what" do
35
- @rollout.should be_active(:chat, stub(:id => 0))
35
+ expect(@rollout).to be_active(:chat, double(id: 0))
36
36
  end
37
37
  end
38
38
 
@@ -47,11 +47,11 @@ describe "Rollout" do
47
47
  end
48
48
 
49
49
  it "deactivates the rules for that group" do
50
- @rollout.should_not be_active(:chat, stub(:id => 10))
50
+ expect(@rollout).not_to be_active(:chat, double(id: 10))
51
51
  end
52
52
 
53
53
  it "leaves the other groups active" do
54
- @rollout.get(:chat).groups.should == [:fivesonly]
54
+ expect(@rollout.get(:chat).groups).to eq [:fivesonly].to_set
55
55
  end
56
56
  end
57
57
 
@@ -60,40 +60,40 @@ describe "Rollout" do
60
60
  @rollout.define_group(:fivesonly) { |user| user.id == 5 }
61
61
  @rollout.activate_group(:chat, :all)
62
62
  @rollout.activate_group(:chat, :fivesonly)
63
- @rollout.activate_user(:chat, stub(:id => 51))
63
+ @rollout.activate_user(:chat, double(id: 51))
64
64
  @rollout.activate_percentage(:chat, 100)
65
65
  @rollout.activate(:chat)
66
66
  @rollout.deactivate(:chat)
67
67
  end
68
68
 
69
69
  it "removes all of the groups" do
70
- @rollout.should_not be_active(:chat, stub(:id => 0))
70
+ expect(@rollout).not_to be_active(:chat, double(id: 0))
71
71
  end
72
72
 
73
73
  it "removes all of the users" do
74
- @rollout.should_not be_active(:chat, stub(:id => 51))
74
+ expect(@rollout).not_to be_active(:chat, double(id: 51))
75
75
  end
76
76
 
77
77
  it "removes the percentage" do
78
- @rollout.should_not be_active(:chat, stub(:id => 24))
78
+ expect(@rollout).not_to be_active(:chat, double(id: 24))
79
79
  end
80
80
 
81
81
  it "removes globally" do
82
- @rollout.should_not be_active(:chat)
82
+ expect(@rollout).not_to be_active(:chat)
83
83
  end
84
84
  end
85
85
 
86
86
  describe "activating a specific user" do
87
87
  before do
88
- @rollout.activate_user(:chat, stub(:id => 42))
88
+ @rollout.activate_user(:chat, double(id: 42))
89
89
  end
90
90
 
91
91
  it "is active for that user" do
92
- @rollout.should be_active(:chat, stub(:id => 42))
92
+ expect(@rollout).to be_active(:chat, double(id: 42))
93
93
  end
94
94
 
95
95
  it "remains inactive for other users" do
96
- @rollout.should_not be_active(:chat, stub(:id => 24))
96
+ expect(@rollout).not_to be_active(:chat, double(id: 24))
97
97
  end
98
98
  end
99
99
 
@@ -103,43 +103,111 @@ describe "Rollout" do
103
103
  end
104
104
 
105
105
  it "is active for that user" do
106
- @rollout.should be_active(:chat, stub(:id => 42))
106
+ expect(@rollout).to be_active(:chat, double(id: 42))
107
107
  end
108
108
 
109
109
  it "remains inactive for other users" do
110
- @rollout.should_not be_active(:chat, stub(:id => 24))
110
+ expect(@rollout).not_to be_active(:chat, double(id: 24))
111
111
  end
112
112
  end
113
113
 
114
114
  describe "activating a specific user with a string id" do
115
115
  before do
116
- @rollout.activate_user(:chat, stub(:id => 'user-72'))
116
+ @rollout.activate_user(:chat, double(id: "user-72"))
117
117
  end
118
118
 
119
119
  it "is active for that user" do
120
- @rollout.should be_active(:chat, stub(:id => 'user-72'))
120
+ expect(@rollout).to be_active(:chat, double(id: "user-72"))
121
121
  end
122
122
 
123
123
  it "remains inactive for other users" do
124
- @rollout.should_not be_active(:chat, stub(:id => 'user-12'))
124
+ expect(@rollout).not_to be_active(:chat, double(id: "user-12"))
125
+ end
126
+ end
127
+
128
+ describe "activating a group of users" do
129
+ context "specified by user objects" do
130
+ let(:users) { [double(id: 1), double(id: 2), double(id: 3)] }
131
+
132
+ before { @rollout.activate_users(:chat, users) }
133
+
134
+ it "is active for the given users" do
135
+ users.each { |user| expect(@rollout).to be_active(:chat, user) }
136
+ end
137
+
138
+ it "remains inactive for other users" do
139
+ expect(@rollout).not_to be_active(:chat, double(id: 4))
140
+ end
141
+ end
142
+
143
+ context "specified by user ids" do
144
+ let(:users) { [1, 2, 3] }
145
+
146
+ before { @rollout.activate_users(:chat, users) }
147
+
148
+ it "is active for the given users" do
149
+ users.each { |user| expect(@rollout).to be_active(:chat, user) }
150
+ end
151
+
152
+ it "remains inactive for other users" do
153
+ expect(@rollout).not_to be_active(:chat, 4)
154
+ end
125
155
  end
126
156
  end
127
157
 
128
158
  describe "deactivating a specific user" do
129
159
  before do
130
- @rollout.activate_user(:chat, stub(:id => 42))
131
- @rollout.activate_user(:chat, stub(:id => 4242))
132
- @rollout.activate_user(:chat, stub(:id => 24))
133
- @rollout.deactivate_user(:chat, stub(:id => 42))
134
- @rollout.deactivate_user(:chat, stub(:id => "4242"))
160
+ @rollout.activate_user(:chat, double(id: 42))
161
+ @rollout.activate_user(:chat, double(id: 4242))
162
+ @rollout.activate_user(:chat, double(id: 24))
163
+ @rollout.deactivate_user(:chat, double(id: 42))
164
+ @rollout.deactivate_user(:chat, double(id: "4242"))
135
165
  end
136
166
 
137
167
  it "that user should no longer be active" do
138
- @rollout.should_not be_active(:chat, stub(:id => 42))
168
+ expect(@rollout).not_to be_active(:chat, double(id: 42))
139
169
  end
140
170
 
141
171
  it "remains active for other active users" do
142
- @rollout.get(:chat).users.should == %w(24)
172
+ expect(@rollout.get(:chat).users).to eq %w(24).to_set
173
+ end
174
+ end
175
+
176
+ describe "deactivating a group of users" do
177
+ context "specified by user objects" do
178
+ let(:active_users) { [double(id: 1), double(id: 2)] }
179
+ let(:inactive_users) { [double(id: 3), double(id: 4)] }
180
+
181
+ before do
182
+ @rollout.activate_users(:chat, active_users + inactive_users)
183
+ @rollout.deactivate_users(:chat, inactive_users)
184
+ end
185
+
186
+ it "is active for the active users" do
187
+ active_users.each { |user| expect(@rollout).to be_active(:chat, user) }
188
+ end
189
+
190
+ it "is not active for inactive users" do
191
+ inactive_users.each { |user| expect(@rollout).not_to be_active(:chat, user) }
192
+ end
193
+ end
194
+
195
+ context "specified by user ids" do
196
+ let(:active_users) { [1, 2] }
197
+ let(:inactive_users) { [3, 4] }
198
+
199
+ before do
200
+ @rollout.activate_users(:chat, active_users + inactive_users)
201
+ @rollout.deactivate_users(:chat, inactive_users)
202
+ end
203
+
204
+ it "is active for the active users" do
205
+ active_users.each { |user| expect(@rollout).to be_active(:chat, user) }
206
+ end
207
+
208
+ it "is not active for inactive users" do
209
+ inactive_users.each { |user| expect(@rollout).not_to be_active(:chat, user) }
210
+ end
143
211
  end
144
212
  end
145
213
 
@@ -149,7 +217,7 @@ describe "Rollout" do
149
217
  end
150
218
 
151
219
  it "activates the feature" do
152
- @rollout.should be_active(:chat)
220
+ expect(@rollout).to be_active(:chat)
153
221
  end
154
222
  end
155
223
 
@@ -159,7 +227,7 @@ describe "Rollout" do
159
227
  end
160
228
 
161
229
  it "activates the feature for that percentage of the users" do
162
- (1..120).select { |id| @rollout.active?(:chat, stub(:id => id)) }.length.should be_within(1).of(20)
230
+ expect((1..120).select { |id| @rollout.active?(:chat, double(id: id)) }.length).to be_within(1).of(20)
163
231
  end
164
232
  end
165
233
 
@@ -169,7 +237,7 @@ describe "Rollout" do
169
237
  end
170
238
 
171
239
  it "activates the feature for that percentage of the users" do
172
- (1..200).select { |id| @rollout.active?(:chat, stub(:id => id)) }.length.should be_within(5).of(40)
240
+ expect((1..200).select { |id| @rollout.active?(:chat, double(id: id)) }.length).to be_within(5).of(40)
173
241
  end
174
242
  end
175
243
 
@@ -179,22 +247,43 @@ describe "Rollout" do
179
247
  end
180
248
 
181
249
  it "activates the feature for that percentage of the users" do
182
- (1..100).select { |id| @rollout.active?(:chat, stub(:id => id)) }.length.should be_within(2).of(5)
250
+ expect((1..100).select { |id| @rollout.active?(:chat, double(id: id)) }.length).to be_within(2).of(5)
251
+ end
252
+ end
253
+
254
+ describe "activating a feature for a percentage of users" do
255
+ before do
256
+ @rollout.activate_percentage(:chat, 20)
257
+ @rollout.activate_percentage(:beta, 20)
258
+ @options = @rollout.instance_variable_get("@options")
259
+ end
260
+
261
+ it "activates the feature for a random set of users when opt is set" do
262
+ @options[:randomize_percentage] = true
263
+ chat_users = (1..100).select { |id| @rollout.active?(:chat, double(id: id)) }
264
+ beta_users = (1..100).select { |id| @rollout.active?(:beta, double(id: id)) }
265
+ expect(chat_users).not_to eq beta_users
266
+ end
267
+ it "activates the feature for the same set of users when opt is not set" do
268
+ @options[:randomize_percentage] = false
269
+ chat_users = (1..100).select { |id| @rollout.active?(:chat, double(id: id)) }
270
+ beta_users = (1..100).select { |id| @rollout.active?(:beta, double(id: id)) }
271
+ expect(chat_users).to eq beta_users
183
272
  end
184
273
  end
185
274
 
186
275
  describe "activating a feature for a group as a string" do
187
276
  before do
188
277
  @rollout.define_group(:admins) { |user| user.id == 5 }
189
- @rollout.activate_group(:chat, 'admins')
278
+ @rollout.activate_group(:chat, "admins")
190
279
  end
191
280
 
192
281
  it "the feature is active for users for which the block evaluates to true" do
193
- @rollout.should be_active(:chat, stub(:id => 5))
282
+ expect(@rollout).to be_active(:chat, double(id: 5))
194
283
  end
195
284
 
196
285
  it "is not active for users for which the block evaluates to false" do
197
- @rollout.should_not be_active(:chat, stub(:id => 1))
286
+ expect(@rollout).not_to be_active(:chat, double(id: 1))
198
287
  end
199
288
  end
200
289
 
@@ -205,7 +294,7 @@ describe "Rollout" do
205
294
  end
206
295
 
207
296
  it "becomes inactivate for all users" do
208
- @rollout.should_not be_active(:chat, stub(:id => 24))
297
+ expect(@rollout).not_to be_active(:chat, double(id: 24))
209
298
  end
210
299
  end
211
300
 
@@ -216,7 +305,7 @@ describe "Rollout" do
216
305
  end
217
306
 
218
307
  it "becomes inactivate" do
219
- @rollout.should_not be_active(:chat)
308
+ expect(@rollout).not_to be_active(:chat)
220
309
  end
221
310
  end
222
311
 
@@ -226,7 +315,7 @@ describe "Rollout" do
226
315
  end
227
316
 
228
317
  it "becomes activated" do
229
- @rollout.should be_active(:chat)
318
+ expect(@rollout).to be_active(:chat)
230
319
  end
231
320
  end
232
321
 
@@ -235,27 +324,45 @@ describe "Rollout" do
235
324
  @rollout.set(:chat, false)
236
325
  end
237
326
 
238
- it "becomes activated" do
239
- @rollout.should_not be_active(:chat)
327
+ it "becomes inactivated" do
328
+ expect(@rollout).not_to be_active(:chat)
329
+ end
330
+ end
331
+
332
+ describe "deleting a feature" do
333
+ before do
334
+ @rollout.set(:chat, true)
335
+ end
336
+
337
+ it "should be removed from features list" do
338
+ expect(@rollout.features.size).to eq 1
339
+ @rollout.delete(:chat)
340
+ expect(@rollout.features.size).to eq 0
341
+ end
342
+
343
+ it "should have metadata cleared" do
344
+ expect(@rollout.get(:chat).percentage).to eq 100
345
+ @rollout.delete(:chat)
346
+ expect(@rollout.get(:chat).percentage).to eq 0
240
347
  end
241
348
  end
242
349
 
243
350
  describe "keeps a list of features" do
244
351
  it "saves the feature" do
245
352
  @rollout.activate(:chat)
246
- @rollout.features.should be_include(:chat)
353
+ expect(@rollout.features).to be_include(:chat)
247
354
  end
248
355
 
249
356
  it "does not contain doubles" do
250
357
  @rollout.activate(:chat)
251
358
  @rollout.activate(:chat)
252
- @rollout.features.size.should == 1
359
+ expect(@rollout.features.size).to eq(1)
253
360
  end
254
361
 
255
362
  it "does not contain doubles when using string" do
256
363
  @rollout.activate(:chat)
257
364
  @rollout.activate("chat")
258
- @rollout.features.size.should == 1
365
+ expect(@rollout.features.size).to eq(1)
259
366
  end
260
367
  end
261
368
 
@@ -265,24 +372,24 @@ describe "Rollout" do
265
372
  @rollout.activate_group(:chat, :caretakers)
266
373
  @rollout.activate_group(:chat, :greeters)
267
374
  @rollout.activate(:signup)
268
- @rollout.activate_user(:chat, stub(:id => 42))
375
+ @rollout.activate_user(:chat, double(id: 42))
269
376
  end
270
377
 
271
378
  it "returns the feature object" do
272
379
  feature = @rollout.get(:chat)
273
- feature.groups.should == [:caretakers, :greeters]
274
- feature.percentage.should == 10
275
- feature.users.should == %w(42)
276
- feature.to_hash.should == {
277
- :groups => [:caretakers, :greeters],
278
- :percentage => 10,
279
- :users => %w(42)
280
- }
380
+ expect(feature.groups).to eq [:caretakers, :greeters].to_set
381
+ expect(feature.percentage).to eq 10
382
+ expect(feature.users).to eq %w(42).to_set
383
+ expect(feature.to_hash).to eq(
384
+ groups: [:caretakers, :greeters].to_set,
385
+ percentage: 10,
386
+ users: %w(42).to_set
387
+ )
281
388
 
282
389
  feature = @rollout.get(:signup)
283
- feature.groups.should be_empty
284
- feature.users.should be_empty
285
- feature.percentage.should == 100
390
+ expect(feature.groups).to be_empty
391
+ expect(feature.users).to be_empty
392
+ expect(feature.percentage).to eq(100)
286
393
  end
287
394
  end
288
395
 
@@ -297,16 +404,16 @@ describe "Rollout" do
297
404
 
298
405
  it "each feature is cleared" do
299
406
  features.each do |feature|
300
- @rollout.get(feature).to_hash.should == {
301
- :percentage => 0,
302
- :users => [],
303
- :groups => []
304
- }
407
+ expect(@rollout.get(feature).to_hash).to eq(
408
+ percentage: 0,
409
+ users: Set.new,
410
+ groups: Set.new
411
+ )
305
412
  end
306
413
  end
307
414
 
308
415
  it "removes all features" do
309
- @rollout.features.should be_empty
416
+ expect(@rollout.features).to be_empty
310
417
  end
311
418
  end
312
419
 
@@ -314,44 +421,121 @@ describe "Rollout" do
314
421
  before do
315
422
  @legacy = Rollout::Legacy.new(@redis)
316
423
  @legacy.activate_percentage(:chat, 12)
317
- @legacy.activate_user(:chat, stub(:id => 42))
318
- @legacy.activate_user(:chat, stub(:id => 24))
424
+ @legacy.activate_user(:chat, double(id: 42))
425
+ @legacy.activate_user(:chat, double(id: 24))
319
426
  @legacy.activate_group(:chat, :dope_people)
320
- @rollout = Rollout.new(@redis, :migrate => true)
427
+ @rollout = Rollout.new(@redis, migrate: true)
321
428
  end
322
429
 
323
430
  it "imports the settings from the legacy rollout once" do
324
- @rollout.get(:chat).to_hash.should == {
325
- :percentage => 12,
326
- :users => %w(24 42),
327
- :groups => [:dope_people]
328
- }
431
+ expect(@rollout.get(:chat).to_hash).to eq({
432
+ percentage: 12,
433
+ users: %w(24 42),
434
+ groups: [:dope_people]
435
+ })
329
436
  @legacy.deactivate_all(:chat)
330
- @rollout.get(:chat).to_hash.should == {
331
- :percentage => 12,
332
- :users => %w(24 42),
333
- :groups => [:dope_people]
334
- }
335
- @redis.get("feature:chat").should_not be_nil
437
+ expect(@rollout.get(:chat).to_hash).to eq({
438
+ percentage: 12,
439
+ users: %w(24 42).to_set,
440
+ groups: [:dope_people].to_set
441
+ })
442
+ expect(@redis.get("feature:chat")).not_to be_nil
336
443
  end
337
444
 
338
445
  it "imports settings that were globally activated" do
339
446
  @legacy.activate_globally(:video_chat)
340
- @rollout.get(:video_chat).to_hash[:percentage].should == 100
447
+ expect(@rollout.get(:video_chat).to_hash[:percentage]).to eq(100)
448
+ end
449
+ end
450
+
451
+ describe "#feature_states" do
452
+ let(:user_double) { double(id: 7) }
453
+
454
+ before do
455
+ @rollout.activate(:chat)
456
+ @rollout.activate_user(:video, user_double)
457
+ @rollout.deactivate(:vr)
458
+ end
459
+
460
+ it "returns a hash" do
461
+ expect(@rollout.feature_states).to be_a(Hash)
462
+ end
463
+
464
+ context "with user argument" do
465
+ it "maps active feature as true" do
466
+ state = @rollout.feature_states(user_double)[:video]
467
+ expect(state).to eq(true)
468
+ end
469
+
470
+ it "maps inactive feature as false" do
471
+ state = @rollout.feature_states[:vr]
472
+ expect(state).to eq(false)
473
+ end
474
+ end
475
+
476
+ context "with no argument" do
477
+ it "maps active feature as true" do
478
+ state = @rollout.feature_states[:chat]
479
+ expect(state).to eq(true)
480
+ end
481
+
482
+ it "maps inactive feature as false" do
483
+ state = @rollout.feature_states[:video]
484
+ expect(state).to eq(false)
485
+ end
486
+ end
487
+ end
488
+
489
+ describe "#active_features" do
490
+ let(:user_double) { double(id: 19) }
491
+
492
+ before do
493
+ @rollout.activate(:chat)
494
+ @rollout.activate_user(:video, user_double)
495
+ @rollout.deactivate(:vr)
496
+ end
497
+
498
+ it "returns an array" do
499
+ expect(@rollout.active_features).to be_a(Array)
500
+ end
501
+
502
+ context "with user argument" do
503
+ it "includes active feature" do
504
+ features = @rollout.active_features(user_double)
505
+ expect(features).to include(:video)
506
+ expect(features).to include(:chat)
507
+ end
508
+
509
+ it "excludes inactive feature" do
510
+ features = @rollout.active_features(user_double)
511
+ expect(features).to_not include(:vr)
512
+ end
513
+ end
514
+
515
+ context "with no argument" do
516
+ it "includes active feature" do
517
+ features = @rollout.active_features
518
+ expect(features).to include(:chat)
519
+ end
520
+
521
+ it "excludes inactive feature" do
522
+ features = @rollout.active_features
523
+ expect(features).to_not include(:video)
524
+ end
341
525
  end
342
526
  end
343
527
  end
344
528
 
345
529
  describe "Rollout::Feature" do
346
530
  before do
347
- @user = stub("User", :email => "test@test.com")
348
- @feature = Rollout::Feature.new(:chat, nil, :id_user_by => :email)
531
+ @user = double("User", email: "test@test.com")
532
+ @feature = Rollout::Feature.new(:chat, nil, id_user_by: :email)
349
533
  end
350
534
 
351
535
  describe "#add_user" do
352
536
  it "ids a user using id_user_by" do
353
537
  @feature.add_user(@user)
354
- @user.should have_received :email
538
+ expect(@user).to have_received :email
355
539
  end
356
540
  end
357
541
  end
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,17 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- require 'rollout'
4
- require 'rspec'
5
- require 'bourne'
6
- require 'redis'
3
+ require "rollout"
4
+ require "rspec"
5
+ require "redis"
6
+ require "codeclimate-test-reporter"
7
+
8
+ SimpleCov.start do
9
+ formatter SimpleCov::Formatter::MultiFormatter.new([
10
+ SimpleCov::Formatter::HTMLFormatter,
11
+ CodeClimate::TestReporter::Formatter,
12
+ ])
13
+ end
7
14
 
8
15
  RSpec.configure do |config|
9
- config.mock_with :mocha
10
16
  config.before { Redis.new.flushdb }
11
17
  end