split 3.4.1 → 4.0.4
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 +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/dependabot.yml +7 -0
- data/.github/workflows/ci.yml +76 -0
- data/.rubocop.yml +177 -4
- data/CHANGELOG.md +87 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +2 -1
- data/README.md +37 -9
- data/Rakefile +5 -5
- data/gemfiles/5.2.gemfile +1 -3
- data/gemfiles/6.0.gemfile +1 -3
- data/gemfiles/{5.0.gemfile → 6.1.gemfile} +2 -4
- data/gemfiles/{5.1.gemfile → 7.0.gemfile} +2 -4
- data/lib/split/algorithms/block_randomization.rb +6 -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 +22 -22
- data/lib/split/cache.rb +27 -0
- data/lib/split/combined_experiments_helper.rb +5 -4
- data/lib/split/configuration.rb +89 -94
- data/lib/split/dashboard/helpers.rb +7 -7
- data/lib/split/dashboard/pagination_helpers.rb +54 -54
- data/lib/split/dashboard/paginator.rb +1 -0
- data/lib/split/dashboard/public/dashboard.js +10 -0
- data/lib/split/dashboard/public/style.css +10 -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 +19 -4
- data/lib/split/dashboard.rb +42 -21
- data/lib/split/encapsulated_helper.rb +15 -8
- data/lib/split/engine.rb +1 -0
- data/lib/split/exceptions.rb +1 -0
- data/lib/split/experiment.rb +151 -124
- data/lib/split/experiment_catalog.rb +7 -8
- data/lib/split/extensions/string.rb +2 -1
- data/lib/split/goals_collection.rb +9 -10
- data/lib/split/helper.rb +50 -23
- data/lib/split/metric.rb +6 -6
- data/lib/split/persistence/cookie_adapter.rb +46 -44
- data/lib/split/persistence/dual_adapter.rb +7 -8
- 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 +15 -29
- data/lib/split/trial.rb +43 -34
- data/lib/split/user.rb +25 -14
- data/lib/split/version.rb +2 -4
- data/lib/split/zscore.rb +2 -3
- data/lib/split.rb +34 -27
- 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 +69 -67
- data/spec/dashboard/paginator_spec.rb +10 -9
- data/spec/dashboard_helpers_spec.rb +19 -18
- data/spec/dashboard_spec.rb +122 -38
- data/spec/encapsulated_helper_spec.rb +46 -22
- data/spec/experiment_catalog_spec.rb +14 -13
- data/spec/experiment_spec.rb +198 -118
- data/spec/goals_collection_spec.rb +18 -16
- data/spec/helper_spec.rb +454 -385
- data/spec/metric_spec.rb +14 -14
- data/spec/persistence/cookie_adapter_spec.rb +26 -11
- data/spec/persistence/dual_adapter_spec.rb +71 -71
- 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 +35 -24
- data/spec/split_spec.rb +11 -11
- data/spec/support/cookies_mock.rb +1 -2
- data/spec/trial_spec.rb +102 -75
- data/spec/user_spec.rb +60 -29
- data/split.gemspec +22 -21
- metadata +43 -40
- data/.rubocop_todo.yml +0 -679
- data/.travis.yml +0 -60
- data/Appraisals +0 -19
- data/gemfiles/4.2.gemfile +0 -9
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,11 +28,11 @@ 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") }
|
|
@@ -34,7 +43,7 @@ describe Split::Dashboard do
|
|
|
34
43
|
end
|
|
35
44
|
|
|
36
45
|
it "should respond to /" do
|
|
37
|
-
get
|
|
46
|
+
get "/"
|
|
38
47
|
expect(last_response).to be_ok
|
|
39
48
|
end
|
|
40
49
|
|
|
@@ -46,33 +55,33 @@ describe Split::Dashboard do
|
|
|
46
55
|
context "experiment without goals" do
|
|
47
56
|
it "should display a Start button" do
|
|
48
57
|
experiment
|
|
49
|
-
get
|
|
50
|
-
expect(last_response.body).to include(
|
|
58
|
+
get "/"
|
|
59
|
+
expect(last_response.body).to include("Start")
|
|
51
60
|
|
|
52
61
|
post "/start?experiment=#{experiment.name}"
|
|
53
|
-
get
|
|
54
|
-
expect(last_response.body).to include(
|
|
55
|
-
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:")
|
|
56
65
|
end
|
|
57
66
|
end
|
|
58
67
|
|
|
59
68
|
context "experiment with metrics" do
|
|
60
69
|
it "should display the names of associated metrics" do
|
|
61
70
|
metric
|
|
62
|
-
get
|
|
63
|
-
expect(last_response.body).to include(
|
|
71
|
+
get "/"
|
|
72
|
+
expect(last_response.body).to include("Metrics:testmetric")
|
|
64
73
|
end
|
|
65
74
|
end
|
|
66
75
|
|
|
67
76
|
context "with goals" do
|
|
68
77
|
it "should display a Start button" do
|
|
69
78
|
experiment_with_goals
|
|
70
|
-
get
|
|
71
|
-
expect(last_response.body).to include(
|
|
79
|
+
get "/"
|
|
80
|
+
expect(last_response.body).to include("Start")
|
|
72
81
|
|
|
73
82
|
post "/start?experiment=#{experiment.name}"
|
|
74
|
-
get
|
|
75
|
-
expect(last_response.body).to include(
|
|
83
|
+
get "/"
|
|
84
|
+
expect(last_response.body).to include("Reset Data")
|
|
76
85
|
end
|
|
77
86
|
end
|
|
78
87
|
end
|
|
@@ -80,7 +89,7 @@ describe Split::Dashboard do
|
|
|
80
89
|
describe "force alternative" do
|
|
81
90
|
context "initial version" do
|
|
82
91
|
let!(:user) do
|
|
83
|
-
Split::User.new(@app, { experiment.name =>
|
|
92
|
+
Split::User.new(@app, { experiment.name => "red" })
|
|
84
93
|
end
|
|
85
94
|
|
|
86
95
|
before do
|
|
@@ -90,15 +99,24 @@ describe Split::Dashboard do
|
|
|
90
99
|
it "should set current user's alternative" do
|
|
91
100
|
blue_link.participant_count = 7
|
|
92
101
|
post "/force_alternative?experiment=#{experiment.name}", alternative: "blue"
|
|
93
|
-
|
|
94
|
-
|
|
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)
|
|
95
113
|
end
|
|
96
114
|
end
|
|
97
115
|
|
|
98
116
|
context "incremented version" do
|
|
99
117
|
let!(:user) do
|
|
100
118
|
experiment.increment_version
|
|
101
|
-
Split::User.new(@app, { "#{experiment.name}:#{experiment.version}" =>
|
|
119
|
+
Split::User.new(@app, { "#{experiment.name}:#{experiment.version}" => "red" })
|
|
102
120
|
end
|
|
103
121
|
|
|
104
122
|
before do
|
|
@@ -108,36 +126,37 @@ describe Split::Dashboard do
|
|
|
108
126
|
it "should set current user's alternative" do
|
|
109
127
|
blue_link.participant_count = 7
|
|
110
128
|
post "/force_alternative?experiment=#{experiment.name}", alternative: "blue"
|
|
111
|
-
|
|
112
|
-
|
|
129
|
+
|
|
130
|
+
get "/my_experiment?experiment=#{experiment.name}"
|
|
131
|
+
expect(last_response.body).to include("blue")
|
|
113
132
|
end
|
|
114
133
|
end
|
|
115
134
|
end
|
|
116
135
|
|
|
117
136
|
describe "index page" do
|
|
118
137
|
context "with winner" do
|
|
119
|
-
before { experiment.winner =
|
|
138
|
+
before { experiment.winner = "red" }
|
|
120
139
|
|
|
121
140
|
it "displays `Reopen Experiment` button" do
|
|
122
|
-
get
|
|
141
|
+
get "/"
|
|
123
142
|
|
|
124
|
-
expect(last_response.body).to include(
|
|
143
|
+
expect(last_response.body).to include("Reopen Experiment")
|
|
125
144
|
end
|
|
126
145
|
end
|
|
127
146
|
|
|
128
147
|
context "without winner" do
|
|
129
148
|
it "should not display `Reopen Experiment` button" do
|
|
130
|
-
get
|
|
149
|
+
get "/"
|
|
131
150
|
|
|
132
|
-
expect(last_response.body).to_not include(
|
|
151
|
+
expect(last_response.body).to_not include("Reopen Experiment")
|
|
133
152
|
end
|
|
134
153
|
end
|
|
135
154
|
end
|
|
136
155
|
|
|
137
156
|
describe "reopen experiment" do
|
|
138
|
-
before { experiment.winner =
|
|
157
|
+
before { experiment.winner = "red" }
|
|
139
158
|
|
|
140
|
-
it
|
|
159
|
+
it "redirects" do
|
|
141
160
|
post "/reopen?experiment=#{experiment.name}"
|
|
142
161
|
|
|
143
162
|
expect(last_response).to be_redirect
|
|
@@ -152,7 +171,7 @@ describe Split::Dashboard do
|
|
|
152
171
|
it "keeps existing stats" do
|
|
153
172
|
red_link.participant_count = 5
|
|
154
173
|
blue_link.participant_count = 7
|
|
155
|
-
experiment.winner =
|
|
174
|
+
experiment.winner = "blue"
|
|
156
175
|
|
|
157
176
|
post "/reopen?experiment=#{experiment.name}"
|
|
158
177
|
|
|
@@ -161,10 +180,63 @@ describe Split::Dashboard do
|
|
|
161
180
|
end
|
|
162
181
|
end
|
|
163
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
|
+
|
|
164
236
|
it "should reset an experiment" do
|
|
165
237
|
red_link.participant_count = 5
|
|
166
238
|
blue_link.participant_count = 7
|
|
167
|
-
experiment.winner =
|
|
239
|
+
experiment.winner = "blue"
|
|
168
240
|
|
|
169
241
|
post "/reset?experiment=#{experiment.name}"
|
|
170
242
|
|
|
@@ -186,16 +258,16 @@ describe Split::Dashboard do
|
|
|
186
258
|
|
|
187
259
|
it "should mark an alternative as the winner" do
|
|
188
260
|
expect(experiment.winner).to be_nil
|
|
189
|
-
post "/experiment?experiment=#{experiment.name}", :
|
|
261
|
+
post "/experiment?experiment=#{experiment.name}", alternative: "red"
|
|
190
262
|
|
|
191
263
|
expect(last_response).to be_redirect
|
|
192
|
-
expect(experiment.winner.name).to eq(
|
|
264
|
+
expect(experiment.winner.name).to eq("red")
|
|
193
265
|
end
|
|
194
266
|
|
|
195
267
|
it "should display the start date" do
|
|
196
268
|
experiment.start
|
|
197
269
|
|
|
198
|
-
get
|
|
270
|
+
get "/"
|
|
199
271
|
|
|
200
272
|
expect(last_response.body).to include("<small>#{experiment.start_time.strftime('%Y-%m-%d')}</small>")
|
|
201
273
|
end
|
|
@@ -203,8 +275,20 @@ describe Split::Dashboard do
|
|
|
203
275
|
it "should handle experiments without a start date" do
|
|
204
276
|
Split.redis.hdel(:experiment_start_times, experiment.name)
|
|
205
277
|
|
|
206
|
-
get
|
|
278
|
+
get "/"
|
|
279
|
+
|
|
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)
|
|
207
289
|
|
|
208
|
-
|
|
290
|
+
get "/"
|
|
291
|
+
|
|
292
|
+
expect(last_response).to be_ok
|
|
209
293
|
end
|
|
210
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
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
|