Files
liquidjs/test/integration/drop/drop.spec.ts
T
55e144a029 fix: isComparable full interface check (#701)
* Improve isComparable function to ensure full Comparable interface implementation

* Deleted trailing commas

---------

Co-authored-by: Guillermo Casal Caro <[email protected]>
2024-05-24 10:35:49 +08:00

123 lines
4.6 KiB
TypeScript

import { Liquid, Drop } from '../../../src'
describe('drop/drop', function () {
let liquid: Liquid
beforeEach(() => (liquid = new Liquid()))
class CustomDrop extends Drop {
private name = 'NAME'
public getName () {
return 'GET NAME'
}
}
class CustomDropWithMethodMissing extends CustomDrop {
public liquidMethodMissing (key: string) {
return key.toUpperCase()
}
}
class PromiseDrop extends Drop {
private name = Promise.resolve('NAME')
public async getName () {
return 'GET NAME'
}
public async liquidMethodMissing (key: string) {
return key.toUpperCase()
}
}
it('should call corresponding method when output', async function () {
const html = await liquid.parseAndRender(`{{obj.getName}}`, { obj: new CustomDrop() })
expect(html).toBe('GET NAME')
})
it('should call corresponding method when expression evaluates', async function () {
const html = await liquid.parseAndRender(`{% if obj.getName == "GET NAME" %}true{% endif %}`, { obj: new CustomDrop() })
expect(html).toBe('true')
})
it('should read corresponding property', async function () {
const html = await liquid.parseAndRender(`{{obj.name}}`, { obj: new CustomDrop() })
expect(html).toBe('NAME')
})
it('should output empty string if not exist', async function () {
const html = await liquid.parseAndRender(`{{obj.foo}}`, { obj: new CustomDrop() })
expect(html).toBe('')
})
it('should respect liquidMethodMissing', async function () {
const html = await liquid.parseAndRender(`{{obj.foo}}`, { obj: new CustomDropWithMethodMissing() })
expect(html).toBe('FOO')
})
it('should call corresponding promise method', async function () {
const html = await liquid.parseAndRender(`{{obj.getName}}`, { obj: new PromiseDrop() })
expect(html).toBe('GET NAME')
})
it('should read corresponding promise property', async function () {
const html = await liquid.parseAndRender(`{{obj.name}}`, { obj: new PromiseDrop() })
expect(html).toBe('NAME')
})
it('should resolve before calling filters', async function () {
const html = await liquid.parseAndRender(`{{obj.name | downcase}}`, { obj: new PromiseDrop() })
expect(html).toBe('name')
})
it('should support promise returned by liquidMethodMissing', async function () {
const html = await liquid.parseAndRender(`{{obj.foo}}`, { obj: new PromiseDrop() })
expect(html).toBe('FOO')
})
it('should respect valueOf', async () => {
class CustomDrop extends Drop {
prop = 'not enumerable'
valueOf () {
return ['foo', 'bar']
}
}
const tpl = '{{drop}}: {% for field in drop %}{{ field }};{% endfor %}'
const html = await liquid.parseAndRender(tpl, { drop: new CustomDrop() })
expect(html).toBe('foobar: foo;bar;')
})
it('should support valueOf in == expression', async () => {
class AddressDrop extends Drop {
valueOf () {
return 'test'
}
}
const address = new AddressDrop()
const customer = { default_address: new AddressDrop() }
const tpl = `{% if address == customer.default_address %}{{address}}{% endif %}`
const html = await liquid.parseAndRender(tpl, { address, customer })
expect(html).toBe('test')
})
it('should correctly evaluate custom Drop objects with equals function without full Comparable implementation', async () => {
class TestDrop extends Drop {
value: string;
constructor () {
super()
this.value = 'test'
}
equals (rhs: string): boolean {
return this.valueOf() === rhs
}
valueOf (): string {
return this.value
}
}
const address = new TestDrop()
const customer = { default_address: new TestDrop() }
const tpl = `{{ address >= customer.default_address }}`
const html = await liquid.parseAndRender(tpl, { address, customer })
expect(html).toBe('true')
})
it('should support returning supported value types from liquidMethodMissing', async function () {
class DynamicTypeDrop extends Drop {
liquidMethodMissing (key: string) {
switch (key) {
case 'number': return 42
case 'string': return 'foo'
case 'boolean': return true
case 'array': return [1, 2, 3]
case 'object': return { foo: 'bar' }
case 'drop': return new CustomDrop()
}
}
}
const html = await liquid.parseAndRender(`{{obj.number}} {{obj.string}} {{obj.boolean}} {{obj.array | first}} {{obj.object.foo}} {{obj.drop.getName}}`, { obj: new DynamicTypeDrop() })
expect(html).toBe('42 foo true 1 bar GET NAME')
})
})