Repository: jsonata-js/jsonata
Pull request #375 (2019-10-02 08:55:42)

Add $assert() function.
Function described in https://github.com/jsonata-js/jsonata/issues/369

coveralls: 
[![Coverage Status](https://coveralls.io/builds/26061108/badge)](https://coveralls.io/builds/26061108)

Coverage remained the same at 100.0% when pulling **797168931625328a7d5c2ead4262b8a46427b9a1 on elasticio:add-assert-function** into **db7cac7aeaa17e6a7c8a55fe76bd80d7cc0fd4d7 on jsonata-js:master**.


Patch:
diff --git a/docs/object-functions.md b/docs/object-functions.md
index c0713a3..56f0c99 100644
--- a/docs/object-functions.md
+++ b/docs/object-functions.md
@@ -57,3 +57,8 @@ __Examples__
 __Signature:__`$error(message)`
 
 Deliberately throws an error with an optional `message`
+
+ ## `$assert()`
+__Signature:__`$assert(condition, message)`
+
+If condition is true, the function returns undefined. If the condition is false, an exception is thrown with the message as the message of the exception.
diff --git a/src/functions.js b/src/functions.js
index 8e23648..cc2f324 100644
--- a/src/functions.js
+++ b/src/functions.js
@@ -1822,6 +1822,25 @@ const functions = (() => {
         };
     }
 
+    /**
+     *
+     * @param {boolean} condition - the condition to evaluate
+     * @param {string} [message] - the message to attach to the error
+     * @throws custom error with code 'D3137'
+     * @returns {undefined}
+     */
+    function assert(condition, message) {
+        if(!condition) {
+            throw {
+                code: "D3141",
+                stack: (new Error()).stack,
+                message: message || "$assert() statement failed"
+            };
+        }
+
+        return undefined;
+    }
+
     /**
      * Implements the merge sort (stable) with optional comparator function
      *
@@ -1995,7 +2014,7 @@ const functions = (() => {
         formatNumber, formatBase, number, floor, ceil, round, abs, sqrt, power, random,
         boolean, not,
         map, zip, filter, single, foldLeft, sift,
-        keys, lookup, append, exists, spread, merge, reverse, each, error, sort, shuffle, distinct,
+        keys, lookup, append, exists, spread, merge, reverse, each, error, assert, sort, shuffle, distinct,
         base64encode, base64decode,  encodeUrlComponent, encodeUrl, decodeUrlComponent, decodeUrl
     };
 })();
diff --git a/src/jsonata.js b/src/jsonata.js
index b5fb676..ebccb06 100644
--- a/src/jsonata.js
+++ b/src/jsonata.js
@@ -1858,6 +1858,7 @@ var jsonata = (function() {
     staticFrame.bind('reverse', defineFunction(fn.reverse, '<a:a>'));
     staticFrame.bind('each', defineFunction(fn.each, '<o-f:a>'));
     staticFrame.bind('error', defineFunction(fn.error, '<s?:x>'));
+    staticFrame.bind('assert', defineFunction(fn.assert, '<bs?:x>'));
     staticFrame.bind('sort', defineFunction(fn.sort, '<af?:a>'));
     staticFrame.bind('shuffle', defineFunction(fn.shuffle, '<a:a>'));
     staticFrame.bind('distinct', defineFunction(fn.distinct, '<x:x>'));
@@ -1980,7 +1981,8 @@ var jsonata = (function() {
         "D3137": "{{{message}}}",
         "D3138": "The $single() function expected exactly 1 matching result.  Instead it matched more.",
         "D3139": "The $single() function expected exactly 1 matching result.  Instead it matched 0.",
-        "D3140": "Malformed URL passed to ${{{functionName}}}(): {{value}}"
+        "D3140": "Malformed URL passed to ${{{functionName}}}(): {{value}}",
+        "D3141": "{{{message}}}"
     };
 
     /**


Test patch:
diff --git a/test/test-suite/datasets/dataset5.json b/test/test-suite/datasets/dataset5.json
index 3c37583..edbcf4e 100644
--- a/test/test-suite/datasets/dataset5.json
+++ b/test/test-suite/datasets/dataset5.json
@@ -70,4 +70,4 @@
             }
         ]
     }
-}
\ No newline at end of file
+}
diff --git a/test/test-suite/groups/function-assert/case000.json b/test/test-suite/groups/function-assert/case000.json
new file mode 100644
index 0000000..8a101f8
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case000.json
@@ -0,0 +1,9 @@
+{
+    "expr": "$assert(Account.Order[0].Product[0].Price < 34, 'Too Expensive')",
+    "dataset": "dataset5",
+    "bindings": {},
+    "error": {
+        "code": "D3141",
+        "message": "Too Expensive"
+    }    
+}
diff --git a/test/test-suite/groups/function-assert/case001.json b/test/test-suite/groups/function-assert/case001.json
new file mode 100644
index 0000000..a377310
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case001.json
@@ -0,0 +1,6 @@
+{
+    "expr": "$assert(Account.Order[0].Product[0].Price < 35, 'Too Expensive')",
+    "dataset": "dataset5",
+    "bindings": {},
+    "undefinedResult": true
+}
diff --git a/test/test-suite/groups/function-assert/case002.json b/test/test-suite/groups/function-assert/case002.json
new file mode 100644
index 0000000..c9ef601
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case002.json
@@ -0,0 +1,6 @@
+{
+    "expr": "($assert(Account.Order[0].Product[0].Price < 35, 'Too Expensive'); Account.Order[0].Product[0].Price)",
+    "dataset": "dataset5",
+    "bindings": {},
+    "result": 34.45
+}
diff --git a/test/test-suite/groups/function-assert/case003.json b/test/test-suite/groups/function-assert/case003.json
new file mode 100644
index 0000000..9493e1d
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case003.json
@@ -0,0 +1,9 @@
+{
+    "expr": "($assert(Account.Order[0].Product[0].Price < 34, 'Too Expensive'); Account.Order[0].Product[0].Price)",
+    "dataset": "dataset5",
+    "bindings": {},
+    "error": {
+        "code": "D3141",
+        "message": "Too Expensive"
+    }
+}
diff --git a/test/test-suite/groups/function-assert/case004.json b/test/test-suite/groups/function-assert/case004.json
new file mode 100644
index 0000000..023ce36
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case004.json
@@ -0,0 +1,6 @@
+{
+    "expr": "$assert(null)",
+    "dataset": "dataset5",
+    "bindings": {},
+    "code": "T0410"
+}
diff --git a/test/test-suite/groups/function-assert/case005.json b/test/test-suite/groups/function-assert/case005.json
new file mode 100644
index 0000000..b188daf
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case005.json
@@ -0,0 +1,6 @@
+{
+    "expr": "$assert(5)",
+    "dataset": "dataset5",
+    "bindings": {},
+    "code": "T0410"
+}
diff --git a/test/test-suite/groups/function-assert/case006.json b/test/test-suite/groups/function-assert/case006.json
new file mode 100644
index 0000000..ce7736b
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case006.json
@@ -0,0 +1,9 @@
+{
+    "expr": "$assert(false)",
+    "dataset": "dataset5",
+    "bindings": {},
+    "error": {
+        "code": "D3141",
+        "message": "$assert() statement failed"
+    }
+}
diff --git a/test/test-suite/groups/function-assert/case007.json b/test/test-suite/groups/function-assert/case007.json
new file mode 100644
index 0000000..bcfe20b
--- /dev/null
+++ b/test/test-suite/groups/function-assert/case007.json
@@ -0,0 +1,6 @@
+{
+    "expr": "$assert(true)",
+    "dataset": "dataset5",
+    "bindings": {},
+    "undefinedResult": true
+}