split 4.0.1 → 4.0.3
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/workflows/ci.yml +8 -3
- data/.rubocop.yml +2 -5
- data/CHANGELOG.md +38 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +1 -1
- data/README.md +11 -3
- data/Rakefile +4 -5
- data/gemfiles/5.2.gemfile +1 -3
- data/gemfiles/6.0.gemfile +1 -3
- data/gemfiles/6.1.gemfile +1 -3
- data/gemfiles/7.0.gemfile +1 -3
- data/lib/split/algorithms/block_randomization.rb +5 -6
- data/lib/split/algorithms/whiplash.rb +16 -18
- data/lib/split/algorithms.rb +14 -0
- data/lib/split/alternative.rb +21 -22
- data/lib/split/cache.rb +0 -1
- data/lib/split/combined_experiments_helper.rb +4 -4
- data/lib/split/configuration.rb +83 -84
- data/lib/split/dashboard/helpers.rb +6 -7
- data/lib/split/dashboard/pagination_helpers.rb +53 -54
- data/lib/split/dashboard/public/style.css +5 -2
- data/lib/split/dashboard/views/_experiment.erb +2 -1
- data/lib/split/dashboard/views/index.erb +19 -4
- data/lib/split/dashboard.rb +29 -23
- data/lib/split/encapsulated_helper.rb +4 -6
- data/lib/split/experiment.rb +93 -88
- data/lib/split/experiment_catalog.rb +6 -5
- data/lib/split/extensions/string.rb +1 -1
- data/lib/split/goals_collection.rb +8 -10
- data/lib/split/helper.rb +20 -20
- data/lib/split/metric.rb +4 -5
- data/lib/split/persistence/cookie_adapter.rb +44 -47
- data/lib/split/persistence/dual_adapter.rb +7 -8
- data/lib/split/persistence/redis_adapter.rb +3 -4
- data/lib/split/persistence/session_adapter.rb +0 -2
- data/lib/split/persistence.rb +4 -4
- data/lib/split/redis_interface.rb +7 -1
- data/lib/split/trial.rb +23 -24
- data/lib/split/user.rb +12 -13
- data/lib/split/version.rb +1 -1
- data/lib/split/zscore.rb +1 -3
- data/lib/split.rb +26 -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 +15 -19
- data/spec/combined_experiments_helper_spec.rb +18 -17
- data/spec/configuration_spec.rb +32 -38
- 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 +79 -35
- data/spec/encapsulated_helper_spec.rb +12 -14
- data/spec/experiment_catalog_spec.rb +14 -13
- data/spec/experiment_spec.rb +132 -123
- data/spec/goals_collection_spec.rb +17 -15
- data/spec/helper_spec.rb +415 -382
- data/spec/metric_spec.rb +14 -14
- data/spec/persistence/cookie_adapter_spec.rb +23 -8
- data/spec/persistence/dual_adapter_spec.rb +71 -71
- data/spec/persistence/redis_adapter_spec.rb +28 -29
- data/spec/persistence/session_adapter_spec.rb +2 -3
- data/spec/persistence_spec.rb +1 -2
- data/spec/redis_interface_spec.rb +26 -14
- data/spec/spec_helper.rb +16 -13
- data/spec/split_spec.rb +11 -11
- data/spec/support/cookies_mock.rb +1 -2
- data/spec/trial_spec.rb +61 -60
- data/spec/user_spec.rb +36 -36
- data/split.gemspec +21 -20
- metadata +25 -14
- data/.rubocop_todo.yml +0 -226
- data/Appraisals +0 -19
- data/gemfiles/5.0.gemfile +0 -9
- data/gemfiles/5.1.gemfile +0 -9
data/spec/metric_spec.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "split/metric"
|
4
5
|
|
5
6
|
describe Split::Metric do
|
6
|
-
describe
|
7
|
+
describe "possible experiments" do
|
7
8
|
it "should load the experiment if there is one, but no metric" do
|
8
|
-
experiment = Split::ExperimentCatalog.find_or_create(
|
9
|
-
expect(Split::Metric.possible_experiments(
|
9
|
+
experiment = Split::ExperimentCatalog.find_or_create("color", "red", "blue")
|
10
|
+
expect(Split::Metric.possible_experiments("color")).to eq([experiment])
|
10
11
|
end
|
11
12
|
|
12
13
|
it "should load the experiments in a metric" do
|
13
|
-
experiment1 = Split::ExperimentCatalog.find_or_create(
|
14
|
-
experiment2 = Split::ExperimentCatalog.find_or_create(
|
14
|
+
experiment1 = Split::ExperimentCatalog.find_or_create("color", "red", "blue")
|
15
|
+
experiment2 = Split::ExperimentCatalog.find_or_create("size", "big", "small")
|
15
16
|
|
16
|
-
metric = Split::Metric.new(:
|
17
|
+
metric = Split::Metric.new(name: "purchase", experiments: [experiment1, experiment2])
|
17
18
|
metric.save
|
18
|
-
expect(Split::Metric.possible_experiments(
|
19
|
+
expect(Split::Metric.possible_experiments("purchase")).to include(experiment1, experiment2)
|
19
20
|
end
|
20
21
|
|
21
22
|
it "should load both the metric experiments and an experiment with the same name" do
|
22
|
-
experiment1 = Split::ExperimentCatalog.find_or_create(
|
23
|
-
experiment2 = Split::ExperimentCatalog.find_or_create(
|
23
|
+
experiment1 = Split::ExperimentCatalog.find_or_create("purchase", "red", "blue")
|
24
|
+
experiment2 = Split::ExperimentCatalog.find_or_create("size", "big", "small")
|
24
25
|
|
25
|
-
metric = Split::Metric.new(:
|
26
|
+
metric = Split::Metric.new(name: "purchase", experiments: [experiment2])
|
26
27
|
metric.save
|
27
|
-
expect(Split::Metric.possible_experiments(
|
28
|
+
expect(Split::Metric.possible_experiments("purchase")).to include(experiment1, experiment2)
|
28
29
|
end
|
29
30
|
end
|
30
|
-
|
31
31
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "spec_helper"
|
3
|
-
require
|
4
|
+
require "rack/test"
|
4
5
|
|
5
6
|
describe Split::Persistence::CookieAdapter do
|
6
7
|
subject { described_class.new(context) }
|
@@ -13,10 +14,24 @@ describe Split::Persistence::CookieAdapter do
|
|
13
14
|
end
|
14
15
|
|
15
16
|
it "handles invalid JSON" do
|
16
|
-
context.request.cookies[
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
context.request.cookies["split"] = "{\"foo\":2,"
|
18
|
+
|
19
|
+
expect(subject["my_key"]).to be_nil
|
20
|
+
subject["my_key"] = "my_value"
|
21
|
+
expect(subject["my_key"]).to eq("my_value")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "ignores valid JSON of invalid type (integer)" do
|
25
|
+
context.request.cookies["split"] = "2"
|
26
|
+
|
27
|
+
expect(subject["my_key"]).to be_nil
|
28
|
+
subject["my_key"] = "my_value"
|
29
|
+
expect(subject["my_key"]).to eq("my_value")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "ignores valid JSON of invalid type (array)" do
|
33
|
+
context.request.cookies["split"] = "[\"foo\", \"bar\"]"
|
34
|
+
|
20
35
|
expect(subject["my_key"]).to be_nil
|
21
36
|
subject["my_key"] = "my_value"
|
22
37
|
expect(subject["my_key"]).to eq("my_value")
|
@@ -56,7 +71,7 @@ describe Split::Persistence::CookieAdapter do
|
|
56
71
|
end
|
57
72
|
|
58
73
|
it "ensure other added cookies are not overriden" do
|
59
|
-
context.response.set_cookie
|
74
|
+
context.response.set_cookie "dummy", "wow"
|
60
75
|
subject["foo"] = "FOO"
|
61
76
|
expect(context.response.headers["Set-Cookie"]).to include("dummy=wow")
|
62
77
|
expect(context.response.headers["Set-Cookie"]).to include("split=")
|
@@ -77,7 +92,7 @@ describe Split::Persistence::CookieAdapter do
|
|
77
92
|
controller.send(:"request=", ActionDispatch::Request.new({}))
|
78
93
|
end
|
79
94
|
|
80
|
-
response = ActionDispatch::Response.new(200, {},
|
95
|
+
response = ActionDispatch::Response.new(200, {}, "").tap do |res|
|
81
96
|
res.request = controller.request
|
82
97
|
end
|
83
98
|
|
@@ -100,7 +115,7 @@ describe Split::Persistence::CookieAdapter do
|
|
100
115
|
expect(subject["foo"]).to eq("FOO")
|
101
116
|
expect(subject["bar"]).to eq("BAR")
|
102
117
|
cookie_jar = context.request.env["action_dispatch.cookies"]
|
103
|
-
expect(cookie_jar[
|
118
|
+
expect(cookie_jar["split"]).to eq('{"foo":"FOO","bar":"BAR"}')
|
104
119
|
end
|
105
120
|
end
|
106
121
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "spec_helper"
|
4
4
|
|
5
5
|
describe Split::Persistence::DualAdapter do
|
6
|
-
let(:context) {
|
6
|
+
let(:context) { "some context" }
|
7
7
|
|
8
8
|
let(:logged_in_adapter_instance) { double }
|
9
9
|
let(:logged_in_adapter) do
|
@@ -14,8 +14,8 @@ describe Split::Persistence::DualAdapter do
|
|
14
14
|
Class.new.tap { |c| allow(c).to receive(:new) { logged_out_adapter_instance } }
|
15
15
|
end
|
16
16
|
|
17
|
-
context
|
18
|
-
context
|
17
|
+
context "when fallback_to_logged_out_adapter is false" do
|
18
|
+
context "when logged in" do
|
19
19
|
subject do
|
20
20
|
described_class.with_config(
|
21
21
|
logged_in: lambda { |context| true },
|
@@ -25,32 +25,32 @@ describe Split::Persistence::DualAdapter do
|
|
25
25
|
).new(context)
|
26
26
|
end
|
27
27
|
|
28
|
-
it
|
29
|
-
expect(logged_in_adapter_instance).to receive(:[]=).with(
|
28
|
+
it "#[]=" do
|
29
|
+
expect(logged_in_adapter_instance).to receive(:[]=).with("my_key", "my_value")
|
30
30
|
expect_any_instance_of(logged_out_adapter).not_to receive(:[]=)
|
31
|
-
subject[
|
31
|
+
subject["my_key"] = "my_value"
|
32
32
|
end
|
33
33
|
|
34
|
-
it
|
35
|
-
expect(logged_in_adapter_instance).to receive(:[]).with(
|
34
|
+
it "#[]" do
|
35
|
+
expect(logged_in_adapter_instance).to receive(:[]).with("my_key") { "my_value" }
|
36
36
|
expect_any_instance_of(logged_out_adapter).not_to receive(:[])
|
37
|
-
expect(subject[
|
37
|
+
expect(subject["my_key"]).to eq("my_value")
|
38
38
|
end
|
39
39
|
|
40
|
-
it
|
41
|
-
expect(logged_in_adapter_instance).to receive(:delete).with(
|
40
|
+
it "#delete" do
|
41
|
+
expect(logged_in_adapter_instance).to receive(:delete).with("my_key") { "my_value" }
|
42
42
|
expect_any_instance_of(logged_out_adapter).not_to receive(:delete)
|
43
|
-
expect(subject.delete(
|
43
|
+
expect(subject.delete("my_key")).to eq("my_value")
|
44
44
|
end
|
45
45
|
|
46
|
-
it
|
47
|
-
expect(logged_in_adapter_instance).to receive(:keys) { [
|
46
|
+
it "#keys" do
|
47
|
+
expect(logged_in_adapter_instance).to receive(:keys) { ["my_value"] }
|
48
48
|
expect_any_instance_of(logged_out_adapter).not_to receive(:keys)
|
49
|
-
expect(subject.keys).to eq([
|
49
|
+
expect(subject.keys).to eq(["my_value"])
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
context
|
53
|
+
context "when logged out" do
|
54
54
|
subject do
|
55
55
|
described_class.with_config(
|
56
56
|
logged_in: lambda { |context| false },
|
@@ -60,34 +60,34 @@ describe Split::Persistence::DualAdapter do
|
|
60
60
|
).new(context)
|
61
61
|
end
|
62
62
|
|
63
|
-
it
|
63
|
+
it "#[]=" do
|
64
64
|
expect_any_instance_of(logged_in_adapter).not_to receive(:[]=)
|
65
|
-
expect(logged_out_adapter_instance).to receive(:[]=).with(
|
66
|
-
subject[
|
65
|
+
expect(logged_out_adapter_instance).to receive(:[]=).with("my_key", "my_value")
|
66
|
+
subject["my_key"] = "my_value"
|
67
67
|
end
|
68
68
|
|
69
|
-
it
|
69
|
+
it "#[]" do
|
70
70
|
expect_any_instance_of(logged_in_adapter).not_to receive(:[])
|
71
|
-
expect(logged_out_adapter_instance).to receive(:[]).with(
|
72
|
-
expect(subject[
|
71
|
+
expect(logged_out_adapter_instance).to receive(:[]).with("my_key") { "my_value" }
|
72
|
+
expect(subject["my_key"]).to eq("my_value")
|
73
73
|
end
|
74
74
|
|
75
|
-
it
|
75
|
+
it "#delete" do
|
76
76
|
expect_any_instance_of(logged_in_adapter).not_to receive(:delete)
|
77
|
-
expect(logged_out_adapter_instance).to receive(:delete).with(
|
78
|
-
expect(subject.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
79
|
end
|
80
80
|
|
81
|
-
it
|
81
|
+
it "#keys" do
|
82
82
|
expect_any_instance_of(logged_in_adapter).not_to receive(:keys)
|
83
|
-
expect(logged_out_adapter_instance).to receive(:keys) { [
|
84
|
-
expect(subject.keys).to eq([
|
83
|
+
expect(logged_out_adapter_instance).to receive(:keys) { ["my_value", "my_value2"] }
|
84
|
+
expect(subject.keys).to eq(["my_value", "my_value2"])
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
context
|
90
|
-
context
|
89
|
+
context "when fallback_to_logged_out_adapter is true" do
|
90
|
+
context "when logged in" do
|
91
91
|
subject do
|
92
92
|
described_class.with_config(
|
93
93
|
logged_in: lambda { |context| true },
|
@@ -97,33 +97,33 @@ describe Split::Persistence::DualAdapter do
|
|
97
97
|
).new(context)
|
98
98
|
end
|
99
99
|
|
100
|
-
it
|
101
|
-
expect(logged_in_adapter_instance).to receive(:[]=).with(
|
102
|
-
expect(logged_out_adapter_instance).to receive(:[]=).with(
|
103
|
-
expect(logged_out_adapter_instance).to receive(:[]).with(
|
104
|
-
subject[
|
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
105
|
end
|
106
106
|
|
107
|
-
it
|
108
|
-
expect(logged_in_adapter_instance).to receive(:[]).with(
|
107
|
+
it "#[]" do
|
108
|
+
expect(logged_in_adapter_instance).to receive(:[]).with("my_key") { "my_value" }
|
109
109
|
expect_any_instance_of(logged_out_adapter).not_to receive(:[])
|
110
|
-
expect(subject[
|
110
|
+
expect(subject["my_key"]).to eq("my_value")
|
111
111
|
end
|
112
112
|
|
113
|
-
it
|
114
|
-
expect(logged_in_adapter_instance).to receive(:delete).with(
|
115
|
-
expect(logged_out_adapter_instance).to receive(:delete).with(
|
116
|
-
expect(subject.delete(
|
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
117
|
end
|
118
118
|
|
119
|
-
it
|
120
|
-
expect(logged_in_adapter_instance).to receive(:keys) { [
|
121
|
-
expect(logged_out_adapter_instance).to receive(:keys) { [
|
122
|
-
expect(subject.keys).to eq([
|
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
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
context
|
126
|
+
context "when logged out" do
|
127
127
|
subject do
|
128
128
|
described_class.with_config(
|
129
129
|
logged_in: lambda { |context| false },
|
@@ -133,39 +133,39 @@ describe Split::Persistence::DualAdapter do
|
|
133
133
|
).new(context)
|
134
134
|
end
|
135
135
|
|
136
|
-
it
|
136
|
+
it "#[]=" do
|
137
137
|
expect_any_instance_of(logged_in_adapter).not_to receive(:[]=)
|
138
|
-
expect(logged_out_adapter_instance).to receive(:[]=).with(
|
139
|
-
expect(logged_out_adapter_instance).to receive(:[]).with(
|
140
|
-
subject[
|
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
141
|
end
|
142
142
|
|
143
|
-
it
|
143
|
+
it "#[]" do
|
144
144
|
expect_any_instance_of(logged_in_adapter).not_to receive(:[])
|
145
|
-
expect(logged_out_adapter_instance).to receive(:[]).with(
|
146
|
-
expect(subject[
|
145
|
+
expect(logged_out_adapter_instance).to receive(:[]).with("my_key") { "my_value" }
|
146
|
+
expect(subject["my_key"]).to eq("my_value")
|
147
147
|
end
|
148
148
|
|
149
|
-
it
|
150
|
-
expect(logged_in_adapter_instance).to receive(:delete).with(
|
151
|
-
expect(logged_out_adapter_instance).to receive(:delete).with(
|
152
|
-
expect(subject.delete(
|
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
153
|
end
|
154
154
|
|
155
|
-
it
|
156
|
-
expect(logged_in_adapter_instance).to receive(:keys) { [
|
157
|
-
expect(logged_out_adapter_instance).to receive(:keys) { [
|
158
|
-
expect(subject.keys).to eq([
|
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
159
|
end
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
describe
|
163
|
+
describe "when errors in config" do
|
164
164
|
before { described_class.config.clear }
|
165
|
-
let(:some_proc) { ->{} }
|
165
|
+
let(:some_proc) { -> { } }
|
166
166
|
|
167
|
-
it
|
168
|
-
expect{
|
167
|
+
it "when no logged in adapter" do
|
168
|
+
expect {
|
169
169
|
described_class.with_config(
|
170
170
|
logged_in: some_proc,
|
171
171
|
logged_out_adapter: logged_out_adapter
|
@@ -173,8 +173,8 @@ describe Split::Persistence::DualAdapter do
|
|
173
173
|
}.to raise_error(StandardError, /:logged_in_adapter/)
|
174
174
|
end
|
175
175
|
|
176
|
-
it
|
177
|
-
expect{
|
176
|
+
it "when no logged out adapter" do
|
177
|
+
expect {
|
178
178
|
described_class.with_config(
|
179
179
|
logged_in: some_proc,
|
180
180
|
logged_in_adapter: logged_in_adapter
|
@@ -182,8 +182,8 @@ describe Split::Persistence::DualAdapter do
|
|
182
182
|
}.to raise_error(StandardError, /:logged_out_adapter/)
|
183
183
|
end
|
184
184
|
|
185
|
-
it
|
186
|
-
expect{
|
185
|
+
it "when no logged in detector" do
|
186
|
+
expect {
|
187
187
|
described_class.with_config(
|
188
188
|
logged_in_adapter: logged_in_adapter,
|
189
189
|
logged_out_adapter: logged_out_adapter
|
@@ -1,67 +1,67 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "spec_helper"
|
3
4
|
|
4
5
|
describe Split::Persistence::RedisAdapter do
|
5
|
-
|
6
|
-
let(:context) { double(:lookup => 'blah') }
|
6
|
+
let(:context) { double(lookup: "blah") }
|
7
7
|
|
8
8
|
subject { Split::Persistence::RedisAdapter.new(context) }
|
9
9
|
|
10
|
-
describe
|
10
|
+
describe "#redis_key" do
|
11
11
|
before { Split::Persistence::RedisAdapter.reset_config! }
|
12
12
|
|
13
|
-
context
|
14
|
-
it
|
15
|
-
expect{Split::Persistence::RedisAdapter.new(context)}.to raise_error(RuntimeError)
|
13
|
+
context "default" do
|
14
|
+
it "should raise error with prompt to set lookup_by" do
|
15
|
+
expect { Split::Persistence::RedisAdapter.new(context) }.to raise_error(RuntimeError)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
context
|
19
|
+
context "config with key" do
|
20
20
|
before { Split::Persistence::RedisAdapter.reset_config! }
|
21
|
-
subject { Split::Persistence::RedisAdapter.new(context,
|
21
|
+
subject { Split::Persistence::RedisAdapter.new(context, "manual") }
|
22
22
|
|
23
23
|
it 'should be "persistence:manual"' do
|
24
|
-
expect(subject.redis_key).to eq(
|
24
|
+
expect(subject.redis_key).to eq("persistence:manual")
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
context 'config with lookup_by = proc { "block" }' do
|
29
|
-
before { Split::Persistence::RedisAdapter.with_config(:
|
29
|
+
before { Split::Persistence::RedisAdapter.with_config(lookup_by: proc { "block" }) }
|
30
30
|
|
31
31
|
it 'should be "persistence:block"' do
|
32
|
-
expect(subject.redis_key).to eq(
|
32
|
+
expect(subject.redis_key).to eq("persistence:block")
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
context
|
37
|
-
before { Split::Persistence::RedisAdapter.with_config(:
|
38
|
-
let(:context) { double(:
|
36
|
+
context "config with lookup_by = proc { |context| context.test }" do
|
37
|
+
before { Split::Persistence::RedisAdapter.with_config(lookup_by: proc { "block" }) }
|
38
|
+
let(:context) { double(test: "block") }
|
39
39
|
|
40
40
|
it 'should be "persistence:block"' do
|
41
|
-
expect(subject.redis_key).to eq(
|
41
|
+
expect(subject.redis_key).to eq("persistence:block")
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
45
|
context 'config with lookup_by = "method_name"' do
|
46
|
-
before { Split::Persistence::RedisAdapter.with_config(:
|
47
|
-
let(:context) { double(:
|
46
|
+
before { Split::Persistence::RedisAdapter.with_config(lookup_by: "method_name") }
|
47
|
+
let(:context) { double(method_name: "val") }
|
48
48
|
|
49
49
|
it 'should be "persistence:bar"' do
|
50
|
-
expect(subject.redis_key).to eq(
|
50
|
+
expect(subject.redis_key).to eq("persistence:val")
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
context
|
55
|
-
before { Split::Persistence::RedisAdapter.with_config(:
|
54
|
+
context "config with namespace and lookup_by" do
|
55
|
+
before { Split::Persistence::RedisAdapter.with_config(lookup_by: proc { "frag" }, namespace: "namer") }
|
56
56
|
|
57
57
|
it 'should be "namer"' do
|
58
|
-
expect(subject.redis_key).to eq(
|
58
|
+
expect(subject.redis_key).to eq("namer:frag")
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
describe
|
64
|
-
before { Split::Persistence::RedisAdapter.with_config(:
|
63
|
+
describe "#find" do
|
64
|
+
before { Split::Persistence::RedisAdapter.with_config(lookup_by: proc { "frag" }, namespace: "a_namespace") }
|
65
65
|
|
66
66
|
it "should create and user from a given key" do
|
67
67
|
adapter = Split::Persistence::RedisAdapter.find(2)
|
@@ -69,13 +69,13 @@ describe Split::Persistence::RedisAdapter do
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
context
|
73
|
-
before { Split::Persistence::RedisAdapter.with_config(:
|
72
|
+
context "functional tests" do
|
73
|
+
before { Split::Persistence::RedisAdapter.with_config(lookup_by: "lookup") }
|
74
74
|
|
75
75
|
describe "#[] and #[]=" do
|
76
|
-
it "should set and return the value for given key" do
|
77
|
-
subject["my_key"] =
|
78
|
-
expect(subject["my_key"]).to eq("
|
76
|
+
it "should convert to string, set and return the value for given key" do
|
77
|
+
subject["my_key"] = true
|
78
|
+
expect(subject["my_key"]).to eq("true")
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -94,6 +94,5 @@ describe Split::Persistence::RedisAdapter do
|
|
94
94
|
expect(subject.keys).to match(["my_key", "my_second_key"])
|
95
95
|
end
|
96
96
|
end
|
97
|
-
|
98
97
|
end
|
99
98
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "spec_helper"
|
3
4
|
|
4
5
|
describe Split::Persistence::SessionAdapter do
|
5
|
-
|
6
|
-
let(:context) { double(:session => {}) }
|
6
|
+
let(:context) { double(session: {}) }
|
7
7
|
subject { Split::Persistence::SessionAdapter.new(context) }
|
8
8
|
|
9
9
|
describe "#[] and #[]=" do
|
@@ -28,5 +28,4 @@ describe Split::Persistence::SessionAdapter do
|
|
28
28
|
expect(subject.keys).to match(["my_key", "my_second_key"])
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
32
31
|
end
|
data/spec/persistence_spec.rb
CHANGED
@@ -1,42 +1,54 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe Split::RedisInterface do
|
4
|
-
let(:list_name) {
|
5
|
-
let(:set_name) {
|
6
|
+
let(:list_name) { "list_name" }
|
7
|
+
let(:set_name) { "set_name" }
|
6
8
|
let(:interface) { described_class.new }
|
7
9
|
|
8
|
-
describe
|
10
|
+
describe "#persist_list" do
|
9
11
|
subject(:persist_list) do
|
10
12
|
interface.persist_list(list_name, %w(a b c d))
|
11
13
|
end
|
12
14
|
|
13
15
|
specify do
|
14
16
|
expect(persist_list).to eq %w(a b c d)
|
15
|
-
expect(Split.redis.lindex(list_name, 0)).to eq
|
16
|
-
expect(Split.redis.lindex(list_name, 1)).to eq
|
17
|
-
expect(Split.redis.lindex(list_name, 2)).to eq
|
18
|
-
expect(Split.redis.lindex(list_name, 3)).to eq
|
17
|
+
expect(Split.redis.lindex(list_name, 0)).to eq "a"
|
18
|
+
expect(Split.redis.lindex(list_name, 1)).to eq "b"
|
19
|
+
expect(Split.redis.lindex(list_name, 2)).to eq "c"
|
20
|
+
expect(Split.redis.lindex(list_name, 3)).to eq "d"
|
19
21
|
expect(Split.redis.llen(list_name)).to eq 4
|
20
22
|
end
|
21
23
|
|
22
|
-
context
|
24
|
+
context "list is overwritten but not deleted" do
|
23
25
|
specify do
|
24
26
|
expect(persist_list).to eq %w(a b c d)
|
25
|
-
interface.persist_list(list_name, [
|
26
|
-
expect(Split.redis.lindex(list_name, 0)).to eq
|
27
|
+
interface.persist_list(list_name, ["z"])
|
28
|
+
expect(Split.redis.lindex(list_name, 0)).to eq "z"
|
27
29
|
expect(Split.redis.llen(list_name)).to eq 1
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
describe
|
34
|
+
describe "#add_to_set" do
|
33
35
|
subject(:add_to_set) do
|
34
|
-
interface.add_to_set(set_name,
|
36
|
+
interface.add_to_set(set_name, "something")
|
35
37
|
end
|
36
38
|
|
37
39
|
specify do
|
38
40
|
add_to_set
|
39
|
-
expect(Split.redis.sismember(set_name,
|
41
|
+
expect(Split.redis.sismember(set_name, "something")).to be true
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when a Redis version is used that supports the 'sadd?' method" do
|
45
|
+
before { expect(Split.redis).to receive(:respond_to?).with(:sadd?).and_return(true) }
|
46
|
+
|
47
|
+
it "will use this method instead of 'sadd'" do
|
48
|
+
expect(Split.redis).to receive(:sadd?).with(set_name, "something")
|
49
|
+
expect(Split.redis).not_to receive(:sadd).with(set_name, "something")
|
50
|
+
add_to_set
|
51
|
+
end
|
40
52
|
end
|
41
53
|
end
|
42
54
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,21 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
ENV['RACK_ENV'] = "test"
|
3
2
|
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
3
|
+
ENV["RACK_ENV"] = "test"
|
6
4
|
|
7
|
-
require
|
5
|
+
require "rubygems"
|
6
|
+
require "bundler/setup"
|
7
|
+
|
8
|
+
require "simplecov"
|
8
9
|
SimpleCov.start
|
9
10
|
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
11
|
+
require "split"
|
12
|
+
require "ostruct"
|
13
|
+
require "yaml"
|
14
|
+
require "pry"
|
13
15
|
|
14
|
-
Dir[
|
16
|
+
Dir["./spec/support/*.rb"].each { |f| require f }
|
15
17
|
|
16
18
|
module GlobalSharedContext
|
17
19
|
extend RSpec::SharedContext
|
18
|
-
let(:mock_user){ Split::User.new(double(session: {})) }
|
20
|
+
let(:mock_user) { Split::User.new(double(session: {})) }
|
19
21
|
|
20
22
|
before(:each) do
|
21
23
|
Split.configuration = Split::Configuration.new
|
@@ -24,13 +26,14 @@ module GlobalSharedContext
|
|
24
26
|
Split.redis.flushdb
|
25
27
|
Split::Cache.clear
|
26
28
|
@ab_user = mock_user
|
27
|
-
params = nil
|
29
|
+
@params = nil
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
31
33
|
RSpec.configure do |config|
|
32
|
-
config.order =
|
34
|
+
config.order = "random"
|
33
35
|
config.include GlobalSharedContext
|
36
|
+
config.raise_errors_for_deprecations!
|
34
37
|
end
|
35
38
|
|
36
39
|
def session
|
@@ -41,11 +44,11 @@ def params
|
|
41
44
|
@params ||= {}
|
42
45
|
end
|
43
46
|
|
44
|
-
def request(ua =
|
47
|
+
def request(ua = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; de-de) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27")
|
45
48
|
@request ||= begin
|
46
49
|
r = OpenStruct.new
|
47
50
|
r.user_agent = ua
|
48
|
-
r.ip =
|
51
|
+
r.ip = "192.168.1.1"
|
49
52
|
r
|
50
53
|
end
|
51
54
|
end
|