erector 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/README.txt +17 -3
  2. data/VERSION.yml +2 -2
  3. data/bin/erector +1 -1
  4. data/lib/erector.rb +22 -2
  5. data/lib/erector/after_initialize.rb +34 -0
  6. data/lib/erector/caching.rb +93 -0
  7. data/lib/erector/convenience.rb +58 -0
  8. data/lib/erector/dependencies.rb +24 -0
  9. data/lib/erector/dependency.rb +21 -0
  10. data/lib/erector/{erect.rb → erect/erect.rb} +14 -4
  11. data/lib/erector/{erected.rb → erect/erected.rb} +6 -4
  12. data/lib/erector/{indenting.rb → erect/indenting.rb} +0 -0
  13. data/lib/erector/{rhtml.treetop → erect/rhtml.treetop} +51 -11
  14. data/lib/erector/errors.rb +12 -0
  15. data/lib/erector/extensions/hash.rb +21 -0
  16. data/lib/erector/externals.rb +88 -24
  17. data/lib/erector/html.rb +352 -0
  18. data/lib/erector/inline.rb +5 -5
  19. data/lib/erector/jquery.rb +36 -0
  20. data/lib/erector/mixin.rb +3 -5
  21. data/lib/erector/needs.rb +94 -0
  22. data/lib/erector/output.rb +117 -0
  23. data/lib/erector/rails.rb +2 -2
  24. data/lib/erector/rails/extensions/action_controller.rb +5 -3
  25. data/lib/erector/rails/extensions/rails_helpers.rb +159 -0
  26. data/lib/erector/rails/extensions/rails_widget.rb +98 -56
  27. data/lib/erector/rails/rails_form_builder.rb +8 -4
  28. data/lib/erector/rails/rails_version.rb +2 -2
  29. data/lib/erector/rails/template_handlers/ert_handler.rb +1 -1
  30. data/lib/erector/rails/template_handlers/rb_handler.rb +42 -1
  31. data/lib/erector/raw_string.rb +2 -2
  32. data/lib/erector/sass.rb +22 -0
  33. data/lib/erector/widget.rb +100 -653
  34. data/lib/erector/widgets.rb +1 -0
  35. data/lib/erector/widgets/external_renderer.rb +51 -0
  36. data/lib/erector/widgets/page.rb +45 -63
  37. data/lib/erector/widgets/table.rb +9 -1
  38. data/spec/erect/erect_rails_spec.rb +19 -17
  39. data/spec/erect/erect_spec.rb +11 -1
  40. data/spec/erect/erected_spec.rb +76 -5
  41. data/spec/erect/rhtml_parser_spec.rb +11 -1
  42. data/spec/erector/caching_spec.rb +267 -0
  43. data/spec/erector/convenience_spec.rb +258 -0
  44. data/spec/erector/dependency_spec.rb +46 -0
  45. data/spec/erector/externals_spec.rb +233 -0
  46. data/spec/erector/html_spec.rb +508 -0
  47. data/spec/erector/indentation_spec.rb +84 -24
  48. data/spec/erector/inline_spec.rb +19 -8
  49. data/spec/erector/jquery_spec.rb +35 -0
  50. data/spec/erector/mixin_spec.rb +1 -1
  51. data/spec/erector/needs_spec.rb +120 -0
  52. data/spec/erector/output_spec.rb +199 -0
  53. data/spec/erector/sample-file.txt +1 -0
  54. data/spec/erector/sass_spec.rb +33 -0
  55. data/spec/erector/widget_spec.rb +113 -932
  56. data/spec/erector/widgets/field_table_spec.rb +6 -6
  57. data/spec/erector/widgets/form_spec.rb +3 -3
  58. data/spec/erector/widgets/page_spec.rb +52 -6
  59. data/spec/erector/widgets/table_spec.rb +4 -4
  60. data/spec/spec_helper.rb +70 -29
  61. metadata +56 -19
  62. data/lib/erector/rails/extensions/rails_widget/rails_helpers.rb +0 -137
  63. data/spec/core_spec_suite.rb +0 -3
  64. data/spec/erector/external_spec.rb +0 -110
  65. data/spec/rails_spec_suite.rb +0 -3
  66. data/spec/spec.opts +0 -1
  67. data/spec/spec_suite.rb +0 -40
@@ -1,10 +1,11 @@
1
1
  require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
2
 
3
3
  describe "indentation" do
4
+ include Erector::Mixin
4
5
 
5
6
  it "can detect newliney tags" do
6
7
  widget = ::Erector.inline
7
- widget.instance_eval do
8
+ widget.instance_eval do
8
9
  @prettyprint = true
9
10
  end
10
11
  widget.send(:newliney?, "i").should == false
@@ -17,21 +18,21 @@ describe "indentation" do
17
18
  b "World"
18
19
  end.to_pretty.should == "Hello, <b>World</b>"
19
20
  end
20
-
21
+
21
22
  it "should add newlines before open newliney tags" do
22
23
  Erector.inline do
23
24
  p "foo"
24
25
  p "bar"
25
26
  end.to_pretty.should == "<p>foo</p>\n<p>bar</p>\n"
26
27
  end
27
-
28
+
28
29
  it "should add newlines between text and open newliney tag" do
29
30
  Erector.inline do
30
31
  text "One"
31
32
  p "Two"
32
33
  end.to_pretty.should == "One\n<p>Two</p>\n"
33
34
  end
34
-
35
+
35
36
  it "should add newlines after end newliney tags" do
36
37
  Erector.inline do
37
38
  tr do
@@ -39,7 +40,7 @@ describe "indentation" do
39
40
  end
40
41
  end.to_pretty.should == "<tr>\n <td>cell</td>\n</tr>\n"
41
42
  end
42
-
43
+
43
44
  it "should treat empty elements as start and end" do
44
45
  Erector.inline do
45
46
  p "before"
@@ -47,13 +48,13 @@ describe "indentation" do
47
48
  p "after"
48
49
  end.to_pretty.should == "<p>before</p>\n<br />\n<p>after</p>\n"
49
50
  end
50
-
51
+
51
52
  it "empty elements sets at_start_of_line" do
52
53
  Erector.inline do
53
54
  text "before"
54
55
  br
55
56
  p "after"
56
- end.to_pretty.should == "before\n<br />\n<p>after</p>\n"
57
+ end.to_pretty.should == "before<br />\n<p>after</p>\n"
57
58
  end
58
59
 
59
60
  it "will not insert extra space before/after input element" do
@@ -65,7 +66,7 @@ describe "indentation" do
65
66
  text 'after'
66
67
  end.to_pretty.should == 'Name<input type="text" />after'
67
68
  end
68
-
69
+
69
70
  it "will indent" do
70
71
  Erector.inline do
71
72
  html do
@@ -91,7 +92,7 @@ describe "indentation" do
91
92
  </html>
92
93
  END
93
94
  end
94
-
95
+
95
96
  it "preserves indentation for sub-rendered widgets" do
96
97
  tea = Erector.inline do
97
98
  div do
@@ -101,10 +102,10 @@ END
101
102
  cup = Erector.inline do
102
103
  div do
103
104
  p "fine china"
104
- tea.write_via(self)
105
+ widget tea
105
106
  end
106
107
  end
107
-
108
+
108
109
  cup.to_pretty.should == <<END
109
110
  <div>
110
111
  <p>fine china</p>
@@ -114,38 +115,97 @@ END
114
115
  </div>
115
116
  END
116
117
  end
117
-
118
- it "can turn off newlines" do
118
+
119
+ # see http://github.com/pivotal/erector/issues/#issue/5
120
+ it "indents scripts properly" do
121
+ pending
119
122
  Erector.inline do
123
+ html :xmlns => 'http://www.w3.org/1999/xhtml' do
124
+ head do
125
+ javascript "Cufon.replace('#content');"
126
+ javascript '$(document).ready(function(){ $(document).pngFix(); });'
127
+ end
128
+ body do
129
+ end
130
+ end
131
+ end.to_pretty.should == <<-HTML
132
+ <html xmlns="http://www.w3.org/1999/xhtml">
133
+ <head>
134
+ <script type="text/javascript">
135
+ // <![CDATA[
136
+ Cufon.replace('#content');
137
+ // ]]>
138
+ </script>
139
+ <script type="text/javascript">
140
+ // <![CDATA[
141
+ $(document).ready(function(){ $(document).pngFix(); });
142
+ // ]]>
143
+ </script>
144
+ </head>
145
+ <body></body>
146
+ </html>
147
+ HTML
148
+ end
149
+
150
+ it "can turn off newlines" do
151
+ erector do
120
152
  text "One"
121
153
  p "Two"
122
- end.to_s.should == "One<p>Two</p>"
154
+ end.should == "One<p>Two</p>"
123
155
  end
124
-
156
+
125
157
  it "can turn newlines on and off" do
126
158
  widget = Erector.inline do
127
159
  text "One"
128
160
  p "Two"
129
161
  end
130
- widget.to_s.should == "One<p>Two</p>"
162
+ widget.to_html.should == "One<p>Two</p>"
131
163
  widget.to_pretty.should == "One\n<p>Two</p>\n"
132
- widget.to_s.should == "One<p>Two</p>"
164
+ widget.to_html.should == "One<p>Two</p>"
133
165
  end
134
-
166
+
135
167
  it "can turn on newlines via to_pretty" do
136
168
  widget = Erector.inline do
137
169
  text "One"
138
170
  p "Two"
139
171
  end.to_pretty.should == "One\n<p>Two</p>\n"
140
172
  end
141
-
173
+
142
174
  it "can turn newlines on/off via global variable" do
143
- Erector.inline { br }.to_s.should == "<br />"
175
+ erector { br }.should == "<br />"
144
176
  Erector::Widget.prettyprint_default = true
145
- Erector.inline { br }.to_s.should == "<br />\n"
177
+ erector { br }.should == "<br />\n"
146
178
  Erector::Widget.prettyprint_default = false
147
- Erector.inline { br }.to_s.should == "<br />"
179
+ erector { br }.should == "<br />"
148
180
  end
149
-
150
- end
151
181
 
182
+ describe ":max_length" do
183
+ it "wraps after N characters" do
184
+ Erector.inline do
185
+ div "the quick brown fox jumps over the lazy dog"
186
+ end.to_html(:max_length => 20).should ==
187
+ "<div>the quick brown\n" +
188
+ "fox jumps over the\n" +
189
+ "lazy dog</div>"
190
+ end
191
+
192
+ it "preserves pretty indent" do
193
+ Erector.inline do
194
+ div "the quick brown fox jumps over the lazy dog"
195
+ end.to_pretty(:max_length => 20).should ==
196
+ "<div>the quick brown\n" +
197
+ " fox jumps over the\n" +
198
+ " lazy dog</div>\n"
199
+ end
200
+
201
+ it "preserves raw strings" do
202
+ Erector.inline do
203
+ div raw("the quick <brown> fox <jumps> over the lazy dog")
204
+ end.to_html(:max_length => 20).should ==
205
+ "<div>the quick\n" +
206
+ "<brown> fox <jumps>\n" +
207
+ "over the lazy dog\n" +
208
+ "</div>"
209
+ end
210
+ end
211
+ end
@@ -3,18 +3,29 @@ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
3
3
  describe Erector::Widget do
4
4
  it "provides access to instance variables from the calling context" do
5
5
  @var = "yay"
6
- Erector::Widget.new { @var.should == "yay"; @var = "yum" }.to_s
6
+ Erector::Widget.new { @var.should == "yay"; @var = "yum" }.to_html
7
7
  @var.should == "yum"
8
8
  end
9
9
 
10
10
  it "provides access to bound variables from the calling context" do
11
11
  var = "yay"
12
- Erector::Widget.new { var.should == "yay"; var = "yum" }.to_s
12
+ Erector::Widget.new { var.should == "yay"; var = "yum" }.to_html
13
13
  var.should == "yum"
14
14
  end
15
15
 
16
16
  it "doesn't provide access to Erector methods" do
17
- Erector::Widget.new { lambda { text "yay" }.should raise_error(NoMethodError) }.to_s
17
+ Erector::Widget.new { lambda { text "yay" }.should raise_error(NoMethodError) }.to_html
18
+ end
19
+
20
+ describe ".inline" do
21
+ it "returns an instance with Erector::Inline mixed in" do
22
+ widget_subclass = Class.new(Erector::Widget)
23
+ widget_subclass.ancestors.should_not include(Erector::Inline)
24
+
25
+ inlined_instance = widget_subclass.inline
26
+ inlined_instance.class.ancestors.should include(widget_subclass)
27
+ inlined_instance.class.ancestors.should include(Erector::Inline)
28
+ end
18
29
  end
19
30
  end
20
31
 
@@ -25,16 +36,16 @@ describe Erector::Inline do
25
36
 
26
37
  it "doesn't provide access to instance variables from the calling context" do
27
38
  @var = "yay"
28
- Erector.inline { text @var }.to_s.should == ""
39
+ Erector.inline { text @var }.to_html.should == ""
29
40
  end
30
41
 
31
42
  it "provides access to bound variables from the calling context" do
32
43
  var = "yay"
33
- Erector.inline { text var }.to_s.should == "yay"
44
+ Erector.inline { text var }.to_html.should == "yay"
34
45
  end
35
46
 
36
47
  it "provides access to explicit assigns" do
37
- Erector.inline(:var => "yay") { text @var }.to_s.should == "yay"
48
+ Erector.inline(:var => "yay") { text @var }.to_html.should == "yay"
38
49
  end
39
50
 
40
51
  it "provides access to methods from the calling context" do
@@ -42,7 +53,7 @@ describe Erector::Inline do
42
53
  "yay"
43
54
  end
44
55
 
45
- Erector.inline { text helper }.to_s.should == "yay"
56
+ Erector.inline { text helper }.to_html.should == "yay"
46
57
  end
47
58
 
48
59
  describe "#call_block" do
@@ -53,7 +64,7 @@ describe Erector::Inline do
53
64
  end
54
65
 
55
66
  # inside the block...
56
- x.to_s.should ==
67
+ x.to_html.should ==
57
68
  "<arg>#{x.object_id}</arg>" + # the argument is the child
58
69
  "<self>#{x.object_id}</self>" # and self is also the child
59
70
  end
@@ -0,0 +1,35 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ describe Erector::JQuery do
4
+ include Erector::Mixin
5
+
6
+ describe "#jquery" do
7
+ def expected(event, *args)
8
+
9
+ "<script #{'id="foo" ' if args.include? :id}type=\"text/javascript\">\n" +
10
+ "// <![CDATA[\n\n" +
11
+ "jQuery(document).#{event}(function($){\n" +
12
+ "alert('hello');\n});\n// ]]>\n</script>\n"
13
+ end
14
+
15
+ it "outputs a 'jquery ready' script block by default" do
16
+ erector { jquery "alert('hello');" }.should == expected("ready")
17
+ end
18
+
19
+ it "outputs attributes" do
20
+ erector { jquery "alert('hello');", :id => 'foo' }.should == expected("ready", :id)
21
+ end
22
+
23
+ it "outputs a 'jquery ready' script block when passed a symbol for the first arg" do
24
+ erector { jquery :ready, "alert('hello');" }.should == expected("ready")
25
+ end
26
+
27
+ it "outputs a 'jquery load' script block" do
28
+ erector { jquery :load, "alert('hello');" }.should == expected("load")
29
+ end
30
+
31
+ it "combines event, text, and attributes" do
32
+ erector { jquery :load, "alert('hello');", :id => "foo" }.should == expected("load", :id)
33
+ end
34
+ end
35
+ end
@@ -23,7 +23,7 @@ module MixinSpec
23
23
  Thing.new.name.should == "<span class=\"name\">Gabriel <i>Garcia</i> Marquez</span>"
24
24
  end
25
25
 
26
- it "passes its parameters to to_s" do
26
+ it "passes its parameters to to_html" do
27
27
  class Thing
28
28
  include Erector::Mixin
29
29
  def pretty_name
@@ -0,0 +1,120 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ describe Erector::Needs do
4
+ it "doesn't complain if there aren't any needs declared" do
5
+ class Thing1 < Erector::Widget
6
+ end
7
+ Thing1.new
8
+ end
9
+
10
+ it "allows you to say that you don't want any parameters" do
11
+ class Thing2 < Erector::Widget
12
+ needs nil
13
+ end
14
+ lambda { Thing2.new }.should_not raise_error
15
+ lambda { Thing2.new(:foo => 1) }.should raise_error
16
+ end
17
+
18
+ it "doesn't complain if you pass it a declared parameter" do
19
+ class Thing2b < Erector::Widget
20
+ needs :foo
21
+ end
22
+ lambda { Thing2b.new(:foo => 1) }.should_not raise_error
23
+ end
24
+
25
+ it "complains if you pass it an undeclared parameter" do
26
+ class Thing3 < Erector::Widget
27
+ needs :foo
28
+ end
29
+ lambda { Thing3.new(:bar => 1) }.should raise_error
30
+ end
31
+
32
+ it "allows multiple declared parameters" do
33
+ class Thing4 < Erector::Widget
34
+ needs :foo, :bar
35
+ end
36
+ lambda { Thing4.new(:foo => 1, :bar => 2) }.should_not raise_error
37
+ end
38
+
39
+ it "complains when passing in an extra parameter after declaring many parameters" do
40
+ class Thing5 < Erector::Widget
41
+ needs :foo, :bar
42
+ end
43
+ lambda { Thing5.new(:foo => 1, :bar => 2, :baz => 3) }.should raise_error
44
+ end
45
+
46
+ it "complains when you forget to pass in a needed parameter" do
47
+ class Thing6 < Erector::Widget
48
+ needs :foo, :bar
49
+ end
50
+ lambda { Thing6.new(:foo => 1) }.should raise_error
51
+ end
52
+
53
+ it "doesn't complain if you omit a parameter with a default value" do
54
+ class Thing7 < Erector::Widget
55
+ needs :foo
56
+ needs :bar => 7
57
+ needs :baz => 8
58
+ end
59
+ lambda {
60
+ thing = Thing7.new(:foo => 1, :baz => 3)
61
+ thing.instance_variable_get(:@bar).should equal(7)
62
+ thing.instance_variable_get(:@baz).should equal(3)
63
+ }.should_not raise_error
64
+ end
65
+
66
+ it "allows multiple values on a line, including default values at the end of the line" do
67
+ class Thing8 < Erector::Widget
68
+ needs :foo, :bar => 7, :baz => 8
69
+ end
70
+ lambda {
71
+ thing = Thing8.new(:foo => 1, :baz => 2)
72
+ thing.instance_variable_get(:@foo).should equal(1)
73
+ thing.instance_variable_get(:@bar).should equal(7)
74
+ thing.instance_variable_get(:@baz).should equal(2)
75
+ }.should_not raise_error
76
+ end
77
+
78
+ it "allows nil to be a default value" do
79
+ class Thing9 < Erector::Widget
80
+ needs :foo => nil
81
+ end
82
+ lambda {
83
+ thing = Thing9.new
84
+ thing.instance_variable_get(:@foo).should be_nil
85
+ }.should_not raise_error
86
+ end
87
+
88
+ it "accumulates needs across the inheritance chain even with modules mixed in" do
89
+ module Something
90
+ end
91
+
92
+ class Vehicle < Erector::Widget
93
+ needs :wheels
94
+ end
95
+
96
+ class Car < Vehicle
97
+ include Something
98
+ needs :engine
99
+ end
100
+
101
+ lambda { Car.new(:engine => 'V-8', :wheels => 4) }.should_not raise_error
102
+ lambda { Car.new(:engine => 'V-8') }.should raise_error
103
+ lambda { Car.new(:wheels => 4) }.should raise_error
104
+ end
105
+
106
+ it "no longer defines accessors for each of the needed variables" do
107
+ class NeedfulThing < Erector::Widget
108
+ needs :love
109
+ end
110
+ thing = NeedfulThing.new(:love => "all we need")
111
+ lambda {thing.love}.should raise_error(NoMethodError)
112
+ end
113
+
114
+ it "no longer complains if you attempt to 'need' a variable whose name overlaps with an existing method" do
115
+ class ThingWithOverlap < Erector::Widget
116
+ needs :text
117
+ end
118
+ lambda { ThingWithOverlap.new(:text => "alas") }.should_not raise_error(ArgumentError)
119
+ end
120
+ end
@@ -0,0 +1,199 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module Erector
4
+ describe Erector::Output do
5
+ before do
6
+ @output = Output.new
7
+ end
8
+
9
+ it "accepts a string via the << operator" do
10
+ @output.to_s.should == ""
11
+ @output << "foo"
12
+ @output.to_s.should == "foo"
13
+ @output << "bar"
14
+ @output.to_s.should == "foobar"
15
+ end
16
+
17
+ it "#<< accepts a number" do
18
+ @output << 1
19
+ @output.to_s.should == "1"
20
+ end
21
+
22
+ it "accepts chained <<s" do
23
+ @output << "foo" << "bar"
24
+ @output.to_s.should == "foobar"
25
+ end
26
+
27
+ it "provides a placeholder string to be filled in later" do
28
+ @output << "foo"
29
+ placeholder = @output.placeholder
30
+ @output << "bar"
31
+ @output.to_s.should == "foobar"
32
+ placeholder << "baz"
33
+ @output.to_s.should == "foobazbar"
34
+ end
35
+
36
+ describe '#to_a' do
37
+ it "emits an array" do
38
+ @output << "foo" << "bar"
39
+ @output.to_a.join.should == "foobar"
40
+ end
41
+ end
42
+
43
+ it "can be initialized with an existing string buffer" do
44
+ s = "foo"
45
+ @output = Output.new { s }
46
+ @output << "bar"
47
+ s.should == "foobar"
48
+ @output.to_s.should == "foobar"
49
+ end
50
+
51
+ it "accepts a prettyprint option" do
52
+ Erector::Output.new(:prettyprint => true).prettyprint.should be_true
53
+ Erector::Output.new(:prettyprint => false).prettyprint.should be_false
54
+ end
55
+
56
+ it "accepts the global prettyprint_default setting" do
57
+ old_default = Erector::Widget.new.prettyprint_default
58
+ begin
59
+ Erector::Widget.prettyprint_default = true
60
+ Erector::Output.new.prettyprint.should be_true
61
+ Erector::Widget.prettyprint_default = false
62
+ Erector::Output.new.prettyprint.should be_false
63
+ ensure
64
+ Erector::Widget.prettyprint_default = old_default
65
+ end
66
+ end
67
+
68
+ describe '#newline' do
69
+ it "inserts a newline if we're in prettyprint mode" do
70
+ @output = Output.new(:prettyprint => true)
71
+ @output << "foo"
72
+ @output.newline
73
+ @output.should be_at_line_start
74
+ @output.to_s.should == "foo\n"
75
+ end
76
+
77
+ it "tracks whether we're at the beginning of a line or not" do
78
+ @output = Output.new(:prettyprint => true)
79
+ @output.should be_at_line_start
80
+ @output << "foo"
81
+ @output.should_not be_at_line_start
82
+ @output.newline
83
+ @output.should be_at_line_start
84
+ @output << "bar"
85
+ @output.should_not be_at_line_start
86
+ @output.newline
87
+ @output.should be_at_line_start
88
+ end
89
+
90
+ it "doesn't insert a newline (or track line starts) if we're not in prettyprint mode" do
91
+ @output = Output.new(:prettyprint => false)
92
+ @output << "foo"
93
+ @output.newline
94
+ @output.should_not be_at_line_start
95
+ @output.to_s.should == "foo"
96
+ end
97
+ end
98
+
99
+ describe "pretty printing" do
100
+ before do
101
+ @output = Output.new(:prettyprint => true)
102
+ end
103
+
104
+ it "indents the next line when we're at line start and indented" do
105
+ @output << "foo"
106
+ @output.newline
107
+ @output.indent
108
+ @output << "bar"
109
+ @output.newline
110
+ @output.undent
111
+ @output << "baz"
112
+ @output.newline
113
+
114
+ @output.to_s.should == "foo\n bar\nbaz\n"
115
+ end
116
+
117
+ it "doesn't indent if there's a linebreak in the middle of a string" do
118
+ @output.indent
119
+ @output << "foo\nbar\nbaz\n"
120
+ @output.to_s.should == " foo\nbar\nbaz\n"
121
+ end
122
+
123
+ it "turns off if prettyprint is false" do
124
+ @output = Output.new(:prettyprint => false)
125
+ @output.indent
126
+ @output << "bar"
127
+ @output.to_s.should == "bar"
128
+ end
129
+
130
+ it "doesn't crash if indentation level is less than 0" do
131
+ @output.undent
132
+ @output << "bar"
133
+ @output.to_s.should == "bar"
134
+ # [@indentation, 0].max
135
+ end
136
+
137
+ it "accepts an initial indentation level" do
138
+ @output = Output.new(:prettyprint => true, :indentation => 2)
139
+ @output << "foo"
140
+ @output.to_s.should == " foo"
141
+ end
142
+
143
+ it "accepts a max line length" do
144
+ @output = Output.new(:prettyprint => true, :max_length => 10)
145
+ @output << "Now is the winter of our discontent made "
146
+ @output << "glorious summer by this sun of York."
147
+ @output.to_s.should ==
148
+ "Now is the\n" +
149
+ "winter of\n" +
150
+ "our\n" +
151
+ "discontent\n" +
152
+ "made \n" +
153
+ "glorious\n" +
154
+ "summer by\n" +
155
+ "this sun\n" +
156
+ "of York."
157
+ end
158
+
159
+ it "preserves leading and trailing spaces" do
160
+ @output = Output.new(:max_length => 10)
161
+ @output << "123456789"
162
+ @output << " foo "
163
+ @output << "bar"
164
+ @output.to_s.should == "123456789 \nfoo bar"
165
+ end
166
+
167
+ it "accepts a max line length wth indentation" do
168
+ # note that 1 indent = 2 spaces
169
+ @output = Output.new(:prettyprint => true, :indentation => 1, :max_length => 10)
170
+ @output << "Now is the winter of our discontent made glorious summer by this sun of York."
171
+ @output.to_s.should ==
172
+ " Now is\n" +
173
+ " the\n" +
174
+ " winter\n" +
175
+ " of our\n" +
176
+ " discontent\n" +
177
+ " made\n" +
178
+ " glorious\n" +
179
+ " summer\n" +
180
+ " by this\n" +
181
+ " sun of\n" +
182
+ " York."
183
+ end
184
+
185
+ end
186
+
187
+ class Puppy < Erector::Widget
188
+ end
189
+ class Kitten < Erector::Widget
190
+ end
191
+
192
+ it "can keep track of widget classes emitted to it" do
193
+ @output.widgets << Puppy
194
+ @output.widgets << Kitten
195
+ @output.widgets << Puppy
196
+ @output.widgets.to_a.should include_only [Puppy, Kitten]
197
+ end
198
+ end
199
+ end