require File.expand_path(File.dirname(__FILE__) + '/spec_helper') require 'dummy_controller' class Ovechkin < Struct.new(:Ovechkin, :id) extend ActiveModel::Naming include ActiveModel::Conversion def to_key() id ? [id] : nil end end describe JQueryOnRails::Helpers::JQueryHelper do before(:each) do @t = DummyController.new.tap do |c| c.request = ActionDispatch::Request.new Rack::MockRequest.env_for('/dummy') end.view_context end def create_generator block = Proc.new{|*args| yield *args if block_given?} @t.class::JavaScriptGenerator.new @t, &block end it "is automatically mixed into the template class" do @t.class.included_modules.should be_include(JQueryOnRails::Helpers::JQueryHelper) end it "overrides all instance methods from ActionView::Helpers::PrototypeHelper" do (ActionView::Helpers::PrototypeHelper.instance_methods - JQueryOnRails::Helpers::JQueryHelper.instance_methods).should == [] end it "overrides all instance methods from ActionView::Helpers::ScriptaculousHelper" do return pending("not yet implemented") (ActionView::Helpers::ScriptaculousHelper.instance_methods - JQueryOnRails::Helpers::JQueryHelper.instance_methods).should == [] end describe '#options_for_javascript' do before(:each) do @t.singleton_class.instance_eval{ public :options_for_javascript } end it "handles empty options" do @t.options_for_javascript({}).should == '{}' end it "orders options deterministically" do @t.options_for_javascript(:b=>1,:c=>3,:a=>2).should == '{a:2, b:1, c:3}' end end describe '#remote_function' do it "calls jQuery.ajax" do # jQuery.ajax({async:true, ... method:'GET', processData:false, ... }) @t.remote_function(:url=>'/foo').should =~ /jQuery\.ajax\(.*.*\)/ end it "is asynchronous by default" do @t.remote_function(:url=>'/foo').should =~ /async: *true/ end it "can be explicitly synchronous" do @t.remote_function(:url=>'/foo', :type=>:synchronous).should =~ /async: *false/ end describe 'request forgery protection' do before(:each) do @regex = /data: *'#{@t.request_forgery_protection_token}=' *\+ *encodeURIComponent/ end it "is included by default" do @t.remote_function(:url=>'/foo').should =~ @regex end it "can be explicitly omitted" do @t.remote_function(:url=>'/foo', :protect_against_forgery=>false).should_not =~ @regex end it "is omitted when :form is given" do @t.remote_function(:url=>'/foo', :form=>true).should_not =~ @regex end end describe ':url' do it "accepts a string" do @t.remote_function(:url=>'/foo').should =~ /url: *'\/foo'/ end it "accepts a hash" do @t.remote_function(:url=>{:controller=>'dummy', :action=>'index'}).should =~ /url: *'\/dummy'/ end end describe ':method' do it "defaults to GET" do @t.remote_function(:url=>'/foo').should =~ /method: *'GET'/ end it "is capitalized" do @t.remote_function(:url=>'/foo', :method=>:post).should =~ /method: *'POST'/ end end end describe '#visual_effect' do it "renames effects" do @t.visual_effect(:fade,'blah').should == %(jQuery("#blah").fadeOut();) @t.visual_effect(:appear,'blah').should == %(jQuery("#blah").fadeIn();) end it "renames toggle effects" do @t.visual_effect(:toggle_slide,'blah').should == %(jQuery("#blah").slideToggle();) end it "rewrites :toggle_appear" do @t.visual_effect(:toggle_appear,'blah').should == "(function(state){ return (function() { state=!state; return jQuery(\"#blah\")['fade'+(state?'In':'Out')](); })(); })(jQuery(\"#blah\").css('visiblity')!='hidden');" end end describe '#update_page' do it 'matches output from #create_generator' do @block = proc{|page| page.replace_html 'foo', 'bar'} @t.update_page(&@block).should == create_generator(&@block).to_s end end describe '#update_page_tag' do before(:each) do @block = proc{|page| page.replace_html 'foo', 'bar'} end it 'matches output from #create_generator wrapped in a script tag' do @t.update_page_tag(&@block).should == @t.javascript_tag(create_generator(&@block).to_s) end it 'outputs html attributes' do @t.update_page_tag(:defer=>true, &@block).should == @t.javascript_tag(create_generator(&@block).to_s, :defer=>true) end end describe 'JavaScriptGenerator' do before(:each) do @g = create_generator end it "replaces the PrototypeHelper's generator" do @t.class::JavaScriptGenerator.should == JQueryOnRails::Helpers::JQueryHelper::JavaScriptGenerator JQueryOnRails::Helpers::JQueryHelper::JavaScriptGenerator.should === @g end it "#insert_html" do @g.insert_html(:top, 'element', '<p>This is a test</p>').should == 'jQuery("#element").prepend("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");' @g.insert_html(:bottom, 'element', '<p>This is a test</p>').should == 'jQuery("#element").append("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");' @g.insert_html(:before, 'element', '<p>This is a test</p>').should == 'jQuery("#element").before("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");' @g.insert_html(:after, 'element', '<p>This is a test</p>').should == 'jQuery("#element").after("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");' end it "#replace_html" do @g.replace_html('element', '<p>This is a test</p>').should == 'jQuery("#element").html("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");' end it "#replace" do @g.replace('element', '<div id="element"><p>This is a test</p></div>').should == 'jQuery("#element").replaceWith("\\u003Cdiv id=\"element\"\\u003E\\u003Cp\\u003EThis is a test\\u003C/p\\u003E\\u003C/div\\u003E");' end it "#remove" do @g.remove('foo').should == 'jQuery("#foo").remove();' @g.remove('foo', 'bar', 'baz').should == 'jQuery("#foo, #bar, #baz").remove();' end it "#show" do @g.show('foo').should == 'jQuery("#foo").show();' @g.show('foo', 'bar', 'baz').should == 'jQuery("#foo, #bar, #baz").show();' end it "#hide" do @g.hide('foo').should == 'jQuery("#foo").hide();' @g.hide('foo', 'bar', 'baz').should == 'jQuery("#foo, #bar, #baz").hide();' end it "#toggle" do @g.toggle('foo').should == 'jQuery("#foo").toggle();' @g.toggle('foo', 'bar', 'baz').should == 'jQuery("#foo, #bar, #baz").toggle();' end it "#alert" do @g.alert('hello').should == 'alert("hello");' end it "#redirect_to" do @g.redirect_to(:controller=>'dummy', :action=>'index').should == 'window.location.href = "/dummy";' @g.redirect_to("http://www.example.com/welcome?a=b&c=d").should == 'window.location.href = "http://www.example.com/welcome?a=b&c=d";' end it "#reload" do @g.reload.should == 'window.location.reload();' end it "#delay" do @g.delay(20){@g.hide('foo')} @g.to_s.should == "setTimeout(function(){\n;\njQuery(\"#foo\").hide();\n}, 20000);" end it "#to_s" do @g.insert_html(:top, 'element', '<p>This is a test</p>') @g.insert_html(:bottom, 'element', '<p>This is a test</p>') @g.remove('foo', 'bar') @g.replace_html('baz', '<p>This is a test</p>') @g.to_s.should == <<-EOS.chomp jQuery("#element").prepend("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E"); jQuery("#element").append("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E"); jQuery("#foo, #bar").remove(); jQuery("#baz").html("\\u003Cp\\u003EThis is a test\\u003C/p\\u003E"); EOS end it "#literal" do ActiveSupport::JSON.encode(@g.literal("function() {}")).should == "function() {}" @g.to_s.should == "" end it "proxies to class methods" do @g.form.focus('my_field') @g.to_s.should == "Form.focus(\"my_field\");" end it "proxies to class methods with blocks" do @g.my_object.my_method do |p| p[:one].show p[:two].hide end @g.to_s.should == "MyObject.myMethod(function() { jQuery(\"#one\").show();\njQuery(\"#two\").hide(); });" end it "calls with or without blocks" do @g.call(:before) @g.call(:my_method) do |p| p[:one].show p[:two].hide end @g.call(:in_between) @g.call(:my_method_with_arguments, true, "hello") do |p| p[:three].toggle end @g.to_s.should == "before();\nmy_method(function() { jQuery(\"#one\").show();\njQuery(\"#two\").hide(); });\nin_between();\nmy_method_with_arguments(true, \"hello\", function() { jQuery(\"#three\").toggle(); });" end it '#visual_effect matches helper method output' do @g.visual_effect(:toggle_slide,'blah') @g.to_s.should == @t.visual_effect(:toggle_slide,'blah') end describe "element proxy compatibility" do before(:each) do @g.extend @g.class::CompatibilityMethods end it "gets properties" do @g['hello']['style'] @g.to_s.should == 'jQuery("#hello")[0].style;' end it "gets nested properties" do @g['hello']['style']['color'] @g.to_s.should == 'jQuery("#hello")[0].style.color;' end it "sets properties" do @g['hello'].width = 400; @g.to_s.should == 'jQuery("#hello")[0].width = 400;' end it "sets nested properties" do @g['hello']['style']['color'] = 'red'; @g.to_s.should == 'jQuery("#hello")[0].style.color = "red";' end end describe "element proxy" do it "refers by element ID" do @g['hello'] @g.to_s.should == 'jQuery("#hello")' end it "refers by element ID, using ActiveModel::Naming" do @g[Ovechkin.new] @g.to_s.should == 'jQuery("#new_ovechkin")' end it "refers indirectly" do @g['hello'].hide('first').show @g.to_s.should == 'jQuery("#hello").hide("first").show();' end it "calls methods" do @g['hello'].hide @g.to_s.should == 'jQuery("#hello").hide();' end it "gets properties" do @g['hello'][0]['style'] @g.to_s.should == 'jQuery("#hello")[0].style;' end it "gets nested properties" do @g['hello'][0]['style']['color'] @g.to_s.should == 'jQuery("#hello")[0].style.color;' end it "sets properties" do @g['hello'][0].width = 400; @g.to_s.should == 'jQuery("#hello")[0].width = 400;' end it "sets nested properties" do @g['hello'][0]['style']['color'] = 'red'; @g.to_s.should == 'jQuery("#hello")[0].style.color = "red";' end end end end