import { processObject, processString, isValid, makePropSafe, getManifest, encodeJSBinding, doesContainString, disableEscaping, findHBSBlocks, } from "../src/index" describe("Test that the string processing works correctly", () => { it("should process a basic template string", async () => { const output = await processString("templating is {{ adjective }}", { adjective: "easy", }) expect(output).toBe("templating is easy") }) it("should process a literal template", async () => { const output = await processString("derp is {{{ adjective }}}", { adjective: "derp", }) expect(output).toBe("derp is derp") }) it("should fail gracefully when wrong type passed in", async () => { let error = null try { await processString(null as any, null as any) } catch (err) { error = err } expect(error).not.toBeNull() }) it("confirm that null properties are handled correctly", async () => { const output = await processString("hello {{ name }} I am {{ name2 }}", { name: undefined, name2: null, }) expect(output).toBe("hello I am ") }) }) describe("Test that the object processing works correctly", () => { it("should be able to process an object with some template strings", async () => { const output = await processObject( { first: "thing is {{ adjective }}", second: "thing is bad", third: "we are {{ adjective }} {{ noun }}", }, { adjective: "easy", noun: "people", } ) expect(output.first).toBe("thing is easy") expect(output.second).toBe("thing is bad") expect(output.third).toBe("we are easy people") }) it("should be able to handle arrays of string templates", async () => { const output = await processObject( ["first {{ noun }}", "second {{ noun }}"], { noun: "person", } ) expect(output[0]).toBe("first person") expect(output[1]).toBe("second person") }) it("should fail gracefully when object passed in has cycles", async () => { let error = null try { const innerObj: any = { a: "thing {{ a }}" } innerObj.b = innerObj await processObject(innerObj, { a: 1 }) } catch (err) { error = err } expect(error).not.toBeNull() }) it("check objects get converted to string JSON automatically", async () => { const row = { a: 1 } const output = await processString("{{ trigger.row }}", { trigger: { row, }, }) expect(JSON.parse(output)).toEqual(row) }) it("should be able to handle null objects", async () => { let error = null try { await processObject(null as any, null as any) } catch (err) { error = err } expect(error).toBeNull() }) it("should be able to handle booleans", async () => { const output = await processObject( { first: true, second: "true", third: "another string", forth: "with {{ template }}", }, { template: "value", } ) expect(output).toEqual({ first: true, second: "true", third: "another string", forth: "with value", }) }) }) describe("check arrays", () => { describe("index with square brackets", () => { it.each([ [0, "1"], [1, "2"], ])("should handle an array of primitive types", async (index, expected) => { const json = [1, 2, 3] const output = await processString(`{{ testing.[${index}] }}`, { testing: json, }) expect(output).toEqual(expected) }) it("should handle an array of objects", async () => { const json = [{ value: 1 }, { value: 2 }, { value: 3 }] const output = await processString("{{ testing.[1] }}", { testing: json, }) expect(output).toEqual('{"value":2}') }) it("should handle nesting properties in an array of objects", async () => { const json = [{ value: 1 }, { value: 2 }, { value: 3 }] const output = await processString("{{ testing.[1].value }}", { testing: json, }) expect(output).toEqual("2") }) }) describe("index without square brackets", () => { it("should not handle an array of primitive types", async () => { const json = [1, 2, 3] const output = await processString(`{{ testing.1 }}`, { testing: json, }) expect(output).toEqual("{{ testing.1 }}") }) it("should not handle an array of objects", async () => { const json = [{ value: 1 }, { value: 2 }, { value: 3 }] const output = await processString("{{ testing.1 }}", { testing: json, }) expect(output).toEqual("{{ testing.1 }}") }) it("should handle nesting properties in an array of object types", async () => { const json = [{ value: 1 }, { value: 2 }, { value: 3 }] const output = await processString("{{ testing.1.value }}", { testing: json, }) expect(output).toEqual("2") }) }) }) describe("check returning objects", () => { it("should handle an array of objects", async () => { const json = [{ a: 1 }, { a: 2 }] const output = await processString("{{ testing }}", { testing: json, }) expect(output).toEqual(JSON.stringify(json)) }) }) describe("check the utility functions", () => { it("should return false for an invalid template string", () => { const valid = isValid("{{ table1.thing prop }}") expect(valid).toBe(false) }) it("should state this template is valid", () => { const valid = isValid("{{ thing }}") expect(valid).toBe(true) }) it("should make a property safe", () => { const property = makePropSafe("thing") expect(property).toEqual("[thing]") }) it("should be able to handle an input date object", async () => { const date = new Date() const output = await processString("{{ dateObj }}", { dateObj: date }) expect(date.toString()).toEqual(output) }) }) describe("check falsy values", () => { it("should get a zero out when context contains it", async () => { const output = await processString("{{ number }}", { number: 0 }) expect(output).toEqual("0") }) it("should get false out when context contains it", async () => { const output = await processString("{{ bool }}", { bool: false }) expect(output).toEqual("false") }) }) describe("check manifest", () => { it("should be able to retrieve the manifest", () => { const manifest = getManifest() expect(manifest.math).not.toBeNull() expect(manifest.math.abs.description).toBe( "

Return the magnitude of a.

\n" ) }) }) describe("check full stops that are safe", () => { it("should allow using an escaped full stop", async () => { const data = { "c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI": { "persons.firstname": "1", }, } const template = "{{ [c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI].[persons.firstname] }}" const output = await processString(template, data) expect(output).toEqual("1") }) }) describe("check does contain string function", () => { it("should work for a simple case", () => { const hbs = "hello {{ name }}" expect(doesContainString(hbs, "name")).toEqual(true) }) it("should reject a case where its in the string, but not the handlebars", () => { const hbs = "hello {{ name }}" expect(doesContainString(hbs, "hello")).toEqual(false) }) it("should handle if its in javascript", () => { const js = encodeJSBinding(`return $("foo")`) expect(doesContainString(js, "foo")).toEqual(true) }) }) describe("check that disabling escaping function works", () => { it("should work for a single statement", () => { expect(disableEscaping("{{ name }}")).toEqual("{{{ name }}}") }) it("should work for two statements", () => { expect(disableEscaping("{{ name }} welcome to {{ platform }}")).toEqual( "{{{ name }}} welcome to {{{ platform }}}" ) }) it("shouldn't convert triple braces", () => { expect(disableEscaping("{{{ name }}}")).toEqual("{{{ name }}}") }) it("should work with a combination", () => { expect(disableEscaping("{{ name }} welcome to {{{ platform }}}")).toEqual( "{{{ name }}} welcome to {{{ platform }}}" ) }) it("should work with multiple escaped", () => { expect(disableEscaping("{{ name }} welcome to {{ name }}")).toEqual( "{{{ name }}} welcome to {{{ name }}}" ) }) }) describe("check find hbs blocks function", () => { it("should find none", () => { expect(findHBSBlocks("hello there")).toEqual([]) }) it("should find two", () => { expect(findHBSBlocks("{{ hello }} there {{{ name }}}")).toEqual([ "{{ hello }}", "{{{ name }}}", ]) }) }) describe("should leave HBS blocks if not found using option", () => { it("should replace one, leave one", async () => { const output = await processString( "{{ a }}, {{ b }}", { b: 1 }, { onlyFound: true } ) expect(output).toBe("{{ a }}, 1") }) })