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
data/lib/split.rb CHANGED
@@ -1,29 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'redis'
3
+ require "redis"
4
4
 
5
- require 'split/algorithms/block_randomization'
6
- require 'split/algorithms/weighted_sample'
7
- require 'split/algorithms/whiplash'
8
- require 'split/alternative'
9
- require 'split/cache'
10
- require 'split/configuration'
11
- require 'split/encapsulated_helper'
12
- require 'split/exceptions'
13
- require 'split/experiment'
14
- require 'split/experiment_catalog'
15
- require 'split/extensions/string'
16
- require 'split/goals_collection'
17
- require 'split/helper'
18
- require 'split/combined_experiments_helper'
19
- require 'split/metric'
20
- require 'split/persistence'
21
- require 'split/redis_interface'
22
- require 'split/trial'
23
- require 'split/user'
24
- require 'split/version'
25
- require 'split/zscore'
26
- require 'split/engine' if defined?(Rails)
5
+ require "split/algorithms"
6
+ require "split/algorithms/block_randomization"
7
+ require "split/algorithms/weighted_sample"
8
+ require "split/algorithms/whiplash"
9
+ require "split/alternative"
10
+ require "split/cache"
11
+ require "split/configuration"
12
+ require "split/encapsulated_helper"
13
+ require "split/exceptions"
14
+ require "split/experiment"
15
+ require "split/experiment_catalog"
16
+ require "split/extensions/string"
17
+ require "split/goals_collection"
18
+ require "split/helper"
19
+ require "split/combined_experiments_helper"
20
+ require "split/metric"
21
+ require "split/persistence"
22
+ require "split/redis_interface"
23
+ require "split/trial"
24
+ require "split/user"
25
+ require "split/version"
26
+ require "split/zscore"
27
+ require "split/engine" if defined?(Rails)
27
28
 
28
29
  module Split
29
30
  extend self
@@ -75,8 +76,8 @@ end
75
76
  # Check to see if being run in a Rails application. If so, wait until before_initialize to run configuration so Gems that create ENV variables have the chance to initialize first.
76
77
  if defined?(::Rails)
77
78
  class Split::Railtie < Rails::Railtie
78
- config.before_initialize { Split.configure {} }
79
+ config.before_initialize { Split.configure { } }
79
80
  end
80
81
  else
81
- Split.configure {}
82
+ Split.configure { }
82
83
  end
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
2
4
 
3
5
  describe Split::Algorithms::BlockRandomization do
4
-
5
- let(:experiment) { Split::Experiment.new 'experiment' }
6
- let(:alternative_A) { Split::Alternative.new 'A', 'experiment' }
7
- let(:alternative_B) { Split::Alternative.new 'B', 'experiment' }
8
- let(:alternative_C) { Split::Alternative.new 'C', 'experiment' }
6
+ let(:experiment) { Split::Experiment.new "experiment" }
7
+ let(:alternative_A) { Split::Alternative.new "A", "experiment" }
8
+ let(:alternative_B) { Split::Alternative.new "B", "experiment" }
9
+ let(:alternative_C) { Split::Alternative.new "C", "experiment" }
9
10
 
10
11
  before :each do
11
12
  allow(experiment).to receive(:alternatives) { [alternative_A, alternative_B, alternative_C] }
@@ -1,19 +1,20 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "spec_helper"
3
4
 
4
5
  describe Split::Algorithms::WeightedSample do
5
6
  it "should return an alternative" do
6
- experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 100}, {'red' => 0 })
7
+ experiment = Split::ExperimentCatalog.find_or_create("link_color", { "blue" => 100 }, { "red" => 0 })
7
8
  expect(Split::Algorithms::WeightedSample.choose_alternative(experiment).class).to eq(Split::Alternative)
8
9
  end
9
10
 
10
11
  it "should always return a heavily weighted option" do
11
- experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 100}, {'red' => 0 })
12
- expect(Split::Algorithms::WeightedSample.choose_alternative(experiment).name).to eq('blue')
12
+ experiment = Split::ExperimentCatalog.find_or_create("link_color", { "blue" => 100 }, { "red" => 0 })
13
+ expect(Split::Algorithms::WeightedSample.choose_alternative(experiment).name).to eq("blue")
13
14
  end
14
15
 
15
16
  it "should return one of the results" do
16
- experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 1 })
17
- expect(['red', 'blue']).to include Split::Algorithms::WeightedSample.choose_alternative(experiment).name
17
+ experiment = Split::ExperimentCatalog.find_or_create("link_color", { "blue" => 1 }, { "red" => 1 })
18
+ expect(["red", "blue"]).to include Split::Algorithms::WeightedSample.choose_alternative(experiment).name
18
19
  end
19
20
  end
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "spec_helper"
3
4
 
4
5
  describe Split::Algorithms::Whiplash do
5
-
6
6
  it "should return an algorithm" do
7
- experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 1 })
7
+ experiment = Split::ExperimentCatalog.find_or_create("link_color", { "blue" => 1 }, { "red" => 1 })
8
8
  expect(Split::Algorithms::Whiplash.choose_alternative(experiment).class).to eq(Split::Alternative)
9
9
  end
10
10
 
11
11
  it "should return one of the results" do
12
- experiment = Split::ExperimentCatalog.find_or_create('link_color', {'blue' => 1}, {'red' => 1 })
13
- expect(['red', 'blue']).to include Split::Algorithms::Whiplash.choose_alternative(experiment).name
12
+ experiment = Split::ExperimentCatalog.find_or_create("link_color", { "blue" => 1 }, { "red" => 1 })
13
+ expect(["red", "blue"]).to include Split::Algorithms::Whiplash.choose_alternative(experiment).name
14
14
  end
15
15
 
16
16
  it "should guess floats" do
@@ -20,5 +20,4 @@ describe Split::Algorithms::Whiplash do
20
20
  expect(Split::Algorithms::Whiplash.send(:arm_guess, 1000, 5).class).to eq(Float)
21
21
  expect(Split::Algorithms::Whiplash.send(:arm_guess, 10, -2).class).to eq(Float)
22
22
  end
23
-
24
23
  end
@@ -1,19 +1,19 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
3
- require 'split/alternative'
4
2
 
5
- describe Split::Alternative do
3
+ require "spec_helper"
4
+ require "split/alternative"
6
5
 
6
+ describe Split::Alternative do
7
7
  let(:alternative) {
8
- Split::Alternative.new('Basket', 'basket_text')
8
+ Split::Alternative.new("Basket", "basket_text")
9
9
  }
10
10
 
11
11
  let(:alternative2) {
12
- Split::Alternative.new('Cart', 'basket_text')
12
+ Split::Alternative.new("Cart", "basket_text")
13
13
  }
14
14
 
15
15
  let!(:experiment) {
16
- Split::ExperimentCatalog.find_or_create({"basket_text" => ["purchase", "refund"]}, "Basket", "Cart")
16
+ Split::ExperimentCatalog.find_or_create({ "basket_text" => ["purchase", "refund"] }, "Basket", "Cart")
17
17
  }
18
18
 
19
19
  let(:goal1) { "purchase" }
@@ -24,48 +24,48 @@ describe Split::Alternative do
24
24
  end
25
25
 
26
26
  it "should have and only return the name" do
27
- expect(alternative.name).to eq('Basket')
27
+ expect(alternative.name).to eq("Basket")
28
28
  end
29
29
 
30
- describe 'weights' do
30
+ describe "weights" do
31
31
  it "should set the weights" do
32
- experiment = Split::Experiment.new('basket_text', :alternatives => [{'Basket' => 0.6}, {"Cart" => 0.4}])
32
+ experiment = Split::Experiment.new("basket_text", alternatives: [{ "Basket" => 0.6 }, { "Cart" => 0.4 }])
33
33
  first = experiment.alternatives[0]
34
- expect(first.name).to eq('Basket')
34
+ expect(first.name).to eq("Basket")
35
35
  expect(first.weight).to eq(0.6)
36
36
 
37
37
  second = experiment.alternatives[1]
38
- expect(second.name).to eq('Cart')
38
+ expect(second.name).to eq("Cart")
39
39
  expect(second.weight).to eq(0.4)
40
40
  end
41
41
 
42
42
  it "accepts probability on alternatives" do
43
43
  Split.configuration.experiments = {
44
- :my_experiment => {
45
- :alternatives => [
46
- { :name => "control_opt", :percent => 67 },
47
- { :name => "second_opt", :percent => 10 },
48
- { :name => "third_opt", :percent => 23 },
44
+ my_experiment: {
45
+ alternatives: [
46
+ { name: "control_opt", percent: 67 },
47
+ { name: "second_opt", percent: 10 },
48
+ { name: "third_opt", percent: 23 },
49
49
  ]
50
50
  }
51
51
  }
52
52
  experiment = Split::Experiment.new(:my_experiment)
53
53
  first = experiment.alternatives[0]
54
- expect(first.name).to eq('control_opt')
54
+ expect(first.name).to eq("control_opt")
55
55
  expect(first.weight).to eq(0.67)
56
56
 
57
57
  second = experiment.alternatives[1]
58
- expect(second.name).to eq('second_opt')
58
+ expect(second.name).to eq("second_opt")
59
59
  expect(second.weight).to eq(0.1)
60
60
  end
61
61
 
62
62
  it "accepts probability on some alternatives" do
63
63
  Split.configuration.experiments = {
64
- :my_experiment => {
65
- :alternatives => [
66
- { :name => "control_opt", :percent => 34 },
64
+ my_experiment: {
65
+ alternatives: [
66
+ { name: "control_opt", percent: 34 },
67
67
  "second_opt",
68
- { :name => "third_opt", :percent => 23 },
68
+ { name: "third_opt", percent: 23 },
69
69
  "fourth_opt",
70
70
  ],
71
71
  }
@@ -87,11 +87,11 @@ describe Split::Alternative do
87
87
  #
88
88
  it "allows name param without probability" do
89
89
  Split.configuration.experiments = {
90
- :my_experiment => {
91
- :alternatives => [
92
- { :name => "control_opt" },
90
+ my_experiment: {
91
+ alternatives: [
92
+ { name: "control_opt" },
93
93
  "second_opt",
94
- { :name => "third_opt", :percent => 64 },
94
+ { name: "third_opt", percent: 64 },
95
95
  ],
96
96
  }
97
97
  }
@@ -126,7 +126,7 @@ describe Split::Alternative do
126
126
 
127
127
  it "should save to redis" do
128
128
  alternative.save
129
- expect(Split.redis.exists?('basket_text:Basket')).to be true
129
+ expect(Split.redis.exists?("basket_text:Basket")).to be true
130
130
  end
131
131
 
132
132
  it "should increment participation count" do
@@ -166,7 +166,7 @@ describe Split::Alternative do
166
166
  expect(alternative2.control?).to be_falsey
167
167
  end
168
168
 
169
- describe 'unfinished_count' do
169
+ describe "unfinished_count" do
170
170
  it "should be difference between participant and completed counts" do
171
171
  alternative.increment_participation
172
172
  expect(alternative.unfinished_count).to eq(alternative.participant_count)
@@ -182,7 +182,7 @@ describe Split::Alternative do
182
182
  end
183
183
  end
184
184
 
185
- describe 'conversion rate' do
185
+ describe "conversion rate" do
186
186
  it "should be 0 if there are no conversions" do
187
187
  expect(alternative.completed_count).to eq(0)
188
188
  expect(alternative.conversion_rate).to eq(0)
@@ -225,8 +225,7 @@ describe Split::Alternative do
225
225
  end
226
226
  end
227
227
 
228
- describe 'z score' do
229
-
228
+ describe "z score" do
230
229
  it "should return an error string when the control has 0 people" do
231
230
  expect(alternative2.z_score).to eq("Needs 30+ participants.")
232
231
  expect(alternative2.z_score(goal1)).to eq("Needs 30+ participants.")
@@ -269,9 +268,9 @@ describe Split::Alternative do
269
268
 
270
269
  it "should be N/A for the control" do
271
270
  control = experiment.control
272
- expect(control.z_score).to eq('N/A')
273
- expect(control.z_score(goal1)).to eq('N/A')
274
- expect(control.z_score(goal2)).to eq('N/A')
271
+ expect(control.z_score).to eq("N/A")
272
+ expect(control.z_score(goal1)).to eq("N/A")
273
+ expect(control.z_score(goal2)).to eq("N/A")
275
274
  end
276
275
 
277
276
  it "should not blow up for Conversion Rates > 1" do
@@ -289,8 +288,8 @@ describe Split::Alternative do
289
288
 
290
289
  describe "extra_info" do
291
290
  it "reads saved value of recorded_info in redis" do
292
- saved_recorded_info = {"key_1" => 1, "key_2" => "2"}
293
- Split.redis.hset "#{alternative.experiment_name}:#{alternative.name}", 'recorded_info', saved_recorded_info.to_json
291
+ saved_recorded_info = { "key_1" => 1, "key_2" => "2" }
292
+ Split.redis.hset "#{alternative.experiment_name}:#{alternative.name}", "recorded_info", saved_recorded_info.to_json
294
293
  extra_info = alternative.extra_info
295
294
 
296
295
  expect(extra_info).to eql(saved_recorded_info)
data/spec/cache_spec.rb CHANGED
@@ -1,19 +1,18 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
3
2
 
4
- describe Split::Cache do
3
+ require "spec_helper"
5
4
 
5
+ describe Split::Cache do
6
6
  let(:namespace) { :test_namespace }
7
7
  let(:key) { :test_key }
8
8
  let(:now) { 1606189017 }
9
9
 
10
10
  before { allow(Time).to receive(:now).and_return(now) }
11
11
 
12
- describe 'clear' do
13
-
12
+ describe "clear" do
14
13
  before { Split.configuration.cache = true }
15
14
 
16
- it 'clears the cache' do
15
+ it "clears the cache" do
17
16
  expect(Time).to receive(:now).and_return(now).exactly(2).times
18
17
  Split::Cache.fetch(namespace, key) { Time.now }
19
18
  Split::Cache.clear
@@ -21,10 +20,10 @@ describe Split::Cache do
21
20
  end
22
21
  end
23
22
 
24
- describe 'clear_key' do
23
+ describe "clear_key" do
25
24
  before { Split.configuration.cache = true }
26
25
 
27
- it 'clears the cache' do
26
+ it "clears the cache" do
28
27
  expect(Time).to receive(:now).and_return(now).exactly(3).times
29
28
  Split::Cache.fetch(namespace, :key1) { Time.now }
30
29
  Split::Cache.fetch(namespace, :key2) { Time.now }
@@ -35,40 +34,37 @@ describe Split::Cache do
35
34
  end
36
35
  end
37
36
 
38
- describe 'fetch' do
39
-
37
+ describe "fetch" do
40
38
  subject { Split::Cache.fetch(namespace, key) { Time.now } }
41
39
 
42
- context 'when cache disabled' do
43
-
40
+ context "when cache disabled" do
44
41
  before { Split.configuration.cache = false }
45
42
 
46
- it 'returns the yield' do
43
+ it "returns the yield" do
47
44
  expect(subject).to eql(now)
48
45
  end
49
46
 
50
- it 'yields every time' do
47
+ it "yields every time" do
51
48
  expect(Time).to receive(:now).and_return(now).exactly(2).times
52
49
  Split::Cache.fetch(namespace, key) { Time.now }
53
50
  Split::Cache.fetch(namespace, key) { Time.now }
54
51
  end
55
52
  end
56
53
 
57
- context 'when cache enabled' do
58
-
54
+ context "when cache enabled" do
59
55
  before { Split.configuration.cache = true }
60
56
 
61
- it 'returns the yield' do
57
+ it "returns the yield" do
62
58
  expect(subject).to eql(now)
63
59
  end
64
60
 
65
- it 'yields once' do
61
+ it "yields once" do
66
62
  expect(Time).to receive(:now).and_return(now).once
67
63
  Split::Cache.fetch(namespace, key) { Time.now }
68
64
  Split::Cache.fetch(namespace, key) { Time.now }
69
65
  end
70
66
 
71
- it 'honors namespace' do
67
+ it "honors namespace" do
72
68
  expect(Split::Cache.fetch(:a, key) { :a }).to eql(:a)
73
69
  expect(Split::Cache.fetch(:b, key) { :b }).to eql(:b)
74
70
 
@@ -76,7 +72,7 @@ describe Split::Cache do
76
72
  expect(Split::Cache.fetch(:b, key) { :b }).to eql(:b)
77
73
  end
78
74
 
79
- it 'honors key' do
75
+ it "honors key" do
80
76
  expect(Split::Cache.fetch(namespace, :a) { :a }).to eql(:a)
81
77
  expect(Split::Cache.fetch(namespace, :b) { :b }).to eql(:b)
82
78
 
@@ -1,57 +1,58 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
3
- require 'split/combined_experiments_helper'
2
+
3
+ require "spec_helper"
4
+ require "split/combined_experiments_helper"
4
5
 
5
6
  describe Split::CombinedExperimentsHelper do
6
7
  include Split::CombinedExperimentsHelper
7
8
 
8
- describe 'ab_combined_test' do
9
+ describe "ab_combined_test" do
9
10
  let!(:config_enabled) { true }
10
- let!(:combined_experiments) { [:exp_1_click, :exp_1_scroll ]}
11
+ let!(:combined_experiments) { [:exp_1_click, :exp_1_scroll ] }
11
12
  let!(:allow_multiple_experiments) { true }
12
13
 
13
14
  before do
14
15
  Split.configuration.experiments = {
15
- :combined_exp_1 => {
16
- :alternatives => [ {"control"=> 0.5}, {"test-alt"=> 0.5} ],
17
- :metric => :my_metric,
18
- :combined_experiments => combined_experiments
16
+ combined_exp_1: {
17
+ alternatives: [ { "control"=> 0.5 }, { "test-alt"=> 0.5 } ],
18
+ metric: :my_metric,
19
+ combined_experiments: combined_experiments
19
20
  }
20
21
  }
21
22
  Split.configuration.enabled = config_enabled
22
23
  Split.configuration.allow_multiple_experiments = allow_multiple_experiments
23
24
  end
24
25
 
25
- context 'without config enabled' do
26
+ context "without config enabled" do
26
27
  let!(:config_enabled) { false }
27
28
 
28
29
  it "raises an error" do
29
- expect(lambda { ab_combined_test :combined_exp_1 }).to raise_error(Split::InvalidExperimentsFormatError )
30
+ expect { ab_combined_test :combined_exp_1 }.to raise_error(Split::InvalidExperimentsFormatError)
30
31
  end
31
32
  end
32
33
 
33
- context 'multiple experiments disabled' do
34
+ context "multiple experiments disabled" do
34
35
  let!(:allow_multiple_experiments) { false }
35
36
 
36
37
  it "raises an error if multiple experiments is disabled" do
37
- expect(lambda { ab_combined_test :combined_exp_1 }).to raise_error(Split::InvalidExperimentsFormatError)
38
+ expect { ab_combined_test :combined_exp_1 }.to raise_error(Split::InvalidExperimentsFormatError)
38
39
  end
39
40
  end
40
41
 
41
- context 'without combined experiments' do
42
+ context "without combined experiments" do
42
43
  let!(:combined_experiments) { nil }
43
44
 
44
45
  it "raises an error" do
45
- expect(lambda { ab_combined_test :combined_exp_1 }).to raise_error(Split::InvalidExperimentsFormatError )
46
+ expect { ab_combined_test :combined_exp_1 }.to raise_error(Split::InvalidExperimentsFormatError)
46
47
  end
47
48
  end
48
49
 
49
50
  it "uses same alternative for all sub experiments and returns the alternative" do
50
51
  allow(self).to receive(:get_alternative) { "test-alt" }
51
- expect(self).to receive(:ab_test).with(:exp_1_click, {"control"=>0.5}, {"test-alt"=>0.5}) { "test-alt" }
52
- expect(self).to receive(:ab_test).with(:exp_1_scroll, [{"control" => 0, "test-alt" => 1}])
52
+ expect(self).to receive(:ab_test).with(:exp_1_click, { "control"=>0.5 }, { "test-alt"=>0.5 }) { "test-alt" }
53
+ expect(self).to receive(:ab_test).with(:exp_1_scroll, [{ "control" => 0, "test-alt" => 1 }])
53
54
 
54
- expect(ab_combined_test('combined_exp_1')).to eq('test-alt')
55
+ expect(ab_combined_test("combined_exp_1")).to eq("test-alt")
55
56
  end
56
57
  end
57
58
  end