mixpal 0.4.1 → 0.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8c9c74b1185daabd7b04ce5ac8865084eeaa8ca222c342c12ace6e4d1c444cd
4
- data.tar.gz: 82a07a359fe377bd2dbf60e95f9eb20d79afb764a4c50219846e529c981e271a
3
+ metadata.gz: c6f66eee2ba6982bd46527e9bb5e39dea9f45f71486f0ab8e5cc83237e4cf017
4
+ data.tar.gz: c11d9ee0b87ae7b4c8ef6230bcd98aab358e34ffb9bbb9ef482cf15f8a7301d2
5
5
  SHA512:
6
- metadata.gz: 9dcceef2cf2269fc79e6c45675702ecc7e568c7340dedc62d45d358d15ff52c87a2c15d257d986bae53004d7c78a305706912f590448877d29622fc0a0f1df36
7
- data.tar.gz: a989eb95e2e2ac576379e4bcc63d161f1d8815774f8ee1a079e735a42da24ed3e7e6dbc42547a285263c4bc5c5642a660de2f5dac8881249d5b5d33bae93baa5
6
+ metadata.gz: b968446550407fe603d29bd7ec1bb42adcaec1505232a4826a62184a0bb705f1c04ccb0ba1af5a7998ed20b83ecf57e4d0c2fffd373ec461f5195d981af24bc6
7
+ data.tar.gz: ff250e09fe05911ca0432d28bcef0f6bfb13b8c2246218ced5515f1c43c443b248f9cf3bafb523ff5af45c7a16f19b74117a42032d6d7d4ea2a951d11b9f5e92
data/README.md CHANGED
@@ -162,5 +162,5 @@ prefer local development, inspect the Dockerfile to get your local env built.
162
162
  docker-compose build \
163
163
  --build-arg USER_ID=$(id -u) \
164
164
  --build-arg GROUP_ID=$(id -g)
165
- docker-compose run rake release
165
+ docker-compose run gem rake release
166
166
  ```
@@ -0,0 +1,23 @@
1
+ module Mixpal
2
+ class Snippet
3
+ attr_reader :snippet
4
+
5
+ def initialize(snippet)
6
+ @snippet = snippet
7
+ end
8
+
9
+ def render
10
+ snippet.html_safe
11
+ end
12
+
13
+ def to_store
14
+ {
15
+ 'snippet' => snippet
16
+ }
17
+ end
18
+
19
+ def self.from_store(data)
20
+ new(data['snippet'])
21
+ end
22
+ end
23
+ end
@@ -1,6 +1,6 @@
1
1
  module Mixpal
2
2
  class Tracker
3
- attr_reader :events, :user_updates, :revenue_updates, :identity, :alias_user
3
+ attr_reader :events, :user_updates, :revenue_updates, :identity, :alias_user, :js_snippets
4
4
 
5
5
  STORAGE_KEY = 'mixpal'
6
6
 
@@ -10,6 +10,7 @@ module Mixpal
10
10
  @events = []
11
11
  @user_updates = []
12
12
  @revenue_updates = []
13
+ @js_snippets = []
13
14
 
14
15
  @identity = args[:identity]
15
16
  end
@@ -31,6 +32,10 @@ module Mixpal
31
32
  revenue_updates << Mixpal::Revenue.new(amount, properties)
32
33
  end
33
34
 
35
+ def add_js_snippet(snippet)
36
+ js_snippets << Mixpal::Snippet.new(snippet)
37
+ end
38
+
34
39
  def render
35
40
  ''.tap do |html|
36
41
  html << '<script type="text/javascript">'
@@ -39,6 +44,7 @@ module Mixpal
39
44
  html << events.map(&:render).join('')
40
45
  html << user_updates.map(&:render).join('')
41
46
  html << revenue_updates.map(&:render).join('')
47
+ html << js_snippets.map(&:render).join('')
42
48
  html << '</script>'
43
49
  end.html_safe
44
50
  end
@@ -58,13 +64,15 @@ module Mixpal
58
64
  end
59
65
 
60
66
  if data['user_updates']
61
- @user_updates =
62
- data['user_updates'].map { |u| Mixpal::User.from_store(u) }
67
+ @user_updates = data['user_updates'].map { |u| Mixpal::User.from_store(u) }
63
68
  end
64
69
 
65
70
  if data['revenue_updates']
66
- @revenue_updates =
67
- data['revenue_updates'].map { |u| Mixpal::Revenue.from_store(u) }
71
+ @revenue_updates = data['revenue_updates'].map { |u| Mixpal::Revenue.from_store(u) }
72
+ end
73
+
74
+ if data['js_snippets']
75
+ @js_snippets = data['js_snippets'].map { |u| Mixpal::Snippet.from_store(u) }
68
76
  end
69
77
 
70
78
  session.delete(STORAGE_KEY)
@@ -78,7 +86,8 @@ module Mixpal
78
86
  'identity' => identity,
79
87
  'events' => events.map(&:to_store),
80
88
  'user_updates' => user_updates.map(&:to_store),
81
- 'revenue_updates' => revenue_updates.map(&:to_store)
89
+ 'revenue_updates' => revenue_updates.map(&:to_store),
90
+ 'js_snippets' => js_snippets.map(&:to_store)
82
91
  }
83
92
  end
84
93
  end
data/lib/mixpal/util.rb CHANGED
@@ -5,12 +5,22 @@ module Mixpal
5
5
  hash.reject! { |_, v| v.nil? }
6
6
 
7
7
  contents = hash.map do |k, v|
8
- js_value = v.is_a?(String) || v.is_a?(Time) ? "\"#{v}\"" : v
9
- "\"#{k}\": #{js_value}"
8
+ "\"#{k}\": #{escape_js_object_value(v)}"
10
9
  end.join(',').html_safe
11
10
 
12
11
  "{#{contents}}"
13
12
  end
13
+
14
+ def escape_js_object_value(value)
15
+ case value
16
+ when String
17
+ value.dump
18
+ when Time
19
+ "\"#{value}\""
20
+ else
21
+ value
22
+ end
23
+ end
14
24
  end
15
25
  end
16
26
  end
@@ -1,3 +1,3 @@
1
1
  module Mixpal
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/mixpal.rb CHANGED
@@ -9,6 +9,7 @@ module Mixpal
9
9
  autoload :User, 'mixpal/user'
10
10
  autoload :Revenue, 'mixpal/revenue'
11
11
  autoload :Integration, 'mixpal/integration'
12
+ autoload :Snippet, 'mixpal/snippet'
12
13
 
13
14
  class << self
14
15
  def configuration
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "pry"
24
24
  spec.add_development_dependency "rubocop", "~> 0.91.0"
25
- spec.add_development_dependency "rspec", "~> 3.9.0"
25
+ spec.add_development_dependency "rspec", "~> 3.13.0"
26
26
  spec.add_development_dependency "guard-rspec", "~> 4.7.3"
27
27
  spec.add_development_dependency "rb-fsevent", "~> 0.10.4"
28
28
  spec.add_development_dependency "awesome_print", "~> 1.8.0"
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mixpal::Snippet do
4
+ let(:snippet) { 'alert("hello world");' }
5
+ subject { described_class.new(snippet) }
6
+
7
+ describe '#render' do
8
+ it 'outputs the snippet string' do
9
+ expect(subject.render).to eq 'alert("hello world");'
10
+ end
11
+
12
+ it 'outputs an html safe string' do
13
+ expect(subject.render).to be_html_safe
14
+ end
15
+ end
16
+
17
+ describe '#to_store' do
18
+ it 'returns a hash with its data' do
19
+ expect(subject.to_store).to eq('snippet' => snippet)
20
+ end
21
+ end
22
+
23
+ describe '.from_store' do
24
+ let(:result) do
25
+ described_class.from_store('snippet' => snippet)
26
+ end
27
+
28
+ it 'instantiates a new instance' do
29
+ expect(result).to be_an_instance_of(described_class)
30
+ end
31
+
32
+ it 'sets its snippet string from the data' do
33
+ expect(result.snippet).to eq snippet
34
+ end
35
+ end
36
+ end
@@ -30,6 +30,10 @@ describe Mixpal::Tracker do
30
30
  expect(subject.revenue_updates).to eq []
31
31
  end
32
32
 
33
+ it 'creates an empty set of arbitrary javascript snippets' do
34
+ expect(subject.js_snippets).to eq []
35
+ end
36
+
33
37
  context 'with an :identity arg' do
34
38
  subject { subject_with_identity }
35
39
 
@@ -102,6 +106,22 @@ describe Mixpal::Tracker do
102
106
  end
103
107
  end
104
108
 
109
+ describe '#add_js_snippet' do
110
+ it 'instantiates a new Snippet object with properties' do
111
+ snippet = "alert('hello world');"
112
+
113
+ expect(Mixpal::Snippet).to receive(:new).with(snippet)
114
+ subject.add_js_snippet(snippet)
115
+ end
116
+
117
+ it 'adds the Snippet to js_snippets for rendering later' do
118
+ expect { subject.add_js_snippet("alert('hello world');") }
119
+ .to change(subject.js_snippets, :size).by(1)
120
+
121
+ expect(subject.js_snippets.first).to be_an_instance_of(Mixpal::Snippet)
122
+ end
123
+ end
124
+
105
125
  describe '#render' do
106
126
  it 'outputs script tag' do
107
127
  expect(subject.render).to have_tag('script')
@@ -190,6 +210,23 @@ describe Mixpal::Tracker do
190
210
  expect(subject.render).to include joined
191
211
  end
192
212
  end
213
+
214
+ context 'with js snippets' do
215
+ before do
216
+ subject.add_js_snippet('alert("hello world");')
217
+ subject.add_js_snippet('arbitraryFunctionCall();')
218
+ end
219
+
220
+ it 'delegates render to the events' do
221
+ subject.js_snippets.each { |snippet| expect(snippet).to receive :render }
222
+ subject.render
223
+ end
224
+
225
+ it 'joins each rendered snippet' do
226
+ joined = subject.js_snippets[0].render + subject.js_snippets[1].render
227
+ expect(subject.render).to include joined
228
+ end
229
+ end
193
230
  end
194
231
 
195
232
  describe '#store!' do
@@ -251,6 +288,25 @@ describe Mixpal::Tracker do
251
288
  )
252
289
  end
253
290
  end
291
+
292
+ context 'when js_snippets have been added' do
293
+ before do
294
+ subject.add_js_snippet('alert("hello world");')
295
+ subject.add_js_snippet('arbitraryFunctionCall();')
296
+ end
297
+
298
+ it 'delegates composition to the snippets' do
299
+ subject.js_snippets.each { |snippet| expect(snippet).to receive :to_store }
300
+ subject.store!(session)
301
+ end
302
+
303
+ it 'stores the snippets in an array' do
304
+ subject.store!(session)
305
+ expect_storage_to_include(
306
+ 'js_snippets' => [subject.js_snippets[0].to_store, subject.js_snippets[1].to_store]
307
+ )
308
+ end
309
+ end
254
310
  end
255
311
 
256
312
  describe '#restore!' do
@@ -260,6 +316,7 @@ describe Mixpal::Tracker do
260
316
  before do
261
317
  old_tracker.track 'Event 1'
262
318
  old_tracker.register_user name: 'Nick Giancola'
319
+ old_tracker.add_js_snippet("alert('hello world');")
263
320
  old_tracker.store!(session)
264
321
  end
265
322
 
@@ -280,9 +337,16 @@ describe Mixpal::Tracker do
280
337
  subject.restore!(session)
281
338
  end
282
339
 
283
- it 'restores the events' do
340
+ it 'restores the snippets' do
341
+ subject.restore!(session)
342
+ expect(subject.js_snippets.size).to eq 1
343
+ end
344
+
345
+ it 'delegates snippet restoration to the Snippet class' do
346
+ expect(Mixpal::Snippet).to receive(:from_store)
347
+ .with(old_tracker.js_snippets.first.to_store)
348
+
284
349
  subject.restore!(session)
285
- expect(subject.events.size).to eq 1
286
350
  end
287
351
 
288
352
  context 'with a different identity (e.g. after login)' do
@@ -24,5 +24,10 @@ describe Mixpal::Util do
24
24
  expect(subject.hash_to_js_object_string(age: 21, gender: nil))
25
25
  .to eq '{"age": 21}'
26
26
  end
27
+
28
+ it 'escapes double quotes in values' do
29
+ expect(subject.hash_to_js_object_string(key: 'value "with" quotes'))
30
+ .to eq '{"key": "value \"with\" quotes"}'
31
+ end
27
32
  end
28
33
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixpal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - patbenatar
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-05-03 00:00:00.000000000 Z
12
+ date: 2024-04-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -73,14 +73,14 @@ dependencies:
73
73
  requirements:
74
74
  - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: 3.9.0
76
+ version: 3.13.0
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: 3.9.0
83
+ version: 3.13.0
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: guard-rspec
86
86
  requirement: !ruby/object:Gem::Requirement
@@ -187,6 +187,7 @@ files:
187
187
  - lib/mixpal/event.rb
188
188
  - lib/mixpal/integration.rb
189
189
  - lib/mixpal/revenue.rb
190
+ - lib/mixpal/snippet.rb
190
191
  - lib/mixpal/tracker.rb
191
192
  - lib/mixpal/user.rb
192
193
  - lib/mixpal/util.rb
@@ -194,6 +195,7 @@ files:
194
195
  - mixpanel_assistant.gemspec
195
196
  - spec/lib/mixpal/event_spec.rb
196
197
  - spec/lib/mixpal/revenue_spec.rb
198
+ - spec/lib/mixpal/snippet_spec.rb
197
199
  - spec/lib/mixpal/tracker_spec.rb
198
200
  - spec/lib/mixpal/user_spec.rb
199
201
  - spec/lib/mixpal/util_spec.rb
@@ -279,6 +281,7 @@ summary: As the JavaScript library is Mixpanel's preferred method of usage, Mixp
279
281
  test_files:
280
282
  - spec/lib/mixpal/event_spec.rb
281
283
  - spec/lib/mixpal/revenue_spec.rb
284
+ - spec/lib/mixpal/snippet_spec.rb
282
285
  - spec/lib/mixpal/tracker_spec.rb
283
286
  - spec/lib/mixpal/user_spec.rb
284
287
  - spec/lib/mixpal/util_spec.rb