mixpal 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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