metry 2.0.5 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +12 -6
- data/Rakefile +5 -0
- data/TODO +1 -6
- data/example/example.rb +1 -1
- data/features/app_tracking.feature +1 -2
- data/features/basic_tracking.feature +19 -38
- data/features/psycho/dashboard.feature +3 -11
- data/features/psycho/experiments.feature +28 -0
- data/features/psycho/visitor_tracking.feature +4 -4
- data/features/step_definitions/experiments.rb +8 -0
- data/features/step_definitions/psycho.rb +14 -0
- data/features/step_definitions/tracking.rb +56 -24
- data/features/support/env.rb +0 -1
- data/features/support/helpers.rb +6 -0
- data/lib/metry.rb +12 -5
- data/lib/metry/cohort.rb +19 -0
- data/lib/metry/event.rb +26 -0
- data/lib/metry/experiment.rb +36 -13
- data/lib/metry/goal.rb +18 -0
- data/lib/metry/psycho.rb +24 -93
- data/lib/metry/psycho/dashboard.erb +5 -5
- data/lib/metry/psycho/edit_goal.erb +1 -1
- data/lib/metry/psycho/experiment.erb +25 -0
- data/lib/metry/psycho/new_goal.erb +1 -1
- data/lib/metry/psycho/visitor.erb +4 -1
- data/lib/metry/psycho/visitors.erb +6 -0
- data/lib/metry/rack/tracking.rb +19 -18
- data/lib/metry/visitor.rb +30 -0
- data/radiant/example/features/metry.feature +21 -43
- data/radiant/example/features/step_definitions/tracking.rb +56 -24
- data/radiant/example/features/step_definitions/web.rb +0 -7
- data/radiant/example/features/support/env.rb +7 -3
- data/radiant/example/features/support/helpers.rb +6 -0
- data/radiant/extension/lib/metry_tags.rb +3 -1
- data/test/shared.rb +3 -1
- data/test/test_experiment.rb +104 -0
- metadata +45 -9
- data/features/psycho/goals.feature +0 -53
- data/features/step_definitions/goals.rb +0 -3
- data/lib/metry/psycho/goal.erb +0 -9
- data/lib/metry/storage.rb +0 -142
- data/radiant/example/features/step_definitions/experiments.rb +0 -12
- data/test/test_storage.rb +0 -25
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -8,24 +8,30 @@ example/example.rb
|
|
8
8
|
features/app_tracking.feature
|
9
9
|
features/basic_tracking.feature
|
10
10
|
features/psycho/dashboard.feature
|
11
|
-
features/psycho/
|
11
|
+
features/psycho/experiments.feature
|
12
12
|
features/psycho/visitor_tracking.feature
|
13
13
|
features/sample_application.feature
|
14
|
-
features/step_definitions/
|
14
|
+
features/step_definitions/experiments.rb
|
15
|
+
features/step_definitions/psycho.rb
|
15
16
|
features/step_definitions/tracking.rb
|
16
17
|
features/step_definitions/web.rb
|
17
18
|
features/support/env.rb
|
19
|
+
features/support/helpers.rb
|
18
20
|
lib/metry.rb
|
21
|
+
lib/metry/cohort.rb
|
22
|
+
lib/metry/event.rb
|
19
23
|
lib/metry/experiment.rb
|
24
|
+
lib/metry/goal.rb
|
20
25
|
lib/metry/psycho.rb
|
21
26
|
lib/metry/psycho/dashboard.erb
|
22
27
|
lib/metry/psycho/edit_goal.erb
|
23
|
-
lib/metry/psycho/
|
28
|
+
lib/metry/psycho/experiment.erb
|
24
29
|
lib/metry/psycho/layout.erb
|
25
30
|
lib/metry/psycho/new_goal.erb
|
26
31
|
lib/metry/psycho/visitor.erb
|
32
|
+
lib/metry/psycho/visitors.erb
|
27
33
|
lib/metry/rack/tracking.rb
|
28
|
-
lib/metry/
|
34
|
+
lib/metry/visitor.rb
|
29
35
|
radiant/example/CHANGELOG
|
30
36
|
radiant/example/CONTRIBUTORS
|
31
37
|
radiant/example/INSTALL
|
@@ -43,11 +49,11 @@ radiant/example/config/routes.rb
|
|
43
49
|
radiant/example/db/schema.rb
|
44
50
|
radiant/example/features/metry.feature
|
45
51
|
radiant/example/features/psycho.feature
|
46
|
-
radiant/example/features/step_definitions/experiments.rb
|
47
52
|
radiant/example/features/step_definitions/radiant.rb
|
48
53
|
radiant/example/features/step_definitions/tracking.rb
|
49
54
|
radiant/example/features/step_definitions/web.rb
|
50
55
|
radiant/example/features/support/env.rb
|
56
|
+
radiant/example/features/support/helpers.rb
|
51
57
|
radiant/example/public/.htaccess
|
52
58
|
radiant/example/public/404.html
|
53
59
|
radiant/example/public/500.html
|
@@ -114,7 +120,7 @@ radiant/extension/lib/metry_tags.rb
|
|
114
120
|
radiant/extension/lib/tasks/metry_extension_tasks.rake
|
115
121
|
radiant/extension/metry_extension.rb
|
116
122
|
test/shared.rb
|
117
|
-
test/
|
123
|
+
test/test_experiment.rb
|
118
124
|
vendor/webrat/.document
|
119
125
|
vendor/webrat/History.txt
|
120
126
|
vendor/webrat/MIT-LICENSE.txt
|
data/Rakefile
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
+
ENV["RUBY_FLAGS"] = "-I#{%w(lib ext bin test).join(File::PATH_SEPARATOR)}"
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'hoe'
|
3
5
|
|
4
6
|
Hoe.spec 'metry' do
|
5
7
|
developer('Nathaniel Talbott', 'nathaniel@terralien.com')
|
6
8
|
self.rubyforge_name = 'terralien'
|
9
|
+
extra_deps << ['mongomapper', '~> 0.3']
|
10
|
+
extra_deps << ['mongodb-mongo', '~> 0.10']
|
11
|
+
extra_deps << ['mongodb-mongo_ext', '~> 0.4']
|
7
12
|
end
|
8
13
|
|
9
14
|
require 'cucumber/rake/task'
|
data/TODO
CHANGED
@@ -1,10 +1,5 @@
|
|
1
|
-
Limit visitors on dashboard to 10 most recent
|
2
|
-
Add full listing of visitors
|
3
|
-
Show more details about visitors
|
4
|
-
Add referrer to event display on visitor pages
|
5
|
-
Add display of last 10 events to dashboard
|
6
1
|
Show goal conversion for each experiment
|
7
|
-
Allow manually viewing a particular
|
2
|
+
Allow manually viewing a particular alternative
|
8
3
|
|
9
4
|
More unit tests
|
10
5
|
|
data/example/example.rb
CHANGED
@@ -6,6 +6,5 @@ Feature: Application Tracking
|
|
6
6
|
Scenario: Track an additional facet
|
7
7
|
Given an empty tracking database
|
8
8
|
When I view "/extra?track=stuff"
|
9
|
-
Then
|
10
|
-
| key | value |
|
9
|
+
Then tracking event #1 extra should contain:
|
11
10
|
| extra | stuff |
|
@@ -20,73 +20,54 @@ Feature: Access Tracking
|
|
20
20
|
Scenario: Basic request data is tracked
|
21
21
|
When I view "/"
|
22
22
|
And I view "/subpage"
|
23
|
-
Then
|
24
|
-
| key | value |
|
23
|
+
Then tracking event #1 should contain:
|
25
24
|
| path | / |
|
26
|
-
|
|
27
|
-
And
|
28
|
-
| key | value |
|
25
|
+
| created_at | _exists_ |
|
26
|
+
And tracking event #2 should contain:
|
29
27
|
| path | /subpage |
|
30
|
-
|
|
28
|
+
| created_at | _exists_ |
|
31
29
|
|
32
30
|
Scenario: New visitor is tracked
|
33
31
|
When I view "/"
|
34
32
|
And I view "/subpage"
|
35
|
-
Then there should be a tracking event
|
36
|
-
|
37
|
-
|
38
|
-
And there should be a tracking event "2":
|
39
|
-
| key | value |
|
40
|
-
| visitor | 1 |
|
41
|
-
And there should be a visitor "1"
|
33
|
+
Then there should be a tracking event #1 with visitor #1
|
34
|
+
And there should be a tracking event #2 with visitor #1
|
35
|
+
And there should be a visitor #1
|
42
36
|
|
43
37
|
Scenario: Two visitors are tracked
|
44
38
|
Given I view "/"
|
45
39
|
When I am a new visitor
|
46
40
|
Given I view "/"
|
47
|
-
Then there should be a tracking event
|
48
|
-
|
49
|
-
| visitor | 1 |
|
50
|
-
And there should be a tracking event "2":
|
51
|
-
| key | value |
|
52
|
-
| visitor | 2 |
|
41
|
+
Then there should be a tracking event #1 with visitor #1
|
42
|
+
Then there should be a tracking event #2 with visitor #2
|
53
43
|
And there should be 2 visitors
|
54
|
-
And there should be a visitor "1"
|
55
|
-
And there should be a visitor "2"
|
56
44
|
|
57
45
|
Scenario: All facets should be tracked
|
58
46
|
When I view "/"
|
59
|
-
Then
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
| host | example.org |
|
47
|
+
Then tracking event #1 should contain:
|
48
|
+
| path | / |
|
49
|
+
| created_at | _exists_ |
|
50
|
+
| ip | 127.0.0.1 |
|
51
|
+
| host | www.example.com |
|
65
52
|
|
66
53
|
Scenario: path should include query string
|
67
54
|
When I view "/?here=there"
|
68
|
-
Then
|
69
|
-
| key | value |
|
55
|
+
Then tracking event #1 should contain:
|
70
56
|
| path | /?here=there |
|
71
57
|
|
72
58
|
Scenario: Should track status codes
|
73
59
|
When I view "/"
|
74
60
|
And I view "/missing"
|
75
|
-
Then
|
76
|
-
| key | value |
|
61
|
+
Then tracking event #1 should contain:
|
77
62
|
| status | 200 |
|
78
|
-
Then
|
79
|
-
| key | value |
|
63
|
+
Then tracking event #2 should contain:
|
80
64
|
| status | 404 |
|
81
65
|
|
82
66
|
Scenario: Should track method
|
83
67
|
When I view "/"
|
84
68
|
And I post to "/post":
|
85
|
-
| key | value |
|
86
69
|
| bogus | bogus |
|
87
|
-
Then
|
88
|
-
| key | value |
|
70
|
+
Then tracking event #1 should contain:
|
89
71
|
| method | GET |
|
90
|
-
Then
|
91
|
-
| key | value |
|
72
|
+
Then tracking event #2 should contain:
|
92
73
|
| method | POST |
|
@@ -2,16 +2,8 @@ Feature: Psycho Dashboard
|
|
2
2
|
|
3
3
|
Scenario: Basics
|
4
4
|
Given an empty tracking database
|
5
|
-
And I add
|
6
|
-
And I am a new visitor
|
7
|
-
And I view "/"
|
8
|
-
And I view "/subpage"
|
9
|
-
And I am a new visitor
|
10
|
-
And I view "/"
|
5
|
+
And I add an experiment "sweet"
|
11
6
|
When I view "/admin/metry"
|
12
|
-
Then I should see "
|
13
|
-
And I should see "sweet
|
14
|
-
And I should see "Recent Visitors"
|
15
|
-
And I should see "Visitor 1"
|
16
|
-
And I should see "Visitor 2"
|
7
|
+
Then I should see "Experiments"
|
8
|
+
And I should see "sweet"
|
17
9
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: Track Experiments
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given an empty tracking database
|
5
|
+
And I add an experiment "Fred"
|
6
|
+
|
7
|
+
Scenario: Add a goal
|
8
|
+
Given I view "/admin/metry"
|
9
|
+
And I follow "Fred"
|
10
|
+
And I follow "New Goal"
|
11
|
+
And I fill in "name" with "Cool"
|
12
|
+
And I fill in "path" with "/goal"
|
13
|
+
And I press "Create"
|
14
|
+
Then I should be on the page for experiment #1
|
15
|
+
And I should see "Cool"
|
16
|
+
And I should see "Path: /goal"
|
17
|
+
|
18
|
+
Scenario: Edit a Goal
|
19
|
+
Given I add a goal named "Bogus" to experiment "Fred" with path "/"
|
20
|
+
When I view "/admin/metry"
|
21
|
+
And I follow "Fred"
|
22
|
+
And I follow "Edit"
|
23
|
+
And I fill in "name" with "Right"
|
24
|
+
And I fill in "path" with "/subpage"
|
25
|
+
And I press "Save"
|
26
|
+
Then I should be on the page for experiment #1
|
27
|
+
And I should see "Right"
|
28
|
+
And I should see "Path: /subpage"
|
@@ -12,8 +12,8 @@ Feature: Psycho Visitor Tracking
|
|
12
12
|
And I am a new visitor
|
13
13
|
And I view "/"
|
14
14
|
When I view "/admin/metry"
|
15
|
-
Then I should see
|
16
|
-
And I should see
|
15
|
+
Then I should see visitor #1
|
16
|
+
And I should see visitor #2
|
17
17
|
|
18
18
|
Scenario: View visitor detail
|
19
19
|
Given I view "/"
|
@@ -21,7 +21,7 @@ Feature: Psycho Visitor Tracking
|
|
21
21
|
And I am a new visitor
|
22
22
|
And I view "/"
|
23
23
|
When I view "/admin/metry"
|
24
|
-
And I follow "Visitor
|
24
|
+
And I follow "Visitor"
|
25
25
|
Then I should see "/"
|
26
26
|
And I should see "/subpage"
|
27
27
|
|
@@ -29,4 +29,4 @@ Feature: Psycho Visitor Tracking
|
|
29
29
|
Given I view "/admin/metry"
|
30
30
|
And I view "/admin/metry"
|
31
31
|
When I view "/admin/metry"
|
32
|
-
Then I should
|
32
|
+
Then I should see "0 events"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Given /^I add an experiment "([^\"]*)"$/ do |name|
|
2
|
+
Metry::Experiment.create(:name => name)
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^I add a goal named "([^\"]*)" to experiment "([^\"]*)" with path "([^\"]*)"$/ do |name, experiment, path|
|
6
|
+
experiment = Metry::Experiment.find(:first, :conditions => {:name => experiment})
|
7
|
+
experiment.goals << Metry::Goal.create(:name => name, :path => path)
|
8
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Then /^I should see visitor #(\d+)$/ do |index|
|
2
|
+
visitor = at(Metry::Visitor, index)
|
3
|
+
assert_contain "Visitor #{visitor.id}"
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^I should not see visitor #(\d+)$/ do |index|
|
7
|
+
visitor = at(Metry::Visitor, index)
|
8
|
+
assert_not_contain "Visitor #{visitor.id}"
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^I should be on the page for experiment #(\d+)$/ do |index|
|
12
|
+
experiment = at(Metry::Experiment, index)
|
13
|
+
assert_equal "/admin/metry/experiments/#{experiment.id}", current_url
|
14
|
+
end
|
@@ -1,43 +1,75 @@
|
|
1
1
|
Given /^an empty tracking database$/ do
|
2
|
-
Metry.
|
2
|
+
Metry.clear
|
3
3
|
end
|
4
4
|
|
5
5
|
Then /^there should be (\d+) tracking events?$/ do |event_count|
|
6
|
-
assert_equal(event_count.to_i, Metry.
|
6
|
+
assert_equal(event_count.to_i, Metry::Event.count)
|
7
7
|
end
|
8
8
|
|
9
9
|
Then /^there should be (\d+) visitors$/ do |visitor_count|
|
10
|
-
assert_equal(visitor_count.to_i, Metry.
|
10
|
+
assert_equal(visitor_count.to_i, Metry::Visitor.count)
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
event = Metry
|
15
|
-
assert event, "Unable to lookup event #{
|
16
|
-
table.
|
17
|
-
expected = hash["value"]
|
13
|
+
Then /^tracking event #(\d+) should contain:$/ do |index, table|
|
14
|
+
event = at(Metry::Event, index)
|
15
|
+
assert event, "Unable to lookup event at #{index}."
|
16
|
+
table.rows_hash.each do |key, expected|
|
18
17
|
case expected
|
19
18
|
when "_exists_"
|
20
|
-
assert event
|
19
|
+
assert event.send(key), "Key #{key} does not exist."
|
21
20
|
else
|
22
|
-
assert_equal expected, event
|
21
|
+
assert_equal expected, event.send(key), "Key #{key} does not match."
|
23
22
|
end
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
27
|
-
Then /^
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
expected = hash["value"]
|
32
|
-
case expected
|
33
|
-
when "_exists_"
|
34
|
-
assert visitor[hash["key"]], "Key #{hash["key"]} does not exist."
|
35
|
-
else
|
36
|
-
assert_equal expected, visitor[hash["key"]], "Key #{hash["key"]} does not match."
|
37
|
-
end
|
26
|
+
Then /^tracking event #(\d+) extra should contain:$/ do |index, table|
|
27
|
+
event = at(Metry::Event, index)
|
28
|
+
table.rows_hash.each do |key, expected|
|
29
|
+
assert_equal expected, event.extra[key]
|
38
30
|
end
|
39
31
|
end
|
40
32
|
|
41
|
-
Then /^there should be a visitor
|
42
|
-
|
43
|
-
|
33
|
+
Then /^there should be a tracking event #(\d+) with visitor #(\d+)$/ do |event_index, visitor_index|
|
34
|
+
event = at(Metry::Event, event_index)
|
35
|
+
visitor = at(Metry::Visitor, visitor_index)
|
36
|
+
assert_equal event.visitor, visitor
|
37
|
+
end
|
38
|
+
|
39
|
+
Then /^there should be a visitor #(\d+)$/ do |index|
|
40
|
+
assert at(Metry::Visitor, index)
|
41
|
+
end
|
42
|
+
|
43
|
+
Then /^visitor #(\d+) should have experiment "([^\"]*)" with "([^\"]*)"$/ do |index, experiment, alternative|
|
44
|
+
visitor = at(Metry::Visitor, index)
|
45
|
+
experiment = Metry::Experiment.find(:first, :conditions => {:name => experiment})
|
46
|
+
assert experiment.cohort_for(visitor)
|
47
|
+
end
|
48
|
+
|
49
|
+
Then /^event #(\d+) should have experiment "([^\"]*)" with "([^\"]*)"$/ do |index, experiment, alternative|
|
50
|
+
event = at(Metry::Event, index)
|
51
|
+
experiment = Metry::Experiment.find(:first, :conditions => {:name => experiment})
|
52
|
+
assert_equal alternative, event.experiments[experiment.id]
|
53
|
+
end
|
54
|
+
|
55
|
+
Then /^I should see the same page (\d+) times$/ do |count|
|
56
|
+
expected_body = webrat.response_body
|
57
|
+
count.to_i.times do
|
58
|
+
When(%(I view "#{current_url}"))
|
59
|
+
assert_equal expected_body, webrat.response_body
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
When /^(\d+) visitors view "([^\"]*)"$/ do |count, path|
|
64
|
+
@alternatives = Hash.new(0)
|
65
|
+
count.to_i.times do
|
66
|
+
visit(path)
|
67
|
+
@alternatives[webrat.response_body] += 1
|
68
|
+
clear_cookies
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
Then /^there should be (\d+) alternatives each displayed at least (\d+) times$/ do |alternatives, minimum|
|
73
|
+
assert_equal alternatives.to_i, @alternatives.size
|
74
|
+
assert @alternatives.values.all?{|e| e >= minimum.to_i}
|
75
|
+
end
|
data/features/support/env.rb
CHANGED
data/lib/metry.rb
CHANGED
@@ -1,18 +1,25 @@
|
|
1
1
|
$: << File.dirname(__FILE__)
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'mongomapper'
|
4
|
+
|
5
|
+
require 'metry/event'
|
6
|
+
require 'metry/visitor'
|
7
|
+
require 'metry/goal'
|
4
8
|
require 'metry/rack/tracking'
|
5
9
|
require 'metry/experiment'
|
10
|
+
require 'metry/cohort'
|
6
11
|
require 'metry/psycho'
|
7
12
|
|
8
13
|
module Metry
|
9
|
-
VERSION = '2.0
|
14
|
+
VERSION = '2.1.0'
|
10
15
|
|
11
16
|
def self.init(dbname)
|
12
|
-
|
17
|
+
MongoMapper.database = dbname
|
13
18
|
end
|
14
19
|
|
15
|
-
def self.
|
16
|
-
|
20
|
+
def self.clear
|
21
|
+
[Metry::Event, Metry::Visitor, Metry::Goal, Metry::Experiment].each do |m|
|
22
|
+
m.delete_all
|
23
|
+
end
|
17
24
|
end
|
18
25
|
end
|