moses-vanity 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/.autotest +22 -0
  2. data/.gitignore +7 -0
  3. data/.rvmrc +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG +374 -0
  6. data/Gemfile +28 -0
  7. data/MIT-LICENSE +21 -0
  8. data/README.rdoc +108 -0
  9. data/Rakefile +189 -0
  10. data/bin/vanity +16 -0
  11. data/doc/_config.yml +2 -0
  12. data/doc/_layouts/_header.html +34 -0
  13. data/doc/_layouts/page.html +47 -0
  14. data/doc/_metrics.textile +12 -0
  15. data/doc/ab_testing.textile +210 -0
  16. data/doc/configuring.textile +45 -0
  17. data/doc/contributing.textile +93 -0
  18. data/doc/credits.textile +23 -0
  19. data/doc/css/page.css +83 -0
  20. data/doc/css/print.css +43 -0
  21. data/doc/css/syntax.css +7 -0
  22. data/doc/email.textile +129 -0
  23. data/doc/experimental.textile +31 -0
  24. data/doc/faq.textile +8 -0
  25. data/doc/identity.textile +43 -0
  26. data/doc/images/ab_in_dashboard.png +0 -0
  27. data/doc/images/clear_winner.png +0 -0
  28. data/doc/images/price_options.png +0 -0
  29. data/doc/images/sidebar_test.png +0 -0
  30. data/doc/images/signup_metric.png +0 -0
  31. data/doc/images/vanity.png +0 -0
  32. data/doc/index.textile +91 -0
  33. data/doc/metrics.textile +231 -0
  34. data/doc/rails.textile +89 -0
  35. data/doc/site.js +27 -0
  36. data/generators/templates/vanity_migration.rb +53 -0
  37. data/generators/vanity_generator.rb +8 -0
  38. data/lib/generators/templates/vanity_migration.rb +53 -0
  39. data/lib/generators/vanity_generator.rb +15 -0
  40. data/lib/vanity.rb +36 -0
  41. data/lib/vanity/adapters/abstract_adapter.rb +140 -0
  42. data/lib/vanity/adapters/active_record_adapter.rb +248 -0
  43. data/lib/vanity/adapters/mock_adapter.rb +157 -0
  44. data/lib/vanity/adapters/mongodb_adapter.rb +178 -0
  45. data/lib/vanity/adapters/redis_adapter.rb +160 -0
  46. data/lib/vanity/backport.rb +26 -0
  47. data/lib/vanity/commands/list.rb +21 -0
  48. data/lib/vanity/commands/report.rb +64 -0
  49. data/lib/vanity/commands/upgrade.rb +34 -0
  50. data/lib/vanity/experiment/ab_test.rb +507 -0
  51. data/lib/vanity/experiment/base.rb +214 -0
  52. data/lib/vanity/frameworks.rb +16 -0
  53. data/lib/vanity/frameworks/rails.rb +318 -0
  54. data/lib/vanity/helpers.rb +66 -0
  55. data/lib/vanity/images/x.gif +0 -0
  56. data/lib/vanity/metric/active_record.rb +85 -0
  57. data/lib/vanity/metric/base.rb +244 -0
  58. data/lib/vanity/metric/google_analytics.rb +83 -0
  59. data/lib/vanity/metric/remote.rb +53 -0
  60. data/lib/vanity/playground.rb +396 -0
  61. data/lib/vanity/templates/_ab_test.erb +28 -0
  62. data/lib/vanity/templates/_experiment.erb +5 -0
  63. data/lib/vanity/templates/_experiments.erb +7 -0
  64. data/lib/vanity/templates/_metric.erb +14 -0
  65. data/lib/vanity/templates/_metrics.erb +13 -0
  66. data/lib/vanity/templates/_report.erb +27 -0
  67. data/lib/vanity/templates/_vanity.js.erb +20 -0
  68. data/lib/vanity/templates/flot.min.js +1 -0
  69. data/lib/vanity/templates/jquery.min.js +19 -0
  70. data/lib/vanity/templates/vanity.css +26 -0
  71. data/lib/vanity/templates/vanity.js +82 -0
  72. data/lib/vanity/version.rb +11 -0
  73. data/test/adapters/redis_adapter_test.rb +17 -0
  74. data/test/experiment/ab_test.rb +771 -0
  75. data/test/experiment/base_test.rb +150 -0
  76. data/test/experiments/age_and_zipcode.rb +19 -0
  77. data/test/experiments/metrics/cheers.rb +3 -0
  78. data/test/experiments/metrics/signups.rb +2 -0
  79. data/test/experiments/metrics/yawns.rb +3 -0
  80. data/test/experiments/null_abc.rb +5 -0
  81. data/test/metric/active_record_test.rb +277 -0
  82. data/test/metric/base_test.rb +293 -0
  83. data/test/metric/google_analytics_test.rb +104 -0
  84. data/test/metric/remote_test.rb +109 -0
  85. data/test/myapp/app/controllers/application_controller.rb +2 -0
  86. data/test/myapp/app/controllers/main_controller.rb +7 -0
  87. data/test/myapp/config/boot.rb +110 -0
  88. data/test/myapp/config/environment.rb +10 -0
  89. data/test/myapp/config/environments/production.rb +0 -0
  90. data/test/myapp/config/routes.rb +3 -0
  91. data/test/passenger_test.rb +43 -0
  92. data/test/playground_test.rb +26 -0
  93. data/test/rails_dashboard_test.rb +37 -0
  94. data/test/rails_helper_test.rb +36 -0
  95. data/test/rails_test.rb +389 -0
  96. data/test/test_helper.rb +145 -0
  97. data/vanity.gemspec +26 -0
  98. metadata +202 -0
@@ -0,0 +1,293 @@
1
+ require "test/test_helper"
2
+
3
+
4
+ context "Metric via playground" do
5
+
6
+ test "knows all loaded metrics" do
7
+ metric "Yawns/sec", "Cheers/sec"
8
+ assert Vanity.playground.metrics.keys.include?(:yawns_sec)
9
+ assert Vanity.playground.metrics.keys.include?(:cheers_sec)
10
+ end
11
+
12
+ test "loads metric definitions" do
13
+ File.open "tmp/experiments/metrics/yawns_sec.rb", "w" do |f|
14
+ f.write <<-RUBY
15
+ metric "Yawns/sec" do
16
+ def xmts
17
+ "x"
18
+ end
19
+ end
20
+ RUBY
21
+ end
22
+ assert_equal "x", Vanity.playground.metric(:yawns_sec).xmts
23
+ end
24
+
25
+ test "bubbles up loaded metrics" do
26
+ File.open "tmp/experiments/metrics/yawns_sec.rb", "w" do |f|
27
+ f.write "fail 'yawn!'"
28
+ end
29
+ assert_raises NameError do
30
+ Vanity.playground.metric(:yawns_sec)
31
+ end
32
+ end
33
+
34
+ test "map identifier from file name" do
35
+ File.open "tmp/experiments/metrics/yawns_sec.rb", "w" do |f|
36
+ f.write <<-RUBY
37
+ metric "yawns/hour" do
38
+ end
39
+ RUBY
40
+ end
41
+ assert Vanity.playground.metric(:yawns_sec)
42
+ end
43
+
44
+ test "fails tracking unknown metric" do
45
+ assert_raises NameError do
46
+ Vanity.playground.track! :yawns_sec
47
+ end
48
+ end
49
+
50
+ test "reloading metrics" do
51
+ metric "Yawns/sec", "Cheers/sec"
52
+ Vanity.playground.metric(:yawns_sec)
53
+ Vanity.playground.metric(:cheers_sec)
54
+ assert_equal 2, Vanity.playground.metrics.size
55
+ metrics = Vanity.playground.metrics.values
56
+ Vanity.playground.reload!
57
+ assert_equal 0, Vanity.playground.metrics.size
58
+ assert_not_equal metrics, Vanity.playground.metrics.values
59
+ end
60
+
61
+ test "ignores undefined metrics in database" do
62
+ metric "Yawns/sec"
63
+ Vanity.playground.reload!
64
+ assert Vanity.playground.metrics.empty?
65
+ end
66
+
67
+ end
68
+
69
+
70
+ context "Metric tracking" do
71
+ test "disabled when metrics are disabled" do
72
+ not_collecting!
73
+ metric "Yawns/sec", "Cheers/sec"
74
+ Vanity.playground.track! :yawns_sec
75
+ Vanity.playground.track! :cheers_sec
76
+ end
77
+
78
+ test "can count" do
79
+ metric "Yawns/sec", "Cheers/sec"
80
+ 4.times { Vanity.playground.track! :yawns_sec }
81
+ 2.times { Vanity.playground.track! :cheers_sec }
82
+ yawns = Vanity.playground.metric(:yawns_sec).values(today, today).first
83
+ cheers = Vanity.playground.metric(:cheers_sec).values(today, today).first
84
+ assert yawns = 2 * cheers
85
+ end
86
+
87
+ test "can tell the time" do
88
+ metric "Yawns/sec"
89
+ Timecop.freeze(today - 4) { 4.times { Vanity.playground.track! :yawns_sec } }
90
+ Timecop.freeze(today - 2) { 2.times { Vanity.playground.track! :yawns_sec } }
91
+ 1.times { Vanity.playground.track! :yawns_sec }
92
+ boredom = Vanity.playground.metric(:yawns_sec).values(today - 5, today)
93
+ assert_equal [0,4,0,2,0,1], boredom
94
+ end
95
+
96
+ test "with no value" do
97
+ metric "Yawns/sec", "Cheers/sec", "Looks"
98
+ Vanity.playground.track! :yawns_sec, 0
99
+ Vanity.playground.track! :cheers_sec
100
+ assert_equal 0, Vanity.playground.metric(:yawns_sec).values(today, today).sum
101
+ assert_equal 1, Vanity.playground.metric(:cheers_sec).values(today, today).sum
102
+ end
103
+
104
+ test "with count" do
105
+ metric "Yawns/sec"
106
+ Timecop.freeze(today - 4) { Vanity.playground.track! :yawns_sec, 4 }
107
+ Timecop.freeze(today - 2) { Vanity.playground.track! :yawns_sec, 2 }
108
+ Vanity.playground.track! :yawns_sec
109
+ boredom = Vanity.playground.metric(:yawns_sec).values(today - 5, today)
110
+ assert_equal [0,4,0,2,0,1], boredom
111
+ end
112
+
113
+ test "runs hook" do
114
+ metric "Many Happy Returns"
115
+ total = 0
116
+ Vanity.playground.metric(:many_happy_returns).hook do |metric_id, timestamp, count|
117
+ assert_equal :many_happy_returns, metric_id
118
+ assert_in_delta Time.now.to_i, timestamp.to_i, 1
119
+ total += count
120
+ end
121
+ Vanity.playground.track! :many_happy_returns, 6
122
+ assert_equal 6, total
123
+ end
124
+
125
+ test "doesn't runs hook when metrics disabled" do
126
+ not_collecting!
127
+ metric "Many Happy Returns"
128
+ total = 0
129
+ Vanity.playground.metric(:many_happy_returns).hook do |metric_id, timestamp, count|
130
+ total += count
131
+ end
132
+ Vanity.playground.track! :many_happy_returns, 6
133
+ assert_equal 0, total
134
+ end
135
+
136
+ test "runs multiple hooks" do
137
+ metric "Many Happy Returns"
138
+ returns = 0
139
+ Vanity.playground.metric(:many_happy_returns).hook { returns += 1 }
140
+ Vanity.playground.metric(:many_happy_returns).hook { returns += 1 }
141
+ Vanity.playground.metric(:many_happy_returns).hook { returns += 1 }
142
+ Vanity.playground.track! :many_happy_returns
143
+ assert_equal 3, returns
144
+ end
145
+
146
+ test "destroy wipes metrics" do
147
+ metric "Many Happy Returns"
148
+ Vanity.playground.track! :many_happy_returns, 3
149
+ assert_equal [3], Vanity.playground.metric(:many_happy_returns).values(today, today)
150
+ Vanity.playground.metric(:many_happy_returns).destroy!
151
+ assert_equal [0], Vanity.playground.metric(:many_happy_returns).values(today, today)
152
+ end
153
+ end
154
+
155
+
156
+ context "Metric name" do
157
+ test "can be whatever" do
158
+ File.open "tmp/experiments/metrics/yawns_sec.rb", "w" do |f|
159
+ f.write <<-RUBY
160
+ metric "Yawns per second" do
161
+ end
162
+ RUBY
163
+ end
164
+ assert_equal "Yawns per second", Vanity.playground.metric(:yawns_sec).name
165
+ end
166
+ end
167
+
168
+
169
+ context "Metric description" do
170
+ test "metric with description" do
171
+ File.open "tmp/experiments/metrics/yawns_sec.rb", "w" do |f|
172
+ f.write <<-RUBY
173
+ metric "Yawns/sec" do
174
+ description "Am I that boring?"
175
+ end
176
+ RUBY
177
+ end
178
+ assert_equal "Am I that boring?", Vanity::Metric.description(Vanity.playground.metric(:yawns_sec))
179
+ end
180
+
181
+ test "metric without description" do
182
+ File.open "tmp/experiments/metrics/yawns_sec.rb", "w" do |f|
183
+ f.write <<-RUBY
184
+ metric "Yawns/sec" do
185
+ end
186
+ RUBY
187
+ end
188
+ assert_nil Vanity::Metric.description(Vanity.playground.metric(:yawns_sec))
189
+ end
190
+
191
+ test "metric with no method description" do
192
+ metric = Object.new
193
+ assert_nil Vanity::Metric.description(metric)
194
+ end
195
+ end
196
+
197
+
198
+ context "Metric bounds" do
199
+ test "metric with bounds" do
200
+ File.open "tmp/experiments/metrics/sky_is_limit.rb", "w" do |f|
201
+ f.write <<-RUBY
202
+ metric "Sky is limit" do
203
+ def bounds
204
+ [6,12]
205
+ end
206
+ end
207
+ RUBY
208
+ end
209
+ assert_equal [6,12], Vanity::Metric.bounds(Vanity.playground.metric(:sky_is_limit))
210
+ end
211
+
212
+ test "metric without bounds" do
213
+ metric "Sky is limit"
214
+ assert_equal [nil, nil], Vanity::Metric.bounds(Vanity.playground.metric(:sky_is_limit))
215
+ end
216
+
217
+ test "metric with no method bounds" do
218
+ metric = Object.new
219
+ assert_equal [nil, nil], Vanity::Metric.bounds(metric)
220
+ end
221
+ end
222
+
223
+
224
+ context "Metric last_update_at" do
225
+ test "for new metric" do
226
+ metric "Coolness"
227
+ metric = Vanity.playground.metric(:coolness)
228
+ assert_nil metric.last_update_at
229
+ end
230
+
231
+ test "with data point" do
232
+ metric "Coolness"
233
+ metric = Vanity.playground.metric(:coolness)
234
+ metric.track!
235
+ Timecop.freeze Time.now + 1.day do
236
+ metric.track!
237
+ end
238
+ assert_in_delta metric.last_update_at.to_i, (Time.now + 1.day).to_i, 1
239
+ end
240
+ end
241
+
242
+
243
+ context "Metric data" do
244
+ test "explicit dates" do
245
+ metric "Yawns/sec"
246
+ Timecop.freeze(today - 4) { Vanity.playground.track! :yawns_sec, 4 }
247
+ Timecop.freeze(today - 2) { Vanity.playground.track! :yawns_sec, 2 }
248
+ Vanity.playground.track! :yawns_sec
249
+ boredom = Vanity::Metric.data(Vanity.playground.metric(:yawns_sec), Date.today - 5, Date.today)
250
+ assert_equal [[today - 5, 0], [today - 4, 4], [today - 3, 0], [today - 2, 2], [today - 1, 0], [today, 1]], boredom
251
+ end
252
+
253
+ test "start date only" do
254
+ metric "Yawns/sec"
255
+ Timecop.freeze(today - 4) { Vanity.playground.track! :yawns_sec, 4 }
256
+ Timecop.freeze(today - 2) { Vanity.playground.track! :yawns_sec, 2 }
257
+ Vanity.playground.track! :yawns_sec
258
+ boredom = Vanity::Metric.data(Vanity.playground.metric(:yawns_sec), Date.today - 4)
259
+ assert_equal [[today - 4, 4], [today - 3, 0], [today - 2, 2], [today - 1, 0], [today, 1]], boredom
260
+ end
261
+
262
+ test "start date and duration" do
263
+ metric "Yawns/sec"
264
+ Timecop.freeze(today - 4) { Vanity.playground.track! :yawns_sec, 4 }
265
+ Timecop.freeze(today - 2) { Vanity.playground.track! :yawns_sec, 2 }
266
+ Vanity.playground.track! :yawns_sec
267
+ boredom = Vanity::Metric.data(Vanity.playground.metric(:yawns_sec), 5)
268
+ assert_equal [[today - 4, 4], [today - 3, 0], [today - 2, 2], [today - 1, 0], [today, 1]], boredom
269
+ end
270
+
271
+ test "no data" do
272
+ metric "Yawns/sec"
273
+ boredom = Vanity::Metric.data(Vanity.playground.metric(:yawns_sec))
274
+ assert_equal 90, boredom.size
275
+ assert_equal [today - 89, 0], boredom.first
276
+ assert_equal [today, 0], boredom.last
277
+ end
278
+
279
+ test "using custom values method" do
280
+ File.open "tmp/experiments/metrics/hours_in_day.rb", "w" do |f|
281
+ f.write <<-RUBY
282
+ metric "Hours in day" do
283
+ def values(from, to)
284
+ (from..to).map { |d| 24 }
285
+ end
286
+ end
287
+ RUBY
288
+ end
289
+ data = Vanity::Metric.data(Vanity.playground.metric(:hours_in_day))
290
+ assert_equal [24] * 90, data.map(&:last)
291
+ end
292
+
293
+ end
@@ -0,0 +1,104 @@
1
+ require "test/test_helper"
2
+
3
+
4
+ context "Google Analytics" do
5
+
6
+ setup do
7
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
8
+ f.write <<-RUBY
9
+ metric "GA" do
10
+ google_analytics "UA2"
11
+ end
12
+ RUBY
13
+ end
14
+ end
15
+
16
+ GA_RESULT = Struct.new(:date, :pageviews, :visits)
17
+ GA_PROFILE = Struct.new(:web_property_id)
18
+
19
+ test "fail if Garb not available" do
20
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
21
+ f.write <<-RUBY
22
+ metric "GA" do
23
+ expects(:require).raises LoadError
24
+ google_analytics "UA2"
25
+ end
26
+ RUBY
27
+ end
28
+ assert_raise LoadError do
29
+ Vanity.playground.metrics
30
+ end
31
+ end
32
+
33
+ test "constructs a report" do
34
+ Vanity.playground.metrics
35
+ assert metric(:ga).report
36
+ end
37
+
38
+ test "default to pageviews metric" do
39
+ Vanity.playground.metrics
40
+ assert_equal [:pageviews], metric(:ga).report.metrics.elements
41
+ end
42
+
43
+ test "apply data dimension and sort" do
44
+ Vanity.playground.metrics
45
+ assert_equal [:date], metric(:ga).report.dimensions.elements
46
+ assert_equal [:date], metric(:ga).report.sort.elements
47
+ end
48
+
49
+ test "accept other metrics" do
50
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
51
+ f.write <<-RUBY
52
+ metric "GA" do
53
+ google_analytics "UA2", :visitors
54
+ end
55
+ RUBY
56
+ end
57
+ Vanity.playground.metrics
58
+ assert_equal [:visitors], metric(:ga).report.metrics.elements
59
+ end
60
+
61
+ test "does not support hooks" do
62
+ Vanity.playground.metrics
63
+ assert_raises RuntimeError do
64
+ metric(:ga).hook
65
+ end
66
+ end
67
+
68
+ test "should find matching profile" do
69
+ Vanity.playground.metrics
70
+ Garb::Profile.expects(:all).returns(Array.new(3) { |i| GA_PROFILE.new("UA#{i + 1}") })
71
+ metric(:ga).report.stubs(:send_request_for_body).returns(nil)
72
+ Garb::ReportResponse.stubs(:new).returns(mock(:results=>[]))
73
+ metric(:ga).values(Date.parse("2010-02-10"), Date.parse("2010-02-12"))
74
+ assert_equal "UA2", metric(:ga).report.profile.web_property_id
75
+ end
76
+
77
+ test "should map results from report" do
78
+ Vanity.playground.metrics
79
+ today = Date.today
80
+ response = mock(:results=>Array.new(3) { |i| GA_RESULT.new("2010021#{i}", i + 1) })
81
+ Garb::Profile.stubs(:all).returns([])
82
+ Garb::ReportResponse.expects(:new).returns(response)
83
+ metric(:ga).report.stubs(:send_request_for_body).returns(nil)
84
+ assert_equal [1,2,3], metric(:ga).values(Date.parse("2010-02-10"), Date.parse("2010-02-12"))
85
+ end
86
+
87
+ test "mapping GA metrics to single value" do
88
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
89
+ f.write <<-RUBY
90
+ metric "GA" do
91
+ google_analytics "UA2", :mapper=>lambda { |e| e.pageviews * e.visits }
92
+ end
93
+ RUBY
94
+ end
95
+ Vanity.playground.metrics
96
+ today = Date.today
97
+ response = mock(:results=>Array.new(3) { |i| GA_RESULT.new("2010021#{i}", i + 1, i + 1) })
98
+ Garb::Profile.stubs(:all).returns([])
99
+ Garb::ReportResponse.expects(:new).returns(response)
100
+ metric(:ga).report.stubs(:send_request_for_body).returns(nil)
101
+ assert_equal [1,4,9], metric(:ga).values(Date.parse("2010-02-10"), Date.parse("2010-02-12"))
102
+ end
103
+
104
+ end
@@ -0,0 +1,109 @@
1
+ require "test/test_helper"
2
+
3
+
4
+ context "Remote metrics" do
5
+ setup do
6
+ FileUtils.mkpath "tmp/config"
7
+ File.open "tmp/config/vanity.yml", "w" do |f|
8
+ f.write <<-RUBY
9
+ metrics:
10
+ sandbox: http://api.vanitydash.com/metrics/sandbox
11
+ RUBY
12
+ end
13
+ ::Rails.stubs(:root).returns(Pathname.new(File.expand_path("tmp")))
14
+ Dir.chdir "tmp" do
15
+ Vanity.playground.load!
16
+ end
17
+ end
18
+
19
+ test "load from configuration file" do
20
+ assert Vanity.playground.metrics[:sandbox]
21
+ end
22
+
23
+ test "create remote metric from configuration file" do
24
+ stub_request :post, /vanitydash/
25
+ metric(:sandbox).track!
26
+ assert_requested :post, /api\.vanitydash\.com/
27
+ end
28
+ end
29
+
30
+
31
+ context "Remote send" do
32
+ setup do
33
+ @metric = Vanity::Metric.new(Vanity.playground, :sandbox)
34
+ @metric.remote "http://api.vanitydash.com/metrics/sandbox"
35
+ Vanity.playground.metrics[:sandbox] = @metric
36
+ stub_request :post, /vanitydash/
37
+ end
38
+
39
+ test "remote send in sequence" do
40
+ Vanity.playground.track! :sandbox
41
+ Vanity.playground.track! :sandbox
42
+ assert_requested(:post, "http://api.vanitydash.com/metrics/sandbox", :times=>2)
43
+ end
44
+
45
+ test "remote sends url-encoded data" do
46
+ Vanity.playground.track! :sandbox, 12
47
+ assert_requested(:post, /api/) { |request| request.headers["Content-Type"] == "application/x-www-form-urlencoded" }
48
+ end
49
+
50
+ test "remote sends metric identifier" do
51
+ Vanity.playground.track! :sandbox, 12
52
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["metric"] == "sandbox" }
53
+ end
54
+
55
+ test "remote sends RFC 2616 compliant time stamp" do
56
+ Vanity.playground.track! :sandbox, 12
57
+ assert_requested(:post, /api/) { |request| Time.httpdate(Rack::Utils.parse_query(request.body)["timestamp"]) }
58
+ end
59
+
60
+ test "remote sends array of values" do
61
+ Vanity.playground.track! :sandbox, [1,2,3]
62
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["values[]"] == %w{1 2 3} }
63
+ end
64
+
65
+ test "remote sends default of 1" do
66
+ Vanity.playground.track! :sandbox
67
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["values[]"] == "1" }
68
+ end
69
+
70
+ test "remote sends current identity" do
71
+ Vanity.context = Object.new
72
+ class << Vanity.context
73
+ def vanity_identity
74
+ "xkcd"
75
+ end
76
+ end
77
+ Vanity.playground.track! :sandbox, 12
78
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["identity"] == "xkcd" }
79
+ end
80
+
81
+ test "remote sends with additional query parameters" do
82
+ @metric.remote "http://api.vanitydash.com/metrics/sandbox?ask=receive"
83
+ Vanity.playground.track! :sandbox, 12
84
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["ask"] == "receive" }
85
+ end
86
+
87
+ test "remote send handles standard error" do
88
+ stub_request(:post, /api/).to_raise(StandardError)
89
+ Vanity.playground.track! :sandbox
90
+ stub_request(:post, /api/)
91
+ Vanity.playground.track! :sandbox
92
+ assert_requested(:post, /api/, :times=>2)
93
+ end
94
+
95
+ test "remote send handles timeout error" do
96
+ stub_request(:post, /api/).to_timeout
97
+ Vanity.playground.track! :sandbox
98
+ stub_request(:post, /api/)
99
+ Vanity.playground.track! :sandbox
100
+ assert_requested(:post, /api/, :times=>2)
101
+ end
102
+
103
+ test "remote does not send when metrics disabled" do
104
+ not_collecting!
105
+ Vanity.playground.track! :sandbox
106
+ Vanity.playground.track! :sandbox
107
+ assert_requested(:post, /api/, :times=>0)
108
+ end
109
+ end