split 4.0.1 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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