The projects controller gets more RESTy. It now supports XML, RSS, ATOM, HTML and plain text views of the projects list.

Changes include:

 * Add assert_xml_select method for testing RSS and ATOM results (Thanks, Jamis! http://weblog.jamisbuck.org/2007/1/4/assert_xml_select)
 * Add resource_feeder plugin for generating RSS and ATOM feeds
 * Update the URL on the Feeds page to use /projects.rss or /projects.txt instead of FeedController link
 * Add created_at and updated_at timestamps to project table to support ATOM feeds
 * Added new filter to login_system "login_or_feed_token_required" to allow RSS, ATOM or text requests with token-based authentication 
 
Notes:
 * This will break previous project listing feed subscriptions.
 * RSS, ATOM & text feeds are available via session or HTTP_BASIC authentication, or by passing the user's token on the url; HTML and XML results are only available via session or HTTP_BASIC authentication
 


git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@415 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
lukemelia 2007-02-01 05:32:05 +00:00
parent fda7788237
commit d9d5ff4d06
35 changed files with 735 additions and 94 deletions

View file

@ -1,4 +1,11 @@
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
<%
def today
Time.now.utc.to_s(:db)
end
%>
timemachine:
id: 1
@ -7,6 +14,8 @@ timemachine:
position: 1
state: 'active'
user_id: 1
created_at: <%= today %>
updated_at: <%= today %>
moremoney:
id: 2
@ -15,6 +24,8 @@ moremoney:
position: 2
state: 'active'
user_id: 1
created_at: <%= today %>
updated_at: <%= today %>
gardenclean:
id: 3
@ -23,3 +34,5 @@ gardenclean:
position: 3
state: 'active'
user_id: 1
created_at: <%= today %>
updated_at: <%= today %>

View file

@ -0,0 +1,30 @@
require File.dirname(__FILE__) + '/../test_helper'
require 'feedlist_controller'
# Re-raise errors caught by the controller.
class FeedlistController; def rescue_action(e) raise e end; end
class FeedlistControllerTest < Test::Unit::TestCase
fixtures :users, :preferences, :projects, :contexts, :todos, :notes
def setup
assert_equal "test", ENV['RAILS_ENV']
assert_equal "change-me", Tracks::Config.salt
@controller = FeedlistController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end
def test_get_index_when_not_logged_in
get :index
assert_redirected_to :controller => 'login', :action => 'login'
end
def test_get_index_by_logged_in_user
@request.session['user_id'] = users(:other_user).id
get :index
assert_response :success
assert_equal "TRACKS::Feeds", assigns['page_title']
end
end

View file

@ -6,7 +6,7 @@ require 'projects_controller'
class ProjectsController; def rescue_action(e) raise e end; end
class ProjectsControllerTest < TodoContainerControllerTestBase
fixtures :users, :todos, :preferences, :projects
fixtures :users, :todos, :preferences, :projects, :contexts
def setup
perform_setup(Project, ProjectsController)
@ -78,5 +78,106 @@ class ProjectsControllerTest < TodoContainerControllerTestBase
assert p.reload().active?
end
def test_rss_feed_content
@request.session['user_id'] = users(:admin_user).id
get :index, { :format => "rss" }
assert_equal 'application/rss+xml; charset=utf-8', @response.headers["Content-Type"]
#puts @response.body
assert_xml_select 'rss[version="2.0"]' do
assert_xml_select 'channel' do
assert_xml_select '>title', 'Tracks Projects'
assert_xml_select '>description', "Lists all the projects for #{users(:admin_user).display_name}."
assert_xml_select 'language', 'en-us'
assert_xml_select 'ttl', '40'
end
assert_xml_select 'item', 3 do
assert_xml_select 'title', /.+/
assert_xml_select 'description', /&lt;p&gt;\d+ actions. Project is (active|hidden|completed). &lt;\/p&gt;/
%w(guid link).each do |node|
assert_xml_select node, /http:\/\/test.host\/projects\/.+/
end
assert_xml_select 'pubDate', projects(:timemachine).created_at.to_s(:rfc822)
end
end
end
def test_rss_feed_not_accessible_to_anonymous_user_without_token
@request.session['user_id'] = nil
get :index, { :format => "rss" }
assert_response 401
end
def test_rss_feed_not_accessible_to_anonymous_user_with_invalid_token
@request.session['user_id'] = nil
get :index, { :format => "rss", :token => 'foo' }
assert_response 401
end
def test_rss_feed_accessible_to_anonymous_user_with_valid_token
@request.session['user_id'] = nil
get :index, { :format => "rss", :token => users(:admin_user).word }
assert_response :ok
end
def test_atom_feed_content
@request.session['user_id'] = users(:admin_user).id
get :index, { :format => "atom" }
assert_equal 'application/atom+xml; charset=utf-8', @response.headers["Content-Type"]
#puts @response.body
assert_xml_select 'feed[xmlns="http://www.w3.org/2005/Atom"]' do
assert_xml_select '>title', 'Tracks Projects'
assert_xml_select '>subtitle', "Lists all the projects for #{users(:admin_user).display_name}."
assert_xml_select 'entry', 3 do
assert_xml_select 'title', /.+/
assert_xml_select 'content[type="html"]', /&lt;p&gt;\d+ actions. Project is (active|hidden|completed). &lt;\/p&gt;/
assert_xml_select 'published', projects(:timemachine).created_at.to_s(:rfc822)
end
end
end
def test_atom_feed_not_accessible_to_anonymous_user_without_token
@request.session['user_id'] = nil
get :index, { :format => "atom" }
assert_response 401
end
def test_atom_feed_not_accessible_to_anonymous_user_with_invalid_token
@request.session['user_id'] = nil
get :index, { :format => "atom", :token => 'foo' }
assert_response 401
end
def test_atom_feed_accessible_to_anonymous_user_with_valid_token
@request.session['user_id'] = nil
get :index, { :format => "atom", :token => users(:admin_user).word }
assert_response :ok
end
def test_text_feed_content
@request.session['user_id'] = users(:admin_user).id
get :index, { :format => "txt" }
assert_equal 'text/plain; charset=utf-8', @response.headers["Content-Type"]
#puts @response.body
end
def test_text_feed_not_accessible_to_anonymous_user_without_token
@request.session['user_id'] = nil
get :index, { :format => "txt" }
assert_response 401
end
def test_text_feed_not_accessible_to_anonymous_user_with_invalid_token
@request.session['user_id'] = nil
get :index, { :format => "txt", :token => 'foo' }
assert_response 401
end
def test_text_feed_accessible_to_anonymous_user_with_valid_token
@request.session['user_id'] = nil
get :index, { :format => "txt", :token => users(:admin_user).word }
assert_response :ok
end
end

View file

@ -80,17 +80,17 @@ class FeedSmokeTest < ActionController::IntegrationTest
end
def test_all_projects_rss
assert_success "/projects/feed/rss/admin/#{ users(:admin_user).word }"
assert_success "/projects.rss?token=#{ users(:admin_user).word }"
end
def test_all_projects_txt
assert_success "/projects/feed/text/admin/#{ users(:admin_user).word }"
assert_success "/projects.txt?token=#{ users(:admin_user).word }"
end
def test_all_projects_txt_with_hidden_project
p = projects(:timemachine)
p.hide!
assert_success "/projects/feed/text/admin/#{ users(:admin_user).word }"
assert_success "/projects.txt?token=#{ users(:admin_user).word }"
end
private

View file

@ -4,7 +4,7 @@ require 'projects_controller'
# Re-raise errors caught by the controller.
class ProjectsController; def rescue_action(e) raise e end; end
class ProjectsControllerXmlApiTest < ActionController::IntegrationTest
class ProjectXmlApiTest < ActionController::IntegrationTest
fixtures :users, :projects
@@project_name = "My New Project"
@ -51,7 +51,15 @@ class ProjectsControllerXmlApiTest < ActionController::IntegrationTest
def test_creates_new_project
initial_count = Project.count
authenticated_post_xml_to_project_create
assert_response_and_body_matches 200, %r|^<\?xml version="1\.0" encoding="UTF-8"\?>\n<project>\n <description></description>\n <id type=\"integer\">[0-9]+</id>\n <name>#{@@project_name}</name>\n <position type=\"integer\">1</position>\n <state>active</state>\n</project>$|
assert_response :success
assert_xml_select 'project' do
assert_xml_select "description"
assert_xml_select 'id[type="integer"]', /[0-9]+/
assert_xml_select 'name', @@project_name
assert_xml_select 'position[type="integer"]', 1
assert_xml_select 'state', 'active'
end
#assert_response_and_body_matches 200, %r|^<\?xml version="1\.0" encoding="UTF-8"\?>\n<project>\n <description></description>\n <id type=\"integer\">[0-9]+</id>\n <name>#{@@project_name}</name>\n <position type=\"integer\">1</position>\n <state>active</state>\n</project>$|
assert_equal initial_count + 1, Project.count
project1 = Project.find_by_name(@@project_name)
assert_not_nil project1, "expected project '#{@@project_name}' to be created"

View file

@ -76,7 +76,6 @@ class UsersXmlApiTest < ActionController::IntegrationTest
def test_get_users_as_xml
get '/users.xml', {}, basic_auth_headers()
#puts @response.body
assert_response :success
assert_tag :tag => "users",
:children => { :count => 3, :only => { :tag => "user" } }
@ -85,7 +84,6 @@ class UsersXmlApiTest < ActionController::IntegrationTest
def test_get_user_as_xml
get "/users/#{users(:other_user).login}.xml", {}, basic_auth_headers()
puts @response.body
assert_response :success
assert_tag :tag => "user"
assert_no_tag :tag => "password"

View file

@ -30,6 +30,16 @@ class Test::Unit::TestCase
end
return string
end
def xml_document
@xml_document ||= HTML::Document.new(@response.body, false, true)
end
def assert_xml_select(*args)
@html_document = xml_document
assert_select(*args)
end
end
class ActionController::IntegrationTest

View file

@ -143,4 +143,8 @@ class ProjectTest < Test::Unit::TestCase
assert_equal 'Build_a_working_time_machine', @timemachine.to_param
end
def test_title_reader_returns_name
assert_equal @timemachine.name, @timemachine.title
end
end