split 3.0.0 → 3.4.0

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 (58) hide show
  1. checksums.yaml +5 -5
  2. data/.eslintrc +1 -1
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +6 -1155
  6. data/.rubocop_todo.yml +679 -0
  7. data/.travis.yml +46 -2
  8. data/Appraisals +12 -1
  9. data/CHANGELOG.md +116 -0
  10. data/CODE_OF_CONDUCT.md +3 -3
  11. data/CONTRIBUTING.md +54 -5
  12. data/Gemfile +1 -0
  13. data/LICENSE +1 -1
  14. data/README.md +209 -118
  15. data/Rakefile +1 -0
  16. data/gemfiles/4.2.gemfile +1 -1
  17. data/gemfiles/5.0.gemfile +1 -2
  18. data/gemfiles/5.1.gemfile +9 -0
  19. data/gemfiles/5.2.gemfile +9 -0
  20. data/gemfiles/6.0.gemfile +9 -0
  21. data/lib/split/algorithms/block_randomization.rb +1 -0
  22. data/lib/split/alternative.rb +6 -3
  23. data/lib/split/combined_experiments_helper.rb +37 -0
  24. data/lib/split/configuration.rb +17 -2
  25. data/lib/split/dashboard/helpers.rb +2 -2
  26. data/lib/split/dashboard/pagination_helpers.rb +86 -0
  27. data/lib/split/dashboard/paginator.rb +16 -0
  28. data/lib/split/dashboard/public/style.css +9 -0
  29. data/lib/split/dashboard/views/index.erb +5 -1
  30. data/lib/split/dashboard/views/layout.erb +1 -1
  31. data/lib/split/dashboard.rb +6 -1
  32. data/lib/split/engine.rb +6 -2
  33. data/lib/split/experiment.rb +34 -22
  34. data/lib/split/goals_collection.rb +1 -0
  35. data/lib/split/helper.rb +17 -3
  36. data/lib/split/persistence/cookie_adapter.rb +53 -15
  37. data/lib/split/persistence/dual_adapter.rb +54 -12
  38. data/lib/split/redis_interface.rb +2 -3
  39. data/lib/split/trial.rb +4 -6
  40. data/lib/split/user.rb +5 -1
  41. data/lib/split/version.rb +1 -1
  42. data/lib/split.rb +9 -1
  43. data/spec/alternative_spec.rb +12 -0
  44. data/spec/combined_experiments_helper_spec.rb +57 -0
  45. data/spec/dashboard/pagination_helpers_spec.rb +200 -0
  46. data/spec/dashboard/paginator_spec.rb +37 -0
  47. data/spec/dashboard_helpers_spec.rb +2 -2
  48. data/spec/dashboard_spec.rb +37 -16
  49. data/spec/encapsulated_helper_spec.rb +1 -1
  50. data/spec/experiment_spec.rb +45 -6
  51. data/spec/helper_spec.rb +143 -80
  52. data/spec/persistence/cookie_adapter_spec.rb +90 -23
  53. data/spec/persistence/dual_adapter_spec.rb +160 -68
  54. data/spec/split_spec.rb +7 -7
  55. data/spec/trial_spec.rb +20 -0
  56. data/spec/user_spec.rb +11 -0
  57. data/split.gemspec +17 -7
  58. metadata +53 -19
@@ -1,102 +1,194 @@
1
1
  # frozen_string_literal: true
2
- require "spec_helper"
2
+
3
+ require 'spec_helper'
3
4
 
4
5
  describe Split::Persistence::DualAdapter do
6
+ let(:context) { 'some context' }
5
7
 
6
- let(:context){ "some context" }
7
-
8
- let(:just_adapter){ Class.new }
9
- let(:selected_adapter_instance){ double }
10
- let(:selected_adapter){
11
- c = Class.new
12
- expect(c).to receive(:new){ selected_adapter_instance }
13
- c
14
- }
15
- let(:not_selected_adapter){
16
- c = Class.new
17
- expect(c).not_to receive(:new)
18
- c
19
- }
20
-
21
- shared_examples_for "forwarding calls" do
22
- it "#[]=" do
23
- expect(selected_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
24
- expect_any_instance_of(not_selected_adapter).not_to receive(:[]=)
25
- subject["my_key"] = "my_value"
26
- end
8
+ let(:logged_in_adapter_instance) { double }
9
+ let(:logged_in_adapter) do
10
+ Class.new.tap { |c| allow(c).to receive(:new) { logged_in_adapter_instance } }
11
+ end
12
+ let(:logged_out_adapter_instance) { double }
13
+ let(:logged_out_adapter) do
14
+ Class.new.tap { |c| allow(c).to receive(:new) { logged_out_adapter_instance } }
15
+ end
27
16
 
28
- it "#[]" do
29
- expect(selected_adapter_instance).to receive(:[]).with('my_key'){'my_value'}
30
- expect_any_instance_of(not_selected_adapter).not_to receive(:[])
31
- expect(subject["my_key"]).to eq('my_value')
32
- end
17
+ context 'when fallback_to_logged_out_adapter is false' do
18
+ context 'when logged in' do
19
+ subject do
20
+ described_class.with_config(
21
+ logged_in: lambda { |context| true },
22
+ logged_in_adapter: logged_in_adapter,
23
+ logged_out_adapter: logged_out_adapter,
24
+ fallback_to_logged_out_adapter: false
25
+ ).new(context)
26
+ end
27
+
28
+ it '#[]=' do
29
+ expect(logged_in_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
30
+ expect_any_instance_of(logged_out_adapter).not_to receive(:[]=)
31
+ subject['my_key'] = 'my_value'
32
+ end
33
+
34
+ it '#[]' do
35
+ expect(logged_in_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
36
+ expect_any_instance_of(logged_out_adapter).not_to receive(:[])
37
+ expect(subject['my_key']).to eq('my_value')
38
+ end
33
39
 
34
- it "#delete" do
35
- expect(selected_adapter_instance).to receive(:delete).with('my_key'){'my_value'}
36
- expect_any_instance_of(not_selected_adapter).not_to receive(:delete)
37
- expect(subject.delete("my_key")).to eq('my_value')
40
+ it '#delete' do
41
+ expect(logged_in_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
42
+ expect_any_instance_of(logged_out_adapter).not_to receive(:delete)
43
+ expect(subject.delete('my_key')).to eq('my_value')
44
+ end
45
+
46
+ it '#keys' do
47
+ expect(logged_in_adapter_instance).to receive(:keys) { ['my_value'] }
48
+ expect_any_instance_of(logged_out_adapter).not_to receive(:keys)
49
+ expect(subject.keys).to eq(['my_value'])
50
+ end
38
51
  end
39
52
 
40
- it "#keys" do
41
- expect(selected_adapter_instance).to receive(:keys){'my_value'}
42
- expect_any_instance_of(not_selected_adapter).not_to receive(:keys)
43
- expect(subject.keys).to eq('my_value')
53
+ context 'when logged out' do
54
+ subject do
55
+ described_class.with_config(
56
+ logged_in: lambda { |context| false },
57
+ logged_in_adapter: logged_in_adapter,
58
+ logged_out_adapter: logged_out_adapter,
59
+ fallback_to_logged_out_adapter: false
60
+ ).new(context)
61
+ end
62
+
63
+ it '#[]=' do
64
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[]=)
65
+ expect(logged_out_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
66
+ subject['my_key'] = 'my_value'
67
+ end
68
+
69
+ it '#[]' do
70
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[])
71
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
72
+ expect(subject['my_key']).to eq('my_value')
73
+ end
74
+
75
+ it '#delete' do
76
+ expect_any_instance_of(logged_in_adapter).not_to receive(:delete)
77
+ expect(logged_out_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
78
+ expect(subject.delete('my_key')).to eq('my_value')
79
+ end
80
+
81
+ it '#keys' do
82
+ expect_any_instance_of(logged_in_adapter).not_to receive(:keys)
83
+ expect(logged_out_adapter_instance).to receive(:keys) { ['my_value', 'my_value2'] }
84
+ expect(subject.keys).to eq(['my_value', 'my_value2'])
85
+ end
44
86
  end
45
87
  end
46
88
 
47
- context "when logged in" do
48
- subject {
49
- described_class.with_config(
50
- logged_in: -> (context) { true },
51
- logged_in_adapter: selected_adapter,
52
- logged_out_adapter: not_selected_adapter
89
+ context 'when fallback_to_logged_out_adapter is true' do
90
+ context 'when logged in' do
91
+ subject do
92
+ described_class.with_config(
93
+ logged_in: lambda { |context| true },
94
+ logged_in_adapter: logged_in_adapter,
95
+ logged_out_adapter: logged_out_adapter,
96
+ fallback_to_logged_out_adapter: true
53
97
  ).new(context)
54
- }
98
+ end
55
99
 
56
- it_should_behave_like "forwarding calls"
57
- end
100
+ it '#[]=' do
101
+ expect(logged_in_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
102
+ expect(logged_out_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
103
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { nil }
104
+ subject['my_key'] = 'my_value'
105
+ end
106
+
107
+ it '#[]' do
108
+ expect(logged_in_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
109
+ expect_any_instance_of(logged_out_adapter).not_to receive(:[])
110
+ expect(subject['my_key']).to eq('my_value')
111
+ end
112
+
113
+ it '#delete' do
114
+ expect(logged_in_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
115
+ expect(logged_out_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
116
+ expect(subject.delete('my_key')).to eq('my_value')
117
+ end
118
+
119
+ it '#keys' do
120
+ expect(logged_in_adapter_instance).to receive(:keys) { ['my_value'] }
121
+ expect(logged_out_adapter_instance).to receive(:keys) { ['my_value', 'my_value2'] }
122
+ expect(subject.keys).to eq(['my_value', 'my_value2'])
123
+ end
124
+ end
58
125
 
59
- context "when not logged in" do
60
- subject {
61
- described_class.with_config(
62
- logged_in: -> (context) { false },
63
- logged_in_adapter: not_selected_adapter,
64
- logged_out_adapter: selected_adapter
126
+ context 'when logged out' do
127
+ subject do
128
+ described_class.with_config(
129
+ logged_in: lambda { |context| false },
130
+ logged_in_adapter: logged_in_adapter,
131
+ logged_out_adapter: logged_out_adapter,
132
+ fallback_to_logged_out_adapter: true
65
133
  ).new(context)
66
- }
134
+ end
135
+
136
+ it '#[]=' do
137
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[]=)
138
+ expect(logged_out_adapter_instance).to receive(:[]=).with('my_key', 'my_value')
139
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { nil }
140
+ subject['my_key'] = 'my_value'
141
+ end
142
+
143
+ it '#[]' do
144
+ expect_any_instance_of(logged_in_adapter).not_to receive(:[])
145
+ expect(logged_out_adapter_instance).to receive(:[]).with('my_key') { 'my_value' }
146
+ expect(subject['my_key']).to eq('my_value')
147
+ end
148
+
149
+ it '#delete' do
150
+ expect(logged_in_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
151
+ expect(logged_out_adapter_instance).to receive(:delete).with('my_key') { 'my_value' }
152
+ expect(subject.delete('my_key')).to eq('my_value')
153
+ end
67
154
 
68
- it_should_behave_like "forwarding calls"
155
+ it '#keys' do
156
+ expect(logged_in_adapter_instance).to receive(:keys) { ['my_value'] }
157
+ expect(logged_out_adapter_instance).to receive(:keys) { ['my_value', 'my_value2'] }
158
+ expect(subject.keys).to eq(['my_value', 'my_value2'])
159
+ end
160
+ end
69
161
  end
70
162
 
71
- describe "when errors in config" do
72
- before{
73
- described_class.config.clear
74
- }
75
- let(:some_proc){ ->{} }
76
- it "when no logged in adapter" do
163
+ describe 'when errors in config' do
164
+ before { described_class.config.clear }
165
+ let(:some_proc) { ->{} }
166
+
167
+ it 'when no logged in adapter' do
77
168
  expect{
78
169
  described_class.with_config(
79
170
  logged_in: some_proc,
80
- logged_out_adapter: just_adapter
81
- ).new(context)
171
+ logged_out_adapter: logged_out_adapter
172
+ ).new(context)
82
173
  }.to raise_error(StandardError, /:logged_in_adapter/)
83
174
  end
84
- it "when no logged out adapter" do
175
+
176
+ it 'when no logged out adapter' do
85
177
  expect{
86
178
  described_class.with_config(
87
179
  logged_in: some_proc,
88
- logged_in_adapter: just_adapter
89
- ).new(context)
180
+ logged_in_adapter: logged_in_adapter
181
+ ).new(context)
90
182
  }.to raise_error(StandardError, /:logged_out_adapter/)
91
183
  end
92
- it "when no logged in detector" do
184
+
185
+ it 'when no logged in detector' do
93
186
  expect{
94
187
  described_class.with_config(
95
- logged_in_adapter: just_adapter,
96
- logged_out_adapter: just_adapter
97
- ).new(context)
188
+ logged_in_adapter: logged_in_adapter,
189
+ logged_out_adapter: logged_out_adapter
190
+ ).new(context)
98
191
  }.to raise_error(StandardError, /:logged_in$/)
99
192
  end
100
193
  end
101
-
102
194
  end
data/spec/split_spec.rb CHANGED
@@ -15,19 +15,19 @@ RSpec.describe Split do
15
15
  Split.redis = 'redis://localhost:6379'
16
16
  expect(Split.redis).to be_a(Redis)
17
17
 
18
- client = Split.redis.client
19
- expect(client.host).to eq("localhost")
20
- expect(client.port).to eq(6379)
18
+ client = Split.redis.connection
19
+ expect(client[:host]).to eq("localhost")
20
+ expect(client[:port]).to eq(6379)
21
21
  end
22
22
 
23
23
  it 'accepts an options hash' do
24
24
  Split.redis = {host: 'localhost', port: 6379, db: 12}
25
25
  expect(Split.redis).to be_a(Redis)
26
26
 
27
- client = Split.redis.client
28
- expect(client.host).to eq("localhost")
29
- expect(client.port).to eq(6379)
30
- expect(client.db).to eq(12)
27
+ client = Split.redis.connection
28
+ expect(client[:host]).to eq("localhost")
29
+ expect(client[:port]).to eq(6379)
30
+ expect(client[:db]).to eq(12)
31
31
  end
32
32
 
33
33
  it 'accepts a valid Redis instance' do
data/spec/trial_spec.rb CHANGED
@@ -176,6 +176,14 @@ describe Split::Trial do
176
176
 
177
177
  expect_alternative(trial, 'basket')
178
178
  end
179
+
180
+ context "when alternative is not found" do
181
+ it "falls back on next_alternative" do
182
+ user[experiment.key] = 'notfound'
183
+ expect(experiment).to receive(:next_alternative).and_call_original
184
+ expect_alternative(trial, alternatives)
185
+ end
186
+ end
179
187
  end
180
188
 
181
189
  context "when user is a new participant" do
@@ -275,5 +283,17 @@ describe Split::Trial do
275
283
  trial.choose!
276
284
  end
277
285
  end
286
+
287
+ context 'when experiment has winner' do
288
+ let(:trial) do
289
+ experiment.winner = 'cart'
290
+ Split::Trial.new(:user => user, :experiment => experiment)
291
+ end
292
+
293
+ it 'does not store' do
294
+ expect(user).to_not receive("[]=")
295
+ trial.choose!
296
+ end
297
+ end
278
298
  end
279
299
  end
data/spec/user_spec.rb CHANGED
@@ -59,6 +59,17 @@ describe Split::User do
59
59
  expect(@subject.keys).to include("link_color:finished")
60
60
  end
61
61
  end
62
+
63
+ context 'when already cleaned up' do
64
+ before do
65
+ @subject.cleanup_old_experiments!
66
+ end
67
+
68
+ it 'does not clean up again' do
69
+ expect(@subject).to_not receive(:keys_without_finished)
70
+ @subject.cleanup_old_experiments!
71
+ end
72
+ end
62
73
  end
63
74
 
64
75
  context "instantiated with custom adapter" do
data/split.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
2
3
  $:.push File.expand_path("../lib", __FILE__)
3
4
  require "split/version"
4
5
 
@@ -12,9 +13,17 @@ Gem::Specification.new do |s|
12
13
  s.homepage = "https://github.com/splitrb/split"
13
14
  s.summary = "Rack based split testing framework"
14
15
 
15
- s.required_ruby_version = '>= 1.9.2'
16
+ s.metadata = {
17
+ "homepage_uri" => "https://github.com/splitrb/split",
18
+ "changelog_uri" => "https://github.com/splitrb/split/blob/master/CHANGELOG.md",
19
+ "source_code_uri" => "https://github.com/splitrb/split",
20
+ "bug_tracker_uri" => "https://github.com/splitrb/split/issues",
21
+ "wiki_uri" => "https://github.com/splitrb/split/wiki",
22
+ "mailing_list_uri" => "https://groups.google.com/d/forum/split-ruby"
23
+ }
16
24
 
17
- s.rubyforge_project = "split"
25
+ s.required_ruby_version = '>= 1.9.3'
26
+ s.required_rubygems_version = '>= 2.0.0'
18
27
 
19
28
  s.files = `git ls-files`.split("\n")
20
29
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -24,11 +33,12 @@ Gem::Specification.new do |s|
24
33
  s.add_dependency 'sinatra', '>= 1.2.6'
25
34
  s.add_dependency 'simple-random', '>= 0.9.3'
26
35
 
27
- s.add_development_dependency 'bundler', '~> 1.10'
28
- s.add_development_dependency 'simplecov', '~> 0.12'
36
+ s.add_development_dependency 'bundler', '>= 1.17'
37
+ s.add_development_dependency 'simplecov', '~> 0.15'
29
38
  s.add_development_dependency 'rack-test', '~> 0.6'
30
- s.add_development_dependency 'rake', '~> 11.1'
31
- s.add_development_dependency 'rspec', '~> 3.4'
39
+ s.add_development_dependency 'rake', '~> 12'
40
+ s.add_development_dependency 'rspec', '~> 3.7'
32
41
  s.add_development_dependency 'pry', '~> 0.10'
33
- s.add_development_dependency 'fakeredis', '~> 0.6.0'
42
+ s.add_development_dependency 'fakeredis', '~> 0.7'
43
+ s.add_development_dependency 'rails', '>= 4.2'
34
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: split
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Nesbitt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-30 00:00:00.000000000 Z
11
+ date: 2019-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -56,30 +56,30 @@ dependencies:
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.10'
61
+ version: '1.17'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '1.10'
68
+ version: '1.17'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: simplecov
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0.12'
75
+ version: '0.15'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0.12'
82
+ version: '0.15'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rack-test
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,28 +100,28 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '11.1'
103
+ version: '12'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '11.1'
110
+ version: '12'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '3.4'
117
+ version: '3.7'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '3.4'
124
+ version: '3.7'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: pry
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +142,28 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 0.6.0
145
+ version: '0.7'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 0.6.0
152
+ version: '0.7'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rails
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '4.2'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '4.2'
153
167
  description:
154
168
  email:
155
169
  - andrewnez@gmail.com
@@ -161,8 +175,11 @@ files:
161
175
  - ".csslintrc"
162
176
  - ".eslintignore"
163
177
  - ".eslintrc"
178
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
164
179
  - ".gitignore"
180
+ - ".rspec"
165
181
  - ".rubocop.yml"
182
+ - ".rubocop_todo.yml"
166
183
  - ".travis.yml"
167
184
  - Appraisals
168
185
  - CHANGELOG.md
@@ -174,14 +191,20 @@ files:
174
191
  - Rakefile
175
192
  - gemfiles/4.2.gemfile
176
193
  - gemfiles/5.0.gemfile
194
+ - gemfiles/5.1.gemfile
195
+ - gemfiles/5.2.gemfile
196
+ - gemfiles/6.0.gemfile
177
197
  - lib/split.rb
178
198
  - lib/split/algorithms/block_randomization.rb
179
199
  - lib/split/algorithms/weighted_sample.rb
180
200
  - lib/split/algorithms/whiplash.rb
181
201
  - lib/split/alternative.rb
202
+ - lib/split/combined_experiments_helper.rb
182
203
  - lib/split/configuration.rb
183
204
  - lib/split/dashboard.rb
184
205
  - lib/split/dashboard/helpers.rb
206
+ - lib/split/dashboard/pagination_helpers.rb
207
+ - lib/split/dashboard/paginator.rb
185
208
  - lib/split/dashboard/public/dashboard-filtering.js
186
209
  - lib/split/dashboard/public/dashboard.js
187
210
  - lib/split/dashboard/public/jquery-1.11.1.min.js
@@ -215,7 +238,10 @@ files:
215
238
  - spec/algorithms/weighted_sample_spec.rb
216
239
  - spec/algorithms/whiplash_spec.rb
217
240
  - spec/alternative_spec.rb
241
+ - spec/combined_experiments_helper_spec.rb
218
242
  - spec/configuration_spec.rb
243
+ - spec/dashboard/pagination_helpers_spec.rb
244
+ - spec/dashboard/paginator_spec.rb
219
245
  - spec/dashboard_helpers_spec.rb
220
246
  - spec/dashboard_spec.rb
221
247
  - spec/encapsulated_helper_spec.rb
@@ -239,7 +265,13 @@ files:
239
265
  homepage: https://github.com/splitrb/split
240
266
  licenses:
241
267
  - MIT
242
- metadata: {}
268
+ metadata:
269
+ homepage_uri: https://github.com/splitrb/split
270
+ changelog_uri: https://github.com/splitrb/split/blob/master/CHANGELOG.md
271
+ source_code_uri: https://github.com/splitrb/split
272
+ bug_tracker_uri: https://github.com/splitrb/split/issues
273
+ wiki_uri: https://github.com/splitrb/split/wiki
274
+ mailing_list_uri: https://groups.google.com/d/forum/split-ruby
243
275
  post_install_message:
244
276
  rdoc_options: []
245
277
  require_paths:
@@ -248,15 +280,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
248
280
  requirements:
249
281
  - - ">="
250
282
  - !ruby/object:Gem::Version
251
- version: 1.9.2
283
+ version: 1.9.3
252
284
  required_rubygems_version: !ruby/object:Gem::Requirement
253
285
  requirements:
254
286
  - - ">="
255
287
  - !ruby/object:Gem::Version
256
- version: '0'
288
+ version: 2.0.0
257
289
  requirements: []
258
- rubyforge_project: split
259
- rubygems_version: 2.6.4
290
+ rubygems_version: 3.0.3
260
291
  signing_key:
261
292
  specification_version: 4
262
293
  summary: Rack based split testing framework
@@ -265,7 +296,10 @@ test_files:
265
296
  - spec/algorithms/weighted_sample_spec.rb
266
297
  - spec/algorithms/whiplash_spec.rb
267
298
  - spec/alternative_spec.rb
299
+ - spec/combined_experiments_helper_spec.rb
268
300
  - spec/configuration_spec.rb
301
+ - spec/dashboard/pagination_helpers_spec.rb
302
+ - spec/dashboard/paginator_spec.rb
269
303
  - spec/dashboard_helpers_spec.rb
270
304
  - spec/dashboard_spec.rb
271
305
  - spec/encapsulated_helper_spec.rb