lang-json 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. package/README.md +0 -0
  2. package/babel.config.js +8 -0
  3. package/coverage/clover.xml +6 -0
  4. package/coverage/coverage-final.json +1 -0
  5. package/coverage/lcov-report/base.css +224 -0
  6. package/coverage/lcov-report/block-navigation.js +87 -0
  7. package/coverage/lcov-report/favicon.png +0 -0
  8. package/coverage/lcov-report/index.html +101 -0
  9. package/coverage/lcov-report/prettify.css +1 -0
  10. package/coverage/lcov-report/prettify.js +2 -0
  11. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  12. package/coverage/lcov-report/sorter.js +196 -0
  13. package/dist/esm/src/index.d.ts +18 -0
  14. package/dist/esm/src/index.js +369 -0
  15. package/dist/esm/src/index.js.map +1 -0
  16. package/dist/esm/src/modules/is-this/index.d.ts +136 -0
  17. package/dist/esm/src/modules/is-this/index.js +484 -0
  18. package/dist/esm/src/modules/is-this/index.js.map +1 -0
  19. package/dist/esm/tests/helpers.test.d.ts +1 -0
  20. package/dist/esm/tests/helpers.test.js +284 -0
  21. package/dist/esm/tests/helpers.test.js.map +1 -0
  22. package/dist/esm/tests/index.test.d.ts +1 -0
  23. package/dist/esm/tests/index.test.js +537 -0
  24. package/dist/esm/tests/index.test.js.map +1 -0
  25. package/dist/esm/tests/readme.test.d.ts +1 -0
  26. package/dist/esm/tests/readme.test.js +73 -0
  27. package/dist/esm/tests/readme.test.js.map +1 -0
  28. package/jest.config.ts +212 -0
  29. package/package.json +40 -12
  30. package/src/index.ts +404 -295
  31. package/src/modules/is-this/index.ts +682 -0
  32. package/tests/helpers.test.ts +331 -0
  33. package/tests/index.test.ts +681 -0
  34. package/tests/readme.test.ts +78 -0
  35. package/tsconfig.json +15 -16
  36. package/dist/esm/dump.js +0 -2
  37. package/dist/esm/dump.js.map +0 -1
  38. package/dist/esm/example.d.ts +0 -13
  39. package/dist/esm/example.js +0 -93
  40. package/dist/esm/example.js.map +0 -1
  41. package/dist/esm/index.d.ts +0 -36
  42. package/dist/esm/index.js +0 -326
  43. package/dist/esm/index.js.map +0 -1
  44. package/src/example.ts +0 -116
  45. /package/{dist/esm/dump.d.ts → coverage/lcov.info} +0 -0
@@ -0,0 +1,681 @@
1
+ import LangJSON from "../src/index";
2
+
3
+ const langJson = new LangJSON();
4
+
5
+ describe("LangJSON Test Suite", () => {
6
+ /**
7
+ * -------------------------
8
+ * Test: lookup method
9
+ * -------------------------
10
+ */
11
+ test("Basic lookup", () => {
12
+ expect(langJson.lookup("key", { key: "value" })).toBe("value");
13
+ });
14
+
15
+ test("Nested lookup", () => {
16
+ const data = { nested: { key: "value" } };
17
+ expect(langJson.lookup("nested.key", data)).toBe("value");
18
+ });
19
+
20
+ test("Non-existent key in lookup", () => {
21
+ expect(langJson.lookup("missingKey", { key: "value" })).toBe(undefined);
22
+ });
23
+
24
+ test("Lookup with array index access", () => {
25
+ const data = { items: ["first", "second", "third"] };
26
+ expect(langJson.lookup("items[1]", data)).toBe("second");
27
+ });
28
+
29
+ test("Lookup for deeply nested paths", () => {
30
+ const data = { a: { b: { c: { d: "deepValue" } } } };
31
+ expect(langJson.lookup("a.b.c.d", data)).toBe("deepValue");
32
+ });
33
+
34
+ test("Lookup with array and non-existent index", () => {
35
+ const data = { items: ["first", "second", "third"] };
36
+ expect(langJson.lookup("items[10]", data)).toBe(undefined);
37
+ });
38
+
39
+ test("Lookup with non-string keys", () => {
40
+ const data = { 1: "one", 2: "two" };
41
+ expect(langJson.lookup("1", data)).toBe("one");
42
+ });
43
+
44
+ test("Lookup with undefined or null values", () => {
45
+ const data = { key: null, anotherKey: undefined };
46
+ expect(langJson.lookup("key", data)).toBe(null);
47
+ expect(langJson.lookup("anotherKey", data)).toBe(undefined);
48
+ });
49
+
50
+ test("Lookup with nested key and array mix", () => {
51
+ const data = { items: [{ name: "first" }, { name: "second" }] };
52
+ expect(langJson.lookup("items[1].name", data)).toBe("second");
53
+ });
54
+
55
+ test("Lookup with complex keys containing spaces", () => {
56
+ const data = { "key with spaces": { "another key": "value" } };
57
+ expect(langJson.lookup("key with spaces.another key", data)).toBe("value");
58
+ });
59
+
60
+ test("Lookup with deeply nested array of objects", () => {
61
+ const data = {
62
+ level1: [{ level2: [{ level3: { key: "deepValue" } }] }],
63
+ };
64
+ expect(langJson.lookup("level1[0].level2[0].level3.key", data)).toBe(
65
+ "deepValue"
66
+ );
67
+ });
68
+
69
+ test("Lookup with special characters and symbols in the key", () => {
70
+ const data = { "key@#": "specialValue" };
71
+ expect(langJson.lookup("key@#", data)).toBe("specialValue");
72
+ });
73
+
74
+ test("Lookup with circular reference in data", () => {
75
+ const data: any = {};
76
+ data.self = data; // Circular reference
77
+ expect(langJson.lookup("self.self.self", data)).toBe(data);
78
+ });
79
+
80
+ test("Lookup with an empty string as key", () => {
81
+ const data = { "": "emptyKey" };
82
+ expect(langJson.lookup("", data)).toBe("emptyKey");
83
+ });
84
+
85
+ test("Lookup with mixed object and array access in key", () => {
86
+ const data = {
87
+ list: [{ nested: { key: "arrayObjectValue" } }],
88
+ };
89
+ expect(langJson.lookup("list[0].nested.key", data)).toBe(
90
+ "arrayObjectValue"
91
+ );
92
+ });
93
+
94
+ /**
95
+ * -------------------------
96
+ * Test: processHelper method
97
+ * -------------------------
98
+ */
99
+ test("processHelper with zero arguments", () => {
100
+ langJson.registerHelper("returnHello", () => "Hello");
101
+ expect(langJson.processHelper("{{#returnHello}}", { key: "value" })).toBe(
102
+ "Hello"
103
+ );
104
+ });
105
+
106
+ test("processHelper with valid var key", () => {
107
+ expect(langJson.processHelper("{{#var key}}", { key: "value" })).toBe(
108
+ "value"
109
+ );
110
+ });
111
+
112
+ test("processHelper with missing key in data", () => {
113
+ expect(
114
+ langJson.processHelper("{{#var missingKey}}", { key: "value" })
115
+ ).toBe(undefined);
116
+ });
117
+
118
+ test("processHelper with missing helper", () => {
119
+ expect(() => {
120
+ langJson.processHelper("{{#unknown key}}", { key: "value" });
121
+ }).toThrow("Missing helper : unknown"); // Or you can specify the error message with toThrow("error message")
122
+ });
123
+
124
+ test("processHelper with nested helper call", () => {
125
+ expect(
126
+ langJson.processHelper("{{#var (var key)}}", {
127
+ key: "nestedKey",
128
+ nestedKey: "result",
129
+ })
130
+ ).toBe("result");
131
+ });
132
+
133
+ test("processHelper with escaped variable", () => {
134
+ expect(
135
+ langJson.processHelper("This is {{#var key}}!", { key: "value" })
136
+ ).toBe("This is value!");
137
+ });
138
+
139
+ test("processHelper with escaping inside helper", () => {
140
+ expect(
141
+ langJson.processHelper("{{#var key}} is {{#var anotherKey}}", {
142
+ key: "value",
143
+ anotherKey: "escapedValue",
144
+ })
145
+ ).toBe("value is escapedValue");
146
+ });
147
+
148
+ test("processHelper with boolean handling", () => {
149
+ const data = { isTrue: true, isFalse: false };
150
+ expect(langJson.processHelper("{{#var isTrue}}", data)).toBe(true);
151
+ expect(langJson.processHelper("{{#var isFalse}}", data)).toBe(false);
152
+ });
153
+
154
+ test("processHelper with multiple variables in one template", () => {
155
+ const template = "Hello, {{#var firstName}} {{#var lastName}}!";
156
+ const data = { firstName: "John", lastName: "Doe" };
157
+ expect(langJson.processHelper(template, data)).toBe("Hello, John Doe!");
158
+ });
159
+
160
+ test("processHelper with nested variable in object", () => {
161
+ const template = "{{#var user.details.name}}";
162
+ const data = { user: { details: { name: "Jane" } } };
163
+ expect(langJson.processHelper(template, data)).toBe("Jane");
164
+ });
165
+
166
+ test("processHelper with array passed as argument", () => {
167
+ langJson.registerHelper("join", ([arr]) => arr.join(", "));
168
+ expect(
169
+ langJson.processHelper("{{#join items}}", {
170
+ items: ["apple", "banana", "cherry"],
171
+ })
172
+ ).toBe("apple, banana, cherry");
173
+ });
174
+
175
+ // test("processHelper with complex nesting of helpers", () => {
176
+ // langJson.registerHelper("outer", ([arg]) => `outer(${arg})`);
177
+ // langJson.registerHelper("inner", ([arg]) => `inner(${arg})`);
178
+ // expect(
179
+ // langJson.processHelper("{{#outer (inner key)}}", { key: "value" })
180
+ // ).toBe("outer(inner(value))");
181
+ // });
182
+
183
+ test("processHelper with variable inside a helper argument", () => {
184
+ langJson.registerHelper("wrap", (arg) => `[${arg}]`);
185
+ expect(
186
+ langJson.processHelper("{{#wrap (var key)}}", { key: "content" })
187
+ ).toBe("[content]");
188
+ });
189
+
190
+ // test("processHelper with escaped special characters", () => {
191
+ // expect(
192
+ // langJson.processHelper("Use \\{{#var key}} to access value", {
193
+ // key: "data",
194
+ // })
195
+ // ).toBe("Use {{#var key}} to access value");
196
+ // });
197
+
198
+ test("processHelper with an empty helper name", () => {
199
+ expect(langJson.processHelper("{{# key}}", { key: "value" })).toBe(
200
+ "{{# key}}"
201
+ );
202
+ });
203
+
204
+ test("processHelper with incorrect data types for variables", () => {
205
+ expect(langJson.processHelper("{{#var key}}", { key: 123 })).toBe(123);
206
+ expect(langJson.processHelper("{{#var key}}", { key: true })).toBe(true);
207
+ expect(langJson.processHelper("{{#var key}}", { key: null })).toBe(null);
208
+ });
209
+
210
+ test("processHelper with non-terminating helper expressions", () => {
211
+ expect(langJson.processHelper("{{#var key", { key: "value" })).toBe(
212
+ "{{#var key"
213
+ );
214
+ });
215
+
216
+ test("processHelper with special characters in variable names", () => {
217
+ const data = {
218
+ "key-with-dash": "valueWithDash",
219
+ "key@symbol": "valueWithSymbol",
220
+ };
221
+ expect(langJson.processHelper("{{#var key-with-dash}}", data)).toBe(
222
+ "valueWithDash"
223
+ );
224
+ expect(langJson.processHelper("{{#var key@symbol}}", data)).toBe(
225
+ "valueWithSymbol"
226
+ );
227
+ });
228
+
229
+ test("processHelper with helper functions throwing errors", () => {
230
+ langJson.registerHelper("errorHelper", () => {
231
+ throw new Error("Helper error");
232
+ });
233
+ expect(() => langJson.processHelper("{{#errorHelper}}", {})).toThrow(
234
+ "Helper error"
235
+ );
236
+ });
237
+ /**
238
+ * -------------------------
239
+ * Test: applyTemplate method
240
+ * -------------------------
241
+ */
242
+ test("applyTemplate with object template", () => {
243
+ const template = { "{{#var firstName}}": "{{#var lastName}}" };
244
+ const data = { firstName: "John", lastName: "Doe" };
245
+ expect(langJson.applyTemplate(template, data)).toEqual({ John: "Doe" });
246
+ });
247
+
248
+ test("applyTemplate with array of strings", () => {
249
+ const template = ["{{#var key}}", "{{#var value}}"];
250
+ const data = { key: "first", value: "second" };
251
+ expect(langJson.applyTemplate(template, data)).toEqual(["first", "second"]);
252
+ });
253
+
254
+ test("applyTemplate with nested objects", () => {
255
+ const template = {
256
+ "{{#var user.name}}": { age: "{{#var user.age}}" },
257
+ };
258
+ const data = { user: { name: "Alice", age: 30 } };
259
+ expect(langJson.applyTemplate(template, data)).toEqual({
260
+ Alice: { age: 30 },
261
+ });
262
+ });
263
+
264
+ test("applyTemplate with array of objects", () => {
265
+ const template = [
266
+ { "{{#var firstName}}": "{{#var lastName}}" },
267
+ { "{{#var firstName}}": "{{#var age}}" },
268
+ ];
269
+ const data = { firstName: "John", lastName: "Doe", age: 30 };
270
+ expect(langJson.applyTemplate(template, data)).toEqual([
271
+ { John: "Doe" },
272
+ { John: 30 },
273
+ ]);
274
+ });
275
+
276
+ test("applyTemplate with boolean values", () => {
277
+ const template = { "{{#var isActive}}": "Active" };
278
+ const data = { isActive: true };
279
+ expect(langJson.applyTemplate(template, data)).toEqual({ true: "Active" });
280
+ });
281
+
282
+ test("applyTemplate with deeply nested object structures", () => {
283
+ const template = {
284
+ "{{#var user.name}}": {
285
+ "{{#var user.details.age}}": "{{#var user.details.address}}",
286
+ },
287
+ };
288
+ const data = {
289
+ user: { name: "John", details: { age: 30, address: "NY" } },
290
+ };
291
+ expect(langJson.applyTemplate(template, data)).toEqual({
292
+ John: { 30: "NY" },
293
+ });
294
+ });
295
+
296
+ test("applyTemplate with mixed arrays and objects", () => {
297
+ const template = [
298
+ { "{{#var firstName}}": "{{#var lastName}}" },
299
+ "{{#var age}}",
300
+ ["{{#var city}}", "{{#var country}}"],
301
+ ];
302
+ const data = {
303
+ firstName: "John",
304
+ lastName: "Doe",
305
+ age: 30,
306
+ city: "New York",
307
+ country: "USA",
308
+ };
309
+ expect(langJson.applyTemplate(template, data)).toEqual([
310
+ { John: "Doe" },
311
+ 30,
312
+ ["New York", "USA"],
313
+ ]);
314
+ });
315
+
316
+ test("applyTemplate with missing keys in template", () => {
317
+ const template = { "{{#var firstName}}": "{{#var lastName}}" };
318
+ const data = { firstName: "John" }; // missing lastName
319
+ expect(langJson.applyTemplate(template, data)).toEqual({
320
+ John: undefined,
321
+ });
322
+ });
323
+
324
+ test("applyTemplate with escaping in template", () => {
325
+ const template = { escapedVar: "{{#var key}}" };
326
+ const data = { key: "value" };
327
+ expect(langJson.applyTemplate(template, data)).toEqual({
328
+ escapedVar: "value",
329
+ });
330
+ });
331
+
332
+ test("applyTemplate with undefined data values", () => {
333
+ const template = { "{{#var key}}": "value" };
334
+ const data = { key: undefined };
335
+ expect(langJson.applyTemplate(template, data)).toEqual({
336
+ undefined: "value",
337
+ });
338
+ });
339
+
340
+ test("applyTemplate with conditional logic in templates", () => {
341
+ langJson.registerHelper("ifEquals", ([a, b]) => (a === b ? "Yes" : "No"));
342
+ const template = { "{{#ifEquals user.role 'admin'}}": "Is Admin" };
343
+ expect(
344
+ langJson.applyTemplate(template, { user: { role: "admin" } })
345
+ ).toEqual({
346
+ Yes: "Is Admin",
347
+ });
348
+ expect(
349
+ langJson.applyTemplate(template, { user: { role: "user" } })
350
+ ).toEqual({
351
+ No: "Is Admin",
352
+ });
353
+ });
354
+
355
+ test("applyTemplate with circular references in data", () => {
356
+ const data: any = { key: "value" };
357
+ data.self = data; // Create circular reference
358
+ const template = { "{{#var key}}": "{{#var self.key}}" };
359
+ expect(langJson.applyTemplate(template, data)).toEqual({ value: "value" });
360
+ });
361
+
362
+ test("applyTemplate with keys that are numbers", () => {
363
+ const template = { "{{#var 1}}": "{{#var 2}}" };
364
+ const data = { 1: "one", 2: "two" };
365
+ expect(langJson.applyTemplate(template, data)).toEqual({ one: "two" });
366
+ });
367
+
368
+ test("applyTemplate with deeply nested structures and template resolution", () => {
369
+ const template = {
370
+ "{{#var user.name}}": {
371
+ "{{#var user.job.title}}": {
372
+ "{{#var user.job.department}}": "{{#var user.job.level}}",
373
+ },
374
+ },
375
+ };
376
+ const data = {
377
+ user: {
378
+ name: "John",
379
+ job: {
380
+ title: "Manager",
381
+ department: "Sales",
382
+ level: "Senior",
383
+ },
384
+ },
385
+ };
386
+ expect(langJson.applyTemplate(template, data)).toEqual({
387
+ John: { Manager: { Sales: "Senior" } },
388
+ });
389
+ });
390
+
391
+ /**
392
+ * -------------------------
393
+ * Test: Registering custom helper functions
394
+ * -------------------------
395
+ */
396
+ test("registerHelper with custom helper", () => {
397
+ langJson.registerHelper("custom", ([arg]) => arg.toUpperCase());
398
+ expect(langJson.processHelper("{{#custom key}}", { key: "value" })).toBe(
399
+ "VALUE"
400
+ );
401
+ });
402
+
403
+ test("registerHelpers with multiple custom helpers", () => {
404
+ langJson.registerHelpers({
405
+ upper: ([arg]) => arg.toUpperCase(),
406
+ lower: ([arg]) => arg.toLowerCase(),
407
+ });
408
+ expect(langJson.processHelper("{{#upper key}}", { key: "Value" })).toBe(
409
+ "VALUE"
410
+ );
411
+ expect(langJson.processHelper("{{#lower key}}", { key: "VALUE" })).toBe(
412
+ "value"
413
+ );
414
+ });
415
+
416
+ test("registerHelper with no arguments", () => {
417
+ langJson.registerHelper("noArgs", () => "No Args!");
418
+ expect(langJson.processHelper("{{#noArgs}}", {})).toBe("No Args!");
419
+ });
420
+
421
+ test("registerHelper with multiple arguments", () => {
422
+ langJson.registerHelper("concat", ([arg1, arg2]) => arg1 + arg2);
423
+ expect(
424
+ langJson.processHelper("{{#concat first second}}", {
425
+ first: "Hello",
426
+ second: "World",
427
+ })
428
+ ).toBe("HelloWorld");
429
+ });
430
+
431
+ test("registerHelper for formatting or computation", () => {
432
+ langJson.registerHelper("add", ([a, b]) => a + b);
433
+ expect(langJson.processHelper("{{#add 5 10}}", {})).toBe(15);
434
+ });
435
+
436
+ test("registerHelper with string manipulation", () => {
437
+ langJson.registerHelper("reverse", ([arg]) =>
438
+ arg.split("").reverse().join("")
439
+ );
440
+ expect(langJson.processHelper("{{#reverse word}}", { word: "hello" })).toBe(
441
+ "olleh"
442
+ );
443
+ });
444
+ });
445
+
446
+ test("registerHelper for conditional formatting", () => {
447
+ langJson.registerHelper("isAdult", ([age]) =>
448
+ age >= 18 ? "Adult" : "Minor"
449
+ );
450
+ expect(langJson.processHelper("{{#isAdult age}}", { age: 20 })).toBe("Adult");
451
+ expect(langJson.processHelper("{{#isAdult age}}", { age: 15 })).toBe("Minor");
452
+ });
453
+
454
+ test("registerHelper with arguments having special characters", () => {
455
+ langJson.registerHelper("sanitize", ([str]) =>
456
+ str.replace(/[^a-zA-Z ]/g, "")
457
+ );
458
+ expect(
459
+ langJson.processHelper("{{#sanitize key}}", { key: "Hello@World!" })
460
+ ).toBe("HelloWorld");
461
+ });
462
+
463
+ test("registerHelper for handling empty input", () => {
464
+ langJson.registerHelper("isEmpty", ([str]) =>
465
+ str === "" ? "Empty" : "Not Empty"
466
+ );
467
+ expect(langJson.processHelper("{{#isEmpty key}}", { key: "" })).toBe("Empty");
468
+ expect(langJson.processHelper("{{#isEmpty key}}", { key: "Value" })).toBe(
469
+ "Not Empty"
470
+ );
471
+ });
472
+
473
+ test("registerHelper that throws an error", () => {
474
+ langJson.registerHelper("throwError", () => {
475
+ throw new Error("Something went wrong!");
476
+ });
477
+ expect(() => langJson.processHelper("{{#throwError}}", {})).toThrow(
478
+ "Something went wrong!"
479
+ );
480
+ });
481
+
482
+ test("registerHelper with default values for missing arguments", () => {
483
+ langJson.registerHelper("defaultArg", ([arg = "default"]) => arg);
484
+ expect(langJson.processHelper("{{#defaultArg}}", {})).toBe("default");
485
+ expect(
486
+ langJson.processHelper("{{#defaultArg key}}", { key: "provided" })
487
+ ).toBe("provided");
488
+ });
489
+
490
+ test("registerHelper with multiple arguments passed dynamically", () => {
491
+ langJson.registerHelper("concat", ([...args]) => args.join("-"));
492
+ expect(
493
+ langJson.processHelper("{{#concat key1 key2 key3}}", {
494
+ key1: "first",
495
+ key2: "second",
496
+ key3: "third",
497
+ })
498
+ ).toBe("first-second-third");
499
+ });
500
+
501
+ test("registerHelper that returns an object instead of a string", () => {
502
+ langJson.registerHelper("createUser", ([name, age]) => ({ name, age }));
503
+ expect(
504
+ langJson.processHelper("{{#createUser name age}}", {
505
+ name: "Alice",
506
+ age: 30,
507
+ })
508
+ ).toEqual({
509
+ name: "Alice",
510
+ age: 30,
511
+ });
512
+ });
513
+
514
+ // test("registerHelper with asynchronous operation (promise)", async () => {
515
+ // langJson.registerHelper("fetchData", async () => {
516
+ // return new Promise((resolve) => setTimeout(() => resolve("data"), 100));
517
+ // });
518
+ // const result = await langJson.processHelper("{{#fetchData}}", {});
519
+ // expect(result).toBe("data");
520
+ // });
521
+
522
+ test("registerHelper with fallback value if input is missing", () => {
523
+ langJson.registerHelper("default", ([value, fallback]) => value || fallback);
524
+ expect(
525
+ langJson.processHelper("{{#default key 'defaultValue'}}", { key: null })
526
+ ).toBe("defaultValue");
527
+ });
528
+
529
+ test("registerHelper with helpers that modify objects", () => {
530
+ langJson.registerHelper("addProperty", ([obj, key, value]) => {
531
+ obj[key] = value;
532
+ return obj;
533
+ });
534
+ expect(
535
+ langJson.processHelper("{{#addProperty obj key value}}", {
536
+ obj: {},
537
+ key: "newKey",
538
+ value: "newValue",
539
+ })
540
+ ).toEqual({
541
+ newKey: "newValue",
542
+ });
543
+ });
544
+
545
+ test("registerHelper that uses an internal state", () => {
546
+ let state = 0;
547
+ langJson.registerHelper("increment", () => {
548
+ state += 1;
549
+ return state;
550
+ });
551
+ expect(langJson.processHelper("{{#increment}}", {})).toBe(1);
552
+ expect(langJson.processHelper("{{#increment}}", {})).toBe(2);
553
+ expect(langJson.processHelper("{{#increment}}", {})).toBe(3);
554
+ });
555
+
556
+ test("registerHelper for formatting dates", () => {
557
+ langJson.registerHelper("formatDate", ([date, format]) => {
558
+ const d = new Date(date);
559
+ return `${d.getFullYear()}-${(d.getMonth() + 1)
560
+ .toString()
561
+ .padStart(2, "0")}-${d.getDate().toString().padStart(2, "0")}`;
562
+ });
563
+ expect(
564
+ langJson.processHelper("{{#formatDate date 'YYYY-MM-DD'}}", {
565
+ date: "2023-01-01",
566
+ })
567
+ ).toBe("2023-01-01");
568
+ });
569
+
570
+ test("registerHelper that accepts multiple arguments and returns an object", () => {
571
+ langJson.registerHelper("createUser", ([name, age, role]) => ({
572
+ name,
573
+ age,
574
+ role,
575
+ }));
576
+ expect(
577
+ langJson.processHelper("{{#createUser name age role}}", {
578
+ name: "Alice",
579
+ age: 30,
580
+ role: "Engineer",
581
+ })
582
+ ).toEqual({
583
+ name: "Alice",
584
+ age: 30,
585
+ role: "Engineer",
586
+ });
587
+ });
588
+
589
+ test("Complex integration test for LangJSON functionality", () => {
590
+ // Register multiple helpers
591
+ langJson.registerHelpers({
592
+ upper: ([str]) => str.toUpperCase(),
593
+ lower: ([str]) => str.toLowerCase(),
594
+ concat: ([arg1, arg2]) => `${arg1} ${arg2}`,
595
+ isTrue: ([arg]) => arg === "true",
596
+ getLength: ([arr]) => arr.length,
597
+ repeat: ([str, times]) => str.repeat(times),
598
+ });
599
+
600
+ // Define a complex data structure
601
+ const data = {
602
+ user: {
603
+ name: "Alice",
604
+ age: 30,
605
+ roles: ["admin", "editor"],
606
+ address: {
607
+ city: "Wonderland",
608
+ zip: "12345",
609
+ coordinates: { lat: 51.5074, long: -0.1278 },
610
+ },
611
+ preferences: {
612
+ notifications: { email: true, sms: false },
613
+ theme: "dark",
614
+ },
615
+ },
616
+ isActive: "true",
617
+ items: [
618
+ { id: 1, name: "Item1", description: "First Item" },
619
+ { id: 2, name: "Item2", description: "Second Item" },
620
+ { id: 3, name: "Item3", description: "Third Item" },
621
+ ],
622
+ };
623
+
624
+ // Define a complex template
625
+ const template = {
626
+ "{{#upper user.name}}": {
627
+ age: "{{#var user.age}}",
628
+ active: "{{#isTrue isActive}}",
629
+ address: {
630
+ city: "{{#var user.address.city}}",
631
+ zip: "{{#var user.address.zip}}",
632
+ coordinates:
633
+ "{{#var user.address.coordinates.lat}}, {{#var user.address.coordinates.long}}",
634
+ },
635
+ roles: {
636
+ "{{#arrayJoin (var user.roles) ', '}}": {
637
+ roleCount: "{{#getLength user.roles}}",
638
+ roleList: "{{#var user.roles[0]}} and {{#var user.roles[1]}}",
639
+ },
640
+ },
641
+ items: "{{#repeat (concat 'Item: ' (var items[0].name)) 3}}",
642
+ preferences: {
643
+ theme: "{{#var user.preferences.theme}}",
644
+ notificationStatus: {
645
+ email: "{{#var user.preferences.notifications.email}}",
646
+ sms: "{{#var user.preferences.notifications.sms}}",
647
+ },
648
+ },
649
+ },
650
+ };
651
+
652
+ // Apply the template with the complex data
653
+ const result = langJson.applyTemplate(template, data);
654
+
655
+ // Validate the output
656
+ expect(result).toEqual({
657
+ ALICE: {
658
+ age: 30,
659
+ active: true,
660
+ address: {
661
+ city: "Wonderland",
662
+ zip: "12345",
663
+ coordinates: "51.5074, -0.1278",
664
+ },
665
+ roles: {
666
+ "admin, editor": {
667
+ roleCount: 2,
668
+ roleList: "admin and editor",
669
+ },
670
+ },
671
+ items: "Item: Item1Item: Item1Item: Item1",
672
+ preferences: {
673
+ theme: "dark",
674
+ notificationStatus: {
675
+ email: true,
676
+ sms: false,
677
+ },
678
+ },
679
+ },
680
+ });
681
+ });