siwilkins-responds_to_parent 1.0.20121128

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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 Sean Treadway
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,42 @@
1
+ RespondsToParent
2
+ ================
3
+
4
+ Adds responds_to_parent to your controller to respond to the parent document of your page.
5
+ Make Ajaxy file uploads by posting the form to a hidden iframe, and respond with
6
+ RJS to the parent window.
7
+
8
+ Example
9
+ =======
10
+
11
+ Controller:
12
+
13
+ class Test < ActionController::Base
14
+ def main
15
+ end
16
+
17
+ def form_action
18
+ # Do stuff with params[:uploaded_file]
19
+
20
+ responds_to_parent do
21
+ render :update do |page|
22
+ page << "alert($('stuff').innerHTML)"
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ main.rhtml:
29
+
30
+ <html>
31
+ <body>
32
+ <div id="stuff">Here is some stuff</div>
33
+
34
+ <form target="frame" action="form_action">
35
+ <input type="file" name="uploaded_file"/>
36
+ <input type="submit"/>
37
+ </form>
38
+
39
+ <iframe id='frame' name="frame"></iframe>
40
+ </body>
41
+ </html>
42
+
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the responds_to_parent plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the responds_to_parent plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'RespondsToParent'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,16 @@
1
+ require 'responds_to_parent/action_controller'
2
+ require 'responds_to_parent/selector_assertion'
3
+
4
+ module ActionController
5
+ class Base
6
+ include RespondsToParent::ActionController
7
+ end
8
+ end
9
+
10
+ module ActionController
11
+ module Assertions
12
+ module SelectorAssertions
13
+ include RespondsToParent::SelectorAssertion
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ module RespondsToParent
2
+ # Module containing the methods useful for child IFRAME to parent window communication
3
+ module ActionController
4
+ # Executes the response body as JavaScript in the context of the parent window.
5
+ # Use this method of you are posting a form to a hidden IFRAME or if you would like
6
+ # to use IFRAME base RPC.
7
+ def responds_to_parent(&block)
8
+ yield
9
+
10
+ if performed?
11
+ # Either pull out a redirect or the request body
12
+ script = if location = erase_redirect_results
13
+ "document.location.href = '#{self.class.helpers.escape_javascript location.to_s}'"
14
+ else
15
+ response.body || ''
16
+ end
17
+
18
+ # Clear out the previous render to prevent double render
19
+ erase_results
20
+
21
+ # We're returning HTML instead of JS or XML now
22
+ response.headers['Content-Type'] = 'text/html; charset=UTF-8'
23
+ @performed_render = false
24
+
25
+ # Eval in parent scope and replace document location of this frame
26
+ # so back button doesn't replay action on targeted forms
27
+ # loc = document.location to be set after parent is updated for IE
28
+ # with(window.parent) - pull in variables from parent window
29
+ # setTimeout - scope the execution in the windows parent for safari
30
+ # window.eval - legal eval for Opera
31
+ render :text => "<html><body><script type='text/javascript' charset='utf-8'>
32
+ var loc = document.location;
33
+ with(window.parent) { setTimeout(function() { window.eval('#{self.class.helpers.escape_javascript script}'); window.loc && loc.replace('about:blank'); }, 1) }
34
+ </script></body></html>"
35
+ end
36
+ end
37
+ alias respond_to_parent responds_to_parent
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ module RespondsToParent
2
+ module SelectorAssertion
3
+ # :call-seq:
4
+ # assert_select_parent()
5
+ # assert_select_parent() { |script| ... }
6
+ #
7
+ # Selects JavaScript that is generated for the `parent' window.
8
+ #
9
+ # Without a block, #assert_select_parent asserts that the response
10
+ # is generated by responds_to_parent.
11
+ #
12
+ # With a block, #assert_select_parent selects script that is supposed
13
+ # to be evaluated in the parent window and passes it to the block.
14
+ # Typically #assert_select_rjs is used in the block.
15
+ def assert_select_parent(*args, &block)
16
+ wrapper_re_str = Regexp.escape("with(window.parent) { setTimeout(function() { window.eval('") +
17
+ "(.*)" +
18
+ Regexp.escape("'); window.loc && loc.replace('about:blank'); }, 1) }")
19
+ match = @response.body.match(Regexp.new(wrapper_re_str))
20
+
21
+ if match
22
+ escaped_js = match[1]
23
+ unescaped_js = escaped_js.
24
+ gsub(%r!</scr"\+"ipt>!, '</script>').
25
+ gsub(/\\(\'|\")/, '\1').
26
+ gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n"). # replace `n' with odd number of backslash.
27
+ gsub(/\\\\/, '\\')
28
+ @response.body = unescaped_js # assert_select_rjs refers @response.body.
29
+
30
+ if block_given?
31
+ begin
32
+ in_scope, @selected = @selected, unescaped_js
33
+ yield unescaped_js
34
+ ensure
35
+ @selected = in_scope
36
+ end
37
+ end
38
+ unescaped_js
39
+ else
40
+ # doesn't seem a responds_to_parent content.
41
+ flunk args.shift || "No content for the parent window."
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,319 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.dirname(__FILE__) + '/../../../../config/environment'
3
+ require 'test/unit'
4
+ require 'test_help'
5
+
6
+ class AssertSelectParentTest < ActionController::TestCase
7
+ class AssertSelectParentController < ActionController::Base
8
+ def response_with=(content)
9
+ @content = content
10
+ end
11
+
12
+ def response_with(&block)
13
+ @update = block
14
+ end
15
+
16
+ def rjs
17
+ responds_to_parent do
18
+ render :update do |page|
19
+ @update.call page
20
+ end
21
+ end
22
+ @update = nil
23
+ end
24
+
25
+ def text
26
+ responds_to_parent do
27
+ render :text => @content, :layout => false
28
+ end
29
+ @content = nil
30
+ end
31
+
32
+ def not_respond_to_parent
33
+ render :nothing => true
34
+ end
35
+
36
+ def rescue_action(e)
37
+ raise e
38
+ end
39
+ end
40
+
41
+ def setup
42
+ @controller = AssertSelectParentController.new
43
+ @request = ActionController::TestRequest.new
44
+ @response = ActionController::TestResponse.new
45
+ end
46
+
47
+ def test_basic
48
+ render_rjs do |page|
49
+ page.replace "test", "<div id=\"1\">foo</div>"
50
+ end
51
+
52
+ found = false
53
+ assert_select_parent do
54
+ assert_select_rjs do
55
+ assert_select "#1"
56
+ found = true
57
+ end
58
+ end
59
+ assert found
60
+ end
61
+
62
+ def test_bubble_up_failure
63
+ render_rjs do |page|
64
+ page.replace "test", "<div id=\"1\">foo</div>"
65
+ end
66
+
67
+ assert_raise(Test::Unit::AssertionFailedError) do
68
+ assert_select_parent do
69
+ assert_select_rjs do
70
+ assert_select "#nonexistent"
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ def test_fail_if_no_content_for_parent
77
+ get :not_respond_to_parent
78
+ assert_raise(Test::Unit::AssertionFailedError) { assert_select_parent }
79
+ end
80
+
81
+ def test_quotes
82
+ do_test_with_text %(single' double" escaped\\' escaped\\" doubleescaped\\\\\\' doubleescaped\\\\\\")
83
+ end
84
+
85
+ def test_new_line
86
+ do_test_with_text "line1\nline2\\nline2\\\nline3\\\\nline3\\\\\nline4\\\\\\nline4"
87
+ end
88
+
89
+ protected
90
+ def render_rjs(&block)
91
+ @controller.response_with &block
92
+ get :rjs
93
+ end
94
+
95
+ def render_text(text)
96
+ @controller.response_with = text
97
+ get :text
98
+ end
99
+
100
+ def do_test_with_text(text)
101
+ render_text text
102
+
103
+ assert_select_parent do |text_for_parent|
104
+ assert_equal text, text_for_parent
105
+ end
106
+ end
107
+ end
108
+ require File.dirname(__FILE__) + '/../../../../config/environment'
109
+ require 'test/unit'
110
+ require 'test_help'
111
+
112
+ class AssertSelectParentTest < ActionController::TestCase
113
+ class AssertSelectParentController < ActionController::Base
114
+ def response_with=(content)
115
+ @content = content
116
+ end
117
+
118
+ def response_with(&block)
119
+ @update = block
120
+ end
121
+
122
+ def rjs
123
+ responds_to_parent do
124
+ render :update do |page|
125
+ @update.call page
126
+ end
127
+ end
128
+ @update = nil
129
+ end
130
+
131
+ def text
132
+ responds_to_parent do
133
+ render :text => @content, :layout => false
134
+ end
135
+ @content = nil
136
+ end
137
+
138
+ def not_respond_to_parent
139
+ render :nothing => true
140
+ end
141
+
142
+ def rescue_action(e)
143
+ raise e
144
+ end
145
+ end
146
+
147
+ def setup
148
+ @controller = AssertSelectParentController.new
149
+ @request = ActionController::TestRequest.new
150
+ @response = ActionController::TestResponse.new
151
+ end
152
+
153
+ def test_basic
154
+ render_rjs do |page|
155
+ page.replace "test", "<div id=\"1\">foo</div>"
156
+ end
157
+
158
+ found = false
159
+ assert_select_parent do
160
+ assert_select_rjs do
161
+ assert_select "#1"
162
+ found = true
163
+ end
164
+ end
165
+ assert found
166
+ end
167
+
168
+ def test_bubble_up_failure
169
+ render_rjs do |page|
170
+ page.replace "test", "<div id=\"1\">foo</div>"
171
+ end
172
+
173
+ assert_raise(Test::Unit::AssertionFailedError) do
174
+ assert_select_parent do
175
+ assert_select_rjs do
176
+ assert_select "#nonexistent"
177
+ end
178
+ end
179
+ end
180
+ end
181
+
182
+ def test_fail_if_no_content_for_parent
183
+ get :not_respond_to_parent
184
+ assert_raise(Test::Unit::AssertionFailedError) { assert_select_parent }
185
+ end
186
+
187
+ def test_quotes
188
+ do_test_with_text %(single' double" escaped\\' escaped\\" doubleescaped\\\\\\' doubleescaped\\\\\\")
189
+ end
190
+
191
+ def test_new_line
192
+ do_test_with_text "line1\nline2\\nline2\\\nline3\\\\nline3\\\\\nline4\\\\\\nline4"
193
+ end
194
+
195
+ protected
196
+ def render_rjs(&block)
197
+ @controller.response_with &block
198
+ get :rjs
199
+ end
200
+
201
+ def render_text(text)
202
+ @controller.response_with = text
203
+ get :text
204
+ end
205
+
206
+ def do_test_with_text(text)
207
+ render_text text
208
+
209
+ assert_select_parent do |text_for_parent|
210
+ assert_equal text, text_for_parent
211
+ end
212
+ end
213
+ end
214
+ require File.dirname(__FILE__) + '/../../../../config/environment'
215
+ require 'test/unit'
216
+ require 'test_help'
217
+
218
+ class AssertSelectParentTest < ActionController::TestCase
219
+ class AssertSelectParentController < ActionController::Base
220
+ def response_with=(content)
221
+ @content = content
222
+ end
223
+
224
+ def response_with(&block)
225
+ @update = block
226
+ end
227
+
228
+ def rjs
229
+ responds_to_parent do
230
+ render :update do |page|
231
+ @update.call page
232
+ end
233
+ end
234
+ @update = nil
235
+ end
236
+
237
+ def text
238
+ responds_to_parent do
239
+ render :text => @content, :layout => false
240
+ end
241
+ @content = nil
242
+ end
243
+
244
+ def not_respond_to_parent
245
+ render :nothing => true
246
+ end
247
+
248
+ def rescue_action(e)
249
+ raise e
250
+ end
251
+ end
252
+
253
+ def setup
254
+ @controller = AssertSelectParentController.new
255
+ @request = ActionController::TestRequest.new
256
+ @response = ActionController::TestResponse.new
257
+ end
258
+
259
+ def test_basic
260
+ render_rjs do |page|
261
+ page.replace "test", "<div id=\"1\">foo</div>"
262
+ end
263
+
264
+ found = false
265
+ assert_select_parent do
266
+ assert_select_rjs do
267
+ assert_select "#1"
268
+ found = true
269
+ end
270
+ end
271
+ assert found
272
+ end
273
+
274
+ def test_bubble_up_failure
275
+ render_rjs do |page|
276
+ page.replace "test", "<div id=\"1\">foo</div>"
277
+ end
278
+
279
+ assert_raise(Test::Unit::AssertionFailedError) do
280
+ assert_select_parent do
281
+ assert_select_rjs do
282
+ assert_select "#nonexistent"
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ def test_fail_if_no_content_for_parent
289
+ get :not_respond_to_parent
290
+ assert_raise(Test::Unit::AssertionFailedError) { assert_select_parent }
291
+ end
292
+
293
+ def test_quotes
294
+ do_test_with_text %(single' double" escaped\\' escaped\\" doubleescaped\\\\\\' doubleescaped\\\\\\")
295
+ end
296
+
297
+ def test_new_line
298
+ do_test_with_text "line1\nline2\\nline2\\\nline3\\\\nline3\\\\\nline4\\\\\\nline4"
299
+ end
300
+
301
+ protected
302
+ def render_rjs(&block)
303
+ @controller.response_with &block
304
+ get :rjs
305
+ end
306
+
307
+ def render_text(text)
308
+ @controller.response_with = text
309
+ get :text
310
+ end
311
+
312
+ def do_test_with_text(text)
313
+ render_text text
314
+
315
+ assert_select_parent do |text_for_parent|
316
+ assert_equal text, text_for_parent
317
+ end
318
+ end
319
+ end
@@ -0,0 +1,116 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.dirname(__FILE__) + '/../../../../config/environment'
3
+ require 'test/unit'
4
+ require 'test_help'
5
+
6
+ class IFrameController < ActionController::Base
7
+ def normal
8
+ render :update do |page|
9
+ page.alert "foo"
10
+ end
11
+ end
12
+
13
+ def aliased
14
+ respond_to_parent do
15
+ render :text => 'woot'
16
+ end
17
+ end
18
+
19
+ def redirect
20
+ responds_to_parent do
21
+ redirect_to '/another/place'
22
+ end
23
+ end
24
+
25
+ def no_block
26
+ responds_to_parent
27
+ end
28
+
29
+ def empty_render
30
+ responds_to_parent do
31
+ end
32
+
33
+ render :text => ''
34
+ end
35
+
36
+ def quotes
37
+ responds_to_parent do
38
+ render :text => %(single' double" qs\\' qd\\" escaped\\\' doubleescaped\\\\')
39
+ end
40
+ end
41
+
42
+ def newlines
43
+ responds_to_parent do
44
+ render :text => "line1\nline2\\nline2"
45
+ end
46
+ end
47
+
48
+ def update
49
+ responds_to_parent do
50
+ render :update do |page|
51
+ page.alert 'foo'
52
+ page.alert 'bar'
53
+ end
54
+ end
55
+ end
56
+
57
+ def rescue_action(e)
58
+ raise e
59
+ end
60
+ end
61
+
62
+ class RespondsToParentTest < ActionController::TestCase
63
+ def setup
64
+ @controller = IFrameController.new
65
+ @request = ActionController::TestRequest.new
66
+ @response = ActionController::TestResponse.new
67
+ end
68
+
69
+ def test_normal
70
+ get :normal
71
+ assert_match /alert\("foo"\)/, @response.body
72
+ assert_no_match /window\.parent/, @response.body
73
+ end
74
+
75
+ def test_quotes_should_be_escaped
76
+ render :quotes
77
+ assert_match %r{eval\('single\\' double\\" qs\\\\\\' qd\\\\\\" escaped\\\\\\' doubleescaped\\\\\\\\\\'}, @response.body
78
+ end
79
+
80
+ def test_newlines_should_be_escaped
81
+ render :newlines
82
+ assert_match %r{eval\('line1\\nline2\\\\nline2'\)}, @response.body
83
+ end
84
+
85
+ def test_no_block_should_raise
86
+ assert_raises LocalJumpError do
87
+ get :no_block
88
+ end
89
+ end
90
+
91
+ def test_empty_render_should_not_expand_javascript
92
+ get :empty_render
93
+ assert_equal '', @response.body
94
+ end
95
+
96
+ def test_update_should_perform_combined_rjs
97
+ render :update
98
+ assert_match /alert\(\\"foo\\"\);\\nalert\(\\"bar\\"\)/, @response.body
99
+ end
100
+
101
+ def test_aliased_method_should_not_raise
102
+ assert_nothing_raised do
103
+ render :aliased
104
+ assert_match /eval\('woot'\)/, @response.body
105
+ end
106
+ end
107
+
108
+ protected
109
+
110
+ def render(action)
111
+ get action
112
+ assert_match /<script type='text\/javascript'/, @response.body
113
+ assert_match /with\(window\.parent\)/, @response.body
114
+ assert_match /loc\.replace\('about:blank'\)/, @response.body
115
+ end
116
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: siwilkins-responds_to_parent
3
+ version: !ruby/object:Gem::Version
4
+ hash: 40242247
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 20121128
10
+ version: 1.0.20121128
11
+ platform: ruby
12
+ authors:
13
+ - Mark Catley
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-11-28 00:00:00 +00:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email:
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - README
32
+ - Rakefile
33
+ - MIT-LICENSE
34
+ - lib/responds_to_parent.rb
35
+ - lib/responds_to_parent/action_controller.rb
36
+ - lib/responds_to_parent/selector_assertion.rb
37
+ - test/responds_to_parent_test.rb
38
+ - test/assert_select_parent_test.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/markcatley/responds_to_parent
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.4.2
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: "[Rails] Adds 'responds_to_parent' to your controller torespond to the parent document of your page.Make Ajaxy file uploads by posting the form to a hiddeniframe, and respond with RJS to the parent window.(added fix to prevent DoubleRenderErrors)"
73
+ test_files: []
74
+