moses-vanity 1.7.1
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.
- data/.autotest +22 -0
- data/.gitignore +7 -0
- data/.rvmrc +3 -0
- data/.travis.yml +13 -0
- data/CHANGELOG +374 -0
- data/Gemfile +28 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +108 -0
- data/Rakefile +189 -0
- data/bin/vanity +16 -0
- data/doc/_config.yml +2 -0
- data/doc/_layouts/_header.html +34 -0
- data/doc/_layouts/page.html +47 -0
- data/doc/_metrics.textile +12 -0
- data/doc/ab_testing.textile +210 -0
- data/doc/configuring.textile +45 -0
- data/doc/contributing.textile +93 -0
- data/doc/credits.textile +23 -0
- data/doc/css/page.css +83 -0
- data/doc/css/print.css +43 -0
- data/doc/css/syntax.css +7 -0
- data/doc/email.textile +129 -0
- data/doc/experimental.textile +31 -0
- data/doc/faq.textile +8 -0
- data/doc/identity.textile +43 -0
- data/doc/images/ab_in_dashboard.png +0 -0
- data/doc/images/clear_winner.png +0 -0
- data/doc/images/price_options.png +0 -0
- data/doc/images/sidebar_test.png +0 -0
- data/doc/images/signup_metric.png +0 -0
- data/doc/images/vanity.png +0 -0
- data/doc/index.textile +91 -0
- data/doc/metrics.textile +231 -0
- data/doc/rails.textile +89 -0
- data/doc/site.js +27 -0
- data/generators/templates/vanity_migration.rb +53 -0
- data/generators/vanity_generator.rb +8 -0
- data/lib/generators/templates/vanity_migration.rb +53 -0
- data/lib/generators/vanity_generator.rb +15 -0
- data/lib/vanity.rb +36 -0
- data/lib/vanity/adapters/abstract_adapter.rb +140 -0
- data/lib/vanity/adapters/active_record_adapter.rb +248 -0
- data/lib/vanity/adapters/mock_adapter.rb +157 -0
- data/lib/vanity/adapters/mongodb_adapter.rb +178 -0
- data/lib/vanity/adapters/redis_adapter.rb +160 -0
- data/lib/vanity/backport.rb +26 -0
- data/lib/vanity/commands/list.rb +21 -0
- data/lib/vanity/commands/report.rb +64 -0
- data/lib/vanity/commands/upgrade.rb +34 -0
- data/lib/vanity/experiment/ab_test.rb +507 -0
- data/lib/vanity/experiment/base.rb +214 -0
- data/lib/vanity/frameworks.rb +16 -0
- data/lib/vanity/frameworks/rails.rb +318 -0
- data/lib/vanity/helpers.rb +66 -0
- data/lib/vanity/images/x.gif +0 -0
- data/lib/vanity/metric/active_record.rb +85 -0
- data/lib/vanity/metric/base.rb +244 -0
- data/lib/vanity/metric/google_analytics.rb +83 -0
- data/lib/vanity/metric/remote.rb +53 -0
- data/lib/vanity/playground.rb +396 -0
- data/lib/vanity/templates/_ab_test.erb +28 -0
- data/lib/vanity/templates/_experiment.erb +5 -0
- data/lib/vanity/templates/_experiments.erb +7 -0
- data/lib/vanity/templates/_metric.erb +14 -0
- data/lib/vanity/templates/_metrics.erb +13 -0
- data/lib/vanity/templates/_report.erb +27 -0
- data/lib/vanity/templates/_vanity.js.erb +20 -0
- data/lib/vanity/templates/flot.min.js +1 -0
- data/lib/vanity/templates/jquery.min.js +19 -0
- data/lib/vanity/templates/vanity.css +26 -0
- data/lib/vanity/templates/vanity.js +82 -0
- data/lib/vanity/version.rb +11 -0
- data/test/adapters/redis_adapter_test.rb +17 -0
- data/test/experiment/ab_test.rb +771 -0
- data/test/experiment/base_test.rb +150 -0
- data/test/experiments/age_and_zipcode.rb +19 -0
- data/test/experiments/metrics/cheers.rb +3 -0
- data/test/experiments/metrics/signups.rb +2 -0
- data/test/experiments/metrics/yawns.rb +3 -0
- data/test/experiments/null_abc.rb +5 -0
- data/test/metric/active_record_test.rb +277 -0
- data/test/metric/base_test.rb +293 -0
- data/test/metric/google_analytics_test.rb +104 -0
- data/test/metric/remote_test.rb +109 -0
- data/test/myapp/app/controllers/application_controller.rb +2 -0
- data/test/myapp/app/controllers/main_controller.rb +7 -0
- data/test/myapp/config/boot.rb +110 -0
- data/test/myapp/config/environment.rb +10 -0
- data/test/myapp/config/environments/production.rb +0 -0
- data/test/myapp/config/routes.rb +3 -0
- data/test/passenger_test.rb +43 -0
- data/test/playground_test.rb +26 -0
- data/test/rails_dashboard_test.rb +37 -0
- data/test/rails_helper_test.rb +36 -0
- data/test/rails_test.rb +389 -0
- data/test/test_helper.rb +145 -0
- data/vanity.gemspec +26 -0
- 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
|