feat: renderSync, parseAndRenderSync and renderFileSync, see #48

This commit is contained in:
harttle
2019-08-26 10:15:43 -05:00
committed by Jun Yang
parent 8028f82499
commit 7fb01ad69a
66 changed files with 896 additions and 272 deletions
+5
View File
@@ -81,4 +81,9 @@ describe('tags/assign', function () {
return expect(html).to.equal('12 2')
})
})
it('should support sync', function () {
const src = '{% assign foo="bar" %}{{foo}}'
const html = liquid.parseAndRenderSync(src)
return expect(html).to.equal('bar')
})
})
+5
View File
@@ -32,4 +32,9 @@ describe('tags/capture', function () {
return expect(liquid.parseAndRender(src))
.to.be.rejectedWith(/tag .* not closed/)
})
it('should support sync', function () {
const src = '{% capture f %}{{"a" | capitalize}}{%endcapture%}{{f}}'
const html = liquid.parseAndRenderSync(src)
return expect(html).to.equal('A')
})
})
+16
View File
@@ -48,4 +48,20 @@ describe('tags/case', function () {
const html = await liquid.parseAndRender(src)
return expect(html).to.equal('d')
})
describe('sync support', function () {
it('should hit the specified case', function () {
const src = '{% case "foo"%}' +
'{% when "foo" %}foo{% when "bar"%}bar' +
'{%endcase%}'
const html = liquid.parseAndRenderSync(src)
return expect(html).to.equal('foo')
})
it('should support else branch', function () {
const src = '{% case "a" %}' +
'{% when "b" %}b{% when "c"%}c{%else %}d' +
'{%endcase%}'
const html = liquid.parseAndRenderSync(src)
return expect(html).to.equal('d')
})
})
})
+7
View File
@@ -31,4 +31,11 @@ describe('tags/comment', function () {
const html = await liquid.parseAndRender(src)
return expect(html).to.equal('')
})
describe('sync support', function () {
it('should ignore plain string', function () {
const src = 'My name is {% comment %}super{% endcomment %} Shopify.'
const html = liquid.parseAndRenderSync(src)
return expect(html).to.equal('My name is Shopify.')
})
})
})
+5
View File
@@ -35,4 +35,9 @@ describe('tags/cycle', function () {
const html = await liquid.parseAndRender(src, ctx)
return expect(html).to.equal('121')
})
it('should support sync', function () {
const src = "{% cycle '1', '2', '3' %}"
const html = liquid.parseAndRenderSync(src + src + src + src)
return expect(html).to.equal('1231')
})
})
+57 -30
View File
@@ -6,13 +6,13 @@ import { Scope } from '../../../../src/context/scope'
use(chaiAsPromised)
describe('tags/for', function () {
let liquid: Liquid, ctx: Scope
let liquid: Liquid, scope: Scope
before(function () {
liquid = new Liquid()
liquid.registerTag('throwingTag', {
render: function () { throw new Error('intended render error') }
})
ctx = {
scope = {
one: 1,
// eslint-disable-next-line
strObj: new String(''),
@@ -25,30 +25,30 @@ describe('tags/for', function () {
})
it('should support array', async function () {
const src = '{%for c in alpha%}{{c}}{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('abc')
})
it('should support object', async function () {
const src = '{%for item in obj%}{{item[0]}},{{item[1]}}-{%else%}b{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('foo,bar-coo,haa-')
})
it('should output forloop', async function () {
const src = '{%for i in (1..1)%}{{forloop}}{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('{"i":0,"length":1}')
})
describe('illegal', function () {
it('should reject when for not closed', function () {
const src = '{%for c in alpha%}{{c}}'
return expect(liquid.parseAndRender(src, ctx))
return expect(liquid.parseAndRender(src, scope))
.to.be.rejectedWith(/tag .* not closed/)
})
it('should reject when inner templates rejected', function () {
const src = '{%for c in alpha%}{%throwingTag%}{%endfor%}'
return expect(liquid.parseAndRender(src, ctx))
return expect(liquid.parseAndRender(src, scope))
.to.be.rejectedWith(/intended render error/)
})
})
@@ -56,38 +56,38 @@ describe('tags/for', function () {
describe('else', function () {
it('should goto else for empty array', async function () {
const src = '{%for c in emptyArray%}a{%else%}b{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('b')
})
it('should treat non-empty string as one single element', async function () {
const src = '{%for c in "abc"%}x{{c}}{%else%}y{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('xabc')
})
it('should goto else for empty string', async function () {
const src = '{%for c in ""%}a{%else%}b{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('b')
})
it('should goto else for empty string object', async function () {
// it should be false although `new String` is none-conform
const src = '{%for c in strObj%}a{%else%}b{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('b')
})
it('should goto else for empty object', async function () {
const src = '{%for c in emptyObj%}a{%else%}b{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('b')
})
it('should goto else for null-prototyped object', async function () {
const src = '{%for c in nullProtoObj%}a{%else%}b{%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('b')
})
})
@@ -102,7 +102,7 @@ describe('tags/for', function () {
const dst = 'true.1.0.false.3.3.2a\n' +
'false.2.1.false.3.2.1b\n' +
'false.3.2.true.3.1.0c\n'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal(dst)
})
@@ -111,7 +111,7 @@ describe('tags/for', function () {
const src = '{% for i in (1..5) %}' +
'{% if i == 4 %}continue{% continue %}{% endif %}{{i}}' +
'{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('123continue5')
})
it('should output contents before continue', async function () {
@@ -119,7 +119,7 @@ describe('tags/for', function () {
'{% if i == 4 %}continue{% continue %}{% endif %}' +
'{{ i }}' +
'{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('123continue5')
})
})
@@ -129,7 +129,7 @@ describe('tags/for', function () {
'{% if i == 4 %}{% break %}{% endif %}' +
'{{ i }}' +
'{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('123')
})
it('should output contents before break', async function () {
@@ -137,7 +137,7 @@ describe('tags/for', function () {
'{% if i == 4 %}breaking{% break %}{% endif %}' +
'{{ i }}' +
'{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('123breaking')
})
})
@@ -145,22 +145,22 @@ describe('tags/for', function () {
describe('limit', function () {
it('should support for with limit', async function () {
const src = '{% for i in (1..5) limit:2 %}{{ i }}{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('12')
})
it('should set forloop.last properly', async function () {
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.last}} {%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('false true ')
})
it('should set forloop.first properly', async function () {
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.first}} {%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('true false ')
})
it('should set forloop.length properly', function () {
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.length}} {%endfor%}'
return expect(liquid.parseAndRender(src, ctx))
return expect(liquid.parseAndRender(src, scope))
.to.eventually.equal('2 2 ')
})
})
@@ -168,27 +168,27 @@ describe('tags/for', function () {
describe('offset', function () {
it('should support offset with limit', async function () {
const src = '{% for i in (1..10) limit:2 offset:5%}{{ i }}{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('67')
})
it('should set index properly', async function () {
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.index}} {%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('1 2 ')
})
it('should set index0 properly', async function () {
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.index0}} {%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('0 1 ')
})
it('should set rindex properly', async function () {
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.rindex}} {%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('2 1 ')
})
it('should set rindex0 properly', async function () {
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.rindex0}} {%endfor%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('1 0 ')
})
})
@@ -196,20 +196,47 @@ describe('tags/for', function () {
describe('reverse', function () {
it('should support for reversed in the last position', async function () {
const src = '{% for i in (1..5) limit:2 reversed %}{{ i }}{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('21')
})
it('should support for reversed in the first position', async function () {
const src = '{% for i in (1..5) reversed limit:2 %}{{ i }}{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('21')
})
it('should support for reversed in the middle position', async function () {
const src = '{% for i in (1..5) offset:2 reversed limit:4 %}{{ i }}{% endfor %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src)
return expect(html).to.equal('543')
})
})
describe('sync', function () {
it('should support sync', function () {
const src = '{% for i in (1..5) %}{{i}}{%endfor%}'
const html = liquid.parseAndRenderSync(src)
return expect(html).to.equal('12345')
})
it('should output contents before break', function () {
const src = '{% for i in (1..5) %}' +
'{% if i == 4 %}breaking{% break %}{% endif %}' +
'{{ i }}' +
'{% endfor %}'
const html = liquid.parseAndRenderSync(src, scope)
return expect(html).to.equal('123breaking')
})
it('should support for with continue', function () {
const src = '{% for i in (1..5) %}' +
'{% if i == 4 %}continue{% continue %}{% endif %}{{i}}' +
'{% endfor %}'
const html = liquid.parseAndRenderSync(src, scope)
return expect(html).to.equal('123continue5')
})
it('should goto else for empty array', async function () {
const src = '{%for c in emptyArray%}a{%else%}b{%endfor%}'
const html = await liquid.parseAndRenderSync(src, scope)
return expect(html).to.equal('b')
})
})
})
+24 -19
View File
@@ -3,7 +3,7 @@ import { expect } from 'chai'
describe('tags/if', function () {
const liquid = new Liquid()
const ctx = {
const scope = {
one: 1,
two: 2,
emptyString: '',
@@ -12,52 +12,52 @@ describe('tags/if', function () {
it('should throw if not closed', function () {
const src = '{% if false%}yes'
return expect(liquid.parseAndRender(src, ctx))
return expect(liquid.parseAndRender(src, scope))
.to.be.rejectedWith(/tag {% if false%} not closed/)
})
it('should support nested', async function () {
const src = '{%if false%}{%if true%}{%else%}a{%endif%}{%endif%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('')
})
describe('single value as condition', function () {
it('should support boolean', async function () {
const src = '{% if false %}1{%elsif true%}2{%else%}3{%endif%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('2')
})
it('should treat Array truthy', async function () {
const src = '{%if emptyArray%}a{%endif%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('a')
})
it('should return true if empty string', async function () {
const src = '{%if emptyString%}a{%endif%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('a')
})
})
describe('expression as condition', function () {
it('should support ==', async function () {
const src = '{% if 2 == 3 %}yes{%else%}no{%endif%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should support >=', async function () {
const src = '{% if 1 >= 2 and one<two %}a{%endif%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('')
})
it('should support !=', async function () {
const src = '{% if one != two %}yes{%else%}no{%endif%}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('yes')
})
it('should support value and expression', async function () {
const src = `X{%if version and version != '' %}x{{version}}y{%endif%}Y`
const ctx = { 'version': '' }
const html = await liquid.parseAndRender(src, ctx)
const scope = { 'version': '' }
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('XY')
})
it('should evaluate right to left', async function () {
@@ -69,50 +69,55 @@ describe('tags/if', function () {
describe('comparasion to null', function () {
it('should evaluate false for null < 10', async function () {
const src = '{% if null < 10 %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should evaluate false for null > 10', async function () {
const src = '{% if null > 10 %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should evaluate false for null <= 10', async function () {
const src = '{% if null <= 10 %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should evaluate false for null >= 10', async function () {
const src = '{% if null >= 10 %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should evaluate false for 10 < null', async function () {
const src = '{% if 10 < null %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should evaluate false for 10 > null', async function () {
const src = '{% if 10 > null %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should evaluate false for 10 <= null', async function () {
const src = '{% if 10 <= null %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
it('should evaluate false for 10 >= null', async function () {
const src = '{% if 10 >= null %}yes{% else %}no{% endif %}'
const html = await liquid.parseAndRender(src, ctx)
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('no')
})
})
it('should support sync', function () {
const src = '{%if true%}true{%else%}false{%endif%}'
const html = liquid.parseAndRenderSync(src, scope)
return expect(html).to.equal('true')
})
})
+35
View File
@@ -171,4 +171,39 @@ describe('tags/include', function () {
return expect(html).to.equal('Xchild with redY')
})
})
describe('sync support', function () {
it('should support quoted string', function () {
mock({
'/current.html': 'bar{% include "bar/foo.html" %}bar',
'/bar/foo.html': 'foo'
})
const html = liquid.renderFileSync('/current.html')
return expect(html).to.equal('barfoobar')
})
it('should support template string', function () {
mock({
'/current.html': 'bar{% include name" %}bar',
'/bar/foo.html': 'foo'
})
const html = liquid.renderFileSync('/current.html', { name: '/bar/foo.html' })
return expect(html).to.equal('barfoobar')
})
it('should support include: with', function () {
mock({
'/with.html': '{% include "color" with "red", shape: "rect" %}',
'/color.html': 'color:{{color}}, shape:{{shape}}'
})
const html = liquid.renderFileSync('with.html')
return expect(html).to.equal('color:red, shape:rect')
})
it('should support filename with extention', function () {
mock({
'/parent.html': 'X{% include child.html color:"red" %}Y',
'/child.html': 'child with {{color}}'
})
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
const html = staticLiquid.renderFileSync('parent.html')
return expect(html).to.equal('Xchild with redY')
})
})
})
+9
View File
@@ -133,4 +133,13 @@ describe('tags/layout', function () {
return expect(html).to.equal('blackA')
})
})
it('should support sync', function () {
mock({
'/grand.html': 'X{%block a%}G{%endblock%}Y',
'/parent.html': '{%layout "grand" %}{%block a%}P{%endblock%}',
'/main.html': '{%layout "parent"%}{%block a%}A{%endblock%}'
})
const html = liquid.renderFileSync('/main.html')
return expect(html).to.equal('XAY')
})
})
+7 -3
View File
@@ -3,20 +3,24 @@ import { expect } from 'chai'
describe('tags/raw', function () {
const liquid = new Liquid()
it('should support raw 1', async function () {
it('should throw when not closed', async function () {
const p = liquid.parseAndRender('{% raw%}')
return expect(p).be.rejectedWith(/{% raw%} not closed/)
})
it('should support raw 2', async function () {
it('should output filters as it is', async function () {
const src = '{% raw %}{{ 5 | plus: 6 }}{% endraw %} is equal to 11.'
const dst = '{{ 5 | plus: 6 }} is equal to 11.'
const html = await liquid.parseAndRender(src)
return expect(html).to.equal(dst)
})
it('should support raw 3', async function () {
it('should preserve blank characters', async function () {
const src = '{% raw %}\n{{ foo}} \n{% endraw %}'
const dst = '\n{{ foo}} \n'
const html = await liquid.parseAndRender(src)
return expect(html).to.equal(dst)
})
it('should support sync', function () {
const html = liquid.parseAndRenderSync('{% raw %}{{foo}}{% endraw %}')
return expect(html).to.equal('{{foo}}')
})
})
+14
View File
@@ -107,4 +107,18 @@ describe('tags/tablerow', function () {
return expect(html).to.equal(dst)
})
})
describe('sync support', function () {
it('should support tablerow', function () {
const src = '{% tablerow i in (1..3)%}{{ i }}{% endtablerow %}'
const dst = '<tr class="row1"><td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>'
const html = liquid.parseAndRenderSync(src)
expect(html).to.equal(dst)
})
it('should support empty tablerow', function () {
const src = '{% tablerow i in "" cols:2 %}{{ i }}{% endtablerow %}'
const dst = ''
const html = liquid.parseAndRenderSync(src)
return expect(html).to.equal(dst)
})
})
})
+12
View File
@@ -34,4 +34,16 @@ describe('tags/unless', function () {
const html = await liquid.parseAndRender(src)
return expect(html).to.equal('')
})
describe('sync support', function () {
it('should render else when predicate yields true', function () {
const src = '{% unless 0 %}yes{%else%}no{%endunless%}'
const html = liquid.parseAndRenderSync(src)
expect(html).to.equal('no')
})
it('should render unless when predicate yields false', function () {
const src = '{% unless false %}yes{%else%}no{%endunless%}'
const html = liquid.parseAndRenderSync(src)
expect(html).to.equal('yes')
})
})
})
+4
View File
@@ -49,6 +49,10 @@ describe('drop/drop', function () {
const html = await liquid.parseAndRender(`{{obj.name}}`, { obj: new PromiseDrop() })
expect(html).to.equal('NAME')
})
it('should resolve before calling filters', async function () {
const html = await liquid.parseAndRender(`{{obj.name | downcase}}`, { obj: new PromiseDrop() })
expect(html).to.equal('name')
})
it('should support promise returned by liquidMethodMissing', async function () {
const html = await liquid.parseAndRender(`{{obj.foo}}`, { obj: new PromiseDrop() })
expect(html).to.equal('FOO')
+80 -29
View File
@@ -3,36 +3,87 @@ import { Liquid } from '../../../src/liquid'
import { mock, restore } from '../../stub/mockfs'
describe('LiquidOptions#cache', function () {
let engine: Liquid
beforeEach(function () {
engine = new Liquid({
root: '/root/',
extname: '.html'
})
mock({ '/root/files/foo.html': 'foo' })
})
afterEach(restore)
it('should be disabled by default', function () {
return engine.renderFile('files/foo')
.then(x => expect(x).to.equal('foo'))
.then(() => mock({
'/root/files/foo.html': 'bar'
}))
.then(() => engine.renderFile('files/foo'))
.then(x => expect(x).to.equal('bar'))
})
it('should respect cache=true option', function () {
engine = new Liquid({
root: '/root/',
extname: '.html',
cache: true
describe('#renderFile', function () {
it('should be disabled by default', async function () {
const engine = new Liquid({
root: '/root/',
extname: '.html'
})
mock({ '/root/files/foo.html': 'foo' })
const x = await engine.renderFile('files/foo')
expect(x).to.equal('foo')
mock({ '/root/files/foo.html': 'bar' })
const y = await engine.renderFile('files/foo')
expect(y).to.equal('bar')
})
it('should respect cache=true option', async function () {
const engine = new Liquid({
root: '/root/',
extname: '.html',
cache: true
})
mock({ '/root/files/foo.html': 'foo' })
const x = await engine.renderFile('files/foo')
expect(x).to.equal('foo')
mock({ '/root/files/foo.html': 'bar' })
const y = await engine.renderFile('files/foo')
expect(y).to.equal('foo')
})
it('should not cache not exist file', async function () {
const engine = new Liquid({
root: '/root/',
extname: '.html',
cache: true
})
try { await engine.renderFile('foo') } catch (err) {}
mock({ '/root/foo.html': 'foo' })
const y = await engine.renderFile('foo')
expect(y).to.equal('foo')
})
})
describe('#renderFileSync', function () {
it('should be disabled by default', function () {
const engine = new Liquid({
root: '/root/',
extname: '.html'
})
mock({ '/root/foo.html': 'foo' })
const x = engine.renderFileSync('foo')
expect(x).to.equal('foo')
mock({ '/root/foo.html': 'bar' })
const y = engine.renderFileSync('foo')
expect(y).to.equal('bar')
})
it('should respect cache=true option', function () {
const engine = new Liquid({
root: '/root/',
extname: '.html',
cache: true
})
mock({ '/root/foo.html': 'foo' })
const x = engine.renderFileSync('foo')
expect(x).to.equal('foo')
mock({ '/root/foo.html': 'bar' })
const y = engine.renderFileSync('foo')
expect(y).to.equal('foo')
})
it('should not cache not exist file', async function () {
const engine = new Liquid({
root: '/root/',
extname: '.html',
cache: true
})
try { engine.renderFileSync('foo') } catch (err) {}
mock({ '/root/foo.html': 'foo' })
const y = await engine.renderFile('foo')
expect(y).to.equal('foo')
})
return engine.renderFile('files/foo')
.then(x => expect(x).to.equal('foo'))
.then(() => mock({
'/root/files/foo.html': 'bar'
}))
.then(() => engine.renderFile('files/foo'))
.then(x => expect(x).to.equal('foo'))
})
})
+2 -2
View File
@@ -53,14 +53,14 @@ describe('Liquid', function () {
})
after(restore)
it('should render single template', function (done) {
render.call({ root: '.' }, 'foo', null as any, (err: Error | null, result: string | undefined) => {
render.call({ root: '/root' }, 'foo', null as any, (err: Error | null, result: string | undefined) => {
if (err) return done(err)
expect(result).to.equal('foo')
done()
})
})
it('should render single template with Array-typed root', function (done) {
render.call({ root: ['.'] }, 'foo', null as any, (err: Error | null, result: string | undefined) => {
render.call({ root: ['/root'] }, 'foo', null as any, (err: Error | null, result: string | undefined) => {
if (err) return done(err)
expect(result).to.equal('foo')
done()
+18 -11
View File
@@ -1,17 +1,24 @@
import { test, liquid } from '../../stub/render'
import { expect } from 'chai'
import { Liquid } from '../../../src/liquid'
describe('liquid#registerFilter()', function () {
const liquid = new Liquid()
describe('object arguments', function () {
liquid.registerFilter('obj_test', function () {
return JSON.stringify(arguments)
liquid.registerFilter('obj_test', function (...args) {
return JSON.stringify(args)
})
it('should support object', async () => {
const src = `{{ "a" | obj_test: k1: "v1", k2: foo }}`,
const dst = '["a",["k1","v1"],["k2","bar"]]'
const html = await liquid.parseAndRender(src, { foo: 'bar' })
return expect(html).to.equal(dst)
})
it('should support mixed object', async () => {
const src = `{{ "a" | obj_test: "something", k1: "v1", k2: foo }}`,
const dst = '["a","something",["k1","v1"],["k2","bar"]]'
const html = await liquid.parseAndRender(src, { foo: 'bar' })
return expect(html).to.equal(dst)
})
it('should support object', () => test(
`{{ "a" | obj_test: k1: "v1", k2: foo }}`,
'{"0":"a","1":["k1","v1"],"2":["k2","bar"]}'
))
it('should support mixed object', () => test(
`{{ "a" | obj_test: "something", k1: "v1", k2: foo }}`,
'{"0":"a","1":"something","2":["k1","v1"],"3":["k2","bar"]}'
))
})
})
+43
View File
@@ -1,4 +1,5 @@
import { expect } from 'chai'
import { RenderError } from '../../../src/util/error'
import { Liquid } from '../../../src/liquid'
import * as path from 'path'
import { mock, restore } from '../../stub/mockfs'
@@ -264,4 +265,46 @@ describe('error', function () {
expect(err.stack).to.match(/at .*:\d+:\d+\)/)
})
})
describe('sync support', function () {
let engine
beforeEach(function () {
engine = new Liquid({
root: '/'
})
engine.registerTag('throwingTag', {
render: function () {
throw new Error('intended render error')
}
})
})
it('should throw RenderError when tag throws', function () {
const src = '{%throwingTag%}'
expect(() => engine.parseAndRenderSync(src))
.to.throw(RenderError, /intended render error/)
})
it('should contain original error info for {% include %}', function () {
const origin = ['1st', '2nd', '3rd', 'X{%throwingTag%} Y', '5th', '6th', '7th']
mock({
'/throwing-tag.html': origin.join('\n')
})
const html = '{%include "throwing-tag.html"%}'
const message = [
' 2| 2nd',
' 3| 3rd',
'>> 4| X{%throwingTag%} Y',
' 5| 5th',
' 6| 6th',
' 7| 7th',
'RenderError'
]
try {
engine.parseAndRenderSync(html)
throw new Error('expected throw')
} catch (err) {
expect(err.message).to.equal(`intended render error, file:${path.resolve('/throwing-tag.html')}, line:4, col:2`)
expect(err.stack).to.contain(message.join('\n'))
expect(err.name).to.equal('RenderError')
}
})
})
})