This series puts in place sample tests for others in the team to use as a base for their own tests ast they get familiar with the new testing libraries. Feel free to ask me for any details that are not clear from reading the examples. Note that rspec has a --format option with many built-in formatters. For instance, try: rspec --format nested
rspec -h will give you the full list.
This patch should have no functional changes, just removes a few things we don't need anymore, and does some minor changes to application_controller. --- src/app/controllers/application_controller.rb | 7 +- src/test/unit/vm_task_test.rb | 38 ------ src/vendor/plugins/render_component/README | 37 ----- src/vendor/plugins/render_component/Rakefile | 22 --- src/vendor/plugins/render_component/init.rb | 2 - .../plugins/render_component/lib/components.rb | 141 -------------------- .../plugins/render_component/test/abstract_unit.rb | 8 - .../render_component/test/components_test.rb | 136 ------------------- 8 files changed, 4 insertions(+), 387 deletions(-) delete mode 100644 src/test/unit/vm_task_test.rb delete mode 100644 src/vendor/plugins/render_component/README delete mode 100644 src/vendor/plugins/render_component/Rakefile delete mode 100644 src/vendor/plugins/render_component/init.rb delete mode 100644 src/vendor/plugins/render_component/lib/components.rb delete mode 100644 src/vendor/plugins/render_component/test/abstract_unit.rb delete mode 100644 src/vendor/plugins/render_component/test/components_test.rb
diff --git a/src/app/controllers/application_controller.rb b/src/app/controllers/application_controller.rb index bc560b9..60b2d82 100644 --- a/src/app/controllers/application_controller.rb +++ b/src/app/controllers/application_controller.rb @@ -43,7 +43,8 @@ class ApplicationController < ActionController::Base if(params[:component_layout]) return (ENV["RAILS_ENV"] != "production")?'components/' << params[:component_layout]:'dcloud' end - return 'dcloud' + @layout = 'dcloud' + return @layout end
def get_login_user @@ -106,7 +107,7 @@ class ApplicationController < ActionController::Base @ajax = params[:ajax] @nolayout = params[:nolayout] if @layout - render :layout => @layout + render :layout => 'dcloud' elsif @ajax render :template => 'layouts/popup-error', :layout => 'tabs-and-content' elsif @nolayout @@ -222,7 +223,7 @@ class ApplicationController < ActionController::Base end
def redirect_back_or_default(default) - redirect_to(session[:return_to] || default) + redirect_to(default || session[:return_to]) session[:return_to] = nil end end diff --git a/src/test/unit/vm_task_test.rb b/src/test/unit/vm_task_test.rb deleted file mode 100644 index 39be915..0000000 --- a/src/test/unit/vm_task_test.rb +++ /dev/null @@ -1,38 +0,0 @@ -# -# Copyright (C) 2009 Red Hat, Inc. -# Written by Jason Guiditta jguiditt@redhat.com -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. A copy of the GNU General Public License is -# also available at http://www.gnu.org/copyleft/gpl.html. - - -require File.dirname(__FILE__) + '/../test_helper' - -class VmTaskTest < ActiveSupport::TestCase - - fixtures :vms - - # Ensure action_privilege method returns nil if it is passed an action - # that does not exist. - def test_action_privilege_with_bad_action - assert_equal(nil, VmTask.action_privilege('stop_vm')) - end - - # Ensure action_privilege_object method returns nil if it is passed an action - # that does not exist. - def test_action_privilege_object_with_bad_action - assert_equal(nil, VmTask.action_privilege_object('stop_vm', vms(:production_httpd_vm).id)) - end -end diff --git a/src/vendor/plugins/render_component/README b/src/vendor/plugins/render_component/README deleted file mode 100644 index a6a318a..0000000 --- a/src/vendor/plugins/render_component/README +++ /dev/null @@ -1,37 +0,0 @@ -Components allow you to call other actions for their rendered response while executing another action. You can either delegate -the entire response rendering or you can mix a partial response in with your other content. - - class WeblogController < ActionController::Base - # Performs a method and then lets hello_world output its render - def delegate_action - do_other_stuff_before_hello_world - render_component :controller => "greeter", :action => "hello_world", :params => { :person => "david" } - end - end - - class GreeterController < ActionController::Base - def hello_world - render :text => "#{params[:person]} says, Hello World!" - end - end - -The same can be done in a view to do a partial rendering: - - Let's see a greeting: - <%= render_component :controller => "greeter", :action => "hello_world" %> - -It is also possible to specify the controller as a class constant, bypassing the inflector -code to compute the controller class at runtime: - -<%= render_component :controller => GreeterController, :action => "hello_world" %> - -== When to use components - -Components should be used with care. They're significantly slower than simply splitting reusable parts into partials and -conceptually more complicated. Don't use components as a way of separating concerns inside a single application. Instead, -reserve components to those rare cases where you truly have reusable view and controller elements that can be employed -across many applications at once. - -So to repeat: Components are a special-purpose approach that can often be replaced with better use of partials and filters. - -Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license \ No newline at end of file diff --git a/src/vendor/plugins/render_component/Rakefile b/src/vendor/plugins/render_component/Rakefile deleted file mode 100644 index d99407b..0000000 --- a/src/vendor/plugins/render_component/Rakefile +++ /dev/null @@ -1,22 +0,0 @@ -require 'rake' -require 'rake/testtask' -require 'rake/rdoctask' - -desc 'Default: run unit tests.' -task :default => :test - -desc 'Test the components plugin.' -Rake::TestTask.new(:test) do |t| - t.libs << 'lib' - t.pattern = 'test/**/*_test.rb' - t.verbose = true -end - -desc 'Generate documentation for the components plugin.' -Rake::RDocTask.new(:rdoc) do |rdoc| - rdoc.rdoc_dir = 'rdoc' - rdoc.title = 'Components' - rdoc.options << '--line-numbers' << '--inline-source' - rdoc.rdoc_files.include('README') - rdoc.rdoc_files.include('lib/**/*.rb') -end \ No newline at end of file diff --git a/src/vendor/plugins/render_component/init.rb b/src/vendor/plugins/render_component/init.rb deleted file mode 100644 index b428c52..0000000 --- a/src/vendor/plugins/render_component/init.rb +++ /dev/null @@ -1,2 +0,0 @@ -require 'components' -ActionController::Base.send :include, Components diff --git a/src/vendor/plugins/render_component/lib/components.rb b/src/vendor/plugins/render_component/lib/components.rb deleted file mode 100644 index 9263cde..0000000 --- a/src/vendor/plugins/render_component/lib/components.rb +++ /dev/null @@ -1,141 +0,0 @@ -module Components - def self.included(base) #:nodoc: - base.class_eval do - include InstanceMethods - extend ClassMethods - helper HelperMethods - - # If this controller was instantiated to process a component request, - # +parent_controller+ points to the instantiator of this controller. - attr_accessor :parent_controller - - alias_method_chain :process_cleanup, :render_component - alias_method_chain :session=, :render_component - alias_method_chain :flash, :render_component - alias_method_chain :perform_action, :render_component - alias_method_chain :send_response, :render_component - - alias_method :component_request?, :parent_controller - end - end - - module ClassMethods - # Track parent controller to identify component requests - def process_with_components(request, response, parent_controller = nil) #:nodoc: - controller = new - controller.parent_controller = parent_controller - controller.process(request, response) - end - end - - module HelperMethods - def render_component(options) - @controller.__send__(:render_component_as_string, options) - end - end - - module InstanceMethods - def perform_action_with_render_component - perform_action_without_render_component - remove_instance_variable(:@_flash) if defined? @_flash - end - - # Extracts the action_name from the request parameters and performs that action. - def process_with_components(request, response, method = :perform_action, *arguments) #:nodoc: - flash.discard if component_request? - process_without_components(request, response, method, *arguments) - end - - def send_response_with_render_component - response.prepare! unless component_request? - response - end - - protected - # Renders the component specified as the response for the current method - def render_component(options) #:doc: - component_logging(options) do - render_for_text(component_response(options, true).body, response.status) - end - end - - # Returns the component response as a string - def render_component_as_string(options) #:doc: - component_logging(options) do - response = component_response(options, false) - - if redirected = response.redirected_to - render_component_as_string(redirected) - else - response.body - end - end - end - - def flash_with_render_component(refresh = false) #:nodoc: - if !defined?(@_flash) || refresh - @_flash = - if defined?(@parent_controller) - @parent_controller.flash - else - flash_without_render_component - end - end - @_flash - end - - private - def component_response(options, reuse_response) - klass = component_class(options) - request = request_for_component(klass.controller_path, options) - new_response = reuse_response ? response : response.dup - - klass.process_with_components(request, new_response, self) - end - - # determine the controller class for the component request - def component_class(options) - if controller = options[:controller] - controller.is_a?(Class) ? controller : "#{controller.camelize}Controller".constantize - else - self.class - end - end - - # Create a new request object based on the current request. - # The new request inherits the session from the current request, - # bypassing any session options set for the component controller's class - def request_for_component(controller_path, options) - new_request = request.dup - new_request.session = request.session - - new_request.instance_variable_set( - :@parameters, - (options[:params] || {}).with_indifferent_access.update( - "controller" => controller_path, "action" => options[:action], "id" => options[:id] - ) - ) - - new_request - end - - def component_logging(options) - if logger - logger.info "Start rendering component (#{options.inspect}): " - result = yield - logger.info "\n\nEnd of component rendering" - result - else - yield - end - end - - def session_with_render_component=(options = {}) - session_without_render_component=(options) unless component_request? - end - - def process_cleanup_with_render_component - process_cleanup_without_render_component unless component_request? - end - end -end diff --git a/src/vendor/plugins/render_component/test/abstract_unit.rb b/src/vendor/plugins/render_component/test/abstract_unit.rb deleted file mode 100644 index f022971..0000000 --- a/src/vendor/plugins/render_component/test/abstract_unit.rb +++ /dev/null @@ -1,8 +0,0 @@ -require 'rubygems' -require 'test/unit' -require 'action_controller' -require 'action_controller/test_process' -ActionController::Routing::Routes.reload rescue nil - -$: << File.dirname(__FILE__) + "/../lib" -require File.dirname(__FILE__) + "/../init" diff --git a/src/vendor/plugins/render_component/test/components_test.rb b/src/vendor/plugins/render_component/test/components_test.rb deleted file mode 100644 index 53fcd7f..0000000 --- a/src/vendor/plugins/render_component/test/components_test.rb +++ /dev/null @@ -1,136 +0,0 @@ -require File.dirname(__FILE__) + '/abstract_unit' - -class CallerController < ActionController::Base - def calling_from_controller - render_component(:controller => "callee", :action => "being_called") - end - - def calling_from_controller_with_params - render_component(:controller => "callee", :action => "being_called", :params => { "name" => "David" }) - end - - def calling_from_controller_with_different_status_code - render_component(:controller => "callee", :action => "blowing_up") - end - - def calling_from_template - render :inline => "Ring, ring: <%= render_component(:controller => 'callee', :action => 'being_called') %>" - end - - def internal_caller - render :inline => "Are you there? <%= render_component(:action => 'internal_callee') %>" - end - - def internal_callee - render :text => "Yes, ma'am" - end - - def set_flash - render_component(:controller => "callee", :action => "set_flash") - end - - def use_flash - render_component(:controller => "callee", :action => "use_flash") - end - - def calling_redirected - render_component(:controller => "callee", :action => "redirected") - end - - def calling_redirected_as_string - render :inline => "<%= render_component(:controller => 'callee', :action => 'redirected') %>" - end - - def rescue_action(e) raise end -end - -class CalleeController < ActionController::Base - def being_called - render :text => "#{params[:name] || "Lady"} of the House, speaking" - end - - def blowing_up - render :text => "It's game over, man, just game over, man!", :status => 500 - end - - def set_flash - flash[:notice] = 'My stoney baby' - render :text => 'flash is set' - end - - def use_flash - render :text => flash[:notice] || 'no flash' - end - - def redirected - redirect_to :controller => "callee", :action => "being_called" - end - - def rescue_action(e) raise end -end - -class ComponentsTest < ActionController::TestCase - tests CallerController - - def test_calling_from_controller - get :calling_from_controller - assert_equal "Lady of the House, speaking", @response.body - end - - def test_calling_from_controller_with_params - get :calling_from_controller_with_params - assert_equal "David of the House, speaking", @response.body - end - - def test_calling_from_controller_with_different_status_code - get :calling_from_controller_with_different_status_code - assert_equal 500, @response.response_code - end - - def test_calling_from_template - get :calling_from_template - assert_equal "Ring, ring: Lady of the House, speaking", @response.body - end - - def test_etag_is_set_for_parent_template_when_calling_from_template - get :calling_from_template - expected_etag = etag_for("Ring, ring: Lady of the House, speaking") - assert_equal expected_etag, @response.headers['ETag'] - end - - def test_internal_calling - get :internal_caller - assert_equal "Are you there? Yes, ma'am", @response.body - end - - def test_flash - get :set_flash - assert_equal 'My stoney baby', flash[:notice] - get :use_flash - assert_equal 'My stoney baby', @response.body - get :use_flash - assert_equal 'no flash', @response.body - end - - def test_component_redirect_redirects - get :calling_redirected - - assert_redirected_to :controller=>"callee", :action => "being_called" - end - - def test_component_multiple_redirect_redirects - test_component_redirect_redirects - test_internal_calling - end - - def test_component_as_string_redirect_renders_redirected_action - get :calling_redirected_as_string - - assert_equal "Lady of the House, speaking", @response.body - end - - protected - def etag_for(text) - %("#{Digest::MD5.hexdigest(text)}") - end -end
This is just an initial partial, still needs styling. Previously, we were setting the flash[] messages, but not displaying them anywhere. --- src/app/views/layouts/_notification.rhtml | 31 +++++++++++++++++++++++ src/app/views/layouts/cloud/_notification.rhtml | 2 +- src/app/views/layouts/dcloud.rhtml | 2 +- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/app/views/layouts/_notification.rhtml
diff --git a/src/app/views/layouts/_notification.rhtml b/src/app/views/layouts/_notification.rhtml new file mode 100644 index 0000000..b969739 --- /dev/null +++ b/src/app/views/layouts/_notification.rhtml @@ -0,0 +1,31 @@ +<div id="notification" <%if flash[:error]%>class="error-align"<%end%>> + <%= link_to "", params, :id => "close-notify" %> + <% if flash[:error] %> + <% if !flash[:error][:successes].nil? && !flash[:error][:successes].empty? %> + <div class="success"> + <h4>The following items were successful:</h4> + <ul> + <% flash[:error][:successes].each {|item| %> + <li><%= item %></li> + <% } %> + </ul> + </div> + <% end %> + <% if !flash[:error][:failures].nil? && !flash[:error][:failures].empty? %> + <div class="warning"><h4><%= flash[:error][:summary]%></h4></div> + <div class="error"> + <ul> + <% flash[:error][:failures].each {|key, value| %> + <li><%= key %>: <%= value %></li> + <% } %> + </ul> + </div> + <% end %> + <% end %> + <% if flash[:warning] %> + <div class="warning"><h4><%= flash[:warning] %></h4></div> + <% end %> + <% if flash[:notice] %> + <div class="success"><ul><li><%= flash[:notice] %></li></ul></div> + <% end %> +</div> \ No newline at end of file diff --git a/src/app/views/layouts/cloud/_notification.rhtml b/src/app/views/layouts/cloud/_notification.rhtml index b969739..bd468a1 100644 --- a/src/app/views/layouts/cloud/_notification.rhtml +++ b/src/app/views/layouts/cloud/_notification.rhtml @@ -1,4 +1,4 @@ -<div id="notification" <%if flash[:error]%>class="error-align"<%end%>> +<div id="notification"> <%= link_to "", params, :id => "close-notify" %> <% if flash[:error] %> <% if !flash[:error][:successes].nil? && !flash[:error][:successes].empty? %> diff --git a/src/app/views/layouts/dcloud.rhtml b/src/app/views/layouts/dcloud.rhtml index 60e0ad8..0026a00 100644 --- a/src/app/views/layouts/dcloud.rhtml +++ b/src/app/views/layouts/dcloud.rhtml @@ -79,7 +79,7 @@ </div> <div id="main"> <div id="content_area"> - + <%= render :partial => '/layouts/notification' %> <%= yield %> <%# the rest of the center and right hand side %> </div> </div>
There are a few non-obvious changes to routes, and an extra testing library (factory_girl). As a result, we can now (but don't _have to_) use factories instead of yaml files for test data. The idea here is to make things more readable, as well as remove duplication, since one Factory can inherit from another. Each still gets it's own object-named file though, so the structure is similar to what we have done in the past. See http://github.com/thoughtbot/factory_girl for more details.
All existing TestUnit tests should still run (with rake test), and the new rspec tests can be run in a similar manner with: rake spec --- src/app/controllers/user_sessions_controller.rb | 6 +- src/app/views/user_sessions/login.html.erb | 18 -------- src/app/views/user_sessions/new.html.erb | 18 ++++++++ src/config/environments/cucumber.rb | 1 + src/config/environments/test.rb | 3 +- src/config/initializers/abstract_request.rb | 26 +++++++---- src/config/routes.rb | 25 +++-------- .../controllers/user_sessions_controller_spec.rb | 31 ++++++++++++++ src/spec/controllers/users_controller_spec.rb | 44 ++++++++++++++++++++ src/spec/factories/user.rb | 13 ++++++ src/spec/helpers/user_sessions_helper_spec.rb | 11 +++++ src/spec/helpers/users_helper_spec.rb | 11 +++++ src/spec/models/provider_spec.rb | 14 ++++++ src/spec/models/user_spec.rb | 13 ++++++ src/spec/spec_helper.rb | 7 +++ .../functional/user_sessions_controller_test.rb | 6 +- 16 files changed, 193 insertions(+), 54 deletions(-) delete mode 100644 src/app/views/user_sessions/login.html.erb create mode 100644 src/app/views/user_sessions/new.html.erb create mode 100644 src/spec/controllers/user_sessions_controller_spec.rb create mode 100644 src/spec/controllers/users_controller_spec.rb create mode 100644 src/spec/factories/user.rb create mode 100644 src/spec/helpers/user_sessions_helper_spec.rb create mode 100644 src/spec/helpers/users_helper_spec.rb create mode 100644 src/spec/models/provider_spec.rb create mode 100644 src/spec/models/user_spec.rb
diff --git a/src/app/controllers/user_sessions_controller.rb b/src/app/controllers/user_sessions_controller.rb index f48f8e0..d5dcfd2 100644 --- a/src/app/controllers/user_sessions_controller.rb +++ b/src/app/controllers/user_sessions_controller.rb @@ -23,7 +23,7 @@ class UserSessionsController < ApplicationController before_filter :require_no_user, :only => [:new, :create] before_filter :require_user, :only => :destroy
- def login + def new @user_session = UserSession.new end
@@ -33,11 +33,11 @@ class UserSessionsController < ApplicationController flash[:notice] = "Login successful!" redirect_back_or_default account_url else - render :action => :login + render :action => :new end end
- def logout + def destroy current_user_session.destroy flash[:notice] = "Logout successful!" redirect_back_or_default login_url diff --git a/src/app/views/user_sessions/login.html.erb b/src/app/views/user_sessions/login.html.erb deleted file mode 100644 index ee7da51..0000000 --- a/src/app/views/user_sessions/login.html.erb +++ /dev/null @@ -1,18 +0,0 @@ -<div class="dcloud_form"> - <h2>Login</h2> - - <% form_for @user_session, :url => user_session_path do |f| %> - <%= f.error_messages %> - <%= f.label :login %><br /> - <%= f.text_field :login %><br /> - <br /> - <%= f.label :password %><br /> - <%= f.password_field :password %><br /> - <br /> - <%= f.check_box :remember_me %><%= f.label :remember_me %><br /> - <br /> - <%= f.submit "Login" %> - <% end %> - <%= link_to 'Register', {:controller => 'users', :action => 'new'}, :class => 'actionlink' %> - -</div> diff --git a/src/app/views/user_sessions/new.html.erb b/src/app/views/user_sessions/new.html.erb new file mode 100644 index 0000000..ee7da51 --- /dev/null +++ b/src/app/views/user_sessions/new.html.erb @@ -0,0 +1,18 @@ +<div class="dcloud_form"> + <h2>Login</h2> + + <% form_for @user_session, :url => user_session_path do |f| %> + <%= f.error_messages %> + <%= f.label :login %><br /> + <%= f.text_field :login %><br /> + <br /> + <%= f.label :password %><br /> + <%= f.password_field :password %><br /> + <br /> + <%= f.check_box :remember_me %><%= f.label :remember_me %><br /> + <br /> + <%= f.submit "Login" %> + <% end %> + <%= link_to 'Register', {:controller => 'users', :action => 'new'}, :class => 'actionlink' %> + +</div> diff --git a/src/config/environments/cucumber.rb b/src/config/environments/cucumber.rb index 5edfa2b..efe0b40 100644 --- a/src/config/environments/cucumber.rb +++ b/src/config/environments/cucumber.rb @@ -26,3 +26,4 @@ config.gem 'database_cleaner', :lib => false, :version => '>=0.4.3' unless File. config.gem 'webrat', :lib => false, :version => '>=0.6.0' unless File.directory?(File.join(Rails.root, 'vendor/plugins/webrat')) config.gem 'rspec', :lib => false, :version => '>=1.3.0' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec')) config.gem 'rspec-rails', :lib => false, :version => '>=1.3.2' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails')) +config.gem "factory_girl", :lib => "factory_girl", :version => ">=1.2.3" diff --git a/src/config/environments/test.rb b/src/config/environments/test.rb index 2d0704e..188f711 100644 --- a/src/config/environments/test.rb +++ b/src/config/environments/test.rb @@ -37,4 +37,5 @@ config.action_controller.perform_caching = false # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test
- config.gem 'rspec-rails', :version => '>= 1.3.2', :lib => false unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails')) +config.gem 'rspec-rails', :version => '>= 1.3.2', :lib => false unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails')) +config.gem "factory_girl", :lib => "factory_girl", :version => ">=1.2.3" diff --git a/src/config/initializers/abstract_request.rb b/src/config/initializers/abstract_request.rb index 938106d..480241c 100644 --- a/src/config/initializers/abstract_request.rb +++ b/src/config/initializers/abstract_request.rb @@ -1,14 +1,20 @@ -#This is a (hopefully) temporary workaround to help -#mongrel, since it hooks into the now-gone AbstracRequest -#class. +# This is a (hopefully) temporary workaround to help +# mongrel, since it hooks into the now-gone AbstractRequest +# class. We should test if this issue occurs with thin +# webserver, perhaps we can use that instead of mongrel +# and drop this altogether. Set only to production, otherwise +# it kills our test suite.
-module ActionController - class AbstractRequest < ActionController::Request - def self.relative_url_root=(path) - ActionController::Base.relative_url_root=(path) - end - def self.relative_url_root - ActionController::Base.relative_url_root +config = Rails::Configuration.new +if config.environment == 'production' + module ActionController + class AbstractRequest < ActionController::Request + def self.relative_url_root=(path) + ActionController::Base.relative_url_root=(path) + end + def self.relative_url_root + ActionController::Base.relative_url_root + end end end end diff --git a/src/config/routes.rb b/src/config/routes.rb index 853ecec..d991be7 100644 --- a/src/config/routes.rb +++ b/src/config/routes.rb @@ -31,14 +31,16 @@ ActionController::Routing::Routes.draw do |map|
# You can have the root of your site routed by hooking up '' # -- just remember to delete public/index.html. - map.default '', :controller => 'provider' + map.connect '', :controller => 'provider'
+ map.login 'login', :controller => "user_sessions", :action => "new" + map.logout 'logout', :controller => "user_sessions", :action => "destroy" map.resource :user_session - map.root :controller => "user_sessions", :action => "login" - map.login 'login', :controller => "user_sessions", :action => "login" - map.logout 'logout', :controller => "user_sessions", :action => "logout" + map.register 'register', :controller => 'users', :action => 'new' map.resource :account, :controller => "users" map.resources :users + map.root :login + map.resources :provider
# Allow downloading Web Service WSDL as a file with an extension @@ -46,21 +48,6 @@ ActionController::Routing::Routes.draw do |map| map.connect ':controller/service.wsdl', :action => 'wsdl'
# Install the default route as the lowest priority. - map.connect 'graph/flexchart_data/:id/:target/:startTime/:endTime/:dataFunction', :controller => 'graph', :action => 'flexchart_data' - map.connect 'graph/host_chart_data/:id/:target/:startTime/:resolution/:dataFunction', :controller => 'graph', :action => 'host_chart_data' map.connect ':controller/:action/:id.:format' map.connect ':controller/:action/:id' - - # We put routes for the REST API _after_ the default routes so that we - # don't disturb existing routes for the Server - # FIXME: Eventually, we want to rename the controllers in a way that makes - # REST work out of the box, and use these as the default routes - map.resources :hosts, :controller => 'host' - map.resources :storage_pools, :controller => 'storage' - map.resources :storage_volumes, :controller => 'storage_volume' - map.resources :hardware_pools, :controller => 'hardware' do |hardware_pools| - hardware_pools.resources :hosts, :controller => 'host' - hardware_pools.resources :storage_pools, :controller => 'storage' - end - map.resources :vms, :controller => 'vm' end diff --git a/src/spec/controllers/user_sessions_controller_spec.rb b/src/spec/controllers/user_sessions_controller_spec.rb new file mode 100644 index 0000000..f2b80d5 --- /dev/null +++ b/src/spec/controllers/user_sessions_controller_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe UserSessionsController do + + before(:each) do + @tuser = Factory :tuser + activate_authlogic + end + + it "should call new method" do + route_for(:controller => 'user_sessions', :action => 'new').should == 'login' + get :new + @current_user.should == nil + UserSession.find.should == nil + response.should be_success + end + + it "should create user session" do + post :create, :user_session => { :login => "tuser", :password => "secret" } + UserSession.find.should_not == nil + @tuser.should == UserSession.find.user + response.should redirect_to(account_path) + end + + it "should destroy user session" do + post :create, :user_session => { :login => "tuser", :password => "secret" } + delete :destroy + UserSession.find.should == nil + response.should redirect_to(login_path) + end +end diff --git a/src/spec/controllers/users_controller_spec.rb b/src/spec/controllers/users_controller_spec.rb new file mode 100644 index 0000000..1c18ba7 --- /dev/null +++ b/src/spec/controllers/users_controller_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe UsersController do + + before(:each) do + @tuser = Factory :tuser + activate_authlogic + end + + it "should call new method" do + route_for(:controller => 'user_sessions', :action => 'new').should == 'login' + get :new + @current_user.should == nil + UserSession.find.should == nil + response.should be_success + end + + it "should create user" do + lambda { + post :create, :user => { :login => "tuser2", :email => "tuser2@example.com", + :password => "testpass", + :password_confirmation => "testpass" } + }.should change{ User.count } + response.should redirect_to(account_path) + end + + it "should show user" do + UserSession.create(@tuser) + get :show + response.should be_success + end + + it "should get edit" do + UserSession.create(@tuser) + get :edit, :id => @tuser.id + response.should be_success + end + + test "should update user" do + UserSession.create(@tuser) + put :update, :id => @tuser.id, :user => { } + response.should redirect_to(account_path) + end +end diff --git a/src/spec/factories/user.rb b/src/spec/factories/user.rb new file mode 100644 index 0000000..637600c --- /dev/null +++ b/src/spec/factories/user.rb @@ -0,0 +1,13 @@ +Factory.define :user do |u| + u.login 'myuser' + u.email 'myuser@example.com' + u.password 'secret' + u.password_confirmation 'secret' + #u.first_name 'John' + #u.last_name 'Smith' +end + +Factory.define :tuser, :parent => :user do |u| + u.login 'tuser' + u.email 'tuser@example.com' +end diff --git a/src/spec/helpers/user_sessions_helper_spec.rb b/src/spec/helpers/user_sessions_helper_spec.rb new file mode 100644 index 0000000..99cee55 --- /dev/null +++ b/src/spec/helpers/user_sessions_helper_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe UserSessionsHelper do + + #Delete this example and add some real ones or delete this file + it "should be included in the object returned by #helper" do + included_modules = (class << helper; self; end).send :included_modules + included_modules.should include(UserSessionsHelper) + end + +end diff --git a/src/spec/helpers/users_helper_spec.rb b/src/spec/helpers/users_helper_spec.rb new file mode 100644 index 0000000..8dae79b --- /dev/null +++ b/src/spec/helpers/users_helper_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe UsersHelper do + + #Delete this example and add some real ones or delete this file + it "should be included in the object returned by #helper" do + included_modules = (class << helper; self; end).send :included_modules + included_modules.should include(UsersHelper) + end + +end diff --git a/src/spec/models/provider_spec.rb b/src/spec/models/provider_spec.rb new file mode 100644 index 0000000..b95e5f2 --- /dev/null +++ b/src/spec/models/provider_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe Provider do + before(:each) do + @valid_attributes = { + + } + end + + it "should create a new instance given valid attributes" do + # pending + # Provider.create!(@valid_attributes) + end +end diff --git a/src/spec/models/user_spec.rb b/src/spec/models/user_spec.rb new file mode 100644 index 0000000..388b116 --- /dev/null +++ b/src/spec/models/user_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe User do + before(:each) do + @valid_attributes = { + + } + end + + it "should create a new user 'tuser'" do + Factory.create(:tuser) + end +end diff --git a/src/spec/spec_helper.rb b/src/spec/spec_helper.rb index 1f72de0..5181389 100644 --- a/src/spec/spec_helper.rb +++ b/src/spec/spec_helper.rb @@ -4,6 +4,7 @@ ENV["RAILS_ENV"] ||= 'test' require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment')) require 'spec/autorun' require 'spec/rails' +require 'authlogic/test_case'
# Uncomment the next line to use webrat's matchers #require 'webrat/integrations/rspec-rails' @@ -51,4 +52,10 @@ Spec::Runner.configure do |config| # == Notes # # For more information take a look at Spec::Runner::Configuration and Spec::Runner + config.before(:each, :type => :controller) do + #activate_authlogic + end + config.after(:each, :type => :controller) do + #current_user_session.destroy + end end diff --git a/src/test/functional/user_sessions_controller_test.rb b/src/test/functional/user_sessions_controller_test.rb index cac84a9..fae1757 100644 --- a/src/test/functional/user_sessions_controller_test.rb +++ b/src/test/functional/user_sessions_controller_test.rb @@ -3,7 +3,7 @@ require 'test_helper' class UserSessionsControllerTest < ActionController::TestCase fixtures :users test "should get new" do - get :login + get :new assert_response :success end
@@ -15,8 +15,8 @@ class UserSessionsControllerTest < ActionController::TestCase end
test "should destroy user session" do - post :create, :user_session => { :login => "tuser", :password => "testpass" } - delete :logout + post :create, :user_session => { :login => "tomuser", :password => "testpass" } + delete :destroy assert_nil UserSession.find assert_redirected_to login_path end
This covers just auth-related app-level features, atm. I have it set up now, so when anyone else writes a new feature or scenario that requires login, they can reuse the bits in here (as in, reference them not duplicate). There may be some tweaking needed for that as we go forward, but this should be a good starting point. Eventually we will probably use cucmber features in place of most or all of the rspec controller tests, as that is a current area of duplication.
Tests can be run from the src directory with either: cucumber or rake cucumber --- src/features/authentication.feature | 51 +++++++++++++++++++++++ src/features/step_definitions/authentication.rb | 37 ++++++++++++++++ src/features/support/paths.rb | 18 ++++++++ 3 files changed, 106 insertions(+), 0 deletions(-) create mode 100644 src/features/authentication.feature create mode 100644 src/features/step_definitions/authentication.rb
diff --git a/src/features/authentication.feature b/src/features/authentication.feature new file mode 100644 index 0000000..2ee925c --- /dev/null +++ b/src/features/authentication.feature @@ -0,0 +1,51 @@ +Feature: User authentication + In order to access the site + As a user + I must register and log in + + Scenario: Register as new user + Given I am on the homepage + When I follow "Register" + Then I should be on the new account page + When I fill in the following: + | login | testuser | + | email | testuser@example.com | + | password | secret | + | password confirmation | secret | + And I press "Register" + Then I should be on the account page + And I should see "User registered!" + + Scenario: Log in as registered user + Given I am a registered user + And I am on the login page + When I login + Then I should see "Login successful!" + And I should be on the account page + + Scenario: Log in without password + Given I am a registered user + And I am on the login page + When I forget to enter my password + Then I should see "Password cannot be blank" + And I should be on the login error page + + Scenario: Edit profile + Given I am logged in + And I am on the homepage + When I want to edit my profile + And I follow "Edit" + Then I should see "Edit My Profile" + When I fill in "email" with "changed@example.com" + And I press "Update" + Then I should be on the account page + And I should see "User updated!" + + Scenario: log out + Given I am logged in + And I am on the homepage + When I follow "Log out" + Then I should be logged out + And I should see "Logout successful!" + And I should see "Register" + And I should see "Login" diff --git a/src/features/step_definitions/authentication.rb b/src/features/step_definitions/authentication.rb new file mode 100644 index 0000000..6f45e90 --- /dev/null +++ b/src/features/step_definitions/authentication.rb @@ -0,0 +1,37 @@ +def user + @user ||= Factory :user +end + +def login(login, password) + user + visit path_to("the login page") + fill_in "Login", :with => login + fill_in "Password", :with => password + click_button "Login" +end + +Given /^I am a registered user$/ do + user +end + +When /^I login$/ do + login(user.login, user.password) +end + +Given /^I am logged in$/ do + login(user.login, user.password) + UserSession.find.should_not == nil +end + +When /^I forget to enter my password$/ do + login(user.login, nil) +end + +When /^I want to edit my profile$/ do + click_link "Hi, #{user.login}" + response.should contain("User Profile for #{user.login}") +end + +Then /^I should be logged out$/ do + UserSession.find.should == nil +end diff --git a/src/features/support/paths.rb b/src/features/support/paths.rb index e79cd9d..87497ab 100644 --- a/src/features/support/paths.rb +++ b/src/features/support/paths.rb @@ -11,6 +11,24 @@ module NavigationHelpers when /the home\s?page/ '/'
+ when /the new account page/ + register_path + + when /the provider list page/ + '/' + + when /the login page/ + login_path + + when /the account page/ + account_path + + when /the login error page/ + user_session_path + + when /the new provider page/ + new_provider_path + # Add more mappings here. # Here is an example that pulls values out of the Regexp: #
On Mon, Mar 01, 2010 at 05:35:26PM -0500, Jason Guiditta wrote:
This series puts in place sample tests for others in the team to use as a base for their own tests ast they get familiar with the new testing libraries. Feel free to ask me for any details that are not clear from reading the examples. Note that rspec has a --format option with many built-in formatters. For instance, try: rspec --format nested
rspec -h will give you the full list.
deltacloud-devel mailing list deltacloud-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/deltacloud-devel
ACKity ACK! (pending whitespace cleanup)
Works for me. As a bonus, it's a good starting point for learning cucumber.
Thanks, Steve
On Tue, Mar 2, 2010 at 3:02 PM, Steve Linabery slinaber@redhat.com wrote:
On Mon, Mar 01, 2010 at 05:35:26PM -0500, Jason Guiditta wrote:
This series puts in place sample tests for others in the team to use as a base for their own tests ast they get familiar with the new testing libraries. Feel free to ask me for any details that are not clear from reading the examples. Note that rspec has a --format option with many built-in formatters. For instance, try: rspec --format nested
rspec -h will give you the full list.
deltacloud-devel mailing list deltacloud-devel@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/deltacloud-devel
ACKity ACK! (pending whitespace cleanup)
Works for me. As a bonus, it's a good starting point for learning cucumber.
Thanks, Steve
Thanks for reviewing that Steve, pushed.
deltacloud-devel@lists.fedorahosted.org