erector 0.2.83 → 0.3.105
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +17 -219
- data/lib/erector.rb +2 -1
- data/lib/erector/erect.rb +3 -1
- data/lib/erector/extensions/action_controller.rb +21 -19
- data/lib/erector/extensions/action_view_template_handler.rb +37 -12
- data/lib/erector/extensions/object.rb +14 -1
- data/lib/erector/helpers.rb +57 -14
- data/lib/erector/html_parts.rb +2 -0
- data/lib/erector/indenting.rb +1 -1
- data/lib/erector/raw_string.rb +8 -0
- data/lib/erector/widget.rb +225 -109
- data/lib/erector/widgets/table.rb +1 -1
- data/spec/erect/erect_spec.rb +4 -1
- data/spec/erect/rhtml_parser_spec.rb +6 -6
- data/spec/erector/extensions/template_handler_spec.rb +29 -0
- data/spec/erector/rails_helpers_spec.rb +147 -0
- data/spec/erector/widget_spec.rb +71 -0
- data/spec/rails/standard_helpers_spec.rb +105 -0
- data/spec/rails/view_spec.rb +33 -0
- data/spec/spec_helper.rb +8 -0
- data/test/rails_root/app/views/template_handler_spec/test_page.rb +8 -0
- metadata +11 -5
data/spec/erect/erect_spec.rb
CHANGED
@@ -137,9 +137,12 @@ module Erector
|
|
137
137
|
mr_slate_rb = "#{dir}/mr_slate.rb"
|
138
138
|
mr_slate_html = "#{dir}/mr_slate.html"
|
139
139
|
create(mr_slate_rb, "class MrSlate\nend")
|
140
|
-
erect = Erect.new(["--to-html", mr_slate_rb])
|
140
|
+
erect = Erect.new(["-q", "--to-html", mr_slate_rb])
|
141
141
|
erect.run
|
142
142
|
File.exist?(mr_slate_html).should be_false
|
143
143
|
end
|
144
|
+
|
145
|
+
it "properly indents lines beginning with for, unless, etc."
|
146
|
+
it "escapes single quotes inside text strings"
|
144
147
|
end
|
145
148
|
end
|
@@ -246,10 +246,10 @@ describe RhtmlParser do
|
|
246
246
|
end
|
247
247
|
|
248
248
|
it "parses some scaffolding" do
|
249
|
-
parse("
|
249
|
+
parse("<p>
|
250
250
|
<b>Name:</b>
|
251
251
|
<%=h @foo.name %>
|
252
|
-
</p>"
|
252
|
+
</p>").convert.should ==
|
253
253
|
"p do\n" +
|
254
254
|
" b do\n" +
|
255
255
|
" text 'Name:'\n" +
|
@@ -259,7 +259,7 @@ describe RhtmlParser do
|
|
259
259
|
end
|
260
260
|
|
261
261
|
it "parses edit.erb.html" do
|
262
|
-
parse("
|
262
|
+
parse("<h1>Editing foo</h1>
|
263
263
|
|
264
264
|
<%= error_messages_for :foo %>
|
265
265
|
|
@@ -281,11 +281,11 @@ describe RhtmlParser do
|
|
281
281
|
|
282
282
|
<%= link_to 'Show', @foo %> |
|
283
283
|
<%= link_to 'Back', foos_path %>
|
284
|
-
"
|
284
|
+
")
|
285
285
|
end
|
286
286
|
|
287
287
|
it "parses show.html.erb" do
|
288
|
-
parse("
|
288
|
+
parse("<p>
|
289
289
|
<b>Name:</b>
|
290
290
|
<%=h @foo.name %>
|
291
291
|
</p>
|
@@ -298,7 +298,7 @@ describe RhtmlParser do
|
|
298
298
|
|
299
299
|
<%= link_to 'Edit', edit_foo_path(@foo) %> |
|
300
300
|
<%= link_to 'Back', foos_path %>
|
301
|
-
"
|
301
|
+
")
|
302
302
|
end
|
303
303
|
|
304
304
|
it "does meta" do
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
|
2
|
+
|
3
|
+
module TemplateHandlerSpec
|
4
|
+
|
5
|
+
class TemplateHandlerSpecController < ActionController::Base
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ActionView::TemplateHandlers::Erector do
|
9
|
+
|
10
|
+
before do
|
11
|
+
@controller = TemplateHandlerSpecController.new
|
12
|
+
@request = ActionController::TestRequest.new
|
13
|
+
@response = ActionController::TestResponse.new
|
14
|
+
@controller.send(:initialize_template_class, @response)
|
15
|
+
@controller.send(:assign_shortcuts, @request, @response)
|
16
|
+
class << @controller
|
17
|
+
public :rendered_widget, :render
|
18
|
+
end
|
19
|
+
@controller.append_view_path("#{RAILS_ROOT}/app/views")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "assigns locals" do
|
23
|
+
handler = ActionView::TemplateHandlers::Erector.new(@controller)
|
24
|
+
handler.render("class Views::TemplateHandlerSpec::TestPartial", {:foo => "bar"}).should ==
|
25
|
+
"<div class=\"partial\">bar</div>"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module RailsHelpersSpec
|
5
|
+
|
6
|
+
class RailsHelpersSpecController < ActionController::Base
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "Rails helpers" do
|
10
|
+
|
11
|
+
before do
|
12
|
+
@controller = RailsHelpersSpecController.new
|
13
|
+
@request = ActionController::TestRequest.new
|
14
|
+
@response = ActionController::TestResponse.new
|
15
|
+
@controller.send(:initialize_template_class, @response)
|
16
|
+
@controller.send(:assign_shortcuts, @request, @response)
|
17
|
+
@controller.send(:initialize_current_url)
|
18
|
+
class << @controller
|
19
|
+
public :rendered_widget, :render
|
20
|
+
|
21
|
+
attr_accessor :user # dummy instance variable for assigns testing
|
22
|
+
end
|
23
|
+
@controller.append_view_path("#{RAILS_ROOT}/app/views")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "image_tag" do
|
27
|
+
class Erector::TestWidget < Erector::Widget
|
28
|
+
def render
|
29
|
+
image_tag("rails.png")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@controller.render :widget => Erector::TestWidget
|
33
|
+
@response.body.should == "<img alt=\"Rails\" src=\"/images/rails.png\" />"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "javascript_include_tag" do
|
37
|
+
class Erector::TestWidget < Erector::Widget
|
38
|
+
def render
|
39
|
+
javascript_include_tag("rails")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
@controller.render :widget => Erector::TestWidget
|
43
|
+
@response.body.should == "<script src=\"/javascripts/rails.js\" type=\"text/javascript\"></script>"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "define_javascript_functions" do
|
47
|
+
class Erector::TestWidget < Erector::Widget
|
48
|
+
def render
|
49
|
+
define_javascript_functions
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@controller.render :widget => Erector::TestWidget
|
53
|
+
@response.body.should =~ /^<script type=\"text\/javascript\">\n/
|
54
|
+
end
|
55
|
+
|
56
|
+
it "stylesheet_link_tag" do
|
57
|
+
class Erector::TestWidget < Erector::Widget
|
58
|
+
def render
|
59
|
+
stylesheet_link_tag("rails")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
@controller.render :widget => Erector::TestWidget
|
63
|
+
@response.body.should == "<link href=\"/stylesheets/rails.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />"
|
64
|
+
end
|
65
|
+
|
66
|
+
def sortable_js_for(element_id, url)
|
67
|
+
"Sortable.create(\"#{element_id}\", {onUpdate:function(){new Ajax.Request('#{url}', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"#{element_id}\")})}})"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "sortable_element" do
|
71
|
+
class Erector::TestWidget < Erector::Widget
|
72
|
+
def render
|
73
|
+
sortable_element("rails", :url => "/foo")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
@controller.render :widget => Erector::TestWidget
|
77
|
+
@response.body.should ==
|
78
|
+
"<script type=\"text/javascript\">\n//<![CDATA[\n" +
|
79
|
+
sortable_js_for("rails", "/foo") +
|
80
|
+
"\n//]]>\n</script>"
|
81
|
+
end
|
82
|
+
|
83
|
+
it "sortable_element_js" do
|
84
|
+
class Erector::TestWidget < Erector::Widget
|
85
|
+
def render
|
86
|
+
sortable_element_js("rails", :url => "/foo")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
@controller.render :widget => Erector::TestWidget
|
90
|
+
@response.body.should == sortable_js_for("rails", "/foo") + ";"
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
#Note: "text_field_with_auto_complete" is now a plugin, which makes it difficult to test inside the Erector project
|
95
|
+
|
96
|
+
# :link_to_function,
|
97
|
+
# :link_to,
|
98
|
+
# :link_to_remote,
|
99
|
+
# :mail_to,
|
100
|
+
# :button_to,
|
101
|
+
# :submit_tag,
|
102
|
+
|
103
|
+
describe "which html-escape their first parameter:" do
|
104
|
+
it "link_to_function with name" do
|
105
|
+
class Erector::TestWidget < Erector::Widget
|
106
|
+
def render
|
107
|
+
link_to_function("hi", "alert('hi')")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
@controller.render :widget => Erector::TestWidget
|
111
|
+
@response.body.should == "<a href=\"#\" onclick=\"alert('hi'); return false;\">hi</a>"
|
112
|
+
end
|
113
|
+
|
114
|
+
it "link_to_function with block" do
|
115
|
+
class Erector::TestWidget < Erector::Widget
|
116
|
+
def render
|
117
|
+
link_to_function("Show me more", nil, :id => "more_link") do |page|
|
118
|
+
page[:details].visual_effect :toggle_blind
|
119
|
+
page[:more_link].replace_html "Show me less"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
@controller.render :widget => Erector::TestWidget
|
124
|
+
@response.body.should == "<a href=\"#\" id=\"more_link\" onclick=\"$("details").visualEffect("toggle_blind");\n$("more_link").update("Show me less");; return false;\">Show me more</a>"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "which render to the ERB stream:" do
|
129
|
+
it "error_messages for, with object name" do
|
130
|
+
pending("error_messages_for is broken")
|
131
|
+
class Erector::TestWidget < Erector::Widget
|
132
|
+
def render
|
133
|
+
error_messages_for 'user'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
errors = ActiveRecord::Errors.new(nil)
|
137
|
+
errors.add("name", "must be unpronounceable")
|
138
|
+
@controller.user = OpenStruct.new({:name => 'bob', :errors => errors})
|
139
|
+
@controller.render :widget => Erector::TestWidget
|
140
|
+
@response.body.should == "<a href=\"#\" onclick=\"alert('hi'); return false;\">hi</a>"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
end
|
data/spec/erector/widget_spec.rb
CHANGED
@@ -266,6 +266,18 @@ module WidgetSpec
|
|
266
266
|
if (x < y && x > z) alert("don't stop");
|
267
267
|
// ]]>
|
268
268
|
</script>
|
269
|
+
EXPECTED
|
270
|
+
end
|
271
|
+
|
272
|
+
it "renders the raw content inside script tags when given text" do
|
273
|
+
Erector::Widget.new do
|
274
|
+
javascript('alert("&<>\'hello");')
|
275
|
+
end.to_s.should == <<EXPECTED
|
276
|
+
<script type="text/javascript">
|
277
|
+
// <![CDATA[
|
278
|
+
alert("&<>'hello");
|
279
|
+
// ]]>
|
280
|
+
</script>
|
269
281
|
EXPECTED
|
270
282
|
end
|
271
283
|
|
@@ -304,6 +316,22 @@ EXPECTED
|
|
304
316
|
end
|
305
317
|
|
306
318
|
end
|
319
|
+
|
320
|
+
describe "#css" do
|
321
|
+
it "makes a link when passed a string" do
|
322
|
+
Erector::Widget.new do
|
323
|
+
css "erector.css"
|
324
|
+
end.to_s.should == "<link href=\"erector.css\" rel=\"stylesheet\" type=\"text/css\" />"
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
describe "#url" do
|
329
|
+
it "renders an anchor tag with the same href and text" do
|
330
|
+
Erector::Widget.new do
|
331
|
+
url "http://example.com"
|
332
|
+
end.to_s.should == "<a href=\"http://example.com\">http://example.com</a>"
|
333
|
+
end
|
334
|
+
end
|
307
335
|
|
308
336
|
describe '#capture' do
|
309
337
|
it "should return content rather than write it to the buffer" do
|
@@ -374,5 +402,48 @@ EXPECTED
|
|
374
402
|
Parent.new.to_s.should == '123'
|
375
403
|
end
|
376
404
|
end
|
405
|
+
|
406
|
+
describe '#render_to' do
|
407
|
+
class A < Erector::Widget
|
408
|
+
def render
|
409
|
+
p "A"
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
it "renders to a doc" do
|
414
|
+
class B < Erector::Widget
|
415
|
+
def render
|
416
|
+
text "B"
|
417
|
+
A.new.render_to(@doc)
|
418
|
+
text "B"
|
419
|
+
end
|
420
|
+
end
|
421
|
+
b = B.new
|
422
|
+
b.to_s.should == "B<p>A</p>B"
|
423
|
+
b.doc.size.should == 5 # B, <p>, A, </p>, B
|
424
|
+
end
|
425
|
+
|
426
|
+
it "renders to a widget's doc" do
|
427
|
+
class B < Erector::Widget
|
428
|
+
def render
|
429
|
+
text "B"
|
430
|
+
A.new.render_to(self)
|
431
|
+
text "B"
|
432
|
+
end
|
433
|
+
end
|
434
|
+
b = B.new
|
435
|
+
b.to_s.should == "B<p>A</p>B"
|
436
|
+
b.doc.size.should == 5 # B, <p>, A, </p>, B
|
437
|
+
end
|
438
|
+
|
439
|
+
it "passing a widget to text method renders it" do
|
440
|
+
Erector::Widget.new() do
|
441
|
+
text "B"
|
442
|
+
text A.new()
|
443
|
+
text "B"
|
444
|
+
end.to_s.should == "B<p>A</p>B"
|
445
|
+
end
|
446
|
+
|
447
|
+
end
|
377
448
|
end
|
378
449
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
describe "a view" do
|
4
|
+
before(:each) do
|
5
|
+
@view = ActionView::Base.new
|
6
|
+
# hook in model and add error messages
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "with errors" do
|
10
|
+
before(:each) do
|
11
|
+
class DummyView < ActionView::Base
|
12
|
+
attr_accessor :model
|
13
|
+
end
|
14
|
+
|
15
|
+
class DummyModel
|
16
|
+
# not sure what the best way is to mock out a model without
|
17
|
+
# needing a database. But here's my attempt.
|
18
|
+
attr_accessor :errors
|
19
|
+
|
20
|
+
def self.human_attribute_name(attribute)
|
21
|
+
attribute.to_s.capitalize
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
@view = DummyView.new()
|
26
|
+
model = DummyModel.new()
|
27
|
+
model.errors = ActiveRecord::Errors.new(model)
|
28
|
+
model.errors.add(:field, 'too silly')
|
29
|
+
@view.model = model
|
30
|
+
end
|
31
|
+
|
32
|
+
it "was set up correctly" do
|
33
|
+
@view.model.errors.full_messages.join(',').should == "Field too silly"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "renders error messages" do
|
37
|
+
pending("error_messages_for is broken")
|
38
|
+
message = Erector::Widget.new(@view) do
|
39
|
+
error_messages_for(:model)
|
40
|
+
end.to_s
|
41
|
+
message.should include("too silly")
|
42
|
+
message.should include("1 error")
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
it "renders links" do
|
48
|
+
Erector::Widget.new(@view) do
|
49
|
+
link_to 'This&that', '/foo?this=1&that=1'
|
50
|
+
end.to_s.should == "<a href=\"/foo?this=1&that=1\">This&that</a>"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "#image_tag" do
|
54
|
+
Erector::Widget.new(@view) do
|
55
|
+
image_tag("/foo")
|
56
|
+
end.to_s.should == %{<img alt="Foo" src="/foo" />}
|
57
|
+
end
|
58
|
+
|
59
|
+
it "#image_tag with parameters" do
|
60
|
+
Erector::Widget.new(@view) do
|
61
|
+
image_tag("/foo", :id => "photo_foo", :class => "a_photo_class")
|
62
|
+
end.to_s.should == %{<img alt="Foo" class="a_photo_class" id="photo_foo" src="/foo" />}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "renders non-forgery-protected forms via form_tag" do
|
66
|
+
pending("needs ActionView::capture to work")
|
67
|
+
class << @view
|
68
|
+
def protect_against_forgery?
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
Erector::Widget.new(@view) do
|
74
|
+
form_tag("/foo") do
|
75
|
+
p "I'm in a form"
|
76
|
+
end
|
77
|
+
end.to_s.should == "<form action=\"/foo\" method=\"post\"><p>I'm in a form</p></form>"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "renders forgery-protected forms via form_tag" do
|
81
|
+
pending("needs ActionView::capture to work")
|
82
|
+
class << @view
|
83
|
+
def protect_against_forgery?
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
def request_forgery_protection_token
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
def form_authenticity_token
|
92
|
+
"token"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Erector::Widget.new(@view) do
|
97
|
+
puts "starting"
|
98
|
+
form_tag("/foo") do
|
99
|
+
puts "start of block"
|
100
|
+
p "I'm in a form"
|
101
|
+
end
|
102
|
+
end.to_s.should == "<form action=\"/foo\" method=\"post\"><div style=\"margin:0;padding:0\"><input name=\"\" type=\"hidden\" value=\"token\" /></div><p>I'm in a form</p></form>"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
describe "a view" do
|
4
|
+
before(:each) do
|
5
|
+
@view = ActionView::Base.new
|
6
|
+
# hook in model and add error messages
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can capture with an erector block" do
|
10
|
+
pending("needs some re-work (maybe how haml does it?)")
|
11
|
+
message = Erector::Widget.new(@view) do
|
12
|
+
captured = @helpers.capture do
|
13
|
+
h1 'capture me!'
|
14
|
+
end
|
15
|
+
captured.should == "<h1>capture me!</h1>"
|
16
|
+
end.to_s.should == ""
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "the case which fake_erbout handles" do
|
22
|
+
it "works" do
|
23
|
+
@view = ActionView::Base.new
|
24
|
+
Erector::Widget.new(@view) do
|
25
|
+
foo = capture() do
|
26
|
+
fake_erbout do
|
27
|
+
helpers.concat('foo')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
foo.should == 'foo'
|
31
|
+
end.to_s.should == ""
|
32
|
+
end
|
33
|
+
end
|