erector 0.2.83 → 0.3.105
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/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
|