ab_panel 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/ab_panel.gemspec +3 -3
- data/lib/ab_panel.rb +18 -0
- data/lib/ab_panel/controller_additions.rb +6 -4
- data/lib/ab_panel/version.rb +1 -1
- data/spec/ab_panel/config_spec.rb +6 -6
- data/spec/ab_panel/controller_additions_spec.rb +2 -2
- data/spec/ab_panel/javascript_spec.rb +2 -2
- data/spec/ab_panel_spec.rb +13 -13
- data/spec/array_spec.rb +13 -13
- data/spec/spec_helper.rb +0 -1
- data/spec/support/rails.rb +2 -2
- metadata +19 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ab8ac9d946978fcbccd263665138478ec313ffa
|
4
|
+
data.tar.gz: e1b49731529c1cfc1479b7016e134ea9283f0394
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65e75cf20b2ec836532920e46bafd64357f59c4fa6ea7e9422a096804ea73fab7232cec0a0a80279a5081a4abf021f7db1b545fffd1e3eba0c3578d515cfe890
|
7
|
+
data.tar.gz: 19d6c9284f032990bde35b91915b5b82e5c6063112124b674cb70dd620cb8f38ff570b185115dc0f8a0215736a703465255666a69a40643aeac9f529ec2c3727
|
data/.travis.yml
CHANGED
data/ab_panel.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = AbPanel::VERSION
|
9
9
|
spec.authors = ["Wouter de Vos", "Mark Mulder", "Peter de Ruijter"]
|
10
10
|
spec.email = ["wouter@springest.com", "markmulder@gmail.com", "hello@thisiswho.im"]
|
11
|
-
spec.description = %q{Run A/B test experiments on your Rails
|
12
|
-
spec.summary = %q{Run A/B test experiments on your Rails
|
11
|
+
spec.description = %q{Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.}
|
12
|
+
spec.summary = %q{Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.}
|
13
13
|
spec.homepage = "https://github.com/Springest/ab_panel"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -19,11 +19,11 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
-
spec.add_development_dependency "rails", '~> 3.2'
|
23
22
|
spec.add_development_dependency "rake"
|
24
23
|
spec.add_development_dependency "fakeweb"
|
25
24
|
spec.add_development_dependency "rspec"
|
26
25
|
spec.add_development_dependency "byebug"
|
27
26
|
|
27
|
+
spec.add_runtime_dependency "rails", '~> 4.0'
|
28
28
|
spec.add_runtime_dependency "mixpanel"
|
29
29
|
end
|
data/lib/ab_panel.rb
CHANGED
@@ -22,6 +22,16 @@ module AbPanel
|
|
22
22
|
Thread.current[:ab_panel_conditions] ||= assign_conditions!
|
23
23
|
end
|
24
24
|
|
25
|
+
def serialized_conditions
|
26
|
+
cs = {}
|
27
|
+
|
28
|
+
conditions.each_pair do |key, value|
|
29
|
+
cs[key] = value.marshal_dump
|
30
|
+
end
|
31
|
+
|
32
|
+
cs.to_json
|
33
|
+
end
|
34
|
+
|
25
35
|
# Set the experiment's conditions.
|
26
36
|
#
|
27
37
|
# This is used to persist conditions from
|
@@ -79,6 +89,14 @@ module AbPanel
|
|
79
89
|
def assign_conditions!(already_assigned=nil)
|
80
90
|
cs = {}
|
81
91
|
|
92
|
+
if already_assigned
|
93
|
+
already_assigned.each do |key, value|
|
94
|
+
already_assigned[key] = OpenStruct.new(already_assigned[key])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
already_assigned = OpenStruct.new already_assigned
|
99
|
+
|
82
100
|
experiments.each do |experiment|
|
83
101
|
cs[experiment] ||= {}
|
84
102
|
|
@@ -48,10 +48,12 @@ module AbPanel
|
|
48
48
|
# in the user's session.
|
49
49
|
def initialize_ab_panel!(options = {})
|
50
50
|
AbPanel.reset!
|
51
|
-
|
52
|
-
cookies.signed[
|
53
|
-
|
54
|
-
cookies.signed[
|
51
|
+
|
52
|
+
AbPanel.conditions = JSON.parse(cookies.signed[:ab_panel_conditions])
|
53
|
+
|
54
|
+
cookies.signed[:ab_panel_conditions] = AbPanel.serialized_conditions
|
55
|
+
AbPanel.funnels = Set.new(cookies.signed[:ab_panel_funnels])
|
56
|
+
cookies.signed[:ab_panel_funnels] = AbPanel.funnels
|
55
57
|
|
56
58
|
{
|
57
59
|
'distinct_id' => distinct_id,
|
data/lib/ab_panel/version.rb
CHANGED
@@ -4,32 +4,32 @@ describe AbPanel::Config do
|
|
4
4
|
let(:config) { AbPanel::Config.new }
|
5
5
|
context "config" do
|
6
6
|
before do
|
7
|
-
AbPanel::Config.
|
7
|
+
allow_any_instance_of(AbPanel::Config).to receive(:settings) { { exp1: { scenario1: 25, scenario2: 75 } } }
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '.experiments' do
|
11
11
|
subject { config.experiments }
|
12
|
-
it {
|
12
|
+
it { is_expected.to match_array [:exp1] }
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '.weights' do
|
16
16
|
subject { config.weights('exp1') }
|
17
17
|
|
18
|
-
it {
|
18
|
+
it { is_expected.to match_array [75.0, 25.0] }
|
19
19
|
end
|
20
20
|
end
|
21
21
|
context "empty config" do
|
22
22
|
before do
|
23
|
-
YAML.
|
23
|
+
allow(YAML).to receive(:load) { false }
|
24
24
|
end
|
25
25
|
describe ".settings" do
|
26
26
|
subject { config.settings }
|
27
|
-
it {
|
27
|
+
it { is_expected.to eq nil }
|
28
28
|
end
|
29
29
|
|
30
30
|
describe ".experiments" do
|
31
31
|
subject { config.experiments }
|
32
|
-
it {
|
32
|
+
it { is_expected.to eq({}) }
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -13,9 +13,9 @@ describe AbPanel::ControllerAdditions do
|
|
13
13
|
|
14
14
|
describe "#distinct_id" do
|
15
15
|
let(:cookies) { {} }
|
16
|
-
before { controller.
|
16
|
+
before { expect(controller).to receive_message_chain(:cookies, :signed).and_return(cookies) }
|
17
17
|
subject { controller.distinct_id }
|
18
18
|
|
19
|
-
it {
|
19
|
+
it { is_expected.to match /^([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])([A-Z]|[0-9])$/ }
|
20
20
|
end
|
21
21
|
end
|
@@ -5,12 +5,12 @@ describe AbPanel::Javascript do
|
|
5
5
|
AbPanel.set_env('distinct_id', 'distinct_id')
|
6
6
|
AbPanel.set_env(:properties, { post_name: 'test' })
|
7
7
|
result = JSON.parse(AbPanel::Javascript.environment)
|
8
|
-
result['distinct_id'].
|
8
|
+
expect(result['distinct_id']).to eq 'distinct_id'
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'works without extra properties' do
|
12
12
|
AbPanel.set_env(:properties, nil)
|
13
13
|
result = JSON.parse(AbPanel::Javascript.environment)
|
14
|
-
result['distinct_id'].
|
14
|
+
expect(result['distinct_id']).to eq 'distinct_id'
|
15
15
|
end
|
16
16
|
end
|
data/spec/ab_panel_spec.rb
CHANGED
@@ -4,14 +4,14 @@ describe AbPanel do
|
|
4
4
|
describe ".experiments" do
|
5
5
|
subject { AbPanel.experiments }
|
6
6
|
|
7
|
-
it {
|
7
|
+
it { is_expected.to match_array %w(experiment1 experiment2).map(&:to_sym) }
|
8
8
|
end
|
9
9
|
|
10
10
|
describe ".weights" do
|
11
11
|
let(:experiment) { AbPanel.experiments.first }
|
12
12
|
subject { AbPanel.weights(experiment) }
|
13
13
|
|
14
|
-
it {
|
14
|
+
it { is_expected.to eq [25, 25, 25, 25] }
|
15
15
|
|
16
16
|
describe "With a nonexistent experiment" do
|
17
17
|
let(:experiment) { :does_not_exist }
|
@@ -27,7 +27,7 @@ describe AbPanel do
|
|
27
27
|
|
28
28
|
let(:experiment) { AbPanel.experiments.first }
|
29
29
|
|
30
|
-
it {
|
30
|
+
it { is_expected.to match_array %w( scenario1 scenario2 scenario3 original ).map(&:to_sym) }
|
31
31
|
|
32
32
|
describe "With an nonexistent experiment" do
|
33
33
|
let(:experiment) { :does_not_exist }
|
@@ -41,8 +41,8 @@ describe AbPanel do
|
|
41
41
|
describe ".conditions" do
|
42
42
|
subject { AbPanel.conditions.experiment1 }
|
43
43
|
|
44
|
-
it {
|
45
|
-
it {
|
44
|
+
it { is_expected.to respond_to :scenario1? }
|
45
|
+
it { is_expected.to respond_to :original? }
|
46
46
|
|
47
47
|
describe 'uniqueness' do
|
48
48
|
let(:conditions) do
|
@@ -54,10 +54,10 @@ describe AbPanel do
|
|
54
54
|
]
|
55
55
|
end
|
56
56
|
|
57
|
-
it { conditions.any
|
58
|
-
it { conditions.all
|
59
|
-
it { conditions.select{|c| c}.size.
|
60
|
-
it { conditions.reject{|c| c}.size.
|
57
|
+
it { expect(conditions.any?).to be true }
|
58
|
+
it { expect(conditions.all?).to be false }
|
59
|
+
it { expect(conditions.select{|c| c}.size).to be 1 }
|
60
|
+
it { expect(conditions.reject{|c| c}.size).to be 3 }
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -72,24 +72,24 @@ describe AbPanel do
|
|
72
72
|
|
73
73
|
it 'adds a funnel' do
|
74
74
|
AbPanel.add_funnel('search')
|
75
|
-
AbPanel.funnels.to_a.
|
75
|
+
expect(AbPanel.funnels.to_a).to eq ['search']
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'only adds a funnel when present' do
|
79
79
|
AbPanel.add_funnel(nil)
|
80
|
-
AbPanel.funnels.to_a.
|
80
|
+
expect(AbPanel.funnels.to_a).to eq []
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'does not add a funnel twice' do
|
84
84
|
AbPanel.add_funnel('search')
|
85
85
|
AbPanel.add_funnel('search')
|
86
|
-
AbPanel.funnels.to_a.
|
86
|
+
expect(AbPanel.funnels.to_a).to eq ['search']
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'sets funnels' do
|
90
90
|
funnels = Set.new ['search', 'cta']
|
91
91
|
AbPanel.funnels = funnels
|
92
|
-
AbPanel.funnels.to_a.
|
92
|
+
expect(AbPanel.funnels.to_a).to eq funnels.to_a
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
data/spec/array_spec.rb
CHANGED
@@ -3,47 +3,47 @@ require 'spec_helper'
|
|
3
3
|
describe Array do
|
4
4
|
describe '.weighted_sample' do
|
5
5
|
before do
|
6
|
-
Kernel.
|
6
|
+
allow(Kernel).to receive(:rand) { 0.5 }
|
7
7
|
end
|
8
8
|
|
9
9
|
context "Stub test" do
|
10
10
|
subject { Kernel.rand }
|
11
|
-
it {
|
11
|
+
it { is_expected.to eq 0.5 }
|
12
12
|
end
|
13
13
|
|
14
14
|
let(:array) { [1, 2, 3, 4] }
|
15
15
|
subject { array.weighted_sample }
|
16
16
|
|
17
|
-
it {
|
17
|
+
it { is_expected.to eq 3 }
|
18
18
|
|
19
19
|
context "different random" do
|
20
20
|
before do
|
21
|
-
Kernel.
|
21
|
+
allow(Kernel).to receive(:rand) { 0 }
|
22
22
|
end
|
23
23
|
|
24
|
-
it {
|
24
|
+
it { is_expected.to eq 1 }
|
25
25
|
end
|
26
26
|
|
27
27
|
context "different random" do
|
28
28
|
before do
|
29
|
-
Kernel.
|
29
|
+
allow(Kernel).to receive(:rand) { 1 }
|
30
30
|
end
|
31
31
|
|
32
|
-
it {
|
32
|
+
it { is_expected.to eq 4 }
|
33
33
|
end
|
34
34
|
|
35
35
|
context "with weights" do
|
36
36
|
subject { array.weighted_sample([1, 0, 0, 0]) }
|
37
|
-
it {
|
37
|
+
it { is_expected.to eq 1 }
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
context "all the same weights" do
|
41
|
-
before { Kernel.
|
41
|
+
before { allow(Kernel).to receive(:rand) { 1 } }
|
42
42
|
subject { array.weighted_sample([0, 0, 0, 0]) }
|
43
|
-
it {
|
43
|
+
it { is_expected.to eq 4 }
|
44
44
|
context "random 0" do
|
45
|
-
before { Kernel.
|
46
|
-
it {
|
45
|
+
before { allow(Kernel).to receive(:rand) { 0 } }
|
46
|
+
it { is_expected.to eq 1 }
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/rails.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rails'
|
|
2
2
|
|
3
3
|
RSpec.configure do |c|
|
4
4
|
c.before do
|
5
|
-
Rails.
|
6
|
-
Rails.
|
5
|
+
allow(Rails).to receive(:root) { File.expand_path( '../files', __FILE__ ) }
|
6
|
+
allow(Rails).to receive(:env) { 'test' }
|
7
7
|
end
|
8
8
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ab_panel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter de Vos
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-07-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -26,20 +26,6 @@ dependencies:
|
|
26
26
|
- - "~>"
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '1.3'
|
29
|
-
- !ruby/object:Gem::Dependency
|
30
|
-
name: rails
|
31
|
-
requirement: !ruby/object:Gem::Requirement
|
32
|
-
requirements:
|
33
|
-
- - "~>"
|
34
|
-
- !ruby/object:Gem::Version
|
35
|
-
version: '3.2'
|
36
|
-
type: :development
|
37
|
-
prerelease: false
|
38
|
-
version_requirements: !ruby/object:Gem::Requirement
|
39
|
-
requirements:
|
40
|
-
- - "~>"
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
version: '3.2'
|
43
29
|
- !ruby/object:Gem::Dependency
|
44
30
|
name: rake
|
45
31
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,6 +82,20 @@ dependencies:
|
|
96
82
|
- - ">="
|
97
83
|
- !ruby/object:Gem::Version
|
98
84
|
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rails
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '4.0'
|
92
|
+
type: :runtime
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - "~>"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '4.0'
|
99
99
|
- !ruby/object:Gem::Dependency
|
100
100
|
name: mixpanel
|
101
101
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,7 +110,7 @@ dependencies:
|
|
110
110
|
- - ">="
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: '0'
|
113
|
-
description: Run A/B test experiments on your Rails
|
113
|
+
description: Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.
|
114
114
|
email:
|
115
115
|
- wouter@springest.com
|
116
116
|
- markmulder@gmail.com
|
@@ -228,10 +228,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
228
228
|
version: '0'
|
229
229
|
requirements: []
|
230
230
|
rubyforge_project:
|
231
|
-
rubygems_version: 2.2.
|
231
|
+
rubygems_version: 2.2.5
|
232
232
|
signing_key:
|
233
233
|
specification_version: 4
|
234
|
-
summary: Run A/B test experiments on your Rails
|
234
|
+
summary: Run A/B test experiments on your Rails 4+ site using Mixpanel as a backend.
|
235
235
|
test_files:
|
236
236
|
- example/.gitignore
|
237
237
|
- example/Gemfile
|