garterbelt 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +38 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +21 -0
- data/Rakefile +46 -0
- data/TODO +3 -0
- data/VERSION +1 -0
- data/garterbelt.gemspec +165 -0
- data/lib/garterbelt.rb +23 -0
- data/lib/page.rb +46 -0
- data/lib/renderers/cache.rb +35 -0
- data/lib/renderers/closed_tag.rb +60 -0
- data/lib/renderers/comment.rb +14 -0
- data/lib/renderers/content_rendering.rb +41 -0
- data/lib/renderers/content_tag.rb +36 -0
- data/lib/renderers/doctype.rb +24 -0
- data/lib/renderers/renderer.rb +33 -0
- data/lib/renderers/text.rb +28 -0
- data/lib/renderers/xml.rb +9 -0
- data/lib/stocking.rb +11 -0
- data/lib/support/string.rb +165 -0
- data/lib/view.rb +341 -0
- data/spec/benchmark/templates/erector.rb +37 -0
- data/spec/benchmark/templates/garterbelt.rb +37 -0
- data/spec/benchmark/vs_erector.rb +53 -0
- data/spec/garterbelt_spec.rb +49 -0
- data/spec/integration/expectations/general_view.html +17 -0
- data/spec/integration/expectations/variables/view_with_user_and_params.html +23 -0
- data/spec/integration/expectations/variables/view_with_user_email.html +23 -0
- data/spec/integration/expectations/view_partial_nest.html +24 -0
- data/spec/integration/expectations/view_with_tags.html +19 -0
- data/spec/integration/templates/view_partial_nest.rb +22 -0
- data/spec/integration/templates/view_with_cache.rb +30 -0
- data/spec/integration/templates/view_with_partial.rb +36 -0
- data/spec/integration/templates/view_with_partial_2.rb +36 -0
- data/spec/integration/templates/view_with_tags.rb +26 -0
- data/spec/integration/templates/view_with_vars.rb +32 -0
- data/spec/integration/view_spec.rb +57 -0
- data/spec/page_spec.rb +99 -0
- data/spec/renderers/cache_spec.rb +85 -0
- data/spec/renderers/closed_tag_spec.rb +172 -0
- data/spec/renderers/comment_spec.rb +68 -0
- data/spec/renderers/content_tag_spec.rb +150 -0
- data/spec/renderers/doctype_spec.rb +46 -0
- data/spec/renderers/text_spec.rb +68 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/support/mock_view.rb +14 -0
- data/spec/support/puters.rb +10 -0
- data/spec/view/view_basics_spec.rb +106 -0
- data/spec/view/view_caching_spec.rb +132 -0
- data/spec/view/view_partial_spec.rb +63 -0
- data/spec/view/view_rails_type_helpers.rb +148 -0
- data/spec/view/view_render_spec.rb +408 -0
- data/spec/view/view_variables_spec.rb +159 -0
- metadata +367 -0
@@ -0,0 +1,172 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Garterbelt::ClosedTag do
|
4
|
+
ClosedTag = Garterbelt::ClosedTag unless defined?(ClosedTag)
|
5
|
+
|
6
|
+
before do
|
7
|
+
@output = ''
|
8
|
+
@view = mock(:output => @output, :level => 2)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'initialize' do
|
12
|
+
it 'requires a type' do
|
13
|
+
lambda{ ClosedTag.new({:view => @view}) }.should raise_error(ArgumentError, ":type required in initialization options")
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'requires a view' do
|
17
|
+
lambda{ ClosedTag.new({:type => :input}) }.should raise_error(ArgumentError, ":view required in initialization options")
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'store the type as an attribute' do
|
21
|
+
ClosedTag.new({:type => :input, :view => @view}).type.should == :input
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'attributes should be empty by default' do
|
25
|
+
ClosedTag.new(:type => :input, :view => @view).attributes.should == {}
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'sets the attributes' do
|
29
|
+
ClosedTag.new(:type => :input, :attributes => {:foo => :bar}, :view => @view).attributes.should == {:foo => :bar}
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'extracts css_class into its own variable' do
|
33
|
+
ClosedTag.new(:type => :input, :attributes => {:class => :foo}, :view => @view).css_class.should == [:foo]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'pooling' do
|
38
|
+
it 'include RuPol::Swimsuit' do
|
39
|
+
ClosedTag.ancestors.should include(RuPol::Swimsuit)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'has a really large max_pool_size' do
|
43
|
+
ClosedTag._pool.max_size.should == 10000
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'method chaining' do
|
48
|
+
before do
|
49
|
+
@tag = ClosedTag.new(:type => :input, :view => @view)
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#id' do
|
53
|
+
it 'adds an id attribute' do
|
54
|
+
@tag.id(:foo).attributes[:id].should == :foo
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'raises an argument error if passed an array or something non-stringy' do
|
58
|
+
lambda{ @tag.id([:foo, :bar]) }.should raise_error(ArgumentError, "Id must be a String or Symbol")
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'returns self' do
|
62
|
+
@tag.id(:foo).should === @tag
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#c' do
|
67
|
+
it 'adds the value to the css_class' do
|
68
|
+
@tag.c(:foo).css_class.should == [:foo]
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'will not overwrite existing css classes' do
|
72
|
+
@tag.c(:foo).css_class.should == [:foo]
|
73
|
+
@tag.c(:bar).css_class.should == [:foo, :bar]
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'takes any number of arguments' do
|
77
|
+
@tag.c(:foo, :bar).css_class.should == [:foo, :bar]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns self' do
|
81
|
+
@tag.c(:foo, :bar).should === @tag
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'view usage' do
|
87
|
+
before do
|
88
|
+
@tag = ClosedTag.new(:type => :input, :view => @view)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'uses its output' do
|
92
|
+
@tag.output.should == @output
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'uses its level' do
|
96
|
+
@tag.level.should == 2
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
describe 'rendering' do
|
102
|
+
before do
|
103
|
+
@tag = ClosedTag.new(
|
104
|
+
:type => :input,
|
105
|
+
:attributes => {:class => :foo_bar, :thing => :thong},
|
106
|
+
:view => @view
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'indent corresponding to the view level' do
|
111
|
+
@tag.indent.should == " "
|
112
|
+
@tag.stub(:level).and_return(1)
|
113
|
+
@tag.indent.should == " "
|
114
|
+
@tag.stub(:level).and_return(0)
|
115
|
+
@tag.indent.should == ""
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '#rendered_attributes' do
|
119
|
+
it 'includes the css_class' do
|
120
|
+
@tag.rendered_attributes.should include "class=\"foo_bar\""
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'multiple classes are separated by a space' do
|
124
|
+
@tag.c(:more_classy)
|
125
|
+
@tag.rendered_attributes.should include "class=\"foo_bar more_classy\""
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'include other key/value pairs' do
|
129
|
+
@tag.rendered_attributes.should include "thing=\"thong\""
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'does not include attributes with nil or false values' do
|
133
|
+
@tag.attributes[:checked] = false
|
134
|
+
@tag.attributes[:nily] = nil
|
135
|
+
rendered = @tag.rendered_attributes
|
136
|
+
rendered.should_not include "checked=\"\""
|
137
|
+
rendered.should_not include "nily=\"\""
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should subs out double quotes from attributes' do
|
141
|
+
@tag.attributes[:foo_title] = 'I am not "sure" if this will work'
|
142
|
+
@tag.rendered_attributes.should include "I am not 'sure' if this will work"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe 'integration' do
|
147
|
+
before do
|
148
|
+
@str = @tag.render
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'starts with the indent' do
|
152
|
+
@str.should match /^\W{4}</
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'includes the full tag' do
|
156
|
+
@str.should match /<input[^>]*>/
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'includes the attributes' do
|
160
|
+
@str.should match /<input#{@tag.rendered_attributes}>/
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'ends with the closing tag and a line break' do
|
164
|
+
@str.should match /\n$/
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'adds the string to the output' do
|
168
|
+
@output.should include @str
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Garterbelt::Comment do
|
4
|
+
before :all do
|
5
|
+
@view = MockView.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'basics' do
|
9
|
+
it 'is decends from Renderer' do
|
10
|
+
Garterbelt::Comment.ancestors.should include Garterbelt::Renderer
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has conent' do
|
14
|
+
comment = Garterbelt::Comment.new(:view => @view, :content => "Initializing ...")
|
15
|
+
comment.content.should == "Initializing ..."
|
16
|
+
comment.content = "foo"
|
17
|
+
comment.content.should == "foo"
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'raises an error when initializing without content' do
|
21
|
+
lambda{ Garterbelt::Comment.new(:view => @view) }.should raise_error(
|
22
|
+
ArgumentError, ":content option required for Garterbelt::Comment initialization"
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'has a smaller pool size' do
|
27
|
+
Garterbelt::Comment._pool.max_size.should == 1000
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'render' do
|
32
|
+
before do
|
33
|
+
@view = MockView.new
|
34
|
+
@comment = Garterbelt::Comment.new(:view => @view, :content => 'Render me')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'raises an error with block content' do
|
38
|
+
@comment.content = lambda { puts "foo" }
|
39
|
+
lambda{ @comment.render }.should raise_error(ArgumentError, "Garterbelt::Comment does not take block content")
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'it adds the content to the output' do
|
43
|
+
@comment.render
|
44
|
+
@view.output.should include "Render me"
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'builds the right header tag' do
|
48
|
+
@comment.render
|
49
|
+
@view.output.should match /<!-- Render me/
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'builds the right footer tag' do
|
53
|
+
@comment.render
|
54
|
+
@view.output.should match /Render me -->/
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'indents to the view level' do
|
58
|
+
@comment.render
|
59
|
+
@view.output.should match /^\W{4}<!-- Render me/
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'does not escape the content' do
|
63
|
+
@comment.content = "<div>foo</div>"
|
64
|
+
@comment.render
|
65
|
+
@view.output.should include "<div>foo</div>"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Garterbelt::ContentTag do
|
4
|
+
ContentTag = Garterbelt::ContentTag unless defined?(ContentTag)
|
5
|
+
|
6
|
+
before do
|
7
|
+
@view = MockView.new
|
8
|
+
@output = @view.output
|
9
|
+
@params = {:type => :p, :attributes => {:class => 'classy'}, :view => @view}
|
10
|
+
@tag = ContentTag.new(@params)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "basics" do
|
14
|
+
it 'takes a content option' do
|
15
|
+
ContentTag.new(@params.merge(:content => 'My great content')).content.should == "My great content"
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'takes a block as content' do
|
19
|
+
ContentTag.new(@params) do
|
20
|
+
@output << "This is block content"
|
21
|
+
end.content.class.should == Proc
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'will override option content in favor of block content' do
|
25
|
+
ContentTag.new(@params.merge(:content => 'not the block')) do
|
26
|
+
@output << "This is block content"
|
27
|
+
end.content.class.should == Proc
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'inherits a really large max_pool_size' do
|
31
|
+
ContentTag._pool.max_size.should == 10000
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'chaining' do
|
36
|
+
describe 'id' do
|
37
|
+
it 'takes a block and sets it to content' do
|
38
|
+
@tag.id(:foo) do
|
39
|
+
@output << "This is block content"
|
40
|
+
end
|
41
|
+
@tag.content.class.should == Proc
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns self' do
|
45
|
+
@tag.id(:foo).should === @tag
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'c' do
|
50
|
+
it 'takes a block and sets it to content' do
|
51
|
+
@tag.c(:foo) do
|
52
|
+
@output << "This is block content"
|
53
|
+
end
|
54
|
+
@tag.content.class.should == Proc
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns self' do
|
58
|
+
@tag.c(:foo).should === @tag
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'rendering' do
|
64
|
+
describe 'tags' do
|
65
|
+
before do
|
66
|
+
@tag.content = 'My string content'
|
67
|
+
@tag.render
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'indents the beginning tag correctly' do
|
71
|
+
@output.should match /^ <p/
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'renders the beginning tag correctly' do
|
75
|
+
@output.should include "<p class=\"classy\">"
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'indents the ending tag correctly' do
|
79
|
+
@output.should match /^ <\/p/
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'renders the ending tag correctly' do
|
83
|
+
@output.should include "</p>"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'content' do
|
88
|
+
describe 'none' do
|
89
|
+
it 'works' do
|
90
|
+
@tag.content.should be_nil
|
91
|
+
@tag.render
|
92
|
+
@output.should match " <p class=\"classy\">\n </p>"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'string' do
|
97
|
+
before do
|
98
|
+
@tag.content = "My string content"
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'makes a Text object' do
|
102
|
+
Garterbelt::Text.should_receive(:new).and_return('text')
|
103
|
+
@tag.render
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'block' do
|
108
|
+
describe 'writing directly to output' do
|
109
|
+
before do
|
110
|
+
@tag.id(:foo) do
|
111
|
+
@output << "Going directly to the source"
|
112
|
+
end
|
113
|
+
@tag.render
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'adds the content' do
|
117
|
+
@output.should include "Going directly to the source"
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'does not indent' do
|
121
|
+
@output.should match /^Going/
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should put the content between the tags' do
|
125
|
+
@output.should match /<p.*\nGoing.*<\/p/
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe 'adding to the tag buffer' do
|
130
|
+
before do
|
131
|
+
@b = Garterbelt::ClosedTag.new(:view => @view, :type => :hr, :attributes => {:class => :linear})
|
132
|
+
@tag.id(:foo) do
|
133
|
+
@view.buffer << @b
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should add the tag to the buffer' do
|
138
|
+
@tag.render
|
139
|
+
@view.buffer.should include @b
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'calls render buffer on the view' do
|
143
|
+
@view.should_receive(:render_buffer)
|
144
|
+
@tag.render
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Garterbelt::Doctype do
|
4
|
+
before :all do
|
5
|
+
@view = MockView.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'basics' do
|
9
|
+
it 'is decends from ClosedTag' do
|
10
|
+
Garterbelt::Doctype.ancestors.should include Garterbelt::ClosedTag
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has a smaller pool size' do
|
14
|
+
Garterbelt::Doctype._pool.max_size.should == 1000
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'render' do
|
19
|
+
before do
|
20
|
+
@view = MockView.new
|
21
|
+
@doctype = Garterbelt::Doctype.new(:view => @view, :type => :transitional)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'builds the right tag for type = :transitional' do
|
25
|
+
tag = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
|
26
|
+
@doctype.render.should include tag
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'builds the right tag for type = :strict' do
|
30
|
+
tag = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
|
31
|
+
@doctype.type = :strict
|
32
|
+
@doctype.render.should include tag
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'builds the right tag for type = :html5' do
|
36
|
+
tag = '<!DOCTYPE html>'
|
37
|
+
@doctype.type = :html5
|
38
|
+
@doctype.render.should include tag
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'indents to the view level' do
|
42
|
+
@doctype.render
|
43
|
+
@view.output.should match /^\W{4}<!DOCTYPE/
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Garterbelt::Text do
|
4
|
+
before :all do
|
5
|
+
@view = MockView.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'basics' do
|
9
|
+
it 'is decends from Renderer' do
|
10
|
+
Garterbelt::Text.ancestors.should include Garterbelt::Renderer
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'has conent' do
|
14
|
+
text = Garterbelt::Text.new(:view => @view, :content => "Initializing ...")
|
15
|
+
text.content.should == "Initializing ..."
|
16
|
+
text.content = "foo"
|
17
|
+
text.content.should == "foo"
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'raises an error when initializing without content' do
|
21
|
+
lambda{ Garterbelt::Text.new(:view => @view) }.should raise_error(
|
22
|
+
ArgumentError, ":content option required for Garterbelt::Text initialization"
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'inherits its pool size' do
|
27
|
+
Garterbelt::Text._pool.max_size.should == 10000
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'render' do
|
32
|
+
before do
|
33
|
+
@view = MockView.new
|
34
|
+
@text = Garterbelt::Text.new(:view => @view, :content => 'Render me')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'raises an error with block content' do
|
38
|
+
@text.content = lambda { puts "foo" }
|
39
|
+
lambda{ @text.render }.should raise_error(ArgumentError, "Garterbelt::Text does not take block content")
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'it adds the content to the output' do
|
43
|
+
@text.render
|
44
|
+
@view.output.should include "Render me"
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'indents to the view level' do
|
48
|
+
@text.render
|
49
|
+
@view.output.should match /^\W{4}Render me\n$/
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'escaping' do
|
53
|
+
it 'escapes if view is set to escape' do
|
54
|
+
str = "<a href='/foo.com'>Foo it!</a>"
|
55
|
+
text = Garterbelt::Text.new(:view => @view, :content => str)
|
56
|
+
text.render.should_not include str
|
57
|
+
text.render.should include ERB::Util.html_escape(str)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'does not escape if the view is set to not escape' do
|
61
|
+
str = "<a href='/foo.com'>Foo it!</a>"
|
62
|
+
@view.escape = false
|
63
|
+
text = Garterbelt::Text.new(:view => @view, :content => str)
|
64
|
+
text.render.should include str
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
require 'rspec'
|
7
|
+
require 'hashie'
|
8
|
+
require 'garterbelt'
|
9
|
+
|
10
|
+
# Requires supporting files with custom matchers and macros, etc,
|
11
|
+
# in ./support/ and its subdirectories.
|
12
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
13
|
+
Dir["#{File.dirname(__FILE__)}/integration/templates/**/*.rb"].each {|f| require f}
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
include PutSpec
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class MockView
|
2
|
+
attr_accessor :output, :buffer, :level, :escape, :cache_store
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
self.buffer = []
|
6
|
+
self.output = ""
|
7
|
+
self.level ||= 2
|
8
|
+
self.escape = true
|
9
|
+
self.cache_store = Moneta::Memory.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def render_buffer
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Garterbelt::View do
|
4
|
+
class BasicView < Garterbelt::View
|
5
|
+
def content
|
6
|
+
end
|
7
|
+
|
8
|
+
def alt_content
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
before do
|
13
|
+
@view = BasicView.new
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'pooling' do
|
17
|
+
it 'includes the swimsuit' do
|
18
|
+
BasicView.ancestors.should include( RuPol::Swimsuit )
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'attributes' do
|
23
|
+
it 'has a tag buffer' do
|
24
|
+
@view.buffer.should == []
|
25
|
+
@tag = Garterbelt::ContentTag.new(:view => @view, :type => :hr)
|
26
|
+
@view.buffer << @tag
|
27
|
+
@view.buffer.should == [@tag]
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'output' do
|
31
|
+
it 'has an output' do
|
32
|
+
@view.output.should == ""
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'its output is that of the curator if the curator is not self' do
|
36
|
+
BasicView.new(:curator => @view).output.should === @view.output
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'escape' do
|
41
|
+
it 'has escape set to true by default' do
|
42
|
+
@view.escape.should == true
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'can be set' do
|
46
|
+
@view.escape = false
|
47
|
+
@view.escape.should == false
|
48
|
+
BasicView.new(:escape => false).escape.should == false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'level' do
|
53
|
+
it 'is 0 by default' do
|
54
|
+
@view.level.should == 0
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'can be set via initialization' do
|
58
|
+
BasicView.new(:level => 42).level.should == 42
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'setting the curator: view responsible for displaying the rendered content' do
|
63
|
+
before do
|
64
|
+
@view.level = 42
|
65
|
+
@view.output = "foo"
|
66
|
+
@view.buffer = ["bar"]
|
67
|
+
@view.escape = false
|
68
|
+
@child = BasicView.new(:curator => @view)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'is self by default' do
|
72
|
+
@view.curator.should == @view
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'can be set' do
|
76
|
+
@view.curator = BasicView.new
|
77
|
+
@view.curator.should_not == @view
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'can be intialized in' do
|
81
|
+
BasicView.new(:curator => @view).curator.should == @view
|
82
|
+
end
|
83
|
+
|
84
|
+
describe 'resets other attributes' do
|
85
|
+
it 'sets the output to the curator\'s' do
|
86
|
+
@child.output.should === @view.output
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'sets the level to the curator\'s' do
|
90
|
+
@child.level.should == @view.level
|
91
|
+
@child.level.should == 42
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'sets the buffer to the curator\'s' do
|
95
|
+
@child.buffer.should === @view.buffer
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'sets the escape to the curator\'s' do
|
99
|
+
@child.escape.should == @view.escape
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|