basic.spec.ts
1 import { 2 processObject, 3 processString, 4 isValid, 5 makePropSafe, 6 getManifest, 7 encodeJSBinding, 8 doesContainString, 9 disableEscaping, 10 findHBSBlocks, 11 } from "../src/index" 12 13 describe("Test that the string processing works correctly", () => { 14 it("should process a basic template string", async () => { 15 const output = await processString("templating is {{ adjective }}", { 16 adjective: "easy", 17 }) 18 expect(output).toBe("templating is easy") 19 }) 20 21 it("should process a literal template", async () => { 22 const output = await processString("derp is {{{ adjective }}}", { 23 adjective: "derp", 24 }) 25 expect(output).toBe("derp is derp") 26 }) 27 28 it("should fail gracefully when wrong type passed in", async () => { 29 let error = null 30 try { 31 await processString(null as any, null as any) 32 } catch (err) { 33 error = err 34 } 35 expect(error).not.toBeNull() 36 }) 37 38 it("confirm that null properties are handled correctly", async () => { 39 const output = await processString("hello {{ name }} I am {{ name2 }}", { 40 name: undefined, 41 name2: null, 42 }) 43 expect(output).toBe("hello I am ") 44 }) 45 }) 46 47 describe("Test that the object processing works correctly", () => { 48 it("should be able to process an object with some template strings", async () => { 49 const output = await processObject( 50 { 51 first: "thing is {{ adjective }}", 52 second: "thing is bad", 53 third: "we are {{ adjective }} {{ noun }}", 54 }, 55 { 56 adjective: "easy", 57 noun: "people", 58 } 59 ) 60 expect(output.first).toBe("thing is easy") 61 expect(output.second).toBe("thing is bad") 62 expect(output.third).toBe("we are easy people") 63 }) 64 65 it("should be able to handle arrays of string templates", async () => { 66 const output = await processObject( 67 ["first {{ noun }}", "second {{ noun }}"], 68 { 69 noun: "person", 70 } 71 ) 72 expect(output[0]).toBe("first person") 73 expect(output[1]).toBe("second person") 74 }) 75 76 it("should fail gracefully when object passed in has cycles", async () => { 77 let error = null 78 try { 79 const innerObj: any = { a: "thing {{ a }}" } 80 innerObj.b = innerObj 81 await processObject(innerObj, { a: 1 }) 82 } catch (err) { 83 error = err 84 } 85 expect(error).not.toBeNull() 86 }) 87 88 it("check objects get converted to string JSON automatically", async () => { 89 const row = { a: 1 } 90 const output = await processString("{{ trigger.row }}", { 91 trigger: { 92 row, 93 }, 94 }) 95 expect(JSON.parse(output)).toEqual(row) 96 }) 97 98 it("should be able to handle null objects", async () => { 99 let error = null 100 try { 101 await processObject(null as any, null as any) 102 } catch (err) { 103 error = err 104 } 105 expect(error).toBeNull() 106 }) 107 108 it("should be able to handle booleans", async () => { 109 const output = await processObject( 110 { 111 first: true, 112 second: "true", 113 third: "another string", 114 forth: "with {{ template }}", 115 }, 116 { 117 template: "value", 118 } 119 ) 120 expect(output).toEqual({ 121 first: true, 122 second: "true", 123 third: "another string", 124 forth: "with value", 125 }) 126 }) 127 }) 128 129 describe("check arrays", () => { 130 describe("index with square brackets", () => { 131 it.each([ 132 [0, "1"], 133 [1, "2"], 134 ])("should handle an array of primitive types", async (index, expected) => { 135 const json = [1, 2, 3] 136 const output = await processString(`{{ testing.[${index}] }}`, { 137 testing: json, 138 }) 139 expect(output).toEqual(expected) 140 }) 141 142 it("should handle an array of objects", async () => { 143 const json = [{ value: 1 }, { value: 2 }, { value: 3 }] 144 const output = await processString("{{ testing.[1] }}", { 145 testing: json, 146 }) 147 expect(output).toEqual('{"value":2}') 148 }) 149 150 it("should handle nesting properties in an array of objects", async () => { 151 const json = [{ value: 1 }, { value: 2 }, { value: 3 }] 152 const output = await processString("{{ testing.[1].value }}", { 153 testing: json, 154 }) 155 expect(output).toEqual("2") 156 }) 157 }) 158 159 describe("index without square brackets", () => { 160 it("should not handle an array of primitive types", async () => { 161 const json = [1, 2, 3] 162 const output = await processString(`{{ testing.1 }}`, { 163 testing: json, 164 }) 165 expect(output).toEqual("{{ testing.1 }}") 166 }) 167 168 it("should not handle an array of objects", async () => { 169 const json = [{ value: 1 }, { value: 2 }, { value: 3 }] 170 const output = await processString("{{ testing.1 }}", { 171 testing: json, 172 }) 173 expect(output).toEqual("{{ testing.1 }}") 174 }) 175 176 it("should handle nesting properties in an array of object types", async () => { 177 const json = [{ value: 1 }, { value: 2 }, { value: 3 }] 178 const output = await processString("{{ testing.1.value }}", { 179 testing: json, 180 }) 181 expect(output).toEqual("2") 182 }) 183 }) 184 }) 185 186 describe("check returning objects", () => { 187 it("should handle an array of objects", async () => { 188 const json = [{ a: 1 }, { a: 2 }] 189 const output = await processString("{{ testing }}", { 190 testing: json, 191 }) 192 expect(output).toEqual(JSON.stringify(json)) 193 }) 194 }) 195 196 describe("check the utility functions", () => { 197 it("should return false for an invalid template string", () => { 198 const valid = isValid("{{ table1.thing prop }}") 199 expect(valid).toBe(false) 200 }) 201 202 it("should state this template is valid", () => { 203 const valid = isValid("{{ thing }}") 204 expect(valid).toBe(true) 205 }) 206 207 it("should make a property safe", () => { 208 const property = makePropSafe("thing") 209 expect(property).toEqual("[thing]") 210 }) 211 212 it("should be able to handle an input date object", async () => { 213 const date = new Date() 214 const output = await processString("{{ dateObj }}", { dateObj: date }) 215 expect(date.toString()).toEqual(output) 216 }) 217 }) 218 219 describe("check falsy values", () => { 220 it("should get a zero out when context contains it", async () => { 221 const output = await processString("{{ number }}", { number: 0 }) 222 expect(output).toEqual("0") 223 }) 224 225 it("should get false out when context contains it", async () => { 226 const output = await processString("{{ bool }}", { bool: false }) 227 expect(output).toEqual("false") 228 }) 229 }) 230 231 describe("check manifest", () => { 232 it("should be able to retrieve the manifest", () => { 233 const manifest = getManifest() 234 expect(manifest.math).not.toBeNull() 235 expect(manifest.math.abs.description).toBe( 236 "<p>Return the magnitude of <code>a</code>.</p>\n" 237 ) 238 }) 239 }) 240 241 describe("check full stops that are safe", () => { 242 it("should allow using an escaped full stop", async () => { 243 const data = { 244 "c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI": { 245 "persons.firstname": "1", 246 }, 247 } 248 const template = 249 "{{ [c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI].[persons.firstname] }}" 250 const output = await processString(template, data) 251 expect(output).toEqual("1") 252 }) 253 }) 254 255 describe("check does contain string function", () => { 256 it("should work for a simple case", () => { 257 const hbs = "hello {{ name }}" 258 expect(doesContainString(hbs, "name")).toEqual(true) 259 }) 260 261 it("should reject a case where its in the string, but not the handlebars", () => { 262 const hbs = "hello {{ name }}" 263 expect(doesContainString(hbs, "hello")).toEqual(false) 264 }) 265 266 it("should handle if its in javascript", () => { 267 const js = encodeJSBinding(`return $("foo")`) 268 expect(doesContainString(js, "foo")).toEqual(true) 269 }) 270 }) 271 272 describe("check that disabling escaping function works", () => { 273 it("should work for a single statement", () => { 274 expect(disableEscaping("{{ name }}")).toEqual("{{{ name }}}") 275 }) 276 277 it("should work for two statements", () => { 278 expect(disableEscaping("{{ name }} welcome to {{ platform }}")).toEqual( 279 "{{{ name }}} welcome to {{{ platform }}}" 280 ) 281 }) 282 283 it("shouldn't convert triple braces", () => { 284 expect(disableEscaping("{{{ name }}}")).toEqual("{{{ name }}}") 285 }) 286 287 it("should work with a combination", () => { 288 expect(disableEscaping("{{ name }} welcome to {{{ platform }}}")).toEqual( 289 "{{{ name }}} welcome to {{{ platform }}}" 290 ) 291 }) 292 293 it("should work with multiple escaped", () => { 294 expect(disableEscaping("{{ name }} welcome to {{ name }}")).toEqual( 295 "{{{ name }}} welcome to {{{ name }}}" 296 ) 297 }) 298 }) 299 300 describe("check find hbs blocks function", () => { 301 it("should find none", () => { 302 expect(findHBSBlocks("hello there")).toEqual([]) 303 }) 304 305 it("should find two", () => { 306 expect(findHBSBlocks("{{ hello }} there {{{ name }}}")).toEqual([ 307 "{{ hello }}", 308 "{{{ name }}}", 309 ]) 310 }) 311 }) 312 313 describe("should leave HBS blocks if not found using option", () => { 314 it("should replace one, leave one", async () => { 315 const output = await processString( 316 "{{ a }}, {{ b }}", 317 { b: 1 }, 318 { onlyFound: true } 319 ) 320 expect(output).toBe("{{ a }}, 1") 321 }) 322 }) 323 324 describe("check multiple space behaviour", () => { 325 it("should remove whitespace and use the helper correctly", async () => { 326 const output = await processString("{{ add num1 num2 }}", { 327 num1: 1, 328 num2: 2, 329 }) 330 expect(output).toEqual("3") 331 }) 332 333 it("should ensure that whitespace within a string is respected", async () => { 334 const output = await processString("{{ trimRight 'test string ' }}", { 335 num1: 1, 336 num2: 2, 337 }) 338 expect(output).toEqual("test string") 339 }) 340 })