diff options
| author | Darius Jahandarie <djahandarie@gmail.com> | 2023-11-04 18:45:57 +0900 | 
|---|---|---|
| committer | Darius Jahandarie <djahandarie@gmail.com> | 2023-11-04 18:45:57 +0900 | 
| commit | ef79eab44bfd000792c610b968b5ceefd41e76a0 (patch) | |
| tree | 48b04f30f6248caedbd880801aa49402a9e8066a /dev/lib/handlebars/src/spec/index.basic.test.ts | |
| parent | 376151096431d4362e4baaacf0cef4a534e169f7 (diff) | |
Modernize codebase
- Use ES modules
- Remove vendored libs and build them from npm using esbuild
- Switch from JSZip to zip.js
Diffstat (limited to 'dev/lib/handlebars/src/spec/index.basic.test.ts')
| -rw-r--r-- | dev/lib/handlebars/src/spec/index.basic.test.ts | 481 | 
1 files changed, 481 insertions, 0 deletions
| diff --git a/dev/lib/handlebars/src/spec/index.basic.test.ts b/dev/lib/handlebars/src/spec/index.basic.test.ts new file mode 100644 index 00000000..6acf3ae9 --- /dev/null +++ b/dev/lib/handlebars/src/spec/index.basic.test.ts @@ -0,0 +1,481 @@ +/* + * This file is forked from the handlebars project (https://github.com/handlebars-lang/handlebars.js), + * and may include modifications made by Elasticsearch B.V. + * Elasticsearch B.V. licenses this file to you under the MIT License. + * See `packages/kbn-handlebars/LICENSE` for more information. + */ + +import Handlebars from '../..'; +import { expectTemplate } from '../__jest__/test_bench'; + +describe('basic context', () => { +  it('most basic', () => { +    expectTemplate('{{foo}}').withInput({ foo: 'foo' }).toCompileTo('foo'); +  }); + +  it('escaping', () => { +    expectTemplate('\\{{foo}}').withInput({ foo: 'food' }).toCompileTo('{{foo}}'); +    expectTemplate('content \\{{foo}}').withInput({ foo: 'food' }).toCompileTo('content {{foo}}'); +    expectTemplate('\\\\{{foo}}').withInput({ foo: 'food' }).toCompileTo('\\food'); +    expectTemplate('content \\\\{{foo}}').withInput({ foo: 'food' }).toCompileTo('content \\food'); +    expectTemplate('\\\\ {{foo}}').withInput({ foo: 'food' }).toCompileTo('\\\\ food'); +  }); + +  it('compiling with a basic context', () => { +    expectTemplate('Goodbye\n{{cruel}}\n{{world}}!') +      .withInput({ +        cruel: 'cruel', +        world: 'world', +      }) +      .toCompileTo('Goodbye\ncruel\nworld!'); +  }); + +  it('compiling with a string context', () => { +    expectTemplate('{{.}}{{length}}').withInput('bye').toCompileTo('bye3'); +  }); + +  it('compiling with an undefined context', () => { +    expectTemplate('Goodbye\n{{cruel}}\n{{world.bar}}!') +      .withInput(undefined) +      .toCompileTo('Goodbye\n\n!'); + +    expectTemplate('{{#unless foo}}Goodbye{{../test}}{{test2}}{{/unless}}') +      .withInput(undefined) +      .toCompileTo('Goodbye'); +  }); + +  it('comments', () => { +    expectTemplate('{{! Goodbye}}Goodbye\n{{cruel}}\n{{world}}!') +      .withInput({ +        cruel: 'cruel', +        world: 'world', +      }) +      .toCompileTo('Goodbye\ncruel\nworld!'); + +    expectTemplate('    {{~! comment ~}}      blah').toCompileTo('blah'); +    expectTemplate('    {{~!-- long-comment --~}}      blah').toCompileTo('blah'); +    expectTemplate('    {{! comment ~}}      blah').toCompileTo('    blah'); +    expectTemplate('    {{!-- long-comment --~}}      blah').toCompileTo('    blah'); +    expectTemplate('    {{~! comment}}      blah').toCompileTo('      blah'); +    expectTemplate('    {{~!-- long-comment --}}      blah').toCompileTo('      blah'); +  }); + +  it('boolean', () => { +    const string = '{{#goodbye}}GOODBYE {{/goodbye}}cruel {{world}}!'; +    expectTemplate(string) +      .withInput({ +        goodbye: true, +        world: 'world', +      }) +      .toCompileTo('GOODBYE cruel world!'); + +    expectTemplate(string) +      .withInput({ +        goodbye: false, +        world: 'world', +      }) +      .toCompileTo('cruel world!'); +  }); + +  it('zeros', () => { +    expectTemplate('num1: {{num1}}, num2: {{num2}}') +      .withInput({ +        num1: 42, +        num2: 0, +      }) +      .toCompileTo('num1: 42, num2: 0'); + +    expectTemplate('num: {{.}}').withInput(0).toCompileTo('num: 0'); + +    expectTemplate('num: {{num1/num2}}') +      .withInput({ num1: { num2: 0 } }) +      .toCompileTo('num: 0'); +  }); + +  it('false', () => { +    /* eslint-disable no-new-wrappers */ +    expectTemplate('val1: {{val1}}, val2: {{val2}}') +      .withInput({ +        val1: false, +        val2: new Boolean(false), +      }) +      .toCompileTo('val1: false, val2: false'); + +    expectTemplate('val: {{.}}').withInput(false).toCompileTo('val: false'); + +    expectTemplate('val: {{val1/val2}}') +      .withInput({ val1: { val2: false } }) +      .toCompileTo('val: false'); + +    expectTemplate('val1: {{{val1}}}, val2: {{{val2}}}') +      .withInput({ +        val1: false, +        val2: new Boolean(false), +      }) +      .toCompileTo('val1: false, val2: false'); + +    expectTemplate('val: {{{val1/val2}}}') +      .withInput({ val1: { val2: false } }) +      .toCompileTo('val: false'); +    /* eslint-enable */ +  }); + +  it('should handle undefined and null', () => { +    expectTemplate('{{awesome undefined null}}') +      .withInput({ +        awesome(_undefined: any, _null: any, options: any) { +          return (_undefined === undefined) + ' ' + (_null === null) + ' ' + typeof options; +        }, +      }) +      .toCompileTo('true true object'); + +    expectTemplate('{{undefined}}') +      .withInput({ +        undefined() { +          return 'undefined!'; +        }, +      }) +      .toCompileTo('undefined!'); + +    expectTemplate('{{null}}') +      .withInput({ +        null() { +          return 'null!'; +        }, +      }) +      .toCompileTo('null!'); +  }); + +  it('newlines', () => { +    expectTemplate("Alan's\nTest").toCompileTo("Alan's\nTest"); +    expectTemplate("Alan's\rTest").toCompileTo("Alan's\rTest"); +  }); + +  it('escaping text', () => { +    expectTemplate("Awesome's").toCompileTo("Awesome's"); +    expectTemplate('Awesome\\').toCompileTo('Awesome\\'); +    expectTemplate('Awesome\\\\ foo').toCompileTo('Awesome\\\\ foo'); +    expectTemplate('Awesome {{foo}}').withInput({ foo: '\\' }).toCompileTo('Awesome \\'); +    expectTemplate(" ' ' ").toCompileTo(" ' ' "); +  }); + +  it('escaping expressions', () => { +    expectTemplate('{{{awesome}}}').withInput({ awesome: "&'\\<>" }).toCompileTo("&'\\<>"); + +    expectTemplate('{{&awesome}}').withInput({ awesome: "&'\\<>" }).toCompileTo("&'\\<>"); + +    expectTemplate('{{awesome}}') +      .withInput({ awesome: '&"\'`\\<>' }) +      .toCompileTo('&"'`\\<>'); + +    expectTemplate('{{awesome}}') +      .withInput({ awesome: 'Escaped, <b> looks like: <b>' }) +      .toCompileTo('Escaped, <b> looks like: &lt;b&gt;'); +  }); + +  it("functions returning safestrings shouldn't be escaped", () => { +    expectTemplate('{{awesome}}') +      .withInput({ +        awesome() { +          return new Handlebars.SafeString("&'\\<>"); +        }, +      }) +      .toCompileTo("&'\\<>"); +  }); + +  it('functions', () => { +    expectTemplate('{{awesome}}') +      .withInput({ +        awesome() { +          return 'Awesome'; +        }, +      }) +      .toCompileTo('Awesome'); + +    expectTemplate('{{awesome}}') +      .withInput({ +        awesome() { +          return this.more; +        }, +        more: 'More awesome', +      }) +      .toCompileTo('More awesome'); +  }); + +  it('functions with context argument', () => { +    expectTemplate('{{awesome frank}}') +      .withInput({ +        awesome(context: any) { +          return context; +        }, +        frank: 'Frank', +      }) +      .toCompileTo('Frank'); +  }); + +  it('pathed functions with context argument', () => { +    expectTemplate('{{bar.awesome frank}}') +      .withInput({ +        bar: { +          awesome(context: any) { +            return context; +          }, +        }, +        frank: 'Frank', +      }) +      .toCompileTo('Frank'); +  }); + +  it('depthed functions with context argument', () => { +    expectTemplate('{{#with frank}}{{../awesome .}}{{/with}}') +      .withInput({ +        awesome(context: any) { +          return context; +        }, +        frank: 'Frank', +      }) +      .toCompileTo('Frank'); +  }); + +  it('block functions with context argument', () => { +    expectTemplate('{{#awesome 1}}inner {{.}}{{/awesome}}') +      .withInput({ +        awesome(context: any, options: any) { +          return options.fn(context); +        }, +      }) +      .toCompileTo('inner 1'); +  }); + +  it('depthed block functions with context argument', () => { +    expectTemplate('{{#with value}}{{#../awesome 1}}inner {{.}}{{/../awesome}}{{/with}}') +      .withInput({ +        value: true, +        awesome(context: any, options: any) { +          return options.fn(context); +        }, +      }) +      .toCompileTo('inner 1'); +  }); + +  it('block functions without context argument', () => { +    expectTemplate('{{#awesome}}inner{{/awesome}}') +      .withInput({ +        awesome(options: any) { +          return options.fn(this); +        }, +      }) +      .toCompileTo('inner'); +  }); + +  it('pathed block functions without context argument', () => { +    expectTemplate('{{#foo.awesome}}inner{{/foo.awesome}}') +      .withInput({ +        foo: { +          awesome() { +            return this; +          }, +        }, +      }) +      .toCompileTo('inner'); +  }); + +  it('depthed block functions without context argument', () => { +    expectTemplate('{{#with value}}{{#../awesome}}inner{{/../awesome}}{{/with}}') +      .withInput({ +        value: true, +        awesome() { +          return this; +        }, +      }) +      .toCompileTo('inner'); +  }); + +  it('paths with hyphens', () => { +    expectTemplate('{{foo-bar}}').withInput({ 'foo-bar': 'baz' }).toCompileTo('baz'); + +    expectTemplate('{{foo.foo-bar}}') +      .withInput({ foo: { 'foo-bar': 'baz' } }) +      .toCompileTo('baz'); + +    expectTemplate('{{foo/foo-bar}}') +      .withInput({ foo: { 'foo-bar': 'baz' } }) +      .toCompileTo('baz'); +  }); + +  it('nested paths', () => { +    expectTemplate('Goodbye {{alan/expression}} world!') +      .withInput({ alan: { expression: 'beautiful' } }) +      .toCompileTo('Goodbye beautiful world!'); +  }); + +  it('nested paths with empty string value', () => { +    expectTemplate('Goodbye {{alan/expression}} world!') +      .withInput({ alan: { expression: '' } }) +      .toCompileTo('Goodbye  world!'); +  }); + +  it('literal paths', () => { +    expectTemplate('Goodbye {{[@alan]/expression}} world!') +      .withInput({ '@alan': { expression: 'beautiful' } }) +      .toCompileTo('Goodbye beautiful world!'); + +    expectTemplate('Goodbye {{[foo bar]/expression}} world!') +      .withInput({ 'foo bar': { expression: 'beautiful' } }) +      .toCompileTo('Goodbye beautiful world!'); +  }); + +  it('literal references', () => { +    expectTemplate('Goodbye {{[foo bar]}} world!') +      .withInput({ 'foo bar': 'beautiful' }) +      .toCompileTo('Goodbye beautiful world!'); + +    expectTemplate('Goodbye {{"foo bar"}} world!') +      .withInput({ 'foo bar': 'beautiful' }) +      .toCompileTo('Goodbye beautiful world!'); + +    expectTemplate("Goodbye {{'foo bar'}} world!") +      .withInput({ 'foo bar': 'beautiful' }) +      .toCompileTo('Goodbye beautiful world!'); + +    expectTemplate('Goodbye {{"foo[bar"}} world!') +      .withInput({ 'foo[bar': 'beautiful' }) +      .toCompileTo('Goodbye beautiful world!'); + +    expectTemplate('Goodbye {{"foo\'bar"}} world!') +      .withInput({ "foo'bar": 'beautiful' }) +      .toCompileTo('Goodbye beautiful world!'); + +    expectTemplate("Goodbye {{'foo\"bar'}} world!") +      .withInput({ 'foo"bar': 'beautiful' }) +      .toCompileTo('Goodbye beautiful world!'); +  }); + +  it("that current context path ({{.}}) doesn't hit helpers", () => { +    expectTemplate('test: {{.}}') +      .withInput(null) +      // @ts-expect-error Setting the helper to a string instead of a function doesn't make sense normally, but here it doesn't matter +      .withHelpers({ helper: 'awesome' }) +      .toCompileTo('test: '); +  }); + +  it('complex but empty paths', () => { +    expectTemplate('{{person/name}}') +      .withInput({ person: { name: null } }) +      .toCompileTo(''); + +    expectTemplate('{{person/name}}').withInput({ person: {} }).toCompileTo(''); +  }); + +  it('this keyword in paths', () => { +    expectTemplate('{{#goodbyes}}{{this}}{{/goodbyes}}') +      .withInput({ goodbyes: ['goodbye', 'Goodbye', 'GOODBYE'] }) +      .toCompileTo('goodbyeGoodbyeGOODBYE'); + +    expectTemplate('{{#hellos}}{{this/text}}{{/hellos}}') +      .withInput({ +        hellos: [{ text: 'hello' }, { text: 'Hello' }, { text: 'HELLO' }], +      }) +      .toCompileTo('helloHelloHELLO'); +  }); + +  it('this keyword nested inside path', () => { +    expectTemplate('{{#hellos}}{{text/this/foo}}{{/hellos}}').toThrow( +      'Invalid path: text/this - 1:13' +    ); + +    expectTemplate('{{[this]}}').withInput({ this: 'bar' }).toCompileTo('bar'); + +    expectTemplate('{{text/[this]}}') +      .withInput({ text: { this: 'bar' } }) +      .toCompileTo('bar'); +  }); + +  it('this keyword in helpers', () => { +    const helpers = { +      foo(value: any) { +        return 'bar ' + value; +      }, +    }; + +    expectTemplate('{{#goodbyes}}{{foo this}}{{/goodbyes}}') +      .withInput({ goodbyes: ['goodbye', 'Goodbye', 'GOODBYE'] }) +      .withHelpers(helpers) +      .toCompileTo('bar goodbyebar Goodbyebar GOODBYE'); + +    expectTemplate('{{#hellos}}{{foo this/text}}{{/hellos}}') +      .withInput({ +        hellos: [{ text: 'hello' }, { text: 'Hello' }, { text: 'HELLO' }], +      }) +      .withHelpers(helpers) +      .toCompileTo('bar hellobar Hellobar HELLO'); +  }); + +  it('this keyword nested inside helpers param', () => { +    expectTemplate('{{#hellos}}{{foo text/this/foo}}{{/hellos}}').toThrow( +      'Invalid path: text/this - 1:17' +    ); + +    expectTemplate('{{foo [this]}}') +      .withInput({ +        foo(value: any) { +          return value; +        }, +        this: 'bar', +      }) +      .toCompileTo('bar'); + +    expectTemplate('{{foo text/[this]}}') +      .withInput({ +        foo(value: any) { +          return value; +        }, +        text: { this: 'bar' }, +      }) +      .toCompileTo('bar'); +  }); + +  it('pass string literals', () => { +    expectTemplate('{{"foo"}}').toCompileTo(''); +    expectTemplate('{{"foo"}}').withInput({ foo: 'bar' }).toCompileTo('bar'); + +    expectTemplate('{{#"foo"}}{{.}}{{/"foo"}}') +      .withInput({ +        foo: ['bar', 'baz'], +      }) +      .toCompileTo('barbaz'); +  }); + +  it('pass number literals', () => { +    expectTemplate('{{12}}').toCompileTo(''); +    expectTemplate('{{12}}').withInput({ '12': 'bar' }).toCompileTo('bar'); +    expectTemplate('{{12.34}}').toCompileTo(''); +    expectTemplate('{{12.34}}').withInput({ '12.34': 'bar' }).toCompileTo('bar'); +    expectTemplate('{{12.34 1}}') +      .withInput({ +        '12.34'(arg: any) { +          return 'bar' + arg; +        }, +      }) +      .toCompileTo('bar1'); +  }); + +  it('pass boolean literals', () => { +    expectTemplate('{{true}}').toCompileTo(''); +    expectTemplate('{{true}}').withInput({ '': 'foo' }).toCompileTo(''); +    expectTemplate('{{false}}').withInput({ false: 'foo' }).toCompileTo('foo'); +  }); + +  it('should handle literals in subexpression', () => { +    expectTemplate('{{foo (false)}}') +      .withInput({ +        false() { +          return 'bar'; +        }, +      }) +      .withHelper('foo', function (arg) { +        return arg; +      }) +      .toCompileTo('bar'); +  }); +}); |