diff options
Diffstat (limited to 'dev/lib/handlebars/index.test.ts')
| -rw-r--r-- | dev/lib/handlebars/index.test.ts | 567 | 
1 files changed, 0 insertions, 567 deletions
| diff --git a/dev/lib/handlebars/index.test.ts b/dev/lib/handlebars/index.test.ts deleted file mode 100644 index ed607db1..00000000 --- a/dev/lib/handlebars/index.test.ts +++ /dev/null @@ -1,567 +0,0 @@ -/* - * Elasticsearch B.V licenses this file to you under the MIT License. - * See `packages/kbn-handlebars/LICENSE` for more information. - */ - -/** - * ABOUT THIS FILE: - * - * This file is for tests not copied from the upstream handlebars project, but - * tests that we feel are needed in order to fully cover our use-cases. - */ - -import Handlebars from '.'; -import type { HelperOptions, TemplateDelegate } from './src/types'; -import { expectTemplate, forEachCompileFunctionName } from './src/__jest__/test_bench'; - -it('Handlebars.create', () => { -  expect(Handlebars.create()).toMatchSnapshot(); -}); - -describe('Handlebars.compileAST', () => { -  describe('compiler options', () => { -    it('noEscape', () => { -      expectTemplate('{{value}}').withInput({ value: '<foo>' }).toCompileTo('<foo>'); - -      expectTemplate('{{value}}') -        .withCompileOptions({ noEscape: false }) -        .withInput({ value: '<foo>' }) -        .toCompileTo('<foo>'); - -      expectTemplate('{{value}}') -        .withCompileOptions({ noEscape: true }) -        .withInput({ value: '<foo>' }) -        .toCompileTo('<foo>'); -    }); -  }); - -  it('invalid template', () => { -    expectTemplate('{{value').withInput({ value: 42 }).toThrow(`Parse error on line 1: -{{value ---^ -Expecting 'ID', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'INVALID'`); -  }); - -  if (!process.env.EVAL) { -    it('reassign', () => { -      const fn = Handlebars.compileAST; -      expect(fn('{{value}}')({ value: 42 })).toEqual('42'); -    }); -  } -}); - -// Extra "helpers" tests -describe('helpers', () => { -  it('Only provide options.fn/inverse to block helpers', () => { -    function toHaveProperties(...args: any[]) { -      toHaveProperties.calls++; -      const options = args[args.length - 1]; -      expect(options).toHaveProperty('fn'); -      expect(options).toHaveProperty('inverse'); -      return 42; -    } -    toHaveProperties.calls = 0; - -    function toNotHaveProperties(...args: any[]) { -      toNotHaveProperties.calls++; -      const options = args[args.length - 1]; -      expect(options).not.toHaveProperty('fn'); -      expect(options).not.toHaveProperty('inverse'); -      return 42; -    } -    toNotHaveProperties.calls = 0; - -    const nonBlockTemplates = ['{{foo}}', '{{foo 1 2}}']; -    const blockTemplates = ['{{#foo}}42{{/foo}}', '{{#foo 1 2}}42{{/foo}}']; - -    for (const template of nonBlockTemplates) { -      expectTemplate(template) -        .withInput({ -          foo: toNotHaveProperties, -        }) -        .toCompileTo('42'); - -      expectTemplate(template).withHelper('foo', toNotHaveProperties).toCompileTo('42'); -    } - -    for (const template of blockTemplates) { -      expectTemplate(template) -        .withInput({ -          foo: toHaveProperties, -        }) -        .toCompileTo('42'); - -      expectTemplate(template).withHelper('foo', toHaveProperties).toCompileTo('42'); -    } - -    const factor = process.env.AST || process.env.EVAL ? 1 : 2; -    expect(toNotHaveProperties.calls).toEqual(nonBlockTemplates.length * 2 * factor); -    expect(toHaveProperties.calls).toEqual(blockTemplates.length * 2 * factor); -  }); - -  it('should pass expected "this" to helper functions (without input)', () => { -    expectTemplate('{{hello "world" 12 true false}}') -      .withHelper('hello', function (this: any, ...args: any[]) { -        expect(this).toMatchInlineSnapshot(`Object {}`); -      }) -      .toCompileTo(''); -  }); - -  it('should pass expected "this" to helper functions (with input)', () => { -    expectTemplate('{{hello "world" 12 true false}}') -      .withHelper('hello', function (this: any, ...args: any[]) { -        expect(this).toMatchInlineSnapshot(` -          Object { -            "people": Array [ -              Object { -                "id": 1, -                "name": "Alan", -              }, -              Object { -                "id": 2, -                "name": "Yehuda", -              }, -            ], -          } -        `); -      }) -      .withInput({ -        people: [ -          { name: 'Alan', id: 1 }, -          { name: 'Yehuda', id: 2 }, -        ], -      }) -      .toCompileTo(''); -  }); - -  it('should pass expected "this" and arguments to helper functions (non-block helper)', () => { -    expectTemplate('{{hello "world" 12 true false}}') -      .withHelper('hello', function (this: any, ...args: any[]) { -        expect(args).toMatchInlineSnapshot(` -          Array [ -            "world", -            12, -            true, -            false, -            Object { -              "data": Object { -                "root": Object { -                  "people": Array [ -                    Object { -                      "id": 1, -                      "name": "Alan", -                    }, -                    Object { -                      "id": 2, -                      "name": "Yehuda", -                    }, -                  ], -                }, -              }, -              "hash": Object {}, -              "loc": Object { -                "end": Object { -                  "column": 31, -                  "line": 1, -                }, -                "start": Object { -                  "column": 0, -                  "line": 1, -                }, -              }, -              "lookupProperty": [Function], -              "name": "hello", -            }, -          ] -        `); -      }) -      .withInput({ -        people: [ -          { name: 'Alan', id: 1 }, -          { name: 'Yehuda', id: 2 }, -        ], -      }) -      .toCompileTo(''); -  }); - -  it('should pass expected "this" and arguments to helper functions (block helper)', () => { -    expectTemplate('{{#hello "world" 12 true false}}{{/hello}}') -      .withHelper('hello', function (this: any, ...args: any[]) { -        expect(args).toMatchInlineSnapshot(` -          Array [ -            "world", -            12, -            true, -            false, -            Object { -              "data": Object { -                "root": Object { -                  "people": Array [ -                    Object { -                      "id": 1, -                      "name": "Alan", -                    }, -                    Object { -                      "id": 2, -                      "name": "Yehuda", -                    }, -                  ], -                }, -              }, -              "fn": [Function], -              "hash": Object {}, -              "inverse": [Function], -              "loc": Object { -                "end": Object { -                  "column": 42, -                  "line": 1, -                }, -                "start": Object { -                  "column": 0, -                  "line": 1, -                }, -              }, -              "lookupProperty": [Function], -              "name": "hello", -            }, -          ] -        `); -      }) -      .withInput({ -        people: [ -          { name: 'Alan', id: 1 }, -          { name: 'Yehuda', id: 2 }, -        ], -      }) -      .toCompileTo(''); -  }); -}); - -// Extra "blocks" tests -describe('blocks', () => { -  describe('decorators', () => { -    it('should only call decorator once', () => { -      let calls = 0; -      const callsExpected = process.env.AST || process.env.EVAL ? 1 : 2; -      expectTemplate('{{#helper}}{{*decorator}}{{/helper}}') -        .withHelper('helper', () => {}) -        .withDecorator('decorator', () => { -          calls++; -        }) -        .toCompileTo(''); -      expect(calls).toEqual(callsExpected); -    }); - -    forEachCompileFunctionName((compileName) => { -      it(`should call decorator again if render function is called again for #${compileName}`, () => { -        global.kbnHandlebarsEnv = Handlebars.create(); - -        kbnHandlebarsEnv!.registerDecorator('decorator', () => { -          calls++; -        }); - -        const compile = kbnHandlebarsEnv![compileName].bind(kbnHandlebarsEnv); -        const render = compile('{{*decorator}}'); - -        let calls = 0; -        expect(render()).toEqual(''); -        expect(calls).toEqual(1); - -        calls = 0; -        expect(render()).toEqual(''); -        expect(calls).toEqual(1); - -        global.kbnHandlebarsEnv = null; -      }); -    }); - -    it('should pass expected options to nested decorator', () => { -      expectTemplate('{{#helper}}{{*decorator foo}}{{/helper}}') -        .withHelper('helper', () => {}) -        .withDecorator('decorator', function (fn, props, container, options) { -          expect(options).toMatchInlineSnapshot(` -            Object { -              "args": Array [ -                "bar", -              ], -              "data": Object { -                "root": Object { -                  "foo": "bar", -                }, -              }, -              "hash": Object {}, -              "loc": Object { -                "end": Object { -                  "column": 29, -                  "line": 1, -                }, -                "start": Object { -                  "column": 11, -                  "line": 1, -                }, -              }, -              "name": "decorator", -            } -          `); -        }) -        .withInput({ foo: 'bar' }) -        .toCompileTo(''); -    }); - -    it('should pass expected options to root decorator with no args', () => { -      expectTemplate('{{*decorator}}') -        .withDecorator('decorator', function (fn, props, container, options) { -          expect(options).toMatchInlineSnapshot(` -            Object { -              "args": Array [], -              "data": Object { -                "root": Object { -                  "foo": "bar", -                }, -              }, -              "hash": Object {}, -              "loc": Object { -                "end": Object { -                  "column": 14, -                  "line": 1, -                }, -                "start": Object { -                  "column": 0, -                  "line": 1, -                }, -              }, -              "name": "decorator", -            } -          `); -        }) -        .withInput({ foo: 'bar' }) -        .toCompileTo(''); -    }); - -    it('should pass expected options to root decorator with one arg', () => { -      expectTemplate('{{*decorator foo}}') -        .withDecorator('decorator', function (fn, props, container, options) { -          expect(options).toMatchInlineSnapshot(` -            Object { -              "args": Array [ -                undefined, -              ], -              "data": Object { -                "root": Object { -                  "foo": "bar", -                }, -              }, -              "hash": Object {}, -              "loc": Object { -                "end": Object { -                  "column": 18, -                  "line": 1, -                }, -                "start": Object { -                  "column": 0, -                  "line": 1, -                }, -              }, -              "name": "decorator", -            } -          `); -        }) -        .withInput({ foo: 'bar' }) -        .toCompileTo(''); -    }); - -    describe('return values', () => { -      for (const [desc, template, result] of [ -        ['non-block', '{{*decorator}}cont{{*decorator}}ent', 'content'], -        ['block', '{{#*decorator}}con{{/decorator}}tent', 'tent'], -      ]) { -        describe(desc, () => { -          const falsy = [undefined, null, false, 0, '']; -          const truthy = [true, 42, 'foo', {}]; - -          // Falsy return values from decorators are simply ignored and the -          // execution falls back to default behavior which is to render the -          // other parts of the template. -          for (const value of falsy) { -            it(`falsy value (type ${typeof value}): ${JSON.stringify(value)}`, () => { -              expectTemplate(template) -                .withDecorator('decorator', () => value) -                .toCompileTo(result); -            }); -          } - -          // Truthy return values from decorators are expected to be functions -          // and the program will attempt to call them. We expect an error to -          // be thrown in this case. -          for (const value of truthy) { -            it(`non-falsy value (type ${typeof value}): ${JSON.stringify(value)}`, () => { -              expectTemplate(template) -                .withDecorator('decorator', () => value) -                .toThrow('is not a function'); -            }); -          } - -          // If the decorator return value is a custom function, its return -          // value will be the final content of the template. -          for (const value of [...falsy, ...truthy]) { -            it(`function returning ${typeof value}: ${JSON.stringify(value)}`, () => { -              expectTemplate(template) -                .withDecorator('decorator', () => () => value) -                .toCompileTo(value as string); -            }); -          } -        }); -      } -    }); - -    describe('custom return function should be called with expected arguments and its return value should be rendered in the template', () => { -      it('root decorator', () => { -        expectTemplate('{{*decorator}}world') -          .withInput({ me: 'my' }) -          .withDecorator( -            'decorator', -            (fn): TemplateDelegate => -              (context, options) => { -                expect(context).toMatchInlineSnapshot(` -              Object { -                "me": "my", -              } -            `); -                expect(options).toMatchInlineSnapshot(` -              Object { -                "decorators": Object { -                  "decorator": [Function], -                }, -                "helpers": Object {}, -                "partials": Object {}, -              } -            `); -                return `hello ${context.me} ${fn()}!`; -              } -          ) -          .toCompileTo('hello my world!'); -      }); - -      it('decorator nested inside of array-helper', () => { -        expectTemplate('{{#arr}}{{*decorator}}world{{/arr}}') -          .withInput({ arr: ['my'] }) -          .withDecorator( -            'decorator', -            (fn): TemplateDelegate => -              (context, options) => { -                expect(context).toMatchInlineSnapshot(`"my"`); -                expect(options).toMatchInlineSnapshot(` -              Object { -                "blockParams": Array [ -                  "my", -                  0, -                ], -                "data": Object { -                  "_parent": Object { -                    "root": Object { -                      "arr": Array [ -                        "my", -                      ], -                    }, -                  }, -                  "first": true, -                  "index": 0, -                  "key": 0, -                  "last": true, -                  "root": Object { -                    "arr": Array [ -                      "my", -                    ], -                  }, -                }, -              } -            `); -                return `hello ${context} ${fn()}!`; -              } -          ) -          .toCompileTo('hello my world!'); -      }); - -      it('decorator nested inside of custom helper', () => { -        expectTemplate('{{#helper}}{{*decorator}}world{{/helper}}') -          .withHelper('helper', function (options: HelperOptions) { -            return options.fn('my', { foo: 'bar' } as any); -          }) -          .withDecorator( -            'decorator', -            (fn): TemplateDelegate => -              (context, options) => { -                expect(context).toMatchInlineSnapshot(`"my"`); -                expect(options).toMatchInlineSnapshot(` -              Object { -                "foo": "bar", -              } -            `); -                return `hello ${context} ${fn()}!`; -              } -          ) -          .toCompileTo('hello my world!'); -      }); -    }); - -    it('should call multiple decorators in the same program body in the expected order and get the expected output', () => { -      let decoratorCall = 0; -      let progCall = 0; -      expectTemplate('{{*decorator}}con{{*decorator}}tent', { -        beforeRender() { -          // ensure the counters are reset between EVAL/AST render calls -          decoratorCall = 0; -          progCall = 0; -        }, -      }) -        .withInput({ -          decoratorCall: 0, -          progCall: 0, -        }) -        .withDecorator('decorator', (fn) => { -          const decoratorCallOrder = ++decoratorCall; -          const ret: TemplateDelegate = () => { -            const progCallOrder = ++progCall; -            return `(decorator: ${decoratorCallOrder}, prog: ${progCallOrder}, fn: "${fn()}")`; -          }; -          return ret; -        }) -        .toCompileTo('(decorator: 2, prog: 1, fn: "(decorator: 1, prog: 2, fn: "content")")'); -    }); - -    describe('registration', () => { -      beforeEach(() => { -        global.kbnHandlebarsEnv = Handlebars.create(); -      }); - -      afterEach(() => { -        global.kbnHandlebarsEnv = null; -      }); - -      it('should be able to call decorators registered using the `registerDecorator` function', () => { -        let calls = 0; -        const callsExpected = process.env.AST || process.env.EVAL ? 1 : 2; - -        kbnHandlebarsEnv!.registerDecorator('decorator', () => { -          calls++; -        }); - -        expectTemplate('{{*decorator}}').toCompileTo(''); -        expect(calls).toEqual(callsExpected); -      }); - -      it('should not be able to call decorators unregistered using the `unregisterDecorator` function', () => { -        let calls = 0; - -        kbnHandlebarsEnv!.registerDecorator('decorator', () => { -          calls++; -        }); - -        kbnHandlebarsEnv!.unregisterDecorator('decorator'); - -        expectTemplate('{{*decorator}}').toThrow('lookupProperty(...) is not a function'); -        expect(calls).toEqual(0); -      }); -    }); -  }); -}); |