mixpal 0.0.5 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop.yml +24 -0
- data/.travis.yml +7 -0
- data/Dockerfile +6 -0
- data/README.md +51 -11
- data/Rakefile +10 -1
- data/docker-compose.yml +14 -0
- data/lib/mixpal.rb +27 -7
- data/lib/mixpal/event.rb +4 -4
- data/lib/mixpal/integration.rb +12 -8
- data/lib/mixpal/revenue.rb +32 -0
- data/lib/mixpal/tracker.rb +44 -27
- data/lib/mixpal/user.rb +9 -7
- data/lib/mixpal/util.rb +3 -3
- data/lib/mixpal/version.rb +1 -1
- data/mixpanel_assistant.gemspec +8 -7
- data/spec/lib/mixpal/event_spec.rb +20 -18
- data/spec/lib/mixpal/revenue_spec.rb +60 -0
- data/spec/lib/mixpal/tracker_spec.rb +181 -153
- data/spec/lib/mixpal/user_spec.rb +37 -31
- data/spec/lib/mixpal/util_spec.rb +15 -14
- data/spec/lib/mixpal_spec.rb +13 -2
- data/spec/spec_helper.rb +4 -7
- data/spec/support/custom_events_module.rb +5 -0
- data/spec/support/matchers/element_matchers.rb +2 -2
- data/test_app/.gitignore +18 -0
- data/test_app/Gemfile +11 -0
- data/test_app/README.rdoc +28 -0
- data/test_app/Rakefile +6 -0
- data/test_app/app/assets/images/.keep +0 -0
- data/test_app/app/assets/javascripts/application.js +16 -0
- data/test_app/app/assets/stylesheets/application.css +15 -0
- data/test_app/app/controllers/application_controller.rb +12 -0
- data/test_app/app/controllers/concerns/.keep +0 -0
- data/test_app/app/controllers/redirects_controller.rb +10 -0
- data/test_app/app/helpers/application_helper.rb +2 -0
- data/test_app/app/mailers/.keep +0 -0
- data/test_app/app/models/.keep +0 -0
- data/test_app/app/models/concerns/.keep +0 -0
- data/test_app/app/views/layouts/application.html.erb +16 -0
- data/test_app/app/views/redirects/new.html.erb +1 -0
- data/test_app/bin/bundle +3 -0
- data/test_app/bin/rails +8 -0
- data/test_app/bin/rake +8 -0
- data/test_app/bin/spring +18 -0
- data/test_app/config.ru +4 -0
- data/test_app/config/application.rb +30 -0
- data/test_app/config/boot.rb +4 -0
- data/test_app/config/environment.rb +5 -0
- data/test_app/config/environments/development.rb +37 -0
- data/test_app/config/environments/production.rb +82 -0
- data/test_app/config/environments/test.rb +39 -0
- data/test_app/config/initializers/assets.rb +8 -0
- data/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test_app/config/initializers/cookies_serializer.rb +3 -0
- data/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/test_app/config/initializers/inflections.rb +16 -0
- data/test_app/config/initializers/mime_types.rb +4 -0
- data/test_app/config/initializers/session_store.rb +3 -0
- data/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/test_app/config/locales/en.yml +23 -0
- data/test_app/config/routes.rb +4 -0
- data/test_app/config/secrets.yml +22 -0
- data/test_app/db/seeds.rb +7 -0
- data/test_app/lib/assets/.keep +0 -0
- data/test_app/lib/tasks/.keep +0 -0
- data/test_app/log/.keep +0 -0
- data/test_app/public/404.html +67 -0
- data/test_app/public/422.html +67 -0
- data/test_app/public/500.html +66 -0
- data/test_app/public/favicon.ico +0 -0
- data/test_app/public/robots.txt +5 -0
- data/test_app/vendor/assets/javascripts/.keep +0 -0
- data/test_app/vendor/assets/stylesheets/.keep +0 -0
- metadata +112 -44
- data/spec/support/mock_rails.rb +0 -6
- data/spec/support/mock_storage.rb +0 -19
data/lib/mixpal/util.rb
CHANGED
@@ -2,12 +2,12 @@ module Mixpal
|
|
2
2
|
module Util
|
3
3
|
class << self
|
4
4
|
def hash_to_js_object_string(hash)
|
5
|
-
hash.reject! { |
|
5
|
+
hash.reject! { |_, v| v.nil? }
|
6
6
|
|
7
|
-
contents = hash.map do |k,v|
|
7
|
+
contents = hash.map do |k, v|
|
8
8
|
js_value = v.is_a?(String) || v.is_a?(Time) ? "\"#{v}\"" : v
|
9
9
|
"\"#{k}\": #{js_value}"
|
10
|
-
end.join(
|
10
|
+
end.join(',').html_safe
|
11
11
|
|
12
12
|
"{#{contents}}"
|
13
13
|
end
|
data/lib/mixpal/version.rb
CHANGED
data/mixpanel_assistant.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'mixpal/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "mixpal"
|
8
8
|
spec.version = Mixpal::VERSION
|
9
|
-
spec.authors = ["patbenatar"]
|
9
|
+
spec.authors = ["patbenatar", "mikehmorrissey"]
|
10
10
|
spec.email = ["nick@gophilosophie.com"]
|
11
11
|
spec.description = "Use Mixpanel's JavaScript library from your backend with ease"
|
12
12
|
spec.summary = "As the JavaScript library is Mixpanel's preferred method of usage, Mixpal aims to make it easier to work with from your Rails backend. Most notably it persists tracking data across redirects, perfect for handling events like user sign ups or form submissions."
|
@@ -18,14 +18,15 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "bundler", "~>
|
21
|
+
spec.add_development_dependency "bundler", "~> 2"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "pry"
|
24
|
-
spec.add_development_dependency "
|
25
|
-
spec.add_development_dependency "
|
26
|
-
spec.add_development_dependency "
|
27
|
-
spec.add_development_dependency "
|
28
|
-
spec.add_development_dependency "
|
24
|
+
spec.add_development_dependency "rubocop", "~> 0.91.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.9.0"
|
26
|
+
spec.add_development_dependency "guard-rspec", "~> 4.7.3"
|
27
|
+
spec.add_development_dependency "rb-fsevent", "~> 0.10.4"
|
28
|
+
spec.add_development_dependency "awesome_print", "~> 1.8.0"
|
29
|
+
spec.add_development_dependency "nokogiri", "~> 1"
|
29
30
|
|
30
31
|
spec.add_development_dependency "actionpack", ">= 3.0"
|
31
32
|
|
@@ -1,48 +1,50 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Mixpal::Event do
|
4
|
-
let(:name) {
|
5
|
-
let(:properties) { { title:
|
4
|
+
let(:name) { 'Event 1' }
|
5
|
+
let(:properties) { { title: 'Awesome Product' } }
|
6
6
|
subject { described_class.new(name, properties) }
|
7
7
|
|
8
|
-
describe
|
9
|
-
it
|
10
|
-
Mixpal::Util.
|
8
|
+
describe '#render' do
|
9
|
+
it 'delegates to Util for js_object composition' do
|
10
|
+
expect(Mixpal::Util).to receive(:hash_to_js_object_string).with(properties)
|
11
11
|
subject.render
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
14
|
+
it 'outputs a call to track' do
|
15
15
|
js_object = Mixpal::Util.hash_to_js_object_string(properties)
|
16
16
|
expect(subject.render).to eq "mixpanel.track(\"#{name}\", #{js_object});"
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
19
|
+
it 'outputs an html safe string' do
|
20
20
|
expect(subject.render).to be_html_safe
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
describe
|
25
|
-
it
|
24
|
+
describe '#to_store' do
|
25
|
+
it 'returns a hash with its data' do
|
26
26
|
expect(subject.to_store).to eq(
|
27
|
-
name
|
28
|
-
properties
|
27
|
+
'name' => name,
|
28
|
+
'properties' => properties
|
29
29
|
)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
describe
|
34
|
-
let(:result)
|
33
|
+
describe '.from_store' do
|
34
|
+
let(:result) do
|
35
|
+
described_class.from_store('name' => name, 'properties' => properties)
|
36
|
+
end
|
35
37
|
|
36
|
-
it
|
38
|
+
it 'instantiates a new instance' do
|
37
39
|
expect(result).to be_an_instance_of(described_class)
|
38
40
|
end
|
39
41
|
|
40
|
-
it
|
42
|
+
it 'sets its name from the data' do
|
41
43
|
expect(result.name).to eq name
|
42
44
|
end
|
43
45
|
|
44
|
-
it
|
46
|
+
it 'sets its properties from the data' do
|
45
47
|
expect(result.properties).to eq properties
|
46
48
|
end
|
47
49
|
end
|
48
|
-
end
|
50
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mixpal::Revenue do
|
4
|
+
let(:properties) do
|
5
|
+
{
|
6
|
+
sku: 'SKU-1010'
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:amount) { 50 }
|
11
|
+
|
12
|
+
let(:subject) { described_class.new(amount, properties) }
|
13
|
+
|
14
|
+
describe '#render' do
|
15
|
+
it 'delegates to Util for js_object composition' do
|
16
|
+
expect(Mixpal::Util).to receive(:hash_to_js_object_string).with(properties)
|
17
|
+
subject.render
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'outputs a call to people.track_charge' do
|
21
|
+
js_object = Mixpal::Util.hash_to_js_object_string(properties)
|
22
|
+
expect(subject.render)
|
23
|
+
.to eq "mixpanel.people.track_charge(#{amount}, #{js_object});"
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'outputs an html safe string' do
|
27
|
+
expect(subject.render).to be_html_safe
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#to_store' do
|
32
|
+
it 'returns a hash with its data' do
|
33
|
+
expect(subject.to_store).to eq(
|
34
|
+
'amount' => amount,
|
35
|
+
'properties' => properties
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#from_store' do
|
41
|
+
let(:result) do
|
42
|
+
described_class.from_store(
|
43
|
+
'amount' => amount,
|
44
|
+
'properties' => properties
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'instantiates a new instance' do
|
49
|
+
expect(result).to be_an_instance_of(described_class)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'sets its amount from the data' do
|
53
|
+
expect(result.amount).to eq amount
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'sets its properties from the data' do
|
57
|
+
expect(result.properties).to eq properties
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -1,278 +1,306 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Mixpal::Tracker do
|
4
4
|
subject { Mixpal::Tracker.new }
|
5
|
-
let(:identity) {
|
5
|
+
let(:identity) { 'nick' }
|
6
6
|
let(:subject_with_identity) { Mixpal::Tracker.new(identity: identity) }
|
7
7
|
|
8
|
-
|
8
|
+
context 'with configured helper module' do
|
9
9
|
before do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@adapter_instance = MyCustomStorageAdapter.new
|
14
|
-
|
15
|
-
described_class.storage = @adapter_instance
|
10
|
+
Mixpal.configure do |config|
|
11
|
+
config.helper_module = CustomEventsModule
|
12
|
+
end
|
16
13
|
end
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
it "uses the specified adapter" do
|
21
|
-
@adapter_instance.should_receive :write
|
22
|
-
subject.store!
|
15
|
+
it 'exposes helper module methods on tracker instance' do
|
16
|
+
expect(subject.custom_event).to eq true
|
23
17
|
end
|
24
18
|
end
|
25
19
|
|
26
|
-
describe
|
27
|
-
it
|
20
|
+
describe '#initialize' do
|
21
|
+
it 'creates an empty set of events' do
|
28
22
|
expect(subject.events).to eq []
|
29
23
|
end
|
30
24
|
|
31
|
-
it
|
25
|
+
it 'creates an empty set of user_updates' do
|
32
26
|
expect(subject.user_updates).to eq []
|
33
27
|
end
|
34
28
|
|
35
|
-
|
36
|
-
subject
|
37
|
-
|
38
|
-
it "sets the identity" do
|
39
|
-
expect(subject.identity).to eq "nick"
|
40
|
-
end
|
29
|
+
it 'creates an empty set of revenue_updates' do
|
30
|
+
expect(subject.revenue_updates).to eq []
|
41
31
|
end
|
42
32
|
|
43
|
-
context
|
44
|
-
|
45
|
-
|
46
|
-
before do
|
47
|
-
old_tracker.track "Event 1"
|
48
|
-
old_tracker.register_user name: "Nick Giancola"
|
49
|
-
old_tracker.store!
|
50
|
-
end
|
51
|
-
|
52
|
-
it "restores the alias_user property" do
|
53
|
-
expect(subject.alias_user).to eq true
|
54
|
-
end
|
55
|
-
|
56
|
-
it "restores the events" do
|
57
|
-
expect(subject.events.size).to eq 1
|
58
|
-
end
|
59
|
-
|
60
|
-
it "delegates event restoration to the Event class" do
|
61
|
-
Mixpal::Event.should_receive(:from_store).
|
62
|
-
with(old_tracker.events.first.to_store)
|
63
|
-
|
64
|
-
subject
|
65
|
-
end
|
66
|
-
|
67
|
-
it "restores the events" do
|
68
|
-
expect(subject.events.size).to eq 1
|
69
|
-
end
|
70
|
-
|
71
|
-
context "when initialized with an identity" do
|
72
|
-
subject { Mixpal::Tracker.new(identity: "Franky") }
|
33
|
+
context 'with an :identity arg' do
|
34
|
+
subject { subject_with_identity }
|
73
35
|
|
74
|
-
|
75
|
-
|
76
|
-
end
|
36
|
+
it 'sets the identity' do
|
37
|
+
expect(subject.identity).to eq 'nick'
|
77
38
|
end
|
78
39
|
end
|
79
40
|
end
|
80
41
|
|
81
|
-
describe
|
82
|
-
it
|
83
|
-
subject.register_user(name:
|
84
|
-
expect(subject.alias_user).to
|
42
|
+
describe '#register_user' do
|
43
|
+
it 'sets the alias_user flag so we render the alias call' do
|
44
|
+
subject.register_user(name: 'Nick')
|
45
|
+
expect(subject.alias_user).to be true
|
85
46
|
end
|
86
47
|
|
87
|
-
it
|
88
|
-
properties = { name:
|
89
|
-
subject.
|
48
|
+
it 'delegates to #update_user for tracking user properties' do
|
49
|
+
properties = { name: 'Nick' }
|
50
|
+
expect(subject).to receive(:update_user).with(properties)
|
90
51
|
subject.register_user(properties)
|
91
52
|
end
|
92
53
|
end
|
93
54
|
|
94
|
-
describe
|
95
|
-
it
|
96
|
-
properties = { name:
|
97
|
-
Mixpal::User.
|
55
|
+
describe '#update_user' do
|
56
|
+
it 'instantiates a new User object with properties' do
|
57
|
+
properties = { name: 'Nick' }
|
58
|
+
expect(Mixpal::User).to receive(:new).with(properties)
|
98
59
|
subject.update_user(properties)
|
99
60
|
end
|
100
61
|
|
101
|
-
it
|
62
|
+
it 'adds the User to user_updates for rendering later' do
|
102
63
|
expect do
|
103
|
-
subject.update_user(name:
|
64
|
+
subject.update_user(name: 'Nick')
|
104
65
|
end.to change(subject.user_updates, :size).by(1)
|
105
66
|
|
106
|
-
subject.user_updates.first.
|
67
|
+
expect(subject.user_updates.first).to be_an_instance_of(Mixpal::User)
|
107
68
|
end
|
108
69
|
end
|
109
70
|
|
110
|
-
describe
|
111
|
-
it
|
112
|
-
name =
|
113
|
-
properties = { color:
|
71
|
+
describe '#track' do
|
72
|
+
it 'instantiates a new Event object with properties' do
|
73
|
+
name = 'Clicked Button'
|
74
|
+
properties = { color: 'Green' }
|
114
75
|
|
115
|
-
Mixpal::Event.
|
76
|
+
expect(Mixpal::Event).to receive(:new).with(name, properties)
|
116
77
|
subject.track(name, properties)
|
117
78
|
end
|
118
79
|
|
119
|
-
it
|
80
|
+
it 'adds the Event to events for rendering later' do
|
120
81
|
expect do
|
121
|
-
subject.track(
|
82
|
+
subject.track('Clicked Button', color: 'Green')
|
122
83
|
end.to change(subject.events, :size).by(1)
|
123
84
|
|
124
|
-
subject.events.first.
|
85
|
+
expect(subject.events.first).to be_an_instance_of(Mixpal::Event)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#track_charge' do
|
90
|
+
it 'instantiates a new Revenue object with properties' do
|
91
|
+
properties = { sku: 'SKU-1010' }
|
92
|
+
expect(Mixpal::Revenue).to receive(:new).with(50, properties)
|
93
|
+
subject.track_charge(50, properties)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'adds the Revenue to revenue_updates for rendering later' do
|
97
|
+
expect do
|
98
|
+
subject.track_charge(50, sku: 'SKU-1010')
|
99
|
+
end.to change(subject.revenue_updates, :size).by(1)
|
100
|
+
|
101
|
+
expect(subject.revenue_updates.first).to be_an_instance_of(Mixpal::Revenue)
|
125
102
|
end
|
126
103
|
end
|
127
104
|
|
128
|
-
describe
|
129
|
-
it
|
130
|
-
expect(subject.render).to have_tag(
|
105
|
+
describe '#render' do
|
106
|
+
it 'outputs script tag' do
|
107
|
+
expect(subject.render).to have_tag('script')
|
131
108
|
end
|
132
109
|
|
133
|
-
it
|
110
|
+
it 'outputs an html safe string' do
|
134
111
|
expect(subject.render).to be_html_safe
|
135
112
|
end
|
136
113
|
|
137
|
-
context
|
114
|
+
context 'with an identity' do
|
138
115
|
subject { subject_with_identity }
|
139
116
|
|
140
|
-
it
|
117
|
+
it 'outputs call to identify' do
|
141
118
|
expect(subject.render).to include "mixpanel.identify(\"#{identity}\");"
|
142
119
|
end
|
143
120
|
|
144
|
-
context
|
145
|
-
before { subject.register_user(
|
121
|
+
context 'when user is being registered' do
|
122
|
+
before { subject.register_user(name: 'Nick Giancola') }
|
146
123
|
|
147
|
-
it
|
124
|
+
it 'outputs call to alias by identity' do
|
148
125
|
expect(subject.render).to include "mixpanel.alias(\"#{identity}\");"
|
149
126
|
end
|
150
127
|
end
|
151
128
|
end
|
152
129
|
|
153
|
-
context
|
154
|
-
it
|
155
|
-
expect(subject.render).not_to include
|
130
|
+
context 'with no registered user' do
|
131
|
+
it 'does not output call to alias' do
|
132
|
+
expect(subject.render).not_to include 'mixpanel.alias'
|
156
133
|
end
|
157
134
|
end
|
158
135
|
|
159
|
-
context
|
160
|
-
it
|
161
|
-
expect(subject.render).not_to include
|
136
|
+
context 'without an identity' do
|
137
|
+
it 'does not output call to identify' do
|
138
|
+
expect(subject.render).not_to include 'mixpanel.indentify'
|
162
139
|
end
|
163
140
|
end
|
164
141
|
|
165
|
-
context
|
142
|
+
context 'with tracked events' do
|
166
143
|
before do
|
167
|
-
subject.track(
|
168
|
-
subject.track(
|
144
|
+
subject.track('Event 1', color: 'Green')
|
145
|
+
subject.track('Event 2', title: 'Something Awesome')
|
169
146
|
end
|
170
147
|
|
171
|
-
it
|
172
|
-
subject.events.each { |event| event.
|
148
|
+
it 'delegates render to the events' do
|
149
|
+
subject.events.each { |event| expect(event).to receive :render }
|
173
150
|
subject.render
|
174
151
|
end
|
175
152
|
|
176
|
-
it
|
153
|
+
it 'joins each rendered event' do
|
177
154
|
joined = subject.events[0].render + subject.events[1].render
|
178
155
|
expect(subject.render).to include joined
|
179
156
|
end
|
180
157
|
end
|
181
158
|
|
182
|
-
context
|
159
|
+
context 'with user properties' do
|
183
160
|
before do
|
184
|
-
subject.update_user(
|
185
|
-
subject.update_user(
|
161
|
+
subject.update_user(name: 'Hank')
|
162
|
+
subject.update_user(location: 'Los Angeles')
|
186
163
|
end
|
187
164
|
|
188
|
-
it
|
189
|
-
subject.user_updates.each { |user| user.
|
165
|
+
it 'delegates render to the users' do
|
166
|
+
subject.user_updates.each { |user| expect(user).to receive :render }
|
190
167
|
subject.render
|
191
168
|
end
|
192
169
|
|
193
|
-
it
|
170
|
+
it 'joins each rendered user' do
|
194
171
|
joined = subject.user_updates[0].render + subject.user_updates[1].render
|
195
172
|
expect(subject.render).to include joined
|
196
173
|
end
|
197
174
|
end
|
198
|
-
end
|
199
|
-
|
200
|
-
describe "#store!" do
|
201
|
-
let(:storage) { described_class::storage }
|
202
175
|
|
203
|
-
|
176
|
+
context 'with revenue' do
|
177
|
+
before do
|
178
|
+
subject.track_charge(50)
|
179
|
+
subject.track_charge(100, sku: 'SKU-1010')
|
180
|
+
end
|
204
181
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
)
|
210
|
-
end
|
182
|
+
it 'delegates render to the revenues' do
|
183
|
+
subject.revenue_updates.each { |r| expect(r).to receive :render }
|
184
|
+
subject.render
|
185
|
+
end
|
211
186
|
|
212
|
-
|
213
|
-
|
214
|
-
|
187
|
+
it 'joins each rendered revenue' do
|
188
|
+
joined =
|
189
|
+
subject.revenue_updates[0].render + subject.revenue_updates[1].render
|
190
|
+
expect(subject.render).to include joined
|
191
|
+
end
|
215
192
|
end
|
193
|
+
end
|
216
194
|
|
217
|
-
|
218
|
-
|
195
|
+
describe '#store!' do
|
196
|
+
let(:session) { {} }
|
219
197
|
|
220
|
-
|
221
|
-
|
222
|
-
subject.store!
|
223
|
-
end
|
198
|
+
def expect_storage_to_include(hash_fragment)
|
199
|
+
expect(session[described_class::STORAGE_KEY]).to include hash_fragment
|
224
200
|
end
|
225
201
|
|
226
|
-
|
227
|
-
subject
|
202
|
+
it 'stores the alias_user property' do
|
203
|
+
subject.register_user({})
|
204
|
+
subject.store!(session)
|
205
|
+
expect_storage_to_include('alias_user' => true)
|
206
|
+
end
|
228
207
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
end
|
208
|
+
it 'stores the identity' do
|
209
|
+
subject_with_identity.store!(session)
|
210
|
+
expect_storage_to_include('identity' => identity)
|
233
211
|
end
|
234
212
|
|
235
|
-
context
|
213
|
+
context 'when events have been tracked' do
|
236
214
|
before do
|
237
|
-
subject.track(
|
238
|
-
subject.track(
|
215
|
+
subject.track('Event 1', color: 'Green')
|
216
|
+
subject.track('Event 2', title: 'Something Awesome')
|
239
217
|
end
|
240
218
|
|
241
|
-
it
|
242
|
-
subject.events.each { |event| event.
|
243
|
-
subject.store!
|
219
|
+
it 'delegates composition to the events' do
|
220
|
+
subject.events.each { |event| expect(event).to receive :to_store }
|
221
|
+
subject.store!(session)
|
244
222
|
end
|
245
223
|
|
246
|
-
it
|
247
|
-
|
248
|
-
|
224
|
+
it 'stores the events composed hashes in an array' do
|
225
|
+
subject.store!(session)
|
226
|
+
expect_storage_to_include(
|
227
|
+
'events' => [subject.events[0].to_store, subject.events[1].to_store]
|
249
228
|
)
|
250
|
-
|
251
|
-
subject.store!
|
252
229
|
end
|
253
230
|
end
|
254
231
|
|
255
|
-
context
|
232
|
+
context 'when user properties have been updated' do
|
256
233
|
before do
|
257
|
-
subject.update_user(
|
258
|
-
subject.update_user(
|
234
|
+
subject.update_user(name: 'Hank')
|
235
|
+
subject.update_user(location: 'Los Angeles')
|
259
236
|
end
|
260
237
|
|
261
|
-
it
|
262
|
-
subject.user_updates.each { |user| user.
|
263
|
-
subject.store!
|
238
|
+
it 'delegates composition to the users' do
|
239
|
+
subject.user_updates.each { |user| expect(user).to receive :to_store }
|
240
|
+
subject.store!(session)
|
264
241
|
end
|
265
242
|
|
266
|
-
it
|
267
|
-
|
268
|
-
|
243
|
+
it 'stores the users composed hashes in an array' do
|
244
|
+
subject.store!(session)
|
245
|
+
|
246
|
+
expect_storage_to_include(
|
247
|
+
'user_updates' => [
|
269
248
|
subject.user_updates[0].to_store,
|
270
249
|
subject.user_updates[1].to_store
|
271
250
|
]
|
272
251
|
)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe '#restore!' do
|
257
|
+
let(:old_tracker) { Mixpal::Tracker.new(identity: identity) }
|
258
|
+
let(:session) { {} }
|
259
|
+
|
260
|
+
before do
|
261
|
+
old_tracker.track 'Event 1'
|
262
|
+
old_tracker.register_user name: 'Nick Giancola'
|
263
|
+
old_tracker.store!(session)
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'restores the alias_user property' do
|
267
|
+
subject.restore!(session)
|
268
|
+
expect(subject.alias_user).to eq true
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'restores the events' do
|
272
|
+
subject.restore!(session)
|
273
|
+
expect(subject.events.size).to eq 1
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'delegates event restoration to the Event class' do
|
277
|
+
expect(Mixpal::Event).to receive(:from_store)
|
278
|
+
.with(old_tracker.events.first.to_store)
|
279
|
+
|
280
|
+
subject.restore!(session)
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'restores the events' do
|
284
|
+
subject.restore!(session)
|
285
|
+
expect(subject.events.size).to eq 1
|
286
|
+
end
|
287
|
+
|
288
|
+
context 'with a different identity (e.g. after login)' do
|
289
|
+
subject { Mixpal::Tracker.new(identity: "#{identity}-2") }
|
290
|
+
|
291
|
+
it 'does not override identity with value in storage' do
|
292
|
+
subject.restore!(session)
|
293
|
+
expect(subject.identity).to eq "#{identity}-2"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
context 'with no identity (e.g. after logout)' do
|
298
|
+
subject { Mixpal::Tracker.new(identity: nil) }
|
273
299
|
|
274
|
-
|
300
|
+
it 'overrides identity with value in storage' do
|
301
|
+
subject.restore!(session)
|
302
|
+
expect(subject.identity).to eq identity
|
275
303
|
end
|
276
304
|
end
|
277
305
|
end
|
278
|
-
end
|
306
|
+
end
|