split 3.2.0 → 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.
- checksums.yaml +5 -5
- data/.eslintrc +1 -1
- data/.github/FUNDING.yml +1 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
- data/.github/dependabot.yml +7 -0
- data/.github/workflows/ci.yml +63 -0
- data/.rspec +1 -0
- data/.rubocop.yml +67 -1043
- data/CHANGELOG.md +174 -0
- data/CODE_OF_CONDUCT.md +3 -3
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +6 -1
- data/README.md +79 -33
- data/Rakefile +6 -5
- data/lib/split/algorithms/block_randomization.rb +7 -6
- data/lib/split/algorithms/weighted_sample.rb +2 -1
- data/lib/split/algorithms/whiplash.rb +17 -18
- data/lib/split/algorithms.rb +14 -0
- data/lib/split/alternative.rb +25 -25
- data/lib/split/cache.rb +27 -0
- data/lib/split/combined_experiments_helper.rb +6 -5
- data/lib/split/configuration.rb +94 -91
- data/lib/split/dashboard/helpers.rb +9 -9
- data/lib/split/dashboard/pagination_helpers.rb +86 -0
- data/lib/split/dashboard/paginator.rb +17 -0
- data/lib/split/dashboard/public/dashboard.js +10 -0
- data/lib/split/dashboard/public/style.css +19 -2
- data/lib/split/dashboard/views/_controls.erb +13 -0
- data/lib/split/dashboard/views/_experiment.erb +2 -1
- data/lib/split/dashboard/views/index.erb +24 -5
- data/lib/split/dashboard/views/layout.erb +1 -1
- data/lib/split/dashboard.rb +47 -20
- data/lib/split/encapsulated_helper.rb +15 -8
- data/lib/split/engine.rb +7 -4
- data/lib/split/exceptions.rb +1 -0
- data/lib/split/experiment.rb +160 -122
- data/lib/split/experiment_catalog.rb +7 -8
- data/lib/split/extensions/string.rb +2 -1
- data/lib/split/goals_collection.rb +10 -10
- data/lib/split/helper.rb +56 -24
- data/lib/split/metric.rb +6 -6
- data/lib/split/persistence/cookie_adapter.rb +52 -15
- data/lib/split/persistence/dual_adapter.rb +53 -12
- data/lib/split/persistence/redis_adapter.rb +8 -4
- data/lib/split/persistence/session_adapter.rb +1 -2
- data/lib/split/persistence.rb +8 -6
- data/lib/split/redis_interface.rb +16 -31
- data/lib/split/trial.rb +48 -41
- data/lib/split/user.rb +30 -15
- data/lib/split/version.rb +2 -4
- data/lib/split/zscore.rb +2 -3
- data/lib/split.rb +39 -25
- data/spec/algorithms/block_randomization_spec.rb +6 -5
- data/spec/algorithms/weighted_sample_spec.rb +6 -5
- data/spec/algorithms/whiplash_spec.rb +4 -5
- data/spec/alternative_spec.rb +35 -36
- data/spec/cache_spec.rb +84 -0
- data/spec/combined_experiments_helper_spec.rb +18 -17
- data/spec/configuration_spec.rb +41 -45
- data/spec/dashboard/pagination_helpers_spec.rb +202 -0
- data/spec/dashboard/paginator_spec.rb +38 -0
- data/spec/dashboard_helpers_spec.rb +19 -18
- data/spec/dashboard_spec.rb +153 -48
- data/spec/encapsulated_helper_spec.rb +47 -23
- data/spec/experiment_catalog_spec.rb +14 -13
- data/spec/experiment_spec.rb +224 -111
- data/spec/goals_collection_spec.rb +18 -16
- data/spec/helper_spec.rb +539 -419
- data/spec/metric_spec.rb +14 -14
- data/spec/persistence/cookie_adapter_spec.rb +105 -27
- data/spec/persistence/dual_adapter_spec.rb +158 -66
- data/spec/persistence/redis_adapter_spec.rb +35 -27
- data/spec/persistence/session_adapter_spec.rb +2 -3
- data/spec/persistence_spec.rb +1 -2
- data/spec/redis_interface_spec.rb +25 -82
- data/spec/spec_helper.rb +38 -24
- data/spec/split_spec.rb +18 -18
- data/spec/support/cookies_mock.rb +1 -2
- data/spec/trial_spec.rb +117 -70
- data/spec/user_spec.rb +69 -27
- data/split.gemspec +26 -22
- metadata +85 -37
- data/.travis.yml +0 -41
- data/Appraisals +0 -13
- data/gemfiles/4.2.gemfile +0 -9
- data/gemfiles/5.0.gemfile +0 -10
- data/gemfiles/5.1.gemfile +0 -10
data/spec/dashboard_spec.rb
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require
|
|
4
|
-
require
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require "rack/test"
|
|
5
|
+
require "split/dashboard"
|
|
5
6
|
|
|
6
7
|
describe Split::Dashboard do
|
|
7
8
|
include Rack::Test::Methods
|
|
8
9
|
|
|
10
|
+
class TestDashboard < Split::Dashboard
|
|
11
|
+
include Split::Helper
|
|
12
|
+
|
|
13
|
+
get "/my_experiment" do
|
|
14
|
+
ab_test(params[:experiment], "blue", "red")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
9
18
|
def app
|
|
10
|
-
@app ||=
|
|
19
|
+
@app ||= TestDashboard
|
|
11
20
|
end
|
|
12
21
|
|
|
13
22
|
def link(color)
|
|
@@ -19,18 +28,22 @@ describe Split::Dashboard do
|
|
|
19
28
|
}
|
|
20
29
|
|
|
21
30
|
let(:experiment_with_goals) {
|
|
22
|
-
Split::ExperimentCatalog.find_or_create({"link_color" => ["goal_1", "goal_2"]}, "blue", "red")
|
|
31
|
+
Split::ExperimentCatalog.find_or_create({ "link_color" => ["goal_1", "goal_2"] }, "blue", "red")
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
let(:metric) {
|
|
26
|
-
Split::Metric.find_or_create(name:
|
|
35
|
+
Split::Metric.find_or_create(name: "testmetric", experiments: [experiment, experiment_with_goals])
|
|
27
36
|
}
|
|
28
37
|
|
|
29
38
|
let(:red_link) { link("red") }
|
|
30
39
|
let(:blue_link) { link("blue") }
|
|
31
40
|
|
|
41
|
+
before(:each) do
|
|
42
|
+
Split.configuration.beta_probability_simulations = 1
|
|
43
|
+
end
|
|
44
|
+
|
|
32
45
|
it "should respond to /" do
|
|
33
|
-
get
|
|
46
|
+
get "/"
|
|
34
47
|
expect(last_response).to be_ok
|
|
35
48
|
end
|
|
36
49
|
|
|
@@ -42,76 +55,108 @@ describe Split::Dashboard do
|
|
|
42
55
|
context "experiment without goals" do
|
|
43
56
|
it "should display a Start button" do
|
|
44
57
|
experiment
|
|
45
|
-
get
|
|
46
|
-
expect(last_response.body).to include(
|
|
58
|
+
get "/"
|
|
59
|
+
expect(last_response.body).to include("Start")
|
|
47
60
|
|
|
48
61
|
post "/start?experiment=#{experiment.name}"
|
|
49
|
-
get
|
|
50
|
-
expect(last_response.body).to include(
|
|
51
|
-
expect(last_response.body).not_to include(
|
|
62
|
+
get "/"
|
|
63
|
+
expect(last_response.body).to include("Reset Data")
|
|
64
|
+
expect(last_response.body).not_to include("Metrics:")
|
|
52
65
|
end
|
|
53
66
|
end
|
|
54
67
|
|
|
55
68
|
context "experiment with metrics" do
|
|
56
69
|
it "should display the names of associated metrics" do
|
|
57
70
|
metric
|
|
58
|
-
get
|
|
59
|
-
expect(last_response.body).to include(
|
|
71
|
+
get "/"
|
|
72
|
+
expect(last_response.body).to include("Metrics:testmetric")
|
|
60
73
|
end
|
|
61
74
|
end
|
|
62
75
|
|
|
63
76
|
context "with goals" do
|
|
64
77
|
it "should display a Start button" do
|
|
65
78
|
experiment_with_goals
|
|
66
|
-
get
|
|
67
|
-
expect(last_response.body).to include(
|
|
79
|
+
get "/"
|
|
80
|
+
expect(last_response.body).to include("Start")
|
|
68
81
|
|
|
69
82
|
post "/start?experiment=#{experiment.name}"
|
|
70
|
-
get
|
|
71
|
-
expect(last_response.body).to include(
|
|
83
|
+
get "/"
|
|
84
|
+
expect(last_response.body).to include("Reset Data")
|
|
72
85
|
end
|
|
73
86
|
end
|
|
74
87
|
end
|
|
75
88
|
|
|
76
89
|
describe "force alternative" do
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
90
|
+
context "initial version" do
|
|
91
|
+
let!(:user) do
|
|
92
|
+
Split::User.new(@app, { experiment.name => "red" })
|
|
93
|
+
end
|
|
80
94
|
|
|
81
|
-
|
|
82
|
-
|
|
95
|
+
before do
|
|
96
|
+
allow(Split::User).to receive(:new).and_return(user)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "should set current user's alternative" do
|
|
100
|
+
blue_link.participant_count = 7
|
|
101
|
+
post "/force_alternative?experiment=#{experiment.name}", alternative: "blue"
|
|
102
|
+
|
|
103
|
+
get "/my_experiment?experiment=#{experiment.name}"
|
|
104
|
+
expect(last_response.body).to include("blue")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should not modify an existing user" do
|
|
108
|
+
blue_link.participant_count = 7
|
|
109
|
+
post "/force_alternative?experiment=#{experiment.name}", alternative: "blue"
|
|
110
|
+
|
|
111
|
+
expect(user[experiment.key]).to eq("red")
|
|
112
|
+
expect(blue_link.participant_count).to eq(7)
|
|
113
|
+
end
|
|
83
114
|
end
|
|
84
115
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
116
|
+
context "incremented version" do
|
|
117
|
+
let!(:user) do
|
|
118
|
+
experiment.increment_version
|
|
119
|
+
Split::User.new(@app, { "#{experiment.name}:#{experiment.version}" => "red" })
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
before do
|
|
123
|
+
allow(Split::User).to receive(:new).and_return(user)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "should set current user's alternative" do
|
|
127
|
+
blue_link.participant_count = 7
|
|
128
|
+
post "/force_alternative?experiment=#{experiment.name}", alternative: "blue"
|
|
129
|
+
|
|
130
|
+
get "/my_experiment?experiment=#{experiment.name}"
|
|
131
|
+
expect(last_response.body).to include("blue")
|
|
132
|
+
end
|
|
88
133
|
end
|
|
89
134
|
end
|
|
90
135
|
|
|
91
136
|
describe "index page" do
|
|
92
137
|
context "with winner" do
|
|
93
|
-
before { experiment.winner =
|
|
138
|
+
before { experiment.winner = "red" }
|
|
94
139
|
|
|
95
140
|
it "displays `Reopen Experiment` button" do
|
|
96
|
-
get
|
|
141
|
+
get "/"
|
|
97
142
|
|
|
98
|
-
expect(last_response.body).to include(
|
|
143
|
+
expect(last_response.body).to include("Reopen Experiment")
|
|
99
144
|
end
|
|
100
145
|
end
|
|
101
146
|
|
|
102
147
|
context "without winner" do
|
|
103
148
|
it "should not display `Reopen Experiment` button" do
|
|
104
|
-
get
|
|
149
|
+
get "/"
|
|
105
150
|
|
|
106
|
-
expect(last_response.body).to_not include(
|
|
151
|
+
expect(last_response.body).to_not include("Reopen Experiment")
|
|
107
152
|
end
|
|
108
153
|
end
|
|
109
154
|
end
|
|
110
155
|
|
|
111
156
|
describe "reopen experiment" do
|
|
112
|
-
before { experiment.winner =
|
|
157
|
+
before { experiment.winner = "red" }
|
|
113
158
|
|
|
114
|
-
it
|
|
159
|
+
it "redirects" do
|
|
115
160
|
post "/reopen?experiment=#{experiment.name}"
|
|
116
161
|
|
|
117
162
|
expect(last_response).to be_redirect
|
|
@@ -120,13 +165,13 @@ describe Split::Dashboard do
|
|
|
120
165
|
it "removes winner" do
|
|
121
166
|
post "/reopen?experiment=#{experiment.name}"
|
|
122
167
|
|
|
123
|
-
expect(experiment).to_not have_winner
|
|
168
|
+
expect(Split::ExperimentCatalog.find(experiment.name)).to_not have_winner
|
|
124
169
|
end
|
|
125
170
|
|
|
126
171
|
it "keeps existing stats" do
|
|
127
172
|
red_link.participant_count = 5
|
|
128
173
|
blue_link.participant_count = 7
|
|
129
|
-
experiment.winner =
|
|
174
|
+
experiment.winner = "blue"
|
|
130
175
|
|
|
131
176
|
post "/reopen?experiment=#{experiment.name}"
|
|
132
177
|
|
|
@@ -135,10 +180,63 @@ describe Split::Dashboard do
|
|
|
135
180
|
end
|
|
136
181
|
end
|
|
137
182
|
|
|
183
|
+
describe "update cohorting" do
|
|
184
|
+
it "calls enable of cohorting when action is enable" do
|
|
185
|
+
post "/update_cohorting?experiment=#{experiment.name}", { "cohorting_action": "enable" }
|
|
186
|
+
|
|
187
|
+
expect(experiment.cohorting_disabled?).to eq false
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "calls disable of cohorting when action is disable" do
|
|
191
|
+
post "/update_cohorting?experiment=#{experiment.name}", { "cohorting_action": "disable" }
|
|
192
|
+
|
|
193
|
+
expect(experiment.cohorting_disabled?).to eq true
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "calls neither enable or disable cohorting when passed invalid action" do
|
|
197
|
+
previous_value = experiment.cohorting_disabled?
|
|
198
|
+
|
|
199
|
+
post "/update_cohorting?experiment=#{experiment.name}", { "cohorting_action": "other" }
|
|
200
|
+
|
|
201
|
+
expect(experiment.cohorting_disabled?).to eq previous_value
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
describe "initialize experiment" do
|
|
206
|
+
before do
|
|
207
|
+
Split.configuration.experiments = {
|
|
208
|
+
my_experiment: {
|
|
209
|
+
alternatives: [ "control", "alternative" ],
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "initializes the experiment when the experiment is given" do
|
|
215
|
+
expect(Split::ExperimentCatalog.find("my_experiment")).to be nil
|
|
216
|
+
|
|
217
|
+
post "/initialize_experiment", { experiment: "my_experiment" }
|
|
218
|
+
|
|
219
|
+
experiment = Split::ExperimentCatalog.find("my_experiment")
|
|
220
|
+
expect(experiment).to be_a(Split::Experiment)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "does not attempt to intialize the experiment when empty experiment is given" do
|
|
224
|
+
post "/initialize_experiment", { experiment: "" }
|
|
225
|
+
|
|
226
|
+
expect(Split::ExperimentCatalog).to_not receive(:find_or_create)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "does not attempt to intialize the experiment when no experiment is given" do
|
|
230
|
+
post "/initialize_experiment"
|
|
231
|
+
|
|
232
|
+
expect(Split::ExperimentCatalog).to_not receive(:find_or_create)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
138
236
|
it "should reset an experiment" do
|
|
139
237
|
red_link.participant_count = 5
|
|
140
238
|
blue_link.participant_count = 7
|
|
141
|
-
experiment.winner =
|
|
239
|
+
experiment.winner = "blue"
|
|
142
240
|
|
|
143
241
|
post "/reset?experiment=#{experiment.name}"
|
|
144
242
|
|
|
@@ -160,30 +258,37 @@ describe Split::Dashboard do
|
|
|
160
258
|
|
|
161
259
|
it "should mark an alternative as the winner" do
|
|
162
260
|
expect(experiment.winner).to be_nil
|
|
163
|
-
post "/experiment?experiment=#{experiment.name}", :
|
|
261
|
+
post "/experiment?experiment=#{experiment.name}", alternative: "red"
|
|
164
262
|
|
|
165
263
|
expect(last_response).to be_redirect
|
|
166
|
-
expect(experiment.winner.name).to eq(
|
|
264
|
+
expect(experiment.winner.name).to eq("red")
|
|
167
265
|
end
|
|
168
266
|
|
|
169
267
|
it "should display the start date" do
|
|
170
|
-
|
|
171
|
-
expect(Time).to receive(:now).at_least(:once).and_return(experiment_start_time)
|
|
172
|
-
experiment
|
|
268
|
+
experiment.start
|
|
173
269
|
|
|
174
|
-
get
|
|
270
|
+
get "/"
|
|
175
271
|
|
|
176
|
-
expect(last_response.body).to include(
|
|
272
|
+
expect(last_response.body).to include("<small>#{experiment.start_time.strftime('%Y-%m-%d')}</small>")
|
|
177
273
|
end
|
|
178
274
|
|
|
179
275
|
it "should handle experiments without a start date" do
|
|
180
|
-
experiment_start_time = Time.parse('2011-07-07')
|
|
181
|
-
expect(Time).to receive(:now).at_least(:once).and_return(experiment_start_time)
|
|
182
|
-
|
|
183
276
|
Split.redis.hdel(:experiment_start_times, experiment.name)
|
|
184
277
|
|
|
185
|
-
get
|
|
278
|
+
get "/"
|
|
186
279
|
|
|
187
|
-
expect(last_response.body).to include(
|
|
280
|
+
expect(last_response.body).to include("<small>Unknown</small>")
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it "should be explode with experiments with invalid data" do
|
|
284
|
+
red_link.participant_count = 1
|
|
285
|
+
red_link.set_completed_count(10)
|
|
286
|
+
|
|
287
|
+
blue_link.participant_count = 3
|
|
288
|
+
blue_link.set_completed_count(2)
|
|
289
|
+
|
|
290
|
+
get "/"
|
|
291
|
+
|
|
292
|
+
expect(last_response).to be_ok
|
|
188
293
|
end
|
|
189
294
|
end
|
|
@@ -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
|
-
|
|
9
|
-
|
|
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(
|
|
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
|
|
31
|
-
template = ERB.new(<<-ERB.split(/\s+/s).map(&:strip).join(
|
|
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
|
-
expect(template.result(binding)).to match
|
|
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
|
|
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
|
-
|
|
49
|
-
expect
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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({
|
|
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({
|
|
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(
|
|
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
|
|
40
|
+
describe ".find" do
|
|
40
41
|
it "should return an existing experiment" do
|
|
41
|
-
experiment = Split::Experiment.new(
|
|
42
|
+
experiment = Split::Experiment.new("basket_text", alternatives: ["blue", "red", "green"])
|
|
42
43
|
experiment.save
|
|
43
44
|
|
|
44
|
-
experiment = subject.find(
|
|
45
|
+
experiment = subject.find("basket_text")
|
|
45
46
|
|
|
46
|
-
expect(experiment.name).to eq(
|
|
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(
|
|
51
|
+
expect(subject.find("non_existent_experiment")).to be_nil
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
end
|