split 4.0.1 → 4.0.5

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +27 -35
  3. data/.rubocop.yml +2 -5
  4. data/CHANGELOG.md +58 -0
  5. data/CONTRIBUTING.md +1 -1
  6. data/Gemfile +4 -1
  7. data/README.md +11 -3
  8. data/Rakefile +4 -5
  9. data/lib/split/algorithms/block_randomization.rb +5 -6
  10. data/lib/split/algorithms/whiplash.rb +16 -18
  11. data/lib/split/algorithms.rb +14 -0
  12. data/lib/split/alternative.rb +21 -22
  13. data/lib/split/cache.rb +0 -1
  14. data/lib/split/combined_experiments_helper.rb +4 -4
  15. data/lib/split/configuration.rb +83 -84
  16. data/lib/split/dashboard/helpers.rb +6 -7
  17. data/lib/split/dashboard/pagination_helpers.rb +53 -54
  18. data/lib/split/dashboard/public/style.css +5 -2
  19. data/lib/split/dashboard/views/_experiment.erb +2 -1
  20. data/lib/split/dashboard/views/index.erb +19 -4
  21. data/lib/split/dashboard.rb +31 -24
  22. data/lib/split/encapsulated_helper.rb +12 -6
  23. data/lib/split/experiment.rb +93 -88
  24. data/lib/split/experiment_catalog.rb +6 -5
  25. data/lib/split/extensions/string.rb +1 -1
  26. data/lib/split/goals_collection.rb +8 -10
  27. data/lib/split/helper.rb +33 -25
  28. data/lib/split/metric.rb +4 -5
  29. data/lib/split/persistence/cookie_adapter.rb +45 -47
  30. data/lib/split/persistence/dual_adapter.rb +7 -8
  31. data/lib/split/persistence/redis_adapter.rb +3 -4
  32. data/lib/split/persistence/session_adapter.rb +0 -2
  33. data/lib/split/persistence.rb +4 -4
  34. data/lib/split/redis_interface.rb +7 -1
  35. data/lib/split/trial.rb +23 -24
  36. data/lib/split/user.rb +12 -13
  37. data/lib/split/version.rb +1 -1
  38. data/lib/split/zscore.rb +1 -3
  39. data/lib/split.rb +27 -26
  40. data/spec/algorithms/block_randomization_spec.rb +6 -5
  41. data/spec/algorithms/weighted_sample_spec.rb +6 -5
  42. data/spec/algorithms/whiplash_spec.rb +4 -5
  43. data/spec/alternative_spec.rb +35 -36
  44. data/spec/cache_spec.rb +15 -19
  45. data/spec/combined_experiments_helper_spec.rb +18 -17
  46. data/spec/configuration_spec.rb +32 -38
  47. data/spec/dashboard/pagination_helpers_spec.rb +69 -67
  48. data/spec/dashboard/paginator_spec.rb +10 -9
  49. data/spec/dashboard_helpers_spec.rb +19 -18
  50. data/spec/dashboard_spec.rb +79 -35
  51. data/spec/encapsulated_helper_spec.rb +46 -22
  52. data/spec/experiment_catalog_spec.rb +14 -13
  53. data/spec/experiment_spec.rb +132 -123
  54. data/spec/goals_collection_spec.rb +17 -15
  55. data/spec/helper_spec.rb +415 -382
  56. data/spec/metric_spec.rb +14 -14
  57. data/spec/persistence/cookie_adapter_spec.rb +26 -11
  58. data/spec/persistence/dual_adapter_spec.rb +71 -71
  59. data/spec/persistence/redis_adapter_spec.rb +28 -29
  60. data/spec/persistence/session_adapter_spec.rb +2 -3
  61. data/spec/persistence_spec.rb +1 -2
  62. data/spec/redis_interface_spec.rb +26 -14
  63. data/spec/spec_helper.rb +33 -18
  64. data/spec/split_spec.rb +11 -11
  65. data/spec/support/cookies_mock.rb +1 -2
  66. data/spec/trial_spec.rb +61 -60
  67. data/spec/user_spec.rb +36 -36
  68. data/split.gemspec +24 -20
  69. metadata +51 -19
  70. data/.rubocop_todo.yml +0 -226
  71. data/Appraisals +0 -19
  72. data/gemfiles/5.0.gemfile +0 -9
  73. data/gemfiles/5.1.gemfile +0 -9
  74. data/gemfiles/5.2.gemfile +0 -9
  75. data/gemfiles/6.0.gemfile +0 -9
  76. data/gemfiles/6.1.gemfile +0 -9
  77. data/gemfiles/7.0.gemfile +0 -9
@@ -1,13 +1,9 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
3
-
4
- describe Split::EncapsulatedHelper do
5
- include Split::EncapsulatedHelper
6
2
 
3
+ require "spec_helper"
7
4
 
8
- def params
9
- raise NoMethodError, 'This method is not really defined'
10
- end
5
+ describe Split::EncapsulatedHelper do
6
+ let(:context_shim) { Split::EncapsulatedHelper::ContextShim.new(double(request: request)) }
11
7
 
12
8
  describe "ab_test" do
13
9
  before do
@@ -15,38 +11,66 @@ describe Split::EncapsulatedHelper do
15
11
  .and_return(mock_user)
16
12
  end
17
13
 
18
- it "should not raise an error when params raises an error" do
19
- expect{ params }.to raise_error(NoMethodError)
20
- expect(lambda { ab_test('link_color', 'blue', 'red') }).not_to raise_error
21
- end
22
-
23
14
  it "calls the block with selected alternative" do
24
- expect{|block| ab_test('link_color', 'red', 'red', &block) }.to yield_with_args('red', {})
15
+ expect { |block| context_shim.ab_test("link_color", "red", "red", &block) }.to yield_with_args("red", {})
25
16
  end
26
17
 
27
18
  context "inside a view" do
28
-
29
19
  it "works inside ERB" do
30
- require 'erb'
31
- template = ERB.new(<<-ERB.split(/\s+/s).map(&:strip).join(' '), nil, "%")
32
- foo <% ab_test(:foo, '1', '2') do |alt, meta| %>
20
+ require "erb"
21
+ template = ERB.new(<<-ERB.split(/\s+/s).map(&:strip).join(" "), nil, "%")
22
+ foo <% context_shim.ab_test(:foo, '1', '2') do |alt, meta| %>
33
23
  static <%= alt %>
34
24
  <% end %>
35
25
  ERB
36
26
  expect(template.result(binding)).to match(/foo static \d/)
37
27
  end
38
-
39
28
  end
40
29
  end
41
30
 
42
31
  describe "context" do
43
- it 'is passed in shim' do
44
- ctx = Class.new{
32
+ it "is passed in shim" do
33
+ ctx = Class.new {
45
34
  include Split::EncapsulatedHelper
46
35
  public :session
47
36
  }.new
48
- expect(ctx).to receive(:session){{}}
49
- expect{ ctx.ab_test('link_color', 'blue', 'red') }.not_to raise_error
37
+
38
+ expect(ctx).to receive(:session) { {} }
39
+ expect { ctx.ab_test("link_color", "blue", "red") }.not_to raise_error
40
+ end
41
+
42
+ context "when request is defined in context of ContextShim" do
43
+ context "when overriding by params" do
44
+ it do
45
+ ctx = Class.new {
46
+ public :session
47
+ def request
48
+ build_request(params: {
49
+ "ab_test" => { "link_color" => "blue" }
50
+ })
51
+ end
52
+ }.new
53
+
54
+ context_shim = Split::EncapsulatedHelper::ContextShim.new(ctx)
55
+ expect(context_shim.ab_test("link_color", "blue", "red")).to be("blue")
56
+ end
57
+ end
58
+
59
+ context "when overriding by cookies" do
60
+ it do
61
+ ctx = Class.new {
62
+ public :session
63
+ def request
64
+ build_request(cookies: {
65
+ "split_override" => '{ "link_color": "red" }'
66
+ })
67
+ end
68
+ }.new
69
+
70
+ context_shim = Split::EncapsulatedHelper::ContextShim.new(ctx)
71
+ expect(context_shim.ab_test("link_color", "blue", "red")).to be("red")
72
+ end
73
+ end
50
74
  end
51
75
  end
52
76
  end
@@ -1,53 +1,54 @@
1
1
  # frozen_string_literal: true
2
- require 'spec_helper'
2
+
3
+ require "spec_helper"
3
4
 
4
5
  describe Split::ExperimentCatalog do
5
6
  subject { Split::ExperimentCatalog }
6
7
 
7
8
  describe ".find_or_create" do
8
9
  it "should not raise an error when passed strings for alternatives" do
9
- expect { subject.find_or_create('xyz', '1', '2', '3') }.not_to raise_error
10
+ expect { subject.find_or_create("xyz", "1", "2", "3") }.not_to raise_error
10
11
  end
11
12
 
12
13
  it "should not raise an error when passed an array for alternatives" do
13
- expect { subject.find_or_create('xyz', ['1', '2', '3']) }.not_to raise_error
14
+ expect { subject.find_or_create("xyz", ["1", "2", "3"]) }.not_to raise_error
14
15
  end
15
16
 
16
17
  it "should raise the appropriate error when passed integers for alternatives" do
17
- expect { subject.find_or_create('xyz', 1, 2, 3) }.to raise_error(ArgumentError)
18
+ expect { subject.find_or_create("xyz", 1, 2, 3) }.to raise_error(ArgumentError)
18
19
  end
19
20
 
20
21
  it "should raise the appropriate error when passed symbols for alternatives" do
21
- expect { subject.find_or_create('xyz', :a, :b, :c) }.to raise_error(ArgumentError)
22
+ expect { subject.find_or_create("xyz", :a, :b, :c) }.to raise_error(ArgumentError)
22
23
  end
23
24
 
24
25
  it "should not raise error when passed an array for goals" do
25
- expect { subject.find_or_create({'link_color' => ["purchase", "refund"]}, 'blue', 'red') }
26
+ expect { subject.find_or_create({ "link_color" => ["purchase", "refund"] }, "blue", "red") }
26
27
  .not_to raise_error
27
28
  end
28
29
 
29
30
  it "should not raise error when passed just one goal" do
30
- expect { subject.find_or_create({'link_color' => "purchase"}, 'blue', 'red') }
31
+ expect { subject.find_or_create({ "link_color" => "purchase" }, "blue", "red") }
31
32
  .not_to raise_error
32
33
  end
33
34
 
34
35
  it "constructs a new experiment" do
35
- expect(subject.find_or_create('my_exp', 'control me').control.to_s).to eq('control me')
36
+ expect(subject.find_or_create("my_exp", "control me").control.to_s).to eq("control me")
36
37
  end
37
38
  end
38
39
 
39
- describe '.find' do
40
+ describe ".find" do
40
41
  it "should return an existing experiment" do
41
- experiment = Split::Experiment.new('basket_text', alternatives: ['blue', 'red', 'green'])
42
+ experiment = Split::Experiment.new("basket_text", alternatives: ["blue", "red", "green"])
42
43
  experiment.save
43
44
 
44
- experiment = subject.find('basket_text')
45
+ experiment = subject.find("basket_text")
45
46
 
46
- expect(experiment.name).to eq('basket_text')
47
+ expect(experiment.name).to eq("basket_text")
47
48
  end
48
49
 
49
50
  it "should return nil if experiment not exist" do
50
- expect(subject.find('non_existent_experiment')).to be_nil
51
+ expect(subject.find("non_existent_experiment")).to be_nil
51
52
  end
52
53
  end
53
54
  end