inversion 0.12.3 → 0.14.0
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -1
- data.tar.gz.sig +0 -0
- data/ChangeLog +305 -9
- data/Examples.rdoc +134 -0
- data/GettingStarted.rdoc +44 -0
- data/Guide.rdoc +47 -0
- data/History.rdoc +15 -0
- data/Manifest.txt +7 -2
- data/README.rdoc +9 -10
- data/Rakefile +23 -10
- data/Tags.rdoc +561 -0
- data/lib/inversion.rb +2 -2
- data/lib/inversion/renderstate.rb +46 -11
- data/lib/inversion/template.rb +85 -7
- data/lib/inversion/template/attrtag.rb +1 -1
- data/lib/inversion/template/begintag.rb +8 -8
- data/lib/inversion/template/fragmenttag.rb +60 -0
- data/lib/inversion/template/rescuetag.rb +1 -1
- data/spec/{lib/helpers.rb → helpers.rb} +7 -30
- data/spec/inversion/mixins_spec.rb +55 -65
- data/spec/inversion/monkeypatches_spec.rb +2 -12
- data/spec/inversion/parser_spec.rb +34 -44
- data/spec/inversion/renderstate_spec.rb +123 -69
- data/spec/inversion/sinatra_spec.rb +6 -19
- data/spec/inversion/template/attrtag_spec.rb +56 -76
- data/spec/inversion/template/begintag_spec.rb +24 -41
- data/spec/inversion/template/calltag_spec.rb +1 -18
- data/spec/inversion/template/codetag_spec.rb +6 -24
- data/spec/inversion/template/commenttag_spec.rb +9 -27
- data/spec/inversion/template/configtag_spec.rb +5 -16
- data/spec/inversion/template/containertag_spec.rb +4 -21
- data/spec/inversion/template/defaulttag_spec.rb +6 -23
- data/spec/inversion/template/elsetag_spec.rb +9 -26
- data/spec/inversion/template/elsiftag_spec.rb +7 -24
- data/spec/inversion/template/endtag_spec.rb +6 -23
- data/spec/inversion/template/escapetag_spec.rb +10 -25
- data/spec/inversion/template/fortag_spec.rb +20 -37
- data/spec/inversion/template/fragmenttag_spec.rb +40 -0
- data/spec/inversion/template/iftag_spec.rb +23 -40
- data/spec/inversion/template/importtag_spec.rb +8 -25
- data/spec/inversion/template/includetag_spec.rb +27 -42
- data/spec/inversion/template/node_spec.rb +6 -15
- data/spec/inversion/template/pptag_spec.rb +10 -23
- data/spec/inversion/template/publishtag_spec.rb +4 -21
- data/spec/inversion/template/rescuetag_spec.rb +12 -29
- data/spec/inversion/template/subscribetag_spec.rb +8 -25
- data/spec/inversion/template/tag_spec.rb +24 -37
- data/spec/inversion/template/textnode_spec.rb +8 -24
- data/spec/inversion/template/timedeltatag_spec.rb +31 -43
- data/spec/inversion/template/unlesstag_spec.rb +7 -24
- data/spec/inversion/template/uriencodetag_spec.rb +6 -23
- data/spec/inversion/template/yieldtag_spec.rb +3 -20
- data/spec/inversion/template_spec.rb +155 -108
- data/spec/inversion/tilt_spec.rb +7 -16
- data/spec/inversion_spec.rb +7 -22
- metadata +63 -40
- metadata.gz.sig +0 -0
- data/spec/lib/constants.rb +0 -9
@@ -1,31 +1,14 @@
|
|
1
1
|
#!/usr/bin/env rspec -cfd -b
|
2
2
|
# vim: set noet nosta sw=4 ts=4 :
|
3
3
|
|
4
|
-
|
5
|
-
require 'pathname'
|
6
|
-
basedir = Pathname( __FILE__ ).dirname.parent.parent.parent
|
7
|
-
libdir = basedir + 'lib'
|
4
|
+
require_relative '../../helpers'
|
8
5
|
|
9
|
-
$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
|
10
|
-
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
11
|
-
}
|
12
|
-
|
13
|
-
require 'rspec'
|
14
|
-
require 'spec/lib/helpers'
|
15
6
|
require 'inversion/template/unlesstag'
|
16
7
|
require 'inversion/template/textnode'
|
17
8
|
require 'inversion/renderstate'
|
18
9
|
|
19
10
|
describe Inversion::Template::UnlessTag do
|
20
11
|
|
21
|
-
before( :all ) do
|
22
|
-
setup_logging( :fatal )
|
23
|
-
end
|
24
|
-
|
25
|
-
after( :all ) do
|
26
|
-
reset_logging()
|
27
|
-
end
|
28
|
-
|
29
12
|
|
30
13
|
it "renders its contents if its attribute is false" do
|
31
14
|
tag = Inversion::Template::UnlessTag.new( 'attribute' )
|
@@ -33,7 +16,7 @@ describe Inversion::Template::UnlessTag do
|
|
33
16
|
|
34
17
|
renderstate = Inversion::RenderState.new( :attribute => false )
|
35
18
|
tag.render( renderstate )
|
36
|
-
renderstate.to_s.
|
19
|
+
expect( renderstate.to_s ).to eq( 'the body' )
|
37
20
|
end
|
38
21
|
|
39
22
|
it "renders its contents if its methodchain is false" do
|
@@ -42,7 +25,7 @@ describe Inversion::Template::UnlessTag do
|
|
42
25
|
|
43
26
|
renderstate = Inversion::RenderState.new( :attribute => {:bar => 1} )
|
44
27
|
tag.render( renderstate )
|
45
|
-
renderstate.to_s.
|
28
|
+
expect( renderstate.to_s ).to eq( 'the body' )
|
46
29
|
end
|
47
30
|
|
48
31
|
it "doesn't render its contents if its attribute is true" do
|
@@ -51,7 +34,7 @@ describe Inversion::Template::UnlessTag do
|
|
51
34
|
|
52
35
|
renderstate = Inversion::RenderState.new( :attribute => true )
|
53
36
|
tag.render( renderstate )
|
54
|
-
renderstate.to_s.
|
37
|
+
expect( renderstate.to_s ).to eq( '' )
|
55
38
|
end
|
56
39
|
|
57
40
|
it "doesn't render its contents if its methodchain is true" do
|
@@ -60,7 +43,7 @@ describe Inversion::Template::UnlessTag do
|
|
60
43
|
|
61
44
|
renderstate = Inversion::RenderState.new( :attribute => {:foo => 1} )
|
62
45
|
tag.render( renderstate )
|
63
|
-
renderstate.to_s.
|
46
|
+
expect( renderstate.to_s ).to eq( '' )
|
64
47
|
end
|
65
48
|
|
66
49
|
context "with an 'else' clause" do
|
@@ -76,13 +59,13 @@ describe Inversion::Template::UnlessTag do
|
|
76
59
|
it "only renders the second half of the contents if its attribute is true" do
|
77
60
|
renderstate = Inversion::RenderState.new( :attribute => true )
|
78
61
|
@tag.render( renderstate )
|
79
|
-
renderstate.to_s.
|
62
|
+
expect( renderstate.to_s ).to eq( 'the body after else' )
|
80
63
|
end
|
81
64
|
|
82
65
|
it "only renders the first half of the contents if its attribute is false" do
|
83
66
|
renderstate = Inversion::RenderState.new( :attribute => false )
|
84
67
|
@tag.render( renderstate )
|
85
|
-
renderstate.to_s.
|
68
|
+
expect( renderstate.to_s ).to eq( 'the body before else' )
|
86
69
|
end
|
87
70
|
|
88
71
|
end
|
@@ -1,49 +1,32 @@
|
|
1
1
|
#!/usr/bin/env rspec -cfd -b
|
2
2
|
# vim: set noet nosta sw=4 ts=4 :
|
3
3
|
|
4
|
-
|
5
|
-
require 'pathname'
|
6
|
-
basedir = Pathname( __FILE__ ).dirname.parent.parent.parent
|
7
|
-
libdir = basedir + 'lib'
|
4
|
+
require_relative '../../helpers'
|
8
5
|
|
9
|
-
$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
|
10
|
-
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
11
|
-
}
|
12
|
-
|
13
|
-
require 'rspec'
|
14
|
-
require 'spec/lib/helpers'
|
15
6
|
require 'inversion/template/uriencodetag'
|
16
7
|
|
17
8
|
describe Inversion::Template::UriencodeTag do
|
18
9
|
|
19
|
-
before( :all ) do
|
20
|
-
setup_logging( :fatal )
|
21
|
-
end
|
22
|
-
|
23
|
-
after( :all ) do
|
24
|
-
reset_logging()
|
25
|
-
end
|
26
|
-
|
27
10
|
before( :each ) do
|
28
|
-
@attribute_object =
|
11
|
+
@attribute_object = double( "template attribute" )
|
29
12
|
end
|
30
13
|
|
31
14
|
|
32
15
|
it "URI encodes the results of rendering" do
|
33
16
|
template = Inversion::Template.new( 'this is<?uriencode foo.bar ?>' )
|
34
17
|
template.foo = @attribute_object
|
35
|
-
@attribute_object.
|
18
|
+
expect( @attribute_object ).to receive( :bar ).with( no_args() ).
|
36
19
|
and_return( " 25% Sparta!" )
|
37
20
|
|
38
|
-
template.render.
|
21
|
+
expect( template.render ).to eq( "this is%2025%25%20Sparta%21" )
|
39
22
|
end
|
40
23
|
|
41
24
|
it "stringifies its content before encoding" do
|
42
25
|
template = Inversion::Template.new( '<?uriencode foo.bar ?> bottles of beer on the wall' )
|
43
26
|
template.foo = @attribute_object
|
44
|
-
@attribute_object.
|
27
|
+
expect( @attribute_object ).to receive( :bar ).with( no_args() ).
|
45
28
|
and_return( 99.999 )
|
46
29
|
|
47
|
-
template.render.
|
30
|
+
expect( template.render ).to eq( "99.999 bottles of beer on the wall" )
|
48
31
|
end
|
49
32
|
end
|
@@ -1,29 +1,12 @@
|
|
1
1
|
#!/usr/bin/env rspec -cfd -b
|
2
2
|
# vim: set noet nosta sw=4 ts=4 :
|
3
3
|
|
4
|
-
|
5
|
-
require 'pathname'
|
6
|
-
basedir = Pathname( __FILE__ ).dirname.parent.parent.parent
|
7
|
-
libdir = basedir + 'lib'
|
4
|
+
require_relative '../../helpers'
|
8
5
|
|
9
|
-
$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
|
10
|
-
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
11
|
-
}
|
12
|
-
|
13
|
-
require 'rspec'
|
14
|
-
require 'spec/lib/helpers'
|
15
6
|
require 'inversion/template/yieldtag'
|
16
7
|
|
17
8
|
describe Inversion::Template::YieldTag do
|
18
9
|
|
19
|
-
before( :all ) do
|
20
|
-
setup_logging( :fatal )
|
21
|
-
end
|
22
|
-
|
23
|
-
after( :all ) do
|
24
|
-
reset_logging()
|
25
|
-
end
|
26
|
-
|
27
10
|
|
28
11
|
it "calls the renderstate's block before rendering, and renders as its return value" do
|
29
12
|
tag = Inversion::Template::YieldTag.new( '' )
|
@@ -36,7 +19,7 @@ describe Inversion::Template::YieldTag do
|
|
36
19
|
renderstate << tag
|
37
20
|
end
|
38
21
|
|
39
|
-
rendered_output.
|
22
|
+
expect( rendered_output ).to eq([ :return_value ])
|
40
23
|
end
|
41
24
|
|
42
25
|
it "renders as nothing if there wasn't a render block" do
|
@@ -48,7 +31,7 @@ describe Inversion::Template::YieldTag do
|
|
48
31
|
renderstate << tag
|
49
32
|
end
|
50
33
|
|
51
|
-
rendered_output.
|
34
|
+
expect( rendered_output ).to eq([ nil ])
|
52
35
|
end
|
53
36
|
|
54
37
|
end
|
@@ -1,48 +1,42 @@
|
|
1
1
|
#!/usr/bin/env rspec -cfd -b
|
2
2
|
# vim: set noet nosta sw=4 ts=4 :
|
3
3
|
|
4
|
-
|
5
|
-
require 'pathname'
|
6
|
-
basedir = Pathname( __FILE__ ).dirname.parent.parent
|
7
|
-
libdir = basedir + 'lib'
|
4
|
+
require_relative '../helpers'
|
8
5
|
|
9
|
-
$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
|
10
|
-
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
11
|
-
}
|
12
|
-
|
13
|
-
require 'rspec'
|
14
6
|
require 'stringio'
|
15
7
|
|
16
|
-
require 'spec/lib/helpers'
|
17
8
|
require 'inversion/template'
|
18
9
|
|
19
10
|
describe Inversion::Template do
|
20
11
|
|
21
|
-
|
22
|
-
setup_logging( :fatal )
|
23
|
-
end
|
12
|
+
context "created from a simple string" do
|
24
13
|
|
25
|
-
|
26
|
-
Inversion::Template.new( "a template" ).source.should == 'a template'
|
27
|
-
end
|
14
|
+
let( :template ) { described_class.new("a template") }
|
28
15
|
|
29
|
-
|
30
|
-
|
31
|
-
|
16
|
+
it "can be loaded from a String" do
|
17
|
+
expect( template.source ).to eq( 'a template' )
|
18
|
+
end
|
19
|
+
|
20
|
+
it "renders the source as-is if there are no instructions" do
|
21
|
+
expect( template.render ).to eq( 'a template' )
|
22
|
+
end
|
23
|
+
|
24
|
+
it "renders when stringified" do
|
25
|
+
expect( template.to_s ).to eq( 'a template' )
|
26
|
+
end
|
32
27
|
|
33
|
-
it "renders when stringified" do
|
34
|
-
Inversion::Template.new( "a template" ).to_s.should == 'a template'
|
35
28
|
end
|
36
29
|
|
30
|
+
|
37
31
|
it "calls before and after rendering hooks on all of its nodes when rendered" do
|
38
32
|
node = double( "fake node" )
|
39
33
|
parentstate = Inversion::RenderState.new( :foo => 'the merged stuff' )
|
40
|
-
tmpl =
|
34
|
+
tmpl = described_class.new( '' )
|
41
35
|
tmpl.node_tree << node
|
42
36
|
|
43
|
-
node.
|
44
|
-
node.
|
45
|
-
node.
|
37
|
+
expect( node ).to receive( :before_rendering ).with( an_instance_of(Inversion::RenderState) )
|
38
|
+
expect( node ).to receive( :render ).with( an_instance_of(Inversion::RenderState) )
|
39
|
+
expect( node ).to receive( :after_rendering ).with( an_instance_of(Inversion::RenderState) )
|
46
40
|
|
47
41
|
tmpl.render( parentstate )
|
48
42
|
end
|
@@ -50,12 +44,12 @@ describe Inversion::Template do
|
|
50
44
|
|
51
45
|
it "passes the block it was rendered with to its RenderState" do
|
52
46
|
node = double( "fake node", :before_rendering => nil, :after_rendering => nil )
|
53
|
-
tmpl =
|
47
|
+
tmpl = described_class.new( '' )
|
54
48
|
tmpl.node_tree << node
|
55
49
|
|
56
50
|
renderblock = Proc.new {}
|
57
|
-
node.
|
58
|
-
renderstate.block.
|
51
|
+
expect( node ).to receive( :render ) do |renderstate|
|
52
|
+
expect( renderstate.block ).to equal( renderblock )
|
59
53
|
end
|
60
54
|
|
61
55
|
tmpl.render( &renderblock )
|
@@ -63,24 +57,40 @@ describe Inversion::Template do
|
|
63
57
|
|
64
58
|
it "carries its global configuration to the parser" do
|
65
59
|
begin
|
66
|
-
orig_config =
|
67
|
-
|
60
|
+
orig_config = described_class.config
|
61
|
+
described_class.configure( :ignore_unknown_tags => false )
|
68
62
|
|
69
63
|
expect {
|
70
|
-
|
64
|
+
described_class.new( '<?rumple an unknown tag ?>' )
|
71
65
|
}.to raise_error( Inversion::ParseError, /unknown tag/i )
|
72
66
|
ensure
|
73
|
-
|
67
|
+
described_class.config = orig_config
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "carries its global configuration to per-template options" do
|
72
|
+
begin
|
73
|
+
orig_config = described_class.config
|
74
|
+
described_class.configure( :stat_delay => 300 )
|
75
|
+
|
76
|
+
template = described_class.new( 'hi!' )
|
77
|
+
expect( template.options[ :stat_delay ] ).to eq( 300 )
|
78
|
+
|
79
|
+
template = described_class.new( 'hi!', :stat_delay => 600 )
|
80
|
+
expect( template.options[ :stat_delay ] ).to eq( 600 )
|
81
|
+
ensure
|
82
|
+
described_class.config = orig_config
|
74
83
|
end
|
75
84
|
end
|
76
85
|
|
86
|
+
|
77
87
|
it "can make an human-readable string version of itself suitable for debugging" do
|
78
|
-
IO.
|
79
|
-
tmpl =
|
80
|
-
tmpl.inspect.
|
81
|
-
tmpl.inspect.
|
82
|
-
tmpl.inspect.
|
83
|
-
tmpl.inspect.
|
88
|
+
expect( IO ).to receive( :read ).with( '/tmp/inspect.tmpl' ).and_return( '<?attr foo ?>' )
|
89
|
+
tmpl = described_class.load( '/tmp/inspect.tmpl' )
|
90
|
+
expect( tmpl.inspect ).to match( /#{Regexp.escape(described_class.name)}/ )
|
91
|
+
expect( tmpl.inspect ).to match( %r{/tmp/inspect.tmpl} )
|
92
|
+
expect( tmpl.inspect ).to match( /attributes/ )
|
93
|
+
expect( tmpl.inspect ).to_not match( /node_tree/ )
|
84
94
|
end
|
85
95
|
|
86
96
|
it "includes the node tree in the inspected object if debugging is enabled" do
|
@@ -88,25 +98,25 @@ describe Inversion::Template do
|
|
88
98
|
debuglevel = $DEBUG
|
89
99
|
$DEBUG = true
|
90
100
|
|
91
|
-
tmpl =
|
92
|
-
tmpl.inspect.
|
101
|
+
tmpl = described_class.new( '<?attr something ?>' )
|
102
|
+
expect( tmpl.inspect ).to match( /node_tree/ )
|
93
103
|
ensure
|
94
104
|
$DEBUG = debuglevel
|
95
105
|
end
|
96
106
|
end
|
97
107
|
|
98
108
|
it "provides accessors for attributes that aren't identifiers in the template" do
|
99
|
-
tmpl =
|
109
|
+
tmpl = described_class.new( '' )
|
100
110
|
tmpl.foo = :bar
|
101
|
-
tmpl.foo.
|
111
|
+
expect( tmpl.foo ).to eq( :bar )
|
102
112
|
end
|
103
113
|
|
104
114
|
it "can pass an encoding option to IO.open through the template constructor" do
|
105
115
|
content = 'some stuff'.encode( 'utf-8' )
|
106
|
-
IO.
|
107
|
-
template =
|
116
|
+
expect( IO ).to receive( :read ).with( '/a/utf8/template.tmpl', encoding: 'utf-8' ).and_return( content )
|
117
|
+
template = described_class.load( '/a/utf8/template.tmpl', encoding: 'utf-8' )
|
108
118
|
|
109
|
-
template.render.encoding.
|
119
|
+
expect( template.render.encoding ).to eq( Encoding::UTF_8 )
|
110
120
|
end
|
111
121
|
|
112
122
|
|
@@ -115,30 +125,30 @@ describe Inversion::Template do
|
|
115
125
|
before( :each ) do
|
116
126
|
@timestamp = Time.now
|
117
127
|
content = 'file contents'.taint
|
118
|
-
IO.
|
119
|
-
@template =
|
128
|
+
allow( IO ).to receive( :read ).with( '/tmp/hooowat' ).and_return( content )
|
129
|
+
@template = described_class.load( '/tmp/hooowat' )
|
120
130
|
end
|
121
131
|
|
122
132
|
|
123
133
|
it "untaints template content loaded from a file" do
|
124
|
-
@template.source.
|
134
|
+
expect( @template.source ).to_not be_tainted()
|
125
135
|
end
|
126
136
|
|
127
137
|
it "can be reloaded" do
|
128
138
|
newcontent = 'changed file contents'.taint
|
129
|
-
IO.
|
139
|
+
expect( IO ).to receive( :read ).with( '/tmp/hooowat' ).and_return( newcontent )
|
130
140
|
@template.reload
|
131
|
-
@template.source.
|
141
|
+
expect( @template.source ).to eq( newcontent )
|
132
142
|
end
|
133
143
|
|
134
144
|
context "that hasn't changed since it was loaded" do
|
135
145
|
|
136
146
|
before( :each ) do
|
137
|
-
@template.source_file.
|
147
|
+
allow( @template.source_file ).to receive( :mtime ).and_return( @timestamp )
|
138
148
|
end
|
139
149
|
|
140
150
|
it "knows that it hasn't changed" do
|
141
|
-
@template.
|
151
|
+
expect( @template ).to_not be_changed()
|
142
152
|
end
|
143
153
|
|
144
154
|
context "with a stat delay" do
|
@@ -149,13 +159,13 @@ describe Inversion::Template do
|
|
149
159
|
|
150
160
|
it "returns unchanged if the delay time hasn't expired" do
|
151
161
|
@template.instance_variable_set( :@last_checked, @timestamp )
|
152
|
-
@template.
|
162
|
+
expect( @template ).to_not be_changed()
|
153
163
|
end
|
154
164
|
|
155
165
|
it "returns unchanged if the delay time has expired" do
|
156
|
-
@template.source_file.
|
166
|
+
expect( @template.source_file ).to receive( :mtime ).and_return( @timestamp - 30 )
|
157
167
|
@template.instance_variable_set( :@last_checked, @timestamp - 30 )
|
158
|
-
@template.
|
168
|
+
expect( @template ).to_not be_changed()
|
159
169
|
end
|
160
170
|
end
|
161
171
|
end
|
@@ -163,11 +173,11 @@ describe Inversion::Template do
|
|
163
173
|
context "that has changed since it was loaded" do
|
164
174
|
|
165
175
|
before( :each ) do
|
166
|
-
@template.source_file.
|
176
|
+
allow( @template.source_file ).to receive( :mtime ).and_return( @timestamp + 1 )
|
167
177
|
end
|
168
178
|
|
169
179
|
it "knows that is has changed" do
|
170
|
-
@template.
|
180
|
+
expect( @template ).to be_changed()
|
171
181
|
end
|
172
182
|
|
173
183
|
context "with a stat delay" do
|
@@ -178,12 +188,12 @@ describe Inversion::Template do
|
|
178
188
|
|
179
189
|
it "returns unchanged if the delay time hasn't expired" do
|
180
190
|
@template.instance_variable_set( :@last_checked, @timestamp )
|
181
|
-
@template.
|
191
|
+
expect( @template ).to_not be_changed()
|
182
192
|
end
|
183
193
|
|
184
194
|
it "returns changed if the delay time has expired" do
|
185
195
|
@template.instance_variable_set( :@last_checked, @timestamp - 60 )
|
186
|
-
@template.
|
196
|
+
expect( @template ).to be_changed()
|
187
197
|
end
|
188
198
|
end
|
189
199
|
end
|
@@ -193,11 +203,11 @@ describe Inversion::Template do
|
|
193
203
|
context "loaded from a String" do
|
194
204
|
|
195
205
|
before( :each ) do
|
196
|
-
@template =
|
206
|
+
@template = described_class.new( 'some stuff' )
|
197
207
|
end
|
198
208
|
|
199
209
|
it "never says it has changed" do
|
200
|
-
@template.
|
210
|
+
expect( @template ).to_not be_changed()
|
201
211
|
end
|
202
212
|
|
203
213
|
it "raises an exception if reloaded" do
|
@@ -213,19 +223,19 @@ describe Inversion::Template do
|
|
213
223
|
context "without template paths set" do
|
214
224
|
|
215
225
|
before( :each ) do
|
216
|
-
|
226
|
+
described_class.template_paths.clear
|
217
227
|
end
|
218
228
|
|
219
229
|
it "instances can be loaded from an absolute path" do
|
220
|
-
IO.
|
221
|
-
|
230
|
+
expect( IO ).to receive( :read ).with( '/tmp/hooowat' ).and_return( 'file contents' )
|
231
|
+
expect( described_class.load( '/tmp/hooowat' ).source ).to eq( 'file contents' )
|
222
232
|
end
|
223
233
|
|
224
234
|
it "instances can be loaded from a path relative to the current working directory" do
|
225
235
|
tmplpath = Pathname.pwd + 'hooowat.tmpl'
|
226
|
-
FileTest.
|
227
|
-
IO.
|
228
|
-
|
236
|
+
expect( FileTest ).to receive( :exist? ).with( tmplpath.to_s ).and_return( true )
|
237
|
+
expect( IO ).to receive( :read ).with( tmplpath.to_s ).and_return( 'file contents' )
|
238
|
+
expect( described_class.load( 'hooowat.tmpl' ).source ).to eq( 'file contents' )
|
229
239
|
end
|
230
240
|
end
|
231
241
|
|
@@ -233,93 +243,93 @@ describe Inversion::Template do
|
|
233
243
|
context "with template paths set" do
|
234
244
|
|
235
245
|
before( :each ) do
|
236
|
-
|
246
|
+
described_class.template_paths = [ '/tmp', '/fun' ]
|
237
247
|
end
|
238
248
|
|
239
249
|
after( :each ) do
|
240
|
-
|
250
|
+
described_class.template_paths.clear
|
241
251
|
end
|
242
252
|
|
243
253
|
it "instances can be loaded from an absolute path" do
|
244
|
-
FileTest.
|
254
|
+
expect( FileTest ).to_not receive( :exist? )
|
245
255
|
|
246
|
-
IO.
|
247
|
-
|
256
|
+
expect( IO ).to receive( :read ).with( '/tmp/hooowat' ).and_return( 'file contents' )
|
257
|
+
expect( described_class.load( '/tmp/hooowat' ).source ).to eq( 'file contents' )
|
248
258
|
end
|
249
259
|
|
250
260
|
it "raises a runtime exception if unable to locate the template" do
|
251
261
|
tmplpath = Pathname.pwd + 'sadmanhose.tmpl'
|
252
262
|
|
253
|
-
FileTest.
|
254
|
-
FileTest.
|
255
|
-
FileTest.
|
263
|
+
expect( FileTest ).to receive( :exist? ).with( '/tmp/sadmanhose.tmpl' ).and_return( false )
|
264
|
+
expect( FileTest ).to receive( :exist? ).with( '/fun/sadmanhose.tmpl' ).and_return( false )
|
265
|
+
expect( FileTest ).to receive( :exist? ).with( tmplpath.to_s ).and_return( false )
|
256
266
|
|
257
267
|
expect {
|
258
|
-
|
268
|
+
described_class.load( 'sadmanhose.tmpl' )
|
259
269
|
}.to raise_error( RuntimeError, /unable to find template ".+" within configured paths/i )
|
260
270
|
end
|
261
271
|
|
262
272
|
it "loads template relative to directories in the template_paths" do
|
263
|
-
FileTest.
|
264
|
-
FileTest.
|
265
|
-
IO.
|
273
|
+
expect( FileTest ).to receive( :exist? ).with( '/tmp/hooowat.tmpl' ).and_return( false )
|
274
|
+
expect( FileTest ).to receive( :exist? ).with( '/fun/hooowat.tmpl' ).and_return( true )
|
275
|
+
expect( IO ).to receive( :read ).with( '/fun/hooowat.tmpl' ).and_return( 'file contents' )
|
266
276
|
|
267
|
-
|
277
|
+
expect( described_class.load( 'hooowat.tmpl' ).source ).to eq( 'file contents' )
|
268
278
|
end
|
269
279
|
|
270
280
|
it "falls back to loading the template relative to the current working directory" do
|
271
281
|
tmplpath = Pathname.pwd + 'hooowat.tmpl'
|
272
282
|
|
273
|
-
FileTest.
|
274
|
-
FileTest.
|
275
|
-
FileTest.
|
276
|
-
IO.
|
283
|
+
expect( FileTest ).to receive( :exist? ).with( '/tmp/hooowat.tmpl' ).and_return( false )
|
284
|
+
expect( FileTest ).to receive( :exist? ).with( '/fun/hooowat.tmpl' ).and_return( false )
|
285
|
+
expect( FileTest ).to receive( :exist? ).with( tmplpath.to_s ).and_return( true )
|
286
|
+
expect( IO ).to receive( :read ).with( tmplpath.to_s ).and_return( 'file contents' )
|
277
287
|
|
278
|
-
|
288
|
+
expect( described_class.load( 'hooowat.tmpl' ).source ).to eq( 'file contents' )
|
279
289
|
end
|
280
290
|
end
|
281
291
|
|
282
292
|
|
283
293
|
context "with an attribute PI" do
|
284
294
|
|
285
|
-
let( :template ) {
|
295
|
+
let( :template ) { described_class.new("<h1><?attr foo ?></h1>") }
|
286
296
|
|
287
297
|
|
288
298
|
it "has a reader for getting the attribute's value" do
|
289
|
-
template.
|
299
|
+
expect( template ).to respond_to( :foo )
|
290
300
|
end
|
291
301
|
|
292
302
|
it "has an accessor for setting the attribute's value" do
|
293
|
-
template.
|
303
|
+
expect( template ).to respond_to( :foo= )
|
294
304
|
end
|
295
305
|
|
296
306
|
it "renders scalar values set for the attribute" do
|
297
307
|
template.foo = "a lion"
|
298
|
-
template.render.
|
308
|
+
expect( template.render ).to eq( "<h1>a lion</h1>" )
|
299
309
|
end
|
300
310
|
|
301
311
|
it "renders an non-String value set for the attribute using #to_s" do
|
302
312
|
template.foo = [ 'a lion', 'a little guy', 'a bad mousie', 'one birdy' ]
|
303
|
-
template.render.
|
313
|
+
expect( template.render ).to eq( %{<h1>a liona little guya bad mousieone birdy</h1>} )
|
304
314
|
end
|
305
315
|
end
|
306
316
|
|
307
317
|
|
308
318
|
context "with several attribute PIs" do
|
309
319
|
|
310
|
-
let( :template ) {
|
320
|
+
let( :template ) { described_class.new("<h1><?attr foo ?> <?attr foo?> RUN!</h1>") }
|
311
321
|
|
312
322
|
it "has a reader for getting the attribute's value" do
|
313
|
-
template.
|
323
|
+
expect( template ).to respond_to( :foo )
|
314
324
|
end
|
315
325
|
|
316
326
|
it "has an accessor for setting the attribute's value" do
|
317
|
-
template.
|
327
|
+
expect( template ).to respond_to( :foo= )
|
318
328
|
end
|
319
329
|
|
320
330
|
it "renders scalar values set for the attribute(s)" do
|
321
331
|
template.foo = "lions!!"
|
322
|
-
template.render.
|
332
|
+
expect( template.render ).to eq( "<h1>lions!! lions!! RUN!</h1>" )
|
323
333
|
end
|
324
334
|
end
|
325
335
|
|
@@ -327,11 +337,11 @@ describe Inversion::Template do
|
|
327
337
|
describe "Configurability support", :if => defined?( Configurability ) do
|
328
338
|
|
329
339
|
after( :each ) do
|
330
|
-
|
340
|
+
described_class.config = described_class::DEFAULT_CONFIG
|
331
341
|
end
|
332
342
|
|
333
343
|
it "is included in the list of configurable objects" do
|
334
|
-
Configurability.configurable_objects.
|
344
|
+
expect( Configurability.configurable_objects ).to include( described_class )
|
335
345
|
end
|
336
346
|
|
337
347
|
it "can be configured using a Configurability::Config object" do
|
@@ -344,12 +354,12 @@ describe Inversion::Template do
|
|
344
354
|
comment_end: ""
|
345
355
|
}.gsub(/^\t{3}/, '') )
|
346
356
|
|
347
|
-
|
357
|
+
described_class.configure( config.templates )
|
348
358
|
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
359
|
+
expect( described_class.config[:ignore_unknown_tags] ).to be_false()
|
360
|
+
expect( described_class.config[:debugging_comments] ).to be_true()
|
361
|
+
expect( described_class.config[:comment_start] ).to eq( '#' )
|
362
|
+
expect( described_class.config[:comment_end] ).to eq( '' )
|
353
363
|
|
354
364
|
end
|
355
365
|
|
@@ -359,11 +369,11 @@ describe Inversion::Template do
|
|
359
369
|
describe "exception-handling:" do
|
360
370
|
|
361
371
|
before( :each ) do
|
362
|
-
@source = "Some stuff\n<?call obj.
|
363
|
-
@tmpl =
|
372
|
+
@source = "Some stuff\n<?call obj.raise_error ?>\nMore stuff"
|
373
|
+
@tmpl = described_class.new( @source )
|
364
374
|
|
365
375
|
@obj = Object.new
|
366
|
-
def @obj.
|
376
|
+
def @obj.raise_error
|
367
377
|
raise "Okay, here's an exception!"
|
368
378
|
end
|
369
379
|
|
@@ -372,24 +382,61 @@ describe Inversion::Template do
|
|
372
382
|
|
373
383
|
it "can be configured to completely ignore exceptions raised while rendering" do
|
374
384
|
@tmpl.options[:on_render_error] = :ignore
|
375
|
-
@tmpl.render.
|
385
|
+
expect( @tmpl.render ).to eq( "Some stuff\nMore stuff" )
|
376
386
|
end
|
377
387
|
|
378
388
|
it "can be configured to insert debugging comments for exceptions raised while rendering" do
|
379
389
|
@tmpl.options[:on_render_error] = :comment
|
380
|
-
|
381
|
-
|
390
|
+
expect(
|
391
|
+
@tmpl.render
|
392
|
+
).to eq( "Some stuff\n<!-- RuntimeError: Okay, here's an exception! -->More stuff" )
|
382
393
|
end
|
383
394
|
|
384
395
|
it "can be configured to propagate exceptions raised while rendering" do
|
385
396
|
@tmpl.options[:on_render_error] = :propagate
|
386
397
|
expect {
|
387
398
|
@tmpl.render
|
388
|
-
}.to
|
399
|
+
}.to raise_error( RuntimeError, /Okay, here's an exception!/ )
|
389
400
|
end
|
390
401
|
|
391
402
|
end
|
392
403
|
|
393
404
|
|
405
|
+
describe "with fragment tags" do
|
406
|
+
|
407
|
+
before( :each ) do
|
408
|
+
@template = Inversion::Template.new <<-TMPL
|
409
|
+
<?default bool to 'yes' ?>
|
410
|
+
<?fragment pork ?>wooo<?end ?>
|
411
|
+
<?fragment beef ?><?attr bool ?> please<?end ?>
|
412
|
+
<?attr beef ?>
|
413
|
+
TMPL
|
414
|
+
end
|
415
|
+
|
416
|
+
it "doesn't have any fragments before it's been rendered" do
|
417
|
+
expect( @template.fragments ).to be_empty
|
418
|
+
end
|
419
|
+
|
420
|
+
it "has a fragment for each tag after it's been rendered" do
|
421
|
+
@template.render
|
422
|
+
|
423
|
+
expect( @template.fragments ).to be_a( Hash )
|
424
|
+
expect( @template.fragments ).to include( :pork, :beef )
|
425
|
+
expect( @template.fragments.size ).to eq( 2 )
|
426
|
+
expect( @template.fragments[:pork] ).to eq( 'wooo' )
|
427
|
+
expect( @template.fragments[:beef] ).to eq( 'yes please' )
|
428
|
+
end
|
429
|
+
|
430
|
+
it "clears previous fragments when rendered a second time" do
|
431
|
+
@template.render
|
432
|
+
expect( @template.fragments[:beef] ).to eq( 'yes please' )
|
433
|
+
|
434
|
+
@template.bool = 'no'
|
435
|
+
@template.render
|
436
|
+
expect( @template.fragments[:beef] ).to eq( 'no please' )
|
437
|
+
end
|
438
|
+
|
439
|
+
end
|
440
|
+
|
394
441
|
end
|
395
442
|
|