diff --git a/.eslintrc.json b/.eslintrc.json index 6d34673390..1e0962b61e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -21,6 +21,7 @@ "no-dupe-class-members": "off", "@typescript-eslint/indent": ["error", 2], "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-object-literal-type-assertion": "off", "@typescript-eslint/no-use-before-define": "off", diff --git a/src/builtin/tags/assign.ts b/src/builtin/tags/assign.ts index e542447272..75c4a7c9b9 100644 --- a/src/builtin/tags/assign.ts +++ b/src/builtin/tags/assign.ts @@ -11,9 +11,7 @@ export default { this.key = match[1] this.value = match[2] }, - render: async function (ctx: Context) { - ctx.front()[this.key] = ctx.sync - ? this.liquid.evalValueSync(this.value, ctx) - : await this.liquid.evalValue(this.value, ctx) + render: function * (ctx: Context) { + ctx.front()[this.key] = yield this.liquid._evalValue(this.value, ctx) } } as ITagImplOptions diff --git a/src/builtin/tags/block.ts b/src/builtin/tags/block.ts index b3da8991c0..c8fbe2083b 100644 --- a/src/builtin/tags/block.ts +++ b/src/builtin/tags/block.ts @@ -14,16 +14,13 @@ export default { }) stream.start() }, - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { const blocks = ctx.getRegister('blocks') const childDefined = blocks[this.block] const r = this.liquid.renderer const html = childDefined !== undefined ? childDefined - : (ctx.sync - ? r.renderTemplatesSync(this.tpls, ctx) - : await r.renderTemplates(this.tpls, ctx) - ) + : yield r.renderTemplates(this.tpls, ctx) if (ctx.getRegister('blockMode', BlockMode.OUTPUT) === BlockMode.STORE) { blocks[this.block] = html diff --git a/src/builtin/tags/break.ts b/src/builtin/tags/break.ts index f765bc8880..1b0c1512da 100644 --- a/src/builtin/tags/break.ts +++ b/src/builtin/tags/break.ts @@ -1,7 +1,7 @@ import { Emitter, Context, Hash } from '../../types' export default { - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function (ctx: Context, hash: Hash, emitter: Emitter) { emitter.break = true } } diff --git a/src/builtin/tags/capture.ts b/src/builtin/tags/capture.ts index 2354e11cc6..89eec503f7 100644 --- a/src/builtin/tags/capture.ts +++ b/src/builtin/tags/capture.ts @@ -20,11 +20,9 @@ export default { }) stream.start() }, - render: async function (ctx: Context) { + render: function * (ctx: Context) { const r = this.liquid.renderer - const html = ctx.sync - ? r.renderTemplatesSync(this.templates, ctx) - : await r.renderTemplates(this.templates, ctx) + const html = yield r.renderTemplates(this.templates, ctx) ctx.front()[this.variable] = html } } as ITagImplOptions diff --git a/src/builtin/tags/case.ts b/src/builtin/tags/case.ts index b38f498255..f8d19b6d6c 100644 --- a/src/builtin/tags/case.ts +++ b/src/builtin/tags/case.ts @@ -24,31 +24,17 @@ export default { stream.start() }, - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { const r = this.liquid.renderer for (let i = 0; i < this.cases.length; i++) { const branch = this.cases[i] - const val = await new Expression(branch.val).value(ctx) - const cond = await new Expression(this.cond).value(ctx) + const val = yield new Expression(branch.val).value(ctx) + const cond = yield new Expression(this.cond).value(ctx) if (val === cond) { - await r.renderTemplates(branch.templates, ctx, emitter) + yield r.renderTemplates(branch.templates, ctx, emitter) return } } - await r.renderTemplates(this.elseTemplates, ctx, emitter) - }, - - renderSync: function (ctx: Context, hash: Hash, emitter: Emitter) { - const r = this.liquid.renderer - for (let i = 0; i < this.cases.length; i++) { - const branch = this.cases[i] - const val = new Expression(branch.val).valueSync(ctx) - const cond = new Expression(this.cond).valueSync(ctx) - if (val === cond) { - r.renderTemplatesSync(branch.templates, ctx, emitter) - return - } - } - r.renderTemplatesSync(this.elseTemplates, ctx, emitter) + yield r.renderTemplates(this.elseTemplates, ctx, emitter) } } as ITagImplOptions diff --git a/src/builtin/tags/continue.ts b/src/builtin/tags/continue.ts index 6e14bbcd46..bc606184c7 100644 --- a/src/builtin/tags/continue.ts +++ b/src/builtin/tags/continue.ts @@ -1,7 +1,7 @@ import { Emitter, Context, Hash } from '../../types' export default { - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function (ctx: Context, hash: Hash, emitter: Emitter) { emitter.continue = true } } diff --git a/src/builtin/tags/cycle.ts b/src/builtin/tags/cycle.ts index 2a7a93b3ac..9d359b443d 100644 --- a/src/builtin/tags/cycle.ts +++ b/src/builtin/tags/cycle.ts @@ -21,10 +21,8 @@ export default { assert(this.candidates.length, `empty candidates: ${tagToken.raw}`) }, - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { - const group = ctx.sync - ? this.group.valueSync(ctx) - : await this.group.value(ctx) + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { + const group = yield this.group.value(ctx) const fingerprint = `cycle:${group}:` + this.candidates.join(',') const groups = ctx.getRegister('cycle') let idx = groups[fingerprint] @@ -36,9 +34,7 @@ export default { const candidate = this.candidates[idx] idx = (idx + 1) % this.candidates.length groups[fingerprint] = idx - const html = ctx.sync - ? new Expression(candidate).valueSync(ctx) - : await new Expression(candidate).value(ctx) + const html = yield new Expression(candidate).value(ctx) emitter.write(html) } } as ITagImplOptions diff --git a/src/builtin/tags/for.ts b/src/builtin/tags/for.ts index 99363196ee..ccef0f6c0a 100644 --- a/src/builtin/tags/for.ts +++ b/src/builtin/tags/for.ts @@ -36,11 +36,9 @@ export default { stream.start() }, - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { const r = this.liquid.renderer - let collection = ctx.sync - ? new Expression(this.collection).valueSync(ctx) - : await new Expression(this.collection).value(ctx) + let collection = yield new Expression(this.collection).value(ctx) if (!isArray(collection)) { if (isString(collection) && collection.length > 0) { @@ -50,9 +48,7 @@ export default { } } if (!isArray(collection) || !collection.length) { - ctx.sync - ? r.renderTemplatesSync(this.elseTemplates, ctx, emitter) - : await r.renderTemplates(this.elseTemplates, ctx, emitter) + yield r.renderTemplates(this.elseTemplates, ctx, emitter) return } @@ -66,9 +62,7 @@ export default { ctx.push(scope) for (const item of collection) { scope[this.variable] = item - ctx.sync - ? r.renderTemplatesSync(this.templates, ctx, emitter) - : await r.renderTemplates(this.templates, ctx, emitter) + yield r.renderTemplates(this.templates, ctx, emitter) if (emitter.break) { emitter.break = false break diff --git a/src/builtin/tags/if.ts b/src/builtin/tags/if.ts index 1f086f8d54..be9a47cae8 100644 --- a/src/builtin/tags/if.ts +++ b/src/builtin/tags/if.ts @@ -27,29 +27,16 @@ export default { stream.start() }, - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { const r = this.liquid.renderer for (const branch of this.branches) { - const cond = await new Expression(branch.cond).value(ctx) + const cond = yield new Expression(branch.cond).value(ctx) if (isTruthy(cond)) { - await r.renderTemplates(branch.templates, ctx, emitter) + yield r.renderTemplates(branch.templates, ctx, emitter) return } } - await r.renderTemplates(this.elseTemplates, ctx, emitter) - }, - - renderSync: function (ctx: Context, hash: Hash, emitter: Emitter) { - const r = this.liquid.renderer - - for (const branch of this.branches) { - const cond = new Expression(branch.cond).valueSync(ctx) - if (isTruthy(cond)) { - r.renderTemplatesSync(branch.templates, ctx, emitter) - return - } - } - r.renderTemplatesSync(this.elseTemplates, ctx, emitter) + yield r.renderTemplates(this.elseTemplates, ctx, emitter) } } as ITagImplOptions diff --git a/src/builtin/tags/include.ts b/src/builtin/tags/include.ts index 9d5ad44f88..986f5fc405 100644 --- a/src/builtin/tags/include.ts +++ b/src/builtin/tags/include.ts @@ -17,14 +17,14 @@ export default { match = withRE.exec(token.args) if (match) this.with = match[1] }, - renderSync: function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { let filepath if (ctx.opts.dynamicPartials) { if (quotedLine.exec(this.value)) { const template = this.value.slice(1, -1) - filepath = this.liquid.parseAndRenderSync(template, ctx.getAll(), ctx.opts) + filepath = yield this.liquid._parseAndRender(template, ctx.getAll(), ctx.opts, ctx.sync) } else { - filepath = new Expression(this.value).valueSync(ctx) + filepath = yield new Expression(this.value).value(ctx) } } else { filepath = this.staticValue @@ -37,41 +37,11 @@ export default { ctx.setRegister('blocks', {}) ctx.setRegister('blockMode', BlockMode.OUTPUT) if (this.with) { - hash[filepath] = new Expression(this.with).evaluateSync(ctx) + hash[filepath] = yield new Expression(this.with).evaluate(ctx) } - const templates = this.liquid.parseFileSync(filepath, ctx.opts) + const templates = yield this.liquid._parseFile(filepath, ctx.opts, ctx.sync) ctx.push(hash) - this.liquid.renderer.renderTemplatesSync(templates, ctx, emitter) - ctx.pop() - ctx.setRegister('blocks', originBlocks) - ctx.setRegister('blockMode', originBlockMode) - }, - - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { - let filepath - if (ctx.opts.dynamicPartials) { - if (quotedLine.exec(this.value)) { - const template = this.value.slice(1, -1) - filepath = await this.liquid.parseAndRender(template, ctx.getAll(), ctx.opts) - } else { - filepath = await new Expression(this.value).value(ctx) - } - } else { - filepath = this.staticValue - } - assert(filepath, `cannot include with empty filename`) - - const originBlocks = ctx.getRegister('blocks') - const originBlockMode = ctx.getRegister('blockMode') - - ctx.setRegister('blocks', {}) - ctx.setRegister('blockMode', BlockMode.OUTPUT) - if (this.with) { - hash[filepath] = await new Expression(this.with).evaluate(ctx) - } - const templates = await this.liquid.parseFile(filepath, ctx.opts) - ctx.push(hash) - await this.liquid.renderer.renderTemplates(templates, ctx, emitter) + yield this.liquid.renderer.renderTemplates(templates, ctx, emitter) ctx.pop() ctx.setRegister('blocks', originBlocks) ctx.setRegister('blockMode', originBlockMode) diff --git a/src/builtin/tags/layout.ts b/src/builtin/tags/layout.ts index 99f3d6bc2f..e8168f8af7 100644 --- a/src/builtin/tags/layout.ts +++ b/src/builtin/tags/layout.ts @@ -19,12 +19,9 @@ export default { this.tpls = this.liquid.parser.parse(remainTokens) }, - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { const layout = ctx.opts.dynamicPartials - ? (ctx.sync - ? new Expression(this.layout).valueSync(ctx) - : await new Expression(this.layout).value(ctx) - ) + ? yield new Expression(this.layout).value(ctx) : this.staticLayout assert(layout, `cannot apply layout with empty filename`) @@ -32,20 +29,14 @@ export default { ctx.setRegister('blockMode', BlockMode.STORE) const blocks = ctx.getRegister('blocks') const r = this.liquid.renderer - const html = ctx.sync - ? r.renderTemplatesSync(this.tpls, ctx) - : await r.renderTemplates(this.tpls, ctx) + const html = yield r.renderTemplates(this.tpls, ctx) if (blocks[''] === undefined) { blocks[''] = html } - const templates = ctx.sync - ? this.liquid.parseFileSync(layout, ctx.opts) - : await this.liquid.parseFile(layout, ctx.opts) + const templates = yield this.liquid._parseFile(layout, ctx.opts, ctx.sync) ctx.push(hash) ctx.setRegister('blockMode', BlockMode.OUTPUT) - const partial = ctx.sync - ? r.renderTemplatesSync(templates, ctx) - : await r.renderTemplates(templates, ctx) + const partial = yield r.renderTemplates(templates, ctx) ctx.pop() emitter.write(partial) } diff --git a/src/builtin/tags/raw.ts b/src/builtin/tags/raw.ts index 406edcf054..5e2aa76b7f 100644 --- a/src/builtin/tags/raw.ts +++ b/src/builtin/tags/raw.ts @@ -1,4 +1,4 @@ -import { TagToken, Token, ITagImplOptions, Context } from '../../types' +import { Hash, Emitter, TagToken, Token, ITagImplOptions, Context } from '../../types' export default { parse: function (tagToken: TagToken, remainTokens: Token[]) { @@ -15,7 +15,7 @@ export default { }) stream.start() }, - render: function (ctx: Context) { - return this.tokens.map((token: Token) => token.raw).join('') + render: function (ctx: Context, hash: Hash, emitter: Emitter) { + emitter.write(this.tokens.map((token: Token) => token.raw).join('')) } } as ITagImplOptions diff --git a/src/builtin/tags/tablerow.ts b/src/builtin/tags/tablerow.ts index e95492c228..a338ac3fb0 100644 --- a/src/builtin/tags/tablerow.ts +++ b/src/builtin/tags/tablerow.ts @@ -28,10 +28,8 @@ export default { stream.start() }, - render: async function (ctx: Context, hash: Hash, emitter: Emitter) { - let collection = ctx.sync - ? new Expression(this.collection).valueSync(ctx) || [] - : await new Expression(this.collection).value(ctx) || [] + render: function * (ctx: Context, hash: Hash, emitter: Emitter) { + let collection = (yield new Expression(this.collection).value(ctx)) || [] const offset = hash.offset || 0 const limit = (hash.limit === undefined) ? collection.length : hash.limit @@ -50,9 +48,7 @@ export default { emitter.write(`
' } as Token - const html = await render.renderTemplates([new HTML(token)], scope) + const html = await toThenable(render.renderTemplates([new HTML(token)], scope)) return expect(html).to.equal('
')
})
})
diff --git a/test/unit/render/value.ts b/test/unit/render/value.ts
index 5fa7c4e92d..f75baa1805 100644
--- a/test/unit/render/value.ts
+++ b/test/unit/render/value.ts
@@ -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').valueSync(ctx)).to.equal(1)
+ expect(new Value('one').value(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?').valueSync(ctx)).to.equal(true)
+ expect(new Value('has_value?').value(ctx)).to.equal(true)
})
it('should eval string variable', async function () {
const ctx = new Context({ x: 'XXX' })
- expect(new Value('x').valueSync(ctx)).to.equal('XXX')
+ expect(new Value('x').value(ctx)).to.equal('XXX')
})
it('should eval null literal', async function () {
- expect(new Value('null').valueSync({})).to.be.null
+ expect(new Value('null').value({} as any)).to.be.null
})
it('should eval nil literal', async function () {
- expect(new Value('nil').valueSync({})).to.be.null
+ expect(new Value('nil').value({} as any)).to.be.null
})
})
diff --git a/test/unit/template/filter/filter.ts b/test/unit/template/filter/filter.ts
index a57b8fb79e..5ef24f2415 100644
--- a/test/unit/template/filter/filter.ts
+++ b/test/unit/template/filter/filter.ts
@@ -3,6 +3,7 @@ import * as sinon from 'sinon'
import * as sinonChai from 'sinon-chai'
import { Filter } from '../../../../src/template/filter/filter'
import { Context } from '../../../../src/context/context'
+import { toThenable } from '../../../../src/util/async'
chai.use(sinonChai)
const expect = chai.expect
@@ -19,40 +20,40 @@ describe('filter', function () {
})
it('should render input if filter not registered', async function () {
- expect(await new Filter('undefined', [], false).render('foo', ctx)).to.equal('foo')
+ expect(await toThenable(new Filter('undefined', [], false).render('foo', ctx))).to.equal('foo')
})
it('should call filter impl with correct arguments', async function () {
const spy = sinon.spy()
Filter.register('foo', spy)
- await new Filter('foo', ['33'], false).render('foo', ctx)
+ await toThenable(new Filter('foo', ['33'], false).render('foo', ctx))
expect(spy).to.have.been.calledWith('foo', 33)
})
it('should call filter impl with correct this arg', async function () {
const spy = sinon.spy()
Filter.register('foo', spy)
- await new Filter('foo', ['33'], false).render('foo', ctx)
+ await toThenable(new Filter('foo', ['33'], false).render('foo', ctx))
expect(spy).to.have.been.calledOn(sinon.match.has('context', ctx))
})
it('should render a simple filter', async function () {
Filter.register('upcase', x => x.toUpperCase())
- expect(await new Filter('upcase', [], false).render('foo', ctx)).to.equal('FOO')
+ expect(await toThenable(new Filter('upcase', [], false).render('foo', ctx))).to.equal('FOO')
})
it('should render filters with argument', async function () {
Filter.register('add', (a, b) => a + b)
- expect(await new Filter('add', ['2'], false).render(3, ctx)).to.equal(5)
+ expect(await toThenable(new Filter('add', ['2'], false).render(3, ctx))).to.equal(5)
})
it('should render filters with multiple arguments', async function () {
Filter.register('add', (a, b, c) => a + b + c)
- expect(await new Filter('add', ['2', '"c"'], false).render(3, ctx)).to.equal('5c')
+ expect(await toThenable(new Filter('add', ['2', '"c"'], false).render(3, ctx))).to.equal('5c')
})
it('should pass Objects/Drops as it is', async function () {
Filter.register('name', a => a.constructor.name)
class Foo {}
- expect(await new Filter('name', [], false).render(new Foo(), ctx)).to.equal('Foo')
+ expect(await toThenable(new Filter('name', [], false).render(new Foo(), ctx))).to.equal('Foo')
})
it('should not throw when filter name illegal', function () {
@@ -61,13 +62,8 @@ describe('filter', function () {
}).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 () {
+ it('should support key value pairs', async 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')
+ expect(await toThenable((new Filter('add', [['num', '2']], false).render(3, ctx)))).to.equal('num:5')
})
})
diff --git a/test/unit/template/hash.ts b/test/unit/template/hash.ts
index 94b15e6f42..b7eea4c671 100644
--- a/test/unit/template/hash.ts
+++ b/test/unit/template/hash.ts
@@ -1,4 +1,5 @@
import * as chai from 'chai'
+import { toThenable } from '../../../src/util/async'
import { Hash } from '../../../src/template/tag/hash'
import { Context } from '../../../src/context/context'
@@ -6,15 +7,11 @@ const expect = chai.expect
describe('Hash', function () {
it('should parse variable', async function () {
- const hash = await Hash.create('num:foo', new Context({ foo: 3 }))
+ const hash = await toThenable(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())
+ const hash = await toThenable(Hash.create('num:3', new Context()))
expect(hash.num).to.equal(3)
})
})
diff --git a/test/unit/template/output.ts b/test/unit/template/output.ts
index 235f0e8900..61c0e56bba 100644
--- a/test/unit/template/output.ts
+++ b/test/unit/template/output.ts
@@ -1,4 +1,5 @@
import * as chai from 'chai'
+import { toThenable } from '../../../src/util/async'
import { Context } from '../../../src/context/context'
import { Output } from '../../../src/template/output'
import { OutputToken } from '../../../src/parser/output-token'
@@ -7,7 +8,7 @@ import { Filter } from '../../../src/template/filter/filter'
const expect = chai.expect
describe('Output', function () {
- const emitter = { write: (html: string) => (emitter.html += html), html: '' }
+ const emitter: any = { write: (html: string) => (emitter.html += html), html: '' }
beforeEach(function () {
Filter.clear()
emitter.html = ''
@@ -18,25 +19,25 @@ describe('Output', function () {
foo: { obj: { arr: ['a', 2] } }
})
const output = new Output({ value: 'foo' } as OutputToken, false)
- await output.render(scope, emitter)
+ await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('[object Object]')
})
it('should skip function property', async function () {
const scope = new Context({ obj: { foo: 'foo', bar: (x: any) => x } })
const output = new Output({ value: 'obj' } as OutputToken, false)
- await output.render(scope, emitter)
+ await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('[object Object]')
})
it('should respect to .toString()', async () => {
const scope = new Context({ obj: { toString: () => 'FOO' } })
const output = new Output({ value: 'obj' } as OutputToken, false)
- await output.render(scope, emitter)
+ await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('FOO')
})
it('should respect to .toString()', async () => {
const scope = new Context({ obj: { toString: () => 'FOO' } })
const output = new Output({ value: 'obj' } as OutputToken, false)
- await output.render(scope, emitter)
+ await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('FOO')
})
})
diff --git a/test/unit/template/tag.ts b/test/unit/template/tag.ts
index 211150ee28..4c6036c3a2 100644
--- a/test/unit/template/tag.ts
+++ b/test/unit/template/tag.ts
@@ -5,6 +5,7 @@ import * as sinon from 'sinon'
import * as sinonChai from 'sinon-chai'
import { Liquid } from '../../../src/liquid'
import { TagToken } from '../../../src/parser/tag-token'
+import { toThenable } from '../../../src/util/async'
chai.use(sinonChai)
const expect = chai.expect
@@ -12,7 +13,7 @@ const liquid = new Liquid()
describe('Tag', function () {
let ctx: Context
- const emitter = { write: (html: string) => (emitter.html += html), html: '' }
+ const emitter: any = { write: (html: string) => (emitter.html += html), html: '' }
before(function () {
ctx = new Context({
foo: 'bar',
@@ -55,7 +56,7 @@ describe('Tag', function () {
value: 'foo',
name: 'foo'
} as TagToken
- await new Tag(token, [], liquid).render(ctx, emitter)
+ await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.called
})
@@ -74,29 +75,29 @@ describe('Tag', function () {
} as TagToken
})
it('should call tag.render with scope', async function () {
- await new Tag(token, [], liquid).render(ctx, emitter)
+ await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch(ctx)
})
it('should resolve identifier hash', async function () {
- await new Tag(token, [], liquid).render(ctx, emitter)
+ await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch({}, {
aa: 'bar'
})
})
it('should accept space between key/value', async function () {
- await new Tag(token, [], liquid).render(ctx, emitter)
+ await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch({}, {
bb: 2
})
})
it('should resolve number value hash', async function () {
- await new Tag(token, [], liquid).render(ctx, emitter)
+ await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch(ctx, {
cc: 2.3
})
})
it('should resolve property access hash', async function () {
- await new Tag(token, [], liquid).render(ctx, emitter)
+ await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch(ctx, {
dd: 'uoo'
})
diff --git a/test/unit/template/value.ts b/test/unit/template/value.ts
index 739d1f434b..fe3ea12060 100644
--- a/test/unit/template/value.ts
+++ b/test/unit/template/value.ts
@@ -1,4 +1,5 @@
import * as chai from 'chai'
+import { toThenable } from '../../../src/util/async'
import * as sinonChai from 'sinon-chai'
import * as sinon from 'sinon'
import { Context } from '../../../src/context/context'
@@ -120,7 +121,7 @@ describe('Value', function () {
const scope = new Context({
foo: { bar: 'bar' }
})
- await tpl.value(scope)
+ await toThenable(tpl.value(scope))
expect(date).to.have.been.calledWith('bar', 'b')
expect(time).to.have.been.calledWith('y', 2)
})
diff --git a/test/unit/util/async.ts b/test/unit/util/async.ts
new file mode 100644
index 0000000000..c37713b039
--- /dev/null
+++ b/test/unit/util/async.ts
@@ -0,0 +1,106 @@
+import { toThenable, toValue } from '../../../src/util/async'
+import { expect, use } from 'chai'
+import * as chaiAsPromised from 'chai-as-promised'
+
+use(chaiAsPromised)
+
+describe('utils/async', () => {
+ describe('#toThenable()', function () {
+ it('should support iterable with single return statement', async () => {
+ function * foo () {
+ return 'foo'
+ }
+ const result = await toThenable(foo())
+ expect(result).to.equal('foo')
+ })
+ it('should support promise', async () => {
+ function foo () {
+ return Promise.resolve('foo')
+ }
+ const result = await toThenable(foo())
+ expect(result).to.equal('foo')
+ })
+ it('should resolve dependency', async () => {
+ function * foo () {
+ return yield bar()
+ }
+ function * bar () {
+ return 'bar'
+ }
+ const result = await toThenable(foo())
+ expect(result).to.equal('bar')
+ })
+ it('should support promise dependency', async () => {
+ function * foo () {
+ return yield Promise.resolve('foo')
+ }
+ const result = await toThenable(foo())
+ expect(result).to.equal('foo')
+ })
+ it('should reject Promise if dependency throws syncly', done => {
+ function * foo () {
+ return yield bar()
+ }
+ function * bar (): IterableIterator