@gregoriusrippenstein/erlang-red-unittest 0.12.4 → 0.15.0

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.
Files changed (211) hide show
  1. package/README.md +5 -1
  2. package/nodes/locales/en-US/ut-assert-success.html +8 -2
  3. package/nodes/locales/en-US/ut-assert-success.json +7 -1
  4. package/nodes/ut-assert-debug.js +385 -2
  5. package/nodes/ut-assert-failure.js +29 -18
  6. package/nodes/ut-assert-status.js +11 -2
  7. package/nodes/ut-assert-success.html +33 -12
  8. package/nodes/ut-assert-success.js +59 -29
  9. package/nodes/ut-assert-values.js +123 -16
  10. package/package.json +1 -1
  11. package/plugins/sidebar.html +131 -28
  12. package/testflows/01b074cfa6ae8818/flows.json +1 -0
  13. package/testflows/02b18fc0ed9de178/flows.json +1 -0
  14. package/testflows/0616f795a4aee63e/flows.json +1 -0
  15. package/testflows/069552b2eb6bce48/flows.json +265 -0
  16. package/testflows/08183069b5f8ef9c/flows.json +156 -0
  17. package/testflows/084fb0fc954b7156/flows.json +132 -0
  18. package/testflows/090eb2d5d71fd45f/flows.json +158 -0
  19. package/testflows/09aab59a2455cf15/flows.json +1 -0
  20. package/testflows/0b299a3175fc0df1/flows.json +1 -0
  21. package/testflows/0c35d269ca7178c6/flows.json +443 -0
  22. package/testflows/0cb8971e5f88ed1e/flows.json +1 -0
  23. package/testflows/0cc95e44532c14ec/flows.json +94 -0
  24. package/testflows/0e54563ba63b1501/flows.json +1 -0
  25. package/testflows/12572f9ac11e1786/flows.json +1 -0
  26. package/testflows/1566e453a88578a9/flows.json +1 -0
  27. package/testflows/15c2fad089960984/flows.json +1 -0
  28. package/testflows/1658196c31549916/flows.json +1 -0
  29. package/testflows/16b0bc0cdb0c5807/flows.json +1 -0
  30. package/testflows/16b254125478329a/flows.json +114 -0
  31. package/testflows/182731f54d855071/flows.json +52 -0
  32. package/testflows/1a196bce3e57f5c1/flows.json +1 -0
  33. package/testflows/1ace9e051618db79/flows.json +125 -0
  34. package/testflows/1bac0a78e0a36ec0/flows.json +1 -0
  35. package/testflows/1c1d2cb981cf9f01/flows.json +120 -0
  36. package/testflows/1d3326a724ecbea0/flows.json +1 -0
  37. package/testflows/1db9c9a1b92e0263/flows.json +172 -0
  38. package/testflows/1eb35963b752eca9/flows.json +1 -0
  39. package/testflows/2037454a5ee0d6c3/flows.json +1 -0
  40. package/testflows/20eeaf41372f7b17/flows.json +62 -0
  41. package/testflows/213803d61ecfde3a/flows.json +1 -0
  42. package/testflows/218350f2e240a15d/flows.json +1 -0
  43. package/testflows/24f35eaa8656755f/flows.json +1 -0
  44. package/testflows/27804627fb8f56bd/flows.json +178 -0
  45. package/testflows/2a12af161b544aa1/flows.json +1 -0
  46. package/testflows/2a2c508260b96236/flows.json +141 -0
  47. package/testflows/2a95a7b40a798878/flows.json +1 -0
  48. package/testflows/2c1c291ec8466bfb/flows.json +1 -0
  49. package/testflows/2c59ef974b2523ba/flows.json +1 -0
  50. package/testflows/30465efe017cc9b0/flows.json +1 -0
  51. package/testflows/30c79fc42a5c35eb/flows.json +1 -0
  52. package/testflows/338c5b411f4edfe8/flows.json +1 -0
  53. package/testflows/34d211e37618313c/flows.json +1 -0
  54. package/testflows/36846ad6698e1bc0/flows.json +163 -0
  55. package/testflows/37883612d913fd66/flows.json +1 -0
  56. package/testflows/38616d22e1569aa5/flows.json +1 -0
  57. package/testflows/3be6bc074c7647bd/flows.json +319 -0
  58. package/testflows/3e9e526b992d4c48/flows.json +1 -0
  59. package/testflows/3ea113b4ec3b6e5e/flows.json +1 -0
  60. package/testflows/3ed472eab9503b4f/flows.json +1 -0
  61. package/testflows/3edda6bd788f88c2/flows.json +1 -0
  62. package/testflows/435d3b48dd0f462c/flows.json +1 -0
  63. package/testflows/44f12f6e4a455084/flows.json +272 -0
  64. package/testflows/45209c67f865ce73/flows.json +1 -0
  65. package/testflows/459322e0f8e0b785/flows.json +1 -0
  66. package/testflows/4657dbc0aa4a97bb/flows.json +268 -0
  67. package/testflows/47514a335b4cd67e/flows.json +362 -0
  68. package/testflows/486c1412721bb241/flows.json +525 -0
  69. package/testflows/48d9fdcde317974e/flows.json +1 -0
  70. package/testflows/4de34883c5d93dc3/flows.json +1 -0
  71. package/testflows/50d5679818477b66/flows.json +1 -0
  72. package/testflows/51870a76d1aaf67a/flows.json +1 -0
  73. package/testflows/51bfa9456b1745c0/flows.json +639 -0
  74. package/testflows/538be5947c639b32/flows.json +75 -0
  75. package/testflows/538d2f4704cd2eca/flows.json +1 -0
  76. package/testflows/5433b57035d597f9/flows.json +1 -0
  77. package/testflows/545871d31c3f5f3f/flows.json +376 -0
  78. package/testflows/55f105cfd894b06c/flows.json +121 -0
  79. package/testflows/55f7fbe90e5befa8/flows.json +1 -0
  80. package/testflows/562c518969666f24/flows.json +1 -0
  81. package/testflows/57d44c342a1f00e2/flows.json +1 -0
  82. package/testflows/597ee2a683d9908f/flows.json +129 -0
  83. package/testflows/59aa8a866d8d7a70/flows.json +1 -0
  84. package/testflows/59da63b5adb460db/flows.json +188 -0
  85. package/testflows/5a06352874fa379d/flows.json +1 -0
  86. package/testflows/5cd133958df17529/flows.json +1 -0
  87. package/testflows/5cf6aec7d688fce4/flows.json +1 -0
  88. package/testflows/5d4908af3d4f95e5/flows.json +1 -0
  89. package/testflows/5e07acf2da13b504/flows.json +1 -0
  90. package/testflows/5f6929bb3374b782/flows.json +1 -0
  91. package/testflows/61142eb3e4e54eab/flows.json +536 -0
  92. package/testflows/61847d719e50f83f/flows.json +1 -0
  93. package/testflows/63ca9baf860d1d8f/flows.json +1 -0
  94. package/testflows/641ddaab2819c61d/flows.json +1 -0
  95. package/testflows/64445798b59d2630/flows.json +257 -0
  96. package/testflows/684b9066e98b9722/flows.json +1 -0
  97. package/testflows/698b83b8aeb5d5b6/flows.json +1 -0
  98. package/testflows/6a9ffd45c418497b/flows.json +1 -0
  99. package/testflows/6d46e3fe1f2245b8/flows.json +86 -0
  100. package/testflows/6dd3a5754f83dc2e/flows.json +232 -0
  101. package/testflows/6ea4c6b373eeaa8d/flows.json +1 -0
  102. package/testflows/6f0dcbf18234c5e2/flows.json +1 -0
  103. package/testflows/6ff45e2a0ce77393/flows.json +149 -0
  104. package/testflows/700c94899fdd3334/flows.json +107 -0
  105. package/testflows/71f65246c742cfc9/flows.json +1 -0
  106. package/testflows/7581c2be261f9c17/flows.json +1874 -0
  107. package/testflows/77854a5ea962257b/flows.json +1 -0
  108. package/testflows/7b77600dcf78933f/flows.json +1 -0
  109. package/testflows/7dae2b1a7881c607/flows.json +1 -0
  110. package/testflows/7e1d04570c6bdff9/flows.json +1 -0
  111. package/testflows/7ecfd18f58fc6510/flows.json +1 -0
  112. package/testflows/7fea9696f6186962/flows.json +141 -0
  113. package/testflows/80655e5d4035fa71/flows.json +215 -0
  114. package/testflows/8180ae5891c673de/flows.json +1 -0
  115. package/testflows/8421f37b6c40e1ec/flows.json +1 -0
  116. package/testflows/84a5a362cafe703f/flows.json +1 -0
  117. package/testflows/866410b56fa42447/flows.json +1076 -0
  118. package/testflows/894f6e38bfd1aca6/flows.json +1 -0
  119. package/testflows/89aeaeef64509bed/flows.json +101 -0
  120. package/testflows/8a627c9bfe3b4aff/flows.json +552 -0
  121. package/testflows/8bc7412d6a4869c6/flows.json +1 -0
  122. package/testflows/92054e0dd22f14c6/flows.json +1 -0
  123. package/testflows/93c6e969dcf84e70/flows.json +1 -0
  124. package/testflows/9463eba0ab843567/flows.json +1 -0
  125. package/testflows/96f6f83dcab507e5/flows.json +105 -0
  126. package/testflows/9746601768c3b3b6/flows.json +93 -0
  127. package/testflows/987cd33b9cda8529/flows.json +1 -0
  128. package/testflows/988f27b9abdde6e9/flows.json +1 -0
  129. package/testflows/9942fa1aeb1b2428/flows.json +2346 -0
  130. package/testflows/9a1bdfdcd7b2be8e/flows.json +1 -0
  131. package/testflows/9b1023c95a2613cc/flows.json +141 -0
  132. package/testflows/9c51a179141515b2/flows.json +1 -0
  133. package/testflows/9d11bfc3a6d88535/flows.json +301 -0
  134. package/testflows/9e7ccc97f80d9afb/flows.json +93 -0
  135. package/testflows/9f0d6c3ad7798a77/flows.json +142 -0
  136. package/testflows/9f7351d7a7304584/flows.json +83 -0
  137. package/testflows/9ff2e8ab21d922c5/flows.json +1 -0
  138. package/testflows/a123cd431f1967cd/flows.json +1757 -0
  139. package/testflows/a4c9cabf4b335488/flows.json +86 -0
  140. package/testflows/a6dc7002d0a8640e/flows.json +1 -0
  141. package/testflows/a862ae412a70ded1/flows.json +1 -0
  142. package/testflows/a916165378c446e3/flows.json +240 -0
  143. package/testflows/ad2bf1089481dcfb/flows.json +1 -0
  144. package/testflows/ae38b2dbd23d1681/flows.json +3089 -0
  145. package/testflows/ae8a9b0bbbaff447/flows.json +271 -0
  146. package/testflows/b07b511dc8bb8339/flows.json +92 -0
  147. package/testflows/b1430ea37ba7cc19/flows.json +1 -0
  148. package/testflows/b1463d7bbf545725/flows.json +1 -0
  149. package/testflows/b1501de32c769cf2/flows.json +94 -0
  150. package/testflows/b2a67e301fabab0e/flows.json +1 -0
  151. package/testflows/b2fcc5806b2715c0/flows.json +1 -0
  152. package/testflows/b3f365d0b7d1f97d/flows.json +1 -0
  153. package/testflows/b50f775ae3b74d38/flows.json +1 -0
  154. package/testflows/b5fbcdbffb568569/flows.json +1 -0
  155. package/testflows/b6d4e4592b27a344/flows.json +1 -0
  156. package/testflows/b723353a316fa50e/flows.json +1 -0
  157. package/testflows/b7ebaf91f4d66ab3/flows.json +1 -0
  158. package/testflows/b85795a24882502b/flows.json +1 -0
  159. package/testflows/b864b3e3510cd120/flows.json +205 -0
  160. package/testflows/b98d0b05a760ad79/flows.json +1 -0
  161. package/testflows/b9cd19107a5145c4/flows.json +1 -0
  162. package/testflows/bbb1fc2d47c3cd5f/flows.json +1 -0
  163. package/testflows/bdbe94d065f3b3a6/flows.json +143 -0
  164. package/testflows/bfced61e72c69715/flows.json +616 -0
  165. package/testflows/c0b1cf6656eac77f/flows.json +518 -0
  166. package/testflows/c1370220fd37968e/flows.json +1 -0
  167. package/testflows/c163c627bd2a37c7/flows.json +1 -0
  168. package/testflows/c274a07715a87ca4/flows.json +1 -0
  169. package/testflows/c28048d859db3773/flows.json +1 -0
  170. package/testflows/c381b5135cc947cd/flows.json +272 -0
  171. package/testflows/c4690c0a085d6ef5/flows.json +145 -0
  172. package/testflows/c5f513bc380bc30a/flows.json +696 -0
  173. package/testflows/c6ee6e89a51c98fc/flows.json +1 -0
  174. package/testflows/c843dacf753a19d8/flows.json +1 -0
  175. package/testflows/caccb020fce3f485/flows.json +1 -0
  176. package/testflows/cd44a688eb2ab3cf/flows.json +1 -0
  177. package/testflows/ce2f98273da05245/flows.json +1 -0
  178. package/testflows/ced70c769db825eb/flows.json +1 -0
  179. package/testflows/cef9dd7dc179b8b3/flows.json +1 -0
  180. package/testflows/cfa8595b2e2b8269/flows.json +255 -0
  181. package/testflows/cffa610c817beb43/flows.json +1 -0
  182. package/testflows/d17062b01c4a9435/flows.json +1 -0
  183. package/testflows/d17fb2553fe8013a/flows.json +157 -0
  184. package/testflows/d206746f9f2594a6/flows.json +1 -0
  185. package/testflows/d4ce58359ff6ff96/flows.json +1 -0
  186. package/testflows/d5424657b497d5af/flows.json +1 -0
  187. package/testflows/d595c53abba88f72/flows.json +1 -0
  188. package/testflows/d61182e87a604efa/flows.json +340 -0
  189. package/testflows/def45a46c8f4da72/flows.json +1 -0
  190. package/testflows/def56742e02f6a75/flows.json +1 -0
  191. package/testflows/e1ced3b16782f7c8/flows.json +1 -0
  192. package/testflows/e2a801d2b3e2143f/flows.json +1 -0
  193. package/testflows/e7184b7ca4f07907/flows.json +1 -0
  194. package/testflows/ea246f68766c8630/flows.json +1 -0
  195. package/testflows/eb447048178f6e16/flows.json +201 -0
  196. package/testflows/ec921769b3c24fb6/flows.json +1 -0
  197. package/testflows/ed621e03921c13de/flows.json +1 -0
  198. package/testflows/eed68dbcecd1431f/flows.json +204 -0
  199. package/testflows/ef61f644d5436dbe/flows.json +1 -0
  200. package/testflows/f19fdae0c02b4f03/flows.json +1008 -0
  201. package/testflows/f1e71f2ccb34fd6e/flows.json +1 -0
  202. package/testflows/f2f61ec9fc46a468/flows.json +575 -0
  203. package/testflows/f346d45c81f595e5/flows.json +501 -0
  204. package/testflows/f38603a59963386c/flows.json +1 -0
  205. package/testflows/f4c4a57e77439a1b/flows.json +1 -0
  206. package/testflows/f5bdafa844f6d280/flows.json +1 -0
  207. package/testflows/f5f82ca50317fda7/flows.json +121 -0
  208. package/testflows/f8727464c799eb22/flows.json +1 -0
  209. package/testflows/f946aafaebb1398d/flows.json +160 -0
  210. package/testflows/f94db507552f4934/flows.json +183 -0
  211. package/testflows/fb50bac16667fc54/flows.json +364 -0
@@ -1,44 +1,74 @@
1
- module.exports = function(RED) {
1
+ module.exports = function (RED) {
2
2
  function CoreutassertsuccessFunctionality(config) {
3
- RED.nodes.createNode(this,config);
3
+ RED.nodes.createNode(this, config);
4
4
 
5
5
  var node = this;
6
6
  var cfg = config;
7
7
 
8
- node.on('close', function() {
8
+ let hasFailed = () => {
9
+ if (!cfg.msglimit) { cfg.msglimit = "==" }
10
+ let msgcnt = (node.context().get("msgcnt") || 0)
11
+
12
+ if (cfg.count == 0) { return msgcnt < 1 } // zero count means 1 and above, so a msgcnt of zero is only failure
13
+ else if (cfg.msglimit == "==") { return msgcnt != cfg.count }
14
+ else if (cfg.msglimit == ">=") { return msgcnt < cfg.count }
15
+ else if (cfg.msglimit == "<=") { return msgcnt > cfg.count }
16
+
17
+ return false
18
+ }
19
+
20
+ node.on('close', function (removed, done) {
21
+ if (removed) {
22
+ if ( hasFailed() ) {
23
+ RED.comms.publish("unittesting:testresults", {
24
+ flowid: node.z,
25
+ status: "failed"
26
+ })
27
+ node.status({ fill: "red", shape: "ring", text: RED._("ut-assert-success.label.failed") + `: ${cfg.count} ${cfg.msglimit} ${node.context().get("msgcnt") || 0}` });
28
+ // use node.log(..) here because node.error(..) sends a message to the debug
29
+ // panel but that errors out because the frontend can't find the workspace:
30
+ // Uncaught TypeError: can't access property "label", RED.nodes.workspace(...) is undefined
31
+ // that has follow-on effects.
32
+ // see https://nodered.org/docs/creating-nodes/node-js#logging-events for more details
33
+ node.log(`FAILED [${node.z}] assert success node failed: ${cfg.count} ${cfg.msglimit} ${node.context().get("msgcnt") || 0}`)
34
+ }
35
+ } else {
36
+ node.status({});
37
+ }
38
+
9
39
  node.context().set("msgcnt", 0)
10
- node.status({});
40
+ done();
11
41
  });
12
42
 
13
43
  /* msg handler, in this case pass the message on unchanged */
14
- node.on("input", function(msg, send, done) {
15
- let msgcnt = (node.context().get("msgcnt") || 0) + 1;
16
- node.context().set("msgcnt", msgcnt)
17
-
18
- // How to send a status update
19
- if ( (cfg.count || 1) == msgcnt) {
20
- node.status({ fill: "green", shape: "ring", text: RED._("ut-assert-success.label.succeed") });
21
- setTimeout(() => { node.status({}); }, 1000)
22
- } else {
23
- node.status({ fill: "red", shape: "ring", text: RED._("ut-assert-success.label.failed") + `: ${cfg.count} != ${msgcnt}`});
24
- }
25
-
26
- // Send a message and how to handle errors.
44
+ node.on("input", function (msg, send, done) {
45
+ let msgcnt = (node.context().get("msgcnt") || 0) + 1;
46
+ node.context().set("msgcnt", msgcnt)
47
+
48
+ // How to send a status update
49
+ if (!hasFailed()) {
50
+ node.status({ fill: "green", shape: "ring", text: RED._("ut-assert-success.label.succeed") });
51
+ setTimeout(() => { node.status({}); }, 1000)
52
+ } else {
53
+ // node.status({ fill: "red", shape: "ring", text: RED._("ut-assert-success.label.failed") + `: ${cfg.count} != ${msgcnt}` });
54
+ }
55
+
56
+ // Send a message and how to handle errors.
57
+ try {
27
58
  try {
28
- try {
29
- send(msg);
30
- done();
31
- } catch ( err ) {
32
- // use node.error if the node might send subsequent messages
33
- node.error("error occurred", { ...msg, error: err })
34
- done();
35
- }
59
+ send(msg);
60
+ done();
36
61
  } catch (err) {
37
- // use done if the node won't send anymore messages for the
38
- // message it received.
39
- msg.error = err
40
- done(err.message, msg)
62
+ // use node.error if the node might send subsequent messages
63
+ node.error("error occurred", { ...msg, error: err })
64
+ done();
41
65
  }
66
+ } catch (err) {
67
+ // use done if the node won't send anymore messages for the
68
+ // message it received.
69
+ msg.error = err
70
+ done(err.message, msg)
71
+ }
42
72
  });
43
73
  }
44
74
 
@@ -5,6 +5,14 @@ module.exports = function(RED) {
5
5
  var node = this;
6
6
  var cfg = config;
7
7
 
8
+
9
+ //
10
+ //
11
+ // Helper Code
12
+ //
13
+ //
14
+
15
+
8
16
  /*
9
17
  * Note to self: getMessageProperty(..) and getObjectProperty(...) only differ in that
10
18
  * getMessageProperty will remove any 'msg.' prefix from the property name. This is not
@@ -17,7 +25,6 @@ module.exports = function(RED) {
17
25
  * getObjectProperty will return undefined if a property isn't set.
18
26
  */
19
27
 
20
-
21
28
  var sendToDebug = (nde,rule,msgc,lvl) => {
22
29
  try {
23
30
  let msg = {
@@ -33,7 +40,15 @@ module.exports = function(RED) {
33
40
 
34
41
  msg = RED.util.encodeObject(msg);
35
42
  if (!cfg.ignore_failure_if_succeed) {
36
- RED.comms.publish("debug", msg);
43
+ // don't post debug, causes error in the editor because the flow does not
44
+ // exist in the workspace of the editor - flow is loaded in the backend only.
45
+ if (!msg._unittest_triggered) {
46
+ RED.comms.publish("debug", msg);
47
+ } else {
48
+ // send details to the console.
49
+ node.log(`ASSERT FAILURE [${node.z}] assert values failed`)
50
+ console.log(msg)
51
+ }
37
52
  }
38
53
  } catch (ex) {
39
54
  console.error(ex)
@@ -45,23 +60,61 @@ module.exports = function(RED) {
45
60
  node.status({ fill: "red", shape: "dot",
46
61
  text: RED._("ut-assert-values.label.unsupported", { property: JSON.stringify(rule) }) });
47
62
  sendToDebug(node, rule, msg, 30)
48
-
63
+
64
+ RED.comms.publish("unittesting:testresults", {
65
+ flowid: node.z,
66
+ status: "pending"
67
+ })
68
+
49
69
  return ["unsupported", rule]
50
70
  }
51
71
 
52
72
  var escapeSpecials = (str) => {
53
- return str ? str.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replaceAll(/\t/g, "\\t") : str
73
+ return (str && str.replace && (typeof str.replace == "function")) ? str.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replaceAll(/\t/g, "\\t") : str
54
74
  }
55
75
 
56
- node.on('close', function() {
57
- node.context().set("succeed", false)
58
- node.status({});
76
+ //
77
+ //
78
+ // Event Hander code
79
+ //
80
+ //
81
+
82
+ /* initialise and close handler - if removed is false, then this is an initailise */
83
+ node.on('close', function(removed, done) {
84
+ if (removed) {
85
+ if ((!node.context().get("succeed") && !cfg.ignore_failure_if_succeed) || !node.context().get("received_message")) {
86
+ RED.comms.publish("unittesting:testresults", {
87
+ flowid: node.z,
88
+ status: "failed"
89
+ })
90
+
91
+ node.status({ fill: "red", shape: "dot", text: "assert failed" })
92
+
93
+ // use node.log(..) here because node.error(..) sends a message to the debug
94
+ // panel but that errors out because the frontend can't find the workspace:
95
+ // Uncaught TypeError: can't access property "label", RED.nodes.workspace(...) is undefined
96
+ // that has follow-on effects.
97
+ // see https://nodered.org/docs/creating-nodes/node-js#logging-events for more details
98
+ if (!node.context().get("received_message")) {
99
+ node.log(`FAILED [${node.z}] Assert Values node not reached`)
100
+ } else {
101
+ node.log(`FAILED [${node.z}] Assert values node failed`)
102
+ }
103
+ }
104
+ } else {
105
+ node.status({});
106
+ node.context().set("succeed", false)
107
+ node.context().set("received_message", false)
108
+ }
109
+
110
+ done()
59
111
  });
60
112
 
61
113
  /* msg handler, in this case pass the message on unchanged */
62
114
  node.on("input", function(msg, send, done) {
63
115
  var failures = [];
64
116
  var unsupported = [];
117
+ node.context().set("received_message", true)
65
118
 
66
119
  try {
67
120
  cfg.rules.forEach(rule => {
@@ -75,8 +128,14 @@ module.exports = function(RED) {
75
128
  failures.push(sendToDebug(node, rule, msg, 20))
76
129
  }
77
130
  } else if ( rule.tot == "num") {
78
- if ( rule.to != RED.util.getObjectProperty(msg,rule.p) ) {
79
- failures.push(sendToDebug(node, rule, msg, 20))
131
+ if (rule.to == "NaN") {
132
+ if ( !isNaN(RED.util.getObjectProperty(msg, rule.p)) ) {
133
+ failures.push(sendToDebug(node, rule, msg, 20))
134
+ }
135
+ } else {
136
+ if ( rule.to != RED.util.getObjectProperty(msg,rule.p) ) {
137
+ failures.push(sendToDebug(node, rule, msg, 20))
138
+ }
80
139
  }
81
140
  } else if (rule.tot == "bin") {
82
141
  let expBuffer = Buffer.from(JSON.parse(rule.to));
@@ -90,17 +149,44 @@ module.exports = function(RED) {
90
149
  } else if (rule.to == "false" && !!RED.util.getObjectProperty(msg, rule.p) ) {
91
150
  failures.push(sendToDebug(node, rule, msg, 20))
92
151
  }
152
+ } else if (rule.tot == "jsonata") {
153
+ try {
154
+ let jsonExpr = RED.util.prepareJSONataExpression(rule.to, node);
155
+
156
+ RED.util.evaluateJSONataExpression(jsonExpr, msg, (err, value) => {
157
+ if (err) {
158
+ rule._err = err
159
+ failures.push(sendToDebug(node, rule, msg, 20))
160
+ } else {
161
+ if (value != escapeSpecials(RED.util.getObjectProperty(msg, rule.p))) {
162
+ rule._vt = escapeSpecials(RED.util.getObjectProperty(msg, rule.p))
163
+ failures.push(sendToDebug(node, rule, msg, 20))
164
+ }
165
+ }
166
+ });
167
+ } catch (e) {
168
+ rule._err = e
169
+ failures.push(sendToDebug(node, rule, msg, 20))
170
+ }
171
+
93
172
  } else if (rule.tot == "json") {
94
173
  let expObj = JSON.parse(rule.to)
95
174
  let oldObj = RED.util.getObjectProperty(msg, rule.p)
96
175
 
97
- if ( Array.isArray(expObj)) {
98
- if (JSON.stringify(oldObj) != JSON.stringify(expObj)) {
176
+ // special case: null or undefined
177
+ if (!expObj) {
178
+ if (oldObj != null && oldObj != undefined) {
99
179
  failures.push(sendToDebug(node, rule, msg, 20))
100
180
  }
101
181
  } else {
102
- if ( JSON.stringify(oldObj, Object.keys(oldObj).sort()) != JSON.stringify(expObj, Object.keys(expObj).sort()) ) {
103
- failures.push(sendToDebug(node, rule, msg, 20))
182
+ if ( Array.isArray(expObj)) {
183
+ if (JSON.stringify(oldObj) != JSON.stringify(expObj)) {
184
+ failures.push(sendToDebug(node, rule, msg, 20))
185
+ }
186
+ } else {
187
+ if ( JSON.stringify(oldObj, Object.keys(oldObj).sort()) != JSON.stringify(expObj, Object.keys(expObj).sort()) ) {
188
+ failures.push(sendToDebug(node, rule, msg, 20))
189
+ }
104
190
  }
105
191
  }
106
192
  } else if (rule.tot == "msg") {
@@ -137,16 +223,37 @@ module.exports = function(RED) {
137
223
  unsupported.push(postUnsupported(rule,msg))
138
224
  }
139
225
  /*
140
- * Rule is not equal
226
+ * Rule is not equal - both value are msg properties
141
227
  */
142
228
  } else if (rule.t == "noteql" && rule.pt == "msg" && rule.tot == "msg") {
143
- /* comparing two values on the message object */
144
229
  let expObj = RED.util.getObjectProperty(msg, rule.to)
145
230
  let oldObj = RED.util.getObjectProperty(msg, rule.p)
146
231
  if (expObj == oldObj) {
147
232
  failures.push(sendToDebug(node, rule, msg, 20))
148
233
  }
149
234
  /*
235
+ * Rule is not equal - comparing message property to string value
236
+ */
237
+ } else if (rule.t == "noteql" && rule.pt == "msg" && rule.tot == "str") {
238
+ let expValue = rule.to
239
+ let msgValue = RED.util.getObjectProperty(msg, rule.p)
240
+ if (expValue == escapeSpecials(msgValue)) {
241
+ rule._vt = escapeSpecials(msgValue)
242
+ failures.push(sendToDebug(node, rule, msg, 20))
243
+ }
244
+
245
+ /*
246
+ * Rule is not equal - comparing message property to number value
247
+ */
248
+ } else if (rule.t == "noteql" && rule.pt == "msg" && rule.tot == "num") {
249
+ let expValue = rule.to
250
+ let msgValue = RED.util.getObjectProperty(msg, rule.p)
251
+ if (expValue == msgValue) {
252
+ rule._vt = msgValue
253
+ failures.push(sendToDebug(node, rule, msg, 20))
254
+ }
255
+
256
+ /*
150
257
  * Other rule types are not supported
151
258
  */
152
259
  } else {
@@ -161,7 +268,7 @@ module.exports = function(RED) {
161
268
  if (failures.length > 0 ) {
162
269
  node.status({fill: "red", shape: "dot", text: "assert failed"})
163
270
  msg.assert_succeed = false
164
- msg.assert_failures = failures.concat(unsupported)
271
+ msg.assert_failures = failures.concat(unsupported)
165
272
  } else {
166
273
  if ( unsupported.length > 0) {
167
274
  node.status({ fill: "yellow", shape: "ring", text: "unsupported errors - check debug" })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gregoriusrippenstein/erlang-red-unittest",
3
- "version": "0.12.4",
3
+ "version": "0.15.0",
4
4
  "dependencies": {
5
5
  },
6
6
 
@@ -72,7 +72,7 @@
72
72
  }
73
73
 
74
74
  $.get({
75
- url: "/UnitTesting/tests.json?cb=" + new Date().getTime(),
75
+ url: "UnitTesting/tests.json?cb=" + new Date().getTime(),
76
76
  }).done((resp) => {
77
77
  handleResponse(resp)
78
78
  }).fail((e) => {
@@ -92,7 +92,7 @@ function doFlowImportForSidebarUnittesting(flowid) {
92
92
  });
93
93
 
94
94
  $.get({
95
- url: "/UnitTesting/" + flowid + "/retrieve?cb=" + new Date().getTime(),
95
+ url: "UnitTesting/" + flowid + "/retrieve?cb=" + new Date().getTime(),
96
96
  headers: {
97
97
  }
98
98
  }).done((e, d) => {
@@ -169,6 +169,7 @@ function resetTestResultsForFlowId(dirList,flowid) {
169
169
 
170
170
  function removeTestResultsForFlow(dirList,listid) {
171
171
  dirList.treeList('select', listid)
172
+ $($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).data("status", "waiting")
172
173
  $($($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).find('i')).prop('class', 'fa fa-minus').css('color', '')
173
174
  }
174
175
 
@@ -180,9 +181,12 @@ function removeAllTestResults(dirList) {
180
181
  })
181
182
  }
182
183
 
183
- function highlightTestResult(dirList, flowid, status) {
184
+ function currentStatusIsWaiting(dirList, flowid) {
184
185
  dirList.treeList('select', `flowid-treelist-${flowid}`);
186
+ return $($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).data("status") == "waiting"
187
+ }
185
188
 
189
+ function highlightTestResult(dirList, flowid, status) {
186
190
  let clr = "green"
187
191
  let shp = "fa-check"
188
192
 
@@ -195,10 +199,20 @@ function highlightTestResult(dirList, flowid, status) {
195
199
  clr = "red";
196
200
  shp = "fa-remove";
197
201
  break;
202
+ case "waiting":
203
+ clr = "";
204
+ shp = "fa-minus";
205
+ break;
198
206
  }
199
207
 
200
- $($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).data("status", status)
201
- $($($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).find('i')).prop('class', "fa " + shp).css('color', clr)
208
+ dirList.treeList('select', `flowid-treelist-${flowid}`);
209
+ if ($($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).data("status") != status) {
210
+ $($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).data("status", status)
211
+ $($($(dirList.treeList('selected').treeList.container).find('.red-ui-treeList-icon')).find('i')).prop('class', "fa " + shp).css('color', clr)
212
+ return true
213
+ } else {
214
+ return false
215
+ }
202
216
  }
203
217
 
204
218
  function clearAllNodeStatus() {
@@ -248,9 +262,15 @@ function runTestForFlowId(flowid,dirList=undefined) {
248
262
  } else {
249
263
  params = `${params}&testpend=false`
250
264
  }
251
-
265
+
266
+ // reveal tab with the test flow if it's in the editor
267
+ if (RED.nodes.workspace(flowid)) {
268
+ RED.notify("Switching to test tab", { type: "warning" });
269
+ RED.view.reveal(flowid)
270
+ }
271
+
252
272
  $.get({
253
- url: `/UnitTesting/${flowid}/runtest?${params}`
273
+ url: `UnitTesting/${flowid}/runtest?${params}`
254
274
  }).done((resp) => {
255
275
  RED.notify(`Triggered test run for ${flowid}`, "success")
256
276
  $('#node-input-unittestingpull-testresults-row').find(".todo").html(resp.todo)
@@ -285,7 +305,7 @@ function triggerInjectsInWorkspace() {
285
305
 
286
306
  function sendUnittestngHalt() {
287
307
  $.get({
288
- url: `/UnitTesting/halt?cb=${new Date().getTime()}`
308
+ url: `UnitTesting/halt?cb=${new Date().getTime()}`
289
309
  }).done((resp) => {
290
310
  RED.notify(`Halt send successfully`, "success")
291
311
  RED.events.emit('unittesting:server-restarted')
@@ -302,7 +322,12 @@ function resetTestResultsRow() {
302
322
  $('#node-input-unittestingpull-testresults-row').find(d).html("0")
303
323
  })
304
324
  }
305
- function runAllTests(dirList) {
325
+
326
+ function runSubsetOfTests(dirList, testIds) {
327
+ runAllTests(dirList, testIds.join(","))
328
+ }
329
+
330
+ function runAllTests(dirList, withLimit) {
306
331
  if (RED.comms.isConnected && !RED.comms.isConnected()) {
307
332
  return RED.notify("Not connected to server, websocket down", "error")
308
333
  }
@@ -325,8 +350,13 @@ function runAllTests(dirList) {
325
350
  params = `${params}&testpend=false`
326
351
  }
327
352
 
353
+ // all with limit of specific tests.
354
+ if (withLimit) {
355
+ params = `${params}&limit=${withLimit}`
356
+ }
357
+
328
358
  $.get({
329
- url: `/UnitTesting/all/runtest?${params}`
359
+ url: `UnitTesting/all/runtest?${params}`
330
360
  }).done((resp) => {
331
361
  RED.notify(`${resp.todo} tests have been triggered`, "success")
332
362
  $('#node-input-unittestingpull-testresults-row').find(".todo").html(resp.todo)
@@ -413,7 +443,6 @@ var dirList = $("#node-input-unittestingpull-sb-target-container-div").css({
413
443
  }
414
444
  });
415
445
 
416
-
417
446
  var search = $("#node-input-unittestingpull-sb-target-filter").searchBox({
418
447
  style: "compact",
419
448
  delay: 300,
@@ -438,7 +467,8 @@ var search = $("#node-input-unittestingpull-sb-target-filter").searchBox({
438
467
  });
439
468
  } else if (val == "is:untested" || val == "is:todo") {
440
469
  count = dirList.treeList("filter", function (item) {
441
- return !$($(item.treeList.container).find('.red-ui-treeList-icon')).data("status")
470
+ return ( $($(item.treeList.container).find('.red-ui-treeList-icon')).data("status") == "waiting" ||
471
+ $($(item.treeList.container).find('.red-ui-treeList-icon')).data("status") == "")
442
472
  });
443
473
  } else if (val == "is:tested") {
444
474
  count = dirList.treeList("filter", function (item) {
@@ -465,7 +495,7 @@ $('#node-input-unittestingpull-sb-test-flow-but').on('click', function (e) {
465
495
  if ( sltd.flowid) {
466
496
  runTestForFlowId(sltd.flowid,dirList)
467
497
  } else if (sltd.children) {
468
- sltd.children.map( d => d.flowid ).map( d => runTestForFlowId(d,dirList))
498
+ runSubsetOfTests(dirList, sltd.children.map(d => d.flowid))
469
499
  }
470
500
  })
471
501
 
@@ -479,7 +509,6 @@ $('#node-input-unittestingpull-sb-test-workspace-but').on('click', function (e)
479
509
  testCurrentWorkspace()
480
510
  })
481
511
 
482
-
483
512
  let handleTestResult = (event, data) => {
484
513
  if (data.flowid) {
485
514
  if ( data.status == "unknown_testcase") {
@@ -490,24 +519,41 @@ let handleTestResult = (event, data) => {
490
519
  return
491
520
  }
492
521
 
493
- RED.notify("Test result for flowid " + data.flowid + ": " + data.status, {
494
- type: data.status == "failed" ? "error" : (data.status == "pending" ? "warning" : "success"),
495
- timeout: (data.status == "failed" || data.status == "pending") ? 3000 : 2000
496
- });
497
-
498
- // update the test results row
499
- let v = parseInt($("#node-input-unittestingpull-testresults-row").find(".todo").html());
500
- if ( v > 0 ) {
501
- $("#node-input-unittestingpull-testresults-row").find(".todo").html(`${v - 1}`)
522
+ if ( data.status == "stopped") {
523
+ handledStoppedStatus(data)
524
+ return
502
525
  }
503
- v = parseInt($("#node-input-unittestingpull-testresults-row").find("."+data.status).html());
504
- $("#node-input-unittestingpull-testresults-row").find("." + data.status).html(`${v+1}`)
505
- v = parseInt($("#node-input-unittestingpull-testresults-row").find(".total").html());
506
- $("#node-input-unittestingpull-testresults-row").find(".total").html(`${v + 1}`)
507
526
 
508
- highlightTestResult(dirList, data.flowid, data.status);
527
+ if (highlightTestResult(dirList, data.flowid, data.status)) {
528
+ RED.notify("Test result for flowid " + data.flowid + ": " + data.status, {
529
+ type: data.status == "failed" ? "error" : (data.status == "pending" ? "warning" : "success"),
530
+ timeout: (data.status == "failed" || data.status == "pending") ? 3000 : 2000
531
+ });
532
+
533
+ // update the test results row
534
+ let v = parseInt($("#node-input-unittestingpull-testresults-row").find(".todo").html());
535
+ if ( v > 0 ) {
536
+ $("#node-input-unittestingpull-testresults-row").find(".todo").html(`${v - 1}`)
537
+ }
538
+
539
+ v = parseInt($("#node-input-unittestingpull-testresults-row").find("."+data.status).html());
540
+ $("#node-input-unittestingpull-testresults-row").find("." + data.status).html(`${v+1}`)
541
+ v = parseInt($("#node-input-unittestingpull-testresults-row").find(".total").html());
542
+ $("#node-input-unittestingpull-testresults-row").find(".total").html(`${v + 1}`)
543
+ }
544
+ }
545
+ }
546
+
547
+ // special handler that first checks whether there has already
548
+ // been a result (failed or succeed) for a flowid. If yes, then
549
+ // ignore this event. If not, the assume it was a success event.
550
+ let handledStoppedStatus = (data) => {
551
+ if (currentStatusIsWaiting(dirList, data.flowid)) {
552
+ data.status = "success"
553
+ handleTestResult(undefined, data)
509
554
  }
510
555
  }
556
+
511
557
  RED.comms.subscribe('unittesting:testresults', handleTestResult);
512
558
 
513
559
  $('#node-input-unittestingpull-expand-all-but').on('click', function (e) {
@@ -586,6 +632,56 @@ $('#node-input-unittestingpull-testresults-row').on('click', 'span.filtrg', (e)
586
632
  }
587
633
  })
588
634
 
635
+ //
636
+ // Select one and select all buttons
637
+ //
638
+ $('#node-input-unittestingselect-one-test-node').on('click', (e) => {
639
+ if (e) e.preventDefault();
640
+
641
+ let sltd = dirList.treeList('selected')
642
+
643
+ if (sltd.flowid) {
644
+ let nodeIds = RED.search.search(`${sltd.flowid}/flows.json flow:current`).map(d => d.node.id)
645
+
646
+ let nde = RED.nodes.node(nodeIds[0])
647
+ var ndeid = nde.id
648
+
649
+ RED.workspaces.show(nde.z, false, false, true);
650
+ RED.view.select({ nodes: nodeIds.map(n => RED.nodes.node(n)) })
651
+
652
+ setTimeout(() => {
653
+ RED.view.reveal(ndeid, true);
654
+ RED.view.redraw();
655
+ }, 38);
656
+ } else if (sltd.children) {
657
+
658
+ let slNodes = sltd.children.map(d => d.flowid).map(d =>
659
+ RED.search.search(`${d}/flows.json flow:current`).map(srchResult => srchResult.node.id)
660
+ ).flat()
661
+
662
+ RED.view.select({ nodes: slNodes.map(n => RED.nodes.node(n)) })
663
+ }
664
+ })
665
+
666
+ $('#node-input-unittestingselect-test-node').on('click', (e) => {
667
+ if (e) e.preventDefault();
668
+
669
+ let sltd = dirList.treeList('selected')
670
+
671
+ if (sltd.flowid) {
672
+ let nodeIds = RED.search.search(`${sltd.flowid}/flows.json flow:current`).map(d => d.node.id)
673
+ let currSelection = (RED.view.selection().nodes || []).map(d => d.id)
674
+
675
+ RED.view.select({ nodes: nodeIds.concat(currSelection).map(n => RED.nodes.node(n)) })
676
+ } else if (sltd.children) {
677
+
678
+ let slNodes = sltd.children.map(d => d.flowid).map(d =>
679
+ RED.search.search(`${d}/flows.json flow:current`).map(srchResult => srchResult.node.id)
680
+ ).flat().concat((RED.view.selection().nodes || []).map(d => d.id))
681
+
682
+ RED.view.select({ nodes: slNodes.map(n => RED.nodes.node(n)) })
683
+ }
684
+ })
589
685
  };
590
686
 
591
687
  RED.events.on('runtime-state', initialiseConfigNodeOnce);
@@ -672,6 +768,13 @@ $('#node-input-unittestingpull-testresults-row').on('click', 'span.filtrg', (e)
672
768
  <button id="node-input-unittestingpull-clear-debug-panel-but"
673
769
  class="red-ui-button">Clear Debug Panel</button>
674
770
  </div>
771
+
772
+ <div class="form-row" style="margin-left: 10px;">
773
+ <button id="node-input-unittestingselect-test-node"
774
+ class="red-ui-button">Select All</button>
775
+ <button id="node-input-unittestingselect-one-test-node"
776
+ class="red-ui-button">Select One</button>
777
+ </div>
675
778
  </div>
676
779
 
677
780
  <!--func-unittesting-tab-compare#-->
@@ -0,0 +1 @@
1
+ [{"id":"01b074cfa6ae8818","type":"tab","label":"[complete] link nodes","disabled":false,"info":"A complete node can listen to link in, out and link call nodes.\n\nIn this case it should receive three messages.\n","env":[{"name":"ERED_PENDING","type":"bool","value":"false"}]},{"id":"bac358bb4dcf839a","type":"inject","z":"01b074cfa6ae8818","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"inject","payloadType":"str","x":602,"y":715,"wires":[["7263e1b679f88c0d"]]},{"id":"5c099ed442ea1955","type":"complete","z":"01b074cfa6ae8818","name":"","scope":["7263e1b679f88c0d","ecdfec4178d1a018","d3f1880457be0207"],"uncaught":false,"x":821,"y":459,"wires":[["d4e6c75a8c71a713"]]},{"id":"7263e1b679f88c0d","type":"link call","z":"01b074cfa6ae8818","name":"link call node","links":["d3f1880457be0207"],"linkType":"static","timeout":"30","x":851,"y":588,"wires":[[]]},{"id":"d3f1880457be0207","type":"link in","z":"01b074cfa6ae8818","name":"link in node","links":[],"x":383,"y":337,"wires":[["e401dd1507dfd07d"]]},{"id":"e401dd1507dfd07d","type":"change","z":"01b074cfa6ae8818","name":"","rules":[{"p":"payload","pt":"msg","t":"set","to":"change","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":504,"y":531,"wires":[["ecdfec4178d1a018"]]},{"id":"ecdfec4178d1a018","type":"link out","z":"01b074cfa6ae8818","name":"link out node","mode":"return","links":[],"x":629,"y":330,"wires":[]},{"id":"d4e6c75a8c71a713","type":"ut-assert-success","z":"01b074cfa6ae8818","name":"","count":"3","x":1125,"y":493,"wires":[]}]
@@ -0,0 +1 @@
1
+ [{"id":"02b18fc0ed9de178","type":"tab","label":"[split] parts id is identical","disabled":false,"info":"## When splitting, ensure parts id is the same\n\nSomething that is required.","env":[]},{"id":"5d723f444ea5d562","type":"inject","z":"02b18fc0ed9de178","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[1,2,3,4,5,6]","payloadType":"json","x":214,"y":637,"wires":[["3d93c04bfb48f434"]]},{"id":"3d93c04bfb48f434","type":"split","z":"02b18fc0ed9de178","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","property":"payload","x":933,"y":639,"wires":[["e320d71438e7a66b"]]},{"id":"e320d71438e7a66b","type":"join","z":"02b18fc0ed9de178","name":"","mode":"custom","build":"array","property":"","propertyType":"full","key":"topic","joiner":"\\n","joinerType":"str","useparts":true,"accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":1039,"y":722.75,"wires":[["f342e7d69d9cd39c"]]},{"id":"f342e7d69d9cd39c","type":"change","z":"02b18fc0ed9de178","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"$map($$.payload, function($v) { $v.parts.id })","tot":"jsonata"},{"t":"set","p":"cnt","pt":"msg","to":"$count($$.payload)","tot":"jsonata"},{"t":"set","p":"uniqcnt","pt":"msg","to":"$count($distinct($$.payload))","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1147,"y":806.5,"wires":[["f8e1f0d0081c4083"]]},{"id":"f8e1f0d0081c4083","type":"ut-assert-values","z":"02b18fc0ed9de178","name":"","ignore_failure_if_succeed":false,"rules":[{"t":"eql","p":"cnt","pt":"msg","to":"6","tot":"num"},{"t":"eql","p":"uniqcnt","pt":"msg","to":"1","tot":"num"}],"x":1833,"y":806.5,"wires":[[]]}]
@@ -0,0 +1 @@
1
+ [{"id":"0616f795a4aee63e","type":"tab","label":"[switch] working JSONata expression operator","disabled":false,"info":"## JSONata expression operator\n\nFrom the documentation:\n\n```\nA JSONata Expression can be provided that will be evaluated against the whole message and will match if the expression returns a true value.\n```\n\nSo the JSONata expression isn't matched to the value, rather it is independently evaluated and must be \"true\".","env":[]},{"id":"7b2ff55b624bab63","type":"switch","z":"0616f795a4aee63e","name":"check all tests","property":"$match($$.payload, /([0-9]+)([a-z]+)([0-9]+)([a-z]+)/,1).match","propertyType":"jsonata","rules":[{"t":"eq","v":"1a2b","vt":"str"},{"t":"eq","v":"\"1\" & \"a\" & \"2\" & \"b\"","vt":"jsonata"},{"t":"true"},{"t":"false"},{"t":"null"},{"t":"empty"},{"t":"nempty"},{"t":"jsonata_exp","v":"$not($not($match($$.payload, /([0-9]+)([a-z]+)([0-9]+)([a-z]+)/,1).match))","vt":"jsonata"},{"t":"nnull"},{"t":"eq","v":"$match($$.payload, /([0-9]+)([a-z]+)([0-9]+)([a-z]+)/,1).match","vt":"jsonata"}],"checkall":"true","repair":false,"outputs":10,"x":1177.1429443359375,"y":857.1428833007812,"wires":[["55d320dfa24df906"],["a08754bfaa13fd5e"],["a6277f760cc8d172"],["40843133c4c3af77"],["dc8df12172b71817"],["81a5c6e674791b89"],["4a1ec4d64791c881"],["63ac80803f5e8cb7"],["6f412a90d907aa81"],["72f30e6f13890db4"]]},{"id":"79f038dd2f630094","type":"inject","z":"0616f795a4aee63e","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1a2b3c","payloadType":"str","x":888.1429443359375,"y":644.1428833007812,"wires":[["7b2ff55b624bab63","bf1d2302c227bea5"]]},{"id":"a6277f760cc8d172","type":"ut-assert-failure","z":"0616f795a4aee63e","name":"","x":1497.142936706543,"y":719.6428527832031,"wires":[]},{"id":"40843133c4c3af77","type":"ut-assert-failure","z":"0616f795a4aee63e","name":"","x":1497.142936706543,"y":784.4642791748047,"wires":[]},{"id":"81a5c6e674791b89","type":"ut-assert-failure","z":"0616f795a4aee63e","name":"","x":1497.142936706543,"y":914.1071319580078,"wires":[]},{"id":"bf1d2302c227bea5","type":"change","z":"0616f795a4aee63e","name":"","rules":[{"t":"set","p":"value","pt":"msg","to":"$match($$.payload, /([0-9]+)([a-z]+)([0-9]+)([a-z]+)/,1).match","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":1177.1429443359375,"y":458.5714416503906,"wires":[["0ce56b7fd4af2f76"]]},{"id":"a08754bfaa13fd5e","type":"ut-assert-success","z":"0616f795a4aee63e","name":"","count":1,"x":1497.142936706543,"y":654.8214263916016,"wires":[]},{"id":"55d320dfa24df906","type":"ut-assert-success","z":"0616f795a4aee63e","name":"","count":1,"x":1497.142936706543,"y":590,"wires":[]},{"id":"4a1ec4d64791c881","type":"ut-assert-success","z":"0616f795a4aee63e","name":"","count":1,"x":1497.142936706543,"y":978.9285583496094,"wires":[]},{"id":"6f412a90d907aa81","type":"ut-assert-success","z":"0616f795a4aee63e","name":"","count":1,"x":1497.142936706543,"y":1108.5714111328125,"wires":[]},{"id":"63ac80803f5e8cb7","type":"ut-assert-success","z":"0616f795a4aee63e","name":"","count":1,"x":1497.142936706543,"y":1043.749984741211,"wires":[]},{"id":"dc8df12172b71817","type":"ut-assert-failure","z":"0616f795a4aee63e","name":"","x":1497.142936706543,"y":849.2857055664062,"wires":[]},{"id":"0ce56b7fd4af2f76","type":"ut-assert-values","z":"0616f795a4aee63e","name":"","ignore_failure_if_succeed":false,"rules":[{"t":"eql","p":"value","pt":"msg","to":"1a2b","tot":"str"}],"x":1507.142936706543,"y":458.5714416503906,"wires":[[]]},{"id":"72f30e6f13890db4","type":"ut-assert-success","z":"0616f795a4aee63e","name":"","count":1,"x":1498.571533203125,"y":1164.2857666015625,"wires":[]}]