@legalplace/lplogic 2.3.2 → 2.3.3

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/.gitlab-automator CHANGED
@@ -1,7 +1,7 @@
1
- GITLAB_PRIVATE_TOKEN=glpat-2LLXVHzUViBmoVAUPBzy
1
+ GITLAB_PRIVATE_TOKEN=glpat-BOv5W1i6MoAAvHjzkmc5nW86MQp1OjkH.01.0w119catf
2
2
  GITLAB_BASE_URL=https://git.legalplace.eu
3
3
  GITLAB_API_PROJECT_ID=28
4
4
  GITLAB_USER_ID=9
5
5
  CURRENT_PROJECT_ID=39
6
6
  SLACK_USER_ID=U0B3SNBV3
7
- CLICKUP_PRIVATE_TOKEN=pk_32519579_FSGO0KOHXZ93NPCODYRPIWHWG12Y4G3A
7
+ CLICKUP_PRIVATE_TOKEN=pk_32519579_K5W4L4KEVXY03A3D2WFA46D07HVGTL5L
package/dist/LpLogic.js CHANGED
@@ -6,9 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  var json_logic_js_1 = __importDefault(require("@legalplace/json-logic-js"));
7
7
  var reduceParents = function (parents, length) {
8
8
  var reducedParents = [];
9
- parents.sort(function (a, b) { return b.length - a.length; });
9
+ var safeParents = parents.filter(function (entry) { return Array.isArray(entry); });
10
+ safeParents.sort(function (a, b) { return b.length - a.length; });
10
11
  var _loop_1 = function (index) {
11
- var currentIndexResult = parents.reduce(function (previousValue, currentValue) {
12
+ var currentIndexResult = safeParents.reduce(function (previousValue, currentValue) {
12
13
  if (currentValue.length === 1)
13
14
  return previousValue && currentValue[0];
14
15
  if (currentValue[index] === undefined)
@@ -23,7 +24,7 @@ var reduceParents = function (parents, length) {
23
24
  return reducedParents;
24
25
  };
25
26
  var reduceValues = function (values, parents, compareFunction) {
26
- if (parents === undefined || parents.length === 0) {
27
+ if (!Array.isArray(parents) || parents.length === 0) {
27
28
  return values.map(function (currentValue) {
28
29
  return compareFunction(currentValue, true);
29
30
  });
@@ -40,10 +41,25 @@ var parseNumber = function (value) {
40
41
  return parseFloat(value.replace(",", "."));
41
42
  return value;
42
43
  };
44
+ var cleanString = function (value) {
45
+ var raw = typeof value === "number" ? value.toString() : value.trim();
46
+ return raw
47
+ .normalize("NFD")
48
+ .replace(/[\u0300-\u036f]/g, "")
49
+ .replace(/œ/g, "oe")
50
+ .replace(/Œ/g, "oe")
51
+ .replace(/æ/g, "ae")
52
+ .replace(/Æ/g, "ae")
53
+ .toLowerCase();
54
+ };
43
55
  var safeEqual = function (value, comparator) {
44
56
  var parsedValue = typeof value === "number" ? value : parseNumber(value);
45
57
  var parsedComparator = typeof comparator === "number" ? comparator : parseNumber(comparator);
46
- return parsedValue === parsedComparator;
58
+ if (typeof parsedValue === "number" &&
59
+ typeof parsedComparator === "number") {
60
+ return parsedValue === parsedComparator;
61
+ }
62
+ return cleanString(value) === cleanString(comparator);
47
63
  };
48
64
  json_logic_js_1.default.add_operation("=", function (values, comparator, parents) {
49
65
  var reducedValues = reduceValues(values, parents, function (value, parent) {
@@ -129,13 +145,7 @@ json_logic_js_1.default.add_operation("has-many", function (values, comparator,
129
145
  });
130
146
  var is = function (values, comparator, parents) {
131
147
  var reducedValues = reduceValues(values, parents, function (value, parent) {
132
- var cleanValue = (typeof value === "number"
133
- ? value.toString()
134
- : value.trim()).toLowerCase();
135
- var cleanComparator = (typeof comparator === "number"
136
- ? comparator.toString()
137
- : comparator.trim()).toLowerCase();
138
- return cleanValue === cleanComparator && parent;
148
+ return cleanString(value) === cleanString(comparator) && parent;
139
149
  });
140
150
  var filter = reducedValues.filter(function (_value) { return _value === true; });
141
151
  return reducedValues.length === filter.length;
@@ -143,13 +153,7 @@ var is = function (values, comparator, parents) {
143
153
  json_logic_js_1.default.add_operation("is", is);
144
154
  var not = function (values, comparator, parents) {
145
155
  var reducedValues = reduceValues(values, parents, function (value, parent) {
146
- var cleanValue = (typeof value === "number"
147
- ? value.toString()
148
- : value.trim()).toLowerCase();
149
- var cleanComparator = (typeof comparator === "number"
150
- ? comparator.toString()
151
- : comparator.trim()).toLowerCase();
152
- return cleanValue !== cleanComparator && parent;
156
+ return cleanString(value) !== cleanString(comparator) && parent;
153
157
  });
154
158
  var filter = reducedValues.filter(function (_value) { return _value === true; });
155
159
  return reducedValues.length === filter.length;
@@ -158,21 +162,11 @@ json_logic_js_1.default.add_operation("not", not);
158
162
  var contains = function (values, comparator, parents) {
159
163
  var reducedValues = reduceValues(values, parents, function (value, parent) {
160
164
  if (Array.isArray(value)) {
161
- return value.some(function (val) {
162
- return (typeof val === "string" ? val.trim() : val.toString())
163
- .toLowerCase()
164
- .includes((typeof comparator === "string"
165
- ? comparator.trim()
166
- : comparator.toString()).toLowerCase()) && parent;
167
- });
168
- }
169
- else {
170
- var cleanValue = (typeof value === "number" ? value.toString() : value.trim()).toLowerCase();
171
- var cleanComparator = (typeof comparator === "number"
172
- ? comparator.toString()
173
- : comparator.trim()).toLowerCase();
174
- return cleanValue.includes(cleanComparator) && parent;
165
+ return (value.some(function (val) {
166
+ return cleanString(val).includes(cleanString(comparator));
167
+ }) && parent);
175
168
  }
169
+ return (cleanString(value).includes(cleanString(comparator)) && parent);
176
170
  });
177
171
  var filter = reducedValues.filter(function (value) { return value === true; });
178
172
  return reducedValues.length === filter.length;
@@ -181,21 +175,9 @@ json_logic_js_1.default.add_operation("contains", contains);
181
175
  var doesNotContain = function (values, comparator, parents) {
182
176
  var reducedValues = reduceValues(values, parents, function (value, parent) {
183
177
  if (Array.isArray(value)) {
184
- return value.every(function (val) {
185
- return !(typeof val === "string" ? val.trim() : val.toString())
186
- .toLowerCase()
187
- .includes((typeof comparator === "string"
188
- ? comparator.trim()
189
- : comparator.toString()).toLowerCase()) && parent;
190
- });
191
- }
192
- else {
193
- var cleanValue = (typeof value === "number" ? value.toString() : value.trim()).toLowerCase();
194
- var cleanComparator = (typeof comparator === "number"
195
- ? comparator.toString()
196
- : comparator.trim()).toLowerCase();
197
- return !cleanValue.includes(cleanComparator) && parent;
178
+ return (value.every(function (val) { return !cleanString(val).includes(cleanString(comparator)); }) && parent);
198
179
  }
180
+ return (!cleanString(value).includes(cleanString(comparator)) && parent);
199
181
  });
200
182
  var filter = reducedValues.filter(function (value) { return value === true; });
201
183
  return reducedValues.length === filter.length;
@@ -219,13 +201,7 @@ json_logic_js_1.default.add_operation("not-empty", function (values, comparator,
219
201
  });
220
202
  var like = function (values, comparator, parents) {
221
203
  var reducedValues = reduceValues(values, parents, function (value, parent) {
222
- var cleanValue = (typeof value === "number"
223
- ? value.toString()
224
- : value.trim()).toLowerCase();
225
- var cleanComparator = (typeof comparator === "number"
226
- ? comparator.toString()
227
- : comparator.trim()).toLowerCase();
228
- return (new RegExp("( |^)".concat(cleanComparator, "( |$)"), "i").test(cleanValue) && parent);
204
+ return (new RegExp("( |^)".concat(cleanString(comparator), "( |$)"), "i").test(cleanString(value)) && parent);
229
205
  });
230
206
  var filter = reducedValues.filter(function (_value) { return _value === true; });
231
207
  return reducedValues.length === filter.length;
@@ -233,14 +209,7 @@ var like = function (values, comparator, parents) {
233
209
  json_logic_js_1.default.add_operation("like", like);
234
210
  var notLike = function (values, comparator, parents) {
235
211
  var reducedValues = reduceValues(values, parents, function (value, parent) {
236
- var cleanValue = (typeof value === "number"
237
- ? value.toString()
238
- : value.trim()).toLowerCase();
239
- var cleanComparator = (typeof comparator === "number"
240
- ? comparator.toString()
241
- : comparator.trim()).toLowerCase();
242
- return (!new RegExp("( |^)".concat(cleanComparator, "( |$)"), "i").test(cleanValue) &&
243
- parent);
212
+ return (!new RegExp("( |^)".concat(cleanString(comparator), "( |$)"), "i").test(cleanString(value)) && parent);
244
213
  });
245
214
  var filter = reducedValues.filter(function (_value) { return _value === true; });
246
215
  return reducedValues.length === filter.length;
@@ -270,5 +239,105 @@ var regexMatch = function (values, comparator, parents) {
270
239
  return reducedValues.length === filter.length;
271
240
  };
272
241
  json_logic_js_1.default.add_operation("regex-match", regexMatch);
242
+ var aggregateAny = function (reducedValues) {
243
+ return reducedValues.includes(true);
244
+ };
245
+ var aggregateFirst = function (reducedValues) {
246
+ return reducedValues[0] === true;
247
+ };
248
+ var registerScopedBooleanOp = function (baseName, compareFn) {
249
+ json_logic_js_1.default.add_operation("".concat(baseName, "-first"), function (values, _comparator, parents) {
250
+ var reducedValue = reduceValues(values, parents, compareFn);
251
+ return aggregateFirst(reducedValue);
252
+ });
253
+ json_logic_js_1.default.add_operation("".concat(baseName, "-any"), function (values, _comparator, parents) {
254
+ var reducedValue = reduceValues(values, parents, compareFn);
255
+ return aggregateAny(reducedValue);
256
+ });
257
+ };
258
+ registerScopedBooleanOp("selected", function (value, parent) { return value && parent; });
259
+ registerScopedBooleanOp("not-selected", function (value, parent) { return !value && parent; });
260
+ var conditionMet = function (value, parent) {
261
+ return value === true && parent;
262
+ };
263
+ var conditionNotMet = function (value, parent) {
264
+ return value !== true && parent;
265
+ };
266
+ json_logic_js_1.default.add_operation("conditions-met", function (values, comparator, parents) {
267
+ return reduceValues(values, parents, conditionMet).every(function (value) { return value === true; });
268
+ });
269
+ json_logic_js_1.default.add_operation("conditions-not-met", function (values, comparator, parents) {
270
+ return reduceValues(values, parents, conditionNotMet).every(function (value) { return value === true; });
271
+ });
272
+ registerScopedBooleanOp("conditions-met", conditionMet);
273
+ registerScopedBooleanOp("conditions-not-met", conditionNotMet);
274
+ var registerScopedComparisonOp = function (baseName, compareFn) {
275
+ json_logic_js_1.default.add_operation("".concat(baseName, "-any"), function (values, comparator, parents) {
276
+ var reducedValues = reduceValues(values, parents, function (value, parent) {
277
+ return compareFn(value, comparator, parent);
278
+ });
279
+ return aggregateAny(reducedValues);
280
+ });
281
+ json_logic_js_1.default.add_operation("".concat(baseName, "-first"), function (values, comparator, parents) {
282
+ var reducedValues = reduceValues(values, parents, function (value, parent) {
283
+ return compareFn(value, comparator, parent);
284
+ });
285
+ return aggregateFirst(reducedValues);
286
+ });
287
+ };
288
+ registerScopedComparisonOp("=", function (value, comparator, parent) {
289
+ return safeEqual(value, comparator) && parent;
290
+ });
291
+ registerScopedComparisonOp("<>", function (value, comparator, parent) {
292
+ return !safeEqual(value, comparator) && parent;
293
+ });
294
+ registerScopedComparisonOp("==", function (value, comparator, parent) {
295
+ return parseNumber(value) === parseNumber(comparator) && parent;
296
+ });
297
+ registerScopedComparisonOp(">=", function (value, comparator, parent) {
298
+ return parseNumber(value) >= parseNumber(comparator) && parent;
299
+ });
300
+ registerScopedComparisonOp("<=", function (value, comparator, parent) {
301
+ return parseNumber(value) <= parseNumber(comparator) && parent;
302
+ });
303
+ registerScopedComparisonOp(">", function (value, comparator, parent) {
304
+ return parseNumber(value) > parseNumber(comparator) && parent;
305
+ });
306
+ registerScopedComparisonOp("<", function (value, comparator, parent) {
307
+ return parseNumber(value) < parseNumber(comparator) && parent;
308
+ });
309
+ registerScopedComparisonOp("is", function (value, comparator, parent) {
310
+ return cleanString(value) === cleanString(comparator) && parent;
311
+ });
312
+ registerScopedComparisonOp("not", function (value, comparator, parent) {
313
+ return cleanString(value) !== cleanString(comparator) && parent;
314
+ });
315
+ registerScopedComparisonOp("contains", function (value, comparator, parent) {
316
+ return cleanString(value).includes(cleanString(comparator)) && parent;
317
+ });
318
+ registerScopedComparisonOp("does-not-contain", function (value, comparator, parent) {
319
+ return !cleanString(value).includes(cleanString(comparator)) && parent;
320
+ });
321
+ registerScopedComparisonOp("like", function (value, comparator, parent) {
322
+ return new RegExp("( |^)".concat(cleanString(comparator), "( |$)"), "i").test(cleanString(value)) && parent;
323
+ });
324
+ registerScopedComparisonOp("not-like", function (value, comparator, parent) {
325
+ return !new RegExp("( |^)".concat(cleanString(comparator), "( |$)"), "i").test(cleanString(value)) && parent;
326
+ });
327
+ registerScopedComparisonOp("regex-match", function (value, comparator, parent) {
328
+ if (typeof comparator !== "string")
329
+ return false;
330
+ var regex;
331
+ try {
332
+ regex = new RegExp(comparator);
333
+ }
334
+ catch (error) {
335
+ return false;
336
+ }
337
+ var stringValue = typeof value === "number" ? value.toString() : value;
338
+ return regex.test(stringValue) && parent;
339
+ });
340
+ registerScopedComparisonOp("empty", function (value, _comparator, parent) { return cleanString(value).length === 0 && parent; });
341
+ registerScopedComparisonOp("not-empty", function (value, _comparator, parent) { return cleanString(value).length > 0 && parent; });
273
342
  var LpLogic = json_logic_js_1.default.apply;
274
343
  exports.default = LpLogic;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@legalplace/lplogic",
3
- "version": "2.3.2",
3
+ "version": "2.3.3",
4
4
  "description": "LegalPlace LpLogic",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -129,3 +129,242 @@ test('Testing "not-like" Bye on a value `Hello world`', async () => {
129
129
  test('Testing "not-like" World on a value `Hello world`', async () => {
130
130
  expect( LpLogic({"not-like":[{"var":"v.1"}, "World"]}, {"v":{"1":["Hello world"]}}) ).toBe(false)
131
131
  })
132
+
133
+ test('Testing "selected-first" on first occurrence only', async () => {
134
+ expect(LpLogic({"selected-first":[{"var":"o.1"}]}, {"o":{"1":[true, false]}})).toBe(true)
135
+ expect(LpLogic({"selected-first":[{"var":"o.1"}]}, {"o":{"1":[false, true]}})).toBe(false)
136
+ })
137
+
138
+ test('Testing "=-any" on multiple values', async () => {
139
+ expect(LpLogic({"=-any":[{"var":"v.1"}, "a"]}, {"v":{"1":["a", "b"]}})).toBe(true)
140
+ expect(LpLogic({"=-any":[{"var":"v.1"}, "a"]}, {"v":{"1":["b", "c"]}})).toBe(false)
141
+ })
142
+
143
+ /**
144
+ * empty-any / not-empty-any cover occurrence scope "at least one" for emptiness checks.
145
+ */
146
+ test('Testing "empty-any" on multiple values', async () => {
147
+ expect(LpLogic({"empty-any":[{"var":"v.1"}]}, {"v":{"1":["", "x"]}})).toBe(true)
148
+ expect(LpLogic({"empty-any":[{"var":"v.1"}]}, {"v":{"1":["x", "y"]}})).toBe(false)
149
+ })
150
+
151
+ test('Testing "empty-first" on multiple values', async () => {
152
+ expect(LpLogic({"empty-first":[{"var":"v.1"}]}, {"v":{"1":["", "x"]}})).toBe(true)
153
+ expect(LpLogic({"empty-first":[{"var":"v.1"}]}, {"v":{"1":["x", ""]}})).toBe(false)
154
+ })
155
+
156
+ test('Testing "not-empty-any" on multiple values', async () => {
157
+ expect(LpLogic({"not-empty-any":[{"var":"v.1"}]}, {"v":{"1":["", "x"]}})).toBe(true)
158
+ expect(LpLogic({"not-empty-any":[{"var":"v.1"}]}, {"v":{"1":["", ""]}})).toBe(false)
159
+ })
160
+
161
+ test('Testing "=-first" on multiple values', async () => {
162
+ expect(LpLogic({"=-first":[{"var":"v.1"}, "a"]}, {"v":{"1":["a", "b"]}})).toBe(true)
163
+ expect(LpLogic({"=-first":[{"var":"v.1"}, "a"]}, {"v":{"1":["b", "a"]}})).toBe(false)
164
+ })
165
+
166
+ test('Testing "conditions-met" without parents', async () => {
167
+ expect(
168
+ LpLogic({"conditions-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, true]}}})
169
+ ).toBe(true)
170
+ expect(
171
+ LpLogic({"conditions-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, false]}}})
172
+ ).toBe(false)
173
+ })
174
+
175
+ test('Testing "conditions-met" with parents', async () => {
176
+ expect(
177
+ LpLogic(
178
+ {"conditions-met":[{"var":"c.o.2"}, undefined, [{"var":"o.1"}]]},
179
+ {"c":{"o":{"2":[true, true]}}, "o":{"1":[true, true]}}
180
+ )
181
+ ).toBe(true)
182
+ expect(
183
+ LpLogic(
184
+ {"conditions-met":[{"var":"c.o.2"}, undefined, [{"var":"o.1"}]]},
185
+ {"c":{"o":{"2":[true, true]}}, "o":{"1":[true, false]}}
186
+ )
187
+ ).toBe(false)
188
+ })
189
+
190
+ test('Testing "conditions-met-first" on first occurrence only', async () => {
191
+ expect(
192
+ LpLogic({"conditions-met-first":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, false]}}})
193
+ ).toBe(true)
194
+ expect(
195
+ LpLogic({"conditions-met-first":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, true]}}})
196
+ ).toBe(false)
197
+ })
198
+
199
+ test('Testing "conditions-met-any" on multiple values', async () => {
200
+ expect(
201
+ LpLogic({"conditions-met-any":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, true]}}})
202
+ ).toBe(true)
203
+ expect(
204
+ LpLogic({"conditions-met-any":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, false]}}})
205
+ ).toBe(false)
206
+ })
207
+
208
+ test('Testing "conditions-not-met"', async () => {
209
+ expect(
210
+ LpLogic({"conditions-not-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, false]}}})
211
+ ).toBe(true)
212
+ expect(
213
+ LpLogic({"conditions-not-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, false]}}})
214
+ ).toBe(false)
215
+ })
216
+
217
+ /**
218
+ * Regression: when a condition tree containing `undefined` parents is passed
219
+ * through any JSON serialization (e.g. Redux DevTools), `undefined` becomes
220
+ * `null` (`JSON.stringify([a, undefined])` → `'[a,null]'`). LpLogic must
221
+ * treat a `null` parents arg as "no parents" instead of throwing on
222
+ * `null.length`.
223
+ */
224
+ test('Testing "conditions-met" with null parents (JSON round-trip safety)', async () => {
225
+ expect(
226
+ LpLogic(
227
+ { "conditions-met": [{ var: "c.o.1" }, null, null] },
228
+ { "c": { "o": { "1": [true, true] } } }
229
+ )
230
+ ).toBe(true)
231
+ expect(
232
+ LpLogic(
233
+ { "conditions-met-first": [{ var: "c.o.1" }, null, null] },
234
+ { "c": { "o": { "1": [true, false] } } }
235
+ )
236
+ ).toBe(true)
237
+ })
238
+
239
+ test('Testing "selected" with null parents (JSON round-trip safety)', async () => {
240
+ expect(
241
+ LpLogic(
242
+ { "selected": [{ var: "o.1" }, null, null] },
243
+ { "o": { "1": [true, true] } }
244
+ )
245
+ ).toBe(true)
246
+ })
247
+
248
+ test('Testing "conditions-met" with parents containing missing refs (null entries)', async () => {
249
+ // `{ var: "o.999" }` resolves to `null` because `o.999` is absent from data.
250
+ // Parents array is `[null]`; LpLogic must not throw.
251
+ expect(
252
+ LpLogic(
253
+ { "conditions-met": [{ var: "c.o.1" }, undefined, [{ var: "o.999" }]] },
254
+ { "c": { "o": { "1": [true] } } }
255
+ )
256
+ ).toBe(true)
257
+ })
258
+
259
+ /**
260
+ * Accent- and case-insensitive text matching (=, contains, like and negations).
261
+ * Matches the product table: la/lax, la/la ha, la/là, la/La, Léon/Leon.
262
+ */
263
+ test('Testing "=" case-insensitive for strings', async () => {
264
+ expect(LpLogic({ "=": [{ var: "v.1" }, "la"] }, { v: { 1: ["La"] } })).toBe(
265
+ true
266
+ )
267
+ expect(LpLogic({ "=": [{ var: "v.1" }, "la"] }, { v: { 1: ["LA"] } })).toBe(
268
+ true
269
+ )
270
+ })
271
+
272
+ test('Testing "=" accent-insensitive for strings', async () => {
273
+ expect(LpLogic({ "=": [{ var: "v.1" }, "la"] }, { v: { 1: ["là"] } })).toBe(
274
+ true
275
+ )
276
+ expect(
277
+ LpLogic({ "=": [{ var: "v.1" }, "Léon"] }, { v: { 1: ["Leon"] } })
278
+ ).toBe(true)
279
+ expect(
280
+ LpLogic({ "=": [{ var: "v.1" }, "Léon"] }, { v: { 1: ["LEON"] } })
281
+ ).toBe(true)
282
+ })
283
+
284
+ test('Testing "=" still false for different words', async () => {
285
+ expect(LpLogic({ "=": [{ var: "v.1" }, "la"] }, { v: { 1: ["lax"] } })).toBe(
286
+ false
287
+ )
288
+ expect(
289
+ LpLogic({ "=": [{ var: "v.1" }, "la"] }, { v: { 1: ["la ha"] } })
290
+ ).toBe(false)
291
+ })
292
+
293
+ test('Testing "=" still numeric for number-like values', async () => {
294
+ expect(LpLogic({ "=": [{ var: "v.1" }, "1.0"] }, { v: { 1: [1] } })).toBe(
295
+ true
296
+ )
297
+ expect(LpLogic({ "=": [{ var: "v.1" }, 1] }, { v: { 1: ["1"] } })).toBe(true)
298
+ })
299
+
300
+ test('Testing "<>" is inverse of accent/case-insensitive "="', async () => {
301
+ expect(LpLogic({ "<>": [{ var: "v.1" }, "la"] }, { v: { 1: ["là"] } })).toBe(
302
+ false
303
+ )
304
+ expect(LpLogic({ "<>": [{ var: "v.1" }, "la"] }, { v: { 1: ["lax"] } })).toBe(
305
+ true
306
+ )
307
+ })
308
+
309
+ test('Testing "contains" accent- and case-insensitive', async () => {
310
+ expect(
311
+ LpLogic({ contains: [{ var: "v.1" }, "la"] }, { v: { 1: ["lax"] } })
312
+ ).toBe(true)
313
+ expect(
314
+ LpLogic({ contains: [{ var: "v.1" }, "la"] }, { v: { 1: ["la ha"] } })
315
+ ).toBe(true)
316
+ expect(
317
+ LpLogic({ contains: [{ var: "v.1" }, "la"] }, { v: { 1: ["là"] } })
318
+ ).toBe(true)
319
+ expect(
320
+ LpLogic({ contains: [{ var: "v.1" }, "la"] }, { v: { 1: ["La"] } })
321
+ ).toBe(true)
322
+ })
323
+
324
+ test('Testing "does-not-contain" is inverse of accent-insensitive contains', async () => {
325
+ expect(
326
+ LpLogic(
327
+ { "does-not-contain": [{ var: "v.1" }, "la"] },
328
+ { v: { 1: ["là"] } }
329
+ )
330
+ ).toBe(false)
331
+ expect(
332
+ LpLogic(
333
+ { "does-not-contain": [{ var: "v.1" }, "la"] },
334
+ { v: { 1: ["Bye"] } }
335
+ )
336
+ ).toBe(true)
337
+ })
338
+
339
+ test('Testing "like" accent- and case-insensitive word match', async () => {
340
+ expect(
341
+ LpLogic({ like: [{ var: "v.1" }, "la"] }, { v: { 1: ["lax"] } })
342
+ ).toBe(false)
343
+ expect(
344
+ LpLogic({ like: [{ var: "v.1" }, "la"] }, { v: { 1: ["la ha"] } })
345
+ ).toBe(true)
346
+ expect(
347
+ LpLogic({ like: [{ var: "v.1" }, "la"] }, { v: { 1: ["là"] } })
348
+ ).toBe(true)
349
+ expect(
350
+ LpLogic({ like: [{ var: "v.1" }, "la"] }, { v: { 1: ["La"] } })
351
+ ).toBe(true)
352
+ })
353
+
354
+ test('Testing "not-like" is inverse of accent-insensitive like', async () => {
355
+ expect(
356
+ LpLogic({ "not-like": [{ var: "v.1" }, "la"] }, { v: { 1: ["là"] } })
357
+ ).toBe(false)
358
+ expect(
359
+ LpLogic({ "not-like": [{ var: "v.1" }, "la"] }, { v: { 1: ["lax"] } })
360
+ ).toBe(true)
361
+ })
362
+
363
+ test('Testing "is" accent-insensitive (legacy equal alias)', async () => {
364
+ expect(LpLogic({ is: [{ var: "v.1" }, "la"] }, { v: { 1: ["là"] } })).toBe(
365
+ true
366
+ )
367
+ expect(
368
+ LpLogic({ is: [{ var: "v.1" }, "Léon"] }, { v: { 1: ["Leon"] } })
369
+ ).toBe(true)
370
+ })