flavour_saver 0.3.9 → 2.0.1
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 +5 -5
- data/.github/workflows/ci.yml +47 -0
- data/CHANGELOG.md +46 -0
- data/Gemfile.lock +34 -62
- data/README.md +3 -10
- data/flavour_saver.gemspec +14 -9
- data/lib/flavour_saver/helpers.rb +28 -16
- data/lib/flavour_saver/lexer.rb +1 -1
- data/lib/flavour_saver/parser.rb +14 -8
- data/lib/flavour_saver/runtime.rb +7 -7
- data/lib/flavour_saver/version.rb +1 -1
- data/spec/acceptance/backtrack_spec.rb +1 -1
- data/spec/acceptance/comment_spec.rb +1 -1
- data/spec/acceptance/custom_block_helper_spec.rb +2 -2
- data/spec/acceptance/custom_helper_spec.rb +1 -1
- data/spec/acceptance/ensure_no_rce_spec.rb +2 -2
- data/spec/acceptance/handlebars_qunit_spec.rb +297 -219
- data/spec/acceptance/if_else_spec.rb +37 -6
- data/spec/acceptance/multi_level_with_spec.rb +1 -1
- data/spec/acceptance/one_character_identifier_spec.rb +2 -2
- data/spec/acceptance/raw_block_spec.rb +1 -1
- data/spec/acceptance/runtime_run_spec.rb +1 -1
- data/spec/acceptance/sections_spec.rb +3 -3
- data/spec/acceptance/segment_literals_spec.rb +3 -3
- data/spec/acceptance/simple_expression_spec.rb +3 -3
- data/spec/acceptance/subexpression_spec.rb +4 -5
- data/spec/acceptance/unless_spec.rb +48 -0
- data/spec/fixtures/if_else.hbs +3 -3
- data/spec/fixtures/unless.hbs +5 -0
- data/spec/lib/flavour_saver/lexer_spec.rb +67 -36
- data/spec/lib/flavour_saver/parser_spec.rb +91 -91
- data/spec/lib/flavour_saver/runtime_spec.rb +37 -37
- metadata +25 -72
- data/.travis.yml +0 -18
- 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.
|
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.
|
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.
|
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).
|
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.
|
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.
|
40
|
-
items.first.method.first.
|
41
|
-
items.first.method.first.name.
|
42
|
-
items.first.method.first.arguments.
|
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.
|
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.
|
55
|
-
items.first.method.first.name.
|
56
|
-
items.first.method.first.arguments.
|
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].
|
61
|
-
items.first.method[1].name.
|
62
|
-
items.first.method[1].arguments.
|
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.
|
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.
|
75
|
-
items.first.method.first.name.
|
76
|
-
items.first.method.first.arguments.
|
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].
|
81
|
-
items.first.method[1].name.
|
82
|
-
items.first.method[1].arguments.
|
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].
|
87
|
-
items.first.method[2].name.
|
88
|
-
items.first.method[2].arguments.
|
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.
|
97
|
-
items.first.method.first.
|
98
|
-
items.first.method.first.name.
|
99
|
-
items.first.method.first.arguments.
|
100
|
-
items.first.method.first.arguments.first.first.
|
101
|
-
items.first.method.first.arguments.first.first.name.
|
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.
|
110
|
-
items.first.method.first.
|
111
|
-
items.first.method.first.name.
|
112
|
-
items.first.method.first.arguments.
|
113
|
-
items.first.method.first.arguments.first.
|
114
|
-
items.first.method.first.arguments.first.value.
|
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.
|
123
|
-
items.first.method.first.
|
124
|
-
items.first.method.first.name.
|
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,15 +129,15 @@ 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.
|
133
|
-
subject.first.first.name.
|
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].
|
140
|
-
subject[1].value.
|
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
|
@@ -147,9 +147,9 @@ describe FlavourSaver::Parser do
|
|
147
147
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo (bar "baz") }}')) }
|
148
148
|
|
149
149
|
it 'calls the method "foo"' do
|
150
|
-
items.first.method.
|
151
|
-
items.first.method.first.
|
152
|
-
items.first.method.first.name.
|
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
153
|
end
|
154
154
|
|
155
155
|
describe 'with arguments' do
|
@@ -157,8 +157,8 @@ describe FlavourSaver::Parser do
|
|
157
157
|
|
158
158
|
describe '[0]' do
|
159
159
|
it 'is a subexpression' do
|
160
|
-
subject.first.first.
|
161
|
-
subject.first.first.name.
|
160
|
+
expect(subject.first.first).to be_a(FlavourSaver::CallNode)
|
161
|
+
expect(subject.first.first.name).to eq 'bar'
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
@@ -169,10 +169,10 @@ describe FlavourSaver::Parser do
|
|
169
169
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz"}}')) }
|
170
170
|
|
171
171
|
it 'calls the method "foo" with the hash {:bar => "baz"} as arguments' do
|
172
|
-
items.first.method.first.
|
173
|
-
items.first.method.first.name.
|
174
|
-
items.first.method.first.arguments.first.
|
175
|
-
items.first.method.first.arguments.first.
|
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
176
|
end
|
177
177
|
end
|
178
178
|
|
@@ -180,10 +180,10 @@ describe FlavourSaver::Parser do
|
|
180
180
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar=(baz "qux")}}')) }
|
181
181
|
|
182
182
|
it 'calls the method "foo" with the hash {:bar => (baz "qux")} as arguments' do
|
183
|
-
items.first.method.first.
|
184
|
-
items.first.method.first.name.
|
185
|
-
items.first.method.first.arguments.first.
|
186
|
-
items.first.method.first.arguments.first[:bar].first.
|
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)
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
@@ -191,14 +191,14 @@ describe FlavourSaver::Parser do
|
|
191
191
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{foo bar=1}}")) }
|
192
192
|
|
193
193
|
it "doesn't throw a NotInLanguage exception" do
|
194
|
-
|
194
|
+
expect { subject }.to_not raise_error
|
195
195
|
end
|
196
196
|
|
197
197
|
it 'calls the method "foo" with the hash {:bar => 1} as arguments' do
|
198
|
-
items.first.method.first.
|
199
|
-
items.first.method.first.name.
|
200
|
-
items.first.method.first.arguments.first.
|
201
|
-
items.first.method.first.arguments.first.
|
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') })
|
202
202
|
end
|
203
203
|
end
|
204
204
|
|
@@ -206,10 +206,10 @@ describe FlavourSaver::Parser do
|
|
206
206
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz" fred="wilma"}}')) }
|
207
207
|
|
208
208
|
it 'calls the method "foo" with the hash {:bar => "baz", :fred => "wilma"} as arguments' do
|
209
|
-
items.first.method.first.
|
210
|
-
items.first.method.first.name.
|
211
|
-
items.first.method.first.arguments.first.
|
212
|
-
items.first.method.first.arguments.first.
|
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') })
|
213
213
|
end
|
214
214
|
end
|
215
215
|
|
@@ -217,7 +217,7 @@ describe FlavourSaver::Parser do
|
|
217
217
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo bar="baz" fred "wilma"}}')) }
|
218
218
|
|
219
219
|
it 'raises an exception' do
|
220
|
-
|
220
|
+
expect { subject }.to raise_exception(RLTK::NotInLanguage)
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
@@ -225,7 +225,7 @@ describe FlavourSaver::Parser do
|
|
225
225
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{{foo}}}')) }
|
226
226
|
|
227
227
|
it 'returns a safe expression node' do
|
228
|
-
items.first.
|
228
|
+
expect(items.first).to be_a(FlavourSaver::SafeExpressionNode)
|
229
229
|
end
|
230
230
|
end
|
231
231
|
|
@@ -233,7 +233,7 @@ describe FlavourSaver::Parser do
|
|
233
233
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{../foo}}')) }
|
234
234
|
|
235
235
|
it 'returns a parent call node' do
|
236
|
-
items.first.method.first.
|
236
|
+
expect(items.first.method.first).to be_a(FlavourSaver::ParentCallNode)
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
@@ -241,7 +241,7 @@ describe FlavourSaver::Parser do
|
|
241
241
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{! comment}}')) }
|
242
242
|
|
243
243
|
it 'returns a comment node' do
|
244
|
-
items.first.
|
244
|
+
expect(items.first).to be_a(FlavourSaver::CommentNode)
|
245
245
|
end
|
246
246
|
end
|
247
247
|
|
@@ -249,14 +249,14 @@ describe FlavourSaver::Parser do
|
|
249
249
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}hello{{/foo}}')) }
|
250
250
|
|
251
251
|
it 'has a block start and end' do
|
252
|
-
items.map(&:class).
|
252
|
+
expect(items.map(&:class)).to eq [ FlavourSaver::BlockExpressionNode ]
|
253
253
|
end
|
254
254
|
|
255
255
|
describe '#contents' do
|
256
256
|
it 'contains a single output node' do
|
257
|
-
items.first.contents.items.size.
|
258
|
-
items.first.contents.items.first.
|
259
|
-
items.first.contents.items.first.value.
|
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'
|
260
260
|
end
|
261
261
|
end
|
262
262
|
end
|
@@ -265,7 +265,7 @@ describe FlavourSaver::Parser do
|
|
265
265
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{/foo}}')) }
|
266
266
|
|
267
267
|
it 'raises a syntax error' do
|
268
|
-
|
268
|
+
expect { subject }.to raise_error(RLTK::NotInLanguage)
|
269
269
|
end
|
270
270
|
end
|
271
271
|
|
@@ -273,7 +273,7 @@ describe FlavourSaver::Parser do
|
|
273
273
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}')) }
|
274
274
|
|
275
275
|
it 'raises a syntax error' do
|
276
|
-
|
276
|
+
expect { subject }.to raise_error(RLTK::NotInLanguage)
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
@@ -281,7 +281,7 @@ describe FlavourSaver::Parser do
|
|
281
281
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{foo}}\n")) }
|
282
282
|
|
283
283
|
it 'has a block start and end' do
|
284
|
-
items.map(&:class).
|
284
|
+
expect(items.map(&:class)).to eq [ FlavourSaver::ExpressionNode, FlavourSaver::OutputNode ]
|
285
285
|
end
|
286
286
|
end
|
287
287
|
|
@@ -289,7 +289,7 @@ describe FlavourSaver::Parser do
|
|
289
289
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{#foo}}{{#bar}}{{/foo}}')) }
|
290
290
|
|
291
291
|
it 'raises a syntax error' do
|
292
|
-
|
292
|
+
expect { subject }.to raise_error(FlavourSaver::Parser::UnbalancedBlockError)
|
293
293
|
end
|
294
294
|
end
|
295
295
|
|
@@ -297,7 +297,7 @@ describe FlavourSaver::Parser do
|
|
297
297
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo}}\n{{/foo}}")) }
|
298
298
|
|
299
299
|
it "doesn't throw a NotInLanguage exception" do
|
300
|
-
|
300
|
+
expect { subject }.to_not raise_error
|
301
301
|
end
|
302
302
|
end
|
303
303
|
|
@@ -308,8 +308,8 @@ describe FlavourSaver::Parser do
|
|
308
308
|
let(:block) { subject.items.first }
|
309
309
|
|
310
310
|
it 'should contain another block' do
|
311
|
-
block.contents.items.size.
|
312
|
-
block.contents.items.first.
|
311
|
+
expect(block.contents.items.size).to eq 1
|
312
|
+
expect(block.contents.items.first).to be_a(FlavourSaver::BlockExpressionNode)
|
313
313
|
end
|
314
314
|
end
|
315
315
|
end
|
@@ -318,7 +318,7 @@ describe FlavourSaver::Parser do
|
|
318
318
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo bar 'baz'}}{{/foo}}")) }
|
319
319
|
|
320
320
|
it "doesn't throw a NotInLanguage exception" do
|
321
|
-
|
321
|
+
expect { subject }.to_not raise_error
|
322
322
|
end
|
323
323
|
end
|
324
324
|
|
@@ -326,25 +326,25 @@ describe FlavourSaver::Parser do
|
|
326
326
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex("{{#foo bar 'baz' }}{{/foo}}")) }
|
327
327
|
|
328
328
|
it "doesn't throw a NotInLanguage exception" do
|
329
|
-
|
329
|
+
expect { subject }.to_not raise_error
|
330
330
|
end
|
331
331
|
end
|
332
332
|
describe '' do
|
333
333
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('')) }
|
334
334
|
|
335
335
|
it 'returns an empty template' do
|
336
|
-
items.
|
336
|
+
expect(items).to be_empty
|
337
337
|
end
|
338
338
|
end
|
339
339
|
describe '{{foo "bar" fred="wilma"}}' do
|
340
340
|
subject { FlavourSaver::Parser.parse(FlavourSaver::Lexer.lex('{{foo "bar" fred="wilma"}}')) }
|
341
341
|
it 'calls the method "foo" with the "bar" and {:fred => "wilma"} as arguments' do
|
342
|
-
items.first.method.first.
|
343
|
-
items.first.method.first.name.
|
344
|
-
items.first.method.first.arguments.first.
|
345
|
-
items.first.method.first.arguments.first.value.
|
346
|
-
items.first.method.first.arguments.last.
|
347
|
-
items.first.method.first.arguments.last.
|
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') })
|
348
348
|
end
|
349
349
|
end
|
350
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).
|
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).
|
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).
|
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.
|
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.
|
48
|
-
subject.evaluate_node(node).
|
47
|
+
expect(context).to receive(:foo).and_return("<html>LOL</html>")
|
48
|
+
expect(subject.evaluate_node(node)).to eq '<html>LOL</html>'
|
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.
|
58
|
-
subject.evaluate_node(node).
|
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).
|
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.
|
76
|
-
subject.evaluate_node(ast).
|
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.
|
90
|
-
subject.evaluate_expression(expr).
|
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.
|
99
|
-
subject.evaluate_expression(expr).
|
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,9 @@ 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.
|
108
|
-
context.
|
109
|
-
subject.evaluate_expression(expr).
|
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
110
|
end
|
111
111
|
end
|
112
112
|
|
@@ -114,10 +114,10 @@ describe FlavourSaver::Runtime do
|
|
114
114
|
let(:template) { "{{hello (there world)}}" }
|
115
115
|
|
116
116
|
it 'calls there & world first, then passes off to hello' do
|
117
|
-
context.
|
118
|
-
context.
|
119
|
-
context.
|
120
|
-
subject.evaluate_expression(expr).
|
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'
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -125,8 +125,8 @@ describe FlavourSaver::Runtime do
|
|
125
125
|
let(:template) { "{{hello.world}}" }
|
126
126
|
|
127
127
|
it 'calls world on the result of hello' do
|
128
|
-
context.
|
129
|
-
subject.evaluate_expression(expr).
|
128
|
+
allow(context).to receive_message_chain(:hello, :world).and_return('hello world')
|
129
|
+
expect(subject.evaluate_expression(expr)).to eq 'hello world'
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
@@ -134,8 +134,8 @@ describe FlavourSaver::Runtime do
|
|
134
134
|
let(:template) { "{{[WAT]}}" }
|
135
135
|
|
136
136
|
it 'indexes the context with WAT' do
|
137
|
-
context.
|
138
|
-
subject.evaluate_expression(expr).
|
137
|
+
expect(context).to receive(:[]).with('WAT').and_return 'w00t'
|
138
|
+
expect(subject.evaluate_expression(expr)).to eq 'w00t'
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
@@ -144,11 +144,11 @@ describe FlavourSaver::Runtime do
|
|
144
144
|
|
145
145
|
it 'indexes the result of hello and calls world on it' do
|
146
146
|
world = double(:world)
|
147
|
-
world.
|
147
|
+
expect(world).to receive(:world).and_return('vr00m')
|
148
148
|
hash = double(:hash)
|
149
|
-
hash.
|
150
|
-
context.
|
151
|
-
subject.evaluate_expression(expr).
|
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'
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
@@ -156,7 +156,7 @@ describe FlavourSaver::Runtime do
|
|
156
156
|
let (:template) { "{{../foo}}" }
|
157
157
|
|
158
158
|
it 'raises an error' do
|
159
|
-
|
159
|
+
expect { subject.evaluate_expression(expr) }.to raise_error(FlavourSaver::UnknownContextException)
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
@@ -164,7 +164,7 @@ describe FlavourSaver::Runtime do
|
|
164
164
|
let (:template) { '{{foo bar="baz"}}' }
|
165
165
|
|
166
166
|
it 'receives the argument as a hash' do
|
167
|
-
context.
|
167
|
+
expect(context).to receive(:foo).with({:bar => 'baz'})
|
168
168
|
subject.evaluate_expression(expr)
|
169
169
|
end
|
170
170
|
end
|
@@ -173,8 +173,8 @@ describe FlavourSaver::Runtime do
|
|
173
173
|
let (:template) { "{{foo bar=baz}}" }
|
174
174
|
|
175
175
|
it 'calls the value and returns it\'s result in the hash' do
|
176
|
-
context.
|
177
|
-
context.
|
176
|
+
expect(context).to receive(:baz).and_return('OMGLOLWAT')
|
177
|
+
expect(context).to receive(:foo).with({:bar => 'OMGLOLWAT'})
|
178
178
|
subject.evaluate_expression(expr)
|
179
179
|
end
|
180
180
|
end
|
@@ -186,15 +186,15 @@ describe FlavourSaver::Runtime do
|
|
186
186
|
let(:block) { ast.items.first }
|
187
187
|
|
188
188
|
it 'creates a new runtime' do
|
189
|
-
subject.
|
190
|
-
context.
|
189
|
+
expect(subject).to receive(:create_child_runtime)
|
190
|
+
allow(context).to receive(:foo)
|
191
191
|
subject.evaluate_block(block, context)
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
195
|
describe '#create_child_runtime' do
|
196
196
|
it 'creates a new runtime' do
|
197
|
-
subject.create_child_runtime([]).
|
197
|
+
expect(subject.create_child_runtime([])).to be_a(FlavourSaver::Runtime)
|
198
198
|
end
|
199
199
|
end
|
200
200
|
|