metry 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ === 2.0.4 / 2009-08-09
2
+
3
+ * Improved goal display.
4
+ * Properly submoduled webrat.
5
+ * Goal paths are now Regexp's.
6
+ * Added goal editing.
7
+
1
8
  === 2.0.3 / 2009-08-08
2
9
 
3
10
  * Really ignore events generated by Psycho.
data/TODO CHANGED
@@ -1,5 +1,3 @@
1
- Figure out why Psycho events are not being ignored in production
2
- Allow goals to have N paths
3
1
  Limit visitors on dashboard to 10 most recent
4
2
  Add full listing of visitors
5
3
  Show more details about visitors
@@ -8,8 +6,6 @@ Add display of last 10 events to dashboard
8
6
  Show goal conversion for each experiment
9
7
  Allow manually viewing a particular alternatively
10
8
 
11
- Switch to submodules for vendor'd libs
12
-
13
9
  More unit tests
14
10
 
15
11
  Add support for non-pageview event tracking
@@ -11,14 +11,43 @@ Feature: Track Goals
11
11
  Scenario: Create a goal
12
12
  Given I view "/admin/metry"
13
13
  And I follow "New Goal"
14
- And I fill in "name" with "Cool goal"
14
+ And I fill in "name" with "Cool"
15
15
  And I fill in "path" with "/goal"
16
16
  And I press "Create"
17
- Then I should be on "/admin/metry/"
18
- And the page should have "#goals .goal"
17
+ Then I should be on "/admin/metry/goals/1"
18
+ And I should see "Cool"
19
19
 
20
20
  Scenario: Goal count
21
21
  Given I add a goal named "My Goal" with path "/"
22
22
  And I view "/"
23
23
  When I view "/admin/metry"
24
- Then I should see "My Goal: 1 visits"
24
+ Then I should see "My Goal: 1 visits"
25
+
26
+ Scenario: Goal Regexp
27
+ Given I add a goal named "Subpage" with path "/subpage/?"
28
+ When I view "/subpage"
29
+ And I view "/subpage/"
30
+ And I view "/admin/metry"
31
+ Then I should see "Subpage: 2 visits"
32
+
33
+ Scenario: View Goal Detail
34
+ Given I add a goal named "Root" with path "/"
35
+ And I view "/"
36
+ And I view "/"
37
+ When I view "/admin/metry"
38
+ And I follow "Root"
39
+ Then I should see "Root"
40
+ And I should see "Path: /"
41
+ And I should see "Visitor 1"
42
+
43
+ Scenario: Edit a Goal
44
+ Given I add a goal named "Bogus" with path "/"
45
+ When I view "/admin/metry"
46
+ And I follow "Bogus"
47
+ And I follow "Edit"
48
+ And I fill in "name" with "Right"
49
+ And I fill in "path" with "/subpage"
50
+ And I press "Save"
51
+ Then I should be on "/admin/metry/goals/1"
52
+ And I should see "Right"
53
+ And I should see "Path: /subpage"
@@ -6,7 +6,7 @@ require 'metry/experiment'
6
6
  require 'metry/psycho'
7
7
 
8
8
  module Metry
9
- VERSION = '2.0.3'
9
+ VERSION = '2.0.4'
10
10
 
11
11
  def self.init(dbname)
12
12
  @storage = Storage.new(dbname)
@@ -30,46 +30,88 @@ module Metry
30
30
  erb :dashboard
31
31
  end
32
32
 
33
- get "#{path}/visitor/:id" do
33
+ get "#{path}/visitors/:id" do
34
34
  @visitor = Visitor.find(params["id"])
35
35
  erb :visitor
36
36
  end
37
37
 
38
38
  post "#{path}/goals" do
39
- Goal.create!(params[:name], params[:path])
40
- redirect url('/')
39
+ goal = Goal.create!(params[:name], params[:path])
40
+ redirect url("/goals/#{goal.id}")
41
41
  end
42
42
 
43
43
  get "#{path}/goals/new" do
44
44
  erb :new_goal
45
45
  end
46
+
47
+ get "#{path}/goals/:id" do
48
+ @goal = Goal.find(params[:id])
49
+ erb :goal
50
+ end
51
+
52
+ get "#{path}/goals/:id/edit" do
53
+ @goal = Goal.find(params[:id])
54
+ erb :edit_goal
55
+ end
56
+
57
+ post "#{path}/goals/:id" do
58
+ goal = Goal.find(params[:id])
59
+ goal.name = params[:name]
60
+ goal.path = params[:path]
61
+ goal.save
62
+ redirect url("/goals/#{goal.id}")
63
+ end
46
64
 
47
65
  helpers do
48
66
  define_method(:url) do |url|
49
67
  "#{path}#{url}"
50
68
  end
69
+
70
+ include ::Rack::Utils
71
+ alias_method :h, :escape_html
51
72
  end
52
73
  end
53
74
  end
54
75
 
55
76
  class Goal
77
+ def self.find(id)
78
+ new(Metry.current.goal(id))
79
+ end
80
+
56
81
  def self.create!(name, path)
57
- Metry.current.add_goal('name' => name, 'path' => path)
82
+ new(Metry.current.add_goal('name' => name, 'path' => path))
58
83
  end
59
84
 
60
85
  def self.all
61
86
  Metry.current.goals.collect{|e| new(e)}
62
87
  end
63
88
 
64
- attr_reader :name, :path
89
+ attr_accessor :path, :id, :name
65
90
 
66
91
  def initialize(hash)
92
+ @id = hash['_id'].to_s
67
93
  @name = hash['name']
68
94
  @path = hash['path']
69
95
  end
70
96
 
97
+ def save
98
+ Metry.current.save_goal({'_id' => id, 'name' => name, 'path' => path})
99
+ end
100
+
101
+ def path_regexp
102
+ Regexp.new("^#{path}$")
103
+ end
104
+
71
105
  def visits
72
- Metry.current.all_events({'path' => @path}).size
106
+ events.size
107
+ end
108
+
109
+ def events
110
+ Metry.current.all_events({'path' => path_regexp})
111
+ end
112
+
113
+ def visitors
114
+ events.collect{|e| e['visitor']}.uniq.collect{|e| Visitor.find(e)}
73
115
  end
74
116
  end
75
117
 
@@ -1,7 +1,7 @@
1
1
  <h1>Goals</h1>
2
2
  <ul id="goals">
3
3
  <% @goals.each do |goal| %>
4
- <li class="goal"><%= goal.name %>: <%= goal.visits %> visits</li>
4
+ <li class="goal"><a href="<%= url "/goals/#{goal.id}" %>"><%= goal.name %></a>: <%= goal.visits %> visits</li>
5
5
  <% end %>
6
6
  </ul>
7
7
  <p><a href="<%= url "/goals/new" %>">New Goal</a></p>
@@ -9,6 +9,6 @@
9
9
  <h1>Recent Visitors</h1>
10
10
  <ul>
11
11
  <% @visitors.each do |v| %>
12
- <li><a href="<%= url "/visitor/#{v.id}" %>">Visitor <%= v.id %></a> (<%= v.events.size %> events)</li>
12
+ <li><a href="<%= url "/visitors/#{v.id}" %>">Visitor <%= v.id %></a> (<%= v.events.size %> events)</li>
13
13
  <% end %>
14
14
  </ul>
@@ -1,9 +1,9 @@
1
1
  <h1>New Goal</h1>
2
2
 
3
- <form action="<%= url "/goals" %>" method="POST">
3
+ <form action="<%= url "/goals" %>" method="post">
4
4
  <fieldset>
5
- <p><label for="name">Name</label><input type="text" name="name" /></p>
6
- <p><label for="path">Path</label><input type="text" name="path" /></p>
5
+ <p><label for="name">Name</label> <input type="text" name="name" /></p>
6
+ <p><label for="path">Path</label> <input type="text" name="path" /></p>
7
7
  <p><input type="submit" value="Create" /></p>
8
8
  </fieldset>
9
9
  </form>
@@ -74,12 +74,20 @@ module Metry
74
74
  end
75
75
 
76
76
  def add_goal(goal)
77
- @db.collection('goals') << goal
77
+ goal(@db.collection('goals').insert(goal))
78
78
  end
79
79
 
80
80
  def goals
81
81
  @db.collection('goals').find.to_a
82
82
  end
83
+
84
+ def goal(id)
85
+ @db.collection('goals').find(prep_selector('_id' => id)).next_object
86
+ end
87
+
88
+ def save_goal(goal)
89
+ @db.collection('goals').repsert(prep_selector('_id' => goal['_id']), goal)
90
+ end
83
91
 
84
92
  def clear
85
93
  %w(visitors events goals).each{|e| @db.drop_collection(e)}
@@ -9,6 +9,8 @@
9
9
 
10
10
  * Minor enhancements
11
11
 
12
+ * Upgrade to selenium-client to 1.2.16 (Brian Landau)
13
+ * Upgrade selenium-server.jar to 1.0.1 (Brian Landau)
12
14
  * Make redirect detection work in the face of rational maths (like when ruby-units is active) (Piers Cawley)
13
15
  * Use Launchy to handle opening pages in the browser with cross-platform compatibility (Bryan Helmkamp)
14
16
  * Added support for field_labeled_locators ending in non word characters
@@ -23,8 +23,14 @@ module Webrat
23
23
  def process_request(http_method, url, data = {}, headers = {})
24
24
  headers ||= {}
25
25
  data ||= {}
26
-
27
- env = headers.merge(:params => data, :method => http_method.to_s.upcase)
26
+
27
+ params = data.inject({}) do |data, (key,value)|
28
+ data[key] = Rack::Utils.unescape(value)
29
+ data
30
+ end
31
+
32
+ headers["HTTP_HOST"] = "www.example.com"
33
+ env = headers.merge(:params => params, :method => http_method.to_s.upcase)
28
34
  @rack_test_session.request(url, env)
29
35
  end
30
36
 
@@ -1,5 +1,5 @@
1
1
  require "webrat"
2
- gem "selenium-client", ">=1.2.14"
2
+ gem "selenium-client", ">=1.2.16"
3
3
  require "selenium/client"
4
4
  require "webrat/selenium/silence_stream"
5
5
  require "webrat/selenium/selenium_session"
@@ -34,7 +34,7 @@ module Webrat
34
34
 
35
35
  @remote_control = ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0",
36
36
  Webrat.configuration.selenium_server_port,
37
- Webrat.configuration.selenium_browser_startup_timeout)
37
+ :timeout => Webrat.configuration.selenium_browser_startup_timeout)
38
38
  @remote_control.jar_file = jar_path
39
39
 
40
40
  return @remote_control
@@ -74,7 +74,9 @@ module Webrat
74
74
 
75
75
  def stop
76
76
  silence_stream(STDOUT) do
77
- ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0", Webrat.configuration.selenium_server_port, 5).stop
77
+ ::Selenium::RemoteControl::RemoteControl.new("0.0.0.0",
78
+ Webrat.configuration.selenium_server_port,
79
+ :timeout => 5).stop
78
80
  end
79
81
  end
80
82
 
@@ -2,8 +2,74 @@ require "rubygems"
2
2
  require "sinatra/base"
3
3
 
4
4
  class RackApp < Sinatra::Default
5
+ template :layout do
6
+ <<TEMPLATE
7
+ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
8
+ <html>
9
+ <title>sinatra testing with webrat</title>
10
+ <body>
11
+ <%= yield %>
12
+ </body>
13
+ </html>
14
+ TEMPLATE
15
+ end
16
+
17
+ template :home do
18
+ <<TEMPLATE
19
+ <p> visit <a href="/go">there</a></p>
20
+
21
+ <form>
22
+ <label>
23
+ Prefilled
24
+ <input type="text" name="prefilled" value="text" />
25
+ </label>
26
+ </form>
27
+ TEMPLATE
28
+ end
29
+
30
+ template :go do
31
+ <<TEMPLATE
32
+ <form method="post" action="/go">
33
+ <div>
34
+ <label for="name">Name</label>
35
+ <input type="text" name="name" id="name">
36
+ </div>
37
+ <div>
38
+ <label for="email">Email</label>
39
+ <input type="text" name="email" id="email">
40
+ </div>
41
+ <input type="submit" value="Submit" />
42
+ </form>
43
+ TEMPLATE
44
+ end
45
+
46
+ template :hello do
47
+ <<TEMPLATE
48
+ <p>Hello, <%= @user %></p>
49
+ <p>Your email is: <%= @email %></p>
50
+ TEMPLATE
51
+ end
52
+
5
53
  get "/" do
6
- "Hello World"
54
+ erb :home
55
+ end
56
+
57
+ get "/go" do
58
+ erb :go
59
+ end
60
+
61
+ get "/internal_redirect" do
62
+ redirect "/"
63
+ end
64
+
65
+ get "/external_redirect" do
66
+ redirect "http://google.com"
67
+ end
68
+
69
+ post "/go" do
70
+ @user = params[:name]
71
+ @email = params[:email]
72
+ erb :hello
7
73
  end
8
74
 
9
75
  get "/redirect_absolute_url" do
@@ -14,6 +14,8 @@ class Test::Unit::TestCase
14
14
  include Webrat::Methods
15
15
  include Webrat::Matchers
16
16
 
17
+ Webrat::Methods.delegate_to_session :response_code, :response_body
18
+
17
19
  def app
18
20
  RackApp.new
19
21
  end
@@ -2,66 +2,40 @@ require File.dirname(__FILE__) + "/test_helper"
2
2
  require File.dirname(__FILE__) + "/../rack_app"
3
3
 
4
4
  class WebratRackTest < Test::Unit::TestCase
5
- def test_visit_returns_response
6
- response = visit "/"
7
- assert response.ok?
5
+ def test_visits_pages
6
+ visit "/"
7
+ assert response_body.include?("visit")
8
+
9
+ click_link "there"
10
+ assert response_body.include?('<form method="post" action="/go">')
8
11
  end
9
12
 
10
- def test_last_response_is_available
11
- visit "/"
12
- assert last_response.ok?
13
+ def test_submits_form
14
+ visit "/go"
15
+ fill_in "Name", :with => "World"
16
+ fill_in "Email", :with => "world@example.org"
17
+ click_button "Submit"
18
+ assert response_body.include?("Hello, World")
19
+ assert response_body.include?("Your email is: world@example.org")
13
20
  end
14
21
 
15
- def test_last_request_is_available
22
+ def test_check_value_of_field
16
23
  visit "/"
17
- assert_equal "/", last_request.env["PATH_INFO"]
24
+ assert field_labeled("Prefilled").value, "text"
18
25
  end
19
26
 
20
- # def test_redirects
21
- # visit "/redirect_absolute_url"
22
- # assert_equal "spam", response_body
23
- # end
24
-
25
- def test_assertions_after_visit
26
- visit "/"
27
- assert_contain "Hello World"
27
+ def test_follows_internal_redirects
28
+ visit "/internal_redirect"
29
+ assert response_body.include?("visit")
28
30
  end
29
31
 
30
- def test_assertions_after_visit
31
- get "/"
32
- assert_contain "Hello World"
32
+ def test_does_not_follow_external_redirects
33
+ visit "/external_redirect"
34
+ assert response_code == 302
33
35
  end
34
36
 
35
- # def test_visits_pages
36
- # visit "/"
37
- # assert response_body.include?("visit")
38
- #
39
- # click_link "there"
40
- # assert response_body.include?('<form method="post" action="/go">')
41
- # end
42
- #
43
- # def test_submits_form
44
- # visit "/go"
45
- # fill_in "Name", :with => "World"
46
- # fill_in "Email", :with => "world@example.org"
47
- # click_button "Submit"
48
- #
49
- # assert response_body.include?("Hello, World")
50
- # assert response_body.include?("Your email is: world@example.org")
51
- # end
52
- #
53
- # def test_check_value_of_field
54
- # visit "/"
55
- # assert field_labeled("Prefilled").value, "text"
56
- # end
57
- #
58
- # def test_follows_internal_redirects
59
- # visit "/internal_redirect"
60
- # assert response_body.include?("visit")
61
- # end
62
- #
63
- # def test_does_not_follow_external_redirects
64
- # visit "/external_redirect"
65
- # assert response_code == 302
66
- # end
37
+ def test_redirects
38
+ visit "/redirect_absolute_url"
39
+ assert_equal "spam", response_body
40
+ end
67
41
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metry
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathaniel Talbott
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-08 00:00:00 -04:00
12
+ date: 2009-08-09 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency