split 3.3.0 → 3.4.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.
data/spec/helper_spec.rb CHANGED
@@ -183,8 +183,7 @@ describe Split::Helper do
183
183
  ab_test('link_color', {'blue' => 0.01}, 'red' => 0.2)
184
184
  experiment = Split::ExperimentCatalog.find('link_color')
185
185
  expect(experiment.alternatives.map(&:name)).to eq(['blue', 'red'])
186
- # TODO: persist alternative weights
187
- # expect(experiment.alternatives.collect{|a| a.weight}).to eq([0.01, 0.2])
186
+ expect(experiment.alternatives.collect{|a| a.weight}).to match_array([0.01, 0.2])
188
187
  end
189
188
 
190
189
  it "should only let a user participate in one experiment at a time" do
@@ -297,98 +296,126 @@ describe Split::Helper do
297
296
  end
298
297
 
299
298
  describe 'ab_finished' do
300
- before(:each) do
301
- @experiment_name = 'link_color'
302
- @alternatives = ['blue', 'red']
303
- @experiment = Split::ExperimentCatalog.find_or_create(@experiment_name, *@alternatives)
304
- @alternative_name = ab_test(@experiment_name, *@alternatives)
305
- @previous_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
306
- end
299
+ context 'for an experiment that the user participates in' do
300
+ before(:each) do
301
+ @experiment_name = 'link_color'
302
+ @alternatives = ['blue', 'red']
303
+ @experiment = Split::ExperimentCatalog.find_or_create(@experiment_name, *@alternatives)
304
+ @alternative_name = ab_test(@experiment_name, *@alternatives)
305
+ @previous_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
306
+ end
307
307
 
308
- it 'should increment the counter for the completed alternative' do
309
- ab_finished(@experiment_name)
310
- new_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
311
- expect(new_completion_count).to eq(@previous_completion_count + 1)
312
- end
308
+ it 'should increment the counter for the completed alternative' do
309
+ ab_finished(@experiment_name)
310
+ new_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
311
+ expect(new_completion_count).to eq(@previous_completion_count + 1)
312
+ end
313
313
 
314
- it "should set experiment's finished key if reset is false" do
315
- ab_finished(@experiment_name, {:reset => false})
316
- expect(ab_user[@experiment.key]).to eq(@alternative_name)
317
- expect(ab_user[@experiment.finished_key]).to eq(true)
318
- end
314
+ it "should set experiment's finished key if reset is false" do
315
+ ab_finished(@experiment_name, {:reset => false})
316
+ expect(ab_user[@experiment.key]).to eq(@alternative_name)
317
+ expect(ab_user[@experiment.finished_key]).to eq(true)
318
+ end
319
319
 
320
- it 'should not increment the counter if reset is false and the experiment has been already finished' do
321
- 2.times { ab_finished(@experiment_name, {:reset => false}) }
322
- new_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
323
- expect(new_completion_count).to eq(@previous_completion_count + 1)
324
- end
320
+ it 'should not increment the counter if reset is false and the experiment has been already finished' do
321
+ 2.times { ab_finished(@experiment_name, {:reset => false}) }
322
+ new_completion_count = Split::Alternative.new(@alternative_name, @experiment_name).completed_count
323
+ expect(new_completion_count).to eq(@previous_completion_count + 1)
324
+ end
325
325
 
326
- it 'should not increment the counter for an experiment that the user is not participating in' do
327
- ab_test('button_size', 'small', 'big')
326
+ it 'should not increment the counter for an ended experiment' do
327
+ e = Split::ExperimentCatalog.find_or_create('button_size', 'small', 'big')
328
+ e.winner = 'small'
329
+ a = ab_test('button_size', 'small', 'big')
330
+ expect(a).to eq('small')
331
+ expect(lambda {
332
+ ab_finished('button_size')
333
+ }).not_to change { Split::Alternative.new(a, 'button_size').completed_count }
334
+ end
328
335
 
329
- # So, user should be participating in the link_color experiment and
330
- # receive the control for button_size. As the user is not participating in
331
- # the button size experiment, finishing it should not increase the
332
- # completion count for that alternative.
333
- expect(lambda {
334
- ab_finished('button_size')
335
- }).not_to change { Split::Alternative.new('small', 'button_size').completed_count }
336
- end
336
+ it "should clear out the user's participation from their session" do
337
+ expect(ab_user[@experiment.key]).to eq(@alternative_name)
338
+ ab_finished(@experiment_name)
339
+ expect(ab_user.keys).to be_empty
340
+ end
337
341
 
338
- it 'should not increment the counter for an ended experiment' do
339
- e = Split::ExperimentCatalog.find_or_create('button_size', 'small', 'big')
340
- e.winner = 'small'
341
- a = ab_test('button_size', 'small', 'big')
342
- expect(a).to eq('small')
343
- expect(lambda {
344
- ab_finished('button_size')
345
- }).not_to change { Split::Alternative.new(a, 'button_size').completed_count }
346
- end
342
+ it "should not clear out the users session if reset is false" do
343
+ expect(ab_user[@experiment.key]).to eq(@alternative_name)
344
+ ab_finished(@experiment_name, {:reset => false})
345
+ expect(ab_user[@experiment.key]).to eq(@alternative_name)
346
+ expect(ab_user[@experiment.finished_key]).to eq(true)
347
+ end
347
348
 
348
- it "should clear out the user's participation from their session" do
349
- expect(ab_user[@experiment.key]).to eq(@alternative_name)
350
- ab_finished(@experiment_name)
351
- expect(ab_user.keys).to be_empty
352
- end
349
+ it "should reset the users session when experiment is not versioned" do
350
+ expect(ab_user[@experiment.key]).to eq(@alternative_name)
351
+ ab_finished(@experiment_name)
352
+ expect(ab_user.keys).to be_empty
353
+ end
353
354
 
354
- it "should not clear out the users session if reset is false" do
355
- expect(ab_user[@experiment.key]).to eq(@alternative_name)
356
- ab_finished(@experiment_name, {:reset => false})
357
- expect(ab_user[@experiment.key]).to eq(@alternative_name)
358
- expect(ab_user[@experiment.finished_key]).to eq(true)
359
- end
355
+ it "should reset the users session when experiment is versioned" do
356
+ @experiment.increment_version
357
+ @alternative_name = ab_test(@experiment_name, *@alternatives)
360
358
 
361
- it "should reset the users session when experiment is not versioned" do
362
- expect(ab_user[@experiment.key]).to eq(@alternative_name)
363
- ab_finished(@experiment_name)
364
- expect(ab_user.keys).to be_empty
365
- end
359
+ expect(ab_user[@experiment.key]).to eq(@alternative_name)
360
+ ab_finished(@experiment_name)
361
+ expect(ab_user.keys).to be_empty
362
+ end
366
363
 
367
- it "should reset the users session when experiment is versioned" do
368
- @experiment.increment_version
369
- @alternative_name = ab_test(@experiment_name, *@alternatives)
364
+ context "when on_trial_complete is set" do
365
+ before { Split.configuration.on_trial_complete = :some_method }
366
+ it "should call the method" do
367
+ expect(self).to receive(:some_method)
368
+ ab_finished(@experiment_name)
369
+ end
370
370
 
371
- expect(ab_user[@experiment.key]).to eq(@alternative_name)
372
- ab_finished(@experiment_name)
373
- expect(ab_user.keys).to be_empty
371
+ it "should not call the method without alternative" do
372
+ ab_user[@experiment.key] = nil
373
+ expect(self).not_to receive(:some_method)
374
+ ab_finished(@experiment_name)
375
+ end
376
+ end
374
377
  end
375
378
 
376
- it "should do nothing where the experiment was not started by this user" do
377
- ab_user = nil
378
- expect(lambda { ab_finished('some_experiment_not_started_by_the_user') }).not_to raise_exception
379
+ context 'for an experiment that the user is excluded from' do
380
+ before do
381
+ alternative = ab_test('link_color', 'blue', 'red')
382
+ expect(Split::Alternative.new(alternative, 'link_color').participant_count).to eq(1)
383
+ alternative = ab_test('button_size', 'small', 'big')
384
+ expect(Split::Alternative.new(alternative, 'button_size').participant_count).to eq(0)
385
+ end
386
+
387
+ it 'should not increment the completed counter' do
388
+ # So, user should be participating in the link_color experiment and
389
+ # receive the control for button_size. As the user is not participating in
390
+ # the button size experiment, finishing it should not increase the
391
+ # completion count for that alternative.
392
+ expect(lambda {
393
+ ab_finished('button_size')
394
+ }).not_to change { Split::Alternative.new('small', 'button_size').completed_count }
395
+ end
379
396
  end
380
397
 
381
- context "when on_trial_complete is set" do
382
- before { Split.configuration.on_trial_complete = :some_method }
383
- it "should call the method" do
384
- expect(self).to receive(:some_method)
385
- ab_finished(@experiment_name)
398
+ context 'for an experiment that the user does not participate in' do
399
+ before do
400
+ Split::ExperimentCatalog.find_or_create(:not_started_experiment, 'control', 'alt')
401
+ end
402
+ it 'should not raise an exception' do
403
+ expect { ab_finished(:not_started_experiment) }.not_to raise_exception
386
404
  end
387
405
 
388
- it "should not call the method without alternative" do
389
- ab_user[@experiment.key] = nil
390
- expect(self).not_to receive(:some_method)
391
- ab_finished(@experiment_name)
406
+ it 'should not change the user state when reset is false' do
407
+ expect { ab_finished(:not_started_experiment, reset: false) }.not_to change { ab_user.keys}.from([])
408
+ end
409
+
410
+ it 'should not change the user state when reset is true' do
411
+ expect(self).not_to receive(:reset!)
412
+ ab_finished(:not_started_experiment)
413
+ end
414
+
415
+ it 'should not increment the completed counter' do
416
+ ab_finished(:not_started_experiment)
417
+ expect(Split::Alternative.new('control', :not_started_experiment).completed_count).to eq(0)
418
+ expect(Split::Alternative.new('alt', :not_started_experiment).completed_count).to eq(0)
392
419
  end
393
420
  end
394
421
  end
@@ -528,6 +555,17 @@ describe Split::Helper do
528
555
  expect(active_experiments.first[0]).to eq "link_color"
529
556
  end
530
557
 
558
+ it 'should show versioned tests properly' do
559
+ 10.times { experiment.reset }
560
+
561
+ alternative = ab_test(experiment.name, 'blue', 'red')
562
+ ab_finished(experiment.name, reset: false)
563
+
564
+ expect(experiment.version).to eq(10)
565
+ expect(active_experiments.count).to eq 1
566
+ expect(active_experiments).to eq({'link_color' => alternative })
567
+ end
568
+
531
569
  it 'should show multiple tests' do
532
570
  Split.configure do |config|
533
571
  config.allow_multiple_experiments = true
@@ -545,7 +583,7 @@ describe Split::Helper do
545
583
  end
546
584
  e = Split::ExperimentCatalog.find_or_create('def', '4', '5', '6')
547
585
  e.winner = '4'
548
- alternative = ab_test('def', '4', '5', '6')
586
+ ab_test('def', '4', '5', '6')
549
587
  another_alternative = ab_test('ghi', '7', '8', '9')
550
588
  expect(active_experiments.count).to eq 1
551
589
  expect(active_experiments.first[0]).to eq "ghi"
@@ -564,6 +602,11 @@ describe Split::Helper do
564
602
  expect(alternative).to eq experiment.control.name
565
603
  end
566
604
 
605
+ it 'should not create a experiment' do
606
+ ab_test('link_color', 'blue', 'red')
607
+ expect(Split::Experiment.new('link_color')).to be_a_new_record
608
+ end
609
+
567
610
  it "should not increment the participation count" do
568
611
 
569
612
  previous_red_count = Split::Alternative.new('red', 'link_color').participant_count
@@ -1016,8 +1059,8 @@ describe Split::Helper do
1016
1059
 
1017
1060
  it 'should handle multiple experiments correctly' do
1018
1061
  experiment2 = Split::ExperimentCatalog.find_or_create('link_color2', 'blue', 'red')
1019
- alternative_name = ab_test('link_color', 'blue', 'red')
1020
- alternative_name2 = ab_test('link_color2', 'blue', 'red')
1062
+ ab_test('link_color', 'blue', 'red')
1063
+ ab_test('link_color2', 'blue', 'red')
1021
1064
  ab_finished('link_color2')
1022
1065
 
1023
1066
  experiment2.alternatives.each do |alt|
@@ -1,102 +1,194 @@
1
1
  # frozen_string_literal: true
2
- require "spec_helper"
2
+
3
+ require 'spec_helper'
3
4
 
4
5
  describe Split::Persistence::DualAdapter do
6
+ let(:context) { 'some context' }
5
7
 
6
- let(:context){ "some context" }
7
-
8
- let(:just_adapter){ Class.new }
9
- let(:selected_adapter_instance){ double }
10
- let(:selected_adapter){
11
- c = Class.new
12
- expect(c).to receive(:new){ selected_adapter_instance }
13
- c
14
- }
15
- let(:not_selected_adapter){
16
- c = Class.new
17
- expect(c).not_to receive(:new)
18
- c
19
- }
20
-
21
- shared_examples_for "forwarding calls" do
22
- it "#[]=" do
23
- expect(selected_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
24
- expect_any_instance_of(not_selected_adapter).not_to receive(:[]=)
25
- subject["my_key"] = "my_value"
26
- end
8
+ let(:logged_in_adapter_instance) { double }
9
+ let(:logged_in_adapter) do
10
+ Class.new.tap { |c| allow(c).to receive(:new) { logged_in_adapter_instance } }
11
+ end
12
+ let(:logged_out_adapter_instance) { double }
13
+ let(:logged_out_adapter) do
14
+ Class.new.tap { |c| allow(c).to receive(:new) { logged_out_adapter_instance } }
15
+ end
27
16
 
28
- it "#[]" do
29
- expect(selected_adapter_instance).to receive(:[]).with('my_key'){'my_value'}
30
- expect_any_instance_of(not_selected_adapter).not_to receive(:[])
31
- expect(subject["my_key"]).to eq('my_value')
32
- end
17
+ context 'when fallback_to_logged_out_adapter is false' do
18
+ context 'when logged in' do
19
+ subject do
20
+ described_class.with_config(
21
+ logged_in: lambda { |context| true },
22
+ logged_in_adapter: logged_in_adapter,
23
+ logged_out_adapter: logged_out_adapter,
24
+ fallback_to_logged_out_adapter: false
25
+ ).new(context)
26
+ end
27
+
28
+ it '#[]=' do
29
+ expect(logged_in_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
30
+ expect_any_instance_of(logged_out_adapter).not_to receive(:[]=)
31
+ subject['my_key'] = 'my_value'
32
+ end
33
+
34
+ it '#[]' do
35
+ expect(logged_in_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
36
+ expect_any_instance_of(logged_out_adapter).not_to receive(:[])
37
+ expect(subject['my_key']).to eq('my_value')
38
+ end
33
39
 
34
- it "#delete" do
35
- expect(selected_adapter_instance).to receive(:delete).with('my_key'){'my_value'}
36
- expect_any_instance_of(not_selected_adapter).not_to receive(:delete)
37
- expect(subject.delete("my_key")).to eq('my_value')
40
+ it '#delete' do
41
+ expect(logged_in_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
42
+ expect_any_instance_of(logged_out_adapter).not_to receive(:delete)
43
+ expect(subject.delete('my_key')).to eq('my_value')
44
+ end
45
+
46
+ it '#keys' do
47
+ expect(logged_in_adapter_instance).to receive(:keys) { ['my_value'] }
48
+ expect_any_instance_of(logged_out_adapter).not_to receive(:keys)
49
+ expect(subject.keys).to eq(['my_value'])
50
+ end
38
51
  end
39
52
 
40
- it "#keys" do
41
- expect(selected_adapter_instance).to receive(:keys){'my_value'}
42
- expect_any_instance_of(not_selected_adapter).not_to receive(:keys)
43
- expect(subject.keys).to eq('my_value')
53
+ context 'when logged out' do
54
+ subject do
55
+ described_class.with_config(
56
+ logged_in: lambda { |context| false },
57
+ logged_in_adapter: logged_in_adapter,
58
+ logged_out_adapter: logged_out_adapter,
59
+ fallback_to_logged_out_adapter: false
60
+ ).new(context)
61
+ end
62
+
63
+ it '#[]=' do
64
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[]=)
65
+ expect(logged_out_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
66
+ subject['my_key'] = 'my_value'
67
+ end
68
+
69
+ it '#[]' do
70
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[])
71
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
72
+ expect(subject['my_key']).to eq('my_value')
73
+ end
74
+
75
+ it '#delete' do
76
+ expect_any_instance_of(logged_in_adapter).not_to receive(:delete)
77
+ expect(logged_out_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
78
+ expect(subject.delete('my_key')).to eq('my_value')
79
+ end
80
+
81
+ it '#keys' do
82
+ expect_any_instance_of(logged_in_adapter).not_to receive(:keys)
83
+ expect(logged_out_adapter_instance).to receive(:keys) { ['my_value', 'my_value2'] }
84
+ expect(subject.keys).to eq(['my_value', 'my_value2'])
85
+ end
44
86
  end
45
87
  end
46
88
 
47
- context "when logged in" do
48
- subject {
49
- described_class.with_config(
50
- logged_in: lambda { |context| true },
51
- logged_in_adapter: selected_adapter,
52
- logged_out_adapter: not_selected_adapter
89
+ context 'when fallback_to_logged_out_adapter is true' do
90
+ context 'when logged in' do
91
+ subject do
92
+ described_class.with_config(
93
+ logged_in: lambda { |context| true },
94
+ logged_in_adapter: logged_in_adapter,
95
+ logged_out_adapter: logged_out_adapter,
96
+ fallback_to_logged_out_adapter: true
53
97
  ).new(context)
54
- }
98
+ end
55
99
 
56
- it_should_behave_like "forwarding calls"
57
- end
100
+ it '#[]=' do
101
+ expect(logged_in_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
102
+ expect(logged_out_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
103
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { nil }
104
+ subject['my_key'] = 'my_value'
105
+ end
106
+
107
+ it '#[]' do
108
+ expect(logged_in_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
109
+ expect_any_instance_of(logged_out_adapter).not_to receive(:[])
110
+ expect(subject['my_key']).to eq('my_value')
111
+ end
112
+
113
+ it '#delete' do
114
+ expect(logged_in_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
115
+ expect(logged_out_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
116
+ expect(subject.delete('my_key')).to eq('my_value')
117
+ end
118
+
119
+ it '#keys' do
120
+ expect(logged_in_adapter_instance).to receive(:keys) { ['my_value'] }
121
+ expect(logged_out_adapter_instance).to receive(:keys) { ['my_value', 'my_value2'] }
122
+ expect(subject.keys).to eq(['my_value', 'my_value2'])
123
+ end
124
+ end
58
125
 
59
- context "when not logged in" do
60
- subject {
61
- described_class.with_config(
62
- logged_in: lambda { |context| false },
63
- logged_in_adapter: not_selected_adapter,
64
- logged_out_adapter: selected_adapter
126
+ context 'when logged out' do
127
+ subject do
128
+ described_class.with_config(
129
+ logged_in: lambda { |context| false },
130
+ logged_in_adapter: logged_in_adapter,
131
+ logged_out_adapter: logged_out_adapter,
132
+ fallback_to_logged_out_adapter: true
65
133
  ).new(context)
66
- }
134
+ end
135
+
136
+ it '#[]=' do
137
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[]=)
138
+ expect(logged_out_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
139
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { nil }
140
+ subject['my_key'] = 'my_value'
141
+ end
142
+
143
+ it '#[]' do
144
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[])
145
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
146
+ expect(subject['my_key']).to eq('my_value')
147
+ end
148
+
149
+ it '#delete' do
150
+ expect(logged_in_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
151
+ expect(logged_out_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
152
+ expect(subject.delete('my_key')).to eq('my_value')
153
+ end
67
154
 
68
- it_should_behave_like "forwarding calls"
155
+ it '#keys' do
156
+ expect(logged_in_adapter_instance).to receive(:keys) { ['my_value'] }
157
+ expect(logged_out_adapter_instance).to receive(:keys) { ['my_value', 'my_value2'] }
158
+ expect(subject.keys).to eq(['my_value', 'my_value2'])
159
+ end
160
+ end
69
161
  end
70
162
 
71
- describe "when errors in config" do
72
- before{
73
- described_class.config.clear
74
- }
75
- let(:some_proc){ ->{} }
76
- it "when no logged in adapter" do
163
+ describe 'when errors in config' do
164
+ before { described_class.config.clear }
165
+ let(:some_proc) { ->{} }
166
+
167
+ it 'when no logged in adapter' do
77
168
  expect{
78
169
  described_class.with_config(
79
170
  logged_in: some_proc,
80
- logged_out_adapter: just_adapter
81
- ).new(context)
171
+ logged_out_adapter: logged_out_adapter
172
+ ).new(context)
82
173
  }.to raise_error(StandardError, /:logged_in_adapter/)
83
174
  end
84
- it "when no logged out adapter" do
175
+
176
+ it 'when no logged out adapter' do
85
177
  expect{
86
178
  described_class.with_config(
87
179
  logged_in: some_proc,
88
- logged_in_adapter: just_adapter
89
- ).new(context)
180
+ logged_in_adapter: logged_in_adapter
181
+ ).new(context)
90
182
  }.to raise_error(StandardError, /:logged_out_adapter/)
91
183
  end
92
- it "when no logged in detector" do
184
+
185
+ it 'when no logged in detector' do
93
186
  expect{
94
187
  described_class.with_config(
95
- logged_in_adapter: just_adapter,
96
- logged_out_adapter: just_adapter
97
- ).new(context)
188
+ logged_in_adapter: logged_in_adapter,
189
+ logged_out_adapter: logged_out_adapter
190
+ ).new(context)
98
191
  }.to raise_error(StandardError, /:logged_in$/)
99
192
  end
100
193
  end
101
-
102
194
  end
data/spec/trial_spec.rb CHANGED
@@ -176,6 +176,14 @@ describe Split::Trial do
176
176
 
177
177
  expect_alternative(trial, 'basket')
178
178
  end
179
+
180
+ context "when alternative is not found" do
181
+ it "falls back on next_alternative" do
182
+ user[experiment.key] = 'notfound'
183
+ expect(experiment).to receive(:next_alternative).and_call_original
184
+ expect_alternative(trial, alternatives)
185
+ end
186
+ end
179
187
  end
180
188
 
181
189
  context "when user is a new participant" do
@@ -275,5 +283,17 @@ describe Split::Trial do
275
283
  trial.choose!
276
284
  end
277
285
  end
286
+
287
+ context 'when experiment has winner' do
288
+ let(:trial) do
289
+ experiment.winner = 'cart'
290
+ Split::Trial.new(:user => user, :experiment => experiment)
291
+ end
292
+
293
+ it 'does not store' do
294
+ expect(user).to_not receive("[]=")
295
+ trial.choose!
296
+ end
297
+ end
278
298
  end
279
299
  end
data/spec/user_spec.rb CHANGED
@@ -59,6 +59,17 @@ describe Split::User do
59
59
  expect(@subject.keys).to include("link_color:finished")
60
60
  end
61
61
  end
62
+
63
+ context 'when already cleaned up' do
64
+ before do
65
+ @subject.cleanup_old_experiments!
66
+ end
67
+
68
+ it 'does not clean up again' do
69
+ expect(@subject).to_not receive(:keys_without_finished)
70
+ @subject.cleanup_old_experiments!
71
+ end
72
+ end
62
73
  end
63
74
 
64
75
  context "instantiated with custom adapter" do
data/split.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  $:.push File.expand_path("../lib", __FILE__)
3
4
  require "split/version"
4
5
 
@@ -24,8 +25,6 @@ Gem::Specification.new do |s|
24
25
  s.required_ruby_version = '>= 1.9.3'
25
26
  s.required_rubygems_version = '>= 2.0.0'
26
27
 
27
- s.rubyforge_project = "split"
28
-
29
28
  s.files = `git ls-files`.split("\n")
30
29
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
30
  s.require_paths = ["lib"]
@@ -34,11 +33,12 @@ Gem::Specification.new do |s|
34
33
  s.add_dependency 'sinatra', '>= 1.2.6'
35
34
  s.add_dependency 'simple-random', '>= 0.9.3'
36
35
 
37
- s.add_development_dependency 'bundler', '~> 1.14'
36
+ s.add_development_dependency 'bundler', '>= 1.17'
38
37
  s.add_development_dependency 'simplecov', '~> 0.15'
39
38
  s.add_development_dependency 'rack-test', '~> 0.6'
40
39
  s.add_development_dependency 'rake', '~> 12'
41
40
  s.add_development_dependency 'rspec', '~> 3.7'
42
41
  s.add_development_dependency 'pry', '~> 0.10'
43
42
  s.add_development_dependency 'fakeredis', '~> 0.7'
43
+ s.add_development_dependency 'rails', '>= 4.2'
44
44
  end