/* * 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, { type HelperOptions } from '../..'; import { expectTemplate } from '../__jest__/test_bench'; describe('subexpressions', () => { it('arg-less helper', () => { expectTemplate('{{foo (bar)}}!') .withHelpers({ foo(val) { return val + val; }, bar() { return 'LOL'; }, }) .toCompileTo('LOLLOL!'); }); it('helper w args', () => { expectTemplate('{{blog (equal a b)}}') .withInput({ bar: 'LOL' }) .withHelpers({ blog(val) { return 'val is ' + val; }, equal(x, y) { return x === y; }, }) .toCompileTo('val is true'); }); it('mixed paths and helpers', () => { expectTemplate('{{blog baz.bat (equal a b) baz.bar}}') .withInput({ bar: 'LOL', baz: { bat: 'foo!', bar: 'bar!' } }) .withHelpers({ blog(val, that, theOther) { return 'val is ' + val + ', ' + that + ' and ' + theOther; }, equal(x, y) { return x === y; }, }) .toCompileTo('val is foo!, true and bar!'); }); it('supports much nesting', () => { expectTemplate('{{blog (equal (equal true true) true)}}') .withInput({ bar: 'LOL' }) .withHelpers({ blog(val) { return 'val is ' + val; }, equal(x, y) { return x === y; }, }) .toCompileTo('val is true'); }); it('GH-800 : Complex subexpressions', () => { const context = { a: 'a', b: 'b', c: { c: 'c' }, d: 'd', e: { e: 'e' } }; const helpers = { dash(a: any, b: any) { return a + '-' + b; }, concat(a: any, b: any) { return a + b; }, }; expectTemplate("{{dash 'abc' (concat a b)}}") .withInput(context) .withHelpers(helpers) .toCompileTo('abc-ab'); expectTemplate('{{dash d (concat a b)}}') .withInput(context) .withHelpers(helpers) .toCompileTo('d-ab'); expectTemplate('{{dash c.c (concat a b)}}') .withInput(context) .withHelpers(helpers) .toCompileTo('c-ab'); expectTemplate('{{dash (concat a b) c.c}}') .withInput(context) .withHelpers(helpers) .toCompileTo('ab-c'); expectTemplate('{{dash (concat a e.e) c.c}}') .withInput(context) .withHelpers(helpers) .toCompileTo('ae-c'); }); it('provides each nested helper invocation its own options hash', () => { let lastOptions: HelperOptions; const helpers = { equal(x: any, y: any, options: HelperOptions) { if (!options || options === lastOptions) { throw new Error('options hash was reused'); } lastOptions = options; return x === y; }, }; expectTemplate('{{equal (equal true true) true}}').withHelpers(helpers).toCompileTo('true'); }); it('with hashes', () => { expectTemplate("{{blog (equal (equal true true) true fun='yes')}}") .withInput({ bar: 'LOL' }) .withHelpers({ blog(val) { return 'val is ' + val; }, equal(x, y) { return x === y; }, }) .toCompileTo('val is true'); }); it('as hashes', () => { expectTemplate("{{blog fun=(equal (blog fun=1) 'val is 1')}}") .withHelpers({ blog(options) { return 'val is ' + options.hash.fun; }, equal(x, y) { return x === y; }, }) .toCompileTo('val is true'); }); it('multiple subexpressions in a hash', () => { expectTemplate('{{input aria-label=(t "Name") placeholder=(t "Example User")}}') .withHelpers({ input(options) { const hash = options.hash; const ariaLabel = Handlebars.Utils.escapeExpression(hash['aria-label']); const placeholder = Handlebars.Utils.escapeExpression(hash.placeholder); return new Handlebars.SafeString( '' ); }, t(defaultString) { return new Handlebars.SafeString(defaultString); }, }) .toCompileTo(''); }); it('multiple subexpressions in a hash with context', () => { expectTemplate('{{input aria-label=(t item.field) placeholder=(t item.placeholder)}}') .withInput({ item: { field: 'Name', placeholder: 'Example User', }, }) .withHelpers({ input(options) { const hash = options.hash; const ariaLabel = Handlebars.Utils.escapeExpression(hash['aria-label']); const placeholder = Handlebars.Utils.escapeExpression(hash.placeholder); return new Handlebars.SafeString( '' ); }, t(defaultString) { return new Handlebars.SafeString(defaultString); }, }) .toCompileTo(''); }); it('subexpression functions on the context', () => { expectTemplate('{{foo (bar)}}!') .withInput({ bar() { return 'LOL'; }, }) .withHelpers({ foo(val) { return val + val; }, }) .toCompileTo('LOLLOL!'); }); it("subexpressions can't just be property lookups", () => { expectTemplate('{{foo (bar)}}!') .withInput({ bar: 'LOL', }) .withHelpers({ foo(val) { return val + val; }, }) .toThrow(); }); });