split 4.0.0.pre2 → 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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +14 -1
  3. data/.rubocop.yml +2 -5
  4. data/CHANGELOG.md +26 -2
  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/{5.0.gemfile → 6.1.gemfile} +2 -4
  12. data/gemfiles/{5.1.gemfile → 7.0.gemfile} +3 -4
  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 +9 -10
  73. data/.rubocop_todo.yml +0 -226
  74. data/Appraisals +0 -19
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
3
- require 'time'
2
+
3
+ require "spec_helper"
4
+ require "time"
4
5
 
5
6
  describe Split::Experiment do
6
- def new_experiment(goals=[])
7
- Split::Experiment.new('link_color', :alternatives => ['blue', 'red', 'green'], :goals => goals)
7
+ def new_experiment(goals = [])
8
+ Split::Experiment.new("link_color", alternatives: ["blue", "red", "green"], goals: goals)
8
9
  end
9
10
 
10
11
  def alternative(color)
11
- Split::Alternative.new(color, 'link_color')
12
+ Split::Alternative.new(color, "link_color")
12
13
  end
13
14
 
14
15
  let(:experiment) { new_experiment }
@@ -17,10 +18,10 @@ describe Split::Experiment do
17
18
  let(:green) { alternative("green") }
18
19
 
19
20
  context "with an experiment" do
20
- let(:experiment) { Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"]) }
21
+ let(:experiment) { Split::Experiment.new("basket_text", alternatives: ["Basket", "Cart"]) }
21
22
 
22
23
  it "should have a name" do
23
- expect(experiment.name).to eq('basket_text')
24
+ expect(experiment.name).to eq("basket_text")
24
25
  end
25
26
 
26
27
  it "should have alternatives" do
@@ -28,7 +29,7 @@ describe Split::Experiment do
28
29
  end
29
30
 
30
31
  it "should have alternatives with correct names" do
31
- expect(experiment.alternatives.collect{|a| a.name}).to eq(['Basket', 'Cart'])
32
+ expect(experiment.alternatives.collect { |a| a.name }).to eq(["Basket", "Cart"])
32
33
  end
33
34
 
34
35
  it "should be resettable by default" do
@@ -37,7 +38,7 @@ describe Split::Experiment do
37
38
 
38
39
  it "should save to redis" do
39
40
  experiment.save
40
- expect(Split.redis.exists?('basket_text')).to be true
41
+ expect(Split.redis.exists?("basket_text")).to be true
41
42
  end
42
43
 
43
44
  it "should save the start time to redis" do
@@ -45,14 +46,14 @@ describe Split::Experiment do
45
46
  expect(Time).to receive(:now).and_return(experiment_start_time)
46
47
  experiment.save
47
48
 
48
- expect(Split::ExperimentCatalog.find('basket_text').start_time).to eq(experiment_start_time)
49
+ expect(Split::ExperimentCatalog.find("basket_text").start_time).to eq(experiment_start_time)
49
50
  end
50
51
 
51
52
  it "should not save the start time to redis when start_manually is enabled" do
52
53
  expect(Split.configuration).to receive(:start_manually).and_return(true)
53
54
  experiment.save
54
55
 
55
- expect(Split::ExperimentCatalog.find('basket_text').start_time).to be_nil
56
+ expect(Split::ExperimentCatalog.find("basket_text").start_time).to be_nil
56
57
  end
57
58
 
58
59
  it "should save the selected algorithm to redis" do
@@ -60,16 +61,16 @@ describe Split::Experiment do
60
61
  experiment.algorithm = experiment_algorithm
61
62
  experiment.save
62
63
 
63
- expect(Split::ExperimentCatalog.find('basket_text').algorithm).to eq(experiment_algorithm)
64
+ expect(Split::ExperimentCatalog.find("basket_text").algorithm).to eq(experiment_algorithm)
64
65
  end
65
66
 
66
67
  it "should handle having a start time stored as a string" do
67
68
  experiment_start_time = Time.parse("Sat Mar 03 14:01:03")
68
69
  expect(Time).to receive(:now).twice.and_return(experiment_start_time)
69
70
  experiment.save
70
- Split.redis.hset(:experiment_start_times, experiment.name, experiment_start_time)
71
+ Split.redis.hset(:experiment_start_times, experiment.name, experiment_start_time.to_s)
71
72
 
72
- expect(Split::ExperimentCatalog.find('basket_text').start_time).to eq(experiment_start_time)
73
+ expect(Split::ExperimentCatalog.find("basket_text").start_time).to eq(experiment_start_time)
73
74
  end
74
75
 
75
76
  it "should handle not having a start time" do
@@ -79,17 +80,17 @@ describe Split::Experiment do
79
80
 
80
81
  Split.redis.hdel(:experiment_start_times, experiment.name)
81
82
 
82
- expect(Split::ExperimentCatalog.find('basket_text').start_time).to be_nil
83
+ expect(Split::ExperimentCatalog.find("basket_text").start_time).to be_nil
83
84
  end
84
85
 
85
86
  it "should not create duplicates when saving multiple times" do
86
87
  experiment.save
87
88
  experiment.save
88
- expect(Split.redis.exists?('basket_text')).to be true
89
- expect(Split.redis.lrange('basket_text', 0, -1)).to eq(['{"Basket":1}', '{"Cart":1}'])
89
+ expect(Split.redis.exists?("basket_text")).to be true
90
+ expect(Split.redis.lrange("basket_text", 0, -1)).to eq(['{"Basket":1}', '{"Cart":1}'])
90
91
  end
91
92
 
92
- describe 'new record?' do
93
+ describe "new record?" do
93
94
  it "should know if it hasn't been saved yet" do
94
95
  expect(experiment.new_record?).to be_truthy
95
96
  end
@@ -100,58 +101,56 @@ describe Split::Experiment do
100
101
  end
101
102
  end
102
103
 
103
- describe 'control' do
104
- it 'should be the first alternative' do
104
+ describe "control" do
105
+ it "should be the first alternative" do
105
106
  experiment.save
106
- expect(experiment.control.name).to eq('Basket')
107
+ expect(experiment.control.name).to eq("Basket")
107
108
  end
108
109
  end
109
110
  end
110
111
 
111
- describe 'initialization' do
112
+ describe "initialization" do
112
113
  it "should set the algorithm when passed as an option to the initializer" do
113
- experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :algorithm => Split::Algorithms::Whiplash)
114
- expect(experiment.algorithm).to eq(Split::Algorithms::Whiplash)
114
+ experiment = Split::Experiment.new("basket_text", alternatives: ["Basket", "Cart"], algorithm: Split::Algorithms::Whiplash)
115
+ expect(experiment.algorithm).to eq(Split::Algorithms::Whiplash)
115
116
  end
116
117
 
117
118
  it "should be possible to make an experiment not resettable" do
118
- experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :resettable => false)
119
+ experiment = Split::Experiment.new("basket_text", alternatives: ["Basket", "Cart"], resettable: false)
119
120
  expect(experiment.resettable).to be_falsey
120
121
  end
121
122
 
122
- context 'from configuration' do
123
+ context "from configuration" do
123
124
  let(:experiment_name) { :my_experiment }
124
125
  let(:experiments) do
125
126
  {
126
127
  experiment_name => {
127
- :alternatives => ['Control Opt', 'Alt one']
128
+ alternatives: ["Control Opt", "Alt one"]
128
129
  }
129
130
  }
130
131
  end
131
132
 
132
133
  before { Split.configuration.experiments = experiments }
133
134
 
134
- it 'assigns default values to the experiment' do
135
+ it "assigns default values to the experiment" do
135
136
  expect(Split::Experiment.new(experiment_name).resettable).to eq(true)
136
137
  end
137
138
  end
138
139
  end
139
140
 
140
- describe 'persistent configuration' do
141
-
141
+ describe "persistent configuration" do
142
142
  it "should persist resettable in redis" do
143
- experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :resettable => false)
143
+ experiment = Split::Experiment.new("basket_text", alternatives: ["Basket", "Cart"], resettable: false)
144
144
  experiment.save
145
145
 
146
- e = Split::ExperimentCatalog.find('basket_text')
146
+ e = Split::ExperimentCatalog.find("basket_text")
147
147
  expect(e).to eq(experiment)
148
148
  expect(e.resettable).to be_falsey
149
-
150
149
  end
151
150
 
152
- describe '#metadata' do
153
- let(:experiment) { Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :algorithm => Split::Algorithms::Whiplash, :metadata => meta) }
154
- let(:meta) { { a: 'b' }}
151
+ describe "#metadata" do
152
+ let(:experiment) { Split::Experiment.new("basket_text", alternatives: ["Basket", "Cart"], algorithm: Split::Algorithms::Whiplash, metadata: meta) }
153
+ let(:meta) { { a: "b" } }
155
154
 
156
155
  before do
157
156
  experiment.save
@@ -164,20 +163,20 @@ describe Split::Experiment do
164
163
  expect(Split.redis.exists?(experiment.metadata_key)).to be_falsey
165
164
  end
166
165
 
167
- context 'simple hash' do
168
- let(:meta) { { 'basket' => 'a', 'cart' => 'b' } }
166
+ context "simple hash" do
167
+ let(:meta) { { "basket" => "a", "cart" => "b" } }
169
168
 
170
169
  it "should persist metadata in redis" do
171
- e = Split::ExperimentCatalog.find('basket_text')
170
+ e = Split::ExperimentCatalog.find("basket_text")
172
171
  expect(e).to eq(experiment)
173
172
  expect(e.metadata).to eq(meta)
174
173
  end
175
174
  end
176
175
 
177
- context 'nested hash' do
178
- let(:meta) { { 'basket' => { 'one' => 'two' }, 'cart' => 'b' } }
176
+ context "nested hash" do
177
+ let(:meta) { { "basket" => { "one" => "two" }, "cart" => "b" } }
179
178
  it "should persist metadata in redis" do
180
- e = Split::ExperimentCatalog.find('basket_text')
179
+ e = Split::ExperimentCatalog.find("basket_text")
181
180
  expect(e).to eq(experiment)
182
181
  expect(e.metadata).to eq(meta)
183
182
  end
@@ -185,32 +184,32 @@ describe Split::Experiment do
185
184
  end
186
185
 
187
186
  it "should persist algorithm in redis" do
188
- experiment = Split::Experiment.new('basket_text', :alternatives => ['Basket', "Cart"], :algorithm => Split::Algorithms::Whiplash)
187
+ experiment = Split::Experiment.new("basket_text", alternatives: ["Basket", "Cart"], algorithm: Split::Algorithms::Whiplash)
189
188
  experiment.save
190
189
 
191
- e = Split::ExperimentCatalog.find('basket_text')
190
+ e = Split::ExperimentCatalog.find("basket_text")
192
191
  expect(e).to eq(experiment)
193
192
  expect(e.algorithm).to eq(Split::Algorithms::Whiplash)
194
193
  end
195
194
 
196
195
  it "should persist a new experiment in redis, that does not exist in the configuration file" do
197
- experiment = Split::Experiment.new('foobar', :alternatives => ['tra', 'la'], :algorithm => Split::Algorithms::Whiplash)
196
+ experiment = Split::Experiment.new("foobar", alternatives: ["tra", "la"], algorithm: Split::Algorithms::Whiplash)
198
197
  experiment.save
199
198
 
200
- e = Split::ExperimentCatalog.find('foobar')
199
+ e = Split::ExperimentCatalog.find("foobar")
201
200
  expect(e).to eq(experiment)
202
- expect(e.alternatives.collect{|a| a.name}).to eq(['tra', 'la'])
201
+ expect(e.alternatives.collect { |a| a.name }).to eq(["tra", "la"])
203
202
  end
204
203
  end
205
204
 
206
- describe 'deleting' do
207
- it 'should delete itself' do
208
- experiment = Split::Experiment.new('basket_text', :alternatives => [ 'Basket', "Cart"])
205
+ describe "deleting" do
206
+ it "should delete itself" do
207
+ experiment = Split::Experiment.new("basket_text", alternatives: [ "Basket", "Cart"])
209
208
  experiment.save
210
209
 
211
210
  experiment.delete
212
- expect(Split.redis.exists?('link_color')).to be false
213
- expect(Split::ExperimentCatalog.find('link_color')).to be_nil
211
+ expect(Split.redis.exists?("link_color")).to be false
212
+ expect(Split::ExperimentCatalog.find("link_color")).to be_nil
214
213
  end
215
214
 
216
215
  it "should increment the version" do
@@ -229,7 +228,7 @@ describe Split::Experiment do
229
228
  experiment.delete
230
229
  end
231
230
 
232
- it 'should reset the start time if the experiment should be manually started' do
231
+ it "should reset the start time if the experiment should be manually started" do
233
232
  Split.configuration.start_manually = true
234
233
  experiment.start
235
234
  experiment.delete
@@ -244,75 +243,75 @@ describe Split::Experiment do
244
243
  end
245
244
  end
246
245
 
247
- describe 'winner' do
246
+ describe "winner" do
248
247
  it "should have no winner initially" do
249
248
  expect(experiment.winner).to be_nil
250
249
  end
251
250
  end
252
251
 
253
- describe 'winner=' do
254
- it 'should allow you to specify a winner' do
252
+ describe "winner=" do
253
+ it "should allow you to specify a winner" do
255
254
  experiment.save
256
- experiment.winner = 'red'
257
- expect(experiment.winner.name).to eq('red')
255
+ experiment.winner = "red"
256
+ expect(experiment.winner.name).to eq("red")
258
257
  end
259
258
 
260
- it 'should call the on_experiment_winner_choose hook' do
259
+ it "should call the on_experiment_winner_choose hook" do
261
260
  expect(Split.configuration.on_experiment_winner_choose).to receive(:call)
262
- experiment.winner = 'green'
261
+ experiment.winner = "green"
263
262
  end
264
263
 
265
- context 'when has_winner state is memoized' do
264
+ context "when has_winner state is memoized" do
266
265
  before { expect(experiment).to_not have_winner }
267
266
 
268
- it 'should keep has_winner state consistent' do
269
- experiment.winner = 'red'
267
+ it "should keep has_winner state consistent" do
268
+ experiment.winner = "red"
270
269
  expect(experiment).to have_winner
271
270
  end
272
271
  end
273
272
  end
274
273
 
275
- describe 'reset_winner' do
276
- before { experiment.winner = 'green' }
274
+ describe "reset_winner" do
275
+ before { experiment.winner = "green" }
277
276
 
278
- it 'should reset the winner' do
277
+ it "should reset the winner" do
279
278
  experiment.reset_winner
280
279
  expect(experiment.winner).to be_nil
281
280
  end
282
281
 
283
- context 'when has_winner state is memoized' do
282
+ context "when has_winner state is memoized" do
284
283
  before { expect(experiment).to have_winner }
285
284
 
286
- it 'should keep has_winner state consistent' do
285
+ it "should keep has_winner state consistent" do
287
286
  experiment.reset_winner
288
287
  expect(experiment).to_not have_winner
289
288
  end
290
289
  end
291
290
  end
292
291
 
293
- describe 'has_winner?' do
294
- context 'with winner' do
295
- before { experiment.winner = 'red' }
292
+ describe "has_winner?" do
293
+ context "with winner" do
294
+ before { experiment.winner = "red" }
296
295
 
297
- it 'returns true' do
296
+ it "returns true" do
298
297
  expect(experiment).to have_winner
299
298
  end
300
299
  end
301
300
 
302
- context 'without winner' do
303
- it 'returns false' do
301
+ context "without winner" do
302
+ it "returns false" do
304
303
  expect(experiment).to_not have_winner
305
304
  end
306
305
  end
307
306
 
308
- it 'memoizes has_winner state' do
307
+ it "memoizes has_winner state" do
309
308
  expect(experiment).to receive(:winner).once
310
309
  expect(experiment).to_not have_winner
311
310
  expect(experiment).to_not have_winner
312
311
  end
313
312
  end
314
313
 
315
- describe 'reset' do
314
+ describe "reset" do
316
315
  let(:reset_manually) { false }
317
316
 
318
317
  before do
@@ -322,10 +321,10 @@ describe Split::Experiment do
322
321
  green.increment_participation
323
322
  end
324
323
 
325
- it 'should reset all alternatives' do
326
- experiment.winner = 'green'
324
+ it "should reset all alternatives" do
325
+ experiment.winner = "green"
327
326
 
328
- expect(experiment.next_alternative.name).to eq('green')
327
+ expect(experiment.next_alternative.name).to eq("green")
329
328
  green.increment_participation
330
329
 
331
330
  experiment.reset
@@ -334,10 +333,10 @@ describe Split::Experiment do
334
333
  expect(green.completed_count).to eq(0)
335
334
  end
336
335
 
337
- it 'should reset the winner' do
338
- experiment.winner = 'green'
336
+ it "should reset the winner" do
337
+ experiment.winner = "green"
339
338
 
340
- expect(experiment.next_alternative.name).to eq('green')
339
+ expect(experiment.next_alternative.name).to eq("green")
341
340
  green.increment_participation
342
341
 
343
342
  experiment.reset
@@ -362,50 +361,50 @@ describe Split::Experiment do
362
361
  end
363
362
  end
364
363
 
365
- describe 'algorithm' do
366
- let(:experiment) { Split::ExperimentCatalog.find_or_create('link_color', 'blue', 'red', 'green') }
364
+ describe "algorithm" do
365
+ let(:experiment) { Split::ExperimentCatalog.find_or_create("link_color", "blue", "red", "green") }
367
366
 
368
- it 'should use the default algorithm if none is specified' do
367
+ it "should use the default algorithm if none is specified" do
369
368
  expect(experiment.algorithm).to eq(Split.configuration.algorithm)
370
369
  end
371
370
 
372
- it 'should use the user specified algorithm for this experiment if specified' do
371
+ it "should use the user specified algorithm for this experiment if specified" do
373
372
  experiment.algorithm = Split::Algorithms::Whiplash
374
373
  expect(experiment.algorithm).to eq(Split::Algorithms::Whiplash)
375
374
  end
376
375
  end
377
376
 
378
- describe '#next_alternative' do
379
- context 'with multiple alternatives' do
380
- let(:experiment) { Split::ExperimentCatalog.find_or_create('link_color', 'blue', 'red', 'green') }
377
+ describe "#next_alternative" do
378
+ context "with multiple alternatives" do
379
+ let(:experiment) { Split::ExperimentCatalog.find_or_create("link_color", "blue", "red", "green") }
381
380
 
382
- context 'with winner' do
381
+ context "with winner" do
383
382
  it "should always return the winner" do
384
- green = Split::Alternative.new('green', 'link_color')
385
- experiment.winner = 'green'
383
+ green = Split::Alternative.new("green", "link_color")
384
+ experiment.winner = "green"
386
385
 
387
- expect(experiment.next_alternative.name).to eq('green')
386
+ expect(experiment.next_alternative.name).to eq("green")
388
387
  green.increment_participation
389
388
 
390
- expect(experiment.next_alternative.name).to eq('green')
389
+ expect(experiment.next_alternative.name).to eq("green")
391
390
  end
392
391
  end
393
392
 
394
- context 'without winner' do
393
+ context "without winner" do
395
394
  it "should use the specified algorithm" do
396
395
  experiment.algorithm = Split::Algorithms::Whiplash
397
- expect(experiment.algorithm).to receive(:choose_alternative).and_return(Split::Alternative.new('green', 'link_color'))
398
- expect(experiment.next_alternative.name).to eq('green')
396
+ expect(experiment.algorithm).to receive(:choose_alternative).and_return(Split::Alternative.new("green", "link_color"))
397
+ expect(experiment.next_alternative.name).to eq("green")
399
398
  end
400
399
  end
401
400
  end
402
401
 
403
- context 'with single alternative' do
404
- let(:experiment) { Split::ExperimentCatalog.find_or_create('link_color', 'blue') }
402
+ context "with single alternative" do
403
+ let(:experiment) { Split::ExperimentCatalog.find_or_create("link_color", "blue") }
405
404
 
406
405
  it "should always return the only alternative" do
407
- expect(experiment.next_alternative.name).to eq('blue')
408
- expect(experiment.next_alternative.name).to eq('blue')
406
+ expect(experiment.next_alternative.name).to eq("blue")
407
+ expect(experiment.next_alternative.name).to eq("blue")
409
408
  end
410
409
  end
411
410
  end
@@ -426,16 +425,16 @@ describe Split::Experiment do
426
425
  end
427
426
  end
428
427
 
429
- describe 'changing an existing experiment' do
428
+ describe "changing an existing experiment" do
430
429
  def same_but_different_alternative
431
- Split::ExperimentCatalog.find_or_create('link_color', 'blue', 'yellow', 'orange')
430
+ Split::ExperimentCatalog.find_or_create("link_color", "blue", "yellow", "orange")
432
431
  end
433
432
 
434
433
  it "should reset an experiment if it is loaded with different alternatives" do
435
434
  experiment.save
436
435
  blue.participant_count = 5
437
436
  same_experiment = same_but_different_alternative
438
- expect(same_experiment.alternatives.map(&:name)).to eq(['blue', 'yellow', 'orange'])
437
+ expect(same_experiment.alternatives.map(&:name)).to eq(["blue", "yellow", "orange"])
439
438
  expect(blue.participant_count).to eq(0)
440
439
  end
441
440
 
@@ -451,7 +450,7 @@ describe Split::Experiment do
451
450
  context "when metadata is changed" do
452
451
  it "should increase version" do
453
452
  experiment.save
454
- experiment.metadata = { 'foo' => 'bar' }
453
+ experiment.metadata = { "foo" => "bar" }
455
454
 
456
455
  expect { experiment.save }.to change { experiment.version }.by(1)
457
456
  end
@@ -463,7 +462,7 @@ describe Split::Experiment do
463
462
  end
464
463
  end
465
464
 
466
- context 'when experiment configuration is changed' do
465
+ context "when experiment configuration is changed" do
467
466
  let(:reset_manually) { false }
468
467
 
469
468
  before do
@@ -476,15 +475,15 @@ describe Split::Experiment do
476
475
  experiment.save
477
476
  end
478
477
 
479
- it 'resets all alternatives' do
478
+ it "resets all alternatives" do
480
479
  expect(green.participant_count).to eq(0)
481
480
  expect(green.completed_count).to eq(0)
482
481
  end
483
482
 
484
- context 'when reset_manually is set' do
483
+ context "when reset_manually is set" do
485
484
  let(:reset_manually) { true }
486
485
 
487
- it 'does not reset alternatives' do
486
+ it "does not reset alternatives" do
488
487
  expect(green.participant_count).to eq(2)
489
488
  expect(green.completed_count).to eq(0)
490
489
  end
@@ -492,16 +491,16 @@ describe Split::Experiment do
492
491
  end
493
492
  end
494
493
 
495
- describe 'alternatives passed as non-strings' do
494
+ describe "alternatives passed as non-strings" do
496
495
  it "should throw an exception if an alternative is passed that is not a string" do
497
- expect(lambda { Split::ExperimentCatalog.find_or_create('link_color', :blue, :red) }).to raise_error(ArgumentError)
498
- expect(lambda { Split::ExperimentCatalog.find_or_create('link_enabled', true, false) }).to raise_error(ArgumentError)
496
+ expect { Split::ExperimentCatalog.find_or_create("link_color", :blue, :red) }.to raise_error(ArgumentError)
497
+ expect { Split::ExperimentCatalog.find_or_create("link_enabled", true, false) }.to raise_error(ArgumentError)
499
498
  end
500
499
  end
501
500
 
502
- describe 'specifying weights' do
501
+ describe "specifying weights" do
503
502
  let(:experiment_with_weight) {
504
- Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 2 })
503
+ Split::ExperimentCatalog.find_or_create("link_color", { "blue" => 1 }, { "red" => 2 })
505
504
  }
506
505
 
507
506
  it "should work for a new experiment" do
@@ -520,7 +519,7 @@ describe Split::Experiment do
520
519
  }
521
520
 
522
521
  context "saving experiment" do
523
- let(:same_but_different_goals) { Split::ExperimentCatalog.find_or_create({'link_color' => ["purchase", "refund"]}, 'blue', 'red', 'green') }
522
+ let(:same_but_different_goals) { Split::ExperimentCatalog.find_or_create({ "link_color" => ["purchase", "refund"] }, "blue", "red", "green") }
524
523
 
525
524
  before { experiment.save }
526
525
 
@@ -532,7 +531,6 @@ describe Split::Experiment do
532
531
  same_but_different_goals
533
532
  expect(Split::ExperimentCatalog.find("link_color").goals).to eq(["purchase", "refund"])
534
533
  end
535
-
536
534
  end
537
535
 
538
536
  it "should have goals" do
@@ -541,9 +539,9 @@ describe Split::Experiment do
541
539
 
542
540
  context "find or create experiment" do
543
541
  it "should have correct goals" do
544
- experiment = Split::ExperimentCatalog.find_or_create({'link_color3' => ["purchase", "refund"]}, 'blue', 'red', 'green')
542
+ experiment = Split::ExperimentCatalog.find_or_create({ "link_color3" => ["purchase", "refund"] }, "blue", "red", "green")
545
543
  expect(experiment.goals).to eq(["purchase", "refund"])
546
- experiment = Split::ExperimentCatalog.find_or_create('link_color3', 'blue', 'red', 'green')
544
+ experiment = Split::ExperimentCatalog.find_or_create("link_color3", "blue", "red", "green")
547
545
  expect(experiment.goals).to eq([])
548
546
  end
549
547
  end
@@ -551,19 +549,19 @@ describe Split::Experiment do
551
549
 
552
550
  describe "beta probability calculation" do
553
551
  it "should return a hash with the probability of each alternative being the best" do
554
- experiment = Split::ExperimentCatalog.find_or_create('mathematicians', 'bernoulli', 'poisson', 'lagrange')
552
+ experiment = Split::ExperimentCatalog.find_or_create("mathematicians", "bernoulli", "poisson", "lagrange")
555
553
  experiment.calc_winning_alternatives
556
554
  expect(experiment.alternative_probabilities).not_to be_nil
557
555
  end
558
556
 
559
557
  it "should return between 46% and 54% probability for an experiment with 2 alternatives and no data" do
560
- experiment = Split::ExperimentCatalog.find_or_create('scientists', 'einstein', 'bohr')
558
+ experiment = Split::ExperimentCatalog.find_or_create("scientists", "einstein", "bohr")
561
559
  experiment.calc_winning_alternatives
562
560
  expect(experiment.alternatives[0].p_winner).to be_within(0.04).of(0.50)
563
561
  end
564
562
 
565
- it "should calculate the probability of being the winning alternative separately for each goal", :skip => true do
566
- experiment = Split::ExperimentCatalog.find_or_create({'link_color3' => ["purchase", "refund"]}, 'blue', 'red', 'green')
563
+ it "should calculate the probability of being the winning alternative separately for each goal", skip: true do
564
+ experiment = Split::ExperimentCatalog.find_or_create({ "link_color3" => ["purchase", "refund"] }, "blue", "red", "green")
567
565
  goal1 = experiment.goals[0]
568
566
  goal2 = experiment.goals[1]
569
567
  experiment.alternatives.each do |alternative|
@@ -579,7 +577,7 @@ describe Split::Experiment do
579
577
  end
580
578
 
581
579
  it "should return nil and not re-calculate probabilities if they have already been calculated today" do
582
- experiment = Split::ExperimentCatalog.find_or_create({'link_color3' => ["purchase", "refund"]}, 'blue', 'red', 'green')
580
+ experiment = Split::ExperimentCatalog.find_or_create({ "link_color3" => ["purchase", "refund"] }, "blue", "red", "green")
583
581
  expect(experiment.calc_winning_alternatives).not_to be nil
584
582
  expect(experiment.calc_winning_alternatives).to be nil
585
583
  end