lang-json 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -0
- package/babel.config.js +8 -0
- package/coverage/clover.xml +6 -0
- package/coverage/coverage-final.json +1 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +101 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/dist/esm/src/index.d.ts +18 -0
- package/dist/esm/src/index.js +369 -0
- package/dist/esm/src/index.js.map +1 -0
- package/dist/esm/src/modules/is-this/index.d.ts +136 -0
- package/dist/esm/src/modules/is-this/index.js +484 -0
- package/dist/esm/src/modules/is-this/index.js.map +1 -0
- package/dist/esm/tests/helpers.test.d.ts +1 -0
- package/dist/esm/tests/helpers.test.js +284 -0
- package/dist/esm/tests/helpers.test.js.map +1 -0
- package/dist/esm/tests/index.test.d.ts +1 -0
- package/dist/esm/tests/index.test.js +537 -0
- package/dist/esm/tests/index.test.js.map +1 -0
- package/dist/esm/tests/readme.test.d.ts +1 -0
- package/dist/esm/tests/readme.test.js +73 -0
- package/dist/esm/tests/readme.test.js.map +1 -0
- package/jest.config.ts +212 -0
- package/package.json +40 -12
- package/src/index.ts +404 -295
- package/src/modules/is-this/index.ts +682 -0
- package/tests/helpers.test.ts +331 -0
- package/tests/index.test.ts +681 -0
- package/tests/readme.test.ts +78 -0
- package/tsconfig.json +15 -16
- package/dist/esm/dump.js +0 -2
- package/dist/esm/dump.js.map +0 -1
- package/dist/esm/example.d.ts +0 -13
- package/dist/esm/example.js +0 -93
- package/dist/esm/example.js.map +0 -1
- package/dist/esm/index.d.ts +0 -36
- package/dist/esm/index.js +0 -326
- package/dist/esm/index.js.map +0 -1
- package/src/example.ts +0 -116
- /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
|
+
});
|