inversion 0.12.3 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -1
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +305 -9
  5. data/Examples.rdoc +134 -0
  6. data/GettingStarted.rdoc +44 -0
  7. data/Guide.rdoc +47 -0
  8. data/History.rdoc +15 -0
  9. data/Manifest.txt +7 -2
  10. data/README.rdoc +9 -10
  11. data/Rakefile +23 -10
  12. data/Tags.rdoc +561 -0
  13. data/lib/inversion.rb +2 -2
  14. data/lib/inversion/renderstate.rb +46 -11
  15. data/lib/inversion/template.rb +85 -7
  16. data/lib/inversion/template/attrtag.rb +1 -1
  17. data/lib/inversion/template/begintag.rb +8 -8
  18. data/lib/inversion/template/fragmenttag.rb +60 -0
  19. data/lib/inversion/template/rescuetag.rb +1 -1
  20. data/spec/{lib/helpers.rb → helpers.rb} +7 -30
  21. data/spec/inversion/mixins_spec.rb +55 -65
  22. data/spec/inversion/monkeypatches_spec.rb +2 -12
  23. data/spec/inversion/parser_spec.rb +34 -44
  24. data/spec/inversion/renderstate_spec.rb +123 -69
  25. data/spec/inversion/sinatra_spec.rb +6 -19
  26. data/spec/inversion/template/attrtag_spec.rb +56 -76
  27. data/spec/inversion/template/begintag_spec.rb +24 -41
  28. data/spec/inversion/template/calltag_spec.rb +1 -18
  29. data/spec/inversion/template/codetag_spec.rb +6 -24
  30. data/spec/inversion/template/commenttag_spec.rb +9 -27
  31. data/spec/inversion/template/configtag_spec.rb +5 -16
  32. data/spec/inversion/template/containertag_spec.rb +4 -21
  33. data/spec/inversion/template/defaulttag_spec.rb +6 -23
  34. data/spec/inversion/template/elsetag_spec.rb +9 -26
  35. data/spec/inversion/template/elsiftag_spec.rb +7 -24
  36. data/spec/inversion/template/endtag_spec.rb +6 -23
  37. data/spec/inversion/template/escapetag_spec.rb +10 -25
  38. data/spec/inversion/template/fortag_spec.rb +20 -37
  39. data/spec/inversion/template/fragmenttag_spec.rb +40 -0
  40. data/spec/inversion/template/iftag_spec.rb +23 -40
  41. data/spec/inversion/template/importtag_spec.rb +8 -25
  42. data/spec/inversion/template/includetag_spec.rb +27 -42
  43. data/spec/inversion/template/node_spec.rb +6 -15
  44. data/spec/inversion/template/pptag_spec.rb +10 -23
  45. data/spec/inversion/template/publishtag_spec.rb +4 -21
  46. data/spec/inversion/template/rescuetag_spec.rb +12 -29
  47. data/spec/inversion/template/subscribetag_spec.rb +8 -25
  48. data/spec/inversion/template/tag_spec.rb +24 -37
  49. data/spec/inversion/template/textnode_spec.rb +8 -24
  50. data/spec/inversion/template/timedeltatag_spec.rb +31 -43
  51. data/spec/inversion/template/unlesstag_spec.rb +7 -24
  52. data/spec/inversion/template/uriencodetag_spec.rb +6 -23
  53. data/spec/inversion/template/yieldtag_spec.rb +3 -20
  54. data/spec/inversion/template_spec.rb +155 -108
  55. data/spec/inversion/tilt_spec.rb +7 -16
  56. data/spec/inversion_spec.rb +7 -22
  57. metadata +63 -40
  58. metadata.gz.sig +0 -0
  59. data/spec/lib/constants.rb +0 -9
@@ -1,17 +1,7 @@
1
1
  #!/usr/bin/env rspec -cfd -b
2
2
  # vim: set noet nosta sw=4 ts=4 :
3
3
 
4
- BEGIN {
5
- require 'pathname'
6
- basedir = Pathname( __FILE__ ).dirname.parent.parent
7
- libdir = basedir + 'lib'
8
-
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'
4
+ require_relative '../helpers'
15
5
 
16
6
  require 'inversion/mixins'
17
7
 
@@ -30,15 +20,15 @@ describe Inversion, "mixins" do
30
20
 
31
21
  result = Inversion::HashUtilities.stringify_keys( testhash )
32
22
 
33
- result.should be_an_instance_of( Hash )
34
- result.should_not be_equal( testhash )
35
- result.should == {
23
+ expect( result ).to be_an_instance_of( Hash )
24
+ expect( result ).to_not be_equal( testhash )
25
+ expect( result ).to eq({
36
26
  'foo' => 1,
37
27
  'bar' => {
38
28
  'klang' => 'klong',
39
29
  'barang' => { 'kerklang' => 'dumdumdum' },
40
30
  }
41
- }
31
+ })
42
32
  end
43
33
 
44
34
 
@@ -53,15 +43,15 @@ describe Inversion, "mixins" do
53
43
 
54
44
  result = Inversion::HashUtilities.symbolify_keys( testhash )
55
45
 
56
- result.should be_an_instance_of( Hash )
57
- result.should_not be_equal( testhash )
58
- result.should == {
46
+ expect( result ).to be_an_instance_of( Hash )
47
+ expect( result ).to_not be_equal( testhash )
48
+ expect( result ).to eq({
59
49
  :foo => 1,
60
50
  :bar => {
61
51
  :klang => 'klong',
62
52
  :barang => { :kerklang => 'dumdumdum' },
63
53
  }
64
- }
54
+ })
65
55
  end
66
56
 
67
57
  end
@@ -125,17 +115,17 @@ describe Inversion, "mixins" do
125
115
 
126
116
  it "adds configurable escaping to including classes" do
127
117
  render_state = Inversion::RenderState.new( {}, :escape_format => :html )
128
- @obj.render( render_state ).should == "<something>"
118
+ expect( @obj.render( render_state ) ).to eq( "<something>" )
129
119
  end
130
120
 
131
121
  it "doesn't escape anything if escaping is disabled" do
132
122
  render_state = Inversion::RenderState.new( {}, :escape_format => nil )
133
- @obj.render( render_state ).should == "<something>"
123
+ expect( @obj.render( render_state ) ).to eq( "<something>" )
134
124
  end
135
125
 
136
126
  it "doesn't escape anything if escaping is set to ':none'" do
137
127
  render_state = Inversion::RenderState.new( {}, :escape_format => :none )
138
- @obj.render( render_state ).should == "<something>"
128
+ expect( @obj.render( render_state ) ).to eq( "<something>" )
139
129
  end
140
130
  end
141
131
 
@@ -143,26 +133,26 @@ describe Inversion, "mixins" do
143
133
  describe Inversion::DataUtilities do
144
134
 
145
135
  it "doesn't try to dup immediate objects" do
146
- Inversion::DataUtilities.deep_copy( nil ).should be( nil )
147
- Inversion::DataUtilities.deep_copy( 112 ).should be( 112 )
148
- Inversion::DataUtilities.deep_copy( true ).should be( true )
149
- Inversion::DataUtilities.deep_copy( false ).should be( false )
150
- Inversion::DataUtilities.deep_copy( :a_symbol ).should be( :a_symbol )
136
+ expect( Inversion::DataUtilities.deep_copy( nil ) ).to be( nil )
137
+ expect( Inversion::DataUtilities.deep_copy( 112 ) ).to be( 112 )
138
+ expect( Inversion::DataUtilities.deep_copy( true ) ).to be( true )
139
+ expect( Inversion::DataUtilities.deep_copy( false ) ).to be( false )
140
+ expect( Inversion::DataUtilities.deep_copy( :a_symbol ) ).to be( :a_symbol )
151
141
  end
152
142
 
153
143
  it "doesn't try to dup modules/classes" do
154
144
  klass = Class.new
155
- Inversion::DataUtilities.deep_copy( klass ).should be( klass )
145
+ expect( Inversion::DataUtilities.deep_copy( klass ) ).to be( klass )
156
146
  end
157
147
 
158
148
  it "doesn't try to dup IOs" do
159
149
  data = [ $stdin ]
160
- Inversion::DataUtilities.deep_copy( data[0] ).should be( $stdin )
150
+ expect( Inversion::DataUtilities.deep_copy( data[0] ) ).to be( $stdin )
161
151
  end
162
152
 
163
153
  it "doesn't try to dup Tempfiles" do
164
154
  data = Tempfile.new( 'inversion_deepcopy.XXXXX' )
165
- Inversion::DataUtilities.deep_copy( data ).should be( data )
155
+ expect( Inversion::DataUtilities.deep_copy( data ) ).to be( data )
166
156
  end
167
157
 
168
158
  it "makes distinct copies of arrays and their members" do
@@ -170,14 +160,14 @@ describe Inversion, "mixins" do
170
160
 
171
161
  copy = Inversion::DataUtilities.deep_copy( original )
172
162
 
173
- copy.should == original
174
- copy.should_not be( original )
175
- copy[0].should == original[0]
176
- copy[0].should_not be( original[0] )
177
- copy[1].should == original[1]
178
- copy[1].should_not be( original[1] )
179
- copy[2].should == original[2]
180
- copy[2].should be( original[2] ) # Immediate
163
+ expect( copy ).to eq( original )
164
+ expect( copy ).to_not be( original )
165
+ expect( copy[0] ).to eq( original[0] )
166
+ expect( copy[0] ).to_not be( original[0] )
167
+ expect( copy[1] ).to eq( original[1] )
168
+ expect( copy[1] ).to_not be( original[1] )
169
+ expect( copy[2] ).to eq( original[2] )
170
+ expect( copy[2] ).to be( original[2] ) # Immediate
181
171
  end
182
172
 
183
173
  it "makes recursive copies of deeply-nested Arrays" do
@@ -185,12 +175,12 @@ describe Inversion, "mixins" do
185
175
 
186
176
  copy = Inversion::DataUtilities.deep_copy( original )
187
177
 
188
- copy.should == original
189
- copy.should_not be( original )
190
- copy[1].should_not be( original[1] )
191
- copy[1][2].should_not be( original[1][2] )
192
- copy[3].should_not be( original[3] )
193
- copy[3][1].should_not be( original[3][1] )
178
+ expect( copy ).to eq( original )
179
+ expect( copy ).to_not be( original )
180
+ expect( copy[1] ).to_not be( original[1] )
181
+ expect( copy[1][2] ).to_not be( original[1][2] )
182
+ expect( copy[3] ).to_not be( original[3] )
183
+ expect( copy[3][1] ).to_not be( original[3][1] )
194
184
  end
195
185
 
196
186
  it "makes distinct copies of Hashes and their members" do
@@ -202,13 +192,13 @@ describe Inversion, "mixins" do
202
192
 
203
193
  copy = Inversion::DataUtilities.deep_copy( original )
204
194
 
205
- copy.should == original
206
- copy.should_not be( original )
207
- copy[:a].should == 1
208
- copy.key( 2 ).should == 'b'
209
- copy.key( 2 ).should_not be( original.key(2) )
210
- copy[3].should == 'c'
211
- copy[3].should_not be( original[3] )
195
+ expect( copy ).to eq( original )
196
+ expect( copy ).to_not be( original )
197
+ expect( copy[:a] ).to eq( 1 )
198
+ expect( copy.key( 2 ) ).to eq( 'b' )
199
+ expect( copy.key( 2 ) ).to_not be( original.key(2) )
200
+ expect( copy[3] ).to eq( 'c' )
201
+ expect( copy[3] ).to_not be( original[3] )
212
202
  end
213
203
 
214
204
  it "makes distinct copies of deeply-nested Hashes" do
@@ -225,15 +215,15 @@ describe Inversion, "mixins" do
225
215
 
226
216
  copy = Inversion::DataUtilities.deep_copy( original )
227
217
 
228
- copy.should == original
229
- copy[:a][:b][:c].should == 'd'
230
- copy[:a][:b][:c].should_not be( original[:a][:b][:c] )
231
- copy[:a][:b][:e].should == 'f'
232
- copy[:a][:b][:e].should_not be( original[:a][:b][:e] )
233
- copy[:a][:g].should == 'h'
234
- copy[:a][:g].should_not be( original[:a][:g] )
235
- copy[:i].should == 'j'
236
- copy[:i].should_not be( original[:i] )
218
+ expect( copy ).to eq( original )
219
+ expect( copy[:a][:b][:c] ).to eq( 'd' )
220
+ expect( copy[:a][:b][:c] ).to_not be( original[:a][:b][:c] )
221
+ expect( copy[:a][:b][:e] ).to eq( 'f' )
222
+ expect( copy[:a][:b][:e] ).to_not be( original[:a][:b][:e] )
223
+ expect( copy[:a][:g] ).to eq( 'h' )
224
+ expect( copy[:a][:g] ).to_not be( original[:a][:g] )
225
+ expect( copy[:i] ).to eq( 'j' )
226
+ expect( copy[:i] ).to_not be( original[:i] )
237
227
  end
238
228
 
239
229
  it "copies the default proc of copied Hashes" do
@@ -241,7 +231,7 @@ describe Inversion, "mixins" do
241
231
 
242
232
  copy = Inversion::DataUtilities.deep_copy( original )
243
233
 
244
- copy.default_proc.should == original.default_proc
234
+ expect( copy.default_proc ).to eq( original.default_proc )
245
235
  end
246
236
 
247
237
  it "preserves taintedness of copied objects" do
@@ -250,8 +240,8 @@ describe Inversion, "mixins" do
250
240
 
251
241
  copy = Inversion::DataUtilities.deep_copy( original )
252
242
 
253
- copy.should_not be( original )
254
- copy.should be_tainted()
243
+ expect( copy ).to_not be( original )
244
+ expect( copy ).to be_tainted()
255
245
  end
256
246
 
257
247
  it "preserves frozen-ness of copied objects" do
@@ -260,8 +250,8 @@ describe Inversion, "mixins" do
260
250
 
261
251
  copy = Inversion::DataUtilities.deep_copy( original )
262
252
 
263
- copy.should_not be( original )
264
- copy.should be_frozen()
253
+ expect( copy ).to_not be( original )
254
+ expect( copy ).to be_frozen()
265
255
  end
266
256
  end
267
257
  end
@@ -1,20 +1,10 @@
1
1
  #!/usr/bin/env rspec -cfd -b
2
2
  # vim: set noet nosta sw=4 ts=4 :
3
3
 
4
- BEGIN {
5
- require 'pathname'
6
- basedir = Pathname( __FILE__ ).dirname.parent.parent
7
- libdir = basedir + 'lib'
8
4
 
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
- }
5
+ require_relative '../helpers'
12
6
 
13
7
  require 'ripper'
14
-
15
- require 'rspec'
16
- require 'spec/lib/helpers'
17
-
18
8
  require 'inversion/monkeypatches'
19
9
 
20
10
 
@@ -25,7 +15,7 @@ describe Inversion, "monkeypatches" do
25
15
  it "exposes the Ripper::TokenPattern::MatchData's #tokens array" do
26
16
  tagpattern = Ripper::TokenPattern.compile( '$(ident) $(sp) $(ident)' )
27
17
  matchdata = tagpattern.match( "foo bar" )
28
- matchdata.tokens.map {|tok| tok[1] }.should == [ :on_ident, :on_sp, :on_ident ]
18
+ expect( matchdata.tokens.map {|tok| tok[1]} ).to eq([ :on_ident, :on_sp, :on_ident ])
29
19
  end
30
20
 
31
21
  end
@@ -1,23 +1,13 @@
1
1
  #!/usr/bin/env rspec -cfd -b
2
2
  # vim: set noet nosta sw=4 ts=4 :
3
3
 
4
- BEGIN {
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
- require 'spec/lib/helpers'
15
6
  require 'inversion/parser'
16
7
 
17
8
  describe Inversion::Parser do
18
9
 
19
10
  before( :all ) do
20
- setup_logging( :fatal )
21
11
  Inversion::Template::Tag.load_all
22
12
  end
23
13
 
@@ -28,14 +18,14 @@ describe Inversion::Parser do
28
18
  it "parses a string with no PIs as a single text node" do
29
19
  result = Inversion::Parser.new( @template ).parse( "render unto Caesar" )
30
20
 
31
- result.should have( 1 ).member
32
- result.first.should be_a( Inversion::Template::TextNode )
33
- result.first.body.should == 'render unto Caesar'
21
+ expect( result.size ).to eq( 1 )
22
+ expect( result.first ).to be_a( Inversion::Template::TextNode )
23
+ expect( result.first.body ).to eq( 'render unto Caesar' )
34
24
  end
35
25
 
36
26
  it "parses an empty string as a empty tree" do
37
27
  result = Inversion::Parser.new( @template ).parse( "" )
38
- result.should be_empty
28
+ expect( result ).to be_empty
39
29
  end
40
30
 
41
31
  it "raises a ParseError on mismatched tag brackets" do
@@ -47,47 +37,47 @@ describe Inversion::Parser do
47
37
  it "parses a string with a single 'attr' tag as a single AttrTag node" do
48
38
  result = Inversion::Parser.new( @template ).parse( "<?attr foo ?>" )
49
39
 
50
- result.should have( 1 ).member
51
- result.first.should be_a( Inversion::Template::AttrTag )
52
- result.first.body.should == 'foo'
40
+ expect( result.size ).to eq( 1 )
41
+ expect( result.first ).to be_a( Inversion::Template::AttrTag )
42
+ expect( result.first.body ).to eq( 'foo' )
53
43
  end
54
44
 
55
45
  it "parses a single 'attr' tag surrounded by plain text" do
56
46
  result = Inversion::Parser.new( @template ).parse( "beginning<?attr foo ?>end" )
57
47
 
58
- result.should have( 3 ).members
59
- result[0].should be_a( Inversion::Template::TextNode )
60
- result[1].should be_a( Inversion::Template::AttrTag )
61
- result[1].body.should == 'foo'
62
- result[2].should be_a( Inversion::Template::TextNode )
48
+ expect( result.size ).to eq( 3 )
49
+ expect( result[0] ).to be_a( Inversion::Template::TextNode )
50
+ expect( result[1] ).to be_a( Inversion::Template::AttrTag )
51
+ expect( result[1].body ).to eq( 'foo' )
52
+ expect( result[2] ).to be_a( Inversion::Template::TextNode )
63
53
  end
64
54
 
65
55
  it "ignores unknown tags by default" do
66
56
  result = Inversion::Parser.new( @template ).parse( "Text <?hoooowhat ?>" )
67
57
 
68
- result.should have( 2 ).members
69
- result[0].should be_a( Inversion::Template::TextNode )
70
- result[1].should be_a( Inversion::Template::TextNode )
71
- result[1].body.should == '<?hoooowhat ?>'
58
+ expect( result.size ).to eq( 2 )
59
+ expect( result[0] ).to be_a( Inversion::Template::TextNode )
60
+ expect( result[1] ).to be_a( Inversion::Template::TextNode )
61
+ expect( result[1].body ).to eq( '<?hoooowhat ?>' )
72
62
  end
73
63
 
74
64
  it "can raise exceptions on unknown tags" do
75
65
  expect {
76
66
  Inversion::Parser.new( @template, :ignore_unknown_tags => false ).
77
67
  parse( "Text <?hoooowhat ?>" )
78
- }.to raise_exception( Inversion::ParseError, /unknown tag/i )
68
+ }.to raise_error( Inversion::ParseError, /unknown tag/i )
79
69
  end
80
70
 
81
71
  it "can raise exceptions on unclosed (nested) tags" do
82
72
  expect {
83
73
  Inversion::Parser.new( @template ).parse( "Text <?attr something <?attr something_else ?>" )
84
- }.to raise_exception( Inversion::ParseError, /unclosed or nested tag/i )
74
+ }.to raise_error( Inversion::ParseError, /unclosed or nested tag/i )
85
75
  end
86
76
 
87
77
  it "can raise exceptions on unclosed (eof) tags" do
88
78
  expect {
89
79
  Inversion::Parser.new( @template ).parse( "Text <?hoooowhat" )
90
- }.to raise_exception( Inversion::ParseError, /unclosed tag/i )
80
+ }.to raise_error( Inversion::ParseError, /unclosed tag/i )
91
81
  end
92
82
 
93
83
 
@@ -103,41 +93,41 @@ describe Inversion::Parser do
103
93
 
104
94
  @state << open_tag << end_tag
105
95
 
106
- @state.tree.should == [ open_tag, end_tag ]
96
+ expect( @state.tree ).to eq( [ open_tag, end_tag ] )
107
97
  end
108
98
 
109
99
  it "knows it is well-formed if there are no open tags" do
110
100
  @state << Inversion::Template::ForTag.new( 'foo in bar' )
111
- @state.should_not be_well_formed
101
+ expect( @state ).to_not be_well_formed
112
102
 
113
103
  @state << Inversion::Template::ForTag.new( 'foo in bar' )
114
- @state.should_not be_well_formed
104
+ expect( @state ).to_not be_well_formed
115
105
 
116
106
  @state << Inversion::Template::EndTag.new( 'for' )
117
- @state.should_not be_well_formed
107
+ expect( @state ).to_not be_well_formed
118
108
 
119
109
  @state << Inversion::Template::EndTag.new( 'for' )
120
- @state.should be_well_formed
110
+ expect( @state ).to be_well_formed
121
111
  end
122
112
 
123
113
  it "can pop a container tag off of the current context" do
124
114
  container = Inversion::Template::ForTag.new( 'foo in bar' )
125
115
  @state << container
126
- @state.pop.should == container
116
+ expect( @state.pop ).to eq( container )
127
117
  end
128
118
 
129
119
  it "calls the #after_appending hook of container nodes when they're popped" do
130
- container = mock( "container tag", :before_appending => false, :is_container? => true )
120
+ container = double( "container tag", :before_appending => false, :is_container? => true )
131
121
  @state << container
132
122
 
133
- container.should_receive( :after_appending ).with( @state )
123
+ expect( container ).to receive( :after_appending ).with( @state )
134
124
  @state.pop
135
125
  end
136
126
 
137
127
  it "raises an error when popping if there is no container tag" do
138
128
  expect {
139
129
  @state.pop
140
- }.to raise_exception( Inversion::ParseError, /unbalanced end: no open tag/i )
130
+ }.to raise_error( Inversion::ParseError, /unbalanced end: no open tag/i )
141
131
  end
142
132
 
143
133
  it "raises an error when the tree is fetched if it isn't well-formed" do
@@ -146,19 +136,19 @@ describe Inversion::Parser do
146
136
 
147
137
  expect {
148
138
  @state.tree
149
- }.to raise_exception( Inversion::ParseError, /unclosed/i )
139
+ }.to raise_error( Inversion::ParseError, /unclosed/i )
150
140
  end
151
141
 
152
142
  it "calls the #before_appending callback on nodes that are appended to it" do
153
- node = mock( "node", :is_container? => false, :after_appending => nil )
154
- node.should_receive( :before_appending ).with( @state )
143
+ node = double( "node", :is_container? => false, :after_appending => nil )
144
+ expect( node ).to receive( :before_appending ).with( @state )
155
145
 
156
146
  @state << node
157
147
  end
158
148
 
159
149
  it "calls the #after_appending callback on nodes that are appended to it" do
160
- node = mock( "node", :is_container? => false, :before_appending => nil )
161
- node.should_receive( :after_appending ).with( @state )
150
+ node = double( "node", :is_container? => false, :before_appending => nil )
151
+ expect( node ).to receive( :after_appending ).with( @state )
162
152
 
163
153
  @state << node
164
154
  end
@@ -2,43 +2,28 @@
2
2
  # encoding: utf-8
3
3
  # vim: set noet nosta sw=4 ts=4 :
4
4
 
5
- BEGIN {
6
- require 'pathname'
7
- basedir = Pathname( __FILE__ ).dirname.parent.parent
8
- libdir = basedir + 'lib'
5
+ require_relative '../helpers'
9
6
 
10
- $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
11
- $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
12
- }
13
-
14
- require 'rspec'
15
-
16
- require 'spec/lib/helpers'
17
7
  require 'inversion/renderstate'
18
8
  require 'inversion/template/attrtag'
19
9
  require 'inversion/template/textnode'
10
+ require 'inversion/template/fragmenttag'
11
+ require 'inversion/template/subscribetag'
12
+ require 'inversion/template/publishtag'
20
13
 
21
14
  describe Inversion::RenderState do
22
15
 
23
- before( :all ) do
24
- setup_logging( :fatal )
25
- end
26
-
27
- after( :all ) do
28
- reset_logging()
29
- end
30
-
31
16
 
32
17
  it "provides access to the block it was constructed with if there was one" do
33
18
  block = Proc.new {}
34
19
  state = Inversion::RenderState.new( &block )
35
- state.block.should equal( block )
20
+ expect( state.block ).to equal( block )
36
21
  end
37
22
 
38
23
  it "can evaluate code in the context of itself" do
39
24
  attributes = { :foot => "in mouth", :bear => "in woods" }
40
25
  state = Inversion::RenderState.new( attributes )
41
- state.eval( "foot" ).should == 'in mouth'
26
+ expect( state.eval( "foot" ) ).to eq( 'in mouth' )
42
27
  end
43
28
 
44
29
 
@@ -49,11 +34,11 @@ describe Inversion::RenderState do
49
34
 
50
35
  state = Inversion::RenderState.new( attributes )
51
36
 
52
- state.scope.__locals__.should_not equal( attributes )
53
- state.scope[:foot].should == "in mouth"
54
- state.scope[:foot].should_not equal( attributes[:foot] )
55
- state.scope[:bear].should == "in woods"
56
- state.scope[:bear].should_not equal( attributes[:bear] )
37
+ expect( state.scope.__locals__ ).to_not equal( attributes )
38
+ expect( state.scope[:foot] ).to eq( "in mouth" )
39
+ expect( state.scope[:foot] ).to_not equal( attributes[:foot] )
40
+ expect( state.scope[:bear] ).to eq( "in woods" )
41
+ expect( state.scope[:bear] ).to_not equal( attributes[:bear] )
57
42
  end
58
43
 
59
44
  it "preserves tainted status when copying its attributes" do
@@ -62,7 +47,7 @@ describe Inversion::RenderState do
62
47
 
63
48
  state = Inversion::RenderState.new( attributes )
64
49
 
65
- state.scope[:danger].should be_tainted()
50
+ expect( state.scope[:danger] ).to be_tainted()
66
51
  end
67
52
 
68
53
  it "preserves singleton methods on attribute objects when copying" do
@@ -71,7 +56,7 @@ describe Inversion::RenderState do
71
56
 
72
57
  state = Inversion::RenderState.new( :foo => obj )
73
58
 
74
- state.scope[:foo].singleton_methods.map( &:to_sym ).should include( :foo )
59
+ expect( state.scope[:foo].singleton_methods.map( &:to_sym ) ).to include( :foo )
75
60
  end
76
61
 
77
62
  it "preserves frozen status when copying its attributes" do
@@ -80,7 +65,7 @@ describe Inversion::RenderState do
80
65
 
81
66
  state = Inversion::RenderState.new( attributes )
82
67
 
83
- state.scope[:danger].should be_frozen()
68
+ expect( state.scope[:danger] ).to be_frozen()
84
69
  end
85
70
 
86
71
  it "can override its attributes for the duration of a block" do
@@ -89,11 +74,11 @@ describe Inversion::RenderState do
89
74
  state = Inversion::RenderState.new( attributes )
90
75
 
91
76
  state.with_attributes( :foot => 'ball' ) do
92
- state.foot.should == 'ball'
93
- state.bear.should == 'in woods'
77
+ expect( state.foot ).to eq( 'ball' )
78
+ expect( state.bear ).to eq( 'in woods' )
94
79
  end
95
80
 
96
- state.scope[:foot].should == 'in mouth'
81
+ expect( state.scope[:foot] ).to eq( 'in mouth' )
97
82
  end
98
83
 
99
84
 
@@ -108,7 +93,7 @@ describe Inversion::RenderState do
108
93
  end
109
94
  }.to raise_error()
110
95
 
111
- state.scope[:foot].should == 'in mouth'
96
+ expect( state.scope[:foot] ).to eq( 'in mouth' )
112
97
  end
113
98
 
114
99
 
@@ -122,12 +107,12 @@ describe Inversion::RenderState do
122
107
 
123
108
  it "provides accessor methods for its attributes" do
124
109
  state = Inversion::RenderState.new( :bar => :the_attribute_value )
125
- state.scope.bar.should == :the_attribute_value
110
+ expect( state.scope.bar ).to eq( :the_attribute_value )
126
111
  end
127
112
 
128
113
  it "doesn't error if an accessor for a non-existant attribute is called" do
129
114
  state = Inversion::RenderState.new( :bar => :the_attribute_value )
130
- state.scope.foo.should be_nil()
115
+ expect( state.scope.foo ).to be_nil()
131
116
  end
132
117
 
133
118
  end
@@ -142,11 +127,11 @@ describe Inversion::RenderState do
142
127
 
143
128
  thirdstate = state.merge( anotherstate )
144
129
 
145
- thirdstate.attributes.should == {
130
+ expect( thirdstate.attributes ).to eq({
146
131
  :bar => :the_bar_value,
147
132
  :foo => :the_foo_value
148
- }
149
- thirdstate.options.should include(
133
+ })
134
+ expect( thirdstate.options ).to include(
150
135
  :debugging_comments => true,
151
136
  :on_render_error => :propagate
152
137
  )
@@ -162,7 +147,7 @@ describe Inversion::RenderState do
162
147
  end
163
148
 
164
149
  it "provides a mechanism for storing tag state for the current render" do
165
- @renderstate.tag_data.should be_a( Hash )
150
+ expect( @renderstate.tag_data ).to be_a( Hash )
166
151
  end
167
152
 
168
153
  it "can override tag state for the duration of a block" do
@@ -170,14 +155,14 @@ describe Inversion::RenderState do
170
155
  @renderstate.tag_data[ :colorado ] = 'fine fishing'
171
156
 
172
157
  @renderstate.with_tag_data( :alaska => 'good fishing' ) do
173
- @renderstate.tag_data[:alaska].should == 'good fishing'
158
+ expect( @renderstate.tag_data[:alaska] ).to eq( 'good fishing' )
174
159
  @renderstate.tag_data[:alaska] = 'blueberry bear poop'
175
160
  @renderstate.tag_data[:colorado] = 'Boulder has hippies'
176
161
  end
177
162
 
178
- @renderstate.tag_data.should_not have_key( :alaska )
179
- @renderstate.tag_data[:montana].should == 'excellent fishing'
180
- @renderstate.tag_data[:colorado].should == 'fine fishing'
163
+ expect( @renderstate.tag_data ).to_not have_key( :alaska )
164
+ expect( @renderstate.tag_data[:montana] ).to eq( 'excellent fishing' )
165
+ expect( @renderstate.tag_data[:colorado] ).to eq( 'fine fishing' )
181
166
  end
182
167
 
183
168
  end
@@ -194,11 +179,11 @@ describe Inversion::RenderState do
194
179
  rval = state.with_destination( newdest ) do
195
180
  state << node
196
181
  end
197
- rval.should equal( newdest )
182
+ expect( rval ).to equal( newdest )
198
183
 
199
- newdest.should have( 1 ).member
200
- newdest.should include( 'New!' )
201
- state.destination.should equal( original_dest )
184
+ expect( newdest.size ).to eq( 1 )
185
+ expect( newdest ).to include( 'New!' )
186
+ expect( state.destination ).to equal( original_dest )
202
187
  end
203
188
 
204
189
  it "restores the original destination if the block raises an exception" do
@@ -212,7 +197,7 @@ describe Inversion::RenderState do
212
197
  end
213
198
  }.to raise_error()
214
199
 
215
- state.destination.should equal( original_dest )
200
+ expect( state.destination ).to equal( original_dest )
216
201
  end
217
202
 
218
203
  it "raises an error if #with_destination is called without a block" do
@@ -232,7 +217,7 @@ describe Inversion::RenderState do
232
217
 
233
218
  state << node
234
219
 
235
- state.to_s.should == '<!-- Attr: { template.foo } -->'
220
+ expect( state.to_s ).to eq( '<!-- Attr: { template.foo } -->' )
236
221
  end
237
222
 
238
223
  it "doesn't add a debugging comment when appending a node if debugging comments are disabled" do
@@ -241,7 +226,7 @@ describe Inversion::RenderState do
241
226
 
242
227
  state << node
243
228
 
244
- state.to_s.should == ''
229
+ expect( state.to_s ).to eq( '' )
245
230
  end
246
231
 
247
232
  end
@@ -255,7 +240,7 @@ describe Inversion::RenderState do
255
240
 
256
241
  state << node
257
242
 
258
- state.to_s.should == ''
243
+ expect( state.to_s ).to eq( '' )
259
244
  end
260
245
 
261
246
  it "adds a comment for errors while rendering appended nodes in 'comment' mode" do
@@ -264,7 +249,7 @@ describe Inversion::RenderState do
264
249
 
265
250
  state << node
266
251
 
267
- state.to_s.should == "<!-- NoMethodError: undefined method `klang' for nil:NilClass -->"
252
+ expect( state.to_s ).to eq( "<!-- NoMethodError: undefined method `klang' for nil:NilClass -->" )
268
253
  end
269
254
 
270
255
  it "includes a backtrace when rendering errors in 'comment' mode with 'debugging_comments' enabled" do
@@ -274,8 +259,8 @@ describe Inversion::RenderState do
274
259
  state << node
275
260
  output = state.to_s
276
261
 
277
- output.should include( "<!-- NoMethodError: undefined method `klang' for nil:NilClass" )
278
- output.should include( "#{__FILE__}:#{__LINE__ - 4}" )
262
+ expect( output ).to include( "<!-- NoMethodError: undefined method `klang' for nil:NilClass" )
263
+ expect( output ).to include( "#{__FILE__}:#{__LINE__ - 4}" )
279
264
  end
280
265
 
281
266
  it "re-raises errors while rendering appended nodes in 'propagate' mode" do
@@ -302,8 +287,8 @@ describe Inversion::RenderState do
302
287
  end
303
288
  }.to_not raise_error()
304
289
 
305
- state.to_s.should =~ /yum, i eat nomethoderror/i
306
- state.errhandler.should equal( defhandler )
290
+ expect( state.to_s ).to match( /yum, i eat nomethoderror/i )
291
+ expect( state.errhandler ).to equal( defhandler )
307
292
  end
308
293
 
309
294
  it "raises an exception if the error handler is set to something that doesn't respond to #call" do
@@ -332,7 +317,7 @@ describe Inversion::RenderState do
332
317
  end
333
318
 
334
319
  it "doesn't have any subscriptions by default" do
335
- @state.subscriptions.should == {}
320
+ expect( @state.subscriptions ).to eq( {} )
336
321
  end
337
322
 
338
323
  it "allows an object to subscribe to node publications" do
@@ -340,8 +325,8 @@ describe Inversion::RenderState do
340
325
 
341
326
  @state.subscribe( :the_key, subscriber )
342
327
 
343
- @state.subscriptions.should have( 1 ).member
344
- @state.subscriptions[ :the_key ].should == [ subscriber ]
328
+ expect( @state.subscriptions.size ).to eq( 1 )
329
+ expect( @state.subscriptions[:the_key] ).to eq( [subscriber] )
345
330
  end
346
331
 
347
332
  end
@@ -354,19 +339,19 @@ describe Inversion::RenderState do
354
339
  end
355
340
 
356
341
  it "allows rendering to be explicitly enabled and disabled" do
357
- @state.rendering_enabled?.should be_true()
342
+ expect( @state.rendering_enabled? ).to be_truthy()
358
343
  @state.disable_rendering
359
- @state.rendering_enabled?.should be_false()
344
+ expect( @state.rendering_enabled? ).to be_falsey()
360
345
  @state.enable_rendering
361
- @state.rendering_enabled?.should be_true()
346
+ expect( @state.rendering_enabled? ).to be_truthy()
362
347
  end
363
348
 
364
349
  it "allows rendering to be toggled" do
365
- @state.rendering_enabled?.should be_true()
350
+ expect( @state.rendering_enabled? ).to be_truthy()
366
351
  @state.toggle_rendering
367
- @state.rendering_enabled?.should be_false()
352
+ expect( @state.rendering_enabled? ).to be_falsey()
368
353
  @state.toggle_rendering
369
- @state.rendering_enabled?.should be_true()
354
+ expect( @state.rendering_enabled? ).to be_truthy()
370
355
  end
371
356
 
372
357
  it "doesn't render nodes that are appended to it if rendering is disabled" do
@@ -376,7 +361,7 @@ describe Inversion::RenderState do
376
361
  @state.enable_rendering
377
362
  @state << Inversion::Template::TextNode.new( "after" )
378
363
 
379
- @state.to_s.should == 'beforeafter'
364
+ expect( @state.to_s ).to eq( 'beforeafter' )
380
365
  end
381
366
 
382
367
  end
@@ -390,7 +375,7 @@ describe Inversion::RenderState do
390
375
 
391
376
 
392
377
  it "knows how many floating-point seconds have passed since it was created" do
393
- @state.time_elapsed.should be_a( Float )
378
+ expect( @state.time_elapsed ).to be_a( Float )
394
379
  end
395
380
 
396
381
  end
@@ -409,7 +394,7 @@ describe Inversion::RenderState do
409
394
  state << Inversion::Template::AttrTag.new( 'good_doggie' )
410
395
  state << Inversion::Template::AttrTag.new( 'little' )
411
396
 
412
- state.to_s.encoding.should be( Encoding::UTF_8 )
397
+ expect( state.to_s.encoding ).to be( Encoding::UTF_8 )
413
398
  end
414
399
 
415
400
  it "replaces characters with undefined conversions instead of raising an encoding error" do
@@ -426,7 +411,76 @@ describe Inversion::RenderState do
426
411
  state << Inversion::Template::AttrTag.new( 'okay' )
427
412
  state << Inversion::Template::AttrTag.new( 'bogus' )
428
413
 
429
- state.to_s.encoding.should be( Encoding::UTF_8 )
414
+ expect( state.to_s.encoding ).to be( Encoding::UTF_8 )
415
+ end
416
+
417
+ end
418
+
419
+
420
+ describe "fragments" do
421
+
422
+ before( :each ) do
423
+ @state = Inversion::RenderState.new
424
+ end
425
+
426
+
427
+ it "can be set to an Array of rendered nodes" do
428
+ subscribe_node = Inversion::Template::SubscribeTag.new( 'brand' )
429
+ @state << subscribe_node
430
+
431
+ publish_node = Inversion::Template::PublishTag.new( 'brand' )
432
+ publish_node << Inversion::Template::TextNode.new( 'Acme' )
433
+ @state << publish_node
434
+
435
+ @state.add_fragment( :title, "Welcome to the ", subscribe_node, " website!" )
436
+
437
+ expect( @state.fragments ).to be_a( Hash )
438
+ expect( @state.fragments[:title] ).to eq([ "Welcome to the ", subscribe_node, " website!" ])
439
+ end
440
+
441
+
442
+ it "can be returned as a rendered Hash" do
443
+ subscribe_node = Inversion::Template::SubscribeTag.new( 'brand' )
444
+ @state << subscribe_node
445
+
446
+ publish_node = Inversion::Template::PublishTag.new( 'brand' )
447
+ publish_node << Inversion::Template::TextNode.new( 'Acme' )
448
+ @state << publish_node
449
+
450
+ @state.add_fragment( :title, "Welcome to the ", subscribe_node, " website!" )
451
+
452
+ expect( @state.rendered_fragments ).to be_a( Hash )
453
+ expect( @state.rendered_fragments[:title] ).to eq( "Welcome to the Acme website!" )
454
+ end
455
+
456
+
457
+ it "acts like a default if an attribute isn't set" do
458
+ node = Inversion::Template::FragmentTag.new( 'pork' )
459
+ node << Inversion::Template::AttrTag.new( 'bool' )
460
+ node << Inversion::Template::TextNode.new( ' please!' )
461
+
462
+ @state.scope[ :bool ] = 'yes'
463
+ @state << node
464
+ @state << Inversion::Template::TextNode.new( '--> ' )
465
+ @state << Inversion::Template::AttrTag.new( 'pork' )
466
+ @state << Inversion::Template::TextNode.new( ' <--' )
467
+
468
+ expect( @state.to_s ).to eq( '--> yes please! <--' )
469
+ end
470
+
471
+
472
+ it "don't override explicitly-set attributes" do
473
+ node = Inversion::Template::FragmentTag.new( 'pork' )
474
+ node << Inversion::Template::AttrTag.new( 'bool' )
475
+ node << Inversion::Template::TextNode.new( ' please!' )
476
+
477
+ @state.scope[ :pork ] = 'pie'
478
+ @state << node
479
+ @state << Inversion::Template::TextNode.new( '--> ' )
480
+ @state << Inversion::Template::AttrTag.new( 'pork' )
481
+ @state << Inversion::Template::TextNode.new( ' <--' )
482
+
483
+ expect( @state.to_s ).to eq( '--> pie <--' )
430
484
  end
431
485
 
432
486
  end