1
1
import { RenderError } from '../../../src/util/error'
2
2
import { Liquid } from '../../../src/liquid'
3
- import * as path from 'path'
3
+ import { resolve } from 'path'
4
4
import { mock , restore } from '../../stub/mockfs'
5
+ import { throwIntendedError , rejectIntendedError } from '../../stub/util'
5
6
6
- let engine = new Liquid ( )
7
7
const strictEngine = new Liquid ( {
8
8
strictVariables : true ,
9
9
strictFilters : true
10
10
} )
11
+ const strictCatchingEngine = new Liquid ( {
12
+ catchAllErrors : true ,
13
+ strictVariables : true ,
14
+ strictFilters : true
15
+ } )
16
+ strictEngine . registerTag ( 'throwingTag' , { render : throwIntendedError } )
17
+ strictEngine . registerFilter ( 'throwingFilter' , throwIntendedError )
18
+ strictCatchingEngine . registerTag ( 'throwingTag' , { render : throwIntendedError } )
19
+ strictCatchingEngine . registerFilter ( 'throwingFilter' , throwIntendedError )
11
20
12
21
describe ( 'error' , function ( ) {
13
22
afterEach ( restore )
14
23
15
24
describe ( 'TokenizationError' , function ( ) {
25
+ const engine = new Liquid ( )
16
26
it ( 'should throw TokenizationError when tag illegal' , async function ( ) {
17
27
await expect ( engine . parseAndRender ( '{% . a %}' , { } ) ) . rejects . toMatchObject ( {
18
28
name : 'TokenizationError' ,
@@ -68,43 +78,34 @@ describe('error', function () {
68
78
} )
69
79
70
80
describe ( 'RenderError' , function ( ) {
81
+ let engine : Liquid
71
82
beforeEach ( function ( ) {
72
83
engine = new Liquid ( {
73
84
root : '/'
74
85
} )
75
- engine . registerTag ( 'throwingTag' , {
76
- render : function ( ) {
77
- throw new Error ( 'intended render error' )
78
- }
79
- } )
80
- engine . registerTag ( 'rejectingTag' , {
81
- render : async function ( ) {
82
- throw new Error ( 'intended render reject' )
83
- }
84
- } )
85
- engine . registerFilter ( 'throwingFilter' , ( ) => {
86
- throw new Error ( 'thrown by filter' )
87
- } )
86
+ engine . registerTag ( 'throwingTag' , { render : throwIntendedError } )
87
+ engine . registerTag ( 'rejectingTag' , { render : rejectIntendedError } )
88
+ engine . registerFilter ( 'throwingFilter' , throwIntendedError )
88
89
} )
89
90
it ( 'should throw RenderError when tag throws' , async function ( ) {
90
91
const src = '{%throwingTag%}'
91
92
await expect ( engine . parseAndRender ( src ) ) . rejects . toMatchObject ( {
92
93
name : 'RenderError' ,
93
- message : expect . stringContaining ( 'intended render error' )
94
+ message : expect . stringContaining ( 'intended error' )
94
95
} )
95
96
} )
96
97
it ( 'should throw RenderError when tag rejects' , async function ( ) {
97
98
const src = '{%rejectingTag%}'
98
99
await expect ( engine . parseAndRender ( src ) ) . rejects . toMatchObject ( {
99
100
name : 'RenderError' ,
100
- message : expect . stringContaining ( 'intended render reject' )
101
+ message : expect . stringContaining ( 'intended reject' )
101
102
} )
102
103
} )
103
104
it ( 'should throw RenderError when filter throws' , async function ( ) {
104
105
const src = '{{1|throwingFilter}}'
105
106
await expect ( engine . parseAndRender ( src ) ) . rejects . toMatchObject ( {
106
107
name : 'RenderError' ,
107
- message : expect . stringContaining ( 'thrown by filter ' )
108
+ message : expect . stringContaining ( 'intended error ' )
108
109
} )
109
110
} )
110
111
it ( 'should not throw when variable undefined by default' , async function ( ) {
@@ -113,8 +114,8 @@ describe('error', function () {
113
114
} )
114
115
it ( 'should throw RenderError when variable not defined' , async function ( ) {
115
116
await expect ( strictEngine . parseAndRender ( '{{a}}' ) ) . rejects . toMatchObject ( {
116
- name : 'RenderError ' ,
117
- message : expect . stringContaining ( 'undefined variable: a' )
117
+ name : 'UndefinedVariableError ' ,
118
+ message : 'undefined variable: a, line:1, col:3'
118
119
} )
119
120
} )
120
121
it ( 'should contain template context in err.stack' , async function ( ) {
@@ -131,7 +132,7 @@ describe('error', function () {
131
132
]
132
133
await expect ( engine . parseAndRender ( html . join ( '\n' ) ) ) . rejects . toMatchObject ( {
133
134
name : 'RenderError' ,
134
- message : 'intended render error, line:4, col:2' ,
135
+ message : 'intended error, line:4, col:2' ,
135
136
stack : expect . stringContaining ( message . join ( '\n' ) )
136
137
} )
137
138
} )
@@ -160,7 +161,7 @@ describe('error', function () {
160
161
]
161
162
await expect ( engine . parseAndRender ( html ) ) . rejects . toMatchObject ( {
162
163
name : 'RenderError' ,
163
- message : `intended render error, file:${ path . resolve ( '/throwing-tag.html' ) } , line:4, col:2` ,
164
+ message : `intended error, file:${ resolve ( '/throwing-tag.html' ) } , line:4, col:2` ,
164
165
stack : expect . stringContaining ( message . join ( '\n' ) )
165
166
} )
166
167
} )
@@ -182,25 +183,69 @@ describe('error', function () {
182
183
]
183
184
await expect ( engine . parseAndRender ( html ) ) . rejects . toMatchObject ( {
184
185
name : 'RenderError' ,
185
- message : `intended render error, file:${ path . resolve ( '/throwing-tag.html' ) } , line:4, col:2` ,
186
+ message : `intended error, file:${ resolve ( '/throwing-tag.html' ) } , line:4, col:2` ,
186
187
stack : expect . stringContaining ( message . join ( '\n' ) )
187
188
} )
188
189
} )
189
190
it ( 'should contain stack in err.stack' , async function ( ) {
190
191
await expect ( engine . parseAndRender ( '{%rejectingTag%}' ) ) . rejects . toMatchObject ( {
191
- message : expect . stringContaining ( 'intended render reject' ) ,
192
+ message : expect . stringContaining ( 'intended reject' ) ,
192
193
stack : expect . stringMatching ( / a t .* : \d + : \d + / )
193
194
} )
194
195
} )
195
196
} )
196
197
198
+ describe ( 'catchAllErrors' , function ( ) {
199
+ it ( 'should catch render errors' , async function ( ) {
200
+ const template = '{{foo}}\n{{"hello" | throwingFilter}}\n{% throwingTag %}'
201
+ return expect ( strictCatchingEngine . parseAndRender ( template ) ) . rejects . toMatchObject ( {
202
+ name : 'LiquidErrors' ,
203
+ message : '3 errors found, line:1, col:3' ,
204
+ errors : [ {
205
+ name : 'UndefinedVariableError' ,
206
+ message : 'undefined variable: foo, line:1, col:3'
207
+ } , {
208
+ name : 'RenderError' ,
209
+ message : 'intended error, line:2, col:1'
210
+ } , {
211
+ name : 'RenderError' ,
212
+ message : 'intended error, line:3, col:1'
213
+ } ]
214
+ } )
215
+ } )
216
+ it ( 'should catch some parse errors' , async function ( ) {
217
+ const template = '{{"foo" | filter foo }}'
218
+ return expect ( strictCatchingEngine . parseAndRender ( template ) ) . rejects . toMatchObject ( {
219
+ name : 'LiquidErrors' ,
220
+ message : '1 error found, line:1, col:18' ,
221
+ errors : [ {
222
+ name : 'TokenizationError' ,
223
+ message : 'expected ":" after filter name, line:1, col:18'
224
+ } ]
225
+ } )
226
+ } )
227
+ it ( 'should catch parse errors from filter/tag' , async function ( ) {
228
+ const template = '{{"foo" | nonExistFilter }} {% nonExistTag %}'
229
+ return expect ( strictCatchingEngine . parseAndRender ( template ) ) . rejects . toMatchObject ( {
230
+ name : 'LiquidErrors' ,
231
+ message : '2 errors found, line:1, col:1' ,
232
+ errors : [ {
233
+ name : 'ParseError' ,
234
+ message : 'undefined filter: nonExistFilter, line:1, col:1'
235
+ } , {
236
+ name : 'ParseError' ,
237
+ message : 'tag "nonExistTag" not found, line:1, col:29'
238
+ } ]
239
+ } )
240
+ } )
241
+ } )
242
+
197
243
describe ( 'ParseError' , function ( ) {
244
+ let engine : Liquid
198
245
beforeEach ( function ( ) {
199
246
engine = new Liquid ( )
200
247
engine . registerTag ( 'throwsOnParse' , {
201
- parse : function ( ) {
202
- throw new Error ( 'intended parse error' )
203
- } ,
248
+ parse : throwIntendedError ,
204
249
render : ( ) => ''
205
250
} )
206
251
} )
@@ -225,7 +270,7 @@ describe('error', function () {
225
270
it ( 'should throw ParseError when tag parse throws' , async function ( ) {
226
271
await expect ( engine . parseAndRender ( '{%throwsOnParse%}' ) ) . rejects . toMatchObject ( {
227
272
name : 'ParseError' ,
228
- message : expect . stringContaining ( 'intended parse error' )
273
+ message : expect . stringContaining ( 'intended error' )
229
274
} )
230
275
} )
231
276
it ( 'should throw ParseError when tag not found' , async function ( ) {
@@ -294,14 +339,14 @@ describe('error', function () {
294
339
} )
295
340
engine . registerTag ( 'throwingTag' , {
296
341
render : function ( ) {
297
- throw new Error ( 'intended render error' )
342
+ throw new Error ( 'intended error' )
298
343
}
299
344
} )
300
345
} )
301
346
it ( 'should throw RenderError when tag throws' , function ( ) {
302
347
const src = '{%throwingTag%}'
303
348
expect ( ( ) => engine . parseAndRenderSync ( src ) ) . toThrow ( RenderError )
304
- expect ( ( ) => engine . parseAndRenderSync ( src ) ) . toThrow ( / i n t e n d e d r e n d e r e r r o r / )
349
+ expect ( ( ) => engine . parseAndRenderSync ( src ) ) . toThrow ( / i n t e n d e d e r r o r / )
305
350
} )
306
351
it ( 'should contain original error info for {% include %}' , function ( ) {
307
352
mock ( {
@@ -323,7 +368,7 @@ describe('error', function () {
323
368
throw new Error ( 'expected throw' )
324
369
} catch ( err ) {
325
370
expect ( err ) . toHaveProperty ( 'name' , 'RenderError' )
326
- expect ( err ) . toHaveProperty ( 'message' , `intended render error, file:${ path . resolve ( '/throwing-tag.html' ) } , line:4, col:2` )
371
+ expect ( err ) . toHaveProperty ( 'message' , `intended error, file:${ resolve ( '/throwing-tag.html' ) } , line:4, col:2` )
327
372
expect ( err ) . toHaveProperty ( 'stack' , expect . stringContaining ( message . join ( '\n' ) ) )
328
373
}
329
374
} )
0 commit comments