From 2796e3a4ebeed89697440f88df66038d580f6185 Mon Sep 17 00:00:00 2001 From: lukemelia Date: Mon, 19 Jun 2006 06:36:00 +0000 Subject: [PATCH] Refactor the Ajax for project creation to use RJS. Introduce the ARTS plugin to test RJS. Move the New Project form to the right-hand side a la the new item form. (I much prefer this -- other input?) Introduce new validation in project model that fixes #306. git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@265 a4c988fc-2ded-0310-b66e-134b36920a42 --- tracks/app/controllers/project_controller.rb | 14 +- tracks/app/helpers/project_helper.rb | 10 + tracks/app/models/project.rb | 3 +- tracks/app/views/project/_project_form.rhtml | 1 - tracks/app/views/project/list.rhtml | 37 +- tracks/app/views/project/new_project.rjs | 11 + .../functional/project_controller_test.rb | 28 +- tracks/test/unit/project_test.rb | 11 +- tracks/vendor/plugins/arts/README | 22 ++ tracks/vendor/plugins/arts/init.rb | 2 + tracks/vendor/plugins/arts/install.rb | 1 + tracks/vendor/plugins/arts/lib/arts.rb | 110 ++++++ tracks/vendor/plugins/arts/meta.yml | 7 + tracks/vendor/plugins/arts/test/arts_test.rb | 361 ++++++++++++++++++ 14 files changed, 571 insertions(+), 47 deletions(-) create mode 100644 tracks/app/views/project/new_project.rjs create mode 100644 tracks/vendor/plugins/arts/README create mode 100644 tracks/vendor/plugins/arts/init.rb create mode 100644 tracks/vendor/plugins/arts/install.rb create mode 100644 tracks/vendor/plugins/arts/lib/arts.rb create mode 100644 tracks/vendor/plugins/arts/meta.yml create mode 100644 tracks/vendor/plugins/arts/test/arts_test.rb diff --git a/tracks/app/controllers/project_controller.rb b/tracks/app/controllers/project_controller.rb index f98f0f29..c554cd4c 100644 --- a/tracks/app/controllers/project_controller.rb +++ b/tracks/app/controllers/project_controller.rb @@ -58,16 +58,10 @@ class ProjectController < ApplicationController end def new_project - project = @user.projects.build - project.attributes = params['project'] - project.name = deurlize(project.name) - - if project.save - render :partial => 'project_listing', :locals => { :project_listing => project } - else - flash["warning"] = "Couldn't update new project" - render :text => "" - end + @project = @user.projects.build + @project.attributes = params['project'] + @project.name = deurlize(@project.name) + @saved = @project.save end # Called by a form button diff --git a/tracks/app/helpers/project_helper.rb b/tracks/app/helpers/project_helper.rb index 12c6d3c7..336f7a32 100644 --- a/tracks/app/helpers/project_helper.rb +++ b/tracks/app/helpers/project_helper.rb @@ -1,2 +1,12 @@ module ProjectHelper + +def get_listing_sortable_options + { + :tag => 'div', + :handle => 'handle', + :complete => visual_effect(:highlight, 'list-projects'), + :url => {:controller => 'project', :action => 'order'} + } +end + end diff --git a/tracks/app/models/project.rb b/tracks/app/models/project.rb index 2cbaa720..f6c78210 100644 --- a/tracks/app/models/project.rb +++ b/tracks/app/models/project.rb @@ -12,7 +12,8 @@ class Project < ActiveRecord::Base validates_presence_of :name, :message => "project must have a name" validates_length_of :name, :maximum => 255, :message => "project name must be less than 256 characters" validates_uniqueness_of :name, :message => "already exists", :scope =>"user_id" - + validates_format_of :name, :with => /^[^\/]*$/i, :message => "cannot contain the slash ('/') character" + def self.list_of(isdone=0) find(:all, :conditions => [ "done = ?" , true ], :order => "position ASC") end diff --git a/tracks/app/views/project/_project_form.rhtml b/tracks/app/views/project/_project_form.rhtml index 421a7b16..64ec4eca 100644 --- a/tracks/app/views/project/_project_form.rhtml +++ b/tracks/app/views/project/_project_form.rhtml @@ -1,7 +1,6 @@ <% @project = project_form %> -<%= error_messages_for 'project' %> <%= text_field 'project', 'name', :class => 'project-name' %> diff --git a/tracks/app/views/project/list.rhtml b/tracks/app/views/project/list.rhtml index 16d25ccc..1649779b 100644 --- a/tracks/app/views/project/list.rhtml +++ b/tracks/app/views/project/list.rhtml @@ -1,9 +1,6 @@ -
- - <% for name in ["notice", "warning", "message"] %> - <% if flash[name] %> - <%= "
#{flash[name]}
" %> - <% end %> +
+ <% for name in ["notice", "warning", "message"] %> +
><%= flash[name] %>
<% end %>
@@ -11,22 +8,14 @@ <%= render_partial( 'project_listing', project ) %> <% end %>
-<% sortable_options = { - :tag => 'div', - :handle => 'handle', - :complete => visual_effect(:highlight, 'list-projects'), - :url => {:controller => 'project', :action => 'order'} - }%> -<%= sortable_element 'list-projects', sortable_options %> -
-Create new project » +<%= sortable_element 'list-projects', get_listing_sortable_options %> +
+ +
+Create new project » - -<% if flash["confirmation"] %> -
<%= flash["confirmation"] %>
-<% end %> -<% if flash["warning"] %> -
<%= flash["warning"] %>
-<% end %> - -
\ No newline at end of file +
diff --git a/tracks/app/views/project/new_project.rjs b/tracks/app/views/project/new_project.rjs new file mode 100644 index 00000000..5012d000 --- /dev/null +++ b/tracks/app/views/project/new_project.rjs @@ -0,0 +1,11 @@ +if @saved + page.hide "warning" + page.insert_html :bottom, "list-projects", :partial => 'project_listing', :locals => { :project_listing => @project } + page.sortable "list-projects", get_listing_sortable_options + page.call "Form.reset", "project-form" + page.call "Form.focusFirstElement", "project-form" +else + page.hide "warning" + page.replace_html "warning", content_tag("div", content_tag("h2", "#{pluralize(@project.errors.count, "error")} prohibited this record from being saved") + content_tag("p", "There were problems with the following fields:") + content_tag("ul", @project.errors.each_full { |msg| content_tag("li", msg) }), "id" => "ErrorExplanation", "class" => "ErrorExplanation") + page.visual_effect :appear, 'warning', :duration => 0.5 +end \ No newline at end of file diff --git a/tracks/test/functional/project_controller_test.rb b/tracks/test/functional/project_controller_test.rb index b1eec90e..a4a4a7e8 100644 --- a/tracks/test/functional/project_controller_test.rb +++ b/tracks/test/functional/project_controller_test.rb @@ -5,13 +5,33 @@ require 'project_controller' class ProjectController; def rescue_action(e) raise e end; end class ProjectControllerTest < Test::Unit::TestCase + fixtures :users, :projects + def setup @controller = ProjectController.new - request, response = ActionController::TestRequest.new, ActionController::TestResponse.new + @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new end - # Replace this with your real tests. - def test_truth - assert true + def test_create_project + num_projects = Project.count + @request.session['user_id'] = users(:other_user).id + xhr :post, :new_project, :project => {:name => 'My New Project'} + assert_rjs :hide, "warning" + assert_rjs :insert_html, :bottom, "list-projects" + assert_rjs :sortable, 'list-projects', { :tag => 'div', :handle => 'handle', :complete => visual_effect(:highlight, 'list-projects'), :url => {:controller => 'project', :action => 'order'} } + # not yet sure how to write the following properly... + assert_rjs :call, "Form.reset", "project-form" + assert_rjs :call, "Form.focusFirstElement", "project-form" + assert_equal num_projects + 1, Project.count + end + + def test_create_with_slash_in_name_fails + num_projects = Project.count + @request.session['user_id'] = users(:other_user).id + xhr :post, :new_project, :project => {:name => 'foo/bar'} + assert_rjs :hide, "warning" + assert_rjs :replace_html, 'warning', "

1 error prohibited this record from being saved

There were problems with the following fields:

" + assert_rjs :visual_effect, :appear, "warning", :duration => '0.5' + assert_equal num_projects, Project.count end end diff --git a/tracks/test/unit/project_test.rb b/tracks/test/unit/project_test.rb index c669f549..aae30025 100644 --- a/tracks/test/unit/project_test.rb +++ b/tracks/test/unit/project_test.rb @@ -9,7 +9,6 @@ class ProjectTest < Test::Unit::TestCase end def test_validate_presence_of_name - assert_equal "Build a working time machine", @timemachine.name @timemachine.name = "" assert !@timemachine.save assert_equal 1, @timemachine.errors.count @@ -17,7 +16,6 @@ class ProjectTest < Test::Unit::TestCase end def test_validate_name_is_less_than_256 - assert_equal "Build a working time machine", @timemachine.name @timemachine.name = "a"*256 assert !@timemachine.save assert_equal 1, @timemachine.errors.count @@ -25,7 +23,6 @@ class ProjectTest < Test::Unit::TestCase end def test_validate_name_is_unique - assert_equal "Build a working time machine", @timemachine.name newproj = Project.new newproj.name = "Build a working time machine" assert !newproj.save @@ -33,4 +30,12 @@ class ProjectTest < Test::Unit::TestCase assert_equal "already exists", newproj.errors.on(:name) end + def test_validate_name_does_not_contain_slash + newproj = Project.new + newproj.name = "Save Earth/Mankind from Evil" + assert !newproj.save + assert_equal 1, newproj.errors.count + assert_equal "cannot contain the slash ('/') character", newproj.errors.on(:name) + end + end diff --git a/tracks/vendor/plugins/arts/README b/tracks/vendor/plugins/arts/README new file mode 100644 index 00000000..98c8786e --- /dev/null +++ b/tracks/vendor/plugins/arts/README @@ -0,0 +1,22 @@ +ARTS is Another RJS Test System + +For a complete tutorial, see http://glu.ttono.us/articles/2006/05/29/guide-test-driven-rjs-with-arts. + +Usage: + assert_rjs :alert, 'Hi!' + assert_rjs :assign, 'a', '2' + assert_rjs :call, 'foo', 'bar', 'baz' + assert_rjs :draggable, 'draggable_item' + assert_rjs :drop_receiving, 'receiving_item' + assert_rjs :hide, "post_1", "post_2", "post_3" + assert_rjs :insert_html, :bottom, 'posts' + assert_rjs :redirect_to, :action => 'list' + assert_rjs :remove, "post_1", "post_2", "post_3" + assert_rjs :replace, 'completely_replaced_div' + assert_rjs :replace, 'completely_replaced_div', '

This replaced the div

' + assert_rjs :replace, 'completely_replaced_div', /replaced the div/ + assert_rjs :replace_html, 'replaceable_div', "This goes inside the div" + assert_rjs :show, "post_1", "post_2", "post_3" + assert_rjs :sortable, 'sortable_item' + assert_rjs :toggle, "post_1", "post_2", "post_3" + assert_rjs :visual_effect, :highlight, "posts", :duration => '1.0' diff --git a/tracks/vendor/plugins/arts/init.rb b/tracks/vendor/plugins/arts/init.rb new file mode 100644 index 00000000..8993ba72 --- /dev/null +++ b/tracks/vendor/plugins/arts/init.rb @@ -0,0 +1,2 @@ +# Give testing some culture +Test::Unit::TestCase.send :include, Arts \ No newline at end of file diff --git a/tracks/vendor/plugins/arts/install.rb b/tracks/vendor/plugins/arts/install.rb new file mode 100644 index 00000000..a63be40f --- /dev/null +++ b/tracks/vendor/plugins/arts/install.rb @@ -0,0 +1 @@ +puts IO.read(File.join(File.dirname(__FILE__), 'README')) \ No newline at end of file diff --git a/tracks/vendor/plugins/arts/lib/arts.rb b/tracks/vendor/plugins/arts/lib/arts.rb new file mode 100644 index 00000000..ce02d986 --- /dev/null +++ b/tracks/vendor/plugins/arts/lib/arts.rb @@ -0,0 +1,110 @@ +module Arts + include ActionView::Helpers::PrototypeHelper + include ActionView::Helpers::ScriptaculousHelper + include ActionView::Helpers::JavaScriptHelper + + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + + def assert_rjs(action, *args, &block) + respond_to?("assert_rjs_#{action}") ? + send("assert_rjs_#{action}", *args) : + assert(lined_response.include?(create_generator.send(action, *args, &block)), + generic_error(action, args)) + end + + def assert_no_rjs(action, *args, &block) + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs(action, *args, &block) } + end + + def assert_rjs_insert_html(*args) + position = args.shift + item_id = args.shift + + content = extract_matchable_content(args) + + unless content.blank? + case content + when Regexp + assert_match Regexp.new("new Insertion\.#{position.to_s.camelize}(.*#{item_id}.*,.*#{content.source}.*);"), + @response.body + when String + assert lined_response.include?("new Insertion.#{position.to_s.camelize}(\"#{item_id}\", #{content});"), + "No insert_html call found for \n" + + " position: '#{position}' id: '#{item_id}' \ncontent: \n" + + "#{content}\n" + + "in response:\n#{lined_response}" + else + raise "Invalid content type" + end + else + assert_match Regexp.new("new Insertion\.#{position.to_s.camelize}(.*#{item_id}.*,.*?);"), + @response.body + end + end + + def assert_rjs_replace_html(*args) + div = args.shift + content = extract_matchable_content(args) + + unless content.blank? + case content + when Regexp + assert_match Regexp.new("Element.update(.*#{div}.*,.*#{content.source}.*);"), + @response.body + when String + assert lined_response.include?("Element.update(\"#{div}\", #{content});"), + "No replace_html call found on div: '#{div}' and content: \n#{content}\n" + + "in response:\n#{lined_response}" + else + raise "Invalid content type" + end + else + assert_match Regexp.new("Element.update(.*#{div}.*,.*?);"), @response.body + end + end + + def assert_rjs_replace(*args) + div = args.shift + content = extract_matchable_content(args) + + unless content.blank? + case content + when Regexp + assert_match Regexp.new("Element.replace(.*#{div}.*,.*#{content.source}.*);"), + @response.body + when String + assert lined_response.include?("Element.replace(\"#{div}\", #{content});"), + "No replace call found on div: '#{div}' and content: \n#{content}\n" + + "in response:\n#{lined_response}" + else + raise "Invalid content type" + end + else + assert_match Regexp.new("Element.replace(.*#{div}.*,.*?);"), @response.body + end + end + + protected + + def lined_response + @response.body.split("\n") + end + + def create_generator + block = Proc.new { |*args| yield *args if block_given? } + JavaScriptGenerator.new self, &block + end + + def generic_error(action, args) + "#{action} with args [#{args.join(" ")}] does not show up in response:\n#{lined_response}" + end + + def extract_matchable_content(args) + if args.size == 1 and args.first.is_a? Regexp + return args.first + else + return create_generator.send(:arguments_for_call, args) + end + end +end diff --git a/tracks/vendor/plugins/arts/meta.yml b/tracks/vendor/plugins/arts/meta.yml new file mode 100644 index 00000000..737fb011 --- /dev/null +++ b/tracks/vendor/plugins/arts/meta.yml @@ -0,0 +1,7 @@ +author: Kevin Clark +summary: RJS Assertion Plugin +homepage: http://glu.ttono.us +plugin: +version: 0.1 +license: MIT +rails_version: 1.1.2+ \ No newline at end of file diff --git a/tracks/vendor/plugins/arts/test/arts_test.rb b/tracks/vendor/plugins/arts/test/arts_test.rb new file mode 100644 index 00000000..c6019499 --- /dev/null +++ b/tracks/vendor/plugins/arts/test/arts_test.rb @@ -0,0 +1,361 @@ +$:.unshift(File.dirname(__FILE__) + '/../lib') + +require File.dirname(__FILE__) + '/../../../../config/environment' +require 'test/unit' +require 'rubygems' +require 'breakpoint' + +require 'action_controller/test_process' + +ActionController::Base.logger = nil +ActionController::Base.ignore_missing_templates = false +ActionController::Routing::Routes.reload rescue nil + +class ArtsController < ActionController::Base + def alert + render :update do |page| + page.alert 'This is an alert' + end + end + + def assign + render :update do |page| + page.assign 'a', '2' + end + end + + def call + render :update do |page| + page.call 'foo', 'bar', 'baz' + end + end + + def draggable + render :update do |page| + page.draggable 'my_image', :revert => true + end + end + + def drop_receiving + render :update do |page| + page.drop_receiving "my_cart", :url => { :controller => "cart", :action => "add" } + end + end + + def hide + render :update do |page| + page.hide 'some_div' + end + end + + def insert_html + render :update do |page| + page.insert_html :bottom, 'content', 'Stuff in the content div' + end + end + + def redirect + render :update do |page| + page.redirect_to :controller => 'sample', :action => 'index' + end + end + + def remove + render :update do |page| + page.remove 'offending_div' + end + end + + def replace + render :update do |page| + page.replace 'person_45', '
This replaces person_45
' + end + end + + def replace_html + render :update do |page| + page.replace_html 'person_45', 'This goes inside person_45' + end + end + + def show + render :update do |page| + page.show 'post_1', 'post_2', 'post_3' + end + end + + def sortable + render :update do |page| + page.sortable 'sortable_item' + end + end + + def toggle + render :update do |page| + page.toggle "post_1", "post_2", "post_3" + end + end + + def visual_effect + render :update do |page| + page.visual_effect :highlight, "posts", :duration => '1.0' + end + end + + def rescue_errors(e) raise e end + +end + +class ArtsTest < Test::Unit::TestCase + def setup + @controller = ArtsController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_alert + get :alert + + assert_nothing_raised { assert_rjs :alert, 'This is an alert' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :alert, 'This is not an alert' + end + + assert_nothing_raised { assert_no_rjs :alert, 'This is not an alert' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :alert, 'This is an alert' + end + end + + def test_assign + get :assign + + assert_nothing_raised { assert_rjs :assign, 'a', '2' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :assign, 'a', '3' + end + + assert_nothing_raised { assert_no_rjs :assign, 'a', '3' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :assign, 'a', '2' + end + end + + def test_call + get :call + + assert_nothing_raised { assert_rjs :call, 'foo', 'bar', 'baz' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :call, 'foo', 'bar' + end + + assert_nothing_raised { assert_no_rjs :call, 'foo', 'bar' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :call, 'foo', 'bar', 'baz' + end + end + + def test_draggable + get :draggable + + assert_nothing_raised { assert_rjs :draggable, 'my_image', :revert => true } + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :draggable, 'not_my_image' + end + + assert_nothing_raised { assert_no_rjs :draggable, 'not_my_image' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :draggable, 'my_image', :revert => true + end + end + + def test_drop_receiving + get :drop_receiving + + assert_nothing_raised { assert_rjs :drop_receiving, "my_cart", :url => { :controller => "cart", :action => "add" } } + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :drop_receiving, "my_cart" + end + + assert_nothing_raised { assert_no_rjs :drop_receiving, "my_cart" } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :drop_receiving, "my_cart", :url => { :controller => "cart", :action => "add" } + end + end + + def test_hide + get :hide + + assert_nothing_raised { assert_rjs :hide, 'some_div' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :hide, 'some_other_div' + end + + assert_nothing_raised { assert_no_rjs :hide, 'not_some_div' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :hide, 'some_div' + end + end + + def test_insert_html + get :insert_html + + + assert_nothing_raised do + # No content matching + assert_rjs :insert_html, :bottom, 'content' + # Exact content matching + assert_rjs :insert_html, :bottom, 'content', 'Stuff in the content div' + # Regex matching + assert_rjs :insert_html, :bottom, 'content', /in.*content/ + + assert_no_rjs :insert_html, :bottom, 'not_our_div' + + assert_no_rjs :insert_html, :bottom, 'content', /in.*no content/ + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :insert_html, :bottom, 'content' + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :insert_html, :bottom, 'no_content' + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :insert_html, :bottom, 'content', /in the/ + end + end + + def test_redirect_to + get :redirect + + assert_nothing_raised do + assert_rjs :redirect_to, :controller => 'sample', :action => 'index' + assert_no_rjs :redirect_to, :controller => 'sample', :action => 'show' + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :redirect_to, :controller => 'doesnt', :action => 'exist' + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :redirect_to, :controller => 'sample', :action => 'index' + end + end + + def test_remove + get :remove + + assert_nothing_raised do + assert_rjs :remove, 'offending_div' + assert_no_rjs :remove, 'dancing_happy_div' + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :remove, 'dancing_happy_div' + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :remove, 'offending_div' + end + end + + def test_replace + get :replace + + assert_nothing_raised do + # No content matching + assert_rjs :replace, 'person_45' + # String content matching + assert_rjs :replace, 'person_45', '
This replaces person_45
' + # regexp content matching + assert_rjs :replace, 'person_45', /
.*person_45.*<\/div>/ + + assert_no_rjs :replace, 'person_45', '
This replaces person_46
' + + assert_no_rjs :replace, 'person_45', /person_46/ + end + + assert_raises(Test::Unit::AssertionFailedError) { assert_no_rjs :replace, 'person_45' } + assert_raises(Test::Unit::AssertionFailedError) { assert_no_rjs :replace, 'person_45', /person_45/ } + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :replace, 'person_46' } + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :replace, 'person_45', 'bad stuff' } + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :replace, 'person_45', /not there/} + end + + def test_replace_html + get :replace_html + + assert_nothing_raised do + # No content matching + assert_rjs :replace_html, 'person_45' + # String content matching + assert_rjs :replace_html, 'person_45', 'This goes inside person_45' + # Regexp content matching + assert_rjs :replace_html, 'person_45', /goes inside/ + + assert_no_rjs :replace_html, 'person_46' + + assert_no_rjs :replace_html, 'person_45', /doesn't go inside/ + end + + assert_raises(Test::Unit::AssertionFailedError) { assert_no_rjs :replace_html, 'person_45' } + assert_raises(Test::Unit::AssertionFailedError) { assert_no_rjs :replace_html, 'person_45', /goes/ } + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :replace_html, 'person_46' } + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :replace_html, 'person_45', /gos inside/ } + end + + def test_show + get :show + assert_nothing_raised do + assert_rjs :show, "post_1", "post_2", "post_3" + assert_no_rjs :show, 'post_4' + end + + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :show, 'post_4' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :show, "post_1", "post_2", "post_3" + end + end + + def test_sortable + get :sortable + assert_nothing_raised do + assert_rjs :sortable, 'sortable_item' + assert_no_rjs :sortable, 'non-sortable-item' + end + + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :sortable, 'non-sortable-item' } + assert_raises(Test::Unit::AssertionFailedError) { assert_no_rjs :sortable, 'sortable_item' } + end + + def test_toggle + get :toggle + assert_nothing_raised do + assert_rjs :toggle, "post_1", "post_2", "post_3" + assert_no_rjs :toggle, 'post_4' + end + + assert_raises(Test::Unit::AssertionFailedError) { assert_rjs :toggle, 'post_4' } + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :toggle, "post_1", "post_2", "post_3" + end + end + + def test_visual_effect + get :visual_effect + assert_nothing_raised do + assert_rjs :visual_effect, :highlight, "posts", :duration => '1.0' + assert_no_rjs :visual_effect, :highlight, "lists" + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_rjs :visual_effect, :highlight, "lists" + end + + assert_raises(Test::Unit::AssertionFailedError) do + assert_no_rjs :visual_effect, :highlight, "posts", :duration => '1.0' + end + end +end