mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
@@ -475,6 +475,15 @@ describe('filters/array', function () {
|
||||
- 2
|
||||
`)
|
||||
})
|
||||
it('should render none if args not specified', function () {
|
||||
return test(`{% assign kitchen_products = products | where %}
|
||||
Kitchen products:
|
||||
{% for product in kitchen_products -%}
|
||||
- {{ product.title }}
|
||||
{% endfor %}`, { products }, `
|
||||
Kitchen products:
|
||||
`)
|
||||
})
|
||||
})
|
||||
describe('where_exp', function () {
|
||||
const products = [
|
||||
@@ -560,6 +569,12 @@ describe('filters/array', function () {
|
||||
{ members },
|
||||
`{"graduation_year":2014,"name":"John"}`)
|
||||
})
|
||||
it('should render none if not found', function () {
|
||||
return test(
|
||||
`{{ members | find: "graduation_year", 2018 | json }}`,
|
||||
{ members },
|
||||
``)
|
||||
})
|
||||
})
|
||||
describe('find_exp', function () {
|
||||
const members = [
|
||||
@@ -573,5 +588,11 @@ describe('filters/array', function () {
|
||||
{ members },
|
||||
`{"graduation_year":2014,"name":"John"}`)
|
||||
})
|
||||
it('should render none if not found', function () {
|
||||
return test(
|
||||
`{{ members | find_exp: "item", "item.graduation_year == 2018" | json }}`,
|
||||
{ members },
|
||||
``)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,22 +1,81 @@
|
||||
import { LiquidOptions } from '../../../src/liquid-options'
|
||||
import { Liquid } from '.././../../src/liquid'
|
||||
import { test } from '../../stub/render'
|
||||
import { disableIntl } from '../../stub/no-intl'
|
||||
|
||||
describe('filters/date', function () {
|
||||
const liquid = new Liquid({ locale: 'en-US' })
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create a new Date when given "now"', function () {
|
||||
return test('{{ "now" | date: "%Y"}}', (new Date()).getFullYear().toString())
|
||||
})
|
||||
it('should create a new Date when given "today"', function () {
|
||||
return test('{{ "today" | date: "%Y"}}', (new Date()).getFullYear().toString())
|
||||
})
|
||||
it('should create from number', async function () {
|
||||
const time = new Date('2017-03-07T12:00:00').getTime() / 1000
|
||||
return test('{{ time | date: "%Y-%m-%dT%H:%M:%S" }}', { time }, '2017-03-07T12:00:00')
|
||||
})
|
||||
it('should create from number-like string', async function () {
|
||||
const time = String(new Date('2017-03-07T12:00:00').getTime() / 1000)
|
||||
return test('{{ time | date: "%Y-%m-%dT%H:%M:%S" }}', { time }, '2017-03-07T12:00:00')
|
||||
})
|
||||
it('should treat nil as 0', () => {
|
||||
expect(liquid.parseAndRenderSync('{{ nil | date: "%Y-%m-%dT%H:%M:%S", "Asia/Shanghai" }}')).toEqual('1970-01-01T08:00:00')
|
||||
})
|
||||
it('should treat undefined as invalid', () => {
|
||||
expect(liquid.parseAndRenderSync('{{ num | date: "%Y-%m-%dT%H:%M:%S", "Asia/Shanghai" }}', { num: undefined })).toEqual('')
|
||||
})
|
||||
})
|
||||
|
||||
it('should support date: %a %b %d %Y', function () {
|
||||
const date = new Date()
|
||||
return test('{{ date | date:"%a %b %d %Y"}}', { date }, date.toDateString())
|
||||
})
|
||||
describe('%a', () => {
|
||||
it('should support short week day', () => {
|
||||
const tpl = '{{ "2024-07-21T20:24:00.000Z" | date: "%a", "Asia/Shanghai" }}'
|
||||
expect(liquid.parseAndRenderSync(tpl)).toEqual('Mon')
|
||||
})
|
||||
it('should support short week day with timezone', () => {
|
||||
const tpl = '{{ "2024-07-21T20:24:00.000Z" | date: "%a", "America/New_York" }}'
|
||||
expect(liquid.parseAndRenderSync(tpl)).toEqual('Sun')
|
||||
})
|
||||
it('should support short week day with locale', () => {
|
||||
const liquid = new Liquid({ locale: 'zh-CN' })
|
||||
const tpl = '{{ "2024-07-21T20:24:00.000Z" | date: "%a", "America/New_York" }}'
|
||||
expect(liquid.parseAndRenderSync(tpl)).toEqual('周日')
|
||||
})
|
||||
})
|
||||
describe('%b', () => {
|
||||
it('should support short month', () => {
|
||||
const tpl = '{{ "2024-07-31T20:24:00.000Z" | date: "%b", "Asia/Shanghai" }}'
|
||||
expect(liquid.parseAndRenderSync(tpl)).toEqual('Aug')
|
||||
})
|
||||
it('should support short week day with locale', () => {
|
||||
const liquid = new Liquid({ locale: 'zh-CN' })
|
||||
const tpl = '{{ "2024-07-31T20:24:00.000Z" | date: "%b", "Asia/Shanghai" }}'
|
||||
expect(liquid.parseAndRenderSync(tpl)).toEqual('8月')
|
||||
})
|
||||
})
|
||||
describe('Intl compatibility', () => {
|
||||
disableIntl()
|
||||
it('should use English if Intl not supported', () => {
|
||||
const liquid = new Liquid()
|
||||
const tpl = '{{ "2024-07-31T20:24:00.000Z" | date: "%b", "Asia/Shanghai" }}'
|
||||
expect(liquid.parseAndRenderSync(tpl)).toEqual('Aug')
|
||||
})
|
||||
it('should use English if Intl not supported even for other locales', () => {
|
||||
const liquid = new Liquid({ locale: 'zh-CN' })
|
||||
const tpl = '{{ "2024-07-31T20:24:00.000Z" | date: "%b", "Asia/Shanghai" }}'
|
||||
expect(liquid.parseAndRenderSync(tpl)).toEqual('Aug')
|
||||
})
|
||||
})
|
||||
it('should support "now"', function () {
|
||||
// sample: Thursday, February 2, 2023 at 6:25 pm +0000
|
||||
return test('{{ "now" | date }}', /\w+, \w+ \d+, \d\d\d\d at \d+:\d\d [ap]m [-+]\d\d\d\d/)
|
||||
})
|
||||
it('should create a new Date when given "now"', function () {
|
||||
return test('{{ "now" | date: "%Y"}}', (new Date()).getFullYear().toString())
|
||||
})
|
||||
it('should create a new Date when given "today"', function () {
|
||||
return test('{{ "today" | date: "%Y"}}', (new Date()).getFullYear().toString())
|
||||
})
|
||||
it('should parse as Date when given a timezoneless string', function () {
|
||||
return test('{{ "1991-02-22T00:00:00" | date: "%Y-%m-%dT%H:%M:%S"}}', '1991-02-22T00:00:00')
|
||||
})
|
||||
@@ -45,14 +104,6 @@ describe('filters/date', function () {
|
||||
it('should render object as string', function () {
|
||||
return test('{{ obj | date: "%Y"}}', { obj: {} }, '[object Object]')
|
||||
})
|
||||
it('should create from number', async function () {
|
||||
const time = new Date('2017-03-07T12:00:00').getTime() / 1000
|
||||
return test('{{ time | date: "%Y-%m-%dT%H:%M:%S" }}', { time }, '2017-03-07T12:00:00')
|
||||
})
|
||||
it('should create from number-like string', async function () {
|
||||
const time = String(new Date('2017-03-07T12:00:00').getTime() / 1000)
|
||||
return test('{{ time | date: "%Y-%m-%dT%H:%M:%S" }}', { time }, '2017-03-07T12:00:00')
|
||||
})
|
||||
it('should support manipulation', async function () {
|
||||
return test('{{ date | date: "%s" | minus : 604800 | date: "%Y-%m-%dT%H:%M:%S"}}',
|
||||
{ date: new Date('2017-03-07T12:00:00') },
|
||||
@@ -180,6 +231,10 @@ describe('filters/date_to_string', function () {
|
||||
const output = liquid.parseAndRenderSync('{{ "2008-11-07T13:07:54-08:00" | date_to_string: "ordinal", "US" }}')
|
||||
expect(output).toEqual('Nov 7th, 2008')
|
||||
})
|
||||
it('should render none if not valid', function () {
|
||||
const output = liquid.parseAndRenderSync('{{ "hello" | date_to_string: "ordinal", "US" }}')
|
||||
expect(output).toEqual('hello')
|
||||
})
|
||||
})
|
||||
|
||||
describe('filters/date_to_long_string', function () {
|
||||
|
||||
@@ -43,9 +43,9 @@ describe('filters/object', function () {
|
||||
})
|
||||
it('should inspect cyclic object', () => {
|
||||
const text = '{{foo | inspect}}'
|
||||
const foo: any = { bar: 'bar' }
|
||||
const foo: any = { bar: { coo: 'coo' } }
|
||||
foo.foo = foo
|
||||
const expected = '{"bar":"bar","foo":"[Circular]"}'
|
||||
const expected = '{"bar":{"coo":"coo"},"foo":"[Circular]"}'
|
||||
return expect(liquid.parseAndRenderSync(text, { foo })).toBe(expected)
|
||||
})
|
||||
it('should support space argument', () => {
|
||||
|
||||
@@ -243,26 +243,39 @@ describe('filters/string', function () {
|
||||
const html = await liquid.parseAndRender('{{ "I\'m not hungry" | number_of_words: "auto"}}')
|
||||
expect(html).toEqual('3')
|
||||
})
|
||||
|
||||
it('should count words of empty sentence', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "" | number_of_words }}')
|
||||
expect(html).toEqual('0')
|
||||
})
|
||||
it('should count words of mixed sentence', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "Hello world!" | number_of_words }}')
|
||||
expect(html).toEqual('2')
|
||||
})
|
||||
|
||||
it('should count words of CJK sentence', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "你好hello世界world" | number_of_words }}')
|
||||
expect(html).toEqual('1')
|
||||
})
|
||||
|
||||
it('should count words of Latin sentence in CJK mode', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "I\'m not hungry" | number_of_words: "cjk"}}')
|
||||
expect(html).toEqual('3')
|
||||
})
|
||||
it('should count words of empty sentence in CJK mode', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "" | number_of_words: "cjk"}}')
|
||||
expect(html).toEqual('0')
|
||||
})
|
||||
it('should count words of CJK sentence with mode "cjk"', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "你好hello世界world" | number_of_words: "cjk" }}')
|
||||
expect(html).toEqual('6')
|
||||
})
|
||||
|
||||
it('should count words of CJK sentence with mode "auto"', async () => {
|
||||
it('should count words of mixed sentence with mode "auto"', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "你好hello世界world" | number_of_words: "auto" }}')
|
||||
expect(html).toEqual('6')
|
||||
})
|
||||
it('should count words of CJK sentence with mode "auto"', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "你好世界" | number_of_words: "auto" }}')
|
||||
expect(html).toEqual('4')
|
||||
})
|
||||
it('should handle empty input', async () => {
|
||||
const html = await liquid.parseAndRender('{{ "" | number_of_words }}')
|
||||
expect(html).toEqual('0')
|
||||
|
||||
@@ -33,6 +33,12 @@ describe('DoS related', function () {
|
||||
await expect(limit10.parseAndRender(src)).rejects.toThrow('template render limit exceeded')
|
||||
await expect(limit20.parseAndRender(src)).resolves.toBe('1,2,3,4,5,')
|
||||
})
|
||||
it('should support reset when calling render', async () => {
|
||||
const src = '{% for i in (1..5) %}{{i}},{% endfor %}'
|
||||
const liquid = new Liquid({ renderLimit: 0.01 })
|
||||
await expect(liquid.parseAndRender(src)).rejects.toThrow('template render limit exceeded')
|
||||
await expect(liquid.parseAndRender(src, {}, { renderLimit: 1e6 })).resolves.toBe('1,2,3,4,5,')
|
||||
})
|
||||
it('should take partials into account', async () => {
|
||||
mock({
|
||||
'/small': '{% for i in (1..5) %}{{i}}{% endfor %}',
|
||||
@@ -50,6 +56,12 @@ describe('DoS related', function () {
|
||||
await expect(liquid.parseAndRender('{{ array | slice: 0, 3 | join }}', { array })).resolves.toBe('0 0 0')
|
||||
await expect(liquid.parseAndRender('{{ array | slice: 0, 300 | join }}', { array })).rejects.toThrow('memory alloc limit exceeded, line:1, col:1')
|
||||
})
|
||||
it('should support reset when calling render', async () => {
|
||||
const array = Array(1e3).fill(0)
|
||||
const liquid = new Liquid({ memoryLimit: 100 })
|
||||
await expect(liquid.parseAndRender('{{ array | slice: 0, 300 | join }}', { array })).rejects.toThrow('memory alloc limit exceeded, line:1, col:1')
|
||||
await expect(liquid.parseAndRender('{{ array | slice: 0, 300 | join }}', { array }, { memoryLimit: 1e3 })).resolves.toBe(Array(300).fill(0).join(' '))
|
||||
})
|
||||
it('should throw for too many array iteration in tags', async () => {
|
||||
const array = ['a']
|
||||
const liquid = new Liquid({ memoryLimit: 100 })
|
||||
|
||||
@@ -9,7 +9,7 @@ describe('LiquidOptions#fs', function () {
|
||||
existsSync: (x: string) => !x.match(/not-exist/),
|
||||
readFile: (x: string) => Promise.resolve(`content for ${x}`),
|
||||
readFileSync: (x: string) => `content for ${x}`,
|
||||
fallback: (x: string) => '/root/files/fallback',
|
||||
fallback: (_x: string) => '/root/files/fallback',
|
||||
resolve: (base: string, path: string) => base + '/' + path
|
||||
}
|
||||
beforeEach(function () {
|
||||
@@ -49,7 +49,7 @@ describe('LiquidOptions#fs', function () {
|
||||
} as any)
|
||||
expect(engine.options.relativeReference).toBe(false)
|
||||
})
|
||||
it('should render from in-memory templates', () => {
|
||||
it('should render from in-memory templates', async () => {
|
||||
const engine = new Liquid({
|
||||
templates: {
|
||||
entry: '{% layout "main" %}entry',
|
||||
@@ -57,6 +57,7 @@ describe('LiquidOptions#fs', function () {
|
||||
}
|
||||
})
|
||||
expect(engine.renderFileSync('entry')).toEqual('header entry footer')
|
||||
await expect(engine.renderFile('entry')).resolves.toEqual('header entry footer')
|
||||
})
|
||||
it('should render relative in-memory templates', () => {
|
||||
const engine = new Liquid({
|
||||
|
||||
Reference in New Issue
Block a user