rollout 2.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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +95 -0
- data/.gitignore +24 -0
- data/.rspec +1 -0
- data/.rubocop.yml +11 -0
- data/.travis.yml +20 -0
- data/Gemfile +5 -0
- data/LICENSE +20 -0
- data/README.md +201 -0
- data/Rakefile +7 -0
- data/lib/rollout.rb +227 -0
- data/lib/rollout/feature.rb +131 -0
- data/lib/rollout/logging.rb +198 -0
- data/lib/rollout/version.rb +5 -0
- data/rollout.gemspec +31 -0
- data/spec/rollout/logging_spec.rb +143 -0
- data/spec/rollout_spec.rb +730 -0
- data/spec/spec_helper.rb +27 -0
- metadata +158 -0
@@ -0,0 +1,730 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "Rollout" do
|
4
|
+
before do
|
5
|
+
@rollout = Rollout.new(Redis.current)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "when a group is activated" do
|
9
|
+
before do
|
10
|
+
@rollout.define_group(:fivesonly) { |user| user.id == 5 }
|
11
|
+
@rollout.activate_group(:chat, :fivesonly)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "the feature is active for users for which the block evaluates to true" do
|
15
|
+
expect(@rollout).to be_active(:chat, double(id: 5))
|
16
|
+
end
|
17
|
+
|
18
|
+
it "is not active for users for which the block evaluates to false" do
|
19
|
+
expect(@rollout).not_to be_active(:chat, double(id: 1))
|
20
|
+
end
|
21
|
+
|
22
|
+
it "is not active if a group is found in Redis but not defined in Rollout" do
|
23
|
+
@rollout.activate_group(:chat, :fake)
|
24
|
+
expect(@rollout).not_to be_active(:chat, double(id: 1))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "the default all group" do
|
29
|
+
before do
|
30
|
+
@rollout.activate_group(:chat, :all)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "evaluates to true no matter what" do
|
34
|
+
expect(@rollout).to be_active(:chat, double(id: 0))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "deactivating a group" do
|
39
|
+
before do
|
40
|
+
@rollout.define_group(:fivesonly) { |user| user.id == 5 }
|
41
|
+
@rollout.activate_group(:chat, :all)
|
42
|
+
@rollout.activate_group(:chat, :some)
|
43
|
+
@rollout.activate_group(:chat, :fivesonly)
|
44
|
+
@rollout.deactivate_group(:chat, :all)
|
45
|
+
@rollout.deactivate_group(:chat, "some")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "deactivates the rules for that group" do
|
49
|
+
expect(@rollout).not_to be_active(:chat, double(id: 10))
|
50
|
+
end
|
51
|
+
|
52
|
+
it "leaves the other groups active" do
|
53
|
+
expect(@rollout.get(:chat).groups).to eq [:fivesonly]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "leaves the other groups active using sets" do
|
57
|
+
@options = @rollout.instance_variable_get("@options")
|
58
|
+
@options[:use_sets] = true
|
59
|
+
expect(@rollout.get(:chat).groups).to eq [:fivesonly].to_set
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "deactivating a feature completely" do
|
64
|
+
before do
|
65
|
+
@rollout.define_group(:fivesonly) { |user| user.id == 5 }
|
66
|
+
@rollout.activate_group(:chat, :all)
|
67
|
+
@rollout.activate_group(:chat, :fivesonly)
|
68
|
+
@rollout.activate_user(:chat, double(id: 51))
|
69
|
+
@rollout.activate_percentage(:chat, 100)
|
70
|
+
@rollout.activate(:chat)
|
71
|
+
@rollout.deactivate(:chat)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "removes all of the groups" do
|
75
|
+
expect(@rollout).not_to be_active(:chat, double(id: 0))
|
76
|
+
end
|
77
|
+
|
78
|
+
it "removes all of the users" do
|
79
|
+
expect(@rollout).not_to be_active(:chat, double(id: 51))
|
80
|
+
end
|
81
|
+
|
82
|
+
it "removes the percentage" do
|
83
|
+
expect(@rollout).not_to be_active(:chat, double(id: 24))
|
84
|
+
end
|
85
|
+
|
86
|
+
it "removes globally" do
|
87
|
+
expect(@rollout).not_to be_active(:chat)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "activating a specific user" do
|
92
|
+
before do
|
93
|
+
@rollout.activate_user(:chat, double(id: 42))
|
94
|
+
end
|
95
|
+
|
96
|
+
it "is active for that user" do
|
97
|
+
expect(@rollout).to be_active(:chat, double(id: 42))
|
98
|
+
end
|
99
|
+
|
100
|
+
it "remains inactive for other users" do
|
101
|
+
expect(@rollout).not_to be_active(:chat, double(id: 24))
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "activating a specific user by ID" do
|
106
|
+
before do
|
107
|
+
@rollout.activate_user(:chat, 42)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "is active for that user" do
|
111
|
+
expect(@rollout).to be_active(:chat, double(id: 42))
|
112
|
+
end
|
113
|
+
|
114
|
+
it "remains inactive for other users" do
|
115
|
+
expect(@rollout).not_to be_active(:chat, double(id: 24))
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "activating a specific user with a string id" do
|
120
|
+
before do
|
121
|
+
@rollout.activate_user(:chat, double(id: "user-72"))
|
122
|
+
end
|
123
|
+
|
124
|
+
it "is active for that user" do
|
125
|
+
expect(@rollout).to be_active(:chat, double(id: "user-72"))
|
126
|
+
end
|
127
|
+
|
128
|
+
it "remains inactive for other users" do
|
129
|
+
expect(@rollout).not_to be_active(:chat, double(id: "user-12"))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "activating a group of users" do
|
134
|
+
context "specified by user objects" do
|
135
|
+
let(:users) { [double(id: 1), double(id: 2), double(id: 3)] }
|
136
|
+
|
137
|
+
before { @rollout.activate_users(:chat, users) }
|
138
|
+
|
139
|
+
it "is active for the given users" do
|
140
|
+
users.each { |user| expect(@rollout).to be_active(:chat, user) }
|
141
|
+
end
|
142
|
+
|
143
|
+
it "remains inactive for other users" do
|
144
|
+
expect(@rollout).not_to be_active(:chat, double(id: 4))
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "specified by user ids" do
|
149
|
+
let(:users) { [1, 2, 3] }
|
150
|
+
|
151
|
+
before { @rollout.activate_users(:chat, users) }
|
152
|
+
|
153
|
+
it "is active for the given users" do
|
154
|
+
users.each { |user| expect(@rollout).to be_active(:chat, user) }
|
155
|
+
end
|
156
|
+
|
157
|
+
it "remains inactive for other users" do
|
158
|
+
expect(@rollout).not_to be_active(:chat, 4)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "deactivating a specific user" do
|
164
|
+
before do
|
165
|
+
@rollout.activate_user(:chat, double(id: 42))
|
166
|
+
@rollout.activate_user(:chat, double(id: 4242))
|
167
|
+
@rollout.activate_user(:chat, double(id: 24))
|
168
|
+
@rollout.deactivate_user(:chat, double(id: 42))
|
169
|
+
@rollout.deactivate_user(:chat, double(id: "4242"))
|
170
|
+
end
|
171
|
+
|
172
|
+
it "that user should no longer be active" do
|
173
|
+
expect(@rollout).not_to be_active(:chat, double(id: 42))
|
174
|
+
end
|
175
|
+
|
176
|
+
it "remains active for other active users" do
|
177
|
+
@options = @rollout.instance_variable_get("@options")
|
178
|
+
@options[:use_sets] = false
|
179
|
+
expect(@rollout.get(:chat).users).to eq %w(24)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "remains active for other active users using sets" do
|
183
|
+
@options = @rollout.instance_variable_get("@options")
|
184
|
+
@options[:use_sets] = true
|
185
|
+
|
186
|
+
expect(@rollout.get(:chat).users).to eq %w(24).to_set
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "deactivating a group of users" do
|
191
|
+
context "specified by user objects" do
|
192
|
+
let(:active_users) { [double(id: 1), double(id: 2)] }
|
193
|
+
let(:inactive_users) { [double(id: 3), double(id: 4)] }
|
194
|
+
|
195
|
+
before do
|
196
|
+
@rollout.activate_users(:chat, active_users + inactive_users)
|
197
|
+
@rollout.deactivate_users(:chat, inactive_users)
|
198
|
+
end
|
199
|
+
|
200
|
+
it "is active for the active users" do
|
201
|
+
active_users.each { |user| expect(@rollout).to be_active(:chat, user) }
|
202
|
+
end
|
203
|
+
|
204
|
+
it "is not active for inactive users" do
|
205
|
+
inactive_users.each { |user| expect(@rollout).not_to be_active(:chat, user) }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context "specified by user ids" do
|
210
|
+
let(:active_users) { [1, 2] }
|
211
|
+
let(:inactive_users) { [3, 4] }
|
212
|
+
|
213
|
+
before do
|
214
|
+
@rollout.activate_users(:chat, active_users + inactive_users)
|
215
|
+
@rollout.deactivate_users(:chat, inactive_users)
|
216
|
+
end
|
217
|
+
|
218
|
+
it "is active for the active users" do
|
219
|
+
active_users.each { |user| expect(@rollout).to be_active(:chat, user) }
|
220
|
+
end
|
221
|
+
|
222
|
+
it "is not active for inactive users" do
|
223
|
+
inactive_users.each { |user| expect(@rollout).not_to be_active(:chat, user) }
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
describe 'set a group of users' do
|
230
|
+
it 'should replace the users with the given array' do
|
231
|
+
users = %w(1 2 3 4)
|
232
|
+
@rollout.activate_users(:chat, %w(10 20 30))
|
233
|
+
@rollout.set_users(:chat, users)
|
234
|
+
expect(@rollout.get(:chat).users).to eq(users)
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "activating a feature globally" do
|
239
|
+
before do
|
240
|
+
@rollout.activate(:chat)
|
241
|
+
end
|
242
|
+
|
243
|
+
it "activates the feature" do
|
244
|
+
expect(@rollout).to be_active(:chat)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "sets @data to empty hash" do
|
248
|
+
expect(@rollout.get(:chat).data).to eq({})
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe "activating a feature for a percentage of users" do
|
253
|
+
before do
|
254
|
+
@rollout.activate_percentage(:chat, 20)
|
255
|
+
end
|
256
|
+
|
257
|
+
it "activates the feature for that percentage of the users" do
|
258
|
+
expect((1..100).select { |id| @rollout.active?(:chat, double(id: id)) }.length).to be_within(2).of(20)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe "activating a feature for a percentage of users" do
|
263
|
+
before do
|
264
|
+
@rollout.activate_percentage(:chat, 20)
|
265
|
+
end
|
266
|
+
|
267
|
+
it "activates the feature for that percentage of the users" do
|
268
|
+
expect((1..200).select { |id| @rollout.active?(:chat, double(id: id)) }.length).to be_within(4).of(40)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe "activating a feature for a percentage of users" do
|
273
|
+
before do
|
274
|
+
@rollout.activate_percentage(:chat, 5)
|
275
|
+
end
|
276
|
+
|
277
|
+
it "activates the feature for that percentage of the users" do
|
278
|
+
expect((1..100).select { |id| @rollout.active?(:chat, double(id: id)) }.length).to be_within(2).of(5)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "activating a feature for a percentage of users" do
|
283
|
+
before do
|
284
|
+
@rollout.activate_percentage(:chat, 0.1)
|
285
|
+
end
|
286
|
+
|
287
|
+
it "activates the feature for that percentage of the users" do
|
288
|
+
expect((1..10_000).to_set.select { |id| @rollout.active?(:chat, double(id: id)) }.length).to be_within(2).of(10)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
describe "activating a feature for a percentage of users" do
|
293
|
+
before do
|
294
|
+
@rollout.activate_percentage(:chat, 20)
|
295
|
+
@rollout.activate_percentage(:beta, 20)
|
296
|
+
@options = @rollout.instance_variable_get("@options")
|
297
|
+
end
|
298
|
+
|
299
|
+
it "activates the feature for a random set of users when opt is set" do
|
300
|
+
@options[:randomize_percentage] = true
|
301
|
+
chat_users = (1..100).select { |id| @rollout.active?(:chat, double(id: id)) }
|
302
|
+
beta_users = (1..100).select { |id| @rollout.active?(:beta, double(id: id)) }
|
303
|
+
expect(chat_users).not_to eq beta_users
|
304
|
+
end
|
305
|
+
it "activates the feature for the same set of users when opt is not set" do
|
306
|
+
@options[:randomize_percentage] = false
|
307
|
+
chat_users = (1..100).select { |id| @rollout.active?(:chat, double(id: id)) }
|
308
|
+
beta_users = (1..100).select { |id| @rollout.active?(:beta, double(id: id)) }
|
309
|
+
expect(chat_users).to eq beta_users
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "activating a feature for a group as a string" do
|
314
|
+
before do
|
315
|
+
@rollout.define_group(:admins) { |user| user.id == 5 }
|
316
|
+
@rollout.activate_group(:chat, "admins")
|
317
|
+
end
|
318
|
+
|
319
|
+
it "the feature is active for users for which the block evaluates to true" do
|
320
|
+
expect(@rollout).to be_active(:chat, double(id: 5))
|
321
|
+
end
|
322
|
+
|
323
|
+
it "is not active for users for which the block evaluates to false" do
|
324
|
+
expect(@rollout).not_to be_active(:chat, double(id: 1))
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
describe "deactivating the percentage of users" do
|
329
|
+
before do
|
330
|
+
@rollout.activate_percentage(:chat, 100)
|
331
|
+
@rollout.deactivate_percentage(:chat)
|
332
|
+
end
|
333
|
+
|
334
|
+
it "becomes inactivate for all users" do
|
335
|
+
expect(@rollout).not_to be_active(:chat, double(id: 24))
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
describe "deactivating the feature globally" do
|
340
|
+
before do
|
341
|
+
@rollout.activate(:chat)
|
342
|
+
@rollout.deactivate(:chat)
|
343
|
+
end
|
344
|
+
|
345
|
+
it "becomes inactivate" do
|
346
|
+
expect(@rollout).not_to be_active(:chat)
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
describe "setting a feature on" do
|
351
|
+
before do
|
352
|
+
@rollout.set(:chat, true)
|
353
|
+
end
|
354
|
+
|
355
|
+
it "becomes activated" do
|
356
|
+
expect(@rollout).to be_active(:chat)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
describe "setting a feature off" do
|
361
|
+
before do
|
362
|
+
@rollout.set(:chat, false)
|
363
|
+
end
|
364
|
+
|
365
|
+
it "becomes inactivated" do
|
366
|
+
expect(@rollout).not_to be_active(:chat)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
describe "deleting a feature" do
|
371
|
+
before do
|
372
|
+
@rollout.set(:chat, true)
|
373
|
+
end
|
374
|
+
|
375
|
+
context "when feature was passed as string" do
|
376
|
+
it "should be removed from features list" do
|
377
|
+
expect(@rollout.features.size).to eq 1
|
378
|
+
@rollout.delete('chat')
|
379
|
+
expect(@rollout.features.size).to eq 0
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
it "should be removed from features list" do
|
384
|
+
expect(@rollout.features.size).to eq 1
|
385
|
+
@rollout.delete(:chat)
|
386
|
+
expect(@rollout.features.size).to eq 0
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should have metadata cleared" do
|
390
|
+
expect(@rollout.get(:chat).percentage).to eq 100
|
391
|
+
@rollout.delete(:chat)
|
392
|
+
expect(@rollout.get(:chat).percentage).to eq 0
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
describe "keeps a list of features" do
|
397
|
+
it "saves the feature" do
|
398
|
+
@rollout.activate(:chat)
|
399
|
+
expect(@rollout.features).to be_include(:chat)
|
400
|
+
end
|
401
|
+
|
402
|
+
it "does not contain doubles" do
|
403
|
+
@rollout.activate(:chat)
|
404
|
+
@rollout.activate(:chat)
|
405
|
+
expect(@rollout.features.size).to eq(1)
|
406
|
+
end
|
407
|
+
|
408
|
+
it "does not contain doubles when using string" do
|
409
|
+
@rollout.activate(:chat)
|
410
|
+
@rollout.activate("chat")
|
411
|
+
expect(@rollout.features.size).to eq(1)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe "#get" do
|
416
|
+
before do
|
417
|
+
@rollout.activate_percentage(:chat, 10)
|
418
|
+
@rollout.activate_group(:chat, :caretakers)
|
419
|
+
@rollout.activate_group(:chat, :greeters)
|
420
|
+
@rollout.activate(:signup)
|
421
|
+
@rollout.activate_user(:chat, double(id: 42))
|
422
|
+
end
|
423
|
+
|
424
|
+
it "returns the feature object" do
|
425
|
+
feature = @rollout.get(:chat)
|
426
|
+
expect(feature.groups).to eq [:caretakers, :greeters]
|
427
|
+
expect(feature.percentage).to eq 10
|
428
|
+
expect(feature.users).to eq %w(42)
|
429
|
+
expect(feature.to_hash).to eq(
|
430
|
+
groups: [:caretakers, :greeters],
|
431
|
+
percentage: 10,
|
432
|
+
users: %w(42),
|
433
|
+
data: {},
|
434
|
+
)
|
435
|
+
|
436
|
+
feature = @rollout.get(:signup)
|
437
|
+
expect(feature.groups).to be_empty
|
438
|
+
expect(feature.users).to be_empty
|
439
|
+
expect(feature.percentage).to eq(100)
|
440
|
+
end
|
441
|
+
|
442
|
+
it "returns the feature objects using sets" do
|
443
|
+
@options = @rollout.instance_variable_get("@options")
|
444
|
+
@options[:use_sets] = true
|
445
|
+
|
446
|
+
feature = @rollout.get(:chat)
|
447
|
+
expect(feature.groups).to eq [:caretakers, :greeters].to_set
|
448
|
+
expect(feature.percentage).to eq 10
|
449
|
+
expect(feature.users).to eq %w(42).to_set
|
450
|
+
expect(feature.to_hash).to eq(
|
451
|
+
groups: [:caretakers, :greeters].to_set,
|
452
|
+
percentage: 10,
|
453
|
+
users: %w(42).to_set,
|
454
|
+
data: {},
|
455
|
+
)
|
456
|
+
|
457
|
+
feature = @rollout.get(:signup)
|
458
|
+
expect(feature.groups).to be_empty
|
459
|
+
expect(feature.users).to be_empty
|
460
|
+
expect(feature.percentage).to eq(100)
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
describe "#clear" do
|
465
|
+
let(:features) { %w(signup beta alpha gm) }
|
466
|
+
|
467
|
+
before do
|
468
|
+
features.each { |f| @rollout.activate(f) }
|
469
|
+
|
470
|
+
@rollout.clear!
|
471
|
+
end
|
472
|
+
|
473
|
+
it "each feature is cleared" do
|
474
|
+
features.each do |feature|
|
475
|
+
expect(@rollout.get(feature).to_hash).to eq(
|
476
|
+
percentage: 0,
|
477
|
+
users: [],
|
478
|
+
groups: [],
|
479
|
+
data: {},
|
480
|
+
)
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
it "each feature is cleared with sets" do
|
485
|
+
@options = @rollout.instance_variable_get("@options")
|
486
|
+
@options[:use_sets] = true
|
487
|
+
features.each do |feature|
|
488
|
+
expect(@rollout.get(feature).to_hash).to eq(
|
489
|
+
percentage: 0,
|
490
|
+
users: Set.new,
|
491
|
+
groups: Set.new,
|
492
|
+
data: {},
|
493
|
+
)
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
it "removes all features" do
|
498
|
+
expect(@rollout.features).to be_empty
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
describe "#feature_states" do
|
503
|
+
let(:user_double) { double(id: 7) }
|
504
|
+
|
505
|
+
before do
|
506
|
+
@rollout.activate(:chat)
|
507
|
+
@rollout.activate_user(:video, user_double)
|
508
|
+
@rollout.deactivate(:vr)
|
509
|
+
end
|
510
|
+
|
511
|
+
it "returns a hash" do
|
512
|
+
expect(@rollout.feature_states).to be_a(Hash)
|
513
|
+
end
|
514
|
+
|
515
|
+
context "with user argument" do
|
516
|
+
it "maps active feature as true" do
|
517
|
+
state = @rollout.feature_states(user_double)[:video]
|
518
|
+
expect(state).to eq(true)
|
519
|
+
end
|
520
|
+
|
521
|
+
it "maps inactive feature as false" do
|
522
|
+
state = @rollout.feature_states[:vr]
|
523
|
+
expect(state).to eq(false)
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
context "with no argument" do
|
528
|
+
it "maps active feature as true" do
|
529
|
+
state = @rollout.feature_states[:chat]
|
530
|
+
expect(state).to eq(true)
|
531
|
+
end
|
532
|
+
|
533
|
+
it "maps inactive feature as false" do
|
534
|
+
state = @rollout.feature_states[:video]
|
535
|
+
expect(state).to eq(false)
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
describe "#active_features" do
|
541
|
+
let(:user_double) { double(id: 19) }
|
542
|
+
|
543
|
+
before do
|
544
|
+
@rollout.activate(:chat)
|
545
|
+
@rollout.activate_user(:video, user_double)
|
546
|
+
@rollout.deactivate(:vr)
|
547
|
+
end
|
548
|
+
|
549
|
+
it "returns an array" do
|
550
|
+
expect(@rollout.active_features).to be_a(Array)
|
551
|
+
end
|
552
|
+
|
553
|
+
context "with user argument" do
|
554
|
+
it "includes active feature" do
|
555
|
+
features = @rollout.active_features(user_double)
|
556
|
+
expect(features).to include(:video)
|
557
|
+
expect(features).to include(:chat)
|
558
|
+
end
|
559
|
+
|
560
|
+
it "excludes inactive feature" do
|
561
|
+
features = @rollout.active_features(user_double)
|
562
|
+
expect(features).to_not include(:vr)
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
context "with no argument" do
|
567
|
+
it "includes active feature" do
|
568
|
+
features = @rollout.active_features
|
569
|
+
expect(features).to include(:chat)
|
570
|
+
end
|
571
|
+
|
572
|
+
it "excludes inactive feature" do
|
573
|
+
features = @rollout.active_features
|
574
|
+
expect(features).to_not include(:video)
|
575
|
+
end
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
describe "#user_in_active_users?" do
|
580
|
+
it "returns true if activated for user" do
|
581
|
+
@rollout.activate_user(:chat, double(id: 5))
|
582
|
+
expect(@rollout.user_in_active_users?(:chat, "5")).to eq(true)
|
583
|
+
end
|
584
|
+
|
585
|
+
it "returns false if activated for group" do
|
586
|
+
@rollout.activate_group(:chat, :all)
|
587
|
+
expect(@rollout.user_in_active_users?(:chat, "5")).to eq(false)
|
588
|
+
end
|
589
|
+
end
|
590
|
+
|
591
|
+
describe "#multi_get" do
|
592
|
+
before do
|
593
|
+
@rollout.activate_percentage(:chat, 10)
|
594
|
+
@rollout.activate_group(:chat, :caretakers)
|
595
|
+
@rollout.activate_group(:videos, :greeters)
|
596
|
+
@rollout.activate(:signup)
|
597
|
+
@rollout.activate_user(:photos, double(id: 42))
|
598
|
+
end
|
599
|
+
|
600
|
+
it "returns an array of features" do
|
601
|
+
features = @rollout.multi_get(:chat, :videos, :signup)
|
602
|
+
expect(features[0].name).to eq :chat
|
603
|
+
expect(features[0].groups).to eq [:caretakers]
|
604
|
+
expect(features[0].percentage).to eq 10
|
605
|
+
expect(features[1].name).to eq :videos
|
606
|
+
expect(features[1].groups).to eq [:greeters]
|
607
|
+
expect(features[2].name).to eq :signup
|
608
|
+
expect(features[2].percentage).to eq 100
|
609
|
+
expect(features.size).to eq 3
|
610
|
+
end
|
611
|
+
|
612
|
+
describe 'when given feature keys is empty' do
|
613
|
+
it 'returns empty array' do
|
614
|
+
expect(@rollout.multi_get(*[])).to match_array([])
|
615
|
+
end
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
describe "#set_feature_data" do
|
620
|
+
before do
|
621
|
+
@rollout.set_feature_data(:chat, description: 'foo', release_date: 'bar')
|
622
|
+
end
|
623
|
+
|
624
|
+
it 'sets the data attribute on feature' do
|
625
|
+
expect(@rollout.get(:chat).data).to include('description' => 'foo', 'release_date' => 'bar')
|
626
|
+
end
|
627
|
+
|
628
|
+
it 'updates a data attribute' do
|
629
|
+
@rollout.set_feature_data(:chat, description: 'baz')
|
630
|
+
expect(@rollout.get(:chat).data).to include('description' => 'baz', 'release_date' => 'bar')
|
631
|
+
end
|
632
|
+
|
633
|
+
it 'only sets data on specified feature' do
|
634
|
+
@rollout.set_feature_data(:talk, image_url: 'kittens.png')
|
635
|
+
expect(@rollout.get(:chat).data).not_to include('image_url' => 'kittens.png')
|
636
|
+
expect(@rollout.get(:chat).data).to include('description' => 'foo', 'release_date' => 'bar')
|
637
|
+
end
|
638
|
+
|
639
|
+
it 'does not modify @data if param is nil' do
|
640
|
+
expect(@rollout.get(:chat).data).to include('description' => 'foo', 'release_date' => 'bar')
|
641
|
+
@rollout.set_feature_data(:chat, nil)
|
642
|
+
expect(@rollout.get(:chat).data).to include('description' => 'foo', 'release_date' => 'bar')
|
643
|
+
end
|
644
|
+
|
645
|
+
it 'does not modify @data if param is empty string' do
|
646
|
+
expect(@rollout.get(:chat).data).to include('description' => 'foo', 'release_date' => 'bar')
|
647
|
+
@rollout.set_feature_data(:chat, " ")
|
648
|
+
expect(@rollout.get(:chat).data).to include('description' => 'foo', 'release_date' => 'bar')
|
649
|
+
end
|
650
|
+
|
651
|
+
it 'properly parses data when it contains a |' do
|
652
|
+
user = double("User", id: 8)
|
653
|
+
@rollout.activate_user(:chat, user)
|
654
|
+
@rollout.set_feature_data(:chat, "|call||text|" => "a|bunch|of|stuff")
|
655
|
+
expect(@rollout.get(:chat).data).to include("|call||text|" => "a|bunch|of|stuff")
|
656
|
+
expect(@rollout.active?(:chat, user)).to be true
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
660
|
+
describe "#clear_feature_data" do
|
661
|
+
it 'resets data to empty string' do
|
662
|
+
@rollout.set_feature_data(:chat, description: 'foo')
|
663
|
+
expect(@rollout.get(:chat).data).to include('description' => 'foo')
|
664
|
+
@rollout.clear_feature_data(:chat)
|
665
|
+
expect(@rollout.get(:chat).data).to eq({})
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
669
|
+
describe 'Check if feature exists' do
|
670
|
+
it 'it should return true if the feature is exist' do
|
671
|
+
@rollout.activate_percentage(:chat, 1)
|
672
|
+
expect(@rollout.exists?(:chat)).to be true
|
673
|
+
end
|
674
|
+
|
675
|
+
it 'it should return false if the feature is not exist' do
|
676
|
+
expect(@rollout.exists?(:chat)).to be false
|
677
|
+
end
|
678
|
+
end
|
679
|
+
end
|
680
|
+
|
681
|
+
describe "Rollout::Feature" do
|
682
|
+
describe "#add_user" do
|
683
|
+
it "ids a user using id_user_by" do
|
684
|
+
user = double("User", email: "test@test.com")
|
685
|
+
feature = Rollout::Feature.new(:chat, nil, id_user_by: :email)
|
686
|
+
feature.add_user(user)
|
687
|
+
expect(user).to have_received :email
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
describe "#initialize" do
|
692
|
+
describe "when string does not exist" do
|
693
|
+
it 'clears feature attributes when string is not given' do
|
694
|
+
feature = Rollout::Feature.new(:chat)
|
695
|
+
expect(feature.groups).to be_empty
|
696
|
+
expect(feature.users).to be_empty
|
697
|
+
expect(feature.percentage).to eq 0
|
698
|
+
expect(feature.data).to eq({})
|
699
|
+
end
|
700
|
+
|
701
|
+
it 'clears feature attributes when string is nil' do
|
702
|
+
feature = Rollout::Feature.new(:chat, nil)
|
703
|
+
expect(feature.groups).to be_empty
|
704
|
+
expect(feature.users).to be_empty
|
705
|
+
expect(feature.percentage).to eq 0
|
706
|
+
expect(feature.data).to eq({})
|
707
|
+
end
|
708
|
+
|
709
|
+
it 'clears feature attributes when string is empty string' do
|
710
|
+
feature = Rollout::Feature.new(:chat, "")
|
711
|
+
expect(feature.groups).to be_empty
|
712
|
+
expect(feature.users).to be_empty
|
713
|
+
expect(feature.percentage).to eq 0
|
714
|
+
expect(feature.data).to eq({})
|
715
|
+
end
|
716
|
+
|
717
|
+
describe "when there is no data" do
|
718
|
+
it 'sets @data to empty hash' do
|
719
|
+
feature = Rollout::Feature.new(:chat, "0||")
|
720
|
+
expect(feature.data).to eq({})
|
721
|
+
end
|
722
|
+
|
723
|
+
it 'sets @data to empty hash' do
|
724
|
+
feature = Rollout::Feature.new(:chat, "||| ")
|
725
|
+
expect(feature.data).to eq({})
|
726
|
+
end
|
727
|
+
end
|
728
|
+
end
|
729
|
+
end
|
730
|
+
end
|