mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-16 12:50:38 -07:00
feat: renderSync, parseAndRenderSync and renderFileSync, see #48
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
import { expect } from 'chai'
|
||||
import { Liquid } from '../..'
|
||||
|
||||
describe('#evalValueSync()', function () {
|
||||
var engine: Liquid
|
||||
beforeEach(() => { engine = new Liquid() })
|
||||
|
||||
it('should throw when scope undefined', async function () {
|
||||
return expect(() => engine.evalValueSync('{{"foo"}}', null as any)).to.throw(/context not defined/)
|
||||
})
|
||||
})
|
||||
@@ -6,6 +6,6 @@ describe('.evalValue()', function () {
|
||||
beforeEach(() => { engine = new Liquid() })
|
||||
|
||||
it('should throw when scope undefined', async function () {
|
||||
return expect(() => engine.evalValue('{{"foo"}}', null as any)).to.throw(/context not defined/)
|
||||
return expect(engine.evalValue('{{"foo"}}', null as any)).to.be.rejectedWith(/context not defined/)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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.')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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}}')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"]}'
|
||||
))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+9
-3
@@ -8,8 +8,7 @@ interface FileDescriptor {
|
||||
}
|
||||
|
||||
let files: { [path: string]: FileDescriptor } = {}
|
||||
const readFile = fs.readFile
|
||||
const exists = fs.exists
|
||||
const { readFile, exists, readFileSync, existsSync } = fs
|
||||
|
||||
export function mock (options: { [path: string]: (string | FileDescriptor) }) {
|
||||
forOwn(options, (val, key) => {
|
||||
@@ -18,19 +17,26 @@ export function mock (options: { [path: string]: (string | FileDescriptor) }) {
|
||||
: val as FileDescriptor
|
||||
})
|
||||
fs.readFile = async function (path) {
|
||||
return fs.readFileSync(path)
|
||||
}
|
||||
fs.readFileSync = function (path) {
|
||||
const file = files[path]
|
||||
if (file === undefined) throw new Error('ENOENT')
|
||||
if (file.mode === '0000') throw new Error('EACCES')
|
||||
return file.content
|
||||
}
|
||||
|
||||
fs.exists = async function (path: string) {
|
||||
return fs.existsSync(path)
|
||||
}
|
||||
fs.existsSync = function (path: string) {
|
||||
return !!files[path]
|
||||
}
|
||||
}
|
||||
|
||||
export function restore () {
|
||||
files = {}
|
||||
fs.readFileSync = readFileSync
|
||||
fs.existsSync = existsSync
|
||||
fs.readFile = readFile
|
||||
fs.exists = exists
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ export const ctx = {
|
||||
foo: 'bar',
|
||||
arr: [-2, 'a'],
|
||||
obj: { foo: 'bar' },
|
||||
func: function () {},
|
||||
func: function () {}, // eslint-disable-line
|
||||
posts: [{ category: 'foo' }, { category: 'bar' }],
|
||||
products: [
|
||||
{ title: 'Vacuum', type: 'living room' },
|
||||
|
||||
@@ -59,6 +59,12 @@ describe('fs/browser', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('#existsSync()', () => {
|
||||
it('should always return true', function () {
|
||||
expect(fs.existsSync('/foo/bar')).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#readFile()', () => {
|
||||
let server: sinon.SinonFakeServer
|
||||
beforeEach(() => {
|
||||
@@ -87,4 +93,29 @@ describe('fs/browser', function () {
|
||||
return result
|
||||
})
|
||||
})
|
||||
|
||||
describe('#readFileSync()', () => {
|
||||
let server: sinon.SinonFakeServer
|
||||
beforeEach(() => {
|
||||
server = sinon.fakeServer.create()
|
||||
server.autoRespond = true
|
||||
server.respondWith(
|
||||
'GET', 'https://example.com/views/hello.html',
|
||||
[200, { 'Content-Type': 'text/plain' }, 'hello {{name}}']
|
||||
);
|
||||
(global as any).XMLHttpRequest = sinon.useFakeXMLHttpRequest()
|
||||
})
|
||||
afterEach(() => {
|
||||
server.restore()
|
||||
delete (global as any).XMLHttpRequest
|
||||
})
|
||||
it('should get corresponding text', function () {
|
||||
const html = fs.readFileSync('https://example.com/views/hello.html')
|
||||
return expect(html).to.equal('hello {{name}}')
|
||||
})
|
||||
it('should throw 404', () => {
|
||||
return expect(() => fs.readFileSync('https://example.com/not/exist.html'))
|
||||
.to.throw('Not Found')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+23
-6
@@ -6,7 +6,7 @@ import * as chaiAsPromised from 'chai-as-promised'
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('fs', function () {
|
||||
describe('#resolve()', function () {
|
||||
describe('.resolve()', function () {
|
||||
it('should resolve based on root', async function () {
|
||||
const filepath = fs.resolve('/foo', 'bar.html', '.liquid')
|
||||
const expected = path.resolve('/foo/bar.html')
|
||||
@@ -18,23 +18,40 @@ describe('fs', function () {
|
||||
return expect(filepath).to.equal(expected)
|
||||
})
|
||||
})
|
||||
describe('#exists', () => {
|
||||
describe('.existsSync', () => {
|
||||
it('should resolve as false if not exists', () => {
|
||||
expect(fs.existsSync('/foo/bar')).to.be.false
|
||||
})
|
||||
it('should resolve as true if exists', () => {
|
||||
expect(fs.existsSync(__filename)).to.be.true
|
||||
})
|
||||
})
|
||||
describe('.exists', () => {
|
||||
it('should resolve as false if not exists', async () => {
|
||||
const result = await fs.exists('/foo/bar')
|
||||
return expect(result).to.be.false
|
||||
expect(result).to.be.false
|
||||
})
|
||||
it('should resolve as true if exists', async () => {
|
||||
const result = await fs.exists(__filename)
|
||||
return expect(result).to.be.true
|
||||
expect(result).to.be.true
|
||||
})
|
||||
})
|
||||
describe('#readFile', function () {
|
||||
describe('.readFileSync', function () {
|
||||
it('should throw when not exist', function () {
|
||||
return expect(() => fs.readFileSync('/foo/bar')).to.throw('ENOENT')
|
||||
})
|
||||
it('should read content if exists', function () {
|
||||
const content = fs.readFileSync(__filename)
|
||||
expect(content).to.contain('should read content if exists')
|
||||
})
|
||||
})
|
||||
describe('.readFile', function () {
|
||||
it('should throw when not exist', function () {
|
||||
return expect(fs.readFile('/foo/bar')).to.rejectedWith('ENOENT')
|
||||
})
|
||||
it('should read content if exists', async function () {
|
||||
const content = await fs.readFile(__filename)
|
||||
return expect(content).to.contain('should read content if exists')
|
||||
expect(content).to.contain('should read content if exists')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -17,51 +17,56 @@ describe('Expression', function () {
|
||||
})
|
||||
|
||||
it('should throw when context not defined', async function () {
|
||||
return expect(() => new Expression().value()).to.throw(/context not defined/)
|
||||
return expect(new Expression().value()).to.be.rejectedWith(/context not defined/)
|
||||
})
|
||||
|
||||
it('should eval simple expression', async function () {
|
||||
expect(new Expression('1 < 2').value(ctx)).to.equal(true)
|
||||
expect(new Expression('2 <= 2').value(ctx)).to.equal(true)
|
||||
expect(new Expression('one <= two').value(ctx)).to.equal(true)
|
||||
expect(new Expression('x contains "x"').value(ctx)).to.equal(false)
|
||||
expect(new Expression('x contains "X"').value(ctx)).to.equal(true)
|
||||
expect(new Expression('1 contains "x"').value(ctx)).to.equal(false)
|
||||
expect(new Expression('y contains "x"').value(ctx)).to.equal(false)
|
||||
expect(new Expression('z contains "x"').value(ctx)).to.equal(false)
|
||||
expect(new Expression('(1..5) contains 3').value(ctx)).to.equal(true)
|
||||
expect(new Expression('(1..5) contains 6').value(ctx)).to.equal(false)
|
||||
expect(new Expression('"<=" == "<="').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('1 < 2').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('1 < 2').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('2 <= 2').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('one <= two').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('x contains "x"').value(ctx)).to.equal(false)
|
||||
expect(await new Expression('x contains "X"').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('1 contains "x"').value(ctx)).to.equal(false)
|
||||
expect(await new Expression('y contains "x"').value(ctx)).to.equal(false)
|
||||
expect(await new Expression('z contains "x"').value(ctx)).to.equal(false)
|
||||
expect(await new Expression('(1..5) contains 3').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('(1..5) contains 6').value(ctx)).to.equal(false)
|
||||
expect(await new Expression('"<=" == "<="').value(ctx)).to.equal(true)
|
||||
})
|
||||
|
||||
describe('complex expression', function () {
|
||||
it('should support value or value', async function () {
|
||||
expect(new Expression('false or true').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('false or true').value(ctx)).to.equal(true)
|
||||
})
|
||||
it('should support < and contains', async function () {
|
||||
expect(new Expression('1 < 2 and x contains "x"').value(ctx)).to.equal(false)
|
||||
expect(await new Expression('1 < 2 and x contains "x"').value(ctx)).to.equal(false)
|
||||
})
|
||||
it('should support < or contains', async function () {
|
||||
expect(new Expression('1 < 2 or x contains "x"').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('1 < 2 or x contains "x"').value(ctx)).to.equal(true)
|
||||
})
|
||||
it('should support value and !=', async function () {
|
||||
expect(new Expression('empty and empty != ""').value(ctx)).to.equal(false)
|
||||
expect(await new Expression('empty and empty != ""').value(ctx)).to.equal(false)
|
||||
})
|
||||
it('should recognize quoted value', async function () {
|
||||
expect(new Expression('">"').value(ctx)).to.equal('>')
|
||||
expect(await new Expression('">"').value(ctx)).to.equal('>')
|
||||
})
|
||||
it('should evaluate from right to left', function () {
|
||||
expect(new Expression('true or false and false').value(ctx)).to.equal(true)
|
||||
expect(new Expression('true and false and false or true').value(ctx)).to.equal(false)
|
||||
it('should evaluate from right to left', async function () {
|
||||
expect(await new Expression('true or false and false').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('true and false and false or true').value(ctx)).to.equal(false)
|
||||
})
|
||||
it('should recognize property access', function () {
|
||||
it('should recognize property access', async function () {
|
||||
const ctx = new Context({ obj: { foo: true } })
|
||||
expect(new Expression('obj["foo"] and true').value(ctx)).to.equal(true)
|
||||
expect(await new Expression('obj["foo"] and true').value(ctx)).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
it('should eval range expression', async function () {
|
||||
expect(new Expression('(2..4)').value(ctx)).to.deep.equal([2, 3, 4])
|
||||
expect(new Expression('(two..4)').value(ctx)).to.deep.equal([2, 3, 4])
|
||||
expect(await new Expression('(2..4)').value(ctx)).to.deep.equal([2, 3, 4])
|
||||
expect(await new Expression('(two..4)').value(ctx)).to.deep.equal([2, 3, 4])
|
||||
})
|
||||
|
||||
it('should support sync', function () {
|
||||
expect(new Expression('empty and empty != ""').valueSync(ctx)).to.equal(false)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -5,20 +5,20 @@ import { expect } from 'chai'
|
||||
describe('Value', function () {
|
||||
it('should eval number variable', async function () {
|
||||
const ctx = new Context({ one: 1 })
|
||||
expect(new Value('one').value(ctx)).to.equal(1)
|
||||
expect(new Value('one').valueSync(ctx)).to.equal(1)
|
||||
})
|
||||
it('question mark should be valid variable name', async function () {
|
||||
const ctx = new Context({ 'has_value?': true })
|
||||
expect(new Value('has_value?').value(ctx)).to.equal(true)
|
||||
expect(new Value('has_value?').valueSync(ctx)).to.equal(true)
|
||||
})
|
||||
it('should eval string variable', async function () {
|
||||
const ctx = new Context({ x: 'XXX' })
|
||||
expect(new Value('x').value(ctx)).to.equal('XXX')
|
||||
expect(new Value('x').valueSync(ctx)).to.equal('XXX')
|
||||
})
|
||||
it('should eval null literal', async function () {
|
||||
expect(new Value('null').value({})).to.be.null
|
||||
expect(new Value('null').valueSync({})).to.be.null
|
||||
})
|
||||
it('should eval nil literal', async function () {
|
||||
expect(new Value('nil').value({})).to.be.null
|
||||
expect(new Value('nil').valueSync({})).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
@@ -60,4 +60,14 @@ describe('filter', function () {
|
||||
new Filter('/', [], false)
|
||||
}).to.not.throw()
|
||||
})
|
||||
|
||||
it('should support sync', function () {
|
||||
Filter.register('add', (a, b) => a + b)
|
||||
expect(new Filter('add', ['2'], false).renderSync(3, ctx)).to.equal(5)
|
||||
})
|
||||
|
||||
it('should support key value pairs', function () {
|
||||
Filter.register('add', (a, b) => b[0] + ':' + (a + b[1]))
|
||||
expect(new Filter('add', [['num', '2']], false).renderSync(3, ctx)).to.equal('num:5')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as chai from 'chai'
|
||||
import { Hash } from '../../../src/template/tag/hash'
|
||||
import { Context } from '../../../src/context/context'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('Hash', function () {
|
||||
it('should parse variable', async function () {
|
||||
const hash = await Hash.create('num:foo', new Context({ foo: 3 }))
|
||||
expect(hash.num).to.equal(3)
|
||||
})
|
||||
it('should parse literals', async function () {
|
||||
const hash = await Hash.create('num:3', new Context())
|
||||
expect(hash.num).to.equal(3)
|
||||
})
|
||||
it('should support sync', function () {
|
||||
const hash = Hash.createSync('num:3', new Context())
|
||||
expect(hash.num).to.equal(3)
|
||||
})
|
||||
})
|
||||
@@ -10,7 +10,7 @@ chai.use(sinonChai)
|
||||
const expect = chai.expect
|
||||
const liquid = new Liquid()
|
||||
|
||||
describe('tag', function () {
|
||||
describe('Tag', function () {
|
||||
let ctx: Context
|
||||
const emitter = { write: (html: string) => (emitter.html += html), html: '' }
|
||||
before(function () {
|
||||
|
||||
Reference in New Issue
Block a user