magellanalytics 0.2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,129 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="RUBY_MODULE" version="4">
3
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
4
+ <exclude-output />
5
+ <content url="file://$MODULE_DIR$" />
6
+ <orderEntry type="jdk" jdkName="RVM: ruby-3.1.2 [magellanalytics]" jdkType="RUBY_SDK" />
7
+ <orderEntry type="sourceFolder" forTests="false" />
8
+ <orderEntry type="library" scope="PROVIDED" name="actionpack (v7.0.4.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
9
+ <orderEntry type="library" scope="PROVIDED" name="actionview (v7.0.4.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
10
+ <orderEntry type="library" scope="PROVIDED" name="activesupport (v7.0.4.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
11
+ <orderEntry type="library" scope="PROVIDED" name="addressable (v2.8.4, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
12
+ <orderEntry type="library" scope="PROVIDED" name="analytics-ruby (v2.4.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
13
+ <orderEntry type="library" scope="PROVIDED" name="ast (v2.4.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
14
+ <orderEntry type="library" scope="PROVIDED" name="builder (v3.2.4, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
15
+ <orderEntry type="library" scope="PROVIDED" name="bundler (v2.2.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
16
+ <orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.2.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
17
+ <orderEntry type="library" scope="PROVIDED" name="crass (v1.0.6, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
18
+ <orderEntry type="library" scope="PROVIDED" name="descendants_tracker (v0.0.4, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
19
+ <orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.5.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
20
+ <orderEntry type="library" scope="PROVIDED" name="docile (v1.4.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
21
+ <orderEntry type="library" scope="PROVIDED" name="erubi (v1.12.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
22
+ <orderEntry type="library" scope="PROVIDED" name="faraday (v1.10.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
23
+ <orderEntry type="library" scope="PROVIDED" name="faraday-em_http (v1.0.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
24
+ <orderEntry type="library" scope="PROVIDED" name="faraday-em_synchrony (v1.0.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
25
+ <orderEntry type="library" scope="PROVIDED" name="faraday-excon (v1.1.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
26
+ <orderEntry type="library" scope="PROVIDED" name="faraday-httpclient (v1.0.1, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
27
+ <orderEntry type="library" scope="PROVIDED" name="faraday-multipart (v1.0.4, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
28
+ <orderEntry type="library" scope="PROVIDED" name="faraday-net_http (v1.0.1, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
29
+ <orderEntry type="library" scope="PROVIDED" name="faraday-net_http_persistent (v1.2.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
30
+ <orderEntry type="library" scope="PROVIDED" name="faraday-patron (v1.0.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
31
+ <orderEntry type="library" scope="PROVIDED" name="faraday-rack (v1.0.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
32
+ <orderEntry type="library" scope="PROVIDED" name="faraday-retry (v1.0.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
33
+ <orderEntry type="library" scope="PROVIDED" name="git (v1.18.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
34
+ <orderEntry type="library" scope="PROVIDED" name="github_api (v0.19.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
35
+ <orderEntry type="library" scope="PROVIDED" name="hashie (v3.6.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
36
+ <orderEntry type="library" scope="PROVIDED" name="highline (v2.1.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
37
+ <orderEntry type="library" scope="PROVIDED" name="i18n (v1.12.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
38
+ <orderEntry type="library" scope="PROVIDED" name="json (v2.6.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
39
+ <orderEntry type="library" scope="PROVIDED" name="juwelier (v2.4.9, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
40
+ <orderEntry type="library" scope="PROVIDED" name="jwt (v2.7.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
41
+ <orderEntry type="library" scope="PROVIDED" name="kamelcase (v0.0.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
42
+ <orderEntry type="library" scope="PROVIDED" name="loofah (v2.20.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
43
+ <orderEntry type="library" scope="PROVIDED" name="mini_portile2 (v2.8.1, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
44
+ <orderEntry type="library" scope="PROVIDED" name="minitest (v5.18.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
45
+ <orderEntry type="library" scope="PROVIDED" name="multi_json (v1.15.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
46
+ <orderEntry type="library" scope="PROVIDED" name="multi_xml (v0.6.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
47
+ <orderEntry type="library" scope="PROVIDED" name="multipart-post (v2.3.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
48
+ <orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.14.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
49
+ <orderEntry type="library" scope="PROVIDED" name="oauth2 (v1.4.11, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
50
+ <orderEntry type="library" scope="PROVIDED" name="parallel (v1.23.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
51
+ <orderEntry type="library" scope="PROVIDED" name="parser (v3.2.2.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
52
+ <orderEntry type="library" scope="PROVIDED" name="psych (v5.1.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
53
+ <orderEntry type="library" scope="PROVIDED" name="public_suffix (v5.0.1, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
54
+ <orderEntry type="library" scope="PROVIDED" name="racc (v1.6.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
55
+ <orderEntry type="library" scope="PROVIDED" name="rack (v2.2.6.4, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
56
+ <orderEntry type="library" scope="PROVIDED" name="rack-test (v2.1.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
57
+ <orderEntry type="library" scope="PROVIDED" name="rails-dom-testing (v2.0.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
58
+ <orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.5.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
59
+ <orderEntry type="library" scope="PROVIDED" name="rainbow (v3.1.1, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
60
+ <orderEntry type="library" scope="PROVIDED" name="rake (v13.0.6, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
61
+ <orderEntry type="library" scope="PROVIDED" name="rchardet (v1.8.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
62
+ <orderEntry type="library" scope="PROVIDED" name="rdoc (v6.5.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
63
+ <orderEntry type="library" scope="PROVIDED" name="regexp_parser (v2.8.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
64
+ <orderEntry type="library" scope="PROVIDED" name="rexml (v3.2.5, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
65
+ <orderEntry type="library" scope="PROVIDED" name="rspec (v3.12.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
66
+ <orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.12.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
67
+ <orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.12.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
68
+ <orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.12.5, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
69
+ <orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.12.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
70
+ <orderEntry type="library" scope="PROVIDED" name="rubocop (v1.50.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
71
+ <orderEntry type="library" scope="PROVIDED" name="rubocop-ast (v1.28.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
72
+ <orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.13.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
73
+ <orderEntry type="library" scope="PROVIDED" name="semver2 (v3.4.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
74
+ <orderEntry type="library" scope="PROVIDED" name="shoulda (v4.0.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
75
+ <orderEntry type="library" scope="PROVIDED" name="shoulda-context (v2.0.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
76
+ <orderEntry type="library" scope="PROVIDED" name="shoulda-matchers (v4.5.1, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
77
+ <orderEntry type="library" scope="PROVIDED" name="simplecov (v0.22.0, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
78
+ <orderEntry type="library" scope="PROVIDED" name="simplecov-html (v0.12.3, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
79
+ <orderEntry type="library" scope="PROVIDED" name="simplecov_json_formatter (v0.1.4, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
80
+ <orderEntry type="library" scope="PROVIDED" name="stringio (v3.0.6, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
81
+ <orderEntry type="library" scope="PROVIDED" name="thread_safe (v0.3.6, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
82
+ <orderEntry type="library" scope="PROVIDED" name="tzinfo (v2.0.6, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
83
+ <orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v2.4.2, RVM: ruby-3.1.2 [magellanalytics]) [gem]" level="application" />
84
+ </component>
85
+ <component name="RakeTasksCache">
86
+ <option name="myRootTask">
87
+ <RakeTaskImpl id="rake">
88
+ <subtasks>
89
+ <RakeTaskImpl description="Build gem into pkg/" fullCommand="build" id="build" />
90
+ <RakeTaskImpl description="Remove any temporary products" fullCommand="clean" id="clean" />
91
+ <RakeTaskImpl description="Remove any generated files" fullCommand="clobber" id="clobber" />
92
+ <RakeTaskImpl description="Remove RDoc HTML files" fullCommand="clobber_rdoc" id="clobber_rdoc" />
93
+ <RakeTaskImpl description="Start IRB with all runtime dependencies loaded" fullCommand="console[script]" id="console[script]" />
94
+ <RakeTaskImpl id="gemcutter">
95
+ <subtasks>
96
+ <RakeTaskImpl description="Release gem to Gemcutter" fullCommand="gemcutter:release" id="release" />
97
+ </subtasks>
98
+ </RakeTaskImpl>
99
+ <RakeTaskImpl description="Generate and validate gemspec" fullCommand="gemspec" id="gemspec" />
100
+ <RakeTaskImpl id="gemspec">
101
+ <subtasks>
102
+ <RakeTaskImpl description="Display the gemspec for debugging purposes, as juwelier knows it (not from the filesystem)" fullCommand="gemspec:debug" id="debug" />
103
+ <RakeTaskImpl description="Regenerate the gemspec on the filesystem" fullCommand="gemspec:generate" id="generate" />
104
+ <RakeTaskImpl description="Regenerate and validate gemspec, and then commits and pushes to git" fullCommand="gemspec:release" id="release" />
105
+ <RakeTaskImpl description="Validates the gemspec on the filesystem" fullCommand="gemspec:validate" id="validate" />
106
+ </subtasks>
107
+ </RakeTaskImpl>
108
+ <RakeTaskImpl id="git">
109
+ <subtasks>
110
+ <RakeTaskImpl description="Tag and push release to git" fullCommand="git:release" id="release" />
111
+ </subtasks>
112
+ </RakeTaskImpl>
113
+ <RakeTaskImpl description="Build and install gem using `gem install`" fullCommand="install" id="install" />
114
+ <RakeTaskImpl description="Build RDoc HTML files" fullCommand="rdoc" id="rdoc" />
115
+ <RakeTaskImpl description="Release gem" fullCommand="release" id="release" />
116
+ <RakeTaskImpl description="Rebuild RDoc HTML files" fullCommand="rerdoc" id="rerdoc" />
117
+ <RakeTaskImpl description="Code coverage detail" fullCommand="simplecov" id="simplecov" />
118
+ <RakeTaskImpl description="Run RSpec code examples" fullCommand="spec" id="spec" />
119
+ <RakeTaskImpl description="Displays the current version" fullCommand="version" id="version" />
120
+ <RakeTaskImpl description="" fullCommand="console" id="console" />
121
+ <RakeTaskImpl description="" fullCommand="default" id="default" />
122
+ <RakeTaskImpl description="" fullCommand="gemspec_required" id="gemspec_required" />
123
+ <RakeTaskImpl description="" fullCommand="rdoc/created.rid" id="rdoc/created.rid" />
124
+ <RakeTaskImpl description="" fullCommand="version_required" id="version_required" />
125
+ </subtasks>
126
+ </RakeTaskImpl>
127
+ </option>
128
+ </component>
129
+ </module>
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Magellanalytics::Event do
4
+ describe 'name assignment' do
5
+ it 'converts name to a symbol' do
6
+ event = described_class.new('I am an event')
7
+ expect(event.name).to eq(:i_am_an_event)
8
+ end
9
+ end
10
+
11
+ describe 'description' do
12
+ context 'when a description is given explicitly' do
13
+ it 'returns the given description' do
14
+ event = described_class.new(:test, 'I am a test event')
15
+ expect(event.description).to eq('I am a test event')
16
+ end
17
+ end
18
+
19
+ context 'when no explicit description is given' do
20
+ it 'titleizes the name' do
21
+ event = described_class.new(:test_event)
22
+ expect(event.description).to eq('Test event')
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,317 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_dispatch'
4
+
5
+ RSpec.describe Magellanalytics do
6
+ let(:segment_spy) { spy(Segment::Analytics) }
7
+ let(:user_class) { Struct.new(:id) }
8
+ let(:user) { user_class.new(1) }
9
+
10
+ before do
11
+ Magellanalytics.reset_config!
12
+ allow(Magellanalytics).to receive(:analytics).and_return(segment_spy)
13
+ end
14
+
15
+ describe '#identify' do
16
+ it 'calls #identify on the Segment client' do
17
+ expect(segment_spy).to receive(:identify).with({ user_id: 1 })
18
+ described_class.identify(user)
19
+ end
20
+
21
+ context 'when the user does not satisfy the tracking check' do
22
+ before do
23
+ Magellanalytics.configure do |config|
24
+ config.track_user_if { |user| user.id == 2 }
25
+ end
26
+ end
27
+
28
+ it 'does not call #identify on the Segment client' do
29
+ expect(segment_spy).not_to receive(:identify)
30
+ described_class.identify(user)
31
+ end
32
+ end
33
+
34
+ context 'when the user satisfies the tracking check' do
35
+ before do
36
+ Magellanalytics.configure do |config|
37
+ config.track_user_if { |user| user.id == 1 }
38
+ end
39
+ end
40
+
41
+ it 'calls #identify on the Segment client' do
42
+ expect(segment_spy).to receive(:identify).with({ user_id: 1 })
43
+ described_class.identify(user)
44
+ end
45
+ end
46
+
47
+ context 'when additional user traits have been specified' do
48
+ let(:user_class) { Struct.new(:id, :name) }
49
+ let(:user) { user_class.new(1, 'Mark Testinger') }
50
+
51
+ before do
52
+ Magellanalytics.configure do |config|
53
+ config.register_user_traits { |user| { name: user.name } }
54
+ end
55
+ end
56
+
57
+ it 'includes the traits per the user' do
58
+ expect(segment_spy).to receive(:identify).with({ user_id: 1, traits: { name: 'Mark Testinger' } })
59
+ described_class.identify(user)
60
+ end
61
+ end
62
+ end
63
+
64
+ describe '#page' do
65
+ let(:user_class) { Struct.new(:id, :client_id) }
66
+ let(:user) { user_class.new(1, 5) }
67
+ let(:request_spy) { spy(ActionDispatch::Request) }
68
+
69
+ before do
70
+ allow(request_spy).to receive(:original_url).and_return('https://app.magellan.ai/analytics/test')
71
+ allow(request_spy).to receive(:original_fullpath).and_return('/analytics/test')
72
+ allow(request_spy).to receive(:referer).and_return('https://app.magellan.ai/previous/page')
73
+ allow(request_spy).to receive(:parameters).and_return({ controller: 'a_controller_name', action: 'an_action_name' }.with_indifferent_access)
74
+ allow(request_spy).to receive(:filtered_parameters).and_return({})
75
+ end
76
+
77
+ it 'calls #identify' do
78
+ expect(described_class).to receive(:identify)
79
+ described_class.page(user, request_spy)
80
+ end
81
+
82
+ it 'calls #page on the Segment client with the default payload' do
83
+ expected_payload =
84
+ {
85
+ user_id: 1,
86
+ name: 'a_controller_name/an_action_name',
87
+ properties: {
88
+ path: '/analytics/test',
89
+ url: 'https://app.magellan.ai/analytics/test',
90
+ referrer: 'https://app.magellan.ai/previous/page',
91
+ client_id: 5
92
+ }
93
+ }
94
+ expect(segment_spy).to receive(:page).with(expected_payload)
95
+ described_class.page(user, request_spy)
96
+ end
97
+
98
+ context 'when additional base props have been specified' do
99
+ before do
100
+ Magellanalytics.configure do |config|
101
+ config.base_props = { context: 'Test!' }
102
+ end
103
+ end
104
+
105
+ it 'includes the base props in the properties of the payload' do
106
+ expected_payload =
107
+ {
108
+ user_id: 1,
109
+ name: 'a_controller_name/an_action_name',
110
+ properties: {
111
+ context: 'Test!',
112
+ path: '/analytics/test',
113
+ url: 'https://app.magellan.ai/analytics/test',
114
+ referrer: 'https://app.magellan.ai/previous/page',
115
+ client_id: 5
116
+ }
117
+ }
118
+ expect(segment_spy).to receive(:page).with(expected_payload)
119
+ described_class.page(user, request_spy)
120
+ end
121
+ end
122
+
123
+ context 'when additional options are supplied' do
124
+ it 'includes the options in the payload' do
125
+ expected_payload =
126
+ {
127
+ user_id: 1,
128
+ name: 'a_controller_name/an_action_name',
129
+ properties: {
130
+ path: '/analytics/test',
131
+ url: 'https://app.magellan.ai/analytics/test',
132
+ referrer: 'https://app.magellan.ai/previous/page',
133
+ client_id: 5
134
+ },
135
+ view_context: 'youtube'
136
+ }
137
+ expect(segment_spy).to receive(:page).with(expected_payload)
138
+ described_class.page(user, request_spy, view_context: 'youtube')
139
+ end
140
+ end
141
+
142
+ context 'when the user does not satisfy the tracking check' do
143
+ before do
144
+ Magellanalytics.configure do |config|
145
+ config.track_user_if { |user| user.id == 2 }
146
+ end
147
+ end
148
+
149
+ it 'does not call #page on the Segment client' do
150
+ expect(segment_spy).not_to receive(:page)
151
+ described_class.page(user, request_spy)
152
+ end
153
+ end
154
+
155
+ context 'when the user satisfies the tracking check' do
156
+ before do
157
+ Magellanalytics.configure do |config|
158
+ config.track_user_if { |user| user.id == 1 }
159
+ end
160
+ end
161
+
162
+ it 'calls #page on the Segment client' do
163
+ expect(segment_spy).to receive(:page)
164
+ described_class.page(user, request_spy)
165
+ end
166
+ end
167
+ end
168
+
169
+ describe '#track' do
170
+ let(:user_class) { Struct.new(:id, :client_id) }
171
+ let(:user) { user_class.new(1, 5) }
172
+
173
+ before do
174
+ Magellanalytics.configure do |config|
175
+ config.register_event :test_event
176
+ end
177
+ end
178
+
179
+ it 'calls #identify' do
180
+ expect(described_class).to receive(:identify)
181
+ described_class.track(user, :test_event)
182
+ end
183
+
184
+ it 'calls #track on the Segment client' do
185
+ expected_payload =
186
+ {
187
+ user_id: 1,
188
+ event: 'Test event',
189
+ properties: { client_id: 5 }
190
+ }
191
+ expect(segment_spy).to receive(:track).with(expected_payload)
192
+ described_class.track(user, :test_event)
193
+ end
194
+
195
+ context 'when the user does not satisfy the tracking check' do
196
+ before do
197
+ Magellanalytics.configure do |config|
198
+ config.track_user_if { |user| user.id == 2 }
199
+ end
200
+ end
201
+
202
+ it 'does not call #track on the Segment client' do
203
+ expect(segment_spy).not_to receive(:track)
204
+ described_class.track(user, :test_event)
205
+ end
206
+ end
207
+
208
+ context 'when the user satisfies the tracking check' do
209
+ before do
210
+ Magellanalytics.configure do |config|
211
+ config.track_user_if { |user| user.id == 1 }
212
+ end
213
+ end
214
+
215
+ it 'calls #track on the Segment client' do
216
+ expect(segment_spy).to receive(:track)
217
+ described_class.track(user, :test_event)
218
+ end
219
+ end
220
+
221
+ context 'when the event is not registered' do
222
+ it 'raises an UnregisteredEvent error' do
223
+ expect { described_class.track(user, :this_event_is_not_registered) }.to raise_error(Magellanalytics::UnregisteredEvent, 'Unknown event: this_event_is_not_registered')
224
+ end
225
+ end
226
+
227
+ context 'when base integrations have been specified' do
228
+ before do
229
+ Magellanalytics.configure do |config|
230
+ config.base_integrations = { 'Slack' => true }
231
+ end
232
+ end
233
+
234
+ it 'includes the integrations' do
235
+ expected_payload =
236
+ {
237
+ user_id: 1,
238
+ event: 'Test event',
239
+ properties: { client_id: 5 },
240
+ integrations: { 'Slack' => true }
241
+ }
242
+ expect(segment_spy).to receive(:track).with(expected_payload)
243
+ described_class.track(user, :test_event)
244
+ end
245
+ end
246
+
247
+ context 'when base properties have been specified' do
248
+ before do
249
+ Magellanalytics.configure do |config|
250
+ config.base_props = { context: 'Test environment' }
251
+ end
252
+ end
253
+
254
+ it 'includes the properties' do
255
+ expected_payload =
256
+ {
257
+ user_id: 1,
258
+ event: 'Test event',
259
+ properties: {
260
+ context: 'Test environment',
261
+ client_id: 5
262
+ }
263
+ }
264
+ expect(segment_spy).to receive(:track).with(expected_payload)
265
+ described_class.track(user, :test_event)
266
+ end
267
+
268
+ context 'when event-specific properties have also been specified' do
269
+ it 'merges both the global and event-specific properties' do
270
+ expected_payload =
271
+ {
272
+ user_id: 1,
273
+ event: 'Test event',
274
+ properties: {
275
+ context: 'Test environment',
276
+ extra: 'This too',
277
+ client_id: 5
278
+ }
279
+ }
280
+ expect(segment_spy).to receive(:track).with(expected_payload)
281
+ described_class.track(user, :test_event, properties: { extra: 'This too' })
282
+ end
283
+ end
284
+ end
285
+
286
+ context 'when event-specific properties are passed to the call' do
287
+ it 'includes the properties' do
288
+ expected_payload =
289
+ {
290
+ user_id: 1,
291
+ event: 'Test event',
292
+ properties: {
293
+ context: 'Test environment',
294
+ client_id: 5
295
+ }
296
+ }
297
+ expect(segment_spy).to receive(:track).with(expected_payload)
298
+ described_class.track(user, :test_event, properties: { context: 'Test environment' })
299
+ end
300
+ end
301
+
302
+ context 'when arbitrary additional keywords are provided' do
303
+ it 'passes the additional keyword arguments to the Segment client' do
304
+ expected_payload =
305
+ {
306
+ user_id: 1,
307
+ event: 'Test event',
308
+ properties: { client_id: 5 },
309
+ a: 'Extra',
310
+ b: { c: 'def' }
311
+ }
312
+ expect(segment_spy).to receive(:track).with(expected_payload)
313
+ described_class.track(user, :test_event, a: 'Extra', b: { c: 'def' })
314
+ end
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'magellanalytics'
4
+
5
+ # This file was generated by the `rspec --init` command. Conventionally, all
6
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
7
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
8
+ # this file to always be loaded, without a need to explicitly require it in any
9
+ # files.
10
+ #
11
+ # Given that it is always loaded, you are encouraged to keep this file as
12
+ # light-weight as possible. Requiring heavyweight dependencies from this file
13
+ # will add to the boot time of your test suite on EVERY test run, even for an
14
+ # individual file that may not need all of that loaded. Instead, consider making
15
+ # a separate helper file that requires the additional dependencies and performs
16
+ # the additional setup, and require it from the spec files that actually need
17
+ # it.
18
+ #
19
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
20
+ RSpec.configure do |config|
21
+ # rspec-expectations config goes here. You can use an alternate
22
+ # assertion/expectation library such as wrong or the stdlib/minitest
23
+ # assertions if you prefer.
24
+ config.expect_with :rspec do |expectations|
25
+ # This option will default to `true` in RSpec 4. It makes the `description`
26
+ # and `failure_message` of custom matchers include text for helper methods
27
+ # defined using `chain`, e.g.:
28
+ # be_bigger_than(2).and_smaller_than(4).description
29
+ # # => "be bigger than 2 and smaller than 4"
30
+ # ...rather than:
31
+ # # => "be bigger than 2"
32
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
33
+ end
34
+
35
+ # rspec-mocks config goes here. You can use an alternate test double
36
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
37
+ config.mock_with :rspec do |mocks|
38
+ # Prevents you from mocking or stubbing a method that does not exist on
39
+ # a real object. This is generally recommended, and will default to
40
+ # `true` in RSpec 4.
41
+ mocks.verify_partial_doubles = true
42
+ end
43
+
44
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
45
+ # have no way to turn it off -- the option exists only for backwards
46
+ # compatibility in RSpec 3). It causes shared context metadata to be
47
+ # inherited by the metadata hash of host groups and examples, rather than
48
+ # triggering implicit auto-inclusion in groups with matching metadata.
49
+ config.shared_context_metadata_behavior = :apply_to_host_groups
50
+
51
+ # The settings below are suggested to provide a good initial experience
52
+ # with RSpec, but feel free to customize to your heart's content.
53
+ # # This allows you to limit a spec run to individual examples or groups
54
+ # # you care about by tagging them with `:focus` metadata. When nothing
55
+ # # is tagged with `:focus`, all examples get run. RSpec also provides
56
+ # # aliases for `it`, `describe`, and `context` that include `:focus`
57
+ # # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
58
+ # config.filter_run_when_matching :focus
59
+ #
60
+ # # Allows RSpec to persist some state between runs in order to support
61
+ # # the `--only-failures` and `--next-failure` CLI options. We recommend
62
+ # # you configure your source control system to ignore this file.
63
+ # config.example_status_persistence_file_path = "spec/examples.txt"
64
+ #
65
+ # # Limits the available syntax to the non-monkey patched syntax that is
66
+ # # recommended. For more details, see:
67
+ # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
68
+ # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
+ # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
70
+ # config.disable_monkey_patching!
71
+ #
72
+ # # This setting enables warnings. It's recommended, but in some cases may
73
+ # # be too noisy due to issues in dependencies.
74
+ # config.warnings = true
75
+ #
76
+ # # Many RSpec users commonly either run the entire suite or an individual
77
+ # # file, and it's useful to allow more verbose output when running an
78
+ # # individual spec file.
79
+ # if config.files_to_run.one?
80
+ # # Use the documentation formatter for detailed output,
81
+ # # unless a formatter has already been configured
82
+ # # (e.g. via a command-line flag).
83
+ # config.default_formatter = "doc"
84
+ # end
85
+ #
86
+ # # Print the 10 slowest examples and example groups at the
87
+ # # end of the spec run, to help surface which specs are running
88
+ # # particularly slow.
89
+ # config.profile_examples = 10
90
+ #
91
+ # # Run specs in random order to surface order dependencies. If you find an
92
+ # # order dependency and want to debug it, you can fix the order by providing
93
+ # # the seed, which is printed after each run.
94
+ # # --seed 1234
95
+ # config.order = :random
96
+ #
97
+ # # Seed global randomization in this process using the `--seed` CLI option.
98
+ # # Setting this allows you to use `--seed` to deterministically reproduce
99
+ # # test failures related to randomization by passing the same `--seed` value
100
+ # # as the one that triggered the failure.
101
+ # Kernel.srand config.seed
102
+ end