flavour_saver 0.3.7 → 2.0.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.
Files changed (36) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +47 -0
  3. data/CHANGELOG.md +40 -0
  4. data/Gemfile.lock +34 -62
  5. data/README.md +34 -11
  6. data/flavour_saver.gemspec +14 -9
  7. data/lib/flavour_saver/helpers.rb +28 -13
  8. data/lib/flavour_saver/lexer.rb +19 -6
  9. data/lib/flavour_saver/nodes.rb +1 -1
  10. data/lib/flavour_saver/parser.rb +8 -7
  11. data/lib/flavour_saver/runtime.rb +8 -8
  12. data/lib/flavour_saver/version.rb +1 -1
  13. data/spec/acceptance/backtrack_spec.rb +1 -1
  14. data/spec/acceptance/comment_spec.rb +1 -1
  15. data/spec/acceptance/custom_block_helper_spec.rb +2 -2
  16. data/spec/acceptance/custom_helper_spec.rb +1 -1
  17. data/spec/acceptance/ensure_no_rce_spec.rb +2 -2
  18. data/spec/acceptance/handlebars_qunit_spec.rb +299 -214
  19. data/spec/acceptance/if_else_spec.rb +37 -6
  20. data/spec/acceptance/multi_level_with_spec.rb +1 -1
  21. data/spec/acceptance/one_character_identifier_spec.rb +2 -2
  22. data/spec/acceptance/raw_block_spec.rb +1 -1
  23. data/spec/acceptance/runtime_run_spec.rb +1 -1
  24. data/spec/acceptance/sections_spec.rb +3 -3
  25. data/spec/acceptance/segment_literals_spec.rb +3 -3
  26. data/spec/acceptance/simple_expression_spec.rb +3 -3
  27. data/spec/acceptance/subexpression_spec.rb +37 -0
  28. data/spec/acceptance/unless_spec.rb +48 -0
  29. data/spec/fixtures/if_else.hbs +3 -3
  30. data/spec/fixtures/unless.hbs +5 -0
  31. data/spec/lib/flavour_saver/lexer_spec.rb +104 -28
  32. data/spec/lib/flavour_saver/parser_spec.rb +115 -82
  33. data/spec/lib/flavour_saver/runtime_spec.rb +44 -33
  34. metadata +27 -72
  35. data/.travis.yml +0 -14
  36. data/Guardfile +0 -12
@@ -5,18 +5,18 @@ describe FlavourSaver::Parser do
5
5
  let (:items) { subject.items }
6
6
 
7
7
  it 'is a RLTK::Parser' do
8
- subject.should be_a(RLTK::Parser)
8
+ expect(subject).to be_a(RLTK::Parser)
9
9
  end
10
10
 
11
11
  describe 'HTML template' do
12
12
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('<html><h1>Hello world!</h1></html>')) }
13
13
 
14
14
  it 'is an output node' do
15
- items.first.should be_a(FlavourSaver::OutputNode)
15
+ expect(items.first).to be_a(FlavourSaver::OutputNode)
16
16
  end
17
17
 
18
18
  it 'has the correct contents' do
19
- items.first.value.should == '<html><h1>Hello world!</h1></html>'
19
+ expect(items.first.value).to eq '<html><h1>Hello world!</h1></html>'
20
20
  end
21
21
  end
22
22
 
@@ -24,7 +24,7 @@ describe FlavourSaver::Parser do
24
24
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('<html>{{foo}}</html>')) }
25
25
 
26
26
  it 'has template output either side of the expression' do
27
- items.map(&:class).should == [FlavourSaver::OutputNode, FlavourSaver::ExpressionNode, FlavourSaver::OutputNode]
27
+ expect(items.map(&:class)).to eq [FlavourSaver::OutputNode, FlavourSaver::ExpressionNode, FlavourSaver::OutputNode]
28
28
  end
29
29
  end
30
30
 
@@ -32,14 +32,14 @@ describe FlavourSaver::Parser do
32
32
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo}}')) }
33
33
 
34
34
  it 'contains an expression node' do
35
- items.first.should be_an(FlavourSaver::ExpressionNode)
35
+ expect(items.first).to be_a(FlavourSaver::ExpressionNode)
36
36
  end
37
37
 
38
38
  it 'calls the method "foo" with no arguments' do
39
- items.first.method.should be_one
40
- items.first.method.first.should be_a(FlavourSaver::CallNode)
41
- items.first.method.first.name.should == 'foo'
42
- items.first.method.first.arguments.should be_empty
39
+ expect(items.first.method).to be_one
40
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
41
+ expect(items.first.method.first.name).to eq 'foo'
42
+ expect(items.first.method.first.arguments).to be_empty
43
43
  end
44
44
  end
45
45
 
@@ -47,19 +47,19 @@ describe FlavourSaver::Parser do
47
47
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo.bar}}')) }
48
48
 
49
49
  it 'calls two methods' do
50
- items.first.method.size.should == 2
50
+ expect(items.first.method.size).to eq 2
51
51
  end
52
52
 
53
53
  it 'calls the method "foo" with no arguments first' do
54
- items.first.method.first.should be_a(FlavourSaver::CallNode)
55
- items.first.method.first.name.should == 'foo'
56
- items.first.method.first.arguments.should be_empty
54
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
55
+ expect(items.first.method.first.name).to eq 'foo'
56
+ expect(items.first.method.first.arguments).to be_empty
57
57
  end
58
58
 
59
59
  it 'calls the method "bar" with no arguments second' do
60
- items.first.method[1].should be_a(FlavourSaver::CallNode)
61
- items.first.method[1].name.should == 'bar'
62
- items.first.method[1].arguments.should be_empty
60
+ expect(items.first.method[1]).to be_a(FlavourSaver::CallNode)
61
+ expect(items.first.method[1].name).to eq 'bar'
62
+ expect(items.first.method[1].arguments).to be_empty
63
63
  end
64
64
  end
65
65
 
@@ -67,25 +67,25 @@ describe FlavourSaver::Parser do
67
67
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo.[&@^$*].bar}}')) }
68
68
 
69
69
  it 'calls three methods' do
70
- items.first.method.size.should == 3
70
+ expect(items.first.method.size).to eq 3
71
71
  end
72
72
 
73
73
  it 'calls the method "foo" with no arguments first' do
74
- items.first.method.first.should be_a(FlavourSaver::CallNode)
75
- items.first.method.first.name.should == 'foo'
76
- items.first.method.first.arguments.should be_empty
74
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
75
+ expect(items.first.method.first.name).to eq 'foo'
76
+ expect(items.first.method.first.arguments).to be_empty
77
77
  end
78
78
 
79
79
  it 'calls the method "&@^$*" with no arguments second' do
80
- items.first.method[1].should be_a(FlavourSaver::CallNode)
81
- items.first.method[1].name.should == '&@^$*'
82
- items.first.method[1].arguments.should be_empty
80
+ expect(items.first.method[1]).to be_a(FlavourSaver::CallNode)
81
+ expect(items.first.method[1].name).to eq '&@^$*'
82
+ expect(items.first.method[1].arguments).to be_empty
83
83
  end
84
84
 
85
85
  it 'calls the method "bar" with no arguments third' do
86
- items.first.method[2].should be_a(FlavourSaver::CallNode)
87
- items.first.method[2].name.should == 'bar'
88
- items.first.method[2].arguments.should be_empty
86
+ expect(items.first.method[2]).to be_a(FlavourSaver::CallNode)
87
+ expect(items.first.method[2].name).to eq 'bar'
88
+ expect(items.first.method[2].arguments).to be_empty
89
89
  end
90
90
  end
91
91
 
@@ -93,12 +93,12 @@ describe FlavourSaver::Parser do
93
93
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar}}')) }
94
94
 
95
95
  it 'calls the method "foo" with a method argument of "bar"' do
96
- items.first.method.should be_one
97
- items.first.method.first.should be_a(FlavourSaver::CallNode)
98
- items.first.method.first.name.should == 'foo'
99
- items.first.method.first.arguments.should be_one
100
- items.first.method.first.arguments.first.first.should be_a(FlavourSaver::CallNode)
101
- items.first.method.first.arguments.first.first.name.should == 'bar'
96
+ expect(items.first.method).to be_one
97
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
98
+ expect(items.first.method.first.name).to eq 'foo'
99
+ expect(items.first.method.first.arguments).to be_one
100
+ expect(items.first.method.first.arguments.first.first).to be_a(FlavourSaver::CallNode)
101
+ expect(items.first.method.first.arguments.first.first.name).to eq 'bar'
102
102
  end
103
103
  end
104
104
 
@@ -106,12 +106,12 @@ describe FlavourSaver::Parser do
106
106
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo "bar" }}')) }
107
107
 
108
108
  it 'calls the method "foo" with a string argument of "bar"' do
109
- items.first.method.should be_one
110
- items.first.method.first.should be_a(FlavourSaver::CallNode)
111
- items.first.method.first.name.should == 'foo'
112
- items.first.method.first.arguments.should be_one
113
- items.first.method.first.arguments.first.should be_a(FlavourSaver::StringNode)
114
- items.first.method.first.arguments.first.value.should == 'bar'
109
+ expect(items.first.method).to be_one
110
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
111
+ expect(items.first.method.first.name).to eq 'foo'
112
+ expect(items.first.method.first.arguments).to be_one
113
+ expect(items.first.method.first.arguments.first).to be_a(FlavourSaver::StringNode)
114
+ expect(items.first.method.first.arguments.first.value).to eq 'bar'
115
115
  end
116
116
  end
117
117
 
@@ -119,9 +119,9 @@ describe FlavourSaver::Parser do
119
119
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar "baz" }}')) }
120
120
 
121
121
  it 'calls the method "foo"' do
122
- items.first.method.should be_one
123
- items.first.method.first.should be_a(FlavourSaver::CallNode)
124
- items.first.method.first.name.should == 'foo'
122
+ expect(items.first.method).to be_one
123
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
124
+ expect(items.first.method.first.name).to eq 'foo'
125
125
  end
126
126
 
127
127
  describe 'with arguments' do
@@ -129,28 +129,61 @@ describe FlavourSaver::Parser do
129
129
 
130
130
  describe '[0]' do
131
131
  it 'is the method call "bar" with no arguments' do
132
- subject.first.first.should be_a(FlavourSaver::CallNode)
133
- subject.first.first.name.should == 'bar'
132
+ expect(subject.first.first).to be_a(FlavourSaver::CallNode)
133
+ expect(subject.first.first.name).to eq 'bar'
134
134
  end
135
135
  end
136
136
 
137
137
  describe '[1]' do
138
138
  it 'is the string "baz"' do
139
- subject[1].should be_a(FlavourSaver::StringNode)
140
- subject[1].value.should == 'baz'
139
+ expect(subject[1]).to be_a(FlavourSaver::StringNode)
140
+ expect(subject[1].value).to eq 'baz'
141
141
  end
142
142
  end
143
143
  end
144
144
  end
145
145
 
146
+ describe '{{foo (bar "baz") }}' do
147
+ subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo (bar "baz") }}')) }
148
+
149
+ it 'calls the method "foo"' do
150
+ expect(items.first.method).to be_one
151
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
152
+ expect(items.first.method.first.name).to eq 'foo'
153
+ end
154
+
155
+ describe 'with arguments' do
156
+ subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo (bar "baz") }}')).items.first.method.first.arguments }
157
+
158
+ describe '[0]' do
159
+ it 'is a subexpression' do
160
+ expect(subject.first.first).to be_a(FlavourSaver::CallNode)
161
+ expect(subject.first.first.name).to eq 'bar'
162
+ end
163
+ end
164
+
165
+ end
166
+ end
167
+
146
168
  describe '{{foo bar="baz"}}' do
147
169
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz"}}')) }
148
170
 
149
171
  it 'calls the method "foo" with the hash {:bar => "baz"} as arguments' do
150
- items.first.method.first.should be_a(FlavourSaver::CallNode)
151
- items.first.method.first.name.should == 'foo'
152
- items.first.method.first.arguments.first.should be_a(Hash)
153
- items.first.method.first.arguments.first.should == { :bar => FlavourSaver::StringNode.new('baz') }
172
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
173
+ expect(items.first.method.first.name).to eq 'foo'
174
+ expect(items.first.method.first.arguments.first).to be_a(Hash)
175
+ expect(items.first.method.first.arguments.first).to eq({ :bar => FlavourSaver::StringNode.new('baz') })
176
+ end
177
+ end
178
+
179
+ describe '{{foo bar=(baz "qux")}}' do
180
+ subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar=(baz "qux")}}')) }
181
+
182
+ it 'calls the method "foo" with the hash {:bar => (baz "qux")} as arguments' do
183
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
184
+ expect(items.first.method.first.name).to eq 'foo'
185
+ expect(items.first.method.first.arguments.first).to be_a(Hash)
186
+ expect(items.first.method.first.arguments.first[:bar].first).to be_a(FlavourSaver::CallNode)
154
187
  end
155
188
  end
156
189
 
@@ -158,14 +191,14 @@ describe FlavourSaver::Parser do
158
191
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{foo bar=1}}")) }
159
192
 
160
193
  it "doesn't throw a NotInLanguage exception" do
161
- -> { subject }.should_not raise_error
194
+ expect { subject }.to_not raise_error
162
195
  end
163
196
 
164
197
  it 'calls the method "foo" with the hash {:bar => 1} as arguments' do
165
- items.first.method.first.should be_a(FlavourSaver::CallNode)
166
- items.first.method.first.name.should == 'foo'
167
- items.first.method.first.arguments.first.should be_a(Hash)
168
- items.first.method.first.arguments.first.should == { :bar => FlavourSaver::NumberNode.new('1') }
198
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
199
+ expect(items.first.method.first.name).to eq 'foo'
200
+ expect(items.first.method.first.arguments.first).to be_a(Hash)
201
+ expect(items.first.method.first.arguments.first).to eq({ :bar => FlavourSaver::NumberNode.new('1') })
169
202
  end
170
203
  end
171
204
 
@@ -173,10 +206,10 @@ describe FlavourSaver::Parser do
173
206
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz" fred="wilma"}}')) }
174
207
 
175
208
  it 'calls the method "foo" with the hash {:bar => "baz", :fred => "wilma"} as arguments' do
176
- items.first.method.first.should be_a(FlavourSaver::CallNode)
177
- items.first.method.first.name.should == 'foo'
178
- items.first.method.first.arguments.first.should be_a(Hash)
179
- items.first.method.first.arguments.first.should == { :bar => FlavourSaver::StringNode.new('baz'), :fred => FlavourSaver::StringNode.new('wilma') }
209
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
210
+ expect(items.first.method.first.name).to eq 'foo'
211
+ expect(items.first.method.first.arguments.first).to be_a(Hash)
212
+ expect(items.first.method.first.arguments.first).to eq({ :bar => FlavourSaver::StringNode.new('baz'), :fred => FlavourSaver::StringNode.new('wilma') })
180
213
  end
181
214
  end
182
215
 
@@ -184,7 +217,7 @@ describe FlavourSaver::Parser do
184
217
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz" fred "wilma"}}')) }
185
218
 
186
219
  it 'raises an exception' do
187
- -> { subject }.should raise_exception(RLTK::NotInLanguage)
220
+ expect { subject }.to raise_exception(RLTK::NotInLanguage)
188
221
  end
189
222
  end
190
223
 
@@ -192,7 +225,7 @@ describe FlavourSaver::Parser do
192
225
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{{foo}}}')) }
193
226
 
194
227
  it 'returns a safe expression node' do
195
- items.first.should be_a(FlavourSaver::SafeExpressionNode)
228
+ expect(items.first).to be_a(FlavourSaver::SafeExpressionNode)
196
229
  end
197
230
  end
198
231
 
@@ -200,7 +233,7 @@ describe FlavourSaver::Parser do
200
233
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{../foo}}')) }
201
234
 
202
235
  it 'returns a parent call node' do
203
- items.first.method.first.should be_a(FlavourSaver::ParentCallNode)
236
+ expect(items.first.method.first).to be_a(FlavourSaver::ParentCallNode)
204
237
  end
205
238
  end
206
239
 
@@ -208,7 +241,7 @@ describe FlavourSaver::Parser do
208
241
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{! comment}}')) }
209
242
 
210
243
  it 'returns a comment node' do
211
- items.first.should be_a(FlavourSaver::CommentNode)
244
+ expect(items.first).to be_a(FlavourSaver::CommentNode)
212
245
  end
213
246
  end
214
247
 
@@ -216,14 +249,14 @@ describe FlavourSaver::Parser do
216
249
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}hello{{/foo}}')) }
217
250
 
218
251
  it 'has a block start and end' do
219
- items.map(&:class).should == [ FlavourSaver::BlockExpressionNode ]
252
+ expect(items.map(&:class)).to eq [ FlavourSaver::BlockExpressionNode ]
220
253
  end
221
254
 
222
255
  describe '#contents' do
223
256
  it 'contains a single output node' do
224
- items.first.contents.items.size.should == 1
225
- items.first.contents.items.first.should be_a(FlavourSaver::OutputNode)
226
- items.first.contents.items.first.value.should == 'hello'
257
+ expect(items.first.contents.items.size).to eq 1
258
+ expect(items.first.contents.items.first).to be_a(FlavourSaver::OutputNode)
259
+ expect(items.first.contents.items.first.value).to eq 'hello'
227
260
  end
228
261
  end
229
262
  end
@@ -232,7 +265,7 @@ describe FlavourSaver::Parser do
232
265
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{/foo}}')) }
233
266
 
234
267
  it 'raises a syntax error' do
235
- -> { subject }.should raise_error
268
+ expect { subject }.to raise_error(RLTK::NotInLanguage)
236
269
  end
237
270
  end
238
271
 
@@ -240,7 +273,7 @@ describe FlavourSaver::Parser do
240
273
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}')) }
241
274
 
242
275
  it 'raises a syntax error' do
243
- -> { subject }.should raise_error
276
+ expect { subject }.to raise_error(RLTK::NotInLanguage)
244
277
  end
245
278
  end
246
279
 
@@ -248,7 +281,7 @@ describe FlavourSaver::Parser do
248
281
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{foo}}\n")) }
249
282
 
250
283
  it 'has a block start and end' do
251
- items.map(&:class).should == [ FlavourSaver::ExpressionNode, FlavourSaver::OutputNode ]
284
+ expect(items.map(&:class)).to eq [ FlavourSaver::ExpressionNode, FlavourSaver::OutputNode ]
252
285
  end
253
286
  end
254
287
 
@@ -256,7 +289,7 @@ describe FlavourSaver::Parser do
256
289
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}{{#bar}}{{/foo}}')) }
257
290
 
258
291
  it 'raises a syntax error' do
259
- -> { subject }.should raise_error
292
+ expect { subject }.to raise_error(FlavourSaver::Parser::UnbalancedBlockError)
260
293
  end
261
294
  end
262
295
 
@@ -264,7 +297,7 @@ describe FlavourSaver::Parser do
264
297
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo}}\n{{/foo}}")) }
265
298
 
266
299
  it "doesn't throw a NotInLanguage exception" do
267
- -> { subject }.should_not raise_error
300
+ expect { subject }.to_not raise_error
268
301
  end
269
302
  end
270
303
 
@@ -275,8 +308,8 @@ describe FlavourSaver::Parser do
275
308
  let(:block) { subject.items.first }
276
309
 
277
310
  it 'should contain another block' do
278
- block.contents.items.size.should == 1
279
- block.contents.items.first.should be_a(FlavourSaver::BlockExpressionNode)
311
+ expect(block.contents.items.size).to eq 1
312
+ expect(block.contents.items.first).to be_a(FlavourSaver::BlockExpressionNode)
280
313
  end
281
314
  end
282
315
  end
@@ -285,7 +318,7 @@ describe FlavourSaver::Parser do
285
318
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo bar 'baz'}}{{/foo}}")) }
286
319
 
287
320
  it "doesn't throw a NotInLanguage exception" do
288
- -> { subject }.should_not raise_error
321
+ expect { subject }.to_not raise_error
289
322
  end
290
323
  end
291
324
 
@@ -293,25 +326,25 @@ describe FlavourSaver::Parser do
293
326
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo bar 'baz' }}{{/foo}}")) }
294
327
 
295
328
  it "doesn't throw a NotInLanguage exception" do
296
- -> { subject }.should_not raise_error
329
+ expect { subject }.to_not raise_error
297
330
  end
298
331
  end
299
332
  describe '' do
300
333
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('')) }
301
334
 
302
335
  it 'returns an empty template' do
303
- items.should be_empty
336
+ expect(items).to be_empty
304
337
  end
305
338
  end
306
339
  describe '{{foo "bar" fred="wilma"}}' do
307
340
  subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo "bar" fred="wilma"}}')) }
308
341
  it 'calls the method "foo" with the "bar" and {:fred => "wilma"} as arguments' do
309
- items.first.method.first.should be_a(FlavourSaver::CallNode)
310
- items.first.method.first.name.should == 'foo'
311
- items.first.method.first.arguments.first.should be_a(FlavourSaver::StringNode)
312
- items.first.method.first.arguments.first.value.should == 'bar'
313
- items.first.method.first.arguments.last.should be_a(Hash)
314
- items.first.method.first.arguments.last.should == { :fred => FlavourSaver::StringNode.new('wilma') }
342
+ expect(items.first.method.first).to be_a(FlavourSaver::CallNode)
343
+ expect(items.first.method.first.name).to eq 'foo'
344
+ expect(items.first.method.first.arguments.first).to be_a(FlavourSaver::StringNode)
345
+ expect(items.first.method.first.arguments.first.value).to eq 'bar'
346
+ expect(items.first.method.first.arguments.last).to be_a(Hash)
347
+ expect(items.first.method.first.arguments.last).to eq({ :fred => FlavourSaver::StringNode.new('wilma') })
315
348
  end
316
349
  end
317
350
  end
@@ -12,7 +12,7 @@ describe FlavourSaver::Runtime do
12
12
  let(:template) { "hello world" }
13
13
 
14
14
  it "concatenates all the nodes items together" do
15
- subject.evaluate_node(ast).should == 'hello world'
15
+ expect(subject.evaluate_node(ast)).to eq 'hello world'
16
16
  end
17
17
  end
18
18
 
@@ -21,7 +21,7 @@ describe FlavourSaver::Runtime do
21
21
 
22
22
  it "returns the value of OutputNodes" do
23
23
  node = ast.items.first
24
- subject.evaluate_node(node).should == 'hello world'
24
+ expect(subject.evaluate_node(node)).to eq 'hello world'
25
25
  end
26
26
  end
27
27
 
@@ -30,7 +30,7 @@ describe FlavourSaver::Runtime do
30
30
  let(:node) { ast.items.select { |n| n.class == FlavourSaver::ExpressionNode }.first.method.first.arguments.first }
31
31
 
32
32
  it 'returns the value of the string' do
33
- subject.evaluate_node(node).should == 'WAT'
33
+ expect(subject.evaluate_node(node)).to eq 'WAT'
34
34
  end
35
35
  end
36
36
 
@@ -39,13 +39,13 @@ describe FlavourSaver::Runtime do
39
39
  let (:template) { "{{foo}}" }
40
40
 
41
41
  it 'calls evaluate_node with the node' do
42
- subject.should_receive(:evaluate_expression).with(node)
42
+ expect(subject).to receive(:evaluate_expression).with(node)
43
43
  subject.evaluate_node(node)
44
44
  end
45
45
 
46
46
  it 'should HTML escape the output' do
47
- context.should_receive(:foo).and_return("<html>LOL</html>")
48
- subject.evaluate_node(node).should == '&lt;html&gt;LOL&lt;/html&gt;'
47
+ expect(context).to receive(:foo).and_return("<html>LOL</html>")
48
+ expect(subject.evaluate_node(node)).to eq '&lt;html&gt;LOL&lt;/html&gt;'
49
49
  end
50
50
  end
51
51
 
@@ -54,8 +54,8 @@ describe FlavourSaver::Runtime do
54
54
  let (:template) { "{{{foo}}}" }
55
55
 
56
56
  it 'should not HTML escape the output' do
57
- context.should_receive(:foo).and_return("<html>LOL</html>")
58
- subject.evaluate_node(node).should == '<html>LOL</html>'
57
+ expect(context).to receive(:foo).and_return("<html>LOL</html>")
58
+ expect(subject.evaluate_node(node)).to eq '<html>LOL</html>'
59
59
  end
60
60
  end
61
61
 
@@ -64,7 +64,7 @@ describe FlavourSaver::Runtime do
64
64
  let(:node) { ast.items.select { |n| n.class == FlavourSaver::CommentNode }.first }
65
65
 
66
66
  it 'should return zilch' do
67
- subject.evaluate_node(node).should == ''
67
+ expect(subject.evaluate_node(node)).to eq ''
68
68
  end
69
69
  end
70
70
 
@@ -72,8 +72,8 @@ describe FlavourSaver::Runtime do
72
72
  let(:template) { "{{#foo}}bar{{/foo}}baz" }
73
73
 
74
74
  it 'snatches up the block contents and skips them from evaluation' do
75
- context.stub(:foo)
76
- subject.evaluate_node(ast).should == 'baz'
75
+ allow(context).to receive(:foo)
76
+ expect(subject.evaluate_node(ast)).to eq 'baz'
77
77
  end
78
78
  end
79
79
  end
@@ -86,8 +86,8 @@ describe FlavourSaver::Runtime do
86
86
  let (:template) { "{{foo}}" }
87
87
 
88
88
  it 'calls the method and return the result' do
89
- context.should_receive(:foo).and_return('foo result')
90
- subject.evaluate_expression(expr).should == 'foo result'
89
+ expect(context).to receive(:foo).and_return('foo result')
90
+ expect(subject.evaluate_expression(expr)).to eq 'foo result'
91
91
  end
92
92
  end
93
93
 
@@ -95,8 +95,8 @@ describe FlavourSaver::Runtime do
95
95
  let(:template) { "{{hello \"world\"}}" }
96
96
 
97
97
  it 'calls the method with the arguments and return the result' do
98
- context.should_receive(:hello).with("world").and_return("hello world")
99
- subject.evaluate_expression(expr).should == 'hello world'
98
+ expect(context).to receive(:hello).with("world").and_return("hello world")
99
+ expect(subject.evaluate_expression(expr)).to eq 'hello world'
100
100
  end
101
101
  end
102
102
 
@@ -104,9 +104,20 @@ describe FlavourSaver::Runtime do
104
104
  let(:template) { "{{hello world}}" }
105
105
 
106
106
  it 'calls hello & world on the context and return the result' do
107
- context.should_receive(:world).and_return('world')
108
- context.should_receive(:hello).with('world').and_return('hello world')
109
- subject.evaluate_expression(expr).should == 'hello world'
107
+ expect(context).to receive(:world).and_return('world')
108
+ expect(context).to receive(:hello).with('world').and_return('hello world')
109
+ expect(subject.evaluate_expression(expr)).to eq 'hello world'
110
+ end
111
+ end
112
+
113
+ describe 'when called with a subexpression' do
114
+ let(:template) { "{{hello (there world)}}" }
115
+
116
+ it 'calls there & world first, then passes off to hello' do
117
+ expect(context).to receive(:world).and_return('world')
118
+ expect(context).to receive(:there).with('world').and_return('there world')
119
+ expect(context).to receive(:hello).with('there world').and_return('hello there world')
120
+ expect(subject.evaluate_expression(expr)).to eq 'hello there world'
110
121
  end
111
122
  end
112
123
 
@@ -114,8 +125,8 @@ describe FlavourSaver::Runtime do
114
125
  let(:template) { "{{hello.world}}" }
115
126
 
116
127
  it 'calls world on the result of hello' do
117
- context.stub_chain(:hello, :world).and_return('hello world')
118
- subject.evaluate_expression(expr).should == 'hello world'
128
+ allow(context).to receive_message_chain(:hello, :world).and_return('hello world')
129
+ expect(subject.evaluate_expression(expr)).to eq 'hello world'
119
130
  end
120
131
  end
121
132
 
@@ -123,8 +134,8 @@ describe FlavourSaver::Runtime do
123
134
  let(:template) { "{{[WAT]}}" }
124
135
 
125
136
  it 'indexes the context with WAT' do
126
- context.should_receive(:[]).with('WAT').and_return 'w00t'
127
- subject.evaluate_expression(expr).should == 'w00t'
137
+ expect(context).to receive(:[]).with('WAT').and_return 'w00t'
138
+ expect(subject.evaluate_expression(expr)).to eq 'w00t'
128
139
  end
129
140
  end
130
141
 
@@ -133,11 +144,11 @@ describe FlavourSaver::Runtime do
133
144
 
134
145
  it 'indexes the result of hello and calls world on it' do
135
146
  world = double(:world)
136
- world.should_receive(:world).and_return('vr00m')
147
+ expect(world).to receive(:world).and_return('vr00m')
137
148
  hash = double(:hash)
138
- hash.should_receive(:[]).with('WAT').and_return(world)
139
- context.should_receive(:hello).and_return(hash)
140
- subject.evaluate_expression(expr).should == 'vr00m'
149
+ expect(hash).to receive(:[]).with('WAT').and_return(world)
150
+ expect(context).to receive(:hello).and_return(hash)
151
+ expect(subject.evaluate_expression(expr)).to eq 'vr00m'
141
152
  end
142
153
  end
143
154
 
@@ -145,7 +156,7 @@ describe FlavourSaver::Runtime do
145
156
  let (:template) { "{{../foo}}" }
146
157
 
147
158
  it 'raises an error' do
148
- -> { subject.evaluate_expression(expr) }.should raise_error(FlavourSaver::UnknownContextException)
159
+ expect { subject.evaluate_expression(expr) }.to raise_error(FlavourSaver::UnknownContextException)
149
160
  end
150
161
  end
151
162
 
@@ -153,7 +164,7 @@ describe FlavourSaver::Runtime do
153
164
  let (:template) { '{{foo bar="baz"}}' }
154
165
 
155
166
  it 'receives the argument as a hash' do
156
- context.should_receive(:foo).with({:bar => 'baz'})
167
+ expect(context).to receive(:foo).with({:bar => 'baz'})
157
168
  subject.evaluate_expression(expr)
158
169
  end
159
170
  end
@@ -162,8 +173,8 @@ describe FlavourSaver::Runtime do
162
173
  let (:template) { "{{foo bar=baz}}" }
163
174
 
164
175
  it 'calls the value and returns it\'s result in the hash' do
165
- context.should_receive(:baz).and_return('OMGLOLWAT')
166
- context.should_receive(:foo).with({:bar => 'OMGLOLWAT'})
176
+ expect(context).to receive(:baz).and_return('OMGLOLWAT')
177
+ expect(context).to receive(:foo).with({:bar => 'OMGLOLWAT'})
167
178
  subject.evaluate_expression(expr)
168
179
  end
169
180
  end
@@ -175,15 +186,15 @@ describe FlavourSaver::Runtime do
175
186
  let(:block) { ast.items.first }
176
187
 
177
188
  it 'creates a new runtime' do
178
- subject.should_receive(:create_child_runtime)
179
- context.stub(:foo)
189
+ expect(subject).to receive(:create_child_runtime)
190
+ allow(context).to receive(:foo)
180
191
  subject.evaluate_block(block, context)
181
192
  end
182
193
  end
183
194
 
184
195
  describe '#create_child_runtime' do
185
196
  it 'creates a new runtime' do
186
- subject.create_child_runtime([]).should be_a(FlavourSaver::Runtime)
197
+ expect(subject.create_child_runtime([])).to be_a(FlavourSaver::Runtime)
187
198
  end
188
199
  end
189
200