prototype-rails 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +7 -0
- data/README +20 -0
- data/Rakefile +10 -0
- data/lib/action_view/helpers/prototype_helper.rb +852 -0
- data/lib/action_view/helpers/scriptaculous_helper.rb +263 -0
- data/lib/action_view/template/handlers/rjs.rb +14 -0
- data/lib/prototype-rails.rb +17 -0
- data/lib/prototype-rails/javascript_helper.rb +65 -0
- data/lib/prototype-rails/on_load_action_controller.rb +2 -0
- data/lib/prototype-rails/on_load_action_view.rb +22 -0
- data/lib/prototype-rails/renderers.rb +12 -0
- data/lib/prototype-rails/rendering.rb +13 -0
- data/lib/prototype-rails/selector_assertions.rb +208 -0
- data/test/abstract_unit.rb +235 -0
- data/test/assert_select_test.rb +452 -0
- data/test/controller/caching_test.rb +46 -0
- data/test/controller/content_type_test.rb +16 -0
- data/test/controller/mime_responds_test.rb +213 -0
- data/test/controller/new_base/content_type_test.rb +19 -0
- data/test/controller/new_base/render_rjs_test.rb +71 -0
- data/test/controller/render_js_test.rb +22 -0
- data/test/fixtures/functional_caching/_partial.erb +3 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
- data/test/fixtures/functional_caching/js_fragment_cached_with_partial.js.rjs +1 -0
- data/test/fixtures/old_content_type/render_default_for_rjs.rjs +1 -0
- data/test/fixtures/respond_to/all_types_with_layout.js.rjs +1 -0
- data/test/fixtures/respond_to/layouts/standard.html.erb +1 -0
- data/test/fixtures/respond_to/using_defaults.js.rjs +1 -0
- data/test/fixtures/respond_to/using_defaults_with_type_list.js.rjs +1 -0
- data/test/fixtures/respond_with/using_resource.js.rjs +1 -0
- data/test/fixtures/test/_one.html.erb +1 -0
- data/test/fixtures/test/_partial.html.erb +1 -0
- data/test/fixtures/test/_partial.js.erb +1 -0
- data/test/fixtures/test/_two.html.erb +1 -0
- data/test/fixtures/test/delete_with_js.rjs +2 -0
- data/test/fixtures/test/enum_rjs_test.rjs +6 -0
- data/test/fixtures/test/greeting.js.rjs +1 -0
- data/test/fixtures/test/render_explicit_html_template.js.rjs +1 -0
- data/test/fixtures/test/render_implicit_html_template.js.rjs +1 -0
- data/test/javascript_helper_test.rb +61 -0
- data/test/lib/controller/fake_models.rb +29 -0
- data/test/render_other_test.rb +257 -0
- data/test/template/prototype_helper_test.rb +476 -0
- data/test/template/render_test.rb +24 -0
- data/test/template/scriptaculous_helper_test.rb +86 -0
- data/vendor/assets/javascripts/controls.js +965 -0
- data/vendor/assets/javascripts/dragdrop.js +974 -0
- data/vendor/assets/javascripts/effects.js +1123 -0
- data/vendor/assets/javascripts/prototype.js +6082 -0
- data/vendor/assets/javascripts/prototype_ujs.js +208 -0
- metadata +127 -0
@@ -0,0 +1 @@
|
|
1
|
+
page[:body].visual_effect :highlight
|
@@ -0,0 +1 @@
|
|
1
|
+
page.call "document.write", render(:partial => "one.html.erb")
|
@@ -0,0 +1 @@
|
|
1
|
+
page.call "document.write", render(:partial => "one")
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
|
3
|
+
class JavaScriptHelperTest < ActionView::TestCase
|
4
|
+
tests ActionView::Helpers::JavaScriptHelper
|
5
|
+
|
6
|
+
def _evaluate_assigns_and_ivars() end
|
7
|
+
|
8
|
+
attr_accessor :formats, :output_buffer
|
9
|
+
|
10
|
+
def update_details(details)
|
11
|
+
@details = details
|
12
|
+
yield if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup
|
16
|
+
super
|
17
|
+
ActiveSupport.escape_html_entities_in_json = true
|
18
|
+
@template = self
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
ActiveSupport.escape_html_entities_in_json = false
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_link_to_function_with_rjs_block
|
26
|
+
html = link_to_function( "Greet me!" ) do |page|
|
27
|
+
page.replace_html 'header', "<h1>Greetings</h1>"
|
28
|
+
end
|
29
|
+
assert_dom_equal %(<a href="#" onclick="Element.update("header", "\\u003Ch1\\u003EGreetings\\u003C/h1\\u003E");; return false;">Greet me!</a>), html
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_link_to_function_with_rjs_block_and_options
|
33
|
+
html = link_to_function( "Greet me!", :class => "updater" ) do |page|
|
34
|
+
page.replace_html 'header', "<h1>Greetings</h1>"
|
35
|
+
end
|
36
|
+
assert_dom_equal %(<a href="#" class="updater" onclick="Element.update("header", "\\u003Ch1\\u003EGreetings\\u003C/h1\\u003E");; return false;">Greet me!</a>), html
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_link_to_function_with_inner_block_does_not_raise_exception
|
40
|
+
html = link_to_function( "Greet me!" ) do |page|
|
41
|
+
page.replace_html 'header', (content_tag :h1 do
|
42
|
+
'Greetings'
|
43
|
+
end)
|
44
|
+
end
|
45
|
+
assert_dom_equal %(<a href="#" onclick="Element.update("header", "\\u003Ch1\\u003EGreetings\\u003C/h1\\u003E");; return false;">Greet me!</a>), html
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_button_to_function_with_rjs_block
|
49
|
+
html = button_to_function( "Greet me!" ) do |page|
|
50
|
+
page.replace_html 'header', "<h1>Greetings</h1>"
|
51
|
+
end
|
52
|
+
assert_dom_equal %(<input type="button" onclick="Element.update("header", "\\u003Ch1\\u003EGreetings\\u003C/h1\\u003E");;" value="Greet me!" />), html
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_button_to_function_with_rjs_block_and_options
|
56
|
+
html = button_to_function( "Greet me!", :class => "greeter" ) do |page|
|
57
|
+
page.replace_html 'header', "<h1>Greetings</h1>"
|
58
|
+
end
|
59
|
+
assert_dom_equal %(<input type="button" class="greeter" onclick="Element.update("header", "\\u003Ch1\\u003EGreetings\\u003C\/h1\\u003E");;" value="Greet me!" />), html
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "active_model"
|
2
|
+
|
3
|
+
class Customer < Struct.new(:name, :id)
|
4
|
+
extend ActiveModel::Naming
|
5
|
+
include ActiveModel::Conversion
|
6
|
+
|
7
|
+
undef_method :to_json
|
8
|
+
|
9
|
+
def to_xml(options={})
|
10
|
+
if options[:builder]
|
11
|
+
options[:builder].name name
|
12
|
+
else
|
13
|
+
"<name>#{name}</name>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_js(options={})
|
18
|
+
"name: #{name.inspect}"
|
19
|
+
end
|
20
|
+
alias :to_text :to_js
|
21
|
+
|
22
|
+
def errors
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
def persisted?
|
27
|
+
id.present?
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
ActionController.add_renderer :simon do |says, options|
|
5
|
+
self.content_type = Mime::TEXT
|
6
|
+
self.response_body = "Simon says: #{says}"
|
7
|
+
end
|
8
|
+
|
9
|
+
class RenderOtherTest < ActionController::TestCase
|
10
|
+
class TestController < ActionController::Base
|
11
|
+
protect_from_forgery
|
12
|
+
|
13
|
+
def self.controller_path
|
14
|
+
'test'
|
15
|
+
end
|
16
|
+
|
17
|
+
layout :determine_layout
|
18
|
+
|
19
|
+
module RenderTestHelper
|
20
|
+
def rjs_helper_method_from_module
|
21
|
+
page.visual_effect :highlight
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
helper RenderTestHelper
|
26
|
+
helper do
|
27
|
+
def rjs_helper_method(value)
|
28
|
+
page.visual_effect :highlight, value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def enum_rjs_test
|
33
|
+
render :update do |page|
|
34
|
+
page.select('.product').each do |value|
|
35
|
+
page.rjs_helper_method_from_module
|
36
|
+
page.rjs_helper_method(value)
|
37
|
+
page.sortable(value, :url => { :action => "order" })
|
38
|
+
page.draggable(value)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def render_explicit_html_template
|
44
|
+
end
|
45
|
+
|
46
|
+
def render_custom_code_rjs
|
47
|
+
render :update, :status => 404 do |page|
|
48
|
+
page.replace :foo, :partial => 'partial'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def render_implicit_html_template
|
53
|
+
end
|
54
|
+
|
55
|
+
def render_js_with_explicit_template
|
56
|
+
@project_id = 4
|
57
|
+
render :template => 'test/delete_with_js'
|
58
|
+
end
|
59
|
+
|
60
|
+
def render_js_with_explicit_action_template
|
61
|
+
@project_id = 4
|
62
|
+
render :action => 'delete_with_js'
|
63
|
+
end
|
64
|
+
|
65
|
+
def delete_with_js
|
66
|
+
@project_id = 4
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_page
|
70
|
+
render :update do |page|
|
71
|
+
page.replace_html 'balance', '$37,000,000.00'
|
72
|
+
page.visual_effect :highlight, 'balance'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def update_page_with_instance_variables
|
77
|
+
@money = '$37,000,000.00'
|
78
|
+
@div_id = 'balance'
|
79
|
+
render :update do |page|
|
80
|
+
page.replace_html @div_id, @money
|
81
|
+
page.visual_effect :highlight, @div_id
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def update_page_with_view_method
|
86
|
+
render :update do |page|
|
87
|
+
page.replace_html 'person', pluralize(2, 'person')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def partial_as_rjs
|
92
|
+
render :update do |page|
|
93
|
+
page.replace :foo, :partial => 'partial'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def respond_to_partial_as_rjs
|
98
|
+
respond_to do |format|
|
99
|
+
format.js do
|
100
|
+
render :update do |page|
|
101
|
+
page.replace :foo, :partial => 'partial'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def render_alternate_default
|
108
|
+
# For this test, the method "default_render" is overridden:
|
109
|
+
@alternate_default_render = lambda do
|
110
|
+
render :update do |page|
|
111
|
+
page.replace :foo, :partial => 'partial'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def render_simon_says
|
117
|
+
render :simon => "foo"
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
def default_render
|
122
|
+
@alternate_default_render ||= nil
|
123
|
+
if @alternate_default_render
|
124
|
+
@alternate_default_render.call
|
125
|
+
else
|
126
|
+
super
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def determine_layout
|
131
|
+
case action_name
|
132
|
+
when "hello_world", "layout_test", "rendering_without_layout",
|
133
|
+
"rendering_nothing_on_layout", "render_text_hello_world",
|
134
|
+
"render_text_hello_world_with_layout",
|
135
|
+
"hello_world_with_layout_false",
|
136
|
+
"partial_only", "partial_only_with_layout",
|
137
|
+
"accessing_params_in_template",
|
138
|
+
"accessing_params_in_template_with_layout",
|
139
|
+
"render_with_explicit_template",
|
140
|
+
"render_with_explicit_string_template",
|
141
|
+
"update_page", "update_page_with_instance_variables"
|
142
|
+
|
143
|
+
"layouts/standard"
|
144
|
+
when "action_talk_to_layout", "layout_overriding_layout"
|
145
|
+
"layouts/talk_from_action"
|
146
|
+
when "render_implicit_html_template_from_xhr_request"
|
147
|
+
(request.xhr? ? 'layouts/xhr' : 'layouts/standard')
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
tests TestController
|
153
|
+
|
154
|
+
def setup
|
155
|
+
# enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
|
156
|
+
# a more accurate simulation of what happens in "real life".
|
157
|
+
super
|
158
|
+
@controller.logger = Logger.new(nil)
|
159
|
+
|
160
|
+
@request.host = "www.nextangle.com"
|
161
|
+
end
|
162
|
+
|
163
|
+
def test_enum_rjs_test
|
164
|
+
ActiveSupport::SecureRandom.stubs(:base64).returns("asdf")
|
165
|
+
get :enum_rjs_test
|
166
|
+
body = %{
|
167
|
+
$$(".product").each(function(value, index) {
|
168
|
+
new Effect.Highlight(element,{});
|
169
|
+
new Effect.Highlight(value,{});
|
170
|
+
Sortable.create(value, {onUpdate:function(){new Ajax.Request('/render_other_test/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value) + '&authenticity_token=' + encodeURIComponent('asdf')})}});
|
171
|
+
new Draggable(value, {});
|
172
|
+
});
|
173
|
+
}.gsub(/^ /, '').strip
|
174
|
+
assert_equal body, @response.body
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_explicitly_rendering_an_html_template_with_implicit_html_template_renders_should_be_possible_from_an_rjs_template
|
178
|
+
[:js, "js"].each do |format|
|
179
|
+
assert_nothing_raised do
|
180
|
+
get :render_explicit_html_template, :format => format
|
181
|
+
assert_equal %(document.write("Hello world\\n");), @response.body
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_render_custom_code_rjs
|
187
|
+
get :render_custom_code_rjs
|
188
|
+
assert_response 404
|
189
|
+
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_render_in_an_rjs_template_should_pick_html_templates_when_available
|
193
|
+
[:js, "js"].each do |format|
|
194
|
+
assert_nothing_raised do
|
195
|
+
get :render_implicit_html_template, :format => format
|
196
|
+
assert_equal %(document.write("Hello world\\n");), @response.body
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_render_rjs_template_explicitly
|
202
|
+
get :render_js_with_explicit_template
|
203
|
+
assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_rendering_rjs_action_explicitly
|
207
|
+
get :render_js_with_explicit_action_template
|
208
|
+
assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_render_rjs_with_default
|
212
|
+
get :delete_with_js
|
213
|
+
assert_equal %!Element.remove("person");\nnew Effect.Highlight(\"project-4\",{});!, @response.body
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_update_page
|
217
|
+
get :update_page
|
218
|
+
assert_template nil
|
219
|
+
assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type']
|
220
|
+
assert_equal 2, @response.body.split($/).length
|
221
|
+
end
|
222
|
+
|
223
|
+
def test_update_page_with_instance_variables
|
224
|
+
get :update_page_with_instance_variables
|
225
|
+
assert_template nil
|
226
|
+
assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
|
227
|
+
assert_match(/balance/, @response.body)
|
228
|
+
assert_match(/\$37/, @response.body)
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_update_page_with_view_method
|
232
|
+
get :update_page_with_view_method
|
233
|
+
assert_template nil
|
234
|
+
assert_equal 'text/javascript; charset=utf-8', @response.headers["Content-Type"]
|
235
|
+
assert_match(/2 people/, @response.body)
|
236
|
+
end
|
237
|
+
|
238
|
+
def test_should_render_html_formatted_partial_with_rjs
|
239
|
+
xhr :get, :partial_as_rjs
|
240
|
+
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_should_render_html_formatted_partial_with_rjs_and_js_format
|
244
|
+
xhr :get, :respond_to_partial_as_rjs
|
245
|
+
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_should_render_with_alternate_default_render
|
249
|
+
xhr :get, :render_alternate_default
|
250
|
+
assert_equal %(Element.replace("foo", "partial html");), @response.body
|
251
|
+
end
|
252
|
+
|
253
|
+
def test_using_custom_render_option
|
254
|
+
get :render_simon_says
|
255
|
+
assert_equal "Simon says: foo", @response.body
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,476 @@
|
|
1
|
+
require 'abstract_unit'
|
2
|
+
require 'active_model'
|
3
|
+
|
4
|
+
class Bunny < Struct.new(:Bunny, :id)
|
5
|
+
extend ActiveModel::Naming
|
6
|
+
include ActiveModel::Conversion
|
7
|
+
def to_key() id ? [id] : nil end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Author
|
11
|
+
extend ActiveModel::Naming
|
12
|
+
include ActiveModel::Conversion
|
13
|
+
|
14
|
+
attr_reader :id
|
15
|
+
def to_key() id ? [id] : nil end
|
16
|
+
def save; @id = 1 end
|
17
|
+
def new_record?; @id.nil? end
|
18
|
+
def name
|
19
|
+
@id.nil? ? 'new author' : "author ##{@id}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Article
|
24
|
+
extend ActiveModel::Naming
|
25
|
+
include ActiveModel::Conversion
|
26
|
+
attr_reader :id
|
27
|
+
attr_reader :author_id
|
28
|
+
def to_key() id ? [id] : nil end
|
29
|
+
def save; @id = 1; @author_id = 1 end
|
30
|
+
def new_record?; @id.nil? end
|
31
|
+
def name
|
32
|
+
@id.nil? ? 'new article' : "article ##{@id}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Author::Nested < Author; end
|
37
|
+
|
38
|
+
|
39
|
+
class PrototypeHelperBaseTest < ActionView::TestCase
|
40
|
+
attr_accessor :formats, :output_buffer
|
41
|
+
|
42
|
+
def update_details(details)
|
43
|
+
@details = details
|
44
|
+
yield if block_given?
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup
|
48
|
+
super
|
49
|
+
@template = self
|
50
|
+
end
|
51
|
+
|
52
|
+
def url_for(options)
|
53
|
+
if options.is_a?(String)
|
54
|
+
options
|
55
|
+
else
|
56
|
+
url = "http://www.example.com/"
|
57
|
+
url << options[:action].to_s if options and options[:action]
|
58
|
+
url << "?a=#{options[:a]}" if options && options[:a]
|
59
|
+
url << "&b=#{options[:b]}" if options && options[:a] && options[:b]
|
60
|
+
url
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
protected
|
65
|
+
def request_forgery_protection_token
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def protect_against_forgery?
|
70
|
+
false
|
71
|
+
end
|
72
|
+
|
73
|
+
def create_generator
|
74
|
+
block = Proc.new { |*args| yield(*args) if block_given? }
|
75
|
+
JavaScriptGenerator.new self, &block
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class PrototypeHelperTest < PrototypeHelperBaseTest
|
80
|
+
def _evaluate_assigns_and_ivars() end
|
81
|
+
|
82
|
+
def setup
|
83
|
+
@record = @author = Author.new
|
84
|
+
@article = Article.new
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_update_page
|
89
|
+
old_output_buffer = output_buffer
|
90
|
+
|
91
|
+
block = Proc.new { |page| page.replace_html('foo', 'bar') }
|
92
|
+
assert_equal create_generator(&block).to_s, update_page(&block)
|
93
|
+
|
94
|
+
assert_equal old_output_buffer, output_buffer
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_update_page_tag
|
98
|
+
block = Proc.new { |page| page.replace_html('foo', 'bar') }
|
99
|
+
assert_equal javascript_tag(create_generator(&block).to_s), update_page_tag(&block)
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_update_page_tag_with_html_options
|
103
|
+
block = Proc.new { |page| page.replace_html('foo', 'bar') }
|
104
|
+
assert_equal javascript_tag(create_generator(&block).to_s, {:defer => 'true'}), update_page_tag({:defer => 'true'}, &block)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_remote_function
|
108
|
+
res = remote_function(:url => authors_path, :with => "'author[name]='+$F('author_name')+'&author[dob]='+$F('author_dob')")
|
109
|
+
assert_equal "new Ajax.Request('/authors', {asynchronous:true, evalScripts:true, parameters:'author[name]='+$F('author_name')+'&author[dob]='+$F('author_dob')})", res
|
110
|
+
assert res.html_safe?
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
def author_path(record)
|
115
|
+
"/authors/#{record.id}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def authors_path
|
119
|
+
"/authors"
|
120
|
+
end
|
121
|
+
|
122
|
+
def author_articles_path(author)
|
123
|
+
"/authors/#{author.id}/articles"
|
124
|
+
end
|
125
|
+
|
126
|
+
def author_article_path(author, article)
|
127
|
+
"/authors/#{author.id}/articles/#{article.id}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class JavaScriptGeneratorTest < PrototypeHelperBaseTest
|
132
|
+
def setup
|
133
|
+
super
|
134
|
+
@generator = create_generator
|
135
|
+
ActiveSupport.escape_html_entities_in_json = true
|
136
|
+
end
|
137
|
+
|
138
|
+
def teardown
|
139
|
+
ActiveSupport.escape_html_entities_in_json = false
|
140
|
+
end
|
141
|
+
|
142
|
+
def _evaluate_assigns_and_ivars() end
|
143
|
+
|
144
|
+
def test_insert_html_with_string
|
145
|
+
assert_equal 'Element.insert("element", { top: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });',
|
146
|
+
@generator.insert_html(:top, 'element', '<p>This is a test</p>')
|
147
|
+
assert_equal 'Element.insert("element", { bottom: "\\u003Cp\u003EThis is a test\\u003C/p\u003E" });',
|
148
|
+
@generator.insert_html(:bottom, 'element', '<p>This is a test</p>')
|
149
|
+
assert_equal 'Element.insert("element", { before: "\\u003Cp\u003EThis is a test\\u003C/p\u003E" });',
|
150
|
+
@generator.insert_html(:before, 'element', '<p>This is a test</p>')
|
151
|
+
assert_equal 'Element.insert("element", { after: "\\u003Cp\u003EThis is a test\\u003C/p\u003E" });',
|
152
|
+
@generator.insert_html(:after, 'element', '<p>This is a test</p>')
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_replace_html_with_string
|
156
|
+
assert_equal 'Element.update("element", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");',
|
157
|
+
@generator.replace_html('element', '<p>This is a test</p>')
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_replace_element_with_string
|
161
|
+
assert_equal 'Element.replace("element", "\\u003Cdiv id=\"element\"\\u003E\\u003Cp\\u003EThis is a test\\u003C/p\\u003E\\u003C/div\\u003E");',
|
162
|
+
@generator.replace('element', '<div id="element"><p>This is a test</p></div>')
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_remove
|
166
|
+
assert_equal 'Element.remove("foo");',
|
167
|
+
@generator.remove('foo')
|
168
|
+
assert_equal '["foo","bar","baz"].each(Element.remove);',
|
169
|
+
@generator.remove('foo', 'bar', 'baz')
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_show
|
173
|
+
assert_equal 'Element.show("foo");',
|
174
|
+
@generator.show('foo')
|
175
|
+
assert_equal '["foo","bar","baz"].each(Element.show);',
|
176
|
+
@generator.show('foo', 'bar', 'baz')
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_hide
|
180
|
+
assert_equal 'Element.hide("foo");',
|
181
|
+
@generator.hide('foo')
|
182
|
+
assert_equal '["foo","bar","baz"].each(Element.hide);',
|
183
|
+
@generator.hide('foo', 'bar', 'baz')
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_toggle
|
187
|
+
assert_equal 'Element.toggle("foo");',
|
188
|
+
@generator.toggle('foo')
|
189
|
+
assert_equal '["foo","bar","baz"].each(Element.toggle);',
|
190
|
+
@generator.toggle('foo', 'bar', 'baz')
|
191
|
+
end
|
192
|
+
|
193
|
+
def test_alert
|
194
|
+
assert_equal 'alert("hello");', @generator.alert('hello')
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_redirect_to
|
198
|
+
assert_equal 'window.location.href = "http://www.example.com/welcome";',
|
199
|
+
@generator.redirect_to(:action => 'welcome')
|
200
|
+
assert_equal 'window.location.href = "http://www.example.com/welcome?a=b&c=d";',
|
201
|
+
@generator.redirect_to("http://www.example.com/welcome?a=b&c=d")
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_reload
|
205
|
+
assert_equal 'window.location.reload();',
|
206
|
+
@generator.reload
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_delay
|
210
|
+
@generator.delay(20) do
|
211
|
+
@generator.hide('foo')
|
212
|
+
end
|
213
|
+
|
214
|
+
assert_equal "setTimeout(function() {\n;\nElement.hide(\"foo\");\n}, 20000);", @generator.to_s
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_to_s
|
218
|
+
@generator.insert_html(:top, 'element', '<p>This is a test</p>')
|
219
|
+
@generator.insert_html(:bottom, 'element', '<p>This is a test</p>')
|
220
|
+
@generator.remove('foo', 'bar')
|
221
|
+
@generator.replace_html('baz', '<p>This is a test</p>')
|
222
|
+
|
223
|
+
assert_equal <<-EOS.chomp, @generator.to_s
|
224
|
+
Element.insert("element", { top: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });
|
225
|
+
Element.insert("element", { bottom: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });
|
226
|
+
["foo","bar"].each(Element.remove);
|
227
|
+
Element.update("baz", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
|
228
|
+
EOS
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_element_access
|
232
|
+
assert_equal %($("hello");), @generator['hello']
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_element_access_on_records
|
236
|
+
assert_equal %($("bunny_5");), @generator[Bunny.new(:id => 5)]
|
237
|
+
assert_equal %($("new_bunny");), @generator[Bunny.new]
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_element_proxy_one_deep
|
241
|
+
@generator['hello'].hide
|
242
|
+
assert_equal %($("hello").hide();), @generator.to_s
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_element_proxy_variable_access
|
246
|
+
@generator['hello']['style']
|
247
|
+
assert_equal %($("hello").style;), @generator.to_s
|
248
|
+
end
|
249
|
+
|
250
|
+
def test_element_proxy_variable_access_with_assignment
|
251
|
+
@generator['hello']['style']['color'] = 'red'
|
252
|
+
assert_equal %($("hello").style.color = "red";), @generator.to_s
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_element_proxy_assignment
|
256
|
+
@generator['hello'].width = 400
|
257
|
+
assert_equal %($("hello").width = 400;), @generator.to_s
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_element_proxy_two_deep
|
261
|
+
@generator['hello'].hide("first").clean_whitespace
|
262
|
+
assert_equal %($("hello").hide("first").cleanWhitespace();), @generator.to_s
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_select_access
|
266
|
+
assert_equal %($$("div.hello");), @generator.select('div.hello')
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_select_proxy_one_deep
|
270
|
+
@generator.select('p.welcome b').first.hide
|
271
|
+
assert_equal %($$("p.welcome b").first().hide();), @generator.to_s
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_visual_effect
|
275
|
+
assert_equal %(new Effect.Puff("blah",{});),
|
276
|
+
@generator.visual_effect(:puff,'blah')
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_visual_effect_toggle
|
280
|
+
assert_equal %(Effect.toggle("blah",'appear',{});),
|
281
|
+
@generator.visual_effect(:toggle_appear,'blah')
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_sortable
|
285
|
+
assert_equal %(Sortable.create("blah", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("blah")})}});),
|
286
|
+
@generator.sortable('blah', :url => { :action => "order" })
|
287
|
+
assert_equal %(Sortable.create("blah", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:false, evalScripts:true, parameters:Sortable.serialize("blah")})}});),
|
288
|
+
@generator.sortable('blah', :url => { :action => "order" }, :type => :synchronous)
|
289
|
+
end
|
290
|
+
|
291
|
+
def test_draggable
|
292
|
+
assert_equal %(new Draggable("blah", {});),
|
293
|
+
@generator.draggable('blah')
|
294
|
+
end
|
295
|
+
|
296
|
+
def test_drop_receiving
|
297
|
+
assert_equal %(Droppables.add("blah", {onDrop:function(element){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}});),
|
298
|
+
@generator.drop_receiving('blah', :url => { :action => "order" })
|
299
|
+
assert_equal %(Droppables.add("blah", {onDrop:function(element){new Ajax.Request('http://www.example.com/order', {asynchronous:false, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}});),
|
300
|
+
@generator.drop_receiving('blah', :url => { :action => "order" }, :type => :synchronous)
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_collection_first_and_last
|
304
|
+
@generator.select('p.welcome b').first.hide()
|
305
|
+
@generator.select('p.welcome b').last.show()
|
306
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
307
|
+
$$("p.welcome b").first().hide();
|
308
|
+
$$("p.welcome b").last().show();
|
309
|
+
EOS
|
310
|
+
end
|
311
|
+
|
312
|
+
def test_collection_proxy_with_each
|
313
|
+
@generator.select('p.welcome b').each do |value|
|
314
|
+
value.remove_class_name 'selected'
|
315
|
+
end
|
316
|
+
@generator.select('p.welcome b').each do |value, index|
|
317
|
+
@generator.visual_effect :highlight, value
|
318
|
+
end
|
319
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
320
|
+
$$("p.welcome b").each(function(value, index) {
|
321
|
+
value.removeClassName("selected");
|
322
|
+
});
|
323
|
+
$$("p.welcome b").each(function(value, index) {
|
324
|
+
new Effect.Highlight(value,{});
|
325
|
+
});
|
326
|
+
EOS
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_collection_proxy_on_collect
|
330
|
+
@generator.select('p').collect('a') { |para| para.show }
|
331
|
+
@generator.select('p').collect { |para| para.hide }
|
332
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
333
|
+
var a = $$("p").collect(function(value, index) {
|
334
|
+
return value.show();
|
335
|
+
});
|
336
|
+
$$("p").collect(function(value, index) {
|
337
|
+
return value.hide();
|
338
|
+
});
|
339
|
+
EOS
|
340
|
+
@generator = create_generator
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_collection_proxy_with_grep
|
344
|
+
@generator.select('p').grep 'a', /^a/ do |value|
|
345
|
+
@generator << '(value.className == "welcome")'
|
346
|
+
end
|
347
|
+
@generator.select('p').grep 'b', /b$/ do |value, index|
|
348
|
+
@generator.call 'alert', value
|
349
|
+
@generator << '(value.className == "welcome")'
|
350
|
+
end
|
351
|
+
|
352
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
353
|
+
var a = $$("p").grep(/^a/, function(value, index) {
|
354
|
+
return (value.className == "welcome");
|
355
|
+
});
|
356
|
+
var b = $$("p").grep(/b$/, function(value, index) {
|
357
|
+
alert(value);
|
358
|
+
return (value.className == "welcome");
|
359
|
+
});
|
360
|
+
EOS
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_collection_proxy_with_inject
|
364
|
+
@generator.select('p').inject 'a', [] do |memo, value|
|
365
|
+
@generator << '(value.className == "welcome")'
|
366
|
+
end
|
367
|
+
@generator.select('p').inject 'b', nil do |memo, value, index|
|
368
|
+
@generator.call 'alert', memo
|
369
|
+
@generator << '(value.className == "welcome")'
|
370
|
+
end
|
371
|
+
|
372
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
373
|
+
var a = $$("p").inject([], function(memo, value, index) {
|
374
|
+
return (value.className == "welcome");
|
375
|
+
});
|
376
|
+
var b = $$("p").inject(null, function(memo, value, index) {
|
377
|
+
alert(memo);
|
378
|
+
return (value.className == "welcome");
|
379
|
+
});
|
380
|
+
EOS
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_collection_proxy_with_pluck
|
384
|
+
@generator.select('p').pluck('a', 'className')
|
385
|
+
assert_equal %(var a = $$("p").pluck("className");), @generator.to_s
|
386
|
+
end
|
387
|
+
|
388
|
+
def test_collection_proxy_with_zip
|
389
|
+
ActionView::Helpers::JavaScriptCollectionProxy.new(@generator, '[1, 2, 3]').zip('a', [4, 5, 6], [7, 8, 9])
|
390
|
+
ActionView::Helpers::JavaScriptCollectionProxy.new(@generator, '[1, 2, 3]').zip('b', [4, 5, 6], [7, 8, 9]) do |array|
|
391
|
+
@generator.call 'array.reverse'
|
392
|
+
end
|
393
|
+
|
394
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
395
|
+
var a = [1, 2, 3].zip([4,5,6], [7,8,9]);
|
396
|
+
var b = [1, 2, 3].zip([4,5,6], [7,8,9], function(array) {
|
397
|
+
return array.reverse();
|
398
|
+
});
|
399
|
+
EOS
|
400
|
+
end
|
401
|
+
|
402
|
+
def test_collection_proxy_with_find_all
|
403
|
+
@generator.select('p').find_all 'a' do |value, index|
|
404
|
+
@generator << '(value.className == "welcome")'
|
405
|
+
end
|
406
|
+
|
407
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
408
|
+
var a = $$("p").findAll(function(value, index) {
|
409
|
+
return (value.className == "welcome");
|
410
|
+
});
|
411
|
+
EOS
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_collection_proxy_with_in_groups_of
|
415
|
+
@generator.select('p').in_groups_of('a', 3)
|
416
|
+
@generator.select('p').in_groups_of('a', 3, 'x')
|
417
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
418
|
+
var a = $$("p").inGroupsOf(3);
|
419
|
+
var a = $$("p").inGroupsOf(3, "x");
|
420
|
+
EOS
|
421
|
+
end
|
422
|
+
|
423
|
+
def test_collection_proxy_with_each_slice
|
424
|
+
@generator.select('p').each_slice('a', 3)
|
425
|
+
@generator.select('p').each_slice('a', 3) do |group, index|
|
426
|
+
group.reverse
|
427
|
+
end
|
428
|
+
|
429
|
+
assert_equal <<-EOS.strip, @generator.to_s
|
430
|
+
var a = $$("p").eachSlice(3);
|
431
|
+
var a = $$("p").eachSlice(3, function(value, index) {
|
432
|
+
return value.reverse();
|
433
|
+
});
|
434
|
+
EOS
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_debug_rjs
|
438
|
+
ActionView::Base.debug_rjs = true
|
439
|
+
@generator['welcome'].replace_html 'Welcome'
|
440
|
+
assert_equal "try {\n$(\"welcome\").update(\"Welcome\");\n} catch (e) { alert('RJS error:\\n\\n' + e.toString()); alert('$(\\\"welcome\\\").update(\\\"Welcome\\\");'); throw e }", @generator.to_s
|
441
|
+
ensure
|
442
|
+
ActionView::Base.debug_rjs = false
|
443
|
+
end
|
444
|
+
|
445
|
+
def test_literal
|
446
|
+
literal = @generator.literal("function() {}")
|
447
|
+
assert_equal "function() {}", ActiveSupport::JSON.encode(literal)
|
448
|
+
assert_equal "", @generator.to_s
|
449
|
+
end
|
450
|
+
|
451
|
+
def test_class_proxy
|
452
|
+
@generator.form.focus('my_field')
|
453
|
+
assert_equal "Form.focus(\"my_field\");", @generator.to_s
|
454
|
+
end
|
455
|
+
|
456
|
+
def test_call_with_block
|
457
|
+
@generator.call(:before)
|
458
|
+
@generator.call(:my_method) do |p|
|
459
|
+
p[:one].show
|
460
|
+
p[:two].hide
|
461
|
+
end
|
462
|
+
@generator.call(:in_between)
|
463
|
+
@generator.call(:my_method_with_arguments, true, "hello") do |p|
|
464
|
+
p[:three].visual_effect(:highlight)
|
465
|
+
end
|
466
|
+
assert_equal "before();\nmy_method(function() { $(\"one\").show();\n$(\"two\").hide(); });\nin_between();\nmy_method_with_arguments(true, \"hello\", function() { $(\"three\").visualEffect(\"highlight\"); });", @generator.to_s
|
467
|
+
end
|
468
|
+
|
469
|
+
def test_class_proxy_call_with_block
|
470
|
+
@generator.my_object.my_method do |p|
|
471
|
+
p[:one].show
|
472
|
+
p[:two].hide
|
473
|
+
end
|
474
|
+
assert_equal "MyObject.myMethod(function() { $(\"one\").show();\n$(\"two\").hide(); });", @generator.to_s
|
475
|
+
end
|
476
|
+
end
|