split 4.0.1 → 4.0.2

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +6 -3
  3. data/.rubocop.yml +2 -5
  4. data/CHANGELOG.md +23 -0
  5. data/CONTRIBUTING.md +1 -1
  6. data/Gemfile +2 -1
  7. data/README.md +4 -2
  8. data/Rakefile +4 -5
  9. data/gemfiles/5.2.gemfile +1 -3
  10. data/gemfiles/6.0.gemfile +1 -3
  11. data/gemfiles/6.1.gemfile +1 -3
  12. data/gemfiles/7.0.gemfile +2 -3
  13. data/lib/split/algorithms/block_randomization.rb +5 -6
  14. data/lib/split/algorithms/whiplash.rb +16 -18
  15. data/lib/split/algorithms.rb +22 -0
  16. data/lib/split/alternative.rb +21 -22
  17. data/lib/split/cache.rb +0 -1
  18. data/lib/split/combined_experiments_helper.rb +4 -4
  19. data/lib/split/configuration.rb +83 -84
  20. data/lib/split/dashboard/helpers.rb +6 -7
  21. data/lib/split/dashboard/pagination_helpers.rb +53 -54
  22. data/lib/split/dashboard/public/style.css +5 -2
  23. data/lib/split/dashboard/views/index.erb +19 -4
  24. data/lib/split/dashboard.rb +29 -23
  25. data/lib/split/encapsulated_helper.rb +4 -6
  26. data/lib/split/experiment.rb +84 -88
  27. data/lib/split/experiment_catalog.rb +6 -5
  28. data/lib/split/extensions/string.rb +1 -1
  29. data/lib/split/goals_collection.rb +8 -10
  30. data/lib/split/helper.rb +19 -19
  31. data/lib/split/metric.rb +4 -5
  32. data/lib/split/persistence/cookie_adapter.rb +44 -47
  33. data/lib/split/persistence/dual_adapter.rb +7 -8
  34. data/lib/split/persistence/redis_adapter.rb +2 -3
  35. data/lib/split/persistence/session_adapter.rb +0 -2
  36. data/lib/split/persistence.rb +4 -4
  37. data/lib/split/redis_interface.rb +1 -2
  38. data/lib/split/trial.rb +23 -24
  39. data/lib/split/user.rb +12 -13
  40. data/lib/split/version.rb +1 -1
  41. data/lib/split/zscore.rb +1 -3
  42. data/lib/split.rb +26 -25
  43. data/spec/algorithms/block_randomization_spec.rb +6 -5
  44. data/spec/algorithms/weighted_sample_spec.rb +6 -5
  45. data/spec/algorithms/whiplash_spec.rb +4 -5
  46. data/spec/alternative_spec.rb +35 -36
  47. data/spec/cache_spec.rb +15 -19
  48. data/spec/combined_experiments_helper_spec.rb +18 -17
  49. data/spec/configuration_spec.rb +32 -38
  50. data/spec/dashboard/pagination_helpers_spec.rb +69 -67
  51. data/spec/dashboard/paginator_spec.rb +10 -9
  52. data/spec/dashboard_helpers_spec.rb +19 -18
  53. data/spec/dashboard_spec.rb +67 -35
  54. data/spec/encapsulated_helper_spec.rb +12 -14
  55. data/spec/experiment_catalog_spec.rb +14 -13
  56. data/spec/experiment_spec.rb +121 -123
  57. data/spec/goals_collection_spec.rb +17 -15
  58. data/spec/helper_spec.rb +379 -382
  59. data/spec/metric_spec.rb +14 -14
  60. data/spec/persistence/cookie_adapter_spec.rb +23 -8
  61. data/spec/persistence/dual_adapter_spec.rb +71 -71
  62. data/spec/persistence/redis_adapter_spec.rb +25 -26
  63. data/spec/persistence/session_adapter_spec.rb +2 -3
  64. data/spec/persistence_spec.rb +1 -2
  65. data/spec/redis_interface_spec.rb +16 -14
  66. data/spec/spec_helper.rb +15 -13
  67. data/spec/split_spec.rb +11 -11
  68. data/spec/support/cookies_mock.rb +1 -2
  69. data/spec/trial_spec.rb +61 -60
  70. data/spec/user_spec.rb +36 -36
  71. data/split.gemspec +20 -20
  72. metadata +7 -10
  73. data/.rubocop_todo.yml +0 -226
  74. data/Appraisals +0 -19
  75. data/gemfiles/5.0.gemfile +0 -9
  76. data/gemfiles/5.1.gemfile +0 -9
data/spec/split_spec.rb CHANGED
@@ -1,18 +1,18 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
3
2
 
4
- RSpec.describe Split do
3
+ require "spec_helper"
5
4
 
5
+ RSpec.describe Split do
6
6
  around(:each) do |ex|
7
- old_env, old_redis = [ENV.delete('REDIS_URL'), Split.redis]
7
+ old_env, old_redis = [ENV.delete("REDIS_URL"), Split.redis]
8
8
  ex.run
9
- ENV['REDIS_URL'] = old_env
9
+ ENV["REDIS_URL"] = old_env
10
10
  Split.redis = old_redis
11
11
  end
12
12
 
13
- describe '#redis=' do
14
- it 'accepts a url string' do
15
- Split.redis = 'redis://localhost:6379'
13
+ describe "#redis=" do
14
+ it "accepts a url string" do
15
+ Split.redis = "redis://localhost:6379"
16
16
  expect(Split.redis).to be_a(Redis)
17
17
 
18
18
  client = Split.redis.connection
@@ -20,8 +20,8 @@ RSpec.describe Split do
20
20
  expect(client[:port]).to eq(6379)
21
21
  end
22
22
 
23
- it 'accepts an options hash' do
24
- Split.redis = {host: 'localhost', port: 6379, db: 12}
23
+ it "accepts an options hash" do
24
+ Split.redis = { host: "localhost", port: 6379, db: 12 }
25
25
  expect(Split.redis).to be_a(Redis)
26
26
 
27
27
  client = Split.redis.connection
@@ -30,13 +30,13 @@ RSpec.describe Split do
30
30
  expect(client[:db]).to eq(12)
31
31
  end
32
32
 
33
- it 'accepts a valid Redis instance' do
33
+ it "accepts a valid Redis instance" do
34
34
  other_redis = Redis.new(url: "redis://localhost:6379")
35
35
  Split.redis = other_redis
36
36
  expect(Split.redis).to eq(other_redis)
37
37
  end
38
38
 
39
- it 'raises an ArgumentError when server cannot be determined' do
39
+ it "raises an ArgumentError when server cannot be determined" do
40
40
  expect { Split.redis = Object.new }.to raise_error(ArgumentError)
41
41
  end
42
42
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
- class CookiesMock
3
2
 
3
+ class CookiesMock
4
4
  def initialize
5
5
  @cookies = {}
6
6
  end
@@ -16,5 +16,4 @@ class CookiesMock
16
16
  def delete(key)
17
17
  @cookies.delete(key)
18
18
  end
19
-
20
19
  end
data/spec/trial_spec.rb CHANGED
@@ -1,54 +1,55 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
3
- require 'split/trial'
2
+
3
+ require "spec_helper"
4
+ require "split/trial"
4
5
 
5
6
  describe Split::Trial do
6
7
  let(:user) { mock_user }
7
- let(:alternatives) { ['basket', 'cart'] }
8
+ let(:alternatives) { ["basket", "cart"] }
8
9
  let(:experiment) do
9
- Split::Experiment.new('basket_text', :alternatives => alternatives).save
10
+ Split::Experiment.new("basket_text", alternatives: alternatives).save
10
11
  end
11
12
 
12
13
  it "should be initializeable" do
13
- experiment = double('experiment')
14
- alternative = double('alternative', :kind_of? => Split::Alternative)
15
- trial = Split::Trial.new(:experiment => experiment, :alternative => alternative)
14
+ experiment = double("experiment")
15
+ alternative = double("alternative", kind_of?: Split::Alternative)
16
+ trial = Split::Trial.new(experiment: experiment, alternative: alternative)
16
17
  expect(trial.experiment).to eq(experiment)
17
18
  expect(trial.alternative).to eq(alternative)
18
19
  end
19
20
 
20
21
  describe "alternative" do
21
22
  it "should use the alternative if specified" do
22
- alternative = double('alternative', :kind_of? => Split::Alternative)
23
- trial = Split::Trial.new(:experiment => double('experiment'),
24
- :alternative => alternative, :user => user)
23
+ alternative = double("alternative", kind_of?: Split::Alternative)
24
+ trial = Split::Trial.new(experiment: double("experiment"),
25
+ alternative: alternative, user: user)
25
26
  expect(trial).not_to receive(:choose)
26
27
  expect(trial.alternative).to eq(alternative)
27
28
  end
28
29
 
29
30
  it "should load the alternative when the alternative name is set" do
30
- experiment = Split::Experiment.new('basket_text', :alternatives => ['basket', 'cart'])
31
+ experiment = Split::Experiment.new("basket_text", alternatives: ["basket", "cart"])
31
32
  experiment.save
32
33
 
33
- trial = Split::Trial.new(:experiment => experiment, :alternative => 'basket')
34
- expect(trial.alternative.name).to eq('basket')
34
+ trial = Split::Trial.new(experiment: experiment, alternative: "basket")
35
+ expect(trial.alternative.name).to eq("basket")
35
36
  end
36
37
  end
37
38
 
38
39
  describe "metadata" do
39
40
  let(:metadata) { Hash[alternatives.map { |k| [k, "Metadata for #{k}"] }] }
40
41
  let(:experiment) do
41
- Split::Experiment.new('basket_text', :alternatives => alternatives, :metadata => metadata).save
42
+ Split::Experiment.new("basket_text", alternatives: alternatives, metadata: metadata).save
42
43
  end
43
44
 
44
- it 'has metadata on each trial' do
45
- trial = Split::Trial.new(:experiment => experiment, :user => user, :metadata => metadata['cart'],
46
- :override => 'cart')
47
- expect(trial.metadata).to eq(metadata['cart'])
45
+ it "has metadata on each trial" do
46
+ trial = Split::Trial.new(experiment: experiment, user: user, metadata: metadata["cart"],
47
+ override: "cart")
48
+ expect(trial.metadata).to eq(metadata["cart"])
48
49
  end
49
50
 
50
- it 'has metadata on each trial from the experiment' do
51
- trial = Split::Trial.new(:experiment => experiment, :user => user)
51
+ it "has metadata on each trial from the experiment" do
52
+ trial = Split::Trial.new(experiment: experiment, user: user)
52
53
  trial.choose!
53
54
  expect(trial.metadata).to eq(metadata[trial.alternative.name])
54
55
  expect(trial.metadata).to match(/#{trial.alternative.name}/)
@@ -56,24 +57,24 @@ describe Split::Trial do
56
57
  end
57
58
 
58
59
  describe "#choose!" do
59
- let(:context) { double(on_trial_callback: 'test callback') }
60
+ let(:context) { double(on_trial_callback: "test callback") }
60
61
  let(:trial) do
61
- Split::Trial.new(:user => user, :experiment => experiment)
62
+ Split::Trial.new(user: user, experiment: experiment)
62
63
  end
63
64
 
64
- shared_examples_for 'a trial with callbacks' do
65
- it 'does not run if on_trial callback is not respondable' do
65
+ shared_examples_for "a trial with callbacks" do
66
+ it "does not run if on_trial callback is not respondable" do
66
67
  Split.configuration.on_trial = :foo
67
68
  allow(context).to receive(:respond_to?).with(:foo, true).and_return false
68
69
  expect(context).to_not receive(:foo)
69
70
  trial.choose! context
70
71
  end
71
- it 'runs on_trial callback' do
72
+ it "runs on_trial callback" do
72
73
  Split.configuration.on_trial = :on_trial_callback
73
74
  expect(context).to receive(:on_trial_callback)
74
75
  trial.choose! context
75
76
  end
76
- it 'does not run nil on_trial callback' do
77
+ it "does not run nil on_trial callback" do
77
78
  Split.configuration.on_trial = nil
78
79
  expect(context).not_to receive(:on_trial_callback)
79
80
  trial.choose! context
@@ -88,12 +89,12 @@ describe Split::Trial do
88
89
  end
89
90
 
90
91
  context "when override is present" do
91
- let(:override) { 'cart' }
92
+ let(:override) { "cart" }
92
93
  let(:trial) do
93
- Split::Trial.new(:user => user, :experiment => experiment, :override => override)
94
+ Split::Trial.new(user: user, experiment: experiment, override: override)
94
95
  end
95
96
 
96
- it_behaves_like 'a trial with callbacks'
97
+ it_behaves_like "a trial with callbacks"
97
98
 
98
99
  it "picks the override" do
99
100
  expect(experiment).to_not receive(:next_alternative)
@@ -102,7 +103,7 @@ describe Split::Trial do
102
103
 
103
104
  context "when alternative doesn't exist" do
104
105
  let(:override) { nil }
105
- it 'falls back on next_alternative' do
106
+ it "falls back on next_alternative" do
106
107
  expect(experiment).to receive(:next_alternative).and_call_original
107
108
  expect_alternative(trial, alternatives)
108
109
  end
@@ -111,7 +112,7 @@ describe Split::Trial do
111
112
 
112
113
  context "when disabled option is true" do
113
114
  let(:trial) do
114
- Split::Trial.new(:user => user, :experiment => experiment, :disabled => true)
115
+ Split::Trial.new(user: user, experiment: experiment, disabled: true)
115
116
  end
116
117
 
117
118
  it "picks the control", :aggregate_failures do
@@ -120,7 +121,7 @@ describe Split::Trial do
120
121
 
121
122
  expect(context).not_to receive(:on_trial_callback)
122
123
 
123
- expect_alternative(trial, 'basket')
124
+ expect_alternative(trial, "basket")
124
125
  Split.configuration.on_trial = nil
125
126
  end
126
127
  end
@@ -132,7 +133,7 @@ describe Split::Trial do
132
133
 
133
134
  expect(experiment).to_not receive(:next_alternative)
134
135
  expect(context).not_to receive(:on_trial_callback)
135
- expect_alternative(trial, 'basket')
136
+ expect_alternative(trial, "basket")
136
137
 
137
138
  Split.configuration.enabled = true
138
139
  Split.configuration.on_trial = nil
@@ -141,45 +142,45 @@ describe Split::Trial do
141
142
 
142
143
  context "when experiment has winner" do
143
144
  let(:trial) do
144
- Split::Trial.new(:user => user, :experiment => experiment)
145
+ Split::Trial.new(user: user, experiment: experiment)
145
146
  end
146
147
 
147
- it_behaves_like 'a trial with callbacks'
148
+ it_behaves_like "a trial with callbacks"
148
149
 
149
150
  it "picks the winner" do
150
- experiment.winner = 'cart'
151
+ experiment.winner = "cart"
151
152
  expect(experiment).to_not receive(:next_alternative)
152
153
 
153
- expect_alternative(trial, 'cart')
154
+ expect_alternative(trial, "cart")
154
155
  end
155
156
  end
156
157
 
157
158
  context "when exclude is true" do
158
159
  let(:trial) do
159
- Split::Trial.new(:user => user, :experiment => experiment, :exclude => true)
160
+ Split::Trial.new(user: user, experiment: experiment, exclude: true)
160
161
  end
161
162
 
162
- it_behaves_like 'a trial with callbacks'
163
+ it_behaves_like "a trial with callbacks"
163
164
 
164
165
  it "picks the control" do
165
166
  expect(experiment).to_not receive(:next_alternative)
166
- expect_alternative(trial, 'basket')
167
+ expect_alternative(trial, "basket")
167
168
  end
168
169
  end
169
170
 
170
171
  context "when user is already participating" do
171
- it_behaves_like 'a trial with callbacks'
172
+ it_behaves_like "a trial with callbacks"
172
173
 
173
174
  it "picks the same alternative" do
174
- user[experiment.key] = 'basket'
175
+ user[experiment.key] = "basket"
175
176
  expect(experiment).to_not receive(:next_alternative)
176
177
 
177
- expect_alternative(trial, 'basket')
178
+ expect_alternative(trial, "basket")
178
179
  end
179
180
 
180
181
  context "when alternative is not found" do
181
182
  it "falls back on next_alternative" do
182
- user[experiment.key] = 'notfound'
183
+ user[experiment.key] = "notfound"
183
184
  expect(experiment).to receive(:next_alternative).and_call_original
184
185
  expect_alternative(trial, alternatives)
185
186
  end
@@ -213,7 +214,7 @@ describe Split::Trial do
213
214
 
214
215
  expect(experiment).to_not receive(:next_alternative)
215
216
  expect(context).not_to receive(:on_trial_callback)
216
- expect_alternative(trial, 'basket')
217
+ expect_alternative(trial, "basket")
217
218
 
218
219
  Split.configuration.enabled = true
219
220
  Split.configuration.on_trial = nil
@@ -229,9 +230,9 @@ describe Split::Trial do
229
230
  end
230
231
 
231
232
  describe "#complete!" do
232
- context 'when there are no goals' do
233
- let(:trial) { Split::Trial.new(:user => user, :experiment => experiment) }
234
- it 'should complete the trial' do
233
+ context "when there are no goals" do
234
+ let(:trial) { Split::Trial.new(user: user, experiment: experiment) }
235
+ it "should complete the trial" do
235
236
  trial.choose!
236
237
  old_completed_count = trial.alternative.completed_count
237
238
  trial.complete!
@@ -241,11 +242,11 @@ describe Split::Trial do
241
242
 
242
243
  context "when there are many goals" do
243
244
  let(:goals) { [ "goal1", "goal2" ] }
244
- let(:trial) { Split::Trial.new(:user => user, :experiment => experiment, :goals => goals) }
245
+ let(:trial) { Split::Trial.new(user: user, experiment: experiment, goals: goals) }
245
246
 
246
247
  it "increments the completed count corresponding to the goals" do
247
248
  trial.choose!
248
- old_completed_counts = goals.map{ |goal| [goal, trial.alternative.completed_count(goal)] }.to_h
249
+ old_completed_counts = goals.map { |goal| [goal, trial.alternative.completed_count(goal)] }.to_h
249
250
  trial.complete!
250
251
  goals.each { | goal | expect(trial.alternative.completed_count(goal)).to eq(old_completed_counts[goal] + 1) }
251
252
  end
@@ -253,7 +254,7 @@ describe Split::Trial do
253
254
 
254
255
  context "when there is 1 goal of type string" do
255
256
  let(:goal) { "goal" }
256
- let(:trial) { Split::Trial.new(:user => user, :experiment => experiment, :goals => goal) }
257
+ let(:trial) { Split::Trial.new(user: user, experiment: experiment, goals: goal) }
257
258
  it "increments the completed count corresponding to the goal" do
258
259
  trial.choose!
259
260
  old_completed_count = trial.alternative.completed_count(goal)
@@ -268,7 +269,7 @@ describe Split::Trial do
268
269
 
269
270
  context "when override is present" do
270
271
  it "stores when store_override is true" do
271
- trial = Split::Trial.new(:user => user, :experiment => experiment, :override => 'basket')
272
+ trial = Split::Trial.new(user: user, experiment: experiment, override: "basket")
272
273
 
273
274
  Split.configuration.store_override = true
274
275
  expect(user).to receive("[]=")
@@ -277,7 +278,7 @@ describe Split::Trial do
277
278
  end
278
279
 
279
280
  it "does not store when store_override is false" do
280
- trial = Split::Trial.new(:user => user, :experiment => experiment, :override => 'basket')
281
+ trial = Split::Trial.new(user: user, experiment: experiment, override: "basket")
281
282
 
282
283
  expect(user).to_not receive("[]=")
283
284
  trial.choose!
@@ -286,7 +287,7 @@ describe Split::Trial do
286
287
 
287
288
  context "when disabled is present" do
288
289
  it "stores when store_override is true" do
289
- trial = Split::Trial.new(:user => user, :experiment => experiment, :disabled => true)
290
+ trial = Split::Trial.new(user: user, experiment: experiment, disabled: true)
290
291
 
291
292
  Split.configuration.store_override = true
292
293
  expect(user).to receive("[]=")
@@ -294,7 +295,7 @@ describe Split::Trial do
294
295
  end
295
296
 
296
297
  it "does not store when store_override is false" do
297
- trial = Split::Trial.new(:user => user, :experiment => experiment, :disabled => true)
298
+ trial = Split::Trial.new(user: user, experiment: experiment, disabled: true)
298
299
 
299
300
  expect(user).to_not receive("[]=")
300
301
  trial.choose!
@@ -303,20 +304,20 @@ describe Split::Trial do
303
304
 
304
305
  context "when exclude is present" do
305
306
  it "does not store" do
306
- trial = Split::Trial.new(:user => user, :experiment => experiment, :exclude => true)
307
+ trial = Split::Trial.new(user: user, experiment: experiment, exclude: true)
307
308
 
308
309
  expect(user).to_not receive("[]=")
309
310
  trial.choose!
310
311
  end
311
312
  end
312
313
 
313
- context 'when experiment has winner' do
314
+ context "when experiment has winner" do
314
315
  let(:trial) do
315
- experiment.winner = 'cart'
316
- Split::Trial.new(:user => user, :experiment => experiment)
316
+ experiment.winner = "cart"
317
+ Split::Trial.new(user: user, experiment: experiment)
317
318
  end
318
319
 
319
- it 'does not store' do
320
+ it "does not store" do
320
321
  expect(user).to_not receive("[]=")
321
322
  trial.choose!
322
323
  end
data/spec/user_spec.rb CHANGED
@@ -1,71 +1,73 @@
1
- require 'spec_helper'
2
- require 'split/experiment_catalog'
3
- require 'split/experiment'
4
- require 'split/user'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "split/experiment_catalog"
5
+ require "split/experiment"
6
+ require "split/user"
5
7
 
6
8
  describe Split::User do
7
- let(:user_keys) { { 'link_color' => 'blue' } }
8
- let(:context) { double(:session => { split: user_keys }) }
9
- let(:experiment) { Split::Experiment.new('link_color') }
9
+ let(:user_keys) { { "link_color" => "blue" } }
10
+ let(:context) { double(session: { split: user_keys }) }
11
+ let(:experiment) { Split::Experiment.new("link_color") }
10
12
 
11
13
  before(:each) do
12
14
  @subject = described_class.new(context)
13
15
  end
14
16
 
15
- it 'delegates methods correctly' do
16
- expect(@subject['link_color']).to eq(@subject.user['link_color'])
17
+ it "delegates methods correctly" do
18
+ expect(@subject["link_color"]).to eq(@subject.user["link_color"])
17
19
  end
18
20
 
19
- context '#cleanup_old_versions!' do
21
+ context "#cleanup_old_versions!" do
20
22
  let(:experiment_version) { "#{experiment.name}:1" }
21
23
  let(:second_experiment_version) { "#{experiment.name}_another:1" }
22
24
  let(:third_experiment_version) { "variation_of_#{experiment.name}:1" }
23
25
  let(:user_keys) do
24
26
  {
25
- experiment_version => 'blue',
26
- second_experiment_version => 'red',
27
- third_experiment_version => 'yellow'
27
+ experiment_version => "blue",
28
+ second_experiment_version => "red",
29
+ third_experiment_version => "yellow"
28
30
  }
29
31
  end
30
32
 
31
33
  before(:each) { @subject.cleanup_old_versions!(experiment) }
32
34
 
33
- it 'removes key if old experiment is found' do
35
+ it "removes key if old experiment is found" do
34
36
  expect(@subject.keys).not_to include(experiment_version)
35
37
  end
36
38
 
37
- it 'does not remove other keys' do
39
+ it "does not remove other keys" do
38
40
  expect(@subject.keys).to include(second_experiment_version, third_experiment_version)
39
41
  end
40
- end
42
+ end
41
43
 
42
- context '#cleanup_old_experiments!' do
43
- it 'removes key if experiment is not found' do
44
+ context "#cleanup_old_experiments!" do
45
+ it "removes key if experiment is not found" do
44
46
  @subject.cleanup_old_experiments!
45
47
  expect(@subject.keys).to be_empty
46
48
  end
47
49
 
48
- it 'removes key if experiment has a winner' do
49
- allow(Split::ExperimentCatalog).to receive(:find).with('link_color').and_return(experiment)
50
+ it "removes key if experiment has a winner" do
51
+ allow(Split::ExperimentCatalog).to receive(:find).with("link_color").and_return(experiment)
50
52
  allow(experiment).to receive(:start_time).and_return(Date.today)
51
53
  allow(experiment).to receive(:has_winner?).and_return(true)
52
54
  @subject.cleanup_old_experiments!
53
55
  expect(@subject.keys).to be_empty
54
56
  end
55
57
 
56
- it 'removes key if experiment has not started yet' do
57
- allow(Split::ExperimentCatalog).to receive(:find).with('link_color').and_return(experiment)
58
+ it "removes key if experiment has not started yet" do
59
+ allow(Split::ExperimentCatalog).to receive(:find).with("link_color").and_return(experiment)
58
60
  allow(experiment).to receive(:has_winner?).and_return(false)
59
61
  @subject.cleanup_old_experiments!
60
62
  expect(@subject.keys).to be_empty
61
63
  end
62
64
 
63
- context 'with finished key' do
64
- let(:user_keys) { { 'link_color' => 'blue', 'link_color:finished' => true } }
65
+ context "with finished key" do
66
+ let(:user_keys) { { "link_color" => "blue", "link_color:finished" => true } }
65
67
 
66
- it 'does not remove finished key for experiment without a winner' do
67
- allow(Split::ExperimentCatalog).to receive(:find).with('link_color').and_return(experiment)
68
- allow(Split::ExperimentCatalog).to receive(:find).with('link_color:finished').and_return(nil)
68
+ it "does not remove finished key for experiment without a winner" do
69
+ allow(Split::ExperimentCatalog).to receive(:find).with("link_color").and_return(experiment)
70
+ allow(Split::ExperimentCatalog).to receive(:find).with("link_color:finished").and_return(nil)
69
71
  allow(experiment).to receive(:start_time).and_return(Date.today)
70
72
  allow(experiment).to receive(:has_winner?).and_return(false)
71
73
  @subject.cleanup_old_experiments!
@@ -74,33 +76,32 @@ describe Split::User do
74
76
  end
75
77
  end
76
78
 
77
- context 'when already cleaned up' do
79
+ context "when already cleaned up" do
78
80
  before do
79
81
  @subject.cleanup_old_experiments!
80
82
  end
81
83
 
82
- it 'does not clean up again' do
84
+ it "does not clean up again" do
83
85
  expect(@subject).to_not receive(:keys_without_finished)
84
86
  @subject.cleanup_old_experiments!
85
87
  end
86
88
  end
87
89
  end
88
90
 
89
- context 'allows user to be loaded from adapter' do
90
- it 'loads user from adapter (RedisAdapter)' do
91
+ context "allows user to be loaded from adapter" do
92
+ it "loads user from adapter (RedisAdapter)" do
91
93
  user = Split::Persistence::RedisAdapter.new(nil, 112233)
92
- user['foo'] = 'bar'
94
+ user["foo"] = "bar"
93
95
 
94
96
  ab_user = Split::User.find(112233, :redis)
95
97
 
96
- expect(ab_user['foo']).to eql('bar')
98
+ expect(ab_user["foo"]).to eql("bar")
97
99
  end
98
100
 
99
- it 'returns nil if adapter does not implement a finder method' do
101
+ it "returns nil if adapter does not implement a finder method" do
100
102
  ab_user = Split::User.find(112233, :dual_adapter)
101
103
  expect(ab_user).to be_nil
102
104
  end
103
-
104
105
  end
105
106
 
106
107
  context "instantiated with custom adapter" do
@@ -114,5 +115,4 @@ describe Split::User do
114
115
  expect(@subject.user).to eq(custom_adapter)
115
116
  end
116
117
  end
117
-
118
118
  end
data/split.gemspec CHANGED
@@ -9,36 +9,36 @@ Gem::Specification.new do |s|
9
9
  s.version = Split::VERSION
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = ["Andrew Nesbitt"]
12
- s.licenses = ['MIT']
12
+ s.licenses = ["MIT"]
13
13
  s.email = ["andrewnez@gmail.com"]
14
14
  s.homepage = "https://github.com/splitrb/split"
15
15
  s.summary = "Rack based split testing framework"
16
16
 
17
17
  s.metadata = {
18
- "homepage_uri" => "https://github.com/splitrb/split",
19
- "changelog_uri" => "https://github.com/splitrb/split/blob/master/CHANGELOG.md",
20
- "source_code_uri" => "https://github.com/splitrb/split",
21
- "bug_tracker_uri" => "https://github.com/splitrb/split/issues",
22
- "wiki_uri" => "https://github.com/splitrb/split/wiki",
23
- "mailing_list_uri" => "https://groups.google.com/d/forum/split-ruby"
24
- }
18
+ "homepage_uri" => "https://github.com/splitrb/split",
19
+ "changelog_uri" => "https://github.com/splitrb/split/blob/main/CHANGELOG.md",
20
+ "source_code_uri" => "https://github.com/splitrb/split",
21
+ "bug_tracker_uri" => "https://github.com/splitrb/split/issues",
22
+ "wiki_uri" => "https://github.com/splitrb/split/wiki",
23
+ "mailing_list_uri" => "https://groups.google.com/d/forum/split-ruby"
24
+ }
25
25
 
26
- s.required_ruby_version = '>= 2.5.0'
27
- s.required_rubygems_version = '>= 2.0.0'
26
+ s.required_ruby_version = ">= 2.5.0"
27
+ s.required_rubygems_version = ">= 2.0.0"
28
28
 
29
29
  s.files = `git ls-files`.split("\n")
30
30
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
31
  s.require_paths = ["lib"]
32
32
 
33
- s.add_dependency 'redis', '>= 4.2'
34
- s.add_dependency 'sinatra', '>= 1.2.6'
35
- s.add_dependency 'rubystats', '>= 0.3.0'
33
+ s.add_dependency "redis", ">= 4.2"
34
+ s.add_dependency "sinatra", ">= 1.2.6"
35
+ s.add_dependency "rubystats", ">= 0.3.0"
36
36
 
37
- s.add_development_dependency 'bundler', '>= 1.17'
38
- s.add_development_dependency 'simplecov', '~> 0.15'
39
- s.add_development_dependency 'rack-test', '~> 1.1'
40
- s.add_development_dependency 'rake', '~> 13'
41
- s.add_development_dependency 'rspec', '~> 3.7'
42
- s.add_development_dependency 'pry', '~> 0.10'
43
- s.add_development_dependency 'rails', '>= 5.0'
37
+ s.add_development_dependency "bundler", ">= 1.17"
38
+ s.add_development_dependency "simplecov", "~> 0.15"
39
+ s.add_development_dependency "rack-test", "~> 2.0"
40
+ s.add_development_dependency "rake", "~> 13"
41
+ s.add_development_dependency "rspec", "~> 3.7"
42
+ s.add_development_dependency "pry", "~> 0.10"
43
+ s.add_development_dependency "rails", ">= 5.0"
44
44
  end