From b1daa8932a2f097e643042afdfaea765b954666c Mon Sep 17 00:00:00 2001
From: "andrew.greene"
Date: Wed, 8 Dec 2021 18:01:31 -0700
Subject: [PATCH] Remove known unused files
---
.gitignore | 1 +
SECURITY.md | 5 -
.../nodes/core/common/20-inject.html | 711 ------
.../@node-red/nodes/core/common/20-inject.js | 177 --
.../@node-red/nodes/core/common/21-debug.html | 513 ----
.../@node-red/nodes/core/common/21-debug.js | 297 ---
.../nodes/core/common/24-complete.html | 154 --
.../nodes/core/common/24-complete.js | 31 -
.../@node-red/nodes/core/common/25-catch.html | 191 --
.../@node-red/nodes/core/common/25-catch.js | 32 -
.../nodes/core/common/25-status.html | 177 --
.../@node-red/nodes/core/common/25-status.js | 31 -
.../@node-red/nodes/core/common/60-link.html | 340 ---
.../@node-red/nodes/core/common/60-link.js | 132 -
.../nodes/core/common/98-unknown.html | 23 -
.../@node-red/nodes/core/common/98-unknown.js | 23 -
.../nodes/core/function/10-function.html | 609 -----
.../nodes/core/function/10-function.js | 507 ----
.../nodes/core/function/10-switch.html | 440 ----
.../nodes/core/function/10-switch.js | 521 ----
.../nodes/core/function/15-change.html | 367 ---
.../nodes/core/function/15-change.js | 357 ---
.../nodes/core/function/16-range.html | 70 -
.../@node-red/nodes/core/function/16-range.js | 55 -
.../nodes/core/function/80-template.html | 155 --
.../nodes/core/function/80-template.js | 200 --
.../nodes/core/function/89-delay.html | 283 ---
.../@node-red/nodes/core/function/89-delay.js | 424 ----
.../nodes/core/function/89-trigger.html | 234 --
.../nodes/core/function/89-trigger.js | 298 ---
.../nodes/core/function/90-exec.html | 113 -
.../@node-red/nodes/core/function/90-exec.js | 200 --
.../@node-red/nodes/core/function/rbe.html | 106 -
.../@node-red/nodes/core/function/rbe.js | 97 -
.../@node-red/nodes/core/network/05-tls.html | 197 --
.../@node-red/nodes/core/network/05-tls.js | 118 -
.../nodes/core/network/06-httpproxy.html | 129 -
.../nodes/core/network/06-httpproxy.js | 33 -
.../@node-red/nodes/core/network/10-mqtt.html | 908 -------
.../@node-red/nodes/core/network/10-mqtt.js | 1139 ---------
.../nodes/core/network/21-httpin.html | 273 --
.../@node-red/nodes/core/network/21-httpin.js | 356 ---
.../nodes/core/network/21-httprequest.html | 249 --
.../nodes/core/network/21-httprequest.js | 673 -----
.../nodes/core/network/22-websocket.html | 288 ---
.../nodes/core/network/22-websocket.js | 415 ---
.../nodes/core/network/31-tcpin.html | 277 --
.../@node-red/nodes/core/network/31-tcpin.js | 719 ------
.../@node-red/nodes/core/network/32-udp.html | 231 --
.../@node-red/nodes/core/network/32-udp.js | 280 ---
.../@node-red/nodes/core/network/lib/mqtt.js | 257 --
.../@node-red/nodes/core/parsers/70-CSV.html | 125 -
.../@node-red/nodes/core/parsers/70-CSV.js | 319 ---
.../@node-red/nodes/core/parsers/70-HTML.html | 64 -
.../@node-red/nodes/core/parsers/70-HTML.js | 90 -
.../@node-red/nodes/core/parsers/70-JSON.html | 62 -
.../@node-red/nodes/core/parsers/70-JSON.js | 134 -
.../@node-red/nodes/core/parsers/70-XML.html | 49 -
.../@node-red/nodes/core/parsers/70-XML.js | 49 -
.../@node-red/nodes/core/parsers/70-YAML.html | 37 -
.../@node-red/nodes/core/parsers/70-YAML.js | 41 -
.../nodes/core/sequence/17-split.html | 325 ---
.../@node-red/nodes/core/sequence/17-split.js | 785 ------
.../nodes/core/sequence/18-sort.html | 119 -
.../@node-red/nodes/core/sequence/18-sort.js | 266 --
.../nodes/core/sequence/19-batch.html | 170 --
.../@node-red/nodes/core/sequence/19-batch.js | 311 ---
.../@node-red/nodes/core/storage/10-file.html | 347 ---
.../@node-red/nodes/core/storage/10-file.js | 401 ---
.../nodes/core/storage/23-watch.html | 53 -
.../@node-red/nodes/core/storage/23-watch.js | 95 -
.../debug/01 - Output payload value.json | 1 -
.../debug/02 - Output complete message.json | 1 -
.../common/debug/03 - Output to console.json | 1 -
.../debug/04 - Output to node status.json | 1 -
.../05 - Formatting output using JSONata.json | 1 -
.../common/link/01 - Link within a tab.json | 1 -
.../change/02 - Set any property value.json | 1 -
.../change/03 - Set value using JSONata.json | 1 -
.../change/04 - Set value from env var.json | 1 -
.../change/05 - Set flow context.json | 1 -
.../function/delay/01 - Delay message.json | 1 -
...2 - Delay message by message property.json | 1 -
.../03 - Reset or flush pending message.json | 1 -
...5 - Limit message rate for each topic.json | 1 -
...standard output from external command.json | 1 -
...et error output from external command.json | 1 -
...02 - Scale input and round to integer.json | 1 -
.../function/range/03 - Limit input.json | 1 -
.../range/04 - Scale and wrap input.json | 1 -
.../function/switch/02 - Check all rules.json | 1 -
.../switch/03 - Stop after first match.json | 1 -
.../04 - Select output port by type.json | 1 -
.../05 - Use JSONata for switch rule.json | 1 -
.../06 - Use JSONata for switch value.json | 1 -
.../template/01 - Use mustache syntax.json | 1 -
.../template/02 - Parse result as JSON.json | 1 -
.../template/03 - Parse result as YAML.json | 1 -
.../01 - Outputs two value with interval.json | 1 -
.../http/03 - Handle URL parameters.json | 135 -
.../http/06 - Post file to a flow.json | 126 -
.../tcp/01 - Connect to TCP out server.json | 92 -
.../tcp/02 - Connect to TCP in server.json | 92 -
...end reply to client of TCP connection.json | 174 --
...01 - Transfer data using UDP protocol.json | 92 -
.../01 - Connect to websocket in server.json | 96 -
.../02 - Connect to websocket out server.json | 96 -
...fault column name as message sequence.json | 99 -
...CSV with default column name as array.json | 99 -
...ified column name as message sequence.json | 99 -
...name in first row as message sequence.json | 99 -
...05 - Convert JavaScript object to CSV.json | 99 -
...06 - Convert JavaScript object to CSV.json | 99 -
...bjects to CSV with column name header.json | 99 -
...Specify column names in input message.json | 126 -
...d column name when reset property set.json | 200 --
...array of HTML element by CSS selector.json | 94 -
...uence of HTML element by CSS selector.json | 94 -
... by CSS selector specified in message.json | 121 -
...vert JSON string to JavaScript object.json | 92 -
...vert JavaScript object to JSON string.json | 92 -
.../json/03 - Validate input JSON string.json | 160 --
...01 - Convert JavaScript object to XML.json | 92 -
...02 - Convert XML to JavaScript object.json | 92 -
...rol conversion using options property.json | 119 -
...1 - Convert JavaScript object to YAML.json | 90 -
...2 - Convert YAML to JavaScript object.json | 90 -
.../sort/01 - Sort array payload.json | 1 -
.../sort/02 - Sort message sequence.json | 1 -
.../split/01 - Split message payload.json | 1 -
.../file-in/01 - Read string from a file.json | 113 -
.../02 - Read data in specified encoding.json | 113 -
...ead data breaking lines into messages.json | 132 -
.../file/01 - Write string to a file.json | 113 -
...tring to a file specified by property.json | 118 -
.../storage/file/03 - Delete a file.json | 85 -
...04 - Specify encoding of written data.json | 113 -
.../watch/01 - Watch change of a file.json | 108 -
test/editor/editor_helper.js | 150 --
.../pageobjects/editor/debugTab_page.js | 40 -
.../editor/pageobjects/editor/palette_page.js | 62 -
.../pageobjects/editor/workspace_page.js | 101 -
.../nodes/core/common/20-inject_page.js | 80 -
.../nodes/core/common/21-debug_page.js | 43 -
.../nodes/core/common/24-complete_page.js | 47 -
.../nodes/core/common/25-catch_page.js | 48 -
.../nodes/core/common/25-status_page.js | 48 -
.../nodes/core/common/90-comment_page.js | 27 -
.../nodes/core/function/10-function_page.js | 41 -
.../nodes/core/function/10-switch_page.js | 234 --
.../nodes/core/function/15-change_page.js | 132 -
.../nodes/core/function/16-range_page.js | 38 -
.../nodes/core/function/80-template_page.js | 48 -
.../nodes/core/function/89-delay_page.js | 31 -
.../nodes/core/function/89-trigger_page.js | 83 -
.../nodes/core/function/90-exec_page.js | 37 -
.../nodes/core/network/10-mqtt_page.js | 74 -
.../nodes/core/network/21-httpin_page.js | 35 -
.../nodes/core/network/21-httprequest_page.js | 39 -
.../core/network/21-httpresponse_page.js | 27 -
.../nodes/core/network/22-websocket_page.js | 93 -
.../nodes/core/parsers/70-CSV_page.js | 51 -
.../nodes/core/parsers/70-HTML_page.js | 31 -
.../nodes/core/parsers/70-JSON_page.js | 35 -
.../nodes/core/parsers/70-XML_page.js | 35 -
.../nodes/core/parsers/70-YAML_page.js | 35 -
.../nodes/core/sequence/17-split_page.js | 47 -
.../nodes/core/sequence/19-batch_page.js | 39 -
.../nodes/core/storage/10-filein_page.js | 44 -
test/editor/pageobjects/nodes/node_page.js | 51 -
.../pageobjects/nodes/nodefactory_page.js | 94 -
test/editor/pageobjects/util/key_page.js | 55 -
.../editor/pageobjects/util/spec_util_page.js | 23 -
test/editor/pageobjects/util/util_page.js | 84 -
test/editor/specs/editor/workspace_uispec.js | 55 -
.../scenario/cookbook_dataformats_uispec.js | 364 ---
.../scenario/cookbook_errorhandling_uispec.js | 74 -
.../scenario/cookbook_flowcontrol_uispec.js | 81 -
.../scenario/cookbook_httpendpoints_uispec.js | 572 -----
.../scenario/cookbook_httprequests_uispec.js | 300 ---
.../scenario/cookbook_messages_uispec.js | 142 --
.../specs/scenario/cookbook_mqtt_uispec.js | 224 --
test/editor/wdio.conf.js | 338 ---
test/node_modules/nr-test-utils/index.js | 31 -
test/node_modules/nr-test-utils/package.json | 6 -
test/nodes/core/common/20-inject_spec.js | 669 -----
test/nodes/core/common/21-debug_spec.js | 659 -----
test/nodes/core/common/25-catch_spec.js | 44 -
test/nodes/core/common/25-status_spec.js | 54 -
test/nodes/core/common/60-link_spec.js | 187 --
test/nodes/core/common/90-comment_spec.js | 36 -
test/nodes/core/common/98-unknown_spec.js | 36 -
test/nodes/core/function/10-function_spec.js | 1721 -------------
test/nodes/core/function/10-switch_spec.js | 1153 ---------
test/nodes/core/function/15-change_spec.js | 1911 --------------
test/nodes/core/function/16-range_spec.js | 152 --
test/nodes/core/function/80-template_spec.js | 498 ----
test/nodes/core/function/89-delay_spec.js | 1004 --------
test/nodes/core/function/89-trigger_spec.js | 1198 ---------
test/nodes/core/function/90-exec_spec.js | 973 --------
test/nodes/core/function/rbe_spec.js | 538 ----
.../nodes/core/network/21-httprequest_spec.js | 2221 -----------------
test/nodes/core/network/22-websocket_spec.js | 568 -----
test/nodes/core/network/31-tcpin_spec.js | 224 --
test/nodes/core/network/31-tcprequest_spec.js | 301 ---
test/nodes/core/network/32-udpin_spec.js | 94 -
test/nodes/core/network/32-udpout_spec.js | 88 -
test/nodes/core/parsers/70-CSV_spec.js | 1062 --------
test/nodes/core/parsers/70-HTML_spec.js | 494 ----
test/nodes/core/parsers/70-JSON_spec.js | 546 ----
test/nodes/core/parsers/70-XML_spec.js | 198 --
test/nodes/core/parsers/70-YAML_spec.js | 195 --
test/nodes/core/sequence/17-split_spec.js | 1919 --------------
test/nodes/core/sequence/18-sort_spec.js | 554 ----
test/nodes/core/sequence/19-batch_spec.js | 542 ----
test/nodes/core/storage/10-file_spec.js | 1722 -------------
test/nodes/core/storage/23-watch_spec.js | 217 --
test/nodes/subflow/subflow_spec.js | 570 -----
test/resources/70-HTML-test-file.html | 29 -
test/resources/file-in-node/test.txt | 1 -
test/resources/icons/test_icon.png | Bin 163 -> 0 bytes
.../plugin/test-plugin/library-filestore.html | 22 -
.../plugin/test-plugin/library-filestore.js | 37 -
.../locales/en-US/library-filestore.json | 8 -
.../locales/en-US/test-editor-plugin.json | 3 -
.../resources/plugin/test-plugin/package.json | 13 -
.../test-plugin/test-editor-plugin.html | 9 -
.../plugin/test-plugin/test-runtime-plugin.js | 10 -
test/resources/plugin/test-plugin/test.html | 6 -
test/resources/plugin/test-plugin/test.js | 13 -
test/resources/ssl/server.crt | 20 -
test/resources/ssl/server.key | 27 -
test/resources/subflow/package/README.md | 3 -
test/resources/subflow/package/package.json | 19 -
test/resources/subflow/package/subflow.js | 4 -
test/resources/subflow/package/subflow.json | 269 --
.../subflow/test-subflow-mod-1.0.2.tgz | Bin 1709 -> 0 bytes
.../editor-api/lib/admin/context_spec.js | 234 --
.../editor-api/lib/admin/flow_spec.js | 248 --
.../editor-api/lib/admin/flows_spec.js | 211 --
.../editor-api/lib/admin/index_spec.js | 458 ----
.../editor-api/lib/admin/nodes_spec.js | 497 ----
.../editor-api/lib/admin/plugins_spec.js | 111 -
.../editor-api/lib/admin/settings_spec.js | 93 -
.../editor-api/lib/auth/clients_spec.js | 47 -
.../editor-api/lib/auth/index_spec.js | 216 --
.../editor-api/lib/auth/permissions_spec.js | 59 -
.../editor-api/lib/auth/strategies_spec.js | 327 ---
.../editor-api/lib/auth/tokens_spec.js | 180 --
.../editor-api/lib/auth/users_spec.js | 276 --
.../editor-api/lib/editor/comms_spec.js | 618 -----
.../editor-api/lib/editor/credentials_spec.js | 94 -
.../editor-api/lib/editor/index_spec.js | 132 -
.../editor-api/lib/editor/library_spec.js | 263 --
.../editor-api/lib/editor/locales_spec.js | 165 --
.../editor-api/lib/editor/projects_spec.js | 21 -
.../editor-api/lib/editor/settings_spec.js | 97 -
.../editor-api/lib/editor/sshkeys_spec.js | 333 ---
.../editor-api/lib/editor/theme_spec.js | 275 --
.../editor-api/lib/editor/ui_spec.js | 210 --
.../@node-red/editor-api/lib/index_spec.js | 182 --
.../@node-red/editor-api/lib/util_spec.js | 110 -
.../@node-red/registry/lib/deprecated_spec.js | 30 -
.../registry/lib/externalModules_spec.js | 371 ---
.../unit/@node-red/registry/lib/index_spec.js | 127 -
.../@node-red/registry/lib/installer_spec.js | 528 ----
.../@node-red/registry/lib/library_spec.js | 62 -
.../@node-red/registry/lib/loader_spec.js | 720 ------
.../registry/lib/localfilesystem_spec.js | 276 --
.../@node-red/registry/lib/plugins_spec.js | 200 --
.../@node-red/registry/lib/registry_spec.js | 614 -----
.../registry/lib/resources/examples/one.json | 0
.../lib/resources/local/DuffNode/DuffNode.js | 5 -
.../local/DuplicateTestNode/TestNode1.html | 3 -
.../local/DuplicateTestNode/TestNode1.js | 5 -
.../local/MultipleNodes1/MultipleNodes1.html | 6 -
.../local/MultipleNodes1/MultipleNodes1.js | 7 -
.../NestedNode/NestedNode.html | 4 -
.../NestedNode/NestedNode.js | 5 -
.../NestedNode/icons/arrow-in.png | Bin 393 -> 0 bytes
.../NestedNode/lib/ShouldNotLoad.html | 4 -
.../NestedNode/lib/ShouldNotLoad.js | 5 -
.../node_modules/ShouldNotLoad.html | 4 -
.../NestedNode/node_modules/ShouldNotLoad.js | 5 -
.../NestedNode/test/ShouldNotLoad.html | 4 -
.../NestedNode/test/ShouldNotLoad.js | 5 -
.../resources/local/TestNode1/TestNode1.html | 5 -
.../resources/local/TestNode1/TestNode1.js | 5 -
.../resources/local/TestNode2/TestNode2.html | 4 -
.../resources/local/TestNode2/TestNode2.js | 9 -
.../resources/local/TestNode3/TestNode3.html | 3 -
.../resources/local/TestNode3/TestNode3.js | 7 -
.../resources/local/TestNode4/TestNode4.html | 3 -
.../resources/local/TestNode4/TestNode4.js | 1 -
.../node_modules/EmptyModule/file.txt | 1 -
.../TestNodeModule/TestNodeModule.html | 5 -
.../TestNodeModule/TestNodeModule.js | 5 -
.../TestNodeModule/TestNodeModule2.html | 5 -
.../TestNodeModule/TestNodeModule2.js | 4 -
.../TestNodeModule/icons/arrow-in.png | Bin 393 -> 0 bytes
.../TestNodeModule/icons/file.txt | 3 -
.../node_modules/TestNodeModule/package.json | 11 -
.../VersionMismatchModule/TestNodeModule.html | 5 -
.../VersionMismatchModule/TestNodeModule.js | 5 -
.../TestNodeModule2.html | 5 -
.../VersionMismatchModule/TestNodeModule2.js | 4 -
.../VersionMismatchModule/icons/file.txt | 3 -
.../VersionMismatchModule/package.json | 12 -
.../lib/resources/userDir/lib/icons/file.txt | 0
.../resources/userDir/lib/icons/test_icon.png | Bin 163 -> 0 bytes
.../userDir/nodes/TestNode5/TestNode5.html | 5 -
.../userDir/nodes/TestNode5/TestNode5.js | 1 -
.../@node-red/registry/lib/subflow_spec.js | 3 -
test/unit/@node-red/registry/lib/util_spec.js | 115 -
.../@node-red/runtime/lib/api/comms_spec.js | 321 ---
.../@node-red/runtime/lib/api/context_spec.js | 353 ---
.../@node-red/runtime/lib/api/flows_spec.js | 430 ----
.../@node-red/runtime/lib/api/index_spec.js | 55 -
.../@node-red/runtime/lib/api/library_spec.js | 167 --
.../@node-red/runtime/lib/api/nodes_spec.js | 1005 --------
.../@node-red/runtime/lib/api/plugins_spec.js | 68 -
.../runtime/lib/api/projects_spec.js | 1170 ---------
.../runtime/lib/api/settings_spec.js | 988 --------
.../@node-red/runtime/lib/flows/Flow_spec.js | 1327 ----------
.../runtime/lib/flows/Subflow_spec.js | 885 -------
.../@node-red/runtime/lib/flows/index_spec.js | 669 -----
.../@node-red/runtime/lib/flows/util_spec.js | 801 ------
test/unit/@node-red/runtime/lib/index_spec.js | 250 --
.../runtime/lib/library/examples_spec.js | 138 -
.../runtime/lib/library/index_spec.js | 199 --
.../runtime/lib/library/local_spec.js | 93 -
.../@node-red/runtime/lib/nodes/Node_spec.js | 809 ------
.../runtime/lib/nodes/context/index_spec.js | 1209 ---------
.../lib/nodes/context/localfilesystem_spec.js | 883 -------
.../runtime/lib/nodes/context/memory_spec.js | 321 ---
.../runtime/lib/nodes/credentials_spec.js | 474 ----
.../@node-red/runtime/lib/nodes/index_spec.js | 404 ---
.../NestedNode/icons/arrow-in.png | Bin 393 -> 0 bytes
.../TestNodeModule/icons/arrow-in.png | 3 -
.../@node-red/runtime/lib/plugins_spec.js | 13 -
.../@node-red/runtime/lib/settings_spec.js | 333 ---
.../runtime/lib/storage/index_spec.js | 271 --
.../lib/storage/localfilesystem/index_spec.js | 518 ----
.../storage/localfilesystem/library_spec.js | 244 --
.../localfilesystem/projects/Project_spec.js | 21 -
.../projects/defaultFileSet_spec.js | 64 -
.../projects/git/authCache_spec.js | 84 -
.../projects/git/authServer_spec.js | 83 -
.../projects/git/authWriter_spec.js | 83 -
.../projects/git/index_spec.js | 21 -
.../localfilesystem/projects/index_spec.js | 21 -
.../projects/ssh/index_spec.js | 433 ----
.../projects/ssh/keygen_spec.js | 110 -
.../storage/localfilesystem/sessions_spec.js | 80 -
.../storage/localfilesystem/settings_spec.js | 134 -
.../lib/storage/localfilesystem/util_spec.js | 32 -
test/unit/@node-red/util/index_spec.js | 21 -
test/unit/@node-red/util/lib/events_spec.js | 25 -
test/unit/@node-red/util/lib/exec_spec.js | 140 --
test/unit/@node-red/util/lib/hooks_spec.js | 338 ---
test/unit/@node-red/util/lib/i18n_spec.js | 26 -
test/unit/@node-red/util/lib/index_spec.js | 19 -
test/unit/@node-red/util/lib/log_spec.js | 252 --
test/unit/@node-red/util/lib/util_spec.js | 1092 --------
test/unit/_spec.js | 87 -
test/unit/node-red/lib/red_spec.js | 76 -
test/unit/node-red/red_spec.js | 21 -
367 files changed, 1 insertion(+), 75791 deletions(-)
delete mode 100644 SECURITY.md
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/20-inject.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/20-inject.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/21-debug.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/21-debug.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/24-complete.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/24-complete.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/25-catch.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/25-catch.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/25-status.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/25-status.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/60-link.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/60-link.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/98-unknown.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/common/98-unknown.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/10-function.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/10-function.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/10-switch.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/10-switch.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/15-change.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/15-change.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/16-range.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/16-range.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/80-template.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/80-template.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/89-delay.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/89-delay.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/89-trigger.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/89-trigger.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/90-exec.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/90-exec.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/rbe.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/function/rbe.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/05-tls.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/05-tls.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/06-httpproxy.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/06-httpproxy.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/10-mqtt.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/10-mqtt.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/21-httpin.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/21-httpin.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/21-httprequest.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/22-websocket.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/22-websocket.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/31-tcpin.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/32-udp.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/32-udp.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/network/lib/mqtt.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-CSV.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-HTML.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-HTML.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-JSON.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-JSON.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-XML.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-XML.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-YAML.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/parsers/70-YAML.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/sequence/17-split.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/sequence/17-split.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/sequence/18-sort.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/sequence/18-sort.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/sequence/19-batch.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/sequence/19-batch.js
delete mode 100755 packages/node_modules/@node-red/nodes/core/storage/10-file.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/storage/10-file.js
delete mode 100644 packages/node_modules/@node-red/nodes/core/storage/23-watch.html
delete mode 100644 packages/node_modules/@node-red/nodes/core/storage/23-watch.js
delete mode 100644 test/editor/editor_helper.js
delete mode 100644 test/editor/pageobjects/editor/debugTab_page.js
delete mode 100644 test/editor/pageobjects/editor/palette_page.js
delete mode 100644 test/editor/pageobjects/editor/workspace_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/common/20-inject_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/common/21-debug_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/common/24-complete_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/common/25-catch_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/common/25-status_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/common/90-comment_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/10-function_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/10-switch_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/15-change_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/16-range_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/80-template_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/89-delay_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/89-trigger_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/function/90-exec_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/network/10-mqtt_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/network/21-httpin_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/network/21-httprequest_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/network/21-httpresponse_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/network/22-websocket_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/parsers/70-CSV_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/parsers/70-HTML_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/parsers/70-JSON_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/parsers/70-XML_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/parsers/70-YAML_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/sequence/17-split_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/sequence/19-batch_page.js
delete mode 100644 test/editor/pageobjects/nodes/core/storage/10-filein_page.js
delete mode 100644 test/editor/pageobjects/nodes/node_page.js
delete mode 100644 test/editor/pageobjects/nodes/nodefactory_page.js
delete mode 100644 test/editor/pageobjects/util/key_page.js
delete mode 100644 test/editor/pageobjects/util/spec_util_page.js
delete mode 100644 test/editor/pageobjects/util/util_page.js
delete mode 100644 test/editor/specs/editor/workspace_uispec.js
delete mode 100644 test/editor/specs/scenario/cookbook_dataformats_uispec.js
delete mode 100644 test/editor/specs/scenario/cookbook_errorhandling_uispec.js
delete mode 100644 test/editor/specs/scenario/cookbook_flowcontrol_uispec.js
delete mode 100644 test/editor/specs/scenario/cookbook_httpendpoints_uispec.js
delete mode 100644 test/editor/specs/scenario/cookbook_httprequests_uispec.js
delete mode 100644 test/editor/specs/scenario/cookbook_messages_uispec.js
delete mode 100644 test/editor/specs/scenario/cookbook_mqtt_uispec.js
delete mode 100644 test/editor/wdio.conf.js
delete mode 100644 test/node_modules/nr-test-utils/index.js
delete mode 100644 test/node_modules/nr-test-utils/package.json
delete mode 100644 test/nodes/core/common/20-inject_spec.js
delete mode 100644 test/nodes/core/common/21-debug_spec.js
delete mode 100644 test/nodes/core/common/25-catch_spec.js
delete mode 100644 test/nodes/core/common/25-status_spec.js
delete mode 100644 test/nodes/core/common/60-link_spec.js
delete mode 100644 test/nodes/core/common/90-comment_spec.js
delete mode 100644 test/nodes/core/common/98-unknown_spec.js
delete mode 100644 test/nodes/core/function/10-function_spec.js
delete mode 100644 test/nodes/core/function/10-switch_spec.js
delete mode 100644 test/nodes/core/function/15-change_spec.js
delete mode 100644 test/nodes/core/function/16-range_spec.js
delete mode 100644 test/nodes/core/function/80-template_spec.js
delete mode 100644 test/nodes/core/function/89-delay_spec.js
delete mode 100644 test/nodes/core/function/89-trigger_spec.js
delete mode 100644 test/nodes/core/function/90-exec_spec.js
delete mode 100644 test/nodes/core/function/rbe_spec.js
delete mode 100644 test/nodes/core/network/21-httprequest_spec.js
delete mode 100644 test/nodes/core/network/22-websocket_spec.js
delete mode 100644 test/nodes/core/network/31-tcpin_spec.js
delete mode 100644 test/nodes/core/network/31-tcprequest_spec.js
delete mode 100644 test/nodes/core/network/32-udpin_spec.js
delete mode 100644 test/nodes/core/network/32-udpout_spec.js
delete mode 100644 test/nodes/core/parsers/70-CSV_spec.js
delete mode 100644 test/nodes/core/parsers/70-HTML_spec.js
delete mode 100644 test/nodes/core/parsers/70-JSON_spec.js
delete mode 100644 test/nodes/core/parsers/70-XML_spec.js
delete mode 100644 test/nodes/core/parsers/70-YAML_spec.js
delete mode 100644 test/nodes/core/sequence/17-split_spec.js
delete mode 100644 test/nodes/core/sequence/18-sort_spec.js
delete mode 100644 test/nodes/core/sequence/19-batch_spec.js
delete mode 100644 test/nodes/core/storage/10-file_spec.js
delete mode 100644 test/nodes/core/storage/23-watch_spec.js
delete mode 100644 test/nodes/subflow/subflow_spec.js
delete mode 100644 test/resources/70-HTML-test-file.html
delete mode 100644 test/resources/file-in-node/test.txt
delete mode 100644 test/resources/icons/test_icon.png
delete mode 100644 test/resources/plugin/test-plugin/library-filestore.html
delete mode 100644 test/resources/plugin/test-plugin/library-filestore.js
delete mode 100644 test/resources/plugin/test-plugin/locales/en-US/library-filestore.json
delete mode 100644 test/resources/plugin/test-plugin/locales/en-US/test-editor-plugin.json
delete mode 100644 test/resources/plugin/test-plugin/package.json
delete mode 100644 test/resources/plugin/test-plugin/test-editor-plugin.html
delete mode 100644 test/resources/plugin/test-plugin/test-runtime-plugin.js
delete mode 100644 test/resources/plugin/test-plugin/test.html
delete mode 100644 test/resources/plugin/test-plugin/test.js
delete mode 100644 test/resources/ssl/server.crt
delete mode 100644 test/resources/ssl/server.key
delete mode 100644 test/resources/subflow/package/README.md
delete mode 100644 test/resources/subflow/package/package.json
delete mode 100644 test/resources/subflow/package/subflow.js
delete mode 100644 test/resources/subflow/package/subflow.json
delete mode 100644 test/resources/subflow/test-subflow-mod-1.0.2.tgz
delete mode 100644 test/unit/@node-red/editor-api/lib/admin/context_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/admin/flow_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/admin/flows_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/admin/index_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/admin/nodes_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/admin/plugins_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/admin/settings_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/auth/clients_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/auth/index_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/auth/permissions_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/auth/strategies_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/auth/tokens_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/auth/users_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/comms_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/credentials_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/index_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/library_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/locales_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/projects_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/settings_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/sshkeys_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/theme_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/editor/ui_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/index_spec.js
delete mode 100644 test/unit/@node-red/editor-api/lib/util_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/deprecated_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/externalModules_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/index_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/installer_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/library_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/loader_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/localfilesystem_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/plugins_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/registry_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/examples/one.json
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/DuffNode/DuffNode.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/EmptyModule/file.txt
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/package.json
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.js
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/icons/file.txt
delete mode 100644 test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/package.json
delete mode 100644 test/unit/@node-red/registry/lib/resources/userDir/lib/icons/file.txt
delete mode 100644 test/unit/@node-red/registry/lib/resources/userDir/lib/icons/test_icon.png
delete mode 100644 test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.html
delete mode 100644 test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.js
delete mode 100644 test/unit/@node-red/registry/lib/subflow_spec.js
delete mode 100644 test/unit/@node-red/registry/lib/util_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/comms_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/context_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/flows_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/library_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/nodes_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/plugins_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/projects_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/api/settings_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/flows/Flow_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/flows/Subflow_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/flows/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/flows/util_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/library/examples_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/library/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/library/local_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/Node_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/context/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/context/localfilesystem_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/context/memory_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/credentials_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png
delete mode 100644 test/unit/@node-red/runtime/lib/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
delete mode 100644 test/unit/@node-red/runtime/lib/plugins_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/settings_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/library_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/Project_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/sessions_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/settings_spec.js
delete mode 100644 test/unit/@node-red/runtime/lib/storage/localfilesystem/util_spec.js
delete mode 100644 test/unit/@node-red/util/index_spec.js
delete mode 100644 test/unit/@node-red/util/lib/events_spec.js
delete mode 100644 test/unit/@node-red/util/lib/exec_spec.js
delete mode 100644 test/unit/@node-red/util/lib/hooks_spec.js
delete mode 100644 test/unit/@node-red/util/lib/i18n_spec.js
delete mode 100644 test/unit/@node-red/util/lib/index_spec.js
delete mode 100644 test/unit/@node-red/util/lib/log_spec.js
delete mode 100644 test/unit/@node-red/util/lib/util_spec.js
delete mode 100644 test/unit/_spec.js
delete mode 100644 test/unit/node-red/lib/red_spec.js
delete mode 100644 test/unit/node-red/red_spec.js
diff --git a/.gitignore b/.gitignore
index d4c991688..d52f81d76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,3 +27,4 @@ docs
.vscode
.nyc_output
sync.ffs_db
+.idea
\ No newline at end of file
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index 816ac507b..000000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Security Policy
-
-## Reporting a Vulnerability
-
-Please report any potential security issues to `team@nodered.org`. This will notify the core project team who will respond accordingly.
diff --git a/packages/node_modules/@node-red/nodes/core/common/20-inject.html b/packages/node_modules/@node-red/nodes/core/common/20-inject.html
deleted file mode 100644
index 2cbf274ce..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/20-inject.html
+++ /dev/null
@@ -1,711 +0,0 @@
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/20-inject.js b/packages/node_modules/@node-red/nodes/core/common/20-inject.js
deleted file mode 100644
index 7e25b1a1d..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/20-inject.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- const {scheduleTask} = require("cronosjs");
-
- function InjectNode(n) {
- RED.nodes.createNode(this,n);
-
- /* Handle legacy */
- if(!Array.isArray(n.props)){
- n.props = [];
- n.props.push({
- p:'payload',
- v:n.payload,
- vt:n.payloadType
- });
- n.props.push({
- p:'topic',
- v:n.topic,
- vt:'str'
- });
- } else {
- for (var i=0,l=n.props.length; i 2147483) {
- node.error(RED._("inject.errors.toolong", this));
- delete node.repeat;
- }
-
- node.repeaterSetup = function () {
- if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
- this.repeat = this.repeat * 1000;
- if (RED.settings.verbose) {
- this.log(RED._("inject.repeat", this));
- }
- this.interval_id = setInterval(function() {
- node.emit("input", {});
- }, this.repeat);
- } else if (this.crontab) {
- if (RED.settings.verbose) {
- this.log(RED._("inject.crontab", this));
- }
- this.cronjob = scheduleTask(this.crontab,() => { node.emit("input", {})});
- }
- };
-
- if (this.once) {
- this.onceTimeout = setTimeout( function() {
- node.emit("input",{});
- node.repeaterSetup();
- }, this.onceDelay);
- } else {
- node.repeaterSetup();
- }
-
- this.on("input", function(msg, send, done) {
- var errors = [];
- var props = this.props;
- if (msg.__user_inject_props__ && Array.isArray(msg.__user_inject_props__)) {
- props = msg.__user_inject_props__;
- }
- delete msg.__user_inject_props__;
- props.forEach(p => {
- var property = p.p;
- var value = p.v ? p.v : '';
- var valueType = p.vt ? p.vt : 'str';
-
- if (!property) return;
-
- if (valueType === "jsonata") {
- if (p.exp) {
- try {
- var val = RED.util.evaluateJSONataExpression(p.exp, msg);
- RED.util.setMessageProperty(msg, property, val, true);
- }
- catch (err) {
- errors.push(err.message);
- }
- }
- return;
- }
- try {
- RED.util.setMessageProperty(msg,property,RED.util.evaluateNodeProperty(value, valueType, this, msg),true);
- } catch (err) {
- errors.push(err.toString());
- }
- });
-
- if (errors.length) {
- done(errors.join('; '));
- } else {
- send(msg);
- done();
- }
- });
- }
-
- RED.nodes.registerType("inject",InjectNode);
-
- InjectNode.prototype.close = function() {
- if (this.onceTimeout) {
- clearTimeout(this.onceTimeout);
- }
- if (this.interval_id != null) {
- clearInterval(this.interval_id);
- if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
- } else if (this.cronjob != null) {
- this.cronjob.stop();
- if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
- delete this.cronjob;
- }
- };
-
- RED.httpAdmin.post("/inject/:id", RED.auth.needsPermission("inject.write"), function(req,res) {
- var node = RED.nodes.getNode(req.params.id);
- if (node != null) {
- try {
- if (req.body && req.body.__user_inject_props__) {
- node.receive(req.body);
- } else {
- node.receive();
- }
- res.sendStatus(200);
- } catch(err) {
- res.sendStatus(500);
- node.error(RED._("inject.failed",{error:err.toString()}));
- }
- } else {
- res.sendStatus(404);
- }
- });
-}
diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.html b/packages/node_modules/@node-red/nodes/core/common/21-debug.html
deleted file mode 100644
index 195423482..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/21-debug.html
+++ /dev/null
@@ -1,513 +0,0 @@
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.js b/packages/node_modules/@node-red/nodes/core/common/21-debug.js
deleted file mode 100644
index 73d364e43..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/21-debug.js
+++ /dev/null
@@ -1,297 +0,0 @@
-module.exports = function(RED) {
- "use strict";
- var util = require("util");
- var events = require("events");
- const fs = require("fs-extra");
- const path = require("path");
- var debuglength = RED.settings.debugMaxLength || 1000;
- var useColors = RED.settings.debugUseColors || false;
- util.inspect.styles.boolean = "red";
-
- function DebugNode(n) {
- var hasEditExpression = (n.targetType === "jsonata");
- var editExpression = hasEditExpression ? n.complete : null;
- RED.nodes.createNode(this,n);
- this.name = n.name;
- this.complete = hasEditExpression ? null : (n.complete||"payload").toString();
- if (this.complete === "false") { this.complete = "payload"; }
- this.console = ""+(n.console || false);
- this.tostatus = n.tostatus || false;
- this.statusType = n.statusType || "auto";
- this.statusVal = n.statusVal || this.complete;
- this.tosidebar = n.tosidebar;
- if (this.tosidebar === undefined) { this.tosidebar = true; }
- this.active = (n.active === null || typeof n.active === "undefined") || n.active;
- if (this.tostatus) {
- this.status({fill:"grey", shape:"ring"});
- this.oldState = "{}";
- }
-
- var hasStatExpression = (n.statusType === "jsonata");
- var statExpression = hasStatExpression ? n.statusVal : null;
-
- var node = this;
- var preparedEditExpression = null;
- var preparedStatExpression = null;
- if (editExpression) {
- try {
- preparedEditExpression = RED.util.prepareJSONataExpression(editExpression, this);
- }
- catch (e) {
- node.error(RED._("debug.invalid-exp", {error: editExpression}));
- return;
- }
- }
- if (statExpression) {
- try {
- preparedStatExpression = RED.util.prepareJSONataExpression(statExpression, this);
- }
- catch (e) {
- node.error(RED._("debug.invalid-exp", {error: editExpression}));
- return;
- }
- }
-
- function prepareValue(msg, done) {
- // Either apply the jsonata expression or...
- if (preparedEditExpression) {
- RED.util.evaluateJSONataExpression(preparedEditExpression, msg, (err, value) => {
- if (err) { done(RED._("debug.invalid-exp", {error: editExpression})); }
- else { done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:value}); }
- });
- } else {
- // Extract the required message property
- var property = "payload";
- var output = msg[property];
- if (node.complete !== "false" && typeof node.complete !== "undefined") {
- property = node.complete;
- try { output = RED.util.getMessageProperty(msg,node.complete); }
- catch(err) { output = undefined; }
- }
- done(null,{id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, property:property, msg:output});
- }
- }
-
- function prepareStatus(msg, done) {
- if (node.statusType === "auto") {
- if (node.complete === "true") {
- done(null,{msg:msg.payload});
- }
- else {
- prepareValue(msg,function(err,debugMsg) {
- if (err) { node.error(err); return; }
- done(null,{msg:debugMsg.msg});
- });
- }
- }
- else {
- // Either apply the jsonata expression or...
- if (preparedStatExpression) {
- RED.util.evaluateJSONataExpression(preparedStatExpression, msg, (err, value) => {
- if (err) { done(RED._("debug.invalid-exp", {error:editExpression})); }
- else { done(null,{msg:value}); }
- });
- }
- else {
- // Extract the required message property
- var output;
- try { output = RED.util.getMessageProperty(msg,node.statusVal); }
- catch(err) { output = undefined; }
- done(null,{msg:output});
- }
- }
- }
- this.on("close", function() {
- if (this.oldState) {
- this.status({});
- }
- })
- this.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("status") && msg.status.hasOwnProperty("source") && msg.status.source.hasOwnProperty("id") && (msg.status.source.id === node.id)) {
- done();
- return;
- }
- if (node.tostatus === true) {
- prepareStatus(msg, function(err,debugMsg) {
- if (err) { node.error(err); return; }
- var output = debugMsg.msg;
- var st = (typeof output === 'string') ? output : util.inspect(output);
- var fill = "grey";
- var shape = "dot";
- if (typeof output === 'object' && output.hasOwnProperty("fill") && output.hasOwnProperty("shape") && output.hasOwnProperty("text")) {
- fill = output.fill;
- shape = output.shape;
- st = output.text;
- }
- if (node.statusType === "auto") {
- if (msg.hasOwnProperty("error")) {
- fill = "red";
- st = msg.error.message;
- }
- if (msg.hasOwnProperty("status")) {
- fill = msg.status.fill || "grey";
- shape = msg.status.shape || "ring";
- st = msg.status.text || "";
- }
- }
-
- if (st.length > 32) { st = st.substr(0,32) + "..."; }
- var newStatus = {fill:fill, shape:shape, text:st};
- if (JSON.stringify(newStatus) !== node.oldState) { // only send if we have to
- node.status(newStatus);
- node.oldState = JSON.stringify(newStatus);
- }
- });
- }
-
- if (this.complete === "true") {
- // debug complete msg object
- if (this.console === "true") {
- node.log("\n"+util.inspect(msg, {colors:useColors, depth:10}));
- }
- if (this.active && this.tosidebar) {
- sendDebug({id:node.id, z:node.z, _alias: node._alias, path:node._flow.path, name:node.name, topic:msg.topic, msg:msg});
- }
- done();
- }
- else {
- prepareValue(msg,function(err,debugMsg) {
- if (err) {
- node.error(err);
- return;
- }
- var output = debugMsg.msg;
- if (node.console === "true") {
- if (typeof output === "string") {
- node.log((output.indexOf("\n") !== -1 ? "\n" : "") + output);
- } else if (typeof output === "object") {
- node.log("\n"+util.inspect(output, {colors:useColors, depth:10}));
- } else {
- node.log(util.inspect(output, {colors:useColors}));
- }
- }
- if (node.active) {
- if (node.tosidebar == true) {
- sendDebug(debugMsg);
- }
- }
- done();
- });
- }
- })
- }
-
- RED.nodes.registerType("debug",DebugNode, {
- settings: {
- debugUseColors: {
- value: false,
- },
- debugMaxLength: {
- value: 1000,
- }
- }
- });
-
- function sendDebug(msg) {
- // don't put blank errors in sidebar (but do add to logs)
- //if ((msg.msg === "") && (msg.hasOwnProperty("level")) && (msg.level === 20)) { return; }
- msg = RED.util.encodeObject(msg,{maxLength:debuglength});
- RED.comms.publish("debug",msg);
- }
-
- DebugNode.logHandler = new events.EventEmitter();
- DebugNode.logHandler.on("log",function(msg) {
- if (msg.level === RED.log.WARN || msg.level === RED.log.ERROR) {
- sendDebug(msg);
- }
- });
- RED.log.addHandler(DebugNode.logHandler);
-
- function setNodeState(node,state) {
- if (state) {
- node.active = true;
- } else {
- node.active = false;
- }
- }
-
- RED.httpAdmin.post("/debug/:state", RED.auth.needsPermission("debug.write"), function(req,res) {
- var state = req.params.state;
- if (state !== 'enable' && state !== 'disable') {
- res.sendStatus(404);
- return;
- }
- var nodes = req.body && req.body.nodes;
- if (Array.isArray(nodes)) {
- nodes.forEach(function(id) {
- var node = RED.nodes.getNode(id);
- if (node !== null && typeof node !== "undefined" ) {
- setNodeState(node, state === "enable");
- }
- })
- res.sendStatus(state === "enable" ? 200 : 201);
- } else {
- res.sendStatus(400);
- }
- })
-
- RED.httpAdmin.post("/debug/:id/:state", RED.auth.needsPermission("debug.write"), function(req,res) {
- var state = req.params.state;
- if (state !== 'enable' && state !== 'disable') {
- res.sendStatus(404);
- return;
- }
- var node = RED.nodes.getNode(req.params.id);
- if (node !== null && typeof node !== "undefined" ) {
- setNodeState(node,state === "enable");
- res.sendStatus(state === "enable" ? 200 : 201);
- } else {
- res.sendStatus(404);
- }
- });
-
- let cachedDebugView;
- RED.httpAdmin.get("/debug/view/view.html", function(req,res) {
- if (!cachedDebugView) {
- fs.readFile(path.join(__dirname,"lib","debug","view.html")).then(data => {
- let customStyles = "";
- try {
- let customStyleList = RED.settings.editorTheme.page._.css || [];
- customStyleList.forEach(style => {
- customStyles += ` \n`
- })
- } catch(err) {}
- cachedDebugView = data.toString().replace("",customStyles)
- res.set('Content-Type', 'text/html');
- res.send(cachedDebugView).end();
- }).catch(err => {
- res.sendStatus(404);
- })
- } else {
- res.send(cachedDebugView).end();
- }
-
- });
-
- // As debug/view/debug-utils.js is loaded via
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/24-complete.js b/packages/node_modules/@node-red/nodes/core/common/24-complete.js
deleted file mode 100644
index ea665a265..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/24-complete.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- function CompleteNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- this.scope = n.scope;
- this.on("input",function(msg, send, done) {
- send(msg);
- done();
- });
- }
-
- RED.nodes.registerType("complete",CompleteNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/common/25-catch.html b/packages/node_modules/@node-red/nodes/core/common/25-catch.html
deleted file mode 100644
index 0b976ea78..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/25-catch.html
+++ /dev/null
@@ -1,191 +0,0 @@
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/25-catch.js b/packages/node_modules/@node-red/nodes/core/common/25-catch.js
deleted file mode 100644
index 5ed525c36..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/25-catch.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- function CatchNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- this.scope = n.scope;
- this.uncaught = n.uncaught;
- this.on("input",function(msg, send, done) {
- send(msg);
- done();
- });
- }
-
- RED.nodes.registerType("catch",CatchNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/common/25-status.html b/packages/node_modules/@node-red/nodes/core/common/25-status.html
deleted file mode 100644
index 47a3192e4..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/25-status.html
+++ /dev/null
@@ -1,177 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/25-status.js b/packages/node_modules/@node-red/nodes/core/common/25-status.js
deleted file mode 100644
index fc6ccbe29..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/25-status.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- function StatusNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- this.scope = n.scope;
- this.on("input", function(msg, send, done) {
- send(msg);
- done();
- });
- }
-
- RED.nodes.registerType("status",StatusNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/common/60-link.html b/packages/node_modules/@node-red/nodes/core/common/60-link.html
deleted file mode 100644
index f3fabba59..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/60-link.html
+++ /dev/null
@@ -1,340 +0,0 @@
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/60-link.js b/packages/node_modules/@node-red/nodes/core/common/60-link.js
deleted file mode 100644
index 53404e446..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/60-link.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- const crypto = require("crypto");
-
- function LinkInNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- var event = "node:"+n.id;
- var handler = function(msg) {
- msg._event = n.event;
- node.receive(msg);
- }
- RED.events.on(event,handler);
- this.on("input", function(msg, send, done) {
- send(msg);
- done();
- });
- this.on("close",function() {
- RED.events.removeListener(event,handler);
- });
- }
-
- RED.nodes.registerType("link in",LinkInNode);
-
- function LinkOutNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- var mode = n.mode || "link";
-
- var event = "node:"+n.id;
- this.on("input", function(msg, send, done) {
- msg._event = event;
- RED.events.emit(event,msg)
-
- if (mode === "return") {
- if (Array.isArray(msg._linkSource) && msg._linkSource.length > 0) {
- var messageEvent = msg._linkSource.pop();
- var returnNode = RED.nodes.getNode(messageEvent.node);
- if (returnNode && returnNode.returnLinkMessage) {
- returnNode.returnLinkMessage(messageEvent.id, msg);
- } else {
- node.warn(RED._("link.error.missingReturn"))
- }
- } else {
- node.warn(RED._("link.error.missingReturn"))
- }
- done();
- } else if (mode === "link") {
- send(msg);
- done();
- }
- });
- }
- RED.nodes.registerType("link out",LinkOutNode);
-
-
- function LinkCallNode(n) {
- RED.nodes.createNode(this,n);
- const node = this;
- const target = n.links[0];
- const messageEvents = {};
- let timeout = parseFloat(n.timeout || "30")*1000;
- if (isNaN(timeout)) {
- timeout = 30000;
- }
-
- this.on("input", function(msg, send, done) {
- msg._linkSource = msg._linkSource || [];
- const messageEvent = {
- id: crypto.randomBytes(14).toString('hex'),
- node: node.id,
- }
- messageEvents[messageEvent.id] = {
- msg: RED.util.cloneMessage(msg),
- send,
- done,
- ts: setTimeout(function() {
- timeoutMessage(messageEvent.id)
- }, timeout )
- };
- msg._linkSource.push(messageEvent);
- var targetNode = RED.nodes.getNode(target);
- if (targetNode) {
- targetNode.receive(msg);
- }
- });
-
- this.returnLinkMessage = function(eventId, msg) {
- if (Array.isArray(msg._linkSource) && msg._linkSource.length === 0) {
- delete msg._linkSource;
- }
- const messageEvent = messageEvents[eventId];
- if (messageEvent) {
- clearTimeout(messageEvent.ts);
- delete messageEvents[eventId];
- messageEvent.send(msg);
- messageEvent.done();
- } else {
- node.send(msg);
- }
- }
-
- function timeoutMessage(eventId) {
- const messageEvent = messageEvents[eventId];
- if (messageEvent) {
- delete messageEvents[eventId];
- node.error("timeout",messageEvent.msg);
- }
- }
-
- }
- RED.nodes.registerType("link call",LinkCallNode);
-
-
-}
diff --git a/packages/node_modules/@node-red/nodes/core/common/98-unknown.html b/packages/node_modules/@node-red/nodes/core/common/98-unknown.html
deleted file mode 100644
index 52071c30f..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/98-unknown.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/common/98-unknown.js b/packages/node_modules/@node-red/nodes/core/common/98-unknown.js
deleted file mode 100644
index 0ee463bb3..000000000
--- a/packages/node_modules/@node-red/nodes/core/common/98-unknown.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- function UnknownNode(n) {
- RED.nodes.createNode(this,n);
- }
- RED.nodes.registerType("unknown",UnknownNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.html b/packages/node_modules/@node-red/nodes/core/function/10-function.html
deleted file mode 100644
index 4175f4448..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/10-function.html
+++ /dev/null
@@ -1,609 +0,0 @@
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.js b/packages/node_modules/@node-red/nodes/core/function/10-function.js
deleted file mode 100644
index 4ce966e9d..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/10-function.js
+++ /dev/null
@@ -1,507 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- var util = require("util");
- var vm = require("vm");
- var acorn = require("acorn");
- var acornWalk = require("acorn-walk");
-
- function sendResults(node,send,_msgid,msgs,cloneFirstMessage) {
- if (msgs == null) {
- return;
- } else if (!util.isArray(msgs)) {
- msgs = [msgs];
- }
- var msgCount = 0;
- for (var m=0; m0) {
- send(msgs);
- }
- }
-
- function createVMOpt(node, kind) {
- var opt = {
- filename: 'Function node'+kind+':'+node.id+(node.name?' ['+node.name+']':''), // filename for stack traces
- displayErrors: true
- // Using the following options causes node 4/6 to not include the line number
- // in the stack output. So don't use them.
- // lineOffset: -11, // line number offset to be used for stack traces
- // columnOffset: 0, // column number offset to be used for stack traces
- };
- return opt;
- }
-
- function updateErrorInfo(err) {
- if (err.stack) {
- var stack = err.stack.toString();
- var m = /^([^:]+):([^:]+):(\d+).*/.exec(stack);
- if (m) {
- var line = parseInt(m[3]) -1;
- var kind = "body:";
- if (/setup/.exec(m[1])) {
- kind = "setup:";
- }
- if (/cleanup/.exec(m[1])) {
- kind = "cleanup:";
- }
- err.message += " ("+kind+"line "+line+")";
- }
- }
- }
-
- function FunctionNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- node.name = n.name;
- node.func = n.func;
- node.outputs = n.outputs;
- node.ini = n.initialize ? n.initialize.trim() : "";
- node.fin = n.finalize ? n.finalize.trim() : "";
- node.libs = n.libs || [];
-
- if (RED.settings.functionExternalModules === false && node.libs.length > 0) {
- throw new Error(RED._("function.error.externalModuleNotAllowed"));
- }
-
-
-
- var functionText = "var results = null;"+
- "results = (async function(msg,__send__,__done__){ "+
- "var __msgid__ = msg._msgid;"+
- "var node = {"+
- "id:__node__.id,"+
- "name:__node__.name,"+
- "outputCount:__node__.outputCount,"+
- "log:__node__.log,"+
- "error:__node__.error,"+
- "warn:__node__.warn,"+
- "debug:__node__.debug,"+
- "trace:__node__.trace,"+
- "on:__node__.on,"+
- "status:__node__.status,"+
- "send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+
- "done:__done__"+
- "};\n"+
- node.func+"\n"+
- "})(msg,__send__,__done__);";
-
- var handleNodeDoneCall = true;
-
- // Check to see if the Function appears to call `node.done()`. If so,
- // we will assume it is well written and does actually call node.done().
- // Otherwise, we will call node.done() after the function returns regardless.
- if (/node\.done\s*\(\s*\)/.test(functionText)) {
- // We have spotted the code contains `node.done`. It could be in a comment
- // so need to do the extra work to parse the AST and examine it properly.
- acornWalk.simple(acorn.parse(functionText,{ecmaVersion: "latest"} ), {
- CallExpression(astNode) {
- if (astNode.callee && astNode.callee.object) {
- if (astNode.callee.object.name === "node" && astNode.callee.property.name === "done") {
- handleNodeDoneCall = false;
- }
- }
- }
- })
- }
-
- var finScript = null;
- var finOpt = null;
- node.topic = n.topic;
- node.outstandingTimers = [];
- node.outstandingIntervals = [];
- node.clearStatus = false;
-
- var sandbox = {
- console:console,
- util:util,
- Buffer:Buffer,
- Date: Date,
- RED: {
- util: RED.util
- },
- __node__: {
- id: node.id,
- name: node.name,
- outputCount: node.outputs,
- log: function() {
- node.log.apply(node, arguments);
- },
- error: function() {
- node.error.apply(node, arguments);
- },
- warn: function() {
- node.warn.apply(node, arguments);
- },
- debug: function() {
- node.debug.apply(node, arguments);
- },
- trace: function() {
- node.trace.apply(node, arguments);
- },
- send: function(send, id, msgs, cloneMsg) {
- sendResults(node, send, id, msgs, cloneMsg);
- },
- on: function() {
- if (arguments[0] === "input") {
- throw new Error(RED._("function.error.inputListener"));
- }
- node.on.apply(node, arguments);
- },
- status: function() {
- node.clearStatus = true;
- node.status.apply(node, arguments);
- }
- },
- context: {
- set: function() {
- node.context().set.apply(node,arguments);
- },
- get: function() {
- return node.context().get.apply(node,arguments);
- },
- keys: function() {
- return node.context().keys.apply(node,arguments);
- },
- get global() {
- return node.context().global;
- },
- get flow() {
- return node.context().flow;
- }
- },
- flow: {
- set: function() {
- node.context().flow.set.apply(node,arguments);
- },
- get: function() {
- return node.context().flow.get.apply(node,arguments);
- },
- keys: function() {
- return node.context().flow.keys.apply(node,arguments);
- }
- },
- global: {
- set: function() {
- node.context().global.set.apply(node,arguments);
- },
- get: function() {
- return node.context().global.get.apply(node,arguments);
- },
- keys: function() {
- return node.context().global.keys.apply(node,arguments);
- }
- },
- env: {
- get: function(envVar) {
- var flow = node._flow;
- return flow.getSetting(envVar);
- }
- },
- setTimeout: function () {
- var func = arguments[0];
- var timerId;
- arguments[0] = function() {
- sandbox.clearTimeout(timerId);
- try {
- func.apply(node,arguments);
- } catch(err) {
- node.error(err,{});
- }
- };
- timerId = setTimeout.apply(node,arguments);
- node.outstandingTimers.push(timerId);
- return timerId;
- },
- clearTimeout: function(id) {
- clearTimeout(id);
- var index = node.outstandingTimers.indexOf(id);
- if (index > -1) {
- node.outstandingTimers.splice(index,1);
- }
- },
- setInterval: function() {
- var func = arguments[0];
- var timerId;
- arguments[0] = function() {
- try {
- func.apply(node,arguments);
- } catch(err) {
- node.error(err,{});
- }
- };
- timerId = setInterval.apply(node,arguments);
- node.outstandingIntervals.push(timerId);
- return timerId;
- },
- clearInterval: function(id) {
- clearInterval(id);
- var index = node.outstandingIntervals.indexOf(id);
- if (index > -1) {
- node.outstandingIntervals.splice(index,1);
- }
- }
- };
- if (util.hasOwnProperty('promisify')) {
- sandbox.setTimeout[util.promisify.custom] = function(after, value) {
- return new Promise(function(resolve, reject) {
- sandbox.setTimeout(function(){ resolve(value); }, after);
- });
- };
- sandbox.promisify = util.promisify;
- }
- const moduleLoadPromises = [];
-
- if (node.hasOwnProperty("libs")) {
- let moduleErrors = false;
- var modules = node.libs;
- modules.forEach(module => {
- var vname = module.hasOwnProperty("var") ? module.var : null;
- if (vname && (vname !== "")) {
- if (sandbox.hasOwnProperty(vname) || vname === 'node') {
- node.error(RED._("function.error.moduleNameError",{name:vname}))
- moduleErrors = true;
- return;
- }
- sandbox[vname] = null;
- var spec = module.module;
- if (spec && (spec !== "")) {
- moduleLoadPromises.push(RED.import(module.module).then(lib => {
- sandbox[vname] = lib.default;
- }).catch(err => {
- node.error(RED._("function.error.moduleLoadError",{module:module.spec, error:err.toString()}))
- throw err;
- }));
- }
- }
- });
- if (moduleErrors) {
- throw new Error(RED._("function.error.externalModuleLoadError"));
- }
- }
- const RESOLVING = 0;
- const RESOLVED = 1;
- const ERROR = 2;
- var state = RESOLVING;
- var messages = [];
- var processMessage = (() => {});
-
- node.on("input", function(msg,send,done) {
- if(state === RESOLVING) {
- messages.push({msg:msg, send:send, done:done});
- }
- else if(state === RESOLVED) {
- processMessage(msg, send, done);
- }
- });
- Promise.all(moduleLoadPromises).then(() => {
- var context = vm.createContext(sandbox);
- try {
- var iniScript = null;
- var iniOpt = null;
- if (node.ini && (node.ini !== "")) {
- var iniText = `
- (async function(__send__) {
- var node = {
- id:__node__.id,
- name:__node__.name,
- outputCount:__node__.outputCount,
- log:__node__.log,
- error:__node__.error,
- warn:__node__.warn,
- debug:__node__.debug,
- trace:__node__.trace,
- status:__node__.status,
- send: function(msgs, cloneMsg) {
- __node__.send(__send__, RED.util.generateId(), msgs, cloneMsg);
- }
- };
- `+ node.ini +`
- })(__initSend__);`;
- iniOpt = createVMOpt(node, " setup");
- iniScript = new vm.Script(iniText, iniOpt);
- }
- node.script = vm.createScript(functionText, createVMOpt(node, ""));
- if (node.fin && (node.fin !== "")) {
- var finText = `(function () {
- var node = {
- id:__node__.id,
- name:__node__.name,
- outputCount:__node__.outputCount,
- log:__node__.log,
- error:__node__.error,
- warn:__node__.warn,
- debug:__node__.debug,
- trace:__node__.trace,
- status:__node__.status,
- send: function(msgs, cloneMsg) {
- __node__.error("Cannot send from close function");
- }
- };
- `+node.fin +`
- })();`;
- finOpt = createVMOpt(node, " cleanup");
- finScript = new vm.Script(finText, finOpt);
- }
- var promise = Promise.resolve();
- if (iniScript) {
- context.__initSend__ = function(msgs) { node.send(msgs); };
- promise = iniScript.runInContext(context, iniOpt);
- }
-
- processMessage = function (msg, send, done) {
- var start = process.hrtime();
- context.msg = msg;
- context.__send__ = send;
- context.__done__ = done;
-
- node.script.runInContext(context);
- context.results.then(function(results) {
- sendResults(node,send,msg._msgid,results,false);
- if (handleNodeDoneCall) {
- done();
- }
-
- var duration = process.hrtime(start);
- var converted = Math.floor((duration[0] * 1e9 + duration[1])/10000)/100;
- node.metric("duration", msg, converted);
- if (process.env.NODE_RED_FUNCTION_TIME) {
- node.status({fill:"yellow",shape:"dot",text:""+converted});
- }
- }).catch(err => {
- if ((typeof err === "object") && err.hasOwnProperty("stack")) {
- //remove unwanted part
- var index = err.stack.search(/\n\s*at ContextifyScript.Script.runInContext/);
- err.stack = err.stack.slice(0, index).split('\n').slice(0,-1).join('\n');
- var stack = err.stack.split(/\r?\n/);
-
- //store the error in msg to be used in flows
- msg.error = err;
-
- var line = 0;
- var errorMessage;
- if (stack.length > 0) {
- while (line < stack.length && stack[line].indexOf("ReferenceError") !== 0) {
- line++;
- }
-
- if (line < stack.length) {
- errorMessage = stack[line];
- var m = /:(\d+):(\d+)$/.exec(stack[line+1]);
- if (m) {
- var lineno = Number(m[1])-1;
- var cha = m[2];
- errorMessage += " (line "+lineno+", col "+cha+")";
- }
- }
- }
- if (!errorMessage) {
- errorMessage = err.toString();
- }
- done(errorMessage);
- }
- else if (typeof err === "string") {
- done(err);
- }
- else {
- done(JSON.stringify(err));
- }
- });
- }
-
- node.on("close", function() {
- if (finScript) {
- try {
- finScript.runInContext(context, finOpt);
- }
- catch (err) {
- node.error(err);
- }
- }
- while (node.outstandingTimers.length > 0) {
- clearTimeout(node.outstandingTimers.pop());
- }
- while (node.outstandingIntervals.length > 0) {
- clearInterval(node.outstandingIntervals.pop());
- }
- if (node.clearStatus) {
- node.status({});
- }
- });
-
- promise.then(function (v) {
- var msgs = messages;
- messages = [];
- while (msgs.length > 0) {
- msgs.forEach(function (s) {
- processMessage(s.msg, s.send, s.done);
- });
- msgs = messages;
- messages = [];
- }
- state = RESOLVED;
- }).catch((error) => {
- messages = [];
- state = ERROR;
- node.error(error);
- });
-
- }
- catch(err) {
- // eg SyntaxError - which v8 doesn't include line number information
- // so we can't do better than this
- updateErrorInfo(err);
- node.error(err);
- }
- }).catch(err => {
- node.error(RED._("function.error.externalModuleLoadError"));
- });
- }
- RED.nodes.registerType("function",FunctionNode, {
- dynamicModuleList: "libs",
- settings: {
- functionExternalModules: { value: true, exportable: true }
- }
- });
- RED.library.register("functions");
-};
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-switch.html b/packages/node_modules/@node-red/nodes/core/function/10-switch.html
deleted file mode 100644
index f6fc82f0a..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/10-switch.html
+++ /dev/null
@@ -1,440 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-switch.js b/packages/node_modules/@node-red/nodes/core/function/10-switch.js
deleted file mode 100644
index aa1972221..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/10-switch.js
+++ /dev/null
@@ -1,521 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- var operators = {
- 'eq': function(a, b) { return a == b; },
- 'neq': function(a, b) { return a != b; },
- 'lt': function(a, b) { return a < b; },
- 'lte': function(a, b) { return a <= b; },
- 'gt': function(a, b) { return a > b; },
- 'gte': function(a, b) { return a >= b; },
- 'btwn': function(a, b, c) { return (a >= b && a <= c) || (a <= b && a >= c); },
- 'cont': function(a, b) { return (a + "").indexOf(b) != -1; },
- 'regex': function(a, b, c, d) { return (a + "").match(new RegExp(b,d?'i':'')); },
- 'true': function(a) { return a === true; },
- 'false': function(a) { return a === false; },
- 'null': function(a) { return (typeof a == "undefined" || a === null); },
- 'nnull': function(a) { return (typeof a != "undefined" && a !== null); },
- 'empty': function(a) {
- if (typeof a === 'string' || Array.isArray(a) || Buffer.isBuffer(a)) {
- return a.length === 0;
- } else if (typeof a === 'object' && a !== null) {
- return Object.keys(a).length === 0;
- }
- return false;
- },
- 'nempty': function(a) {
- if (typeof a === 'string' || Array.isArray(a) || Buffer.isBuffer(a)) {
- return a.length !== 0;
- } else if (typeof a === 'object' && a !== null) {
- return Object.keys(a).length !== 0;
- }
- return false;
- },
- 'istype': function(a, b) {
- if (b === "array") { return Array.isArray(a); }
- else if (b === "buffer") { return Buffer.isBuffer(a); }
- else if (b === "json") {
- try { JSON.parse(a); return true; } // or maybe ??? a !== null; }
- catch(e) { return false;}
- }
- else if (b === "null") { return a === null; }
- else { return typeof a === b && !Array.isArray(a) && !Buffer.isBuffer(a) && a !== null; }
- },
- 'head': function(a, b, c, d, parts) {
- var count = Number(b);
- return (parts.index < count);
- },
- 'tail': function(a, b, c, d, parts) {
- var count = Number(b);
- return (parts.count -count <= parts.index);
- },
- 'index': function(a, b, c, d, parts) {
- var min = Number(b);
- var max = Number(c);
- var index = parts.index;
- return ((min <= index) && (index <= max));
- },
- 'hask': function(a, b) {
- return a !== undefined && a !== null && (typeof b !== "object" ) && a.hasOwnProperty(b+"");
- },
- 'jsonata_exp': function(a, b) { return (b === true); },
- 'else': function(a) { return a === true; }
- };
-
- var _maxKeptCount;
-
- function getMaxKeptCount() {
- if (_maxKeptCount === undefined) {
- var name = "nodeMessageBufferMaxLength";
- if (RED.settings.hasOwnProperty(name)) {
- _maxKeptCount = RED.settings[name];
- }
- else {
- _maxKeptCount = 0;
- }
- }
- return _maxKeptCount;
- }
-
- function getProperty(node,msg,done) {
- if (node.propertyType === 'jsonata') {
- RED.util.evaluateJSONataExpression(node.property,msg,(err,value) => {
- if (err) {
- done(RED._("switch.errors.invalid-expr",{error:err.message}));
- } else {
- done(undefined,value);
- }
- });
- } else {
- RED.util.evaluateNodeProperty(node.property,node.propertyType,node,msg,(err,value) => {
- if (err) {
- done(undefined,undefined);
- } else {
- done(undefined,value);
- }
- });
- }
- }
-
- function getV1(node,msg,rule,hasParts,done) {
- if (rule.vt === 'prev') {
- return done(undefined,node.previousValue);
- } else if (rule.vt === 'jsonata') {
- var exp = rule.v;
- if (rule.t === 'jsonata_exp') {
- if (hasParts) {
- exp.assign("I", msg.parts.index);
- exp.assign("N", msg.parts.count);
- }
- }
- RED.util.evaluateJSONataExpression(exp,msg,(err,value) => {
- if (err) {
- done(RED._("switch.errors.invalid-expr",{error:err.message}));
- } else {
- done(undefined, value);
- }
- });
- } else if (rule.vt === 'json') {
- done(undefined,"json"); // TODO: ?! invalid case
- } else if (rule.vt === 'null') {
- done(undefined,"null");
- } else {
- RED.util.evaluateNodeProperty(rule.v,rule.vt,node,msg, function(err,value) {
- if (err) {
- done(undefined, undefined);
- } else {
- done(undefined, value);
- }
- });
- }
- }
-
- function getV2(node,msg,rule,done) {
- var v2 = rule.v2;
- if (rule.v2t === 'prev') {
- return done(undefined,node.previousValue);
- } else if (rule.v2t === 'jsonata') {
- RED.util.evaluateJSONataExpression(rule.v2,msg,(err,value) => {
- if (err) {
- done(RED._("switch.errors.invalid-expr",{error:err.message}));
- } else {
- done(undefined,value);
- }
- });
- } else if (typeof v2 !== 'undefined') {
- RED.util.evaluateNodeProperty(rule.v2,rule.v2t,node,msg, function(err,value) {
- if (err) {
- done(undefined,undefined);
- } else {
- done(undefined,value);
- }
- });
- } else {
- done(undefined,v2);
- }
- }
-
- function applyRule(node, msg, property, state, done) {
- var rule = node.rules[state.currentRule];
- var v1,v2;
-
- getV1(node,msg,rule,state.hasParts, (err,value) => {
- if (err) {
- // This only happens if v1 is an invalid JSONata expr
- // But that will have already been logged and the node marked
- // invalid as part of the constructor
- return done(err);
- }
- v1 = value;
- getV2(node,msg,rule, (err,value) => {
- if (err) {
- // This only happens if v1 is an invalid JSONata expr
- // But that will have already been logged and the node marked
- // invalid as part of the constructor
- return done(err);
- }
- v2 = value;
- if (rule.t == "else") {
- property = state.elseflag;
- state.elseflag = true;
- }
- try {
- if (operators[rule.t](property,v1,v2,rule.case,msg.parts)) {
- state.onward.push(msg);
- state.elseflag = false;
- if (node.checkall == "false") {
- return done(undefined,false);
- }
- } else {
- state.onward.push(null);
- }
- done(undefined, state.currentRule < node.rules.length - 1);
- } catch(err) {
- // An error occurred evaluating the rule - for example, an
- // invalid RegExp value.
- done(err);
- }
- });
- });
- }
-
- function applyRules(node, msg, property,state,done) {
- if (!state) {
- if (node.rules.length === 0) {
- done(undefined, []);
- return;
- }
- state = {
- currentRule: 0,
- elseflag: true,
- onward: [],
- hasParts: msg.hasOwnProperty("parts") &&
- msg.parts.hasOwnProperty("id") &&
- msg.parts.hasOwnProperty("index")
- }
- }
- applyRule(node,msg,property,state,(err,hasMore) => {
- if (err) {
- return done(err);
- }
- if (hasMore) {
- state.currentRule++;
- applyRules(node,msg,property,state,done);
- } else {
- node.previousValue = property;
- done(undefined,state.onward);
- }
- });
- }
-
-
- function SwitchNode(n) {
- RED.nodes.createNode(this, n);
- this.rules = n.rules || [];
- this.property = n.property;
- this.propertyType = n.propertyType || "msg";
-
- if (this.propertyType === 'jsonata') {
- try {
- this.property = RED.util.prepareJSONataExpression(this.property,this);
- } catch(err) {
- this.error(RED._("switch.errors.invalid-expr",{error:err.message}));
- return;
- }
- }
-
- this.checkall = n.checkall || "true";
- this.previousValue = null;
- var node = this;
- var valid = true;
- var repair = n.repair;
- var needsCount = repair;
-
- for (var i=0; i 0) && (pendingCount > max_msgs)) {
- clearPending();
- node.error(RED._("switch.errors.too-many"), msg);
- }
- if (parts.hasOwnProperty("count")) {
- group.count = parts.count;
- }
- return group;
- }
-
- function drainMessageGroup(msgs,count,done) {
- var msg = msgs.shift();
- msg.parts.count = count;
- processMessage(msg,false, err => {
- if (err) {
- done(err);
- } else {
- if (msgs.length === 0) {
- done()
- } else {
- drainMessageGroup(msgs,count,done);
- }
- }
- })
- }
- function addMessageToPending(msg,done) {
- var parts = msg.parts;
- // We've already checked the msg.parts has the require bits
- var group = addMessageToGroup(parts.id, msg, parts);
- var msgs = group.msgs;
- var count = group.count;
- var msgsCount = msgs.length;
- if (count === msgsCount) {
- // We have a complete group - send the individual parts
- drainMessageGroup(msgs,count,err => {
- pendingCount -= msgsCount;
- delete pendingIn[parts.id];
- done();
- })
- return;
- }
- done();
- }
-
- function sendGroup(onwards, port_count) {
- var counts = new Array(port_count).fill(0);
- for (var i = 0; i < onwards.length; i++) {
- var onward = onwards[i];
- for (var j = 0; j < port_count; j++) {
- counts[j] += (onward[j] !== null) ? 1 : 0
- }
- }
- var ids = new Array(port_count);
- for (var j = 0; j < port_count; j++) {
- ids[j] = RED.util.generateId();
- }
- var ports = new Array(port_count);
- var indexes = new Array(port_count).fill(0);
- for (var i = 0; i < onwards.length; i++) {
- var onward = onwards[i];
- for (var j = 0; j < port_count; j++) {
- var msg = onward[j];
- if (msg) {
- var new_msg = RED.util.cloneMessage(msg);
- var parts = new_msg.parts;
- parts.id = ids[j];
- parts.index = indexes[j];
- parts.count = counts[j];
- ports[j] = new_msg;
- indexes[j]++;
- }
- else {
- ports[j] = null;
- }
- }
- node.send(ports);
- }
- }
-
- function sendGroupMessages(onward, msg) {
- var parts = msg.parts;
- var gid = parts.id;
- received[gid] = ((gid in received) ? received[gid] : 0) +1;
- var send_ok = (received[gid] === parts.count);
-
- if (!(gid in pendingOut)) {
- pendingOut[gid] = {
- onwards: []
- };
- }
- var group = pendingOut[gid];
- var onwards = group.onwards;
- onwards.push(onward);
- pendingCount++;
- if (send_ok) {
- sendGroup(onwards, onward.length, msg);
- pendingCount -= onward.length;
- delete pendingOut[gid];
- delete received[gid];
- }
- var max_msgs = getMaxKeptCount();
- if ((max_msgs > 0) && (pendingCount > max_msgs)) {
- clearPending();
- node.error(RED._("switch.errors.too-many"), msg);
- }
- }
-
- function processMessage(msg, checkParts, done) {
- var hasParts = msg.hasOwnProperty("parts") &&
- msg.parts.hasOwnProperty("id") &&
- msg.parts.hasOwnProperty("index");
-
- if (needsCount && checkParts && hasParts) {
- addMessageToPending(msg,done);
- } else {
- getProperty(node,msg,(err,property) => {
- if (err) {
- node.warn(err);
- done();
- } else {
- applyRules(node,msg,property,undefined,(err,onward) => {
- if (err) {
- node.error(err, msg);
- } else {
- if (!repair || !hasParts) {
- node.send(onward);
- } else {
- sendGroupMessages(onward, msg);
- }
- }
- done();
- });
- }
- });
- }
- }
-
- function clearPending() {
- pendingCount = 0;
- pendingId = 0;
- pendingIn = {};
- pendingOut = {};
- received = {};
- }
-
- var pendingMessages = [];
- var handlingMessage = false;
- var processMessageQueue = function(msg) {
- if (msg) {
-
- // A new message has arrived - add it to the message queue
- pendingMessages.push(msg);
- if (handlingMessage) {
- // The node is currently processing a message, so do nothing
- // more with this message
- return;
- }
- }
- if (pendingMessages.length === 0) {
- // There are no more messages to process, clear the active flag
- // and return
- handlingMessage = false;
- return;
- }
-
- // There are more messages to process. Get the next message and
- // start processing it. Recurse back in to check for any more
- var nextMsg = pendingMessages.shift();
- handlingMessage = true;
- processMessage(nextMsg,true,err => {
- if (err) {
- node.error(err,nextMsg);
- }
- processMessageQueue()
- });
- }
-
- this.on('input', function(msg) {
- processMessageQueue(msg);
- });
-
- this.on('close', function() {
- clearPending();
- });
- }
-
- RED.nodes.registerType("switch", SwitchNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/15-change.html b/packages/node_modules/@node-red/nodes/core/function/15-change.html
deleted file mode 100644
index b40039028..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/15-change.html
+++ /dev/null
@@ -1,367 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/15-change.js b/packages/node_modules/@node-red/nodes/core/function/15-change.js
deleted file mode 100644
index d177caec8..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/15-change.js
+++ /dev/null
@@ -1,357 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- function ChangeNode(n) {
- RED.nodes.createNode(this, n);
- var node = this;
-
- this.rules = n.rules;
- var rule;
- if (!this.rules) {
- rule = {
- t:(n.action=="replace"?"set":n.action),
- p:n.property||""
- }
-
- if ((rule.t === "set")||(rule.t === "move")) {
- rule.to = n.to||"";
- } else if (rule.t === "change") {
- rule.from = n.from||"";
- rule.to = n.to||"";
- rule.re = (n.reg===null||n.reg);
- }
- this.rules = [rule];
- }
-
- var valid = true;
- for (var i=0;i {
- if (err) {
- done(undefined,undefined);
- } else {
- done(undefined,value);
- }
- });
- return
- } else if (rule.tot === 'date') {
- value = Date.now();
- } else if (rule.tot === 'jsonata') {
- RED.util.evaluateJSONataExpression(rule.to,msg, (err, value) => {
- if (err) {
- done(RED._("change.errors.invalid-expr",{error:err.message}))
- } else {
- done(undefined, value);
- }
- });
- return;
- }
- done(undefined,value);
- }
-
- function getFromValueType(fromValue, done) {
- var fromType;
- var fromRE;
- if (typeof fromValue === 'number' || fromValue instanceof Number) {
- fromType = 'num';
- } else if (typeof fromValue === 'boolean') {
- fromType = 'bool'
- } else if (fromValue instanceof RegExp) {
- fromType = 're';
- fromRE = fromValue;
- } else if (typeof fromValue === 'string') {
- fromType = 'str';
- fromRE = fromValue.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
- try {
- fromRE = new RegExp(fromRE, "g");
- } catch (e) {
- done(new Error(RED._("change.errors.invalid-from",{error:e.message})));
- }
- } else {
- done(new Error(RED._("change.errors.invalid-from",{error:"unsupported type: "+(typeof fromValue)})));
- }
- done(undefined,{
- fromType,
- fromValue,
- fromRE
- });
- }
- function getFromValue(msg,rule, done) {
- var fromValue;
- var fromType;
- var fromRE;
- if (rule.t === 'change') {
- if (rule.fromt === 'msg' || rule.fromt === 'flow' || rule.fromt === 'global') {
- if (rule.fromt === "msg") {
- return getFromValueType(RED.util.getMessageProperty(msg,rule.from),done);
- } else if (rule.fromt === 'flow' || rule.fromt === 'global') {
- var contextKey = RED.util.parseContextStore(rule.from);
- if (/\[msg\./.test(context.key)) {
- // The key has a nest msg. reference to evaluate first
- context.key = RED.util.normalisePropertyExpression(contextKey.key,msg,true);
- }
- node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => {
- if (err) {
- done(err)
- } else {
- getFromValueType(fromValue,done);
- }
- });
- return;
- }
- } else {
- fromType = rule.fromt;
- fromValue = rule.from;
- fromRE = rule.fromRE;
- }
- }
- done(undefined, {
- fromType,
- fromValue,
- fromRE
- });
- }
- function applyRule(msg,rule,done) {
- var property = rule.p;
- var current;
- var fromValue;
- var fromType;
- var fromRE;
-
- try {
- getToValue(msg,rule,(err,value) => {
- if (err) {
- node.error(err, msg);
- return done(undefined,null);
- } else {
- if (rule.dc) {
- value = RED.util.cloneMessage(value);
- }
- getFromValue(msg,rule,(err,fromParts) => {
- if (err) {
- node.error(err, msg);
- return done(undefined,null);
- } else {
- fromValue = fromParts.fromValue;
- fromType = fromParts.fromType;
- fromRE = fromParts.fromRE;
- if (rule.pt === 'msg') {
- try {
- if (rule.t === 'delete') {
- RED.util.setMessageProperty(msg,property,undefined);
- } else if (rule.t === 'set') {
- if (!RED.util.setMessageProperty(msg,property,value)) {
- node.warn(RED._("change.errors.no-override",{property:property}));
- }
- } else if (rule.t === 'change') {
- current = RED.util.getMessageProperty(msg,property);
- if (typeof current === 'string') {
- if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) {
- // str representation of exact from number/boolean
- // only replace if they match exactly
- RED.util.setMessageProperty(msg,property,value);
- } else {
- current = current.replace(fromRE,value);
- RED.util.setMessageProperty(msg,property,current);
- }
- } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') {
- if (current == Number(fromValue)) {
- RED.util.setMessageProperty(msg,property,value);
- }
- } else if (typeof current === 'boolean' && fromType === 'bool') {
- if (current.toString() === fromValue) {
- RED.util.setMessageProperty(msg,property,value);
- }
- }
- }
- } catch(err) {}
- return done(undefined,msg);
- } else if (rule.pt === 'flow' || rule.pt === 'global') {
- var contextKey = RED.util.parseContextStore(property);
- if (/\[msg/.test(contextKey.key)) {
- // The key has a nest msg. reference to evaluate first
- contextKey.key = RED.util.normalisePropertyExpression(contextKey.key, msg, true)
- }
- var target = node.context()[rule.pt];
- var callback = err => {
- if (err) {
- node.error(err, msg);
- return done(undefined,null);
- } else {
- done(undefined,msg);
- }
- }
- if (rule.t === 'delete') {
- target.set(contextKey.key,undefined,contextKey.store,callback);
- } else if (rule.t === 'set') {
- target.set(contextKey.key,value,contextKey.store,callback);
- } else if (rule.t === 'change') {
- target.get(contextKey.key,contextKey.store,(err,current) => {
- if (err) {
- node.error(err, msg);
- return done(undefined,null);
- }
- if (typeof current === 'string') {
- if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) {
- // str representation of exact from number/boolean
- // only replace if they match exactly
- target.set(contextKey.key,value,contextKey.store,callback);
- } else {
- current = current.replace(fromRE,value);
- target.set(contextKey.key,current,contextKey.store,callback);
- }
- } else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') {
- if (current == Number(fromValue)) {
- target.set(contextKey.key,value,contextKey.store,callback);
- }
- } else if (typeof current === 'boolean' && fromType === 'bool') {
- if (current.toString() === fromValue) {
- target.set(contextKey.key,value,contextKey.store,callback);
- }
- }
- });
- }
- }
- }
- })
- }
- });
- } catch(err) {
- // This is an okay error
- done(undefined,msg);
- }
- }
- function completeApplyingRules(msg,currentRule,done) {
- if (!msg) {
- return done();
- } else if (currentRule === node.rules.length - 1) {
- return done(undefined, msg);
- } else {
- applyRules(msg, currentRule+1,done);
- }
- }
- function applyRules(msg, currentRule, done) {
- if (currentRule >= node.rules.length) {
- return done(undefined,msg);
- }
- var r = node.rules[currentRule];
- if (r.t === "move") {
- if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) {
- applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => {
- applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => {
- completeApplyingRules(msg,currentRule,done);
- })
- });
- } else { // 2 step move if we are moving from a child
- applyRule(msg,{t:"set", p:"_temp_move", pt:r.tot, to:r.p, tot:r.pt},(err,msg)=> {
- applyRule(msg,{t:"delete", p:r.p, pt:r.pt},(err,msg)=> {
- applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:"_temp_move", tot:r.pt},(err,msg)=> {
- applyRule(msg,{t:"delete", p:"_temp_move", pt:r.pt},(err,msg)=> {
- completeApplyingRules(msg,currentRule,done);
- });
- });
- });
- });
- }
- } else {
- applyRule(msg,r,(err,msg)=> { completeApplyingRules(msg,currentRule,done); });
- }
- }
-
- if (valid) {
- this.on('input', function(msg, send, done) {
- applyRules(msg, 0, (err,msg) => {
- if (err) {
- done(err);
- } else if (msg) {
- send(msg);
- done();
- }
- })
- });
- }
- }
- RED.nodes.registerType("change", ChangeNode);
-};
diff --git a/packages/node_modules/@node-red/nodes/core/function/16-range.html b/packages/node_modules/@node-red/nodes/core/function/16-range.html
deleted file mode 100644
index f108a99ce..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/16-range.html
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/16-range.js b/packages/node_modules/@node-red/nodes/core/function/16-range.js
deleted file mode 100644
index a5dede4ea..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/16-range.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- function RangeNode(n) {
- RED.nodes.createNode(this, n);
- this.action = n.action;
- this.round = n.round || false;
- this.minin = Number(n.minin);
- this.maxin = Number(n.maxin);
- this.minout = Number(n.minout);
- this.maxout = Number(n.maxout);
- this.property = n.property||"payload";
- var node = this;
-
- this.on('input', function (msg, send, done) {
- var value = RED.util.getMessageProperty(msg,node.property);
- if (value !== undefined) {
- var n = Number(value);
- if (!isNaN(n)) {
- if (node.action == "clamp") {
- if (n < node.minin) { n = node.minin; }
- if (n > node.maxin) { n = node.maxin; }
- }
- if (node.action == "roll") {
- var divisor = node.maxin - node.minin;
- n = ((n - node.minin) % divisor + divisor) % divisor + node.minin;
- }
- value = ((n - node.minin) / (node.maxin - node.minin) * (node.maxout - node.minout)) + node.minout;
- if (node.round) { value = Math.round(value); }
- RED.util.setMessageProperty(msg,node.property,value);
- send(msg);
- }
- else { node.log(RED._("range.errors.notnumber")+": "+value); }
- }
- else { send(msg); } // If no payload - just pass it on.
- done();
- });
- }
- RED.nodes.registerType("range", RangeNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/80-template.html b/packages/node_modules/@node-red/nodes/core/function/80-template.html
deleted file mode 100644
index 98d4a0d37..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/80-template.html
+++ /dev/null
@@ -1,155 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/80-template.js b/packages/node_modules/@node-red/nodes/core/function/80-template.js
deleted file mode 100644
index d4c27cfd0..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/80-template.js
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var mustache = require("mustache");
- var yaml = require("js-yaml");
-
- function extractTokens(tokens,set) {
- set = set || new Set();
- tokens.forEach(function(token) {
- if (token[0] !== 'text') {
- set.add(token[1]);
- if (token.length > 4) {
- extractTokens(token[4],set);
- }
- }
- });
- return set;
- }
-
- function parseContext(key) {
- var match = /^(flow|global)(\[(\w+)\])?\.(.+)/.exec(key);
- if (match) {
- var parts = {};
- parts.type = match[1];
- parts.store = (match[3] === '') ? "default" : match[3];
- parts.field = match[4];
- return parts;
- }
- return undefined;
- }
-
- /**
- * Custom Mustache Context capable to collect message property and node
- * flow and global context
- */
-
- function NodeContext(msg, nodeContext, parent, escapeStrings, cachedContextTokens) {
- this.msgContext = new mustache.Context(msg,parent);
- this.nodeContext = nodeContext;
- this.escapeStrings = escapeStrings;
- this.cachedContextTokens = cachedContextTokens;
- }
-
- NodeContext.prototype = new mustache.Context();
-
- NodeContext.prototype.lookup = function (name) {
- // try message first:
- try {
- var value = this.msgContext.lookup(name);
- if (value !== undefined) {
- if (this.escapeStrings && typeof value === "string") {
- value = value.replace(/\\/g, "\\\\");
- value = value.replace(/\n/g, "\\n");
- value = value.replace(/\t/g, "\\t");
- value = value.replace(/\r/g, "\\r");
- value = value.replace(/\f/g, "\\f");
- value = value.replace(/[\b]/g, "\\b");
- }
- return value;
- }
-
- // try flow/global context:
- var context = parseContext(name);
- if (context) {
- var type = context.type;
- var store = context.store;
- var field = context.field;
- var target = this.nodeContext[type];
- if (target) {
- return this.cachedContextTokens[name];
- }
- }
- return '';
- }
- catch(err) {
- throw err;
- }
- }
-
- NodeContext.prototype.push = function push (view) {
- return new NodeContext(view, this.nodeContext, this.msgContext, undefined, this.cachedContextTokens);
- };
-
- function TemplateNode(n) {
- RED.nodes.createNode(this,n);
- this.name = n.name;
- this.field = n.field || "payload";
- this.template = n.template;
- this.syntax = n.syntax || "mustache";
- this.fieldType = n.fieldType || "msg";
- this.outputFormat = n.output || "str";
-
- var node = this;
-
- function output(msg,value,send,done) {
- /* istanbul ignore else */
- if (node.outputFormat === "json") {
- value = JSON.parse(value);
- }
- /* istanbul ignore else */
- if (node.outputFormat === "yaml") {
- value = yaml.load(value);
- }
-
- if (node.fieldType === 'msg') {
- RED.util.setMessageProperty(msg, node.field, value);
- send(msg);
- done();
- } else if ((node.fieldType === 'flow') ||
- (node.fieldType === 'global')) {
- var context = RED.util.parseContextStore(node.field);
- var target = node.context()[node.fieldType];
- target.set(context.key, value, context.store, function (err) {
- if (err) {
- done(err);
- } else {
- send(msg);
- done();
- }
- });
- }
- }
-
- node.on("input", function(msg, send, done) {
-
- try {
- /***
- * Allow template contents to be defined externally
- * through inbound msg.template IFF node.template empty
- */
- var template = node.template;
- if (msg.hasOwnProperty("template")) {
- if (template == "" || template === null) {
- template = msg.template;
- }
- }
-
- if (node.syntax === "mustache") {
- var is_json = (node.outputFormat === "json");
- var promises = [];
- var tokens = extractTokens(mustache.parse(template));
- var resolvedTokens = {};
- tokens.forEach(function(name) {
- var context = parseContext(name);
- if (context) {
- var type = context.type;
- var store = context.store;
- var field = context.field;
- var target = node.context()[type];
- if (target) {
- var promise = new Promise((resolve, reject) => {
- target.get(field, store, (err, val) => {
- if (err) {
- reject(err);
- } else {
- resolvedTokens[name] = val;
- resolve();
- }
- });
- });
- promises.push(promise);
- return;
- }
- }
- });
-
- Promise.all(promises).then(function() {
- var value = mustache.render(template, new NodeContext(msg, node.context(), null, is_json, resolvedTokens));
- output(msg, value, send, done);
- }).catch(function (err) {
- done(err.message);
- });
- } else {
- output(msg, template, send, done);
- }
- }
- catch(err) {
- done(err.message);
- }
- });
- }
-
- RED.nodes.registerType("template",TemplateNode);
- RED.library.register("templates");
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/89-delay.html b/packages/node_modules/@node-red/nodes/core/function/89-delay.html
deleted file mode 100644
index 3ae4637d7..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/89-delay.html
+++ /dev/null
@@ -1,283 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/89-delay.js b/packages/node_modules/@node-red/nodes/core/function/89-delay.js
deleted file mode 100644
index 5205a5b18..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/89-delay.js
+++ /dev/null
@@ -1,424 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-//Simple node to introduce a pause into a flow
-module.exports = function(RED) {
- "use strict";
-
- var MILLIS_TO_NANOS = 1000000;
- var SECONDS_TO_NANOS = 1000000000;
- var _maxKeptMsgsCount;
-
- function maxKeptMsgsCount(node) {
- if (_maxKeptMsgsCount === undefined) {
- var name = "nodeMessageBufferMaxLength";
- if (RED.settings.hasOwnProperty(name)) {
- _maxKeptMsgsCount = RED.settings[name];
- }
- else {
- _maxKeptMsgsCount = 0;
- }
- }
- return _maxKeptMsgsCount;
- }
-
- function DelayNode(n) {
- RED.nodes.createNode(this,n);
-
- this.pauseType = n.pauseType;
- this.timeoutUnits = n.timeoutUnits;
- this.randomUnits = n.randomUnits;
- this.rateUnits = n.rateUnits;
-
- if (n.timeoutUnits === "milliseconds") {
- this.timeout = n.timeout;
- } else if (n.timeoutUnits === "minutes") {
- this.timeout = n.timeout * (60 * 1000);
- } else if (n.timeoutUnits === "hours") {
- this.timeout = n.timeout * (60 * 60 * 1000);
- } else if (n.timeoutUnits === "days") {
- this.timeout = n.timeout * (24 * 60 * 60 * 1000);
- } else { // Default to seconds
- this.timeout = n.timeout * 1000;
- }
-
- if (n.rateUnits === "minute") {
- this.rate = (60 * 1000)/n.rate;
- } else if (n.rateUnits === "hour") {
- this.rate = (60 * 60 * 1000)/n.rate;
- } else if (n.rateUnits === "day") {
- this.rate = (24 * 60 * 60 * 1000)/n.rate;
- } else { // Default to seconds
- this.rate = 1000/n.rate;
- }
-
- this.rate *= (n.nbRateUnits > 0 ? n.nbRateUnits : 1);
-
- if (n.randomUnits === "milliseconds") {
- this.randomFirst = n.randomFirst * 1;
- this.randomLast = n.randomLast * 1;
- } else if (n.randomUnits === "minutes") {
- this.randomFirst = n.randomFirst * (60 * 1000);
- this.randomLast = n.randomLast * (60 * 1000);
- } else if (n.randomUnits === "hours") {
- this.randomFirst = n.randomFirst * (60 * 60 * 1000);
- this.randomLast = n.randomLast * (60 * 60 * 1000);
- } else if (n.randomUnits === "days") {
- this.randomFirst = n.randomFirst * (24 * 60 * 60 * 1000);
- this.randomLast = n.randomLast * (24 * 60 * 60 * 1000);
- } else { // Default to seconds
- this.randomFirst = n.randomFirst * 1000;
- this.randomLast = n.randomLast * 1000;
- }
-
- this.diff = this.randomLast - this.randomFirst;
- this.name = n.name;
- this.idList = [];
- this.buffer = [];
- this.intervalID = -1;
- this.randomID = -1;
- this.lastSent = null;
- this.drop = n.drop;
- this.droppedMsgs = 0;
- this.allowrate = n.allowrate|| false;
- this.fixedrate = this.rate;
- this.outputs = n.outputs;
- var node = this;
-
- function ourTimeout(handler, delay, clearHandler) {
- var toutID = setTimeout(handler, delay);
- return {
- clear: function() { clearTimeout(toutID); clearHandler(); },
- trigger: function() { clearTimeout(toutID); return handler(); }
- };
- }
-
- var sendMsgFromBuffer = function() {
- if (node.buffer.length === 0) {
- clearInterval(node.intervalID);
- node.intervalID = -1;
- }
- if (node.buffer.length > 0) {
- const msgInfo = node.buffer.shift();
- if (Object.keys(msgInfo.msg).length > 1) {
- msgInfo.send(msgInfo.msg);
- msgInfo.done();
- }
- }
- node.reportDepth();
- }
-
- var clearDelayList = function(s) {
- var len = node.idList.length;
- for (var i=0; i 0) { node.status({text:node.buffer.length}); }
- // else { node.status({}); }
- node.status({fill:"blue",shape:"dot",text:node.buffer.length});
- node.busy = null;
- }, 500);
- }
- }
-
- var loggerId = setInterval(function () {
- if (node.droppedMsgs !== 0) {
- node.debug("node.droppedMsgs = " + node.droppedMsgs);
- node.droppedMsgs = 0;
- }
- }, 15 * 1000);
- node.on("close", function() { clearInterval(loggerId); });
-
- // The delay type modes
- if (node.pauseType === "delay") {
- node.on("input", function(msg, send, done) {
- var id = ourTimeout(function() {
- node.idList.splice(node.idList.indexOf(id),1);
- if (node.timeout > 1000) {
- node.status({fill:"blue",shape:"dot",text:node.idList.length});
- }
- send(msg);
- done();
- }, node.timeout, () => done());
- if (Object.keys(msg).length === 2 && msg.hasOwnProperty("flush")) { id.clear(); }
- else { node.idList.push(id); }
- if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
- else if (msg.hasOwnProperty("flush")) { flushDelayList(msg.flush); done(); }
- else if (node.timeout > 1000) {
- node.status({fill:"blue",shape:"dot",text:node.idList.length});
- }
- });
- node.on("close", function() { clearDelayList(); });
- }
- else if (node.pauseType === "delayv") {
- node.on("input", function(msg, send, done) {
- var delayvar = Number(node.timeout);
- if (msg.hasOwnProperty("delay") && !isNaN(parseFloat(msg.delay))) {
- delayvar = parseFloat(msg.delay);
- }
- if (delayvar < 0) { delayvar = 0; }
- var id = ourTimeout(function() {
- node.idList.splice(node.idList.indexOf(id),1);
- if (node.idList.length === 0) { node.status({}); }
- send(msg);
- if (delayvar >= 0) {
- node.status({fill:"blue",shape:"dot",text:node.idList.length});
- }
- done();
- }, delayvar, () => done());
- node.idList.push(id);
- if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
- if (msg.hasOwnProperty("flush")) { flushDelayList(msg.flush); done(); }
- if (delayvar >= 0) {
- node.status({fill:"blue",shape:"dot",text:node.idList.length});
- }
- });
- node.on("close", function() { clearDelayList(); });
- }
- else if (node.pauseType === "random") {
- node.on("input", function(msg, send, done) {
- var wait = node.randomFirst + (node.diff * Math.random());
- var id = ourTimeout(function() {
- node.idList.splice(node.idList.indexOf(id),1);
- send(msg);
- if (node.timeout >= 1000) {
- node.status({fill:"blue",shape:"dot",text:node.idList.length});
- }
- done();
- }, wait, () => done());
- if (Object.keys(msg).length === 2 && msg.hasOwnProperty("flush")) { id.clear(); }
- else { node.idList.push(id); }
- if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
- if (msg.hasOwnProperty("flush")) { flushDelayList(msg.flush); done(); }
- if (node.timeout >= 1000) {
- node.status({fill:"blue",shape:"dot",text:node.idList.length});
- }
- });
- node.on("close", function() { clearDelayList(); });
- }
-
- // The rate limit/queue type modes
- else if (node.pauseType === "rate") {
- node.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("reset")) {
- if (node.intervalID !== -1 ) {
- clearInterval(node.intervalID);
- node.intervalID = -1;
- }
- delete node.lastSent;
- node.buffer = [];
- node.rate = node.fixedrate;
- node.status({fill:"blue",shape:"ring",text:0});
- done();
- return;
- }
-
- if (!node.drop) {
- var m = RED.util.cloneMessage(msg);
- delete m.flush;
- delete m.lifo;
- if (Object.keys(m).length > 1) {
- if (node.intervalID !== -1) {
- if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
- node.rate = msg.rate;
- clearInterval(node.intervalID);
- node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
- }
- var max_msgs = maxKeptMsgsCount(node);
- if ((max_msgs > 0) && (node.buffer.length >= max_msgs)) {
- node.buffer = [];
- node.error(RED._("delay.errors.too-many"), msg);
- } else if (msg.toFront === true) {
- node.buffer.unshift({msg: m, send: send, done: done});
- node.reportDepth();
- } else {
- node.buffer.push({msg: m, send: send, done: done});
- node.reportDepth();
- }
- }
- else {
- if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
- node.rate = msg.rate;
- }
- send(m);
- node.reportDepth();
- node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
- done();
- }
- }
- if (msg.hasOwnProperty("flush")) {
- var len = node.buffer.length;
- if (typeof(msg.flush) == 'number') { len = Math.min(Math.floor(msg.flush),len); }
- while (len > 0) {
- const msgInfo = node.buffer.shift();
- if (Object.keys(msgInfo.msg).length > 1) {
- node.send(msgInfo.msg);
- msgInfo.done();
- }
- len = len - 1;
- }
- if (node.buffer.length === 0) {
- clearInterval(node.intervalID);
- node.intervalID = -1;
- }
- node.status({fill:"blue",shape:"dot",text:node.buffer.length});
- done();
- }
- }
- else {
- if (maxKeptMsgsCount(node) > 0) {
- if (node.intervalID === -1) {
- node.send(msg);
- node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
- } else {
- if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
- node.rate = msg.rate;
- clearInterval(node.intervalID);
- node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
- }
- if (node.buffer.length < _maxKeptMsgsCount) {
- var m = RED.util.cloneMessage(msg);
- node.buffer.push({msg: m, send: send, done: done});
- } else {
- node.trace("dropped due to buffer overflow. msg._msgid = " + msg._msgid);
- node.droppedMsgs++;
- }
- }
- } else {
- if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
- node.rate = msg.rate;
- }
- var timeSinceLast;
- if (node.lastSent) {
- timeSinceLast = process.hrtime(node.lastSent);
- }
- if (!node.lastSent) { // ensuring that we always send the first message
- node.lastSent = process.hrtime();
- send(msg);
- }
- else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) {
- node.lastSent = process.hrtime();
- send(msg);
- } else if (node.outputs === 2) {
- send([null,msg])
- }
- }
- done();
- }
- });
- node.on("close", function() {
- clearInterval(node.intervalID);
- clearTimeout(node.busy);
- node.buffer.forEach((msgInfo) => msgInfo.done());
- node.buffer = [];
- node.status({});
- });
- }
-
- // The topic based fair queue and last arrived on all topics queue
- else if ((node.pauseType === "queue") || (node.pauseType === "timed")) {
- node.intervalID = setInterval(function() {
- if (node.pauseType === "queue") {
- if (node.buffer.length > 0) {
- const msgInfo = node.buffer.shift();
- msgInfo.send(msgInfo.msg); // send the first on the queue
- msgInfo.done();
- }
- }
- else {
- while (node.buffer.length > 0) { // send the whole queue
- const msgInfo = node.buffer.shift();
- msgInfo.send(msgInfo.msg);
- msgInfo.done();
- }
- }
- node.reportDepth();
- },node.rate);
-
- var hit;
- node.on("input", function(msg, send, done) {
- if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
- node.rate = msg.rate;
- clearInterval(node.intervalID);
- node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
- }
- if (!msg.hasOwnProperty("topic")) { msg.topic = "_none_"; }
- hit = false;
- for (var b in node.buffer) { // check if already in queue
- if (msg.topic === node.buffer[b].msg.topic) {
- if (node.outputs === 2) { send([null,node.buffer[b].msg]) }
- node.buffer[b].done();
- node.buffer[b] = {msg, send, done}; // if so - replace existing entry
- hit = true;
- break;
- }
- }
- if (!hit) {
- node.buffer.push({msg, send, done}); // if not add to end of queue
- node.reportDepth();
- }
- if (msg.hasOwnProperty("reset")) {
- while (node.buffer.length > 0) {
- const msgInfo = node.buffer.shift();
- msgInfo.done();
- }
- node.buffer = [];
- node.rate = node.fixedrate;
- node.status({text:"reset"});
- done();
- }
- if (msg.hasOwnProperty("flush")) {
- var len = node.buffer.length;
- if (typeof(msg.flush) == 'number') { len = Math.min(Math.floor(msg.flush,len)); }
- while (len > 0) {
- const msgInfo = node.buffer.shift();
- delete msgInfo.msg.flush;
- if (Object.keys(msgInfo.msg).length > 2) {
- node.send(msgInfo.msg);
- msgInfo.done();
- }
- len = len - 1;
- }
- node.status({});
- done();
- }
- });
- node.on("close", function() {
- clearInterval(node.intervalID);
- while (node.buffer.length > 0) {
- const msgInfo = node.buffer.shift();
- msgInfo.done();
- }
- node.buffer = [];
- node.status({});
- });
- }
- }
- RED.nodes.registerType("delay",DelayNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/89-trigger.html b/packages/node_modules/@node-red/nodes/core/function/89-trigger.html
deleted file mode 100644
index a7ab0356f..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/89-trigger.html
+++ /dev/null
@@ -1,234 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js b/packages/node_modules/@node-red/nodes/core/function/89-trigger.js
deleted file mode 100644
index 16a00e99d..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/89-trigger.js
+++ /dev/null
@@ -1,298 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var mustache = require("mustache");
- function TriggerNode(n) {
- RED.nodes.createNode(this,n);
- this.bytopic = n.bytopic || "all";
- this.op1 = n.op1 || "1";
- this.op2 = n.op2 || "0";
- this.op1type = n.op1type || "str";
- this.op2type = n.op2type || "str";
- this.second = (n.outputs == 2) ? true : false;
- this.topic = n.topic || "topic";
-
- if (this.op1type === 'val') {
- if (this.op1 === 'true' || this.op1 === 'false') {
- this.op1type = 'bool'
- } else if (this.op1 === 'null') {
- this.op1type = 'null';
- this.op1 = null;
- } else {
- this.op1type = 'str';
- }
- }
- if (this.op2type === 'val') {
- if (this.op2 === 'true' || this.op2 === 'false') {
- this.op2type = 'bool'
- } else if (this.op2 === 'null') {
- this.op2type = 'null';
- this.op2 = null;
- } else {
- this.op2type = 'str';
- }
- }
- this.extend = n.extend || "false";
- this.overrideDelay = n.overrideDelay || false;
- this.units = n.units || "ms";
- this.reset = n.reset || '';
- this.duration = parseFloat(n.duration);
- if (isNaN(this.duration)) {
- this.duration = 250;
- }
- if (this.duration < 0) {
- this.loop = true;
- this.duration = this.duration * -1;
- this.extend = false;
- }
-
- if (this.units == "s") { this.duration = this.duration * 1000; }
- if (this.units == "min") { this.duration = this.duration * 1000 * 60; }
- if (this.units == "hr") { this.duration = this.duration * 1000 *60 * 60; }
-
- this.op1Templated = (this.op1type === 'str' && this.op1.indexOf("{{") != -1);
- this.op2Templated = (this.op2type === 'str' && this.op2.indexOf("{{") != -1);
- if ((this.op1type === "num") && (!isNaN(this.op1))) { this.op1 = Number(this.op1); }
- if ((this.op2type === "num") && (!isNaN(this.op2))) { this.op2 = Number(this.op2); }
- //if (this.op1 == "null") { this.op1 = null; }
- //if (this.op2 == "null") { this.op2 = null; }
- //try { this.op1 = JSON.parse(this.op1); }
- //catch(e) { this.op1 = this.op1; }
- //try { this.op2 = JSON.parse(this.op2); }
- //catch(e) { this.op2 = this.op2; }
-
- var node = this;
- node.topics = {};
-
- var npay = {};
- var pendingMessages = [];
- var activeMessagePromise = null;
- var processMessageQueue = function(msgInfo) {
- if (msgInfo) {
- // A new message has arrived - add it to the message queue
- pendingMessages.push(msgInfo);
- if (activeMessagePromise !== null) {
- // The node is currently processing a message, so do nothing
- // more with this message
- return;
- }
- }
- if (pendingMessages.length === 0) {
- // There are no more messages to process, clear the active flag
- // and return
- activeMessagePromise = null;
- return;
- }
-
- // There are more messages to process. Get the next message and
- // start processing it. Recurse back in to check for any more
- var nextMsgInfo = pendingMessages.shift();
- activeMessagePromise = processMessage(nextMsgInfo)
- .then(processMessageQueue)
- .catch((err) => {
- nextMsgInfo.done(err);
- return processMessageQueue();
- });
- }
-
- this.on('input', function(msg, send, done) {
- processMessageQueue({msg, send, done});
- });
-
- var stat = function() {
- var l = Object.keys(node.topics).length;
- if (l === 0) { return {} }
- else if (l === 1) { return {fill:"blue",shape:"dot"} }
- else return {fill:"blue",shape:"dot",text:l};
- }
-
- var processMessage = function(msgInfo) {
- let msg = msgInfo.msg;
- var topic = RED.util.getMessageProperty(msg,node.topic) || "_none";
- var promise;
- var delayDuration = node.duration;
- if (node.overrideDelay && msg.hasOwnProperty("delay") && !isNaN(parseFloat(msg.delay))) {
- delayDuration = parseFloat(msg.delay);
- }
- if (node.bytopic === "all") { topic = "_none"; }
- node.topics[topic] = node.topics[topic] || {};
- if (msg.hasOwnProperty("reset") || ((node.reset !== '') && msg.hasOwnProperty("payload") && (msg.payload !== null) && msg.payload.toString && (msg.payload.toString() == node.reset)) ) {
- if (node.loop === true) { clearInterval(node.topics[topic].tout); }
- else { clearTimeout(node.topics[topic].tout); }
- delete node.topics[topic];
- node.status(stat());
- }
- else {
- if (node.op2type === "payl") { npay[topic] = RED.util.cloneMessage(msg); }
- if (((!node.topics[topic].tout) && (node.topics[topic].tout !== 0)) || (node.loop === true)) {
- promise = Promise.resolve();
- if (node.op2type === "pay") { node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
- else if (node.op2Templated) { node.topics[topic].m2 = mustache.render(node.op2,msg); }
- else if (node.op2type !== "nul") {
- promise = new Promise((resolve,reject) => {
- RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg,(err,value) => {
- if (err) {
- reject(err);
- } else {
- node.topics[topic].m2 = value;
- resolve();
- }
- });
- });
- }
-
- return promise.then(() => {
- promise = Promise.resolve();
- if (node.op1type === "pay") { }
- else if (node.op1Templated) { msg.payload = mustache.render(node.op1,msg); }
- else if (node.op1type !== "nul") {
- promise = new Promise((resolve,reject) => {
- RED.util.evaluateNodeProperty(node.op1,node.op1type,node,msg,(err,value) => {
- if (err) {
- reject(err);
- } else {
- msg.payload = value;
- resolve();
- }
- });
- });
- }
- return promise.then(() => {
- if (delayDuration === 0) { node.topics[topic].tout = 0; }
- else if (node.loop === true) {
- /* istanbul ignore else */
- if (node.topics[topic].tout) { clearInterval(node.topics[topic].tout); }
- /* istanbul ignore else */
- if (node.op1type !== "nul") {
- var msg2 = RED.util.cloneMessage(msg);
- node.topics[topic].tout = setInterval(function() {
- if (node.op1type === "date") { msg2.payload = Date.now(); }
- msgInfo.send(RED.util.cloneMessage(msg2));
- }, delayDuration);
- }
- }
- else {
- if (!node.topics[topic].tout) {
- node.topics[topic].tout = setTimeout(function() {
- var msg2 = null;
- if (node.op2type !== "nul") {
- var promise = Promise.resolve();
- msg2 = RED.util.cloneMessage(msg);
- if (node.op2type === "flow" || node.op2type === "global") {
- promise = new Promise((resolve,reject) => {
- RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg,(err,value) => {
- if (err) {
- reject(err);
- } else {
- node.topics[topic].m2 = value;
- resolve();
- }
- });
- });
- }
- promise.then(() => {
- if (node.op2type === "payl") {
- if (node.second === true) { msgInfo.send([null,npay[topic]]); }
- else { msgInfo.send(npay[topic]); }
- delete npay[topic];
- }
- else {
- msg2.payload = node.topics[topic].m2;
- if (node.op2type === "date") { msg2.payload = Date.now(); }
- if (node.second === true) { msgInfo.send([null,msg2]); }
- else { msgInfo.send(msg2); }
- }
- delete node.topics[topic];
- node.status(stat());
- }).catch(err => {
- node.error(err);
- });
- } else {
- delete node.topics[topic];
- node.status(stat());
- }
-
- }, delayDuration);
- }
- }
- msgInfo.done();
- node.status(stat());
- if (node.op1type !== "nul") { msgInfo.send(RED.util.cloneMessage(msg)); }
- });
- });
- }
- else if ((node.extend === "true" || node.extend === true) && (delayDuration > 0)) {
- /* istanbul ignore else */
- if (node.op2type === "payl") { node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
- /* istanbul ignore else */
- if (node.topics[topic].tout) { clearTimeout(node.topics[topic].tout); }
- node.topics[topic].tout = setTimeout(function() {
- var msg2 = null;
- var promise = Promise.resolve();
-
- if (node.op2type !== "nul") {
- if (node.op2type === "flow" || node.op2type === "global") {
- promise = new Promise((resolve,reject) => {
- RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg,(err,value) => {
- if (err) {
- reject(err);
- } else {
- node.topics[topic].m2 = value;
- resolve();
- }
- });
- });
- }
- }
- promise.then(() => {
- if (node.op2type !== "nul") {
- if (node.topics[topic] !== undefined) {
- msg2 = RED.util.cloneMessage(msg);
- msg2.payload = node.topics[topic].m2;
- }
- }
- delete node.topics[topic];
- node.status(stat());
- if (node.second === true) { msgInfo.send([null,msg2]); }
- else { msgInfo.send(msg2); }
- }).catch(err => {
- node.error(err);
- });
- }, delayDuration);
- }
- // else {
- // if (node.op2type === "payl") {node.topics[topic].m2 = RED.util.cloneMessage(msg.payload); }
- // }
- }
- msgInfo.done();
- return Promise.resolve();
- }
- this.on("close", function() {
- for (var t in node.topics) {
- /* istanbul ignore else */
- if (node.topics[t]) {
- if (node.loop === true) { clearInterval(node.topics[t].tout); }
- else { clearTimeout(node.topics[t].tout); }
- delete node.topics[t];
- }
- }
- node.status(stat());
- });
- }
- RED.nodes.registerType("trigger",TriggerNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/90-exec.html b/packages/node_modules/@node-red/nodes/core/function/90-exec.html
deleted file mode 100644
index ea988a84a..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/90-exec.html
+++ /dev/null
@@ -1,113 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/90-exec.js b/packages/node_modules/@node-red/nodes/core/function/90-exec.js
deleted file mode 100644
index cf4168ae8..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/90-exec.js
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var spawn = require('child_process').spawn;
- var exec = require('child_process').exec;
- var fs = require('fs');
- var isUtf8 = require('is-utf8');
-
- function ExecNode(n) {
- RED.nodes.createNode(this,n);
- this.cmd = (n.command || "").trim();
- if (n.addpay === undefined) { n.addpay = true; }
- this.addpay = n.addpay;
- if (this.addpay === true) {
- this.addpay = "payload";
- }
- this.append = (n.append || "").trim();
- this.useSpawn = (n.useSpawn == "true");
- this.timer = Number(n.timer || 0)*1000;
- this.activeProcesses = {};
- this.oldrc = (n.oldrc || false).toString();
- this.execOpt = {encoding:'binary', maxBuffer:RED.settings.execMaxBufferSize||10000000, windowsHide: (n.winHide === true)};
- this.spawnOpt = {windowsHide: (n.winHide === true) }
- var node = this;
-
- if (process.platform === 'linux' && fs.existsSync('/bin/bash')) { node.execOpt.shell = '/bin/bash'; }
-
- var cleanup = function(p) {
- node.activeProcesses[p].kill();
- //node.status({fill:"red",shape:"dot",text:"timeout"});
- //node.error("Exec node timeout");
- }
-
- this.on("input", function(msg, nodeSend, nodeDone) {
- if (msg.hasOwnProperty("kill")) {
- if (typeof msg.kill !== "string" || msg.kill.length === 0 || !msg.kill.toUpperCase().startsWith("SIG") ) { msg.kill = "SIGTERM"; }
- if (msg.hasOwnProperty("pid")) {
- if (node.activeProcesses.hasOwnProperty(msg.pid) ) {
- node.activeProcesses[msg.pid].kill(msg.kill.toUpperCase());
- node.status({fill:"red",shape:"dot",text:"killed"});
- }
- }
- else {
- if (Object.keys(node.activeProcesses).length === 1) {
- node.activeProcesses[Object.keys(node.activeProcesses)[0]].kill(msg.kill.toUpperCase());
- node.status({fill:"red",shape:"dot",text:"killed"});
- }
- }
- nodeDone();
- }
- else {
- var child;
- // make the extra args into an array
- // then prepend with the msg.payload
- var arg = node.cmd;
- if (node.addpay) {
- var value = RED.util.getMessageProperty(msg, node.addpay);
- if (value !== undefined) {
- arg += " " + value;
- }
- }
- if (node.append.trim() !== "") { arg += " " + node.append; }
- if (this.useSpawn === true) {
- // slice whole line by spaces and removes any quotes since spawn can't handle them
- arg = arg.match(/(?:[^\s"]+|"[^"]*")+/g).map((a) => {
- if (/^".*"$/.test(a)) {
- return a.slice(1,-1)
- } else {
- return a
- }
- });
- var cmd = arg.shift();
- /* istanbul ignore else */
- if (RED.settings.verbose) { node.log(cmd+" ["+arg+"]"); }
- child = spawn(cmd,arg,node.spawnOpt);
- node.status({fill:"blue",shape:"dot",text:"pid:"+child.pid});
- var unknownCommand = (child.pid === undefined);
- if (node.timer !== 0) {
- child.tout = setTimeout(function() { cleanup(child.pid); }, node.timer);
- }
- node.activeProcesses[child.pid] = child;
- child.stdout.on('data', function (data) {
- if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
- // console.log('[exec] stdout: ' + data,child.pid);
- if (isUtf8(data)) { msg.payload = data.toString(); }
- else { msg.payload = data; }
- nodeSend([RED.util.cloneMessage(msg),null,null]);
- }
- });
- child.stderr.on('data', function (data) {
- if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
- if (isUtf8(data)) { msg.payload = data.toString(); }
- else { msg.payload = Buffer.from(data); }
- nodeSend([null,RED.util.cloneMessage(msg),null]);
- }
- });
- child.on('close', function (code,signal) {
- if (unknownCommand || (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null)) {
- delete node.activeProcesses[child.pid];
- if (child.tout) { clearTimeout(child.tout); }
- msg.payload = code;
- if (node.oldrc === "false") {
- msg.payload = {code:code};
- if (signal) { msg.payload.signal = signal; }
- }
- if (code === 0) { node.status({}); }
- if (code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
- else if (code < 0) { node.status({fill:"red",shape:"dot",text:"rc:"+code}); }
- else { node.status({fill:"yellow",shape:"dot",text:"rc:"+code}); }
- nodeSend([null,null,RED.util.cloneMessage(msg)]);
- }
- nodeDone();
- });
- child.on('error', function (code) {
- if (child.tout) { clearTimeout(child.tout); }
- delete node.activeProcesses[child.pid];
- if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
- node.error(code,RED.util.cloneMessage(msg));
- }
- });
- }
- else {
- /* istanbul ignore else */
- if (RED.settings.verbose) { node.log(arg); }
- child = exec(arg, node.execOpt, function (error, stdout, stderr) {
- var msg2, msg3;
- delete msg.payload;
- if (stderr) {
- msg2 = RED.util.cloneMessage(msg);
- msg2.payload = stderr;
- }
- msg.payload = Buffer.from(stdout,"binary");
- if (isUtf8(msg.payload)) { msg.payload = msg.payload.toString(); }
- node.status({});
- //console.log('[exec] stdout: ' + stdout);
- //console.log('[exec] stderr: ' + stderr);
- if (error !== null) {
- msg3 = RED.util.cloneMessage(msg);
- msg3.payload = {code:error.code, message:error.message};
- if (error.signal) { msg3.payload.signal = error.signal; }
- if (error.code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
- else { node.status({fill:"red",shape:"dot",text:"error:"+error.code}); }
- if (RED.settings.verbose) { node.log('error:' + error); }
- }
- else if (node.oldrc === "false") {
- msg3 = RED.util.cloneMessage(msg);
- msg3.payload = {code:0};
- }
- if (!msg3) { node.status({}); }
- else {
- msg.rc = msg3.payload;
- if (msg2) { msg2.rc = msg3.payload; }
- }
- nodeSend([msg,msg2,msg3]);
- if (child.tout) { clearTimeout(child.tout); }
- delete node.activeProcesses[child.pid];
- nodeDone();
- });
- node.status({fill:"blue",shape:"dot",text:"pid:"+child.pid});
- child.on('error',function() {});
- if (node.timer !== 0) {
- child.tout = setTimeout(function() { cleanup(child.pid); }, node.timer);
- }
- node.activeProcesses[child.pid] = child;
- }
- }
- });
-
- this.on('close',function() {
- for (var pid in node.activeProcesses) {
- /* istanbul ignore else */
- if (node.activeProcesses.hasOwnProperty(pid)) {
- if (node.activeProcesses[pid].tout) { clearTimeout(node.activeProcesses[pid].tout); }
- // console.log("KILLING",pid);
- var process = node.activeProcesses[pid];
- node.activeProcesses[pid] = null;
- process.kill();
- }
- }
- node.activeProcesses = {};
- node.status({});
- });
- }
- RED.nodes.registerType("exec",ExecNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/function/rbe.html b/packages/node_modules/@node-red/nodes/core/function/rbe.html
deleted file mode 100644
index 11ff18860..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/rbe.html
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/function/rbe.js b/packages/node_modules/@node-red/nodes/core/function/rbe.js
deleted file mode 100644
index 4548a8c6a..000000000
--- a/packages/node_modules/@node-red/nodes/core/function/rbe.js
+++ /dev/null
@@ -1,97 +0,0 @@
-
-module.exports = function(RED) {
- "use strict";
- function RbeNode(n) {
- RED.nodes.createNode(this,n);
- this.func = n.func || "rbe";
- this.gap = n.gap || "0";
- this.start = n.start || '';
- this.inout = n.inout || "out";
- this.pc = false;
- if (this.gap.substr(-1) === "%") {
- this.pc = true;
- this.gap = parseFloat(this.gap);
- }
- this.g = this.gap;
- this.property = n.property || "payload";
- this.topi = n.topi || "topic";
- this.septopics = true;
- if (n.septopics !== undefined && n.septopics === false) {
- this.septopics = false;
- }
-
- var node = this;
-
- node.previous = {};
- this.on("input",function(msg) {
- var topic;
- try {
- topic = RED.util.getMessageProperty(msg,node.topi);
- }
- catch(e) { }
- if (msg.hasOwnProperty("reset")) {
- if (node.septopics && topic && (typeof topic === "string") && (topic !== "")) {
- delete node.previous[msg.topic];
- }
- else { node.previous = {}; }
- }
- var value = RED.util.getMessageProperty(msg,node.property);
- if (value !== undefined) {
- var t = "_no_topic";
- if (node.septopics) { t = topic || t; }
- if ((this.func === "rbe") || (this.func === "rbei")) {
- var doSend = (this.func !== "rbei") || (node.previous.hasOwnProperty(t)) || false;
- if (typeof(value) === "object") {
- if (typeof(node.previous[t]) !== "object") { node.previous[t] = {}; }
- if (!RED.util.compareObjects(value, node.previous[t])) {
- node.previous[t] = RED.util.cloneMessage(value);
- if (doSend) { node.send(msg); }
- }
- }
- else {
- if (value !== node.previous[t]) {
- node.previous[t] = RED.util.cloneMessage(value);
- if (doSend) { node.send(msg); }
- }
- }
- }
- else {
- var n = parseFloat(value);
- if (!isNaN(n)) {
- if ((typeof node.previous[t] === 'undefined') && (this.func === "narrowband")) {
- if (node.start === '') { node.previous[t] = n; }
- else { node.previous[t] = node.start; }
- }
- if (node.pc) { node.gap = Math.abs(node.previous[t] * node.g / 100) || 0; }
- else { node.gap = Number(node.gap); }
- if ((node.previous[t] === undefined) && (node.func === "narrowbandEq")) { node.previous[t] = n; }
- if (node.previous[t] === undefined) { node.previous[t] = n - node.gap - 1; }
- if (Math.abs(n - node.previous[t]) === node.gap) {
- if ((this.func === "deadbandEq")||(this.func === "narrowband")) {
- if (node.inout === "out") { node.previous[t] = n; }
- node.send(msg);
- }
- }
- else if (Math.abs(n - node.previous[t]) > node.gap) {
- if (this.func === "deadband" || this.func === "deadbandEq") {
- if (node.inout === "out") { node.previous[t] = n; }
- node.send(msg);
- }
- }
- else if (Math.abs(n - node.previous[t]) < node.gap) {
- if ((this.func === "narrowband")||(this.func === "narrowbandEq")) {
- if (node.inout === "out") { node.previous[t] = n; }
- node.send(msg);
- }
- }
- if (node.inout === "in") { node.previous[t] = n; }
- }
- else {
- node.warn(RED._("rbe.warn.nonumber"));
- }
- }
- } // ignore msg with no payload property.
- });
- }
- RED.nodes.registerType("rbe",RbeNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/05-tls.html b/packages/node_modules/@node-red/nodes/core/network/05-tls.html
deleted file mode 100644
index d09860843..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/05-tls.html
+++ /dev/null
@@ -1,197 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/05-tls.js b/packages/node_modules/@node-red/nodes/core/network/05-tls.js
deleted file mode 100644
index 888d749fd..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/05-tls.js
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var fs = require('fs');
-module.exports = function(RED) {
- "use strict";
-
- function TLSConfig(n) {
- RED.nodes.createNode(this,n);
- this.valid = true;
- this.verifyservercert = n.verifyservercert;
- var certPath = n.cert.trim();
- var keyPath = n.key.trim();
- var caPath = n.ca.trim();
- this.servername = (n.servername||"").trim();
- this.alpnprotocol = (n.alpnprotocol||"").trim();
-
- if ((certPath.length > 0) || (keyPath.length > 0) || (caPath.length > 0)) {
-
- if ( (certPath.length > 0) !== (keyPath.length > 0)) {
- this.valid = false;
- this.error(RED._("tls.error.missing-file"));
- return;
- }
-
- try {
- if (certPath) {
- this.cert = fs.readFileSync(certPath);
- }
- if (keyPath) {
- this.key = fs.readFileSync(keyPath);
- }
- if (caPath) {
- this.ca = fs.readFileSync(caPath);
- }
- } catch(err) {
- this.valid = false;
- this.error(err.toString());
- return;
- }
- } else {
- if (this.credentials) {
- var certData = this.credentials.certdata || "";
- var keyData = this.credentials.keydata || "";
- var caData = this.credentials.cadata || "";
-
- if ((certData.length > 0) !== (keyData.length > 0)) {
- this.valid = false;
- this.error(RED._("tls.error.missing-file"));
- return;
- }
-
- if (certData) {
- this.cert = certData;
- }
- if (keyData) {
- this.key = keyData;
- }
- if (caData) {
- this.ca = caData;
- }
- }
- }
- }
- RED.nodes.registerType("tls-config", TLSConfig, {
- credentials: {
- certdata: {type:"text"},
- keydata: {type:"text"},
- cadata: {type:"text"},
- passphrase: {type:"password"}
- },
- settings: {
- tlsConfigDisableLocalFiles: {
- value: false,
- exportable: true
- }
- }
- });
-
- TLSConfig.prototype.addTLSOptions = function(opts) {
- if (this.valid) {
- if (this.key) {
- opts.key = this.key;
- }
- if (this.cert) {
- opts.cert = this.cert;
- }
- if (this.ca) {
- opts.ca = this.ca;
- }
- if (this.credentials && this.credentials.passphrase) {
- opts.passphrase = this.credentials.passphrase;
- }
- if (this.servername) {
- opts.servername = this.servername;
- }
- if (this.alpnprotocol) {
- opts.ALPNProtocols = [this.alpnprotocol];
- }
- opts.rejectUnauthorized = this.verifyservercert;
- }
- return opts;
- }
-
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/06-httpproxy.html b/packages/node_modules/@node-red/nodes/core/network/06-httpproxy.html
deleted file mode 100644
index 85939a1ef..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/06-httpproxy.html
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/06-httpproxy.js b/packages/node_modules/@node-red/nodes/core/network/06-httpproxy.js
deleted file mode 100644
index abcee66f6..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/06-httpproxy.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- 'use strict';
-
- function HTTPProxyConfig(n) {
- RED.nodes.createNode(this, n);
- this.name = n.name;
- this.url = n.url;
- this.noproxy = n.noproxy;
- };
-
- RED.nodes.registerType('http proxy', HTTPProxyConfig, {
- credentials: {
- username: {type:'text'},
- password: {type:'password'}
- }
- });
-};
diff --git a/packages/node_modules/@node-red/nodes/core/network/10-mqtt.html b/packages/node_modules/@node-red/nodes/core/network/10-mqtt.html
deleted file mode 100644
index 747281ad0..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/10-mqtt.html
+++ /dev/null
@@ -1,908 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/10-mqtt.js b/packages/node_modules/@node-red/nodes/core/network/10-mqtt.js
deleted file mode 100644
index 5d4efaf93..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/10-mqtt.js
+++ /dev/null
@@ -1,1139 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var mqtt = require("mqtt");
- var isUtf8 = require('is-utf8');
- var HttpsProxyAgent = require('https-proxy-agent');
- var url = require('url');
-
- //#region "Supporting functions"
- function matchTopic(ts,t) {
- if (ts == "#") {
- return true;
- }
- /* The following allows shared subscriptions (as in MQTT v5)
- http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02.html#_Toc514345522
-
- 4.8.2 describes shares like:
- $share/{ShareName}/{filter}
- $share is a literal string that marks the Topic Filter as being a Shared Subscription Topic Filter.
- {ShareName} is a character string that does not include "/", "+" or "#"
- {filter} The remainder of the string has the same syntax and semantics as a Topic Filter in a non-shared subscription. Refer to section 4.7.
- */
- else if(ts.startsWith("$share")){
- ts = ts.replace(/^\$share\/[^#+/]+\/(.*)/g,"$1");
- }
- var re = new RegExp("^"+ts.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
- return re.test(t);
- }
-
- /**
- * Helper function for setting integer property values in the MQTT V5 properties object
- * @param {object} src Source object containing properties
- * @param {object} dst Destination object to set/add properties
- * @param {string} propName The property name to set in the Destination object
- * @param {integer} [minVal] The minimum value. If the src value is less than minVal, it will NOT be set in the destination
- * @param {integer} [maxVal] The maximum value. If the src value is greater than maxVal, it will NOT be set in the destination
- * @param {integer} [def] An optional default to set in the destination object if prop is NOT present in the soruce object
- */
- function setIntProp(src, dst, propName, minVal, maxVal, def) {
- if (hasProperty(src, propName)) {
- var v = parseInt(src[propName]);
- if(isNaN(v)) return;
- if(minVal != null) {
- if(v < minVal) return;
- }
- if(maxVal != null) {
- if(v > maxVal) return;
- }
- dst[propName] = v;
- } else {
- if(def != undefined) dst[propName] = def;
- }
- }
-
- /**
- * Test a topic string is valid
- * @param {string} topic
- * @returns `true` if it is a valid topic
- */
- function isValidSubscriptionTopic(topic) {
- return /^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/.test(topic)
- }
-
- /**
- * Helper function for setting string property values in the MQTT V5 properties object
- * @param {object} src Source object containing properties
- * @param {object} dst Destination object to set/add properties
- * @param {string} propName The property name to set in the Destination object
- * @param {string} [def] An optional default to set in the destination object if prop is NOT present in the soruce object
- */
- function setStrProp(src, dst, propName, def) {
- if (src[propName] && typeof src[propName] == "string") {
- dst[propName] = src[propName];
- } else {
- if(def != undefined) dst[propName] = def;
- }
- }
-
- /**
- * Helper function for setting boolean property values in the MQTT V5 properties object
- * @param {object} src Source object containing properties
- * @param {object} dst Destination object to set/add properties
- * @param {string} propName The property name to set in the Destination object
- * @param {boolean} [def] An optional default to set in the destination object if prop is NOT present in the soruce object
- */
- function setBoolProp(src, dst, propName, def) {
- if (src[propName] != null) {
- if(src[propName] === "true" || src[propName] === true) {
- dst[propName] = true;
- } else if(src[propName] === "false" || src[propName] === false) {
- dst[propName] = true;
- }
- } else {
- if(def != undefined) dst[propName] = def;
- }
- }
-
- /**
- * Helper function for copying the MQTT v5 srcUserProperties object (parameter1) to the properties object (parameter2).
- * Any property in srcUserProperties that is NOT a key/string pair will be silently discarded.
- * NOTE: if no sutable properties are present, the userProperties object will NOT be added to the properties object
- * @param {object} srcUserProperties An object with key/value string pairs
- * @param {object} properties A properties object in which userProperties will be copied to
- */
- function setUserProperties(srcUserProperties, properties) {
- if (srcUserProperties && typeof srcUserProperties == "object") {
- let _clone = {};
- let count = 0;
- let keys = Object.keys(srcUserProperties);
- if(!keys || !keys.length) return null;
- keys.forEach(key => {
- let val = srcUserProperties[key];
- if(typeof val == "string") {
- count++;
- _clone[key] = val;
- }
- });
- if(count) properties.userProperties = _clone;
- }
- }
-
- /**
- * Helper function for copying the MQTT v5 buffer type properties
- * NOTE: if src[propName] is not a buffer, dst[propName] will NOT be assigned a value (unless def is set)
- * @param {object} src Source object containing properties
- * @param {object} dst Destination object to set/add properties
- * @param {string} propName The property name to set in the Destination object
- * @param {boolean} [def] An optional default to set in the destination object if prop is NOT present in the Source object
- */
- function setBufferProp(src, dst, propName, def) {
- if(!dst) return;
- if (src && dst) {
- var buf = src[propName];
- if (buf && typeof Buffer.isBuffer(buf)) {
- dst[propName] = Buffer.from(buf);
- }
- } else {
- if(def != undefined) dst[propName] = def;
- }
- }
-
- /**
- * Helper function for applying changes to an objects properties ONLY when the src object actually has the property.
- * This avoids setting a `dst` property null/undefined when the `src` object doesnt have the named property.
- * @param {object} src Source object containing properties
- * @param {object} dst Destination object to set property
- * @param {string} propName The property name to set in the Destination object
- * @param {boolean} force force the dst property to be updated/created even if src property is empty
- */
- function setIfHasProperty(src, dst, propName, force) {
- if (src && dst && propName) {
- const ok = force || hasProperty(src, propName);
- if (ok) {
- dst[propName] = src[propName];
- }
- }
- }
-
- /**
- * Helper function to test an object has a property
- * @param {object} obj Object to test
- * @param {string} propName Name of property to find
- * @returns true if object has property `propName`
- */
- function hasProperty(obj, propName) {
- //JavaScript does not protect the property name hasOwnProperty
- //Object.prototype.hasOwnProperty.call is the recommended/safer test
- return Object.prototype.hasOwnProperty.call(obj, propName);
- }
-
- /**
- * Handle the payload / packet recieved in MQTT In and MQTT Sub nodes
- */
- function subscriptionHandler(node, datatype ,topic, payload, packet) {
- const v5 = node.brokerConn.options && node.brokerConn.options.protocolVersion == 5;
-
- if (datatype === "buffer") {
- // payload = payload;
- } else if (datatype === "base64") {
- payload = payload.toString('base64');
- } else if (datatype === "utf8") {
- payload = payload.toString('utf8');
- } else if (datatype === "json") {
- if (isUtf8(payload)) {
- payload = payload.toString();
- try { payload = JSON.parse(payload); }
- catch(e) { node.error(RED._("mqtt.errors.invalid-json-parse"),{payload:payload, topic:topic, qos:packet.qos, retain:packet.retain}); return; }
- }
- else { node.error((RED._("mqtt.errors.invalid-json-string")),{payload:payload, topic:topic, qos:packet.qos, retain:packet.retain}); return; }
- } else {
- if (isUtf8(payload)) { payload = payload.toString(); }
- }
- var msg = {topic:topic, payload:payload, qos:packet.qos, retain:packet.retain};
- if(v5 && packet.properties) {
- setStrProp(packet.properties, msg, "responseTopic");
- setBufferProp(packet.properties, msg, "correlationData");
- setStrProp(packet.properties, msg, "contentType");
- setIntProp(packet.properties, msg, "messageExpiryInterval", 0);
- setBoolProp(packet.properties, msg, "payloadFormatIndicator");
- setStrProp(packet.properties, msg, "reasonString");
- setUserProperties(packet.properties.userProperties, msg);
- }
- if ((node.brokerConn.broker === "localhost")||(node.brokerConn.broker === "127.0.0.1")) {
- msg._topic = topic;
- }
- node.send(msg);
- }
-
- /**
- * Send an mqtt message to broker
- * @param {MQTTOutNode} node the owner node
- * @param {object} msg The msg to prepare for publishing
- * @param {function} done callback when done
- */
- function doPublish(node, msg, done) {
- try {
- done = typeof done == "function" ? done : function noop(){};
- let v5 = node.brokerConn.options && node.brokerConn.options.protocolVersion == 5;
- const bsp = (node.brokerConn && node.brokerConn.serverProperties) || {};
-
- //Sanitise the `msg` object properties ready for publishing
- if (msg.qos) {
- msg.qos = parseInt(msg.qos);
- if ((msg.qos !== 0) && (msg.qos !== 1) && (msg.qos !== 2)) {
- msg.qos = null;
- }
- }
-
- /* If node properties exists, override/set that to property in msg */
- if (node.topic) { msg.topic = node.topic; }
- msg.qos = Number(node.qos || msg.qos || 0);
- msg.retain = node.retain || msg.retain || false;
- msg.retain = ((msg.retain === true) || (msg.retain === "true")) || false;
-
- if (v5) {
- if (node.userProperties) {
- msg.userProperties = node.userProperties;
- }
- if (node.responseTopic) {
- msg.responseTopic = node.responseTopic;
- }
- if (node.correlationData) {
- msg.correlationData = node.correlationData;
- }
- if (node.contentType) {
- msg.contentType = node.contentType;
- }
- if (node.messageExpiryInterval) {
- msg.messageExpiryInterval = node.messageExpiryInterval;
- }
- }
- if (msg.userProperties && typeof msg.userProperties !== "object") {
- delete msg.userProperties;
- }
- if (hasProperty(msg, "topicAlias") && !isNaN(msg.topicAlias) && (msg.topicAlias === 0 || bsp.topicAliasMaximum === 0 || msg.topicAlias > bsp.topicAliasMaximum)) {
- delete msg.topicAlias;
- }
-
- if (hasProperty(msg, "payload")) {
-
- //check & sanitise topic
- let topicOK = hasProperty(msg, "topic") && (typeof msg.topic === "string") && (msg.topic !== "");
-
- if (!topicOK && v5) {
- //NOTE: A value of 0 (in server props topicAliasMaximum) indicates that the Server does not accept any Topic Aliases on this connection
- if (hasProperty(msg, "topicAlias") && !isNaN(msg.topicAlias) && msg.topicAlias >= 0 && bsp.topicAliasMaximum && bsp.topicAliasMaximum >= msg.topicAlias) {
- topicOK = true;
- msg.topic = ""; //must be empty string
- } else if (hasProperty(msg, "responseTopic") && (typeof msg.responseTopic === "string") && (msg.responseTopic !== "")) {
- //TODO: if topic is empty but responseTopic has a string value, use that instead. Is this desirable?
- topicOK = true;
- msg.topic = msg.responseTopic;
- //TODO: delete msg.responseTopic - to prevent it being resent?
- }
- }
- topicOK = topicOK && !/[\+#]/.test(msg.topic);
-
- if (topicOK) {
- node.brokerConn.publish(msg, done); // send the message
- } else {
- node.warn(RED._("mqtt.errors.invalid-topic"));
- done();
- }
- } else {
- done();
- }
- } catch (error) {
- done(error);
- }
- }
-
- function setStatusDisconnected(node, allNodes) {
- if(allNodes) {
- for (var id in node.users) {
- if (hasProperty(node.users, id)) {
- node.users[id].status({ fill: "red", shape: "ring", text: "node-red:common.status.disconnected" });
- }
- }
- } else {
- node.status({ fill: "red", shape: "ring", text: "node-red:common.status.disconnected" });
- }
- }
-
- function setStatusConnecting(node, allNodes) {
- if(allNodes) {
- for (var id in node.users) {
- if (hasProperty(node.users, id)) {
- node.users[id].status({ fill: "yellow", shape: "ring", text: "node-red:common.status.connecting" });
- }
- }
- } else {
- node.status({ fill: "yellow", shape: "ring", text: "node-red:common.status.connecting" });
- }
- }
-
- function setStatusConnected(node, allNodes) {
- if(allNodes) {
- for (var id in node.users) {
- if (hasProperty(node.users, id)) {
- node.users[id].status({ fill: "green", shape: "dot", text: "node-red:common.status.connected" });
- }
- }
- } else {
- node.status({ fill: "green", shape: "dot", text: "node-red:common.status.connected" });
- }
- }
-
- function handleConnectAction(node, msg, done) {
- let actionData = typeof msg.broker === 'object' ? msg.broker : null;
- if (node.brokerConn.canConnect()) {
- // Not currently connected/connecting - trigger the connect
- if (actionData) {
- node.brokerConn.setOptions(actionData);
- }
- node.brokerConn.connect(function () {
- done();
- });
- } else {
- // Already Connected/Connecting
- if (!actionData) {
- // All is good - already connected and no broker override provided
- done()
- } else if (actionData.force) {
- // The force flag tells us to cycle the connection.
- node.brokerConn.disconnect(function() {
- node.brokerConn.setOptions(actionData);
- node.brokerConn.connect(function () {
- done();
- });
- })
- } else {
- // Without force flag, we will refuse to cycle an active connection
- done(new Error(RED._('mqtt.errors.invalid-action-alreadyconnected')));
- }
- }
- }
-
- function handleDisconnectAction(node, done) {
- node.brokerConn.disconnect(function () {
- done();
- });
- }
-
- //#endregion "Supporting functions"
-
- //#region "Broker node"
- function MQTTBrokerNode(n) {
- RED.nodes.createNode(this,n);
- const node = this;
- node.users = {};
- // Config node state
- node.brokerurl = "";
- node.connected = false;
- node.connecting = false;
- node.closing = false;
- node.options = {};
- node.queue = [];
- node.subscriptions = {};
- /** @type {mqtt.MqttClient}*/ this.client;
- node.setOptions = function(opts, init) {
- if(!opts || typeof opts !== "object") {
- return; //nothing to change, simply return
- }
- const originalBrokerURL = node.brokerurl;
-
- //apply property changes (only if the property exists in the opts object)
- setIfHasProperty(opts, node, "url", init);
- setIfHasProperty(opts, node, "broker", init);
- setIfHasProperty(opts, node, "port", init);
- setIfHasProperty(opts, node, "clientid", init);
- setIfHasProperty(opts, node, "autoConnect", init);
- setIfHasProperty(opts, node, "usetls", init);
- setIfHasProperty(opts, node, "usews", init);
- setIfHasProperty(opts, node, "verifyservercert", init);
- setIfHasProperty(opts, node, "compatmode", init);
- setIfHasProperty(opts, node, "protocolVersion", init);
- setIfHasProperty(opts, node, "keepalive", init);
- setIfHasProperty(opts, node, "cleansession", init);
- setIfHasProperty(opts, node, "sessionExpiry", init);
- setIfHasProperty(opts, node, "topicAliasMaximum", init);
- setIfHasProperty(opts, node, "maximumPacketSize", init);
- setIfHasProperty(opts, node, "receiveMaximum", init);
- setIfHasProperty(opts, node, "userProperties", init);//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901116
- setIfHasProperty(opts, node, "userPropertiesType", init);
-
- function createLWT(topic, payload, qos, retain, v5opts, v5SubPropName) {
- let message = undefined;
- if(topic) {
- message = {
- topic: topic,
- payload: payload || "",
- qos: Number(qos||0),
- retain: retain=="true"|| retain===true,
- }
- if (v5opts) {
- let v5Properties = message;
- if(v5SubPropName) {
- v5Properties = message[v5SubPropName] = {};
- }
- //re-align local prop name to mqttjs std
- if(hasProperty(v5opts, "respTopic")) { v5opts.responseTopic = v5opts.respTopic; }
- if(hasProperty(v5opts, "correl")) { v5opts.correlationData = v5opts.correl; }
- if(hasProperty(v5opts, "expiry")) { v5opts.messageExpiryInterval = v5opts.expiry; }
- if(hasProperty(v5opts, "delay")) { v5opts.willDelayInterval = v5opts.delay; }
- if(hasProperty(v5opts, "userProps")) { v5opts.userProperties = v5opts.userProps; }
- //setup v5 properties
- if(typeof v5opts.userProperties == "string" && /^ *{/.test(v5opts.userProperties)) {
- try {
- setUserProperties(JSON.parse(v5opts.userProps), v5Properties);
- } catch(err) {}
- } else if (typeof v5opts.userProperties == "object") {
- setUserProperties(v5opts.userProperties, v5Properties);
- }
- setStrProp(v5opts, v5Properties, "contentType");
- setStrProp(v5opts, v5Properties, "responseTopic");
- setBufferProp(v5opts, v5Properties, "correlationData");
- setIntProp(v5opts, v5Properties, "messageExpiryInterval");
- setIntProp(v5opts, v5Properties, "willDelayInterval");
- }
- }
- return message;
- }
-
- if(init) {
- if(hasProperty(opts, "birthTopic")) {
- node.birthMessage = createLWT(opts.birthTopic, opts.birthPayload, opts.birthQos, opts.birthRetain, opts.birthMsg, "");
- };
- if(hasProperty(opts, "closeTopic")) {
- node.closeMessage = createLWT(opts.closeTopic, opts.closePayload, opts.closeQos, opts.closeRetain, opts.closeMsg, "");
- };
- if(hasProperty(opts, "willTopic")) {
- //will v5 properties must be set in the "properties" sub object
- node.options.will = createLWT(opts.willTopic, opts.willPayload, opts.willQos, opts.willRetain, opts.willMsg, "properies");
- };
- } else {
- //update options
- if(hasProperty(opts, "birth")) {
- if(typeof opts.birth !== "object") { opts.birth = {}; }
- node.birthMessage = createLWT(opts.birth.topic, opts.birth.payload, opts.birth.qos, opts.birth.retain, opts.birth.properties, "");
- }
- if(hasProperty(opts, "close")) {
- if(typeof opts.close !== "object") { opts.close = {}; }
- node.closeMessage = createLWT(opts.close.topic, opts.close.payload, opts.close.qos, opts.close.retain, opts.close.properties, "");
- }
- if(hasProperty(opts, "will")) {
- if(typeof opts.will !== "object") { opts.will = {}; }
- //will v5 properties must be set in the "properties" sub object
- node.options.will = createLWT(opts.will.topic, opts.will.payload, opts.will.qos, opts.will.retain, opts.will.properties, "properties");
- }
- }
-
- if (node.credentials) {
- node.username = node.credentials.user;
- node.password = node.credentials.password;
- }
- if(!init & hasProperty(opts, "username")) {
- node.username = opts.username;
- };
- if(!init & hasProperty(opts, "password")) {
- node.password = opts.password;
- };
-
- // If the config node is missing certain options (it was probably deployed prior to an update to the node code),
- // select/generate sensible options for the new fields
- if (typeof node.usetls === 'undefined') {
- node.usetls = false;
- }
- if (typeof node.usews === 'undefined') {
- node.usews = false;
- }
- if (typeof node.verifyservercert === 'undefined') {
- node.verifyservercert = false;
- }
- if (typeof node.keepalive === 'undefined') {
- node.keepalive = 60;
- } else if (typeof node.keepalive === 'string') {
- node.keepalive = Number(node.keepalive);
- }
- if (typeof node.cleansession === 'undefined') {
- node.cleansession = true;
- }
-
- //use url or build a url from usetls://broker:port
- if (node.url && node.brokerurl !== node.url) {
- node.brokerurl = node.url;
- } else {
- // if the broker is ws:// or wss:// or tcp://
- if (node.broker.indexOf("://") > -1) {
- node.brokerurl = node.broker;
- // Only for ws or wss, check if proxy env var for additional configuration
- if (node.brokerurl.indexOf("wss://") > -1 || node.brokerurl.indexOf("ws://") > -1) {
- // check if proxy is set in env
- let prox, noprox;
- if (process.env.http_proxy) { prox = process.env.http_proxy; }
- if (process.env.HTTP_PROXY) { prox = process.env.HTTP_PROXY; }
- if (process.env.no_proxy) { noprox = process.env.no_proxy.split(","); }
- if (process.env.NO_PROXY) { noprox = process.env.NO_PROXY.split(","); }
- if (noprox) {
- for (var i = 0; i < noprox.length; i += 1) {
- if (node.brokerurl.indexOf(noprox[i].trim()) !== -1) { noproxy = true; }
- }
- }
- if (prox && !noproxy) {
- var parsedUrl = url.parse(node.brokerurl);
- var proxyOpts = url.parse(prox);
- // true for wss
- proxyOpts.secureEndpoint = parsedUrl.protocol ? parsedUrl.protocol === 'wss:' : true;
- // Set Agent for wsOption in MQTT
- var agent = new HttpsProxyAgent(proxyOpts);
- node.options.wsOptions = {
- agent: agent
- };
- }
- }
- } else {
- // construct the std mqtt:// url
- if (node.usetls) {
- node.brokerurl = "mqtts://";
- } else {
- node.brokerurl = "mqtt://";
- }
- if (node.broker !== "") {
- //Check for an IPv6 address
- if (/(?:^|(?<=\s))(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))(?=\s|$)/.test(node.broker)) {
- node.brokerurl = node.brokerurl + "[" + node.broker + "]:";
- } else {
- node.brokerurl = node.brokerurl + node.broker + ":";
- }
- // port now defaults to 1883 if unset.
- if (!node.port) {
- node.brokerurl = node.brokerurl + "1883";
- } else {
- node.brokerurl = node.brokerurl + node.port;
- }
- } else {
- node.brokerurl = node.brokerurl + "localhost:1883";
- }
- }
- }
-
- // Ensure cleansession set if clientid not supplied
- if (!node.cleansession && !node.clientid) {
- node.cleansession = true;
- node.warn(RED._("mqtt.errors.nonclean-missingclientid"));
- }
-
- // Build options for passing to the MQTT.js API
- node.options.username = node.username;
- node.options.password = node.password;
- node.options.keepalive = node.keepalive;
- node.options.clean = node.cleansession;
- node.options.clientId = node.clientid || 'nodered_' + RED.util.generateId();
- node.options.reconnectPeriod = RED.settings.mqttReconnectTime||5000;
- delete node.options.protocolId; //V4+ default
- delete node.options.protocolVersion; //V4 default
- delete node.options.properties;//V5 only
- if (node.compatmode == "true" || node.compatmode === true || node.protocolVersion == 3) {
- node.options.protocolId = 'MQIsdp';//V3 compat only
- node.options.protocolVersion = 3;
- } else if ( node.protocolVersion == 5 ) {
- delete node.options.protocolId;
- node.options.protocolVersion = 5;
- node.options.properties = {};
- node.options.properties.requestResponseInformation = true;
- node.options.properties.requestProblemInformation = true;
- if(node.userProperties && /^ *{/.test(node.userProperties)) {
- try {
- setUserProperties(JSON.parse(node.userProperties), node.options.properties);
- } catch(err) {}
- }
- if (node.sessionExpiryInterval && node.sessionExpiryInterval !== "0") {
- setIntProp(node,node.options.properties,"sessionExpiryInterval");
- }
- }
- if (node.usetls && n.tls) {
- var tlsNode = RED.nodes.getNode(n.tls);
- if (tlsNode) {
- tlsNode.addTLSOptions(node.options);
- }
- }
-
- // If there's no rejectUnauthorized already, then this could be an
- // old config where this option was provided on the broker node and
- // not the tls node
- if (typeof node.options.rejectUnauthorized === 'undefined') {
- node.options.rejectUnauthorized = (node.verifyservercert == "true" || node.verifyservercert === true);
- }
- }
-
- n.autoConnect = n.autoConnect === "false" || n.autoConnect === false ? false : true;
- node.setOptions(n, true);
-
- // Define functions called by MQTT in and out nodes
- node.register = function(mqttNode) {
- node.users[mqttNode.id] = mqttNode;
- if (Object.keys(node.users).length === 1) {
- if(node.autoConnect) {
- node.connect();
- }
- }
- };
-
- node.deregister = function(mqttNode,done) {
- delete node.users[mqttNode.id];
- if (node.closing) {
- return done();
- }
- if (Object.keys(node.users).length === 0) {
- if (node.client && node.client.connected) {
- // Send close message
- if (node.closeMessage) {
- node.publish(node.closeMessage,function(err) {
- node.client.end(done);
- });
- } else {
- node.client.end(done);
- }
- return;
- } else {
- if (node.client) { node.client.end(); }
- return done();
- }
- }
- done();
- };
- node.canConnect = function() {
- return !node.connected && !node.connecting;
- }
- node.connect = function (callback) {
- if (node.canConnect()) {
- node.connecting = true;
- setStatusConnecting(node, true);
- try {
- node.serverProperties = {};
- node.client = mqtt.connect(node.brokerurl, node.options);
- node.client.setMaxListeners(0);
- let callbackDone = false; //prevent re-connects causing node.client.on('connect' firing callback multiple times
- // Register successful connect or reconnect handler
- node.client.on('connect', function (connack) {
- node.connecting = false;
- node.connected = true;
- if(!callbackDone && typeof callback == "function") {
- callback();
- }
- callbackDone = true;
- node.topicAliases = {};
- node.log(RED._("mqtt.state.connected",{broker:(node.clientid?node.clientid+"@":"")+node.brokerurl}));
- if(node.options.protocolVersion == 5 && connack && hasProperty(connack, "properties")) {
- if(typeof connack.properties == "object") {
- //clean & assign all props sent from server.
- setIntProp(connack.properties, node.serverProperties, "topicAliasMaximum", 0);
- setIntProp(connack.properties, node.serverProperties, "receiveMaximum", 0);
- setIntProp(connack.properties, node.serverProperties, "sessionExpiryInterval", 0, 0xFFFFFFFF);
- setIntProp(connack.properties, node.serverProperties, "maximumQoS", 0, 2);
- setBoolProp(connack.properties, node.serverProperties, "retainAvailable",true);
- setBoolProp(connack.properties, node.serverProperties, "wildcardSubscriptionAvailable", true);
- setBoolProp(connack.properties, node.serverProperties, "subscriptionIdentifiersAvailable", true);
- setBoolProp(connack.properties, node.serverProperties, "sharedSubscriptionAvailable");
- setIntProp(connack.properties, node.serverProperties, "maximumPacketSize", 0);
- setIntProp(connack.properties, node.serverProperties, "serverKeepAlive");
- setStrProp(connack.properties, node.serverProperties, "responseInformation");
- setStrProp(connack.properties, node.serverProperties, "serverReference");
- setStrProp(connack.properties, node.serverProperties, "assignedClientIdentifier");
- setStrProp(connack.properties, node.serverProperties, "reasonString");
- setUserProperties(connack.properties, node.serverProperties);
- }
- }
- setStatusConnected(node, true);
- // Remove any existing listeners before resubscribing to avoid duplicates in the event of a re-connection
- node.client.removeAllListeners('message');
-
- // Re-subscribe to stored topics
- for (var s in node.subscriptions) {
- if (node.subscriptions.hasOwnProperty(s)) {
- let topic = s;
- let qos = 0;
- let _options = {};
- for (var r in node.subscriptions[s]) {
- if (node.subscriptions[s].hasOwnProperty(r)) {
- qos = Math.max(qos,node.subscriptions[s][r].qos);
- _options = node.subscriptions[s][r].options;
- node.client.on('message',node.subscriptions[s][r].handler);
- }
- }
- _options.qos = _options.qos || qos;
- node.client.subscribe(topic, _options);
- }
- }
-
- // Send any birth message
- if (node.birthMessage) {
- node.publish(node.birthMessage);
- }
- });
- node.client.on("reconnect", function() {
- setStatusConnecting(node, true);
- });
- //TODO: what to do with this event? Anything? Necessary?
- node.client.on("disconnect", function(packet) {
- //Emitted after receiving disconnect packet from broker. MQTT 5.0 feature.
- var rc = packet && packet.properties && packet.properties.reasonString;
- var rc = packet && packet.properties && packet.reasonCode;
- //TODO: If keeping this event, do we use these? log these?
- });
- // Register disconnect handlers
- node.client.on('close', function () {
- if (node.connected) {
- node.connected = false;
- node.log(RED._("mqtt.state.disconnected",{broker:(node.clientid?node.clientid+"@":"")+node.brokerurl}));
- setStatusDisconnected(node, true);
- } else if (node.connecting) {
- node.log(RED._("mqtt.state.connect-failed",{broker:(node.clientid?node.clientid+"@":"")+node.brokerurl}));
- }
- });
-
- // Register connect error handler
- // The client's own reconnect logic will take care of errors
- node.client.on('error', function (error) {
- });
- }catch(err) {
- console.log(err);
- }
- }
- };
- node.disconnect = function (callback) {
- const _callback = function () {
- setStatusDisconnected(node, true);
- node.connecting = false;
- node.connected = false;
- callback && typeof callback == "function" && callback();
- };
-
- if(node.client) {
- if(node.client.connected && node.closeMessage) {
- node.publish(node.closeMessage, function (err) {
- node.client.end(_callback);
- });
- } else if(node.client.connected || node.client.reconnecting) {
- node.client.end(_callback);
- } else if(node.client.disconnecting || node.client.connected === false) {
- _callback();
- }
- } else {
- _callback();
- }
- }
- node.subscriptionIds = {};
- node.subid = 1;
- node.subscribe = function (topic,options,callback,ref) {
- ref = ref||0;
- var qos;
- if(typeof options == "object") {
- qos = options.qos;
- } else {
- qos = options;
- options = {};
- }
- options.qos = qos;
- if (!node.subscriptionIds[topic]) {
- node.subscriptionIds[topic] = node.subid++;
- }
- options.properties = options.properties || {};
- options.properties.subscriptionIdentifier = node.subscriptionIds[topic];
-
- node.subscriptions[topic] = node.subscriptions[topic]||{};
- var sub = {
- topic:topic,
- qos:qos,
- options:options,
- handler:function(mtopic,mpayload, mpacket) {
- if(mpacket.properties && options.properties && mpacket.properties.subscriptionIdentifier && options.properties.subscriptionIdentifier && (mpacket.properties.subscriptionIdentifier !== options.properties.subscriptionIdentifier) ) {
- //do nothing as subscriptionIdentifier does not match
- } else if (matchTopic(topic,mtopic)) {
- callback(mtopic,mpayload, mpacket);
- }
- },
- ref: ref
- };
- node.subscriptions[topic][ref] = sub;
- if (node.connected) {
- node.client.on('message',sub.handler);
- node.client.subscribe(topic, options);
- }
- };
-
- node.unsubscribe = function (topic, ref, removed) {
- ref = ref||0;
- var sub = node.subscriptions[topic];
- if (sub) {
- if (sub[ref]) {
- if(node.client) {
- node.client.removeListener('message',sub[ref].handler);
- }
- delete sub[ref];
- }
- //TODO: Review. The `if(removed)` was commented out to always delete and remove subscriptions.
- // if we dont then property changes dont get applied and old subs still trigger
- //if (removed) {
- if (Object.keys(sub).length === 0) {
- delete node.subscriptions[topic];
- delete node.subscriptionIds[topic];
- if (node.connected) {
- node.client.unsubscribe(topic);
- }
- }
- //}
- }
- };
- node.topicAliases = {};
-
- node.publish = function (msg,done) {
- if (node.connected) {
- if (msg.payload === null || msg.payload === undefined) {
- msg.payload = "";
- } else if (!Buffer.isBuffer(msg.payload)) {
- if (typeof msg.payload === "object") {
- msg.payload = JSON.stringify(msg.payload);
- } else if (typeof msg.payload !== "string") {
- msg.payload = "" + msg.payload;
- }
- }
- var options = {
- qos: msg.qos || 0,
- retain: msg.retain || false
- };
- //https://github.com/mqttjs/MQTT.js/blob/master/README.md#mqttclientpublishtopic-message-options-callback
- if(node.options.protocolVersion == 5) {
- options.properties = options.properties || {};
- setStrProp(msg, options.properties, "responseTopic");
- setBufferProp(msg, options.properties, "correlationData");
- setStrProp(msg, options.properties, "contentType");
- setIntProp(msg, options.properties, "messageExpiryInterval", 0);
- setUserProperties(msg.userProperties, options.properties);
- setIntProp(msg, options.properties, "topicAlias", 1, node.serverProperties.topicAliasMaximum || 0);
- setBoolProp(msg, options.properties, "payloadFormatIndicator");
- //FUTURE setIntProp(msg, options.properties, "subscriptionIdentifier", 1, 268435455);
- if (options.properties.topicAlias) {
- if (!node.topicAliases.hasOwnProperty(options.properties.topicAlias) && msg.topic == "") {
- done("Invalid topicAlias");
- return
- }
- if (node.topicAliases[options.properties.topicAlias] === msg.topic) {
- msg.topic = ""
- } else {
- node.topicAliases[options.properties.topicAlias] = msg.topic
- }
- }
- }
-
- node.client.publish(msg.topic, msg.payload, options, function(err) {
- done && done(err);
- return
- });
- }
- };
-
- node.on('close', function(done) {
- node.closing = true;
- node.disconnect(done);
- });
-
- }
-
- RED.nodes.registerType("mqtt-broker",MQTTBrokerNode,{
- credentials: {
- user: {type:"text"},
- password: {type: "password"}
- }
- });
- //#endregion "Broker node"
-
- //#region "MQTTIn node"
- function MQTTInNode(n) {
- RED.nodes.createNode(this,n);
- /**@type {MQTTInNode}*/const node = this;
- /**@type {string}*/node.broker = n.broker;
- /**@type {MQTTBrokerNode}*/node.brokerConn = RED.nodes.getNode(node.broker);
-
- node.dynamicSubs = {};
- node.isDynamic = n.hasOwnProperty("inputs") && n.inputs == 1
- node.inputs = n.inputs;
- node.topic = n.topic;
- node.qos = parseInt(n.qos);
- node.subscriptionIdentifier = n.subscriptionIdentifier;//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901117
- node.nl = n.nl;
- node.rap = n.rap;
- node.rh = n.rh;
-
- const Actions = {
- CONNECT: 'connect',
- DISCONNECT: 'disconnect',
- SUBSCRIBE: 'subscribe',
- UNSUBSCRIBE: 'unsubscribe',
- GETSUBS: 'getSubscriptions',
- };
- const allowableActions = Object.values(Actions);
-
- if (isNaN(node.qos) || node.qos < 0 || node.qos > 2) {
- node.qos = 2;
- }
- if (!node.isDynamic && !isValidSubscriptionTopic(node.topic)) {
- return node.warn(RED._("mqtt.errors.invalid-topic"));
- }
- node.datatype = n.datatype || "utf8";
- if (node.brokerConn) {
- const v5 = node.brokerConn.options && node.brokerConn.options.protocolVersion == 5;
- setStatusDisconnected(node);
- if (node.topic || node.isDynamic) {
- node.brokerConn.register(node);
- if (!node.isDynamic) {
- let options = { qos: node.qos };
- if(v5) {
- setIntProp(node, options, "rh", 0, 2, 0);
- if(node.nl === "true" || node.nl === true) options.nl = true;
- else if(node.nl === "false" || node.nl === false) options.nl = false;
- if(node.rap === "true" || node.rap === true) options.rap = true;
- else if(node.rap === "false" || node.rap === false) options.rap = false;
- }
-
- node.brokerConn.subscribe(node.topic,options,function(topic, payload, packet) {
- subscriptionHandler(node, node.datatype, topic, payload, packet);
- },node.id);
- }
- if (node.brokerConn.connected) {
- node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
- }
- }
- else {
- node.error(RED._("mqtt.errors.not-defined"));
- }
- node.on('input', function (msg, send, done) {
- const v5 = node.brokerConn.options && node.brokerConn.options.protocolVersion == 5;
- const action = msg.action;
-
- if (!allowableActions.includes(action)) {
- done(new Error(RED._('mqtt.errors.invalid-action-action')));
- return;
- }
-
- if (action === Actions.CONNECT) {
- handleConnectAction(node, msg, done)
- } else if (action === Actions.DISCONNECT) {
- handleDisconnectAction(node, done)
- } else if (action === Actions.SUBSCRIBE || action === Actions.UNSUBSCRIBE) {
- const subscriptions = [];
- let actionData;
- //coerce msg.topic into an array of strings or objects (for later iteration)
- if(action === Actions.UNSUBSCRIBE && msg.topic === true) {
- actionData = Object.values(node.dynamicSubs);
- } else if (Array.isArray(msg.topic)) {
- actionData = msg.topic;
- } else if (typeof msg.topic == 'string' || typeof msg.topic == 'object') {
- actionData = [msg.topic];
- } else {
- done(new Error(RED._('mqtt.errors.invalid-action-badsubscription')));
- return;
- }
- //ensure each subscription is an object with topic etc
- for (let index = 0; index < actionData.length; index++) {
- let subscription = actionData[index];
- if (typeof subscription === 'string') {
- subscription = { topic: subscription };
- }
- if (!subscription.topic || !isValidSubscriptionTopic(subscription.topic)) {
- done(new Error(RED._('mqtt.errors.invalid-topic')));
- return;
- }
- subscriptions.push(subscription);
- }
- if (action === Actions.UNSUBSCRIBE) {
- subscriptions.forEach(function (sub) {
- node.brokerConn.unsubscribe(sub.topic, node.id);
- delete node.dynamicSubs[sub.topic];
- })
- //user can access current subscriptions through the complete node is so desired
- msg.subscriptions = Object.values(node.dynamicSubs);
- done();
- } else if (action === Actions.SUBSCRIBE) {
- subscriptions.forEach(function (sub) {
- //always unsubscribe before subscribe to prevent multiple subs to same topic
- if (node.dynamicSubs[sub.topic]) {
- node.brokerConn.unsubscribe(sub.topic, node.id);
- delete node.dynamicSubs[sub.topic];
- }
-
- //prepare options. Default qos 2 & rap flag true (same as 'mqtt in' node ui defaults when adding to editor)
- let options = {}
- setIntProp(sub, options, 'qos', 0, 2, 2);//default to qos 2 (same as 'mqtt in' default)
- sub.qos = options.qos;
- if (v5) {
- setIntProp(sub, options, 'rh', 0, 2, 0); //default rh to 0:send retained messages (same as 'mqtt in' default)
- sub.rh = options.rh;
- setBoolProp(sub, options, 'rap', true); //default rap to true:Keep retain flag of original publish (same as 'mqtt in' default)
- sub.rap = options.rap;
- if (sub.nl === 'true' || sub.nl === true) {
- options.nl = true;
- sub.nl = true;
- } else if (sub.nl === 'false' || sub.nl === false) {
- options.nl = false;
- sub.nl = false;
- } else {
- delete sub.nl
- }
- }
-
- //subscribe to sub.topic & hook up subscriptionHandler
- node.brokerConn.subscribe(sub.topic, options, function (topic, payload, packet) {
- subscriptionHandler(node, sub.datatype || node.datatype, topic, payload, packet);
- }, node.id);
- node.dynamicSubs[sub.topic] = sub; //save for later unsubscription & 'list' action
- })
- //user can access current subscriptions through the complete node is so desired
- msg.subscriptions = Object.values(node.dynamicSubs);
- done();
- }
- } else if (action === Actions.GETSUBS) {
- //send list of subscriptions in payload
- msg.topic = "subscriptions";
- msg.payload = Object.values(node.dynamicSubs);
- send(msg);
- done();
- }
- });
-
- node.on('close', function(removed, done) {
- if (node.brokerConn) {
- if(node.isDynamic) {
- Object.keys(node.dynamicSubs).forEach(function (topic) {
- node.brokerConn.unsubscribe(topic, node.id, removed);
- });
- node.dynamicSubs = {};
- } else {
- node.brokerConn.unsubscribe(node.topic,node.id, removed);
- }
- node.brokerConn.deregister(node, done);
- }
- });
- } else {
- node.error(RED._("mqtt.errors.missing-config"));
- }
- }
- RED.nodes.registerType("mqtt in",MQTTInNode);
- //#endregion "MQTTIn node"
-
- //#region "MQTTOut node"
- function MQTTOutNode(n) {
- RED.nodes.createNode(this,n);
- const node = this;
- node.topic = n.topic;
- node.qos = n.qos || null;
- node.retain = n.retain;
- node.broker = n.broker;
- node.responseTopic = n.respTopic;//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901114
- node.correlationData = n.correl;//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901115
- node.contentType = n.contentType;//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901118
- node.messageExpiryInterval = n.expiry; //https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901112
- try {
- if (/^ *{/.test(n.userProps)) {
- //setup this.userProperties
- setUserProperties(JSON.parse(n.userProps), node);//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901116
- }
- } catch(err) {}
- // node.topicAlias = n.topicAlias; //https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901113
- // node.payloadFormatIndicator = n.payloadFormatIndicator; //https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901111
- // node.subscriptionIdentifier = n.subscriptionIdentifier;//https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901117
-
- /** @type {MQTTBrokerNode}*/node.brokerConn = RED.nodes.getNode(node.broker);
-
- const Actions = {
- CONNECT: 'connect',
- DISCONNECT: 'disconnect',
- };
-
- if (node.brokerConn) {
- setStatusDisconnected(node);
- node.on("input",function(msg,send,done) {
- if (msg.action) {
- if (msg.action === Actions.CONNECT) {
- handleConnectAction(node, msg, done)
- } else if (msg.action === Actions.DISCONNECT) {
- handleDisconnectAction(node, done)
- } else {
- done(new Error(RED._('mqtt.errors.invalid-action-action')));
- return;
- }
- } else {
- doPublish(node, msg, done);
- }
-
- });
- if (node.brokerConn.connected) {
- node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
- }
- node.brokerConn.register(node);
- node.on('close', function(done) {
- node.brokerConn.deregister(node,done);
- });
- } else {
- node.error(RED._("mqtt.errors.missing-config"));
- }
- }
- RED.nodes.registerType("mqtt out",MQTTOutNode);
- //#endregion "MQTTOut node"
-};
diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httpin.html b/packages/node_modules/@node-red/nodes/core/network/21-httpin.html
deleted file mode 100644
index 450bd32cc..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/21-httpin.html
+++ /dev/null
@@ -1,273 +0,0 @@
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httpin.js b/packages/node_modules/@node-red/nodes/core/network/21-httpin.js
deleted file mode 100644
index b458a459c..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/21-httpin.js
+++ /dev/null
@@ -1,356 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var bodyParser = require("body-parser");
- var multer = require("multer");
- var cookieParser = require("cookie-parser");
- var getBody = require('raw-body');
- var cors = require('cors');
- var onHeaders = require('on-headers');
- var typer = require('content-type');
- var mediaTyper = require('media-typer');
- var isUtf8 = require('is-utf8');
- var hashSum = require("hash-sum");
-
- function rawBodyParser(req, res, next) {
- if (req.skipRawBodyParser) { next(); } // don't parse this if told to skip
- if (req._body) { return next(); }
- req.body = "";
- req._body = true;
-
- var isText = true;
- var checkUTF = false;
-
- if (req.headers['content-type']) {
- var contentType = typer.parse(req.headers['content-type'])
- if (contentType.type) {
- var parsedType = mediaTyper.parse(contentType.type);
- if (parsedType.type === "text") {
- isText = true;
- } else if (parsedType.subtype === "xml" || parsedType.suffix === "xml") {
- isText = true;
- } else if (parsedType.type !== "application") {
- isText = false;
- } else if ((parsedType.subtype !== "octet-stream")
- && (parsedType.subtype !== "cbor")
- && (parsedType.subtype !== "x-protobuf")) {
- checkUTF = true;
- } else {
- // application/octet-stream or application/cbor
- isText = false;
- }
-
- }
- }
-
- getBody(req, {
- length: req.headers['content-length'],
- encoding: isText ? "utf8" : null
- }, function (err, buf) {
- if (err) { return next(err); }
- if (!isText && checkUTF && isUtf8(buf)) {
- buf = buf.toString()
- }
- req.body = buf;
- next();
- });
- }
-
- var corsSetup = false;
-
- function createRequestWrapper(node,req) {
- // This misses a bunch of properties (eg headers). Before we use this function
- // need to ensure it captures everything documented by Express and HTTP modules.
- var wrapper = {
- _req: req
- };
- var toWrap = [
- "param",
- "get",
- "is",
- "acceptsCharset",
- "acceptsLanguage",
- "app",
- "baseUrl",
- "body",
- "cookies",
- "fresh",
- "hostname",
- "ip",
- "ips",
- "originalUrl",
- "params",
- "path",
- "protocol",
- "query",
- "route",
- "secure",
- "signedCookies",
- "stale",
- "subdomains",
- "xhr",
- "socket" // TODO: tidy this up
- ];
- toWrap.forEach(function(f) {
- if (typeof req[f] === "function") {
- wrapper[f] = function() {
- node.warn(RED._("httpin.errors.deprecated-call",{method:"msg.req."+f}));
- var result = req[f].apply(req,arguments);
- if (result === req) {
- return wrapper;
- } else {
- return result;
- }
- }
- } else {
- wrapper[f] = req[f];
- }
- });
-
-
- return wrapper;
- }
- function createResponseWrapper(node,res) {
- var wrapper = {
- _res: res
- };
- var toWrap = [
- "append",
- "attachment",
- "cookie",
- "clearCookie",
- "download",
- "end",
- "format",
- "get",
- "json",
- "jsonp",
- "links",
- "location",
- "redirect",
- "render",
- "send",
- "sendfile",
- "sendFile",
- "sendStatus",
- "set",
- "status",
- "type",
- "vary"
- ];
- toWrap.forEach(function(f) {
- wrapper[f] = function() {
- node.warn(RED._("httpin.errors.deprecated-call",{method:"msg.res."+f}));
- var result = res[f].apply(res,arguments);
- if (result === res) {
- return wrapper;
- } else {
- return result;
- }
- }
- });
- return wrapper;
- }
-
- var corsHandler = function(req,res,next) { next(); }
-
- if (RED.settings.httpNodeCors) {
- corsHandler = cors(RED.settings.httpNodeCors);
- RED.httpNode.options("*",corsHandler);
- }
-
- function HTTPIn(n) {
- RED.nodes.createNode(this,n);
- if (RED.settings.httpNodeRoot !== false) {
-
- if (!n.url) {
- this.warn(RED._("httpin.errors.missing-path"));
- return;
- }
- this.url = n.url;
- if (this.url[0] !== '/') {
- this.url = '/'+this.url;
- }
- this.method = n.method;
- this.upload = n.upload;
- this.swaggerDoc = n.swaggerDoc;
-
- var node = this;
-
- this.errorHandler = function(err,req,res,next) {
- node.warn(err);
- res.sendStatus(500);
- };
-
- this.callback = function(req,res) {
- var msgid = RED.util.generateId();
- res._msgid = msgid;
- if (node.method.match(/^(post|delete|put|options|patch)$/)) {
- node.send({_msgid:msgid,req:req,res:createResponseWrapper(node,res),payload:req.body});
- } else if (node.method == "get") {
- node.send({_msgid:msgid,req:req,res:createResponseWrapper(node,res),payload:req.query});
- } else {
- node.send({_msgid:msgid,req:req,res:createResponseWrapper(node,res)});
- }
- };
-
- var httpMiddleware = function(req,res,next) { next(); }
-
- if (RED.settings.httpNodeMiddleware) {
- if (typeof RED.settings.httpNodeMiddleware === "function" || Array.isArray(RED.settings.httpNodeMiddleware)) {
- httpMiddleware = RED.settings.httpNodeMiddleware;
- }
- }
-
- var maxApiRequestSize = RED.settings.apiMaxLength || '5mb';
- var jsonParser = bodyParser.json({limit:maxApiRequestSize});
- var urlencParser = bodyParser.urlencoded({limit:maxApiRequestSize,extended:true});
-
- var metricsHandler = function(req,res,next) { next(); }
- if (this.metric()) {
- metricsHandler = function(req, res, next) {
- var startAt = process.hrtime();
- onHeaders(res, function() {
- if (res._msgid) {
- var diff = process.hrtime(startAt);
- var ms = diff[0] * 1e3 + diff[1] * 1e-6;
- var metricResponseTime = ms.toFixed(3);
- var metricContentLength = res.getHeader("content-length");
- //assuming that _id has been set for res._metrics in HttpOut node!
- node.metric("response.time.millis", {_msgid:res._msgid} , metricResponseTime);
- node.metric("response.content-length.bytes", {_msgid:res._msgid} , metricContentLength);
- }
- });
- next();
- };
- }
-
- var multipartParser = function(req,res,next) { next(); }
- if (this.upload) {
- var mp = multer({ storage: multer.memoryStorage() }).any();
- multipartParser = function(req,res,next) {
- mp(req,res,function(err) {
- req._body = true;
- next(err);
- })
- };
- }
-
- if (this.method == "get") {
- RED.httpNode.get(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,this.callback,this.errorHandler);
- } else if (this.method == "post") {
- RED.httpNode.post(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,multipartParser,rawBodyParser,this.callback,this.errorHandler);
- } else if (this.method == "put") {
- RED.httpNode.put(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
- } else if (this.method == "patch") {
- RED.httpNode.patch(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
- } else if (this.method == "delete") {
- RED.httpNode.delete(this.url,cookieParser(),httpMiddleware,corsHandler,metricsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
- }
-
- this.on("close",function() {
- var node = this;
- RED.httpNode._router.stack.forEach(function(route,i,routes) {
- if (route.route && route.route.path === node.url && route.route.methods[node.method]) {
- routes.splice(i,1);
- }
- });
- });
- } else {
- this.warn(RED._("httpin.errors.not-created"));
- }
- }
- RED.nodes.registerType("http in",HTTPIn);
-
-
- function HTTPOut(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- this.headers = n.headers||{};
- this.statusCode = n.statusCode;
- this.on("input",function(msg,_send,done) {
- if (msg.res) {
- var headers = RED.util.cloneMessage(node.headers);
- if (msg.headers) {
- if (msg.headers.hasOwnProperty('x-node-red-request-node')) {
- var headerHash = msg.headers['x-node-red-request-node'];
- delete msg.headers['x-node-red-request-node'];
- var hash = hashSum(msg.headers);
- if (hash === headerHash) {
- delete msg.headers;
- }
- }
- if (msg.headers) {
- for (var h in msg.headers) {
- if (msg.headers.hasOwnProperty(h) && !headers.hasOwnProperty(h)) {
- headers[h] = msg.headers[h];
- }
- }
- }
- }
- if (Object.keys(headers).length > 0) {
- msg.res._res.set(headers);
- }
- if (msg.cookies) {
- for (var name in msg.cookies) {
- if (msg.cookies.hasOwnProperty(name)) {
- if (msg.cookies[name] === null || msg.cookies[name].value === null) {
- if (msg.cookies[name]!==null) {
- msg.res._res.clearCookie(name,msg.cookies[name]);
- } else {
- msg.res._res.clearCookie(name);
- }
- } else if (typeof msg.cookies[name] === 'object') {
- msg.res._res.cookie(name,msg.cookies[name].value,msg.cookies[name]);
- } else {
- msg.res._res.cookie(name,msg.cookies[name]);
- }
- }
- }
- }
- var statusCode = node.statusCode || msg.statusCode || 200;
- if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) {
- msg.res._res.status(statusCode).jsonp(msg.payload);
- } else {
- if (msg.res._res.get('content-length') == null) {
- var len;
- if (msg.payload == null) {
- len = 0;
- } else if (Buffer.isBuffer(msg.payload)) {
- len = msg.payload.length;
- } else if (typeof msg.payload == "number") {
- len = Buffer.byteLength(""+msg.payload);
- } else {
- len = Buffer.byteLength(msg.payload);
- }
- msg.res._res.set('content-length', len);
- }
-
- if (typeof msg.payload === "number") {
- msg.payload = ""+msg.payload;
- }
- msg.res._res.status(statusCode).send(msg.payload);
- }
- } else {
- node.warn(RED._("httpin.errors.no-response"));
- }
- done();
- });
- }
- RED.nodes.registerType("http response",HTTPOut);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
deleted file mode 100644
index bf1f76b7f..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
+++ /dev/null
@@ -1,249 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js
deleted file mode 100644
index e9bf49d68..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.js
+++ /dev/null
@@ -1,673 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- const got = require("got");
- const {CookieJar} = require("tough-cookie");
- const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent');
- const FormData = require('form-data');
- const { v4: uuid } = require('uuid');
- const crypto = require('crypto');
- const URL = require("url").URL
- var mustache = require("mustache");
- var querystring = require("querystring");
- var cookie = require("cookie");
- var hashSum = require("hash-sum");
-
-
- // Cache a reference to the existing https.request function
- // so we can compare later to see if an old agent-base instance
- // has been required.
- // This is generally okay as the core nodes are required before
- // any contrib nodes. Where it will fail is if the agent-base module
- // is required via the settings file or outside of Node-RED before it
- // is started.
- // If there are other modules that patch the function, they will get undone
- // as well. Not much we can do about that right now. Patching core
- // functions is bad.
- const HTTPS_MODULE = require("https");
- const HTTPS_REQUEST = HTTPS_MODULE.request;
-
- function checkNodeAgentPatch() {
- if (HTTPS_MODULE.request !== HTTPS_REQUEST && HTTPS_MODULE.request.length === 2) {
- RED.log.warn(`
-
----------------------------------------------------------------------
-Patched https.request function detected. This will break the
-HTTP Request node. The original code has now been restored.
-
-This is likely caused by a contrib node including an old version of
-the 'agent-base@<5.0.0' module.
-
-You can identify what node is at fault by running:
- npm list agent-base
-in your Node-RED user directory (${RED.settings.userDir}).
----------------------------------------------------------------------
-`);
- HTTPS_MODULE.request = HTTPS_REQUEST
- }
- }
-
- function HTTPRequest(n) {
- RED.nodes.createNode(this,n);
- checkNodeAgentPatch();
- var node = this;
- var nodeUrl = n.url;
- var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1;
- var nodeMethod = n.method || "GET";
- var paytoqs = false;
- var paytobody = false;
- var redirectList = [];
- var sendErrorsToCatch = n.senderr;
-
- var nodeHTTPPersistent = n["persist"];
- if (n.tls) {
- var tlsNode = RED.nodes.getNode(n.tls);
- }
- this.ret = n.ret || "txt";
- this.authType = n.authType || "basic";
- if (RED.settings.httpRequestTimeout) { this.reqTimeout = parseInt(RED.settings.httpRequestTimeout) || 120000; }
- else { this.reqTimeout = 120000; }
-
- if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; }
- else if (n.paytoqs === "body") { paytobody = true; }
-
-
- var prox, noprox;
- if (process.env.http_proxy) { prox = process.env.http_proxy; }
- if (process.env.HTTP_PROXY) { prox = process.env.HTTP_PROXY; }
- if (process.env.no_proxy) { noprox = process.env.no_proxy.split(","); }
- if (process.env.NO_PROXY) { noprox = process.env.NO_PROXY.split(","); }
-
- var proxyConfig = null;
- if (n.proxy) {
- proxyConfig = RED.nodes.getNode(n.proxy);
- prox = proxyConfig.url;
- noprox = proxyConfig.noproxy;
- }
-
- let timingLog = false;
- if (RED.settings.hasOwnProperty("httpRequestTimingLog")) {
- timingLog = RED.settings.httpRequestTimingLog;
- }
-
- this.on("input",function(msg,nodeSend,nodeDone) {
- checkNodeAgentPatch();
- //reset redirectList on each request
- redirectList = [];
- var preRequestTimestamp = process.hrtime();
- node.status({fill:"blue",shape:"dot",text:"httpin.status.requesting"});
- var url = nodeUrl || msg.url;
- if (msg.url && nodeUrl && (nodeUrl !== msg.url)) { // revert change below when warning is finally removed
- node.warn(RED._("common.errors.nooverride"));
- }
-
- if (isTemplatedUrl) {
- url = mustache.render(nodeUrl,msg);
- }
- if (!url) {
- node.error(RED._("httpin.errors.no-url"),msg);
- nodeDone();
- return;
- }
-
-
- // url must start http:// or https:// so assume http:// if not set
- if (url.indexOf("://") !== -1 && url.indexOf("http") !== 0) {
- node.warn(RED._("httpin.errors.invalid-transport"));
- node.status({fill:"red",shape:"ring",text:"httpin.errors.invalid-transport"});
- nodeDone();
- return;
- }
- if (!((url.indexOf("http://") === 0) || (url.indexOf("https://") === 0))) {
- if (tlsNode) {
- url = "https://"+url;
- } else {
- url = "http://"+url;
- }
- }
-
- // The Request module used in Node-RED 1.x was tolerant of query strings that
- // were partially encoded. For example - "?a=hello%20there&b=20%"
- // The GOT module doesn't like that.
- // The following is an attempt to normalise the url to ensure it is properly
- // encoded. We cannot just encode it directly as we don't want any valid
- // encoded entity to end up doubly encoded.
- if (url.indexOf("?") > -1) {
- // Only do this if there is a query string to deal with
- const [hostPath, ...queryString] = url.split("?")
- const query = queryString.join("?");
- if (query) {
- // Look for any instance of % not followed by two hex chars.
- // Replace any we find with %25.
- const escapedQueryString = query.replace(/(%.?.?)/g, function(v) {
- if (/^%[a-f0-9]{2}/i.test(v)) {
- return v;
- }
- return v.replace(/%/,"%25")
- })
- url = hostPath+"?"+escapedQueryString;
- }
- }
-
- var method = nodeMethod.toUpperCase() || "GET";
- if (msg.method && n.method && (n.method !== "use")) { // warn if override option not set
- node.warn(RED._("common.errors.nooverride"));
- }
- if (msg.method && n.method && (n.method === "use")) {
- method = msg.method.toUpperCase(); // use the msg parameter
- }
-
- // var isHttps = (/^https/i.test(url));
-
- var opts = {};
- // set defaultport, else when using HttpsProxyAgent, it's defaultPort of 443 will be used :(.
- // Had to remove this to get http->https redirect to work
- // opts.defaultPort = isHttps?443:80;
- opts.timeout = node.reqTimeout;
- opts.throwHttpErrors = false;
- // TODO: add UI option to auto decompress. Setting to false for 1.x compatibility
- opts.decompress = false;
- opts.method = method;
- opts.headers = {};
- opts.retry = 0;
- opts.responseType = 'buffer';
- opts.maxRedirects = 21;
- opts.cookieJar = new CookieJar();
- opts.ignoreInvalidCookies = true;
- opts.forever = nodeHTTPPersistent;
- if (msg.requestTimeout !== undefined) {
- if (isNaN(msg.requestTimeout)) {
- node.warn(RED._("httpin.errors.timeout-isnan"));
- } else if (msg.requestTimeout < 1) {
- node.warn(RED._("httpin.errors.timeout-isnegative"));
- } else {
- opts.timeout = msg.requestTimeout;
- }
- }
- const originalHeaderMap = {};
-
- opts.hooks = {
- beforeRequest: [
- options => {
- // Whilst HTTP headers are meant to be case-insensitive,
- // in the real world, there are servers that aren't so compliant.
- // GOT will lower case all headers given a chance, so we need
- // to restore the case of any headers the user has set.
- Object.keys(options.headers).forEach(h => {
- if (originalHeaderMap[h] && originalHeaderMap[h] !== h) {
- options.headers[originalHeaderMap[h]] = options.headers[h];
- delete options.headers[h];
- }
- })
- }
- ],
- beforeRedirect: [
- (options, response) => {
- let redirectInfo = {
- location: response.headers.location
- }
- if (response.headers.hasOwnProperty('set-cookie')) {
- redirectInfo.cookies = extractCookies(response.headers['set-cookie']);
- }
- redirectList.push(redirectInfo)
- }
- ]
- }
-
- var ctSet = "Content-Type"; // set default camel case
- var clSet = "Content-Length";
- if (msg.headers) {
- if (msg.headers.hasOwnProperty('x-node-red-request-node')) {
- var headerHash = msg.headers['x-node-red-request-node'];
- delete msg.headers['x-node-red-request-node'];
- var hash = hashSum(msg.headers);
- if (hash === headerHash) {
- delete msg.headers;
- }
- }
- if (msg.headers) {
- for (var v in msg.headers) {
- if (msg.headers.hasOwnProperty(v)) {
- var name = v.toLowerCase();
- if (name !== "content-type" && name !== "content-length") {
- // only normalise the known headers used later in this
- // function. Otherwise leave them alone.
- name = v;
- }
- else if (name === 'content-type') { ctSet = v; }
- else { clSet = v; }
- opts.headers[name] = msg.headers[v];
- }
- }
- }
- }
-
- if (msg.hasOwnProperty('followRedirects')) {
- opts.followRedirect = !!msg.followRedirects;
- }
-
- if (opts.headers.hasOwnProperty('cookie')) {
- var cookies = cookie.parse(opts.headers.cookie, {decode:String});
- for (var name in cookies) {
- opts.cookieJar.setCookie(cookie.serialize(name, cookies[name], {encode:String}), url, {ignoreError: true});
- }
- delete opts.headers.cookie;
- }
- if (msg.cookies) {
- for (var name in msg.cookies) {
- if (msg.cookies.hasOwnProperty(name)) {
- if (msg.cookies[name] === null || msg.cookies[name].value === null) {
- // This case clears a cookie for HTTP In/Response nodes.
- // Ignore for this node.
- } else if (typeof msg.cookies[name] === 'object') {
- if(msg.cookies[name].encode === false){
- // If the encode option is false, the value is not encoded.
- opts.cookieJar.setCookie(cookie.serialize(name, msg.cookies[name].value, {encode: String}), url, {ignoreError: true});
- } else {
- // The value is encoded by encodeURIComponent().
- opts.cookieJar.setCookie(cookie.serialize(name, msg.cookies[name].value), url, {ignoreError: true});
- }
- } else {
- opts.cookieJar.setCookie(cookie.serialize(name, msg.cookies[name]), url, {ignoreError: true});
- }
- }
- }
- }
- var parsedURL = new URL(url)
- this.credentials = this.credentials || {}
- if (parsedURL.username && !this.credentials.user) {
- this.credentials.user = parsedURL.username
- }
- if (parsedURL.password && !this.credentials.password) {
- this.credentials.password = parsedURL.password
- }
- if (Object.keys(this.credentials).length != 0) {
- if (this.authType === "basic") {
- // Workaround for https://github.com/sindresorhus/got/issues/1169 (fixed in got v12)
- // var cred = ""
- if (this.credentials.user || this.credentials.password) {
- // cred = `${this.credentials.user}:${this.credentials.password}`;
- opts.headers.Authorization = "Basic " + Buffer.from(`${this.credentials.user}:${this.credentials.password}`).toString("base64");
- }
- // build own basic auth header
- // opts.headers.Authorization = "Basic " + Buffer.from(cred).toString("base64");
- } else if (this.authType === "digest") {
- let digestCreds = this.credentials;
- let sentCreds = false;
- opts.hooks.afterResponse = [(response, retry) => {
- if (response.statusCode === 401) {
- if (sentCreds) {
- return response
- }
- const requestUrl = new URL(response.request.requestUrl);
- const options = response.request.options;
- const normalisedHeaders = {};
- Object.keys(response.headers).forEach(k => {
- normalisedHeaders[k.toLowerCase()] = response.headers[k]
- })
- if (normalisedHeaders['www-authenticate']) {
- let authHeader = buildDigestHeader(digestCreds.user,digestCreds.password, options.method, requestUrl.pathname, normalisedHeaders['www-authenticate'])
- options.headers.Authorization = authHeader;
- }
- sentCreds = true;
- return retry(options);
- }
- return response
- }];
- } else if (this.authType === "bearer") {
- opts.headers.Authorization = `Bearer ${this.credentials.password||""}`
- }
- }
- var payload = null;
-
-
- if (method !== 'GET' && method !== 'HEAD' && typeof msg.payload !== "undefined") {
- if (opts.headers['content-type'] == 'multipart/form-data' && typeof msg.payload === "object") {
- let formData = new FormData();
- for (var opt in msg.payload) {
- if (msg.payload.hasOwnProperty(opt)) {
- var val = msg.payload[opt];
- if (val !== undefined && val !== null) {
- if (typeof val === 'string' || Buffer.isBuffer(val)) {
- formData.append(opt, val);
- } else if (typeof val === 'object' && val.hasOwnProperty('value')) {
- formData.append(opt,val.value,val.options || {});
- } else {
- formData.append(opt,JSON.stringify(val));
- }
- }
- }
- }
- // GOT will only set the content-type header with the correct boundary
- // if the header isn't set. So we delete it here, for GOT to reset it.
- delete opts.headers['content-type'];
- opts.body = formData;
- } else {
- if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
- payload = msg.payload;
- } else if (typeof msg.payload == "number") {
- payload = msg.payload+"";
- } else {
- if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') {
- payload = querystring.stringify(msg.payload);
- } else {
- payload = JSON.stringify(msg.payload);
- if (opts.headers['content-type'] == null) {
- opts.headers[ctSet] = "application/json";
- }
- }
- }
- if (opts.headers['content-length'] == null) {
- if (Buffer.isBuffer(payload)) {
- opts.headers[clSet] = payload.length;
- } else {
- opts.headers[clSet] = Buffer.byteLength(payload);
- }
- }
- opts.body = payload;
- }
- }
-
-
- if (method == 'GET' && typeof msg.payload !== "undefined" && paytoqs) {
- if (typeof msg.payload === "object") {
- try {
- if (url.indexOf("?") !== -1) {
- url += (url.endsWith("?")?"":"&") + querystring.stringify(msg.payload);
- } else {
- url += "?" + querystring.stringify(msg.payload);
- }
- } catch(err) {
-
- node.error(RED._("httpin.errors.invalid-payload"),msg);
- nodeDone();
- return;
- }
- } else {
-
- node.error(RED._("httpin.errors.invalid-payload"),msg);
- nodeDone();
- return;
- }
- } else if ( method == "GET" && typeof msg.payload !== "undefined" && paytobody) {
- opts.allowGetBody = true;
- if (typeof msg.payload === "object") {
- opts.body = JSON.stringify(msg.payload);
- } else if (typeof msg.payload == "number") {
- opts.body = msg.payload+"";
- } else if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
- opts.body = msg.payload;
- }
- }
-
- // revert to user supplied Capitalisation if needed.
- if (opts.headers.hasOwnProperty('content-type') && (ctSet !== 'content-type')) {
- opts.headers[ctSet] = opts.headers['content-type'];
- delete opts.headers['content-type'];
- }
- if (opts.headers.hasOwnProperty('content-length') && (clSet !== 'content-length')) {
- opts.headers[clSet] = opts.headers['content-length'];
- delete opts.headers['content-length'];
- }
-
- var noproxy;
- if (noprox) {
- for (var i = 0; i < noprox.length; i += 1) {
- if (url.indexOf(noprox[i]) !== -1) { noproxy=true; }
- }
- }
- if (prox && !noproxy) {
- var match = prox.match(/^(https?:\/\/)?(.+)?:([0-9]+)?/i);
- if (match) {
- let proxyAgent;
- let proxyURL = new URL(prox);
- //set username/password to null to stop empty creds header
- let proxyOptions = {
- proxy: {
- protocol: proxyURL.protocol,
- hostname: proxyURL.hostname,
- port: proxyURL.port,
- username: null,
- password: null
- },
- maxFreeSockets: 256,
- maxSockets: 256,
- keepAlive: true
- }
- if (proxyConfig && proxyConfig.credentials) {
- let proxyUsername = proxyConfig.credentials.username || '';
- let proxyPassword = proxyConfig.credentials.password || '';
- if (proxyUsername || proxyPassword) {
- proxyOptions.proxy.username = proxyUsername;
- proxyOptions.proxy.password = proxyPassword;
- }
- } else if (proxyURL.username || proxyURL.password){
- proxyOptions.proxy.username = proxyURL.username;
- proxyOptions.proxy.password = proxyURL.password;
- }
- //need both incase of http -> https redirect
- opts.agent = {
- http: new HttpProxyAgent(proxyOptions),
- https: new HttpsProxyAgent(proxyOptions)
- };
-
- } else {
- node.warn("Bad proxy url: "+ prox);
- }
- }
- if (tlsNode) {
- opts.https = {};
- tlsNode.addTLSOptions(opts.https);
- if (opts.https.ca) {
- opts.https.certificateAuthority = opts.https.ca;
- delete opts.https.ca;
- }
- if (opts.https.cert) {
- opts.https.certificate = opts.https.cert;
- delete opts.https.cert;
- }
- } else {
- if (msg.hasOwnProperty('rejectUnauthorized')) {
- opts.https = { rejectUnauthorized: msg.rejectUnauthorized };
- }
- }
-
- // Now we have established all of our own headers, take a snapshot
- // of their case so we can restore it prior to the request being sent.
- if (opts.headers) {
- Object.keys(opts.headers).forEach(h => {
- originalHeaderMap[h.toLowerCase()] = h
- })
- }
- got(url,opts).then(res => {
- msg.statusCode = res.statusCode;
- msg.headers = res.headers;
- msg.responseUrl = res.url;
- msg.payload = res.body;
- msg.redirectList = redirectList;
- msg.retry = 0;
-
- if (msg.headers.hasOwnProperty('set-cookie')) {
- msg.responseCookies = extractCookies(msg.headers['set-cookie']);
- }
- msg.headers['x-node-red-request-node'] = hashSum(msg.headers);
- // msg.url = url; // revert when warning above finally removed
- if (node.metric()) {
- // Calculate request time
- var diff = process.hrtime(preRequestTimestamp);
- var ms = diff[0] * 1e3 + diff[1] * 1e-6;
- var metricRequestDurationMillis = ms.toFixed(3);
- node.metric("duration.millis", msg, metricRequestDurationMillis);
- if (res.client && res.client.bytesRead) {
- node.metric("size.bytes", msg, res.client.bytesRead);
- }
- if (timingLog) {
- emitTimingMetricLog(res.timings, msg);
- }
- }
-
- // Convert the payload to the required return type
- if (node.ret !== "bin") {
- msg.payload = msg.payload.toString('utf8'); // txt
-
- if (node.ret === "obj") {
- try { msg.payload = JSON.parse(msg.payload); } // obj
- catch(e) { node.warn(RED._("httpin.errors.json-error")); }
- }
- }
- node.status({});
- nodeSend(msg);
- nodeDone();
- }).catch(err => {
- // Pre 2.1, any errors would be sent to both Catch node and sent on as normal.
- // This is not ideal but is the legacy behaviour of the node.
- // 2.1 adds the 'senderr' option, if set to true, will *only* send errors
- // to Catch nodes. If false, it still does both behaviours.
- // TODO: 3.0 - make it one or the other.
-
- if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
- node.error(RED._("common.notification.errors.no-response"), msg);
- node.status({fill:"red", shape:"ring", text:"common.notification.errors.no-response"});
- } else {
- node.error(err,msg);
- node.status({fill:"red", shape:"ring", text:err.code});
- }
- msg.payload = err.toString() + " : " + url;
- msg.statusCode = err.code || (err.response?err.response.statusCode:undefined);
- if (node.metric() && timingLog) {
- emitTimingMetricLog(err.timings, msg);
- }
- if (!sendErrorsToCatch) {
- nodeSend(msg);
- }
- nodeDone();
- });
- });
-
- this.on("close",function() {
- node.status({});
- });
-
- function emitTimingMetricLog(timings, msg) {
- const props = [
- "start",
- "socket",
- "lookup",
- "connect",
- "secureConnect",
- "upload",
- "response",
- "end",
- "error",
- "abort"
- ];
- if (timings) {
- props.forEach(p => {
- if (timings[p]) {
- node.metric(`timings.${p}`, msg, timings[p]);
- }
- });
- }
- }
-
- function extractCookies(setCookie) {
- var cookies = {};
- setCookie.forEach(function(c) {
- var parsedCookie = cookie.parse(c);
- var eq_idx = c.indexOf('=');
- var key = c.substr(0, eq_idx).trim()
- parsedCookie.value = parsedCookie[key];
- delete parsedCookie[key];
- cookies[key] = parsedCookie;
- });
- return cookies;
- }
- }
-
- RED.nodes.registerType("http request",HTTPRequest,{
- credentials: {
- user: {type:"text"},
- password: {type: "password"}
- }
- });
-
- const md5 = (value) => { return crypto.createHash('md5').update(value).digest('hex') }
-
- function ha1Compute(algorithm, user, realm, pass, nonce, cnonce) {
- /**
- * RFC 2617: handle both MD5 and MD5-sess algorithms.
- *
- * If the algorithm directive's value is "MD5" or unspecified, then HA1 is
- * HA1=MD5(username:realm:password)
- * If the algorithm directive's value is "MD5-sess", then HA1 is
- * HA1=MD5(MD5(username:realm:password):nonce:cnonce)
- */
- var ha1 = md5(user + ':' + realm + ':' + pass)
- if (algorithm && algorithm.toLowerCase() === 'md5-sess') {
- return md5(ha1 + ':' + nonce + ':' + cnonce)
- } else {
- return ha1
- }
- }
-
-
- function buildDigestHeader(user, pass, method, path, authHeader) {
- var challenge = {}
- var re = /([a-z0-9_-]+)=(?:"([^"]+)"|([a-z0-9_-]+))/gi
- for (;;) {
- var match = re.exec(authHeader)
- if (!match) {
- break
- }
- challenge[match[1]] = match[2] || match[3]
- }
- var qop = /(^|,)\s*auth\s*($|,)/.test(challenge.qop) && 'auth'
- var nc = qop && '00000001'
- var cnonce = qop && uuid().replace(/-/g, '')
- var ha1 = ha1Compute(challenge.algorithm, user, challenge.realm, pass, challenge.nonce, cnonce)
- var ha2 = md5(method + ':' + path)
- var digestResponse = qop
- ? md5(ha1 + ':' + challenge.nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2)
- : md5(ha1 + ':' + challenge.nonce + ':' + ha2)
- var authValues = {
- username: user,
- realm: challenge.realm,
- nonce: challenge.nonce,
- uri: path,
- qop: qop,
- response: digestResponse,
- nc: nc,
- cnonce: cnonce,
- algorithm: challenge.algorithm,
- opaque: challenge.opaque
- }
-
- authHeader = []
- for (var k in authValues) {
- if (authValues[k]) {
- if (k === 'qop' || k === 'nc' || k === 'algorithm') {
- authHeader.push(k + '=' + authValues[k])
- } else {
- authHeader.push(k + '="' + authValues[k] + '"')
- }
- }
- }
- authHeader = 'Digest ' + authHeader.join(', ')
- return authHeader
- }
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/22-websocket.html b/packages/node_modules/@node-red/nodes/core/network/22-websocket.html
deleted file mode 100644
index e3ee30eeb..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/22-websocket.html
+++ /dev/null
@@ -1,288 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/22-websocket.js b/packages/node_modules/@node-red/nodes/core/network/22-websocket.js
deleted file mode 100644
index 3373c6e72..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/22-websocket.js
+++ /dev/null
@@ -1,415 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var ws = require("ws");
- var inspect = require("util").inspect;
- var url = require("url");
- var HttpsProxyAgent = require('https-proxy-agent');
-
-
- var serverUpgradeAdded = false;
- function handleServerUpgrade(request, socket, head) {
- const pathname = url.parse(request.url).pathname;
- if (listenerNodes.hasOwnProperty(pathname)) {
- listenerNodes[pathname].server.handleUpgrade(request, socket, head, function done(ws) {
- listenerNodes[pathname].server.emit('connection', ws, request);
- });
- } else {
- // Don't destroy the socket as other listeners may want to handle the
- // event.
- }
- }
- var listenerNodes = {};
- var activeListenerNodes = 0;
-
-
- // A node red node that sets up a local websocket server
- function WebSocketListenerNode(n) {
- // Create a RED node
- RED.nodes.createNode(this,n);
- var node = this;
-
- // Store local copies of the node configuration (as defined in the .html)
- node.path = n.path;
- node.wholemsg = (n.wholemsg === "true");
-
- node._inputNodes = []; // collection of nodes that want to receive events
- node._clients = {};
- // match absolute url
- node.isServer = !/^ws{1,2}:\/\//i.test(node.path);
- node.closing = false;
- node.tls = n.tls;
-
- if (n.hb) {
- var heartbeat = parseInt(n.hb);
- if (heartbeat > 0) {
- node.heartbeat = heartbeat * 1000;
- }
- }
-
- function startconn() { // Connect to remote endpoint
- node.tout = null;
- var prox, noprox;
- if (process.env.http_proxy) { prox = process.env.http_proxy; }
- if (process.env.HTTP_PROXY) { prox = process.env.HTTP_PROXY; }
- if (process.env.no_proxy) { noprox = process.env.no_proxy.split(","); }
- if (process.env.NO_PROXY) { noprox = process.env.NO_PROXY.split(","); }
-
- var noproxy = false;
- if (noprox) {
- for (var i in noprox) {
- if (node.path.indexOf(noprox[i].trim()) !== -1) { noproxy=true; }
- }
- }
-
- var agent = undefined;
- if (prox && !noproxy) {
- agent = new HttpsProxyAgent(prox);
- }
-
- var options = {};
- if (agent) {
- options.agent = agent;
- }
- if (node.tls) {
- var tlsNode = RED.nodes.getNode(node.tls);
- if (tlsNode) {
- tlsNode.addTLSOptions(options);
- }
- }
- var socket = new ws(node.path,options);
- socket.setMaxListeners(0);
- node.server = socket; // keep for closing
- handleConnection(socket);
- }
-
- function handleConnection(/*socket*/socket) {
- var id = RED.util.generateId();
- socket.nrId = id;
- socket.nrPendingHeartbeat = false;
- if (node.isServer) {
- node._clients[id] = socket;
- node.emit('opened',{count:Object.keys(node._clients).length,id:id});
- } else {
- if (node.heartbeat) {
- node.heartbeatInterval = setInterval(function() {
- if (socket.nrPendingHeartbeat) {
- // No pong received
- socket.terminate();
- socket.nrErrorHandler(new Error("timeout"));
- return;
- }
- socket.nrPendingHeartbeat = true;
- socket.ping();
- },node.heartbeat);
- }
- }
- socket.on('open',function() {
- if (!node.isServer) {
- node.emit('opened',{count:'',id:id});
- }
- });
- socket.on('close',function() {
- clearInterval(node.heartbeatInterval);
- if (node.isServer) {
- delete node._clients[id];
- node.emit('closed',{count:Object.keys(node._clients).length,id:id});
- } else {
- node.emit('closed',{count:'',id:id});
- }
- if (!node.closing && !node.isServer) {
- clearTimeout(node.tout);
- node.tout = setTimeout(function() { startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
- }
- });
- socket.on('message',function(data,flags) {
- node.handleEvent(id,socket,'message',data,flags);
- });
- socket.nrErrorHandler = function(err) {
- clearInterval(node.heartbeatInterval);
- node.emit('erro',{err:err,id:id});
- if (!node.closing && !node.isServer) {
- clearTimeout(node.tout);
- node.tout = setTimeout(function() { startconn(); }, 3000); // try to reconnect every 3 secs... bit fast ?
- }
- }
- socket.on('error',socket.nrErrorHandler);
- socket.on('ping', function() {
- socket.nrPendingHeartbeat = false;
- })
- socket.on('pong', function() {
- socket.nrPendingHeartbeat = false;
- })
- }
-
- if (node.isServer) {
- activeListenerNodes++;
- if (!serverUpgradeAdded) {
- RED.server.on('upgrade', handleServerUpgrade);
- serverUpgradeAdded = true
- }
-
- var path = RED.settings.httpNodeRoot || "/";
- path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path);
- node.fullPath = path;
-
- if (listenerNodes.hasOwnProperty(path)) {
- node.error(RED._("websocket.errors.duplicate-path",{path: node.path}));
- return;
- }
- listenerNodes[node.fullPath] = node;
- var serverOptions = {
- noServer: true
- }
- if (RED.settings.webSocketNodeVerifyClient) {
- serverOptions.verifyClient = RED.settings.webSocketNodeVerifyClient;
- }
- // Create a WebSocket Server
- node.server = new ws.Server(serverOptions);
- node.server.setMaxListeners(0);
- node.server.on('connection', handleConnection);
- // Not adding server-initiated heartbeats yet
- // node.heartbeatInterval = setInterval(function() {
- // node.server.clients.forEach(function(ws) {
- // if (ws.nrPendingHeartbeat) {
- // // No pong received
- // ws.terminate();
- // ws.nrErrorHandler(new Error("timeout"));
- // return;
- // }
- // ws.nrPendingHeartbeat = true;
- // ws.ping();
- // });
- // })
- }
- else {
- node.closing = false;
- startconn(); // start outbound connection
- }
-
- node.on("close", function() {
- if (node.heartbeatInterval) {
- clearInterval(node.heartbeatInterval);
- }
- if (node.isServer) {
- delete listenerNodes[node.fullPath];
- node.server.close();
- node._inputNodes = [];
- activeListenerNodes--;
- // if (activeListenerNodes === 0 && serverUpgradeAdded) {
- // RED.server.removeListener('upgrade', handleServerUpgrade);
- // serverUpgradeAdded = false;
- // }
- }
- else {
- node.closing = true;
- node.server.close();
- if (node.tout) {
- clearTimeout(node.tout);
- node.tout = null;
- }
- }
- });
- }
- RED.nodes.registerType("websocket-listener",WebSocketListenerNode);
- RED.nodes.registerType("websocket-client",WebSocketListenerNode);
-
- WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler) {
- this._inputNodes.push(handler);
- }
-
- WebSocketListenerNode.prototype.removeInputNode = function(/*Node*/handler) {
- this._inputNodes.forEach(function(node, i, inputNodes) {
- if (node === handler) {
- inputNodes.splice(i, 1);
- }
- });
- }
-
- WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags) {
- var msg;
- if (this.wholemsg) {
- try {
- msg = JSON.parse(data);
- if (typeof msg !== "object" && !Array.isArray(msg) && (msg !== null)) {
- msg = { payload:msg };
- }
- }
- catch(err) {
- msg = { payload:data };
- }
- } else {
- msg = {
- payload:data
- };
- }
- msg._session = {type:"websocket",id:id};
- for (var i = 0; i < this._inputNodes.length; i++) {
- this._inputNodes[i].send(msg);
- }
- }
-
- WebSocketListenerNode.prototype.broadcast = function(data) {
- if (this.isServer) {
- for (let client in this._clients) {
- if (this._clients.hasOwnProperty(client)) {
- try {
- this._clients[client].send(data);
- } catch(err) {
- this.warn(RED._("websocket.errors.send-error")+" "+client+" "+err.toString())
- }
- }
- }
- }
- else {
- try {
- this.server.send(data);
- } catch(err) {
- this.warn(RED._("websocket.errors.send-error")+" "+err.toString())
- }
- }
- }
-
- WebSocketListenerNode.prototype.reply = function(id,data) {
- var session = this._clients[id];
- if (session) {
- try {
- session.send(data);
- }
- catch(e) { // swallow any errors
- }
- }
- }
-
- function WebSocketInNode(n) {
- RED.nodes.createNode(this,n);
- this.server = (n.client)?n.client:n.server;
- var node = this;
- this.serverConfig = RED.nodes.getNode(this.server);
- if (this.serverConfig) {
- this.serverConfig.registerInputNode(this);
- // TODO: nls
- this.serverConfig.on('opened', function(event) {
- node.status({
- fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count}),
- event:"connect",
- _session: {type:"websocket",id:event.id}
- });
- });
- this.serverConfig.on('erro', function(event) {
- node.status({
- fill:"red",shape:"ring",text:"common.status.error",
- event:"error",
- _session: {type:"websocket",id:event.id}
- });
- });
- this.serverConfig.on('closed', function(event) {
- var status;
- if (event.count > 0) {
- status = {fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count})};
- } else {
- status = {fill:"red",shape:"ring",text:"common.status.disconnected"};
- }
- status.event = "disconnect";
- status._session = {type:"websocket",id:event.id}
- node.status(status);
- });
- } else {
- this.error(RED._("websocket.errors.missing-conf"));
- }
- this.on('close', function() {
- if (node.serverConfig) {
- node.serverConfig.removeInputNode(node);
- }
- node.status({});
- });
- }
- RED.nodes.registerType("websocket in",WebSocketInNode);
-
- function WebSocketOutNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- this.server = (n.client)?n.client:n.server;
- this.serverConfig = RED.nodes.getNode(this.server);
- if (!this.serverConfig) {
- return this.error(RED._("websocket.errors.missing-conf"));
- }
- else {
- // TODO: nls
- this.serverConfig.on('opened', function(event) {
- node.status({
- fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count}),
- event:"connect",
- _session: {type:"websocket",id:event.id}
- });
- });
- this.serverConfig.on('erro', function(event) {
- node.status({
- fill:"red",shape:"ring",text:"common.status.error",
- event:"error",
- _session: {type:"websocket",id:event.id}
- })
- });
- this.serverConfig.on('closed', function(event) {
- var status;
- if (event.count > 0) {
- status = {fill:"green",shape:"dot",text:RED._("websocket.status.connected",{count:event.count})};
- } else {
- status = {fill:"red",shape:"ring",text:"common.status.disconnected"};
- }
- status.event = "disconnect";
- status._session = {type:"websocket",id:event.id}
- node.status(status);
- });
- }
- this.on("input", function(msg, nodeSend, nodeDone) {
- var payload;
- if (this.serverConfig.wholemsg) {
- var sess;
- if (msg._session) { sess = JSON.stringify(msg._session); }
- delete msg._session;
- payload = JSON.stringify(msg);
- if (sess) { msg._session = JSON.parse(sess); }
- }
- else if (msg.hasOwnProperty("payload")) {
- if (!Buffer.isBuffer(msg.payload)) { // if it's not a buffer make sure it's a string.
- payload = RED.util.ensureString(msg.payload);
- }
- else {
- payload = msg.payload;
- }
- }
- if (payload) {
- if (msg._session && msg._session.type == "websocket") {
- node.serverConfig.reply(msg._session.id,payload);
- } else {
- node.serverConfig.broadcast(payload,function(error) {
- if (!!error) {
- node.warn(RED._("websocket.errors.send-error")+inspect(error));
- }
- });
- }
- }
- nodeDone();
- });
- this.on('close', function() {
- node.status({});
- });
- }
- RED.nodes.registerType("websocket out",WebSocketOutNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html
deleted file mode 100644
index 39e987851..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html
+++ /dev/null
@@ -1,277 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
deleted file mode 100644
index 2f59227c8..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
+++ /dev/null
@@ -1,719 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var reconnectTime = RED.settings.socketReconnectTime||10000;
- var socketTimeout = RED.settings.socketTimeout||null;
- const msgQueueSize = RED.settings.tcpMsgQueueSize || 1000;
- const Denque = require('denque');
- var net = require('net');
-
- var connectionPool = {};
-
- /**
- * Enqueue `item` in `queue`
- * @param {Denque} queue - Queue
- * @param {*} item - Item to enqueue
- * @private
- * @returns {Denque} `queue`
- */
- const enqueue = (queue, item) => {
- // drop msgs from front of queue if size is going to be exceeded
- if (queue.length === msgQueueSize) { queue.shift(); }
- queue.push(item);
- return queue;
- };
-
- /**
- * Shifts item off front of queue
- * @param {Deque} queue - Queue
- * @private
- * @returns {*} Item previously at front of queue
- */
- const dequeue = queue => queue.shift();
-
- function TcpIn(n) {
- RED.nodes.createNode(this,n);
- this.host = n.host;
- this.port = n.port * 1;
- this.topic = n.topic;
- this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/
- this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */
- this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r");
- this.base64 = n.base64;
- this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server");
- this.closing = false;
- this.connected = false;
- var node = this;
- var count = 0;
-
- if (!node.server) {
- var buffer = null;
- var client;
- var reconnectTimeout;
- var end = false;
- var setupTcpClient = function() {
- node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
- node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
- var id = RED.util.generateId();
- client = net.connect(node.port, node.host, function() {
- buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
- node.connected = true;
- node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
- node.status({fill:"green",shape:"dot",text:"common.status.connected",_session:{type:"tcp",id:id}});
- });
- client.setKeepAlive(true,120000);
- connectionPool[id] = client;
-
- client.on('data', function (data) {
- if (node.datatype != 'buffer') {
- data = data.toString(node.datatype);
- }
- if (node.stream) {
- var msg;
- if ((node.datatype) === "utf8" && node.newline !== "") {
- buffer = buffer+data;
- var parts = buffer.split(node.newline);
- for (var i = 0; i 0)) {
- var msg = {topic:node.topic, payload:buffer};
- msg._session = {type:"tcp",id:id};
- if (buffer.length !== 0) {
- end = true; // only ask for fast re-connect if we actually got something
- node.send(msg);
- }
- buffer = null;
- }
- });
- client.on('close', function() {
- delete connectionPool[id];
- node.connected = false;
- node.status({fill:"red",shape:"ring",text:"common.status.disconnected",_session:{type:"tcp",id:id}});
- if (!node.closing) {
- if (end) { // if we were asked to close then try to reconnect once very quick.
- end = false;
- reconnectTimeout = setTimeout(setupTcpClient, 20);
- }
- else {
- node.log(RED._("tcpin.errors.connection-lost",{host:node.host,port:node.port}));
- reconnectTimeout = setTimeout(setupTcpClient, reconnectTime);
- }
- } else {
- if (node.doneClose) { node.doneClose(); }
- }
- });
- client.on('error', function(err) {
- node.log(err);
- });
- }
- setupTcpClient();
-
- this.on('close', function(done) {
- node.doneClose = done;
- this.closing = true;
- if (client) { client.destroy(); }
- clearTimeout(reconnectTimeout);
- if (!node.connected) { done(); }
- });
- }
- else {
- var server = net.createServer(function (socket) {
- socket.setKeepAlive(true,120000);
- if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
- var id = RED.util.generateId();
- var fromi;
- var fromp;
- connectionPool[id] = socket;
- count++;
- node.status({
- text:RED._("tcpin.status.connections",{count:count}),
- event:"connect",
- ip:socket.remoteAddress,
- port:socket.remotePort,
- _session: {type:"tcp",id:id}
- });
-
- var buffer = (node.datatype == 'buffer') ? Buffer.alloc(0) : "";
- socket.on('data', function (data) {
- if (node.datatype != 'buffer') {
- data = data.toString(node.datatype);
- }
- if (node.stream) {
- var msg;
- if ((typeof data) === "string" && node.newline !== "") {
- buffer = buffer+data;
- var parts = buffer.split(node.newline);
- for (var i = 0; i 0) {
- var msg = {topic:node.topic, payload:buffer, ip:fromi, port:fromp};
- msg._session = {type:"tcp",id:id};
- node.send(msg);
- }
- buffer = null;
- }
- });
- socket.on('timeout', function() {
- node.log(RED._("tcpin.errors.timeout",{port:node.port}));
- socket.end();
- });
- socket.on('close', function() {
- delete connectionPool[id];
- count--;
- node.status({
- text:RED._("tcpin.status.connections",{count:count}),
- event:"disconnect",
- ip:socket.remoteAddress,
- port:socket.remotePort,
- _session: {type:"tcp",id:id}
-
- });
- });
- socket.on('error',function(err) {
- node.log(err);
- });
- });
-
- server.on('error', function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- }
- });
-
- server.listen(node.port, function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- } else {
- node.log(RED._("tcpin.status.listening-port",{port:node.port}));
- node.on('close', function() {
- for (var c in connectionPool) {
- if (connectionPool.hasOwnProperty(c)) {
- connectionPool[c].end();
- connectionPool[c].unref();
- }
- }
- node.closing = true;
- server.close();
- node.log(RED._("tcpin.status.stopped-listening",{port:node.port}));
- });
- }
- });
- }
- }
- RED.nodes.registerType("tcp in",TcpIn);
-
-
- function TcpOut(n) {
- RED.nodes.createNode(this,n);
- this.host = n.host;
- this.port = n.port * 1;
- this.base64 = n.base64;
- this.doend = n.end || false;
- this.beserver = n.beserver;
- this.name = n.name;
- this.closing = false;
- this.connected = false;
- var node = this;
-
- if (!node.beserver||node.beserver=="client") {
- var reconnectTimeout;
- var client = null;
- var end = false;
-
- var setupTcpClient = function() {
- node.log(RED._("tcpin.status.connecting",{host:node.host,port:node.port}));
- node.status({fill:"grey",shape:"dot",text:"common.status.connecting"});
- client = net.connect(node.port, node.host, function() {
- node.connected = true;
- node.log(RED._("tcpin.status.connected",{host:node.host,port:node.port}));
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
- });
- client.setKeepAlive(true,120000);
- client.on('error', function (err) {
- node.log(RED._("tcpin.errors.error",{error:err.toString()}));
- });
- client.on('end', function (err) {
- node.status({});
- node.connected = false;
- });
- client.on('close', function() {
- node.status({fill:"red",shape:"ring",text:"common.status.disconnected"});
- node.connected = false;
- client.destroy();
- if (!node.closing) {
- if (end) {
- end = false;
- reconnectTimeout = setTimeout(setupTcpClient,20);
- }
- else {
- node.log(RED._("tcpin.errors.connection-lost",{host:node.host,port:node.port}));
- reconnectTimeout = setTimeout(setupTcpClient,reconnectTime);
- }
- } else {
- if (node.doneClose) { node.doneClose(); }
- }
- });
- }
- setupTcpClient();
-
- node.on("input", function(msg, nodeSend, nodeDone) {
- if (node.connected && msg.payload != null) {
- if (Buffer.isBuffer(msg.payload)) {
- client.write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- client.write(Buffer.from(msg.payload,'base64'));
- } else {
- client.write(Buffer.from(""+msg.payload));
- }
- if (node.doend === true) {
- end = true;
- if (client) { node.status({}); client.destroy(); }
- }
- }
- nodeDone();
- });
-
- node.on("close", function(done) {
- node.doneClose = done;
- this.closing = true;
- if (client) { client.destroy(); }
- clearTimeout(reconnectTimeout);
- if (!node.connected) { done(); }
- });
-
- }
- else if (node.beserver == "reply") {
- node.on("input",function(msg, nodeSend, nodeDone) {
- if (msg._session && msg._session.type == "tcp") {
- var client = connectionPool[msg._session.id];
- if (client) {
- if (Buffer.isBuffer(msg.payload)) {
- client.write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- client.write(Buffer.from(msg.payload,'base64'));
- } else {
- client.write(Buffer.from(""+msg.payload));
- }
- }
- }
- else {
- for (var i in connectionPool) {
- if (Buffer.isBuffer(msg.payload)) {
- connectionPool[i].write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- connectionPool[i].write(Buffer.from(msg.payload,'base64'));
- } else {
- connectionPool[i].write(Buffer.from(""+msg.payload));
- }
- }
- }
- nodeDone();
- });
- }
- else {
- var connectedSockets = [];
- node.status({text:RED._("tcpin.status.connections",{count:0})});
- var server = net.createServer(function (socket) {
- socket.setKeepAlive(true,120000);
- if (socketTimeout !== null) { socket.setTimeout(socketTimeout); }
- node.log(RED._("tcpin.status.connection-from",{host:socket.remoteAddress, port:socket.remotePort}));
- socket.on('timeout', function() {
- node.log(RED._("tcpin.errors.timeout",{port:node.port}));
- socket.end();
- });
- socket.on('data', function(d) {
- // console.log("DATA",d)
- });
- socket.on('close',function() {
- node.log(RED._("tcpin.status.connection-closed",{host:socket.remoteAddress, port:socket.remotePort}));
- connectedSockets.splice(connectedSockets.indexOf(socket),1);
- node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})});
- });
- socket.on('error',function() {
- node.log(RED._("tcpin.errors.socket-error",{host:socket.remoteAddress, port:socket.remotePort}));
- connectedSockets.splice(connectedSockets.indexOf(socket),1);
- node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})});
- });
- connectedSockets.push(socket);
- node.status({text:RED._("tcpin.status.connections",{count:connectedSockets.length})});
- });
-
- node.on("input", function(msg, nodeSend, nodeDone) {
- if (msg.payload != null) {
- var buffer;
- if (Buffer.isBuffer(msg.payload)) {
- buffer = msg.payload;
- } else if (typeof msg.payload === "string" && node.base64) {
- buffer = Buffer.from(msg.payload,'base64');
- } else {
- buffer = Buffer.from(""+msg.payload);
- }
- for (var i = 0; i < connectedSockets.length; i += 1) {
- if (node.doend === true) { connectedSockets[i].end(buffer); }
- else { connectedSockets[i].write(buffer); }
- }
- }
- nodeDone();
- });
-
- server.on('error', function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- }
- });
-
- server.listen(node.port, function(err) {
- if (err) {
- node.error(RED._("tcpin.errors.cannot-listen",{port:node.port,error:err.toString()}));
- } else {
- node.log(RED._("tcpin.status.listening-port",{port:node.port}));
- node.on('close', function() {
- for (var c in connectedSockets) {
- if (connectedSockets.hasOwnProperty(c)) {
- connectedSockets[c].end();
- connectedSockets[c].unref();
- }
- }
- server.close();
- node.log(RED._("tcpin.status.stopped-listening",{port:node.port}));
- });
- }
- });
- }
- }
- RED.nodes.registerType("tcp out",TcpOut);
-
-
- function TcpGet(n) {
- RED.nodes.createNode(this,n);
- this.server = n.server;
- this.port = Number(n.port);
- this.out = n.out;
- this.ret = n.ret || "buffer";
- this.splitc = n.splitc;
-
- if (this.out === "immed") { this.splitc = -1; this.out = "time"; }
- if (this.out !== "char") { this.splitc = Number(this.splitc); }
- else {
- if (this.splitc[0] == '\\') {
- this.splitc = parseInt(this.splitc.replace("\\n",0x0A).replace("\\r",0x0D).replace("\\t",0x09).replace("\\e",0x1B).replace("\\f",0x0C).replace("\\0",0x00));
- } // jshint ignore:line
- if (typeof this.splitc == "string") {
- if (this.splitc.substr(0,2) == "0x") {
- this.splitc = parseInt(this.splitc);
- }
- else {
- this.splitc = this.splitc.charCodeAt(0);
- }
- } // jshint ignore:line
- }
-
- var node = this;
-
- var clients = {};
-
- this.on("input", function(msg, nodeSend, nodeDone) {
- var i = 0;
- if ((!Buffer.isBuffer(msg.payload)) && (typeof msg.payload !== "string")) {
- msg.payload = msg.payload.toString();
- }
-
- var host = node.server || msg.host;
- var port = node.port || msg.port;
-
- // Store client information independently
- // the clients object will have:
- // clients[id].client, clients[id].msg, clients[id].timeout
- var connection_id = host + ":" + port;
- if (connection_id !== node.last_id) {
- node.status({});
- node.last_id = connection_id;
- }
- clients[connection_id] = clients[connection_id] || {
- msgQueue: new Denque(),
- connected: false,
- connecting: false
- };
- enqueue(clients[connection_id].msgQueue, {msg:msg, nodeSend:nodeSend, nodeDone:nodeDone});
- clients[connection_id].lastMsg = msg;
-
- if (!clients[connection_id].connecting && !clients[connection_id].connected) {
- var buf;
- if (this.out == "count") {
- if (this.splitc === 0) { buf = Buffer.alloc(1); }
- else { buf = Buffer.alloc(this.splitc); }
- }
- else { buf = Buffer.alloc(65536); } // set it to 64k... hopefully big enough for most TCP packets.... but only hopefully
-
- clients[connection_id].client = net.Socket();
- if (socketTimeout !== null) { clients[connection_id].client.setTimeout(socketTimeout);}
-
- if (host && port) {
- clients[connection_id].connecting = true;
- clients[connection_id].client.connect(port, host, function() {
- //node.log(RED._("tcpin.errors.client-connected"));
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
- if (clients[connection_id] && clients[connection_id].client) {
- clients[connection_id].connected = true;
- clients[connection_id].connecting = false;
- let event;
- while (event = dequeue(clients[connection_id].msgQueue)) {
- clients[connection_id].client.write(event.msg.payload);
- event.nodeDone();
- }
- if (node.out === "time" && node.splitc < 0) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- clients[connection_id].client.end();
- delete clients[connection_id];
- node.status({});
- }
- }
- });
- }
- else {
- node.warn(RED._("tcpin.errors.no-host"));
- }
-
- clients[connection_id].client.on('data', function(data) {
- if (node.out === "sit") { // if we are staying connected just send the buffer
- if (clients[connection_id]) {
- const msg = clients[connection_id].lastMsg || {};
- msg.payload = RED.util.cloneMessage(data);
- if (node.ret === "string") {
- try { msg.payload = msg.payload.toString(); }
- catch(e) { node.error("Failed to create string", msg); }
- }
- nodeSend(msg);
- }
- }
- // else if (node.splitc === 0) {
- // clients[connection_id].msg.payload = data;
- // node.send(clients[connection_id].msg);
- // }
- else {
- for (var j = 0; j < data.length; j++ ) {
- if (node.out === "time") {
- if (clients[connection_id]) {
- // do the timer thing
- if (clients[connection_id].timeout) {
- i += 1;
- buf[i] = data[j];
- }
- else {
- clients[connection_id].timeout = setTimeout(function () {
- if (clients[connection_id]) {
- clients[connection_id].timeout = null;
- const msg = clients[connection_id].lastMsg || {};
- msg.payload = Buffer.alloc(i+1);
- buf.copy(msg.payload,0,0,i+1);
- if (node.ret === "string") {
- try { msg.payload = msg.payload.toString(); }
- catch(e) { node.error("Failed to create string", msg); }
- }
- nodeSend(msg);
- if (clients[connection_id].client) {
- node.status({});
- clients[connection_id].client.destroy();
- delete clients[connection_id];
- }
- }
- }, node.splitc);
- i = 0;
- buf[0] = data[j];
- }
- }
- }
- // count bytes into a buffer...
- else if (node.out == "count") {
- buf[i] = data[j];
- i += 1;
- if ( i >= node.splitc) {
- if (clients[connection_id]) {
- const msg = clients[connection_id].lastMsg || {};
- msg.payload = Buffer.alloc(i);
- buf.copy(msg.payload,0,0,i);
- if (node.ret === "string") {
- try { msg.payload = msg.payload.toString(); }
- catch(e) { node.error("Failed to create string", msg); }
- }
- nodeSend(msg);
- if (clients[connection_id].client) {
- node.status({});
- clients[connection_id].client.destroy();
- delete clients[connection_id];
- }
- i = 0;
- }
- }
- }
- // look for a char
- else {
- buf[i] = data[j];
- i += 1;
- if (data[j] == node.splitc) {
- if (clients[connection_id]) {
- const msg = clients[connection_id].lastMsg || {};
- msg.payload = Buffer.alloc(i);
- buf.copy(msg.payload,0,0,i);
- if (node.ret === "string") {
- try { msg.payload = msg.payload.toString(); }
- catch(e) { node.error("Failed to create string", msg); }
- }
- nodeSend(msg);
- if (clients[connection_id].client) {
- node.status({});
- clients[connection_id].client.destroy();
- delete clients[connection_id];
- }
- i = 0;
- }
- }
- }
- }
- }
- });
-
- clients[connection_id].client.on('end', function() {
- //console.log("END");
- node.status({fill:"grey",shape:"ring",text:"common.status.disconnected"});
- if (clients[connection_id] && clients[connection_id].client) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- clients[connection_id].client = null;
- }
- });
-
- clients[connection_id].client.on('close', function() {
- //console.log("CLOSE");
- if (clients[connection_id]) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- }
-
- var anyConnected = false;
-
- for (var client in clients) {
- if (clients[client].connected) {
- anyConnected = true;
- break;
- }
- }
- if (node.doneClose && !anyConnected) {
- clients = {};
- node.doneClose();
- }
- });
-
- clients[connection_id].client.on('error', function() {
- //console.log("ERROR");
- node.status({fill:"red",shape:"ring",text:"common.status.error"});
- node.error(RED._("tcpin.errors.connect-fail") + " " + connection_id, msg);
- if (clients[connection_id] && clients[connection_id].client) {
- clients[connection_id].client.destroy();
- delete clients[connection_id];
- }
- });
-
- clients[connection_id].client.on('timeout',function() {
- //console.log("TIMEOUT");
- if (clients[connection_id]) {
- clients[connection_id].connected = clients[connection_id].connecting = false;
- node.status({fill:"grey",shape:"dot",text:"tcpin.errors.connect-timeout"});
- //node.warn(RED._("tcpin.errors.connect-timeout"));
- if (clients[connection_id].client) {
- clients[connection_id].connecting = true;
- clients[connection_id].client.connect(port, host, function() {
- clients[connection_id].connected = true;
- clients[connection_id].connecting = false;
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
- });
- }
- }
- });
- }
- else if (!clients[connection_id].connecting && clients[connection_id].connected) {
- if (clients[connection_id] && clients[connection_id].client) {
- let event = dequeue(clients[connection_id].msgQueue)
- clients[connection_id].client.write(event.msg.payload);
- event.nodeDone();
- }
- }
- });
-
- this.on("close", function(done) {
- node.doneClose = done;
- for (var cl in clients) {
- if (clients[cl].hasOwnProperty("client")) {
- clients[cl].client.destroy();
- }
- }
- node.status({});
-
- // this is probably not necessary and may be removed
- var anyConnected = false;
- for (var c in clients) {
- if (clients[c].connected) {
- anyConnected = true;
- break;
- }
- }
- if (!anyConnected) { clients = {}; }
- done();
- });
-
- }
- RED.nodes.registerType("tcp request",TcpGet);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/32-udp.html b/packages/node_modules/@node-red/nodes/core/network/32-udp.html
deleted file mode 100644
index 3a4e241af..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/32-udp.html
+++ /dev/null
@@ -1,231 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/network/32-udp.js b/packages/node_modules/@node-red/nodes/core/network/32-udp.js
deleted file mode 100644
index d42d3a7c3..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/32-udp.js
+++ /dev/null
@@ -1,280 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var os = require('os');
- var dgram = require('dgram');
- var udpInputPortsInUse = {};
-
- // The Input Node
- function UDPin(n) {
- RED.nodes.createNode(this,n);
- this.group = n.group;
- this.port = n.port;
- this.datatype = n.datatype;
- this.iface = n.iface || null;
- this.multicast = n.multicast;
- this.ipv = n.ipv || "udp4";
- var node = this;
-
- if (node.iface && node.iface.indexOf(".") === -1) {
- try {
- if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) {
- if (node.ipv === "udp4") {
- node.iface = (os.networkInterfaces())[node.iface][1].address;
- } else {
- node.iface = (os.networkInterfaces())[node.iface][0].address;
- }
- }
- else {
- if (node.ipv === "udp4") {
- node.iface = (os.networkInterfaces())[node.iface][0].address;
- } else {
- node.iface = (os.networkInterfaces())[node.iface][1].address;
- }
- }
- }
- catch(e) {
- node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface}));
- node.iface = null;
- }
- }
-
- var opts = {type:node.ipv, reuseAddr:true};
- if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; }
- var server;
-
- if (!udpInputPortsInUse.hasOwnProperty(node.port)) {
- server = dgram.createSocket(opts); // default to udp4
- server.bind(node.port, function() {
- if (node.multicast == "true") {
- server.setBroadcast(true);
- server.setMulticastLoopback(false);
- try {
- server.setMulticastTTL(128);
- server.addMembership(node.group,node.iface);
- if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
- node.log(RED._("udp.status.mc-group",{group:node.group}));
- } catch (e) {
- if (e.errno == "EINVAL") {
- node.error(RED._("udp.errors.bad-mcaddress"));
- } else if (e.errno == "ENODEV") {
- node.error(RED._("udp.errors.interface"));
- } else {
- node.error(RED._("udp.errors.error",{error:e.errno}));
- }
- }
- }
- });
- udpInputPortsInUse[node.port] = server;
- }
- else {
- node.log(RED._("udp.errors.alreadyused",{port:node.port}));
- server = udpInputPortsInUse[node.port]; // re-use existing
- if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
- }
-
- server.on("error", function (err) {
- if ((err.code == "EACCES") && (node.port < 1024)) {
- node.error(RED._("udp.errors.access-error"));
- } else {
- node.error(RED._("udp.errors.error",{error:err.code}));
- }
- server.close();
- });
-
- server.on('message', function (message, remote) {
- var msg;
- if (node.datatype =="base64") {
- msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
- } else if (node.datatype =="utf8") {
- msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
- } else {
- msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
- }
- node.send(msg);
- });
-
- server.on('listening', function () {
- var address = server.address();
- node.log(RED._("udp.status.listener-at",{host:node.iface||address.address,port:address.port}));
-
- });
-
- node.on("close", function() {
- try {
- if (node.multicast == "true") { server.dropMembership(node.group); }
- server.close();
- node.log(RED._("udp.status.listener-stopped"));
- } catch (err) {
- //node.error(err);
- }
- if (udpInputPortsInUse.hasOwnProperty(node.port)) {
- delete udpInputPortsInUse[node.port];
- }
- node.status({});
- });
-
- }
- RED.httpAdmin.get('/udp-ports/:id', RED.auth.needsPermission('udp-ports.read'), function(req,res) {
- res.json(Object.keys(udpInputPortsInUse));
- });
- RED.nodes.registerType("udp in",UDPin);
-
-
-
- // The Output Node
- function UDPout(n) {
- RED.nodes.createNode(this,n);
- //this.group = n.group;
- this.port = n.port;
- this.outport = n.outport||"";
- this.base64 = n.base64;
- this.addr = n.addr;
- this.iface = n.iface || null;
- this.multicast = n.multicast;
- this.ipv = n.ipv || "udp4";
- var node = this;
-
- if (node.iface && node.iface.indexOf(".") === -1) {
- try {
- if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) {
- if (node.ipv === "udp4") {
- node.iface = (os.networkInterfaces())[node.iface][1].address;
- } else {
- node.iface = (os.networkInterfaces())[node.iface][0].address;
- }
- }
- else {
- if (node.ipv === "udp4") {
- node.iface = (os.networkInterfaces())[node.iface][0].address;
- } else {
- node.iface = (os.networkInterfaces())[node.iface][1].address;
- }
- }
- }
- catch(e) {
- node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface}));
- node.iface = null;
- }
- }
-
- var opts = {type:node.ipv, reuseAddr:true};
-
- var sock;
- var p = this.outport || this.port || "0";
- node.tout = setTimeout(function() {
- if ((p != 0) && udpInputPortsInUse[p]) {
- sock = udpInputPortsInUse[p];
- if (node.multicast != "false") {
- sock.setBroadcast(true);
- sock.setMulticastLoopback(false);
- }
- node.log(RED._("udp.status.re-use",{outport:node.outport,host:node.addr,port:node.port}));
- if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
- }
- else {
- sock = dgram.createSocket(opts); // default to udp4
- if (node.multicast != "false") {
- sock.bind(node.outport, function() { // have to bind before you can enable broadcast...
- sock.setBroadcast(true); // turn on broadcast
- sock.setMulticastLoopback(false); // turn off loopback
- if (node.multicast == "multi") {
- try {
- sock.setMulticastTTL(128);
- sock.addMembership(node.addr,node.iface); // Add to the multicast group
- if (node.iface) { node.status({text:n.iface+" : "+node.iface}); }
- node.log(RED._("udp.status.mc-ready",{iface:node.iface,outport:node.outport,host:node.addr,port:node.port}));
- } catch (e) {
- if (e.errno == "EINVAL") {
- node.error(RED._("udp.errors.bad-mcaddress"));
- } else if (e.errno == "ENODEV") {
- node.error(RED._("udp.errors.interface"));
- } else {
- node.error(RED._("udp.errors.error",{error:e.errno}));
- }
- }
- } else {
- node.log(RED._("udp.status.bc-ready",{outport:node.outport,host:node.addr,port:node.port}));
- }
- });
- } else if ((node.outport !== "") && (!udpInputPortsInUse[node.outport])) {
- sock.bind(node.outport);
- node.log(RED._("udp.status.ready",{outport:node.outport,host:node.addr,port:node.port}));
- } else {
- node.log(RED._("udp.status.ready-nolocal",{host:node.addr,port:node.port}));
- }
- sock.on("error", function(err) {
- // Any async error will also get reported in the sock.send call.
- // This handler is needed to ensure the error marked as handled to
- // prevent it going to the global error handler and shutting node-red
- // down.
- });
- udpInputPortsInUse[p] = sock;
- }
-
- node.on("input", function(msg, nodeSend, nodeDone) {
- if (msg.hasOwnProperty("payload")) {
- var add = node.addr || msg.ip || "";
- var por = node.port || msg.port || 0;
- if (add === "") {
- node.warn(RED._("udp.errors.ip-notset"));
- nodeDone();
- } else if (por === 0) {
- node.warn(RED._("udp.errors.port-notset"));
- nodeDone();
- } else if (isNaN(por) || (por < 1) || (por > 65535)) {
- node.warn(RED._("udp.errors.port-invalid"));
- nodeDone();
- } else {
- var message;
- if (node.base64) {
- message = Buffer.from(msg.payload, 'base64');
- } else if (msg.payload instanceof Buffer) {
- message = msg.payload;
- } else {
- message = Buffer.from(""+msg.payload);
- }
- sock.send(message, 0, message.length, por, add, function(err, bytes) {
- if (err) {
- node.error("udp : "+err,msg);
- }
- message = null;
- nodeDone();
- });
- }
- }
- });
- }, 75);
-
- node.on("close", function() {
- if (node.tout) { clearTimeout(node.tout); }
- try {
- if (node.multicast == "multi") { sock.dropMembership(node.group); }
- sock.close();
- node.log(RED._("udp.status.output-stopped"));
- } catch (err) {
- //node.error(err);
- }
- if (udpInputPortsInUse.hasOwnProperty(p)) {
- delete udpInputPortsInUse[p];
- }
- node.status({});
- });
- }
- RED.nodes.registerType("udp out",UDPout);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/network/lib/mqtt.js b/packages/node_modules/@node-red/nodes/core/network/lib/mqtt.js
deleted file mode 100644
index c472f01e9..000000000
--- a/packages/node_modules/@node-red/nodes/core/network/lib/mqtt.js
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var util = require("util");
-var mqtt = require("mqtt");
-var events = require("events");
-
-util.log("[warn] nodes/core/io/lib/mqtt.js is deprecated and will be removed in a future release of Node-RED. Please report this usage to the Node-RED mailing list.");
-
-//var inspect = require("util").inspect;
-
-//var Client = module.exports.Client = function(
-
-var port = 1883;
-var host = "localhost";
-
-function MQTTClient(port,host) {
- this.port = port||1883;
- this.host = host||"localhost";
- this.messageId = 1;
- this.pendingSubscriptions = {};
- this.inboundMessages = {};
- this.lastOutbound = (new Date()).getTime();
- this.lastInbound = (new Date()).getTime();
- this.connected = false;
-
- this._nextMessageId = function() {
- this.messageId += 1;
- if (this.messageId > 0xFFFF) {
- this.messageId = 1;
- }
- return this.messageId;
- }
- events.EventEmitter.call(this);
-}
-util.inherits(MQTTClient, events.EventEmitter);
-
-MQTTClient.prototype.connect = function(options) {
- if (!this.connected) {
- var self = this;
- options = options||{};
- self.options = options;
- self.options.keepalive = options.keepalive||15;
- self.options.clean = self.options.clean||true;
- self.options.protocolId = 'MQIsdp';
- self.options.protocolVersion = 3;
-
- self.client = mqtt.createConnection(this.port,this.host,function(err,client) {
- if (err) {
- self.connected = false;
- clearInterval(self.watchdog);
- self.connectionError = true;
- //util.log('[mqtt] ['+self.uid+'] connection error 1 : '+inspect(err));
- self.emit('connectionlost',err);
- return;
- }
- client.on('close',function(e) {
- //util.log('[mqtt] ['+self.uid+'] on close');
- clearInterval(self.watchdog);
- if (!self.connectionError) {
- if (self.connected) {
- self.connected = false;
- self.emit('connectionlost',e);
- } else {
- self.emit('disconnect');
- }
- }
- });
- client.on('error',function(e) {
- //util.log('[mqtt] ['+self.uid+'] on error : '+inspect(e));
- clearInterval(self.watchdog);
- if (self.connected) {
- self.connected = false;
- self.emit('connectionlost',e);
- }
- });
- client.on('connack',function(packet) {
- if (packet.returnCode === 0) {
- self.watchdog = setInterval(function(self) {
- var now = (new Date()).getTime();
-
- //util.log('[mqtt] ['+self.uid+'] watchdog '+inspect({connected:self.connected,connectionError:self.connectionError,pingOutstanding:self.pingOutstanding,now:now,lastOutbound:self.lastOutbound,lastInbound:self.lastInbound}));
-
- if (now - self.lastOutbound > self.options.keepalive*500 || now - self.lastInbound > self.options.keepalive*500) {
- if (self.pingOutstanding) {
- //util.log('[mqtt] ['+self.uid+'] watchdog pingOustanding - disconnect');
- try {
- self.client.disconnect();
- } catch (err) {
- }
- } else {
- //util.log('[mqtt] ['+self.uid+'] watchdog pinging');
- self.lastOutbound = (new Date()).getTime();
- self.lastInbound = (new Date()).getTime();
- self.pingOutstanding = true;
- self.client.pingreq();
- }
- }
-
- },self.options.keepalive*500,self);
- self.pingOutstanding = false;
- self.lastInbound = (new Date()).getTime()
- self.lastOutbound = (new Date()).getTime()
- self.connected = true;
- self.connectionError = false;
- self.emit('connect');
- } else {
- self.connected = false;
- self.emit('connectionlost');
- }
- });
- client.on('suback',function(packet) {
- self.lastInbound = (new Date()).getTime()
- var topic = self.pendingSubscriptions[packet.messageId];
- self.emit('subscribe',topic,packet.granted[0]);
- delete self.pendingSubscriptions[packet.messageId];
- });
- client.on('unsuback',function(packet) {
- self.lastInbound = (new Date()).getTime()
- var topic = self.pendingSubscriptions[packet.messageId];
- self.emit('unsubscribe',topic);
- delete self.pendingSubscriptions[packet.messageId];
- });
- client.on('publish',function(packet) {
- self.lastInbound = (new Date()).getTime();
- if (packet.qos < 2) {
- var p = packet;
- self.emit('message',p.topic,p.payload,p.qos,p.retain);
- } else {
- self.inboundMessages[packet.messageId] = packet;
- this.lastOutbound = (new Date()).getTime()
- self.client.pubrec(packet);
- }
- if (packet.qos == 1) {
- this.lastOutbound = (new Date()).getTime()
- self.client.puback(packet);
- }
- });
-
- client.on('pubrel',function(packet) {
- self.lastInbound = (new Date()).getTime()
- var p = self.inboundMessages[packet.messageId];
- if (p) {
- self.emit('message',p.topic,p.payload,p.qos,p.retain);
- delete self.inboundMessages[packet.messageId];
- }
- self.lastOutbound = (new Date()).getTime()
- self.client.pubcomp(packet);
- });
-
- client.on('puback',function(packet) {
- self.lastInbound = (new Date()).getTime()
- // outbound qos-1 complete
- });
-
- client.on('pubrec',function(packet) {
- self.lastInbound = (new Date()).getTime()
- self.lastOutbound = (new Date()).getTime()
- self.client.pubrel(packet);
- });
- client.on('pubcomp',function(packet) {
- self.lastInbound = (new Date()).getTime()
- // outbound qos-2 complete
- });
- client.on('pingresp',function(packet) {
- //util.log('[mqtt] ['+self.uid+'] received pingresp');
- self.lastInbound = (new Date()).getTime()
- self.pingOutstanding = false;
- });
-
- this.lastOutbound = (new Date()).getTime()
- this.connectionError = false;
- client.connect(self.options);
- });
- }
-}
-
-MQTTClient.prototype.subscribe = function(topic,qos) {
- var self = this;
- if (self.connected) {
- var options = {
- subscriptions:[{topic:topic,qos:qos}],
- messageId: self._nextMessageId()
- };
- this.pendingSubscriptions[options.messageId] = topic;
- this.lastOutbound = (new Date()).getTime();
- self.client.subscribe(options);
- self.client.setPacketEncoding('binary');
- }
-}
-MQTTClient.prototype.unsubscribe = function(topic) {
- var self = this;
- if (self.connected) {
- var options = {
- unsubscriptions:[topic],
- messageId: self._nextMessageId()
- };
- this.pendingSubscriptions[options.messageId] = topic;
- this.lastOutbound = (new Date()).getTime()
- self.client.unsubscribe(options);
- }
-}
-
-MQTTClient.prototype.publish = function(topic,payload,qos,retain) {
- var self = this;
- if (self.connected) {
-
- if (!Buffer.isBuffer(payload)) {
- if (typeof payload === "object") {
- payload = JSON.stringify(payload);
- } else if (typeof payload !== "string") {
- payload = ""+payload;
- }
- }
- var options = {
- topic: topic,
- payload: payload,
- qos: qos||0,
- retain:retain||false
- };
- if (options.qos !== 0) {
- options.messageId = self._nextMessageId();
- }
- this.lastOutbound = (new Date()).getTime()
- self.client.publish(options);
- }
-}
-
-MQTTClient.prototype.disconnect = function() {
- var self = this;
- if (this.connected) {
- this.connected = false;
- try {
- this.client.disconnect();
- } catch(err) {
- }
- }
-}
-MQTTClient.prototype.isConnected = function() {
- return this.connected;
-}
-module.exports.createClient = function(port,host) {
- var mqtt_client = new MQTTClient(port,host);
- return mqtt_client;
-}
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.html b/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.html
deleted file mode 100644
index 80778ac1b..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.html
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js b/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js
deleted file mode 100644
index 184f40bdd..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-CSV.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- function CSVNode(n) {
- RED.nodes.createNode(this,n);
- this.template = (n.temp || "");
- this.sep = (n.sep || ',').replace("\\t","\t").replace("\\n","\n").replace("\\r","\r");
- this.quo = '"';
- this.ret = (n.ret || "\n").replace("\\n","\n").replace("\\r","\r");
- this.winflag = (this.ret === "\r\n");
- this.lineend = "\n";
- this.multi = n.multi || "one";
- this.hdrin = n.hdrin || false;
- this.hdrout = n.hdrout || "none";
- this.goodtmpl = true;
- this.skip = parseInt(n.skip || 0);
- this.store = [];
- this.parsestrings = n.strings;
- this.include_empty_strings = n.include_empty_strings || false;
- this.include_null_values = n.include_null_values || false;
- if (this.parsestrings === undefined) { this.parsestrings = true; }
- if (this.hdrout === false) { this.hdrout = "none"; }
- if (this.hdrout === true) { this.hdrout = "all"; }
- var tmpwarn = true;
- var node = this;
- var re = new RegExp(node.sep.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g,'\\$&') + '(?=(?:(?:[^"]*"){2})*[^"]*$)','g');
-
- // pass in an array of column names to be trimmed, de-quoted and retrimmed
- var clean = function(col,sep) {
- if (sep) { re = new RegExp(sep.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g,'\\$&') +'(?=(?:(?:[^"]*"){2})*[^"]*$)','g'); }
- col = col.trim().split(re) || [""];
- col = col.map(x => x.replace(/"/g,'').trim());
- if ((col.length === 1) && (col[0] === "")) { node.goodtmpl = false; }
- else { node.goodtmpl = true; }
- return col;
- }
- var template = clean(node.template,',');
- var notemplate = template.length === 1 && template[0] === '';
- node.hdrSent = false;
-
- this.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("reset")) {
- node.hdrSent = false;
- }
- if (msg.hasOwnProperty("payload")) {
- if (typeof msg.payload == "object") { // convert object to CSV string
- try {
- if (!(notemplate && (msg.hasOwnProperty("parts") && msg.parts.hasOwnProperty("index") && msg.parts.index > 0))) {
- template = clean(node.template);
- }
- var ou = "";
- if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
- if (node.hdrout !== "none" && node.hdrSent === false) {
- if ((template.length === 1) && (template[0] === '')) {
- if (msg.hasOwnProperty("columns")) {
- template = clean(msg.columns || "",",");
- }
- else {
- template = Object.keys(msg.payload[0]);
- }
- }
- ou += template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep) + node.ret;
- if (node.hdrout === "once") { node.hdrSent = true; }
- }
- for (var s = 0; s < msg.payload.length; s++) {
- if ((Array.isArray(msg.payload[s])) || (typeof msg.payload[s] !== "object")) {
- if (typeof msg.payload[s] !== "object") { msg.payload = [ msg.payload ]; }
- for (var t = 0; t < msg.payload[s].length; t++) {
- if (msg.payload[s][t] === undefined) { msg.payload[s][t] = ""; }
- if (msg.payload[s][t].toString().indexOf(node.quo) !== -1) { // add double quotes if any quotes
- msg.payload[s][t] = msg.payload[s][t].toString().replace(/"/g, '""');
- msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
- }
- else if (msg.payload[s][t].toString().indexOf(node.sep) !== -1) { // add quotes if any "commas"
- msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
- }
- }
- ou += msg.payload[s].join(node.sep) + node.ret;
- }
- else {
- if ((template.length === 1) && (template[0] === '') && (msg.hasOwnProperty("columns"))) {
- template = clean(msg.columns || "",",");
- }
- if ((template.length === 1) && (template[0] === '')) {
- /* istanbul ignore else */
- if (tmpwarn === true) { // just warn about missing template once
- node.warn(RED._("csv.errors.obj_csv"));
- tmpwarn = false;
- }
- for (var p in msg.payload[0]) {
- /* istanbul ignore else */
- if (msg.payload[s].hasOwnProperty(p)) {
- /* istanbul ignore else */
- if (typeof msg.payload[s][p] !== "object") {
- var q = "" + msg.payload[s][p];
- if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
- q = q.replace(/"/g, '""');
- ou += node.quo + q + node.quo + node.sep;
- }
- else if (q.indexOf(node.sep) !== -1) { // add quotes if any "commas"
- ou += node.quo + q + node.quo + node.sep;
- }
- else { ou += q + node.sep; } // otherwise just add
- }
- }
- }
- ou = ou.slice(0,-1) + node.ret;
- }
- else {
- for (var t=0; t < template.length; t++) {
- if (template[t] === '') {
- ou += node.sep;
- }
- else {
- var p = RED.util.ensureString(RED.util.getMessageProperty(msg,"payload["+s+"]['"+template[t]+"']"));
- /* istanbul ignore else */
- if (p === "undefined") { p = ""; }
- if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
- p = p.replace(/"/g, '""');
- ou += node.quo + p + node.quo + node.sep;
- }
- else if (p.indexOf(node.sep) !== -1) { // add quotes if any "commas"
- ou += node.quo + p + node.quo + node.sep;
- }
- else { ou += p + node.sep; } // otherwise just add
- }
- }
- ou = ou.slice(0,-1) + node.ret; // remove final "comma" and add "newline"
- }
- }
- }
- msg.payload = ou;
- msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
- if (msg.payload !== '') { send(msg); }
- done();
- }
- catch(e) { done(e); }
- }
- else if (typeof msg.payload == "string") { // convert CSV string to object
- try {
- var f = true; // flag to indicate if inside or outside a pair of quotes true = outside.
- var j = 0; // pointer into array of template items
- var k = [""]; // array of data for each of the template items
- var o = {}; // output object to build up
- var a = []; // output array is needed for multiline option
- var first = true; // is this the first line
- var last = false;
- var line = msg.payload;
- var linecount = 0;
- var tmp = "";
- var has_parts = msg.hasOwnProperty("parts");
- var reg = /^[-]?(?!E)(?!0\d)\d*\.?\d*(E-?\+?)?\d+$/i;
- if (msg.hasOwnProperty("parts")) {
- linecount = msg.parts.index;
- if (msg.parts.index > node.skip) { first = false; }
- if (msg.parts.hasOwnProperty("count") && (msg.parts.index+1 >= msg.parts.count)) { last = true; }
- }
-
- // For now we are just going to assume that any \r or \n means an end of line...
- // got to be a weird csv that has singleton \r \n in it for another reason...
-
- // Now process the whole file/line
- var nocr = (line.match(/[\r\n]/g)||[]).length;
- if (has_parts && node.multi === "mult" && nocr > 1) { tmp = ""; first = true; }
- for (var i = 0; i < line.length; i++) {
- if (first && (linecount < node.skip)) {
- if (line[i] === "\n") { linecount += 1; }
- continue;
- }
- if ((node.hdrin === true) && first) { // if the template is in the first line
- if ((line[i] === "\n")||(line[i] === "\r")||(line.length - i === 1)) { // look for first line break
- if (line.length - i === 1) { tmp += line[i]; }
- template = clean(tmp,node.sep);
- first = false;
- }
- else { tmp += line[i]; }
- }
- else {
- if (line[i] === node.quo) { // if it's a quote toggle inside or outside
- f = !f;
- if (line[i-1] === node.quo) {
- if (f === false) { k[j] += '\"'; }
- } // if it's a quotequote then it's actually a quote
- //if ((line[i-1] !== node.sep) && (line[i+1] !== node.sep)) { k[j] += line[i]; }
- }
- else if ((line[i] === node.sep) && f) { // if it is the end of the line then finish
- if (!node.goodtmpl) { template[j] = "col"+(j+1); }
- if ( template[j] && (template[j] !== "") ) {
- // if no value between separators ('1,,"3"...') or if the line beings with separator (',1,"2"...') treat value as null
- if (line[i-1] === node.sep || line[i-1].includes('\n','\r')) k[j] = null;
- if ( (k[j] !== null && node.parsestrings === true) && reg.test(k[j].trim()) ) { k[j] = parseFloat(k[j].trim()); }
- if (node.include_null_values && k[j] === null) o[template[j]] = k[j];
- if (node.include_empty_strings && k[j] === "") o[template[j]] = k[j];
- if (k[j] !== null && k[j] !== "") o[template[j]] = k[j];
- }
- j += 1;
- // if separator is last char in processing string line (without end of line), add null value at the end - example: '1,2,3\n3,"3",'
- k[j] = line.length - 1 === i ? null : "";
- }
- else if (((line[i] === "\n") || (line[i] === "\r")) && f) { // handle multiple lines
- //console.log(j,k,o,k[j]);
- if (!node.goodtmpl) { template[j] = "col"+(j+1); }
- if ( template[j] && (template[j] !== "") ) {
- // if separator before end of line, set null value ie. '1,2,"3"\n1,2,\n1,2,3'
- if (line[i-1] === node.sep) k[j] = null;
- if ( (k[j] !== null && node.parsestrings === true) && reg.test(k[j].trim()) ) { k[j] = parseFloat(k[j].trim()); }
- else { if (k[j] !== null) k[j].replace(/\r$/,''); }
- if (node.include_null_values && k[j] === null) o[template[j]] = k[j];
- if (node.include_empty_strings && k[j] === "") o[template[j]] = k[j];
- if (k[j] !== null && k[j] !== "") o[template[j]] = k[j];
- }
- if (JSON.stringify(o) !== "{}") { // don't send empty objects
- a.push(o); // add to the array
- }
- j = 0;
- k = [""];
- o = {};
- f = true; // reset in/out flag ready for next line.
- }
- else { // just add to the part of the message
- k[j] += line[i];
- }
- }
- }
- // Finished so finalize and send anything left
- if (f === false) { node.warn(RED._("csv.errors.bad_csv")); }
- if (!node.goodtmpl) { template[j] = "col"+(j+1); }
-
- if ( template[j] && (template[j] !== "") ) {
- if ( (k[j] !== null && node.parsestrings === true) && reg.test(k[j].trim()) ) { k[j] = parseFloat(k[j].trim()); }
- else { if (k[j] !== null) k[j].replace(/\r$/,''); }
- if (node.include_null_values && k[j] === null) o[template[j]] = k[j];
- if (node.include_empty_strings && k[j] === "") o[template[j]] = k[j];
- if (k[j] !== null && k[j] !== "") o[template[j]] = k[j];
- }
-
- if (JSON.stringify(o) !== "{}") { // don't send empty objects
- a.push(o); // add to the array
- }
-
- if (node.multi !== "one") {
- msg.payload = a;
- if (has_parts && nocr <= 1) {
- if (JSON.stringify(o) !== "{}") {
- node.store.push(o);
- }
- if (msg.parts.index + 1 === msg.parts.count) {
- msg.payload = node.store;
- msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
- delete msg.parts;
- send(msg);
- node.store = [];
- }
- }
- else {
- msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
- send(msg); // finally send the array
- }
- }
- else {
- var len = a.length;
- for (var i = 0; i < len; i++) {
- var newMessage = RED.util.cloneMessage(msg);
- newMessage.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).filter(v => v).join(',');
- newMessage.payload = a[i];
- if (!has_parts) {
- newMessage.parts = {
- id: msg._msgid,
- index: i,
- count: len
- };
- }
- else {
- newMessage.parts.index -= node.skip;
- newMessage.parts.count -= node.skip;
- if (node.hdrin) { // if we removed the header line then shift the counts by 1
- newMessage.parts.index -= 1;
- newMessage.parts.count -= 1;
- }
- }
- if (last) { newMessage.complete = true; }
- send(newMessage);
- }
- if (has_parts && last && len === 0) {
- send({complete:true});
- }
- }
- node.linecount = 0;
- done();
- }
- catch(e) { done(e); }
- }
- else { node.warn(RED._("csv.errors.csv_js")); done(); }
- }
- else {
- if (!msg.hasOwnProperty("reset")) {
- node.send(msg); // If no payload and not reset - just pass it on.
- }
- done();
- }
- });
- }
- RED.nodes.registerType("csv",CSVNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-HTML.html b/packages/node_modules/@node-red/nodes/core/parsers/70-HTML.html
deleted file mode 100644
index 4509dd054..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-HTML.html
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-HTML.js b/packages/node_modules/@node-red/nodes/core/parsers/70-HTML.js
deleted file mode 100644
index 073b98689..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-HTML.js
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var cheerio = require('cheerio');
-
- function CheerioNode(n) {
- RED.nodes.createNode(this,n);
- this.property = n.property||"payload";
- this.outproperty = n.outproperty||this.property||"payload";
- this.tag = n.tag;
- this.ret = n.ret || "html";
- this.as = n.as || "single";
- var node = this;
- this.on("input", function(msg,send,done) {
- var value = RED.util.getMessageProperty(msg,node.property);
- if (value !== undefined) {
- var tag = node.tag;
- if (msg.hasOwnProperty("select")) { tag = node.tag || msg.select; }
- try {
- var $ = cheerio.load(value);
- var pay = [];
- var count = 0;
- $(tag).each(function() {
- count++;
- });
- var index = 0;
- $(tag).each(function() {
- if (node.as === "multi") {
- var pay2 = null;
- if (node.ret === "html") { pay2 = cheerio.load($(this).html().trim(),null,false).xml(); }
- if (node.ret === "text") { pay2 = $(this).text(); }
- if (node.ret === "attr") {
- pay2 = Object.assign({},this.attribs);
- }
- //if (node.ret === "val") { pay2 = $(this).val(); }
- /* istanbul ignore else */
- if (pay2) {
- var new_msg = RED.util.cloneMessage(msg);
- RED.util.setMessageProperty(new_msg,node.outproperty,pay2);
- new_msg.parts = {
- id: msg._msgid,
- index: index,
- count: count,
- type: "string",
- ch: ""
- };
- send(new_msg);
- }
- }
- if (node.as === "single") {
- if (node.ret === "html") { pay.push( cheerio.load($(this).html().trim(),null,false).xml() ); }
- if (node.ret === "text") { pay.push( $(this).text() ); }
- if (node.ret === "attr") {
- var attribs = Object.assign({},this.attribs);
- pay.push( attribs );
- }
- //if (node.ret === "val") { pay.push( $(this).val() ); }
- }
- index++;
- });
- if (node.as === "single") { // Always return an array - even if blank
- RED.util.setMessageProperty(msg,node.outproperty,pay);
- send(msg);
- }
- done();
- }
- catch (error) {
- done(error.message);
- }
- }
- else { send(msg); done(); } // If no payload - just pass it on.
- });
- }
- RED.nodes.registerType("html",CheerioNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.html b/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.html
deleted file mode 100644
index 6599cf0e0..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.js b/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.js
deleted file mode 100644
index a68edc681..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-JSON.js
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- const Ajv = require('ajv');
- const ajv = new Ajv({allErrors: true});
- ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'));
-
- function JSONNode(n) {
- RED.nodes.createNode(this,n);
- this.indent = n.pretty ? 4 : 0;
- this.action = n.action||"";
- this.property = n.property||"payload";
- this.schema = null;
- this.compiledSchema = null;
-
- var node = this;
-
- this.on("input", function(msg,send,done) {
- var validate = false;
- if (msg.schema) {
- // If input schema is different, re-compile it
- if (JSON.stringify(this.schema) != JSON.stringify(msg.schema)) {
- try {
- this.compiledSchema = ajv.compile(msg.schema);
- this.schema = msg.schema;
- } catch(e) {
- this.schema = null;
- this.compiledSchema = null;
- done(RED._("json.errors.schema-error-compile"));
- return;
- }
- }
- validate = true;
- }
- var value = RED.util.getMessageProperty(msg,node.property);
- if (value !== undefined) {
- if (typeof value === "string") {
- if (node.action === "" || node.action === "obj") {
- try {
- RED.util.setMessageProperty(msg,node.property,JSON.parse(value));
- if (validate) {
- if (this.compiledSchema(msg[node.property])) {
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- send(msg);
- done();
- }
- }
- catch(e) { done(e.message); }
- } else {
- // If node.action is str and value is str
- if (validate) {
- if (this.compiledSchema(JSON.parse(msg[node.property]))) {
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- send(msg);
- done();
- }
- }
- }
- else if ((typeof value === "object") || (typeof value === "boolean") || (typeof value === "number")) {
- if (node.action === "" || node.action === "str") {
- if (!Buffer.isBuffer(value)) {
- try {
- if (validate) {
- if (this.compiledSchema(value)) {
- RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- RED.util.setMessageProperty(msg,node.property,JSON.stringify(value,null,node.indent));
- send(msg);
- done();
- }
- }
- catch(e) { done(RED._("json.errors.dropped-error")); }
- }
- else { node.warn(RED._("json.errors.dropped-object")); done(); }
- } else {
- // If node.action is obj and value is object
- if (validate) {
- if (this.compiledSchema(value)) {
- delete msg.schema;
- send(msg);
- done();
- } else {
- msg.schemaError = this.compiledSchema.errors;
- done(`${RED._("json.errors.schema-error")}: ${ajv.errorsText(this.compiledSchema.errors)}`);
- }
- } else {
- send(msg);
- done();
- }
- }
- }
- else { node.warn(RED._("json.errors.dropped")); done(); }
- }
- else { send(msg); done(); } // If no property - just pass it on.
- });
- }
- RED.nodes.registerType("json",JSONNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-XML.html b/packages/node_modules/@node-red/nodes/core/parsers/70-XML.html
deleted file mode 100644
index 642fe4d04..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-XML.html
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-XML.js b/packages/node_modules/@node-red/nodes/core/parsers/70-XML.js
deleted file mode 100644
index a778c4d72..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-XML.js
+++ /dev/null
@@ -1,49 +0,0 @@
-
-module.exports = function(RED) {
- "use strict";
- var xml2js = require('xml2js');
- var parseString = xml2js.parseString;
-
- function XMLNode(n) {
- RED.nodes.createNode(this,n);
- this.attrkey = n.attr;
- this.charkey = n.chr;
- this.property = n.property||"payload";
- var node = this;
- this.on("input", function(msg,send,done) {
- var value = RED.util.getMessageProperty(msg,node.property);
- if (value !== undefined) {
- var options;
- if (typeof value === "object") {
- options = {renderOpts:{pretty:false}};
- if (msg.hasOwnProperty("options") && typeof msg.options === "object") { options = msg.options; }
- options.async = false;
- var builder = new xml2js.Builder(options);
- value = builder.buildObject(value, options);
- RED.util.setMessageProperty(msg,node.property,value);
- send(msg);
- done();
- }
- else if (typeof value == "string") {
- options = {};
- if (msg.hasOwnProperty("options") && typeof msg.options === "object") { options = msg.options; }
- options.async = true;
- options.attrkey = node.attrkey || options.attrkey || '$';
- options.charkey = node.charkey || options.charkey || '_';
- parseString(value, options, function (err, result) {
- if (err) { done(err); }
- else {
- value = result;
- RED.util.setMessageProperty(msg,node.property,value);
- send(msg);
- done();
- }
- });
- }
- else { node.warn(RED._("xml.errors.xml_js")); done(); }
- }
- else { send(msg); done(); } // If no property - just pass it on.
- });
- }
- RED.nodes.registerType("xml",XMLNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-YAML.html b/packages/node_modules/@node-red/nodes/core/parsers/70-YAML.html
deleted file mode 100644
index deaf47d95..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-YAML.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/parsers/70-YAML.js b/packages/node_modules/@node-red/nodes/core/parsers/70-YAML.js
deleted file mode 100644
index 69a6bf444..000000000
--- a/packages/node_modules/@node-red/nodes/core/parsers/70-YAML.js
+++ /dev/null
@@ -1,41 +0,0 @@
-
-module.exports = function(RED) {
- "use strict";
- var yaml = require('js-yaml');
- function YAMLNode(n) {
- RED.nodes.createNode(this,n);
- this.property = n.property||"payload";
- var node = this;
- this.on("input", function(msg,send,done) {
- var value = RED.util.getMessageProperty(msg,node.property);
- if (value !== undefined) {
- if (typeof value === "string") {
- try {
- value = yaml.load(value);
- RED.util.setMessageProperty(msg,node.property,value);
- send(msg);
- done();
- }
- catch(e) { done(e.message); }
- }
- else if (typeof value === "object") {
- if (!Buffer.isBuffer(value)) {
- try {
- value = yaml.dump(value);
- RED.util.setMessageProperty(msg,node.property,value);
- send(msg);
- done();
- }
- catch(e) {
- done(RED._("yaml.errors.dropped-error"));
- }
- }
- else { node.warn(RED._("yaml.errors.dropped-object")); done(); }
- }
- else { node.warn(RED._("yaml.errors.dropped")); done(); }
- }
- else { send(msg); done(); } // If no payload - just pass it on.
- });
- }
- RED.nodes.registerType("yaml",YAMLNode);
-};
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/17-split.html b/packages/node_modules/@node-red/nodes/core/sequence/17-split.html
deleted file mode 100644
index 265719d1e..000000000
--- a/packages/node_modules/@node-red/nodes/core/sequence/17-split.html
+++ /dev/null
@@ -1,325 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/17-split.js b/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
deleted file mode 100644
index e158f344c..000000000
--- a/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
+++ /dev/null
@@ -1,785 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- function sendArray(node,msg,array,send) {
- for (var i = 0; i < array.length-1; i++) {
- msg.payload = array[i];
- msg.parts.index = node.c++;
- if (node.stream !== true) { msg.parts.count = array.length; }
- send(RED.util.cloneMessage(msg));
- }
- if (node.stream !== true) {
- msg.payload = array[i];
- msg.parts.index = node.c++;
- msg.parts.count = array.length;
- send(RED.util.cloneMessage(msg));
- node.c = 0;
- }
- else { node.remainder = array[i]; }
- }
-
- function SplitNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- node.stream = n.stream;
- node.spltType = n.spltType || "str";
- node.addname = n.addname || "";
- try {
- if (node.spltType === "str") {
- this.splt = (n.splt || "\\n").replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g,"\t").replace(/\\e/g,"\e").replace(/\\f/g,"\f").replace(/\\0/g,"\0");
- } else if (node.spltType === "bin") {
- var spltArray = JSON.parse(n.splt);
- if (Array.isArray(spltArray)) {
- this.splt = Buffer.from(spltArray);
- } else {
- throw new Error("not an array");
- }
- this.spltBuffer = spltArray;
- } else if (node.spltType === "len") {
- this.splt = parseInt(n.splt);
- if (isNaN(this.splt) || this.splt < 1) {
- throw new Error("invalid split length: "+n.splt);
- }
- }
- this.arraySplt = (n.arraySplt === undefined)?1:parseInt(n.arraySplt);
- if (isNaN(this.arraySplt) || this.arraySplt < 1) {
- throw new Error("invalid array split length: "+n.arraySplt);
- }
- } catch(err) {
- this.error("Invalid split property: "+err.toString());
- return;
- }
- node.c = 0;
- node.buffer = Buffer.from([]);
- node.pendingDones = [];
- this.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("payload")) {
- if (msg.hasOwnProperty("parts")) { msg.parts = { parts:msg.parts }; } // push existing parts to a stack
- else { msg.parts = {}; }
- msg.parts.id = RED.util.generateId(); // generate a random id
- delete msg._msgid;
- if (typeof msg.payload === "string") { // Split String into array
- msg.payload = (node.remainder || "") + msg.payload;
- msg.parts.type = "string";
- if (node.spltType === "len") {
- msg.parts.ch = "";
- msg.parts.len = node.splt;
- var count = msg.payload.length/node.splt;
- if (Math.floor(count) !== count) {
- count = Math.ceil(count);
- }
- if (node.stream !== true) {
- msg.parts.count = count;
- node.c = 0;
- }
- var pos = 0;
- var data = msg.payload;
- for (var i=0; i 1) {
- node.pendingDones.forEach(d => d());
- node.pendingDones = [];
- }
- node.remainder = data.substring(pos);
- if ((node.stream !== true) || (node.remainder.length === node.splt)) {
- msg.payload = node.remainder;
- msg.parts.index = node.c++;
- send(RED.util.cloneMessage(msg));
- node.pendingDones.forEach(d => d());
- node.pendingDones = [];
- done();
- node.remainder = "";
- } else {
- node.pendingDones.push(done);
- }
- }
- else {
- var a = [];
- if (node.spltType === "bin") {
- if (!node.spltBufferString) {
- node.spltBufferString = node.splt.toString();
- }
- a = msg.payload.split(node.spltBufferString);
- msg.parts.ch = node.spltBuffer; // pass the split char to other end for rejoin
- } else if (node.spltType === "str") {
- a = msg.payload.split(node.splt);
- msg.parts.ch = node.splt; // pass the split char to other end for rejoin
- }
- sendArray(node,msg,a,send);
- done();
- }
- }
- else if (Array.isArray(msg.payload)) { // then split array into messages
- msg.parts.type = "array";
- var count = msg.payload.length/node.arraySplt;
- if (Math.floor(count) !== count) {
- count = Math.ceil(count);
- }
- msg.parts.count = count;
- var pos = 0;
- var data = msg.payload;
- msg.parts.len = node.arraySplt;
- for (var i=0; i 1) {
- node.pendingDones.forEach(d => d());
- node.pendingDones = [];
- }
- node.buffer = buff.slice(pos);
- if ((node.stream !== true) || (node.buffer.length === node.splt)) {
- msg.payload = node.buffer;
- msg.parts.index = node.c++;
- send(RED.util.cloneMessage(msg));
- node.pendingDones.forEach(d => d());
- node.pendingDones = [];
- done();
- node.buffer = Buffer.from([]);
- } else {
- node.pendingDones.push(done);
- }
- }
- else {
- var count = 0;
- if (node.spltType === "bin") {
- msg.parts.ch = node.spltBuffer;
- } else if (node.spltType === "str") {
- msg.parts.ch = node.splt;
- }
- var pos = buff.indexOf(node.splt);
- var end;
- while (pos > -1) {
- count++;
- end = pos+node.splt.length;
- pos = buff.indexOf(node.splt,end);
- }
- count++;
- if (node.stream !== true) {
- msg.parts.count = count;
- node.c = 0;
- }
- var i = 0, p = 0;
- pos = buff.indexOf(node.splt);
- while (pos > -1) {
- msg.payload = buff.slice(p,pos);
- msg.parts.index = node.c++;
- send(RED.util.cloneMessage(msg));
- i++;
- p = pos+node.splt.length;
- pos = buff.indexOf(node.splt,p);
- }
- if (count > 1) {
- node.pendingDones.forEach(d => d());
- node.pendingDones = [];
- }
- if ((node.stream !== true) && (p < buff.length)) {
- msg.payload = buff.slice(p,buff.length);
- msg.parts.index = node.c++;
- msg.parts.count = node.c++;
- send(RED.util.cloneMessage(msg));
- node.pendingDones.forEach(d => d());
- node.pendingDones = [];
- }
- else {
- node.buffer = buff.slice(p,buff.length);
- node.pendingDones.push(done);
- }
- if (node.buffer.length == 0) {
- done();
- }
- }
- } else { // otherwise drop the message.
- done();
- }
- }
- });
- }
- RED.nodes.registerType("split",SplitNode);
-
-
- var _maxKeptMsgsCount;
-
- function maxKeptMsgsCount(node) {
- if (_maxKeptMsgsCount === undefined) {
- var name = "nodeMessageBufferMaxLength";
- if (RED.settings.hasOwnProperty(name)) {
- _maxKeptMsgsCount = RED.settings[name];
- }
- else {
- _maxKeptMsgsCount = 0;
- }
- }
- return _maxKeptMsgsCount;
- }
-
- function applyReduce(exp, accum, msg, index, count, done) {
- exp.assign("I", index);
- exp.assign("N", count);
- exp.assign("A", accum);
- RED.util.evaluateJSONataExpression(exp, msg, done);
- }
-
- function exp_or_undefined(exp) {
- if((exp === "") ||
- (exp === null)) {
- return undefined;
- }
- return exp
- }
-
-
- function reduceMessageGroup(node,msgInfos,exp,fixup,count,accumulator,done) {
- var msgInfo = msgInfos.shift();
- exp.assign("I", msgInfo.msg.parts.index);
- exp.assign("N", count);
- exp.assign("A", accumulator);
- RED.util.evaluateJSONataExpression(exp, msgInfo.msg, (err,result) => {
- if (err) {
- return done(err);
- }
- if (msgInfos.length === 0) {
- if (fixup) {
- fixup.assign("N", count);
- fixup.assign("A", result);
- RED.util.evaluateJSONataExpression(fixup, {}, (err, result) => {
- if (err) {
- return done(err);
- }
- msgInfo.send({payload: result});
- done();
- });
- } else {
- msgInfo.send({payload: result});
- done();
- }
- } else {
- reduceMessageGroup(node,msgInfos,exp,fixup,count,result,done);
- }
- });
- }
- function reduceAndSendGroup(node, group, done) {
- var is_right = node.reduce_right;
- var flag = is_right ? -1 : 1;
- var msgInfos = group.msgs;
- const preservedMsgInfos = [...msgInfos];
- try {
- RED.util.evaluateNodeProperty(node.exp_init, node.exp_init_type, node, {}, (err,accum) => {
- var reduceExpression = node.reduceExpression;
- var fixupExpression = node.fixupExpression;
- var count = group.count;
- msgInfos.sort(function(x,y) {
- var ix = x.msg.parts.index;
- var iy = y.msg.parts.index;
- if (ix < iy) {return -flag;}
- if (ix > iy) {return flag;}
- return 0;
- });
- reduceMessageGroup(node, msgInfos,reduceExpression,fixupExpression,count,accum,(err,result) => {
- if (err) {
- preservedMsgInfos.pop(); // omit last message to emit error message
- preservedMsgInfos.forEach(mInfo => mInfo.done());
- done(err);
- return;
- } else {
- preservedMsgInfos.forEach(mInfo => mInfo.done());
- done();
- }
- })
- });
- } catch(err) {
- done(new Error(RED._("join.errors.invalid-expr",{error:err.message})));
- }
- }
-
- function reduceMessage(node, msgInfo, done) {
- let msg = msgInfo.msg;
- if (msg.hasOwnProperty('parts')) {
- var parts = msg.parts;
- var pending = node.pending;
- var pending_count = node.pending_count;
- var gid = msg.parts.id;
- var count;
- if (!pending.hasOwnProperty(gid)) {
- if(parts.hasOwnProperty('count')) {
- count = msg.parts.count;
- }
- pending[gid] = {
- count: count,
- msgs: []
- };
- }
- var group = pending[gid];
- var msgs = group.msgs;
- if (parts.hasOwnProperty('count') && (group.count === undefined)) {
- group.count = parts.count;
- }
- msgs.push(msgInfo);
- pending_count++;
- var completeProcess = function(err) {
- if (err) {
- return done(err);
- }
- node.pending_count = pending_count;
- var max_msgs = maxKeptMsgsCount(node);
- if ((max_msgs > 0) && (pending_count > max_msgs)) {
- Object.values(node.pending).forEach(group => {
- group.msgs.forEach(mInfo => {
- if (mInfo.msg._msgid !== msgInfo.msg._msgid) {
- mInfo.done();
- }
- });
- });
- node.pending = {};
- node.pending_count = 0;
- done(RED._("join.too-many"));
- return;
- }
- return done();
- }
- if (msgs.length === group.count) {
- delete pending[gid];
- pending_count -= msgs.length;
- reduceAndSendGroup(node, group, completeProcess)
- } else {
- completeProcess();
- }
- } else {
- msgInfo.send(msg);
- msgInfo.done();
- done();
- }
- }
-
- function JoinNode(n) {
- RED.nodes.createNode(this,n);
- this.mode = n.mode||"auto";
- this.property = n.property||"payload";
- this.propertyType = n.propertyType||"msg";
- if (this.propertyType === 'full') {
- this.property = "payload";
- }
- this.key = n.key||"topic";
- this.timer = (this.mode === "auto") ? 0 : Number(n.timeout || 0)*1000;
- this.count = Number(n.count || 0);
- this.joiner = n.joiner||"";
- this.joinerType = n.joinerType||"str";
-
- this.reduce = (this.mode === "reduce");
- if (this.reduce) {
- this.exp_init = n.reduceInit;
- this.exp_init_type = n.reduceInitType;
- var exp_reduce = n.reduceExp;
- var exp_fixup = exp_or_undefined(n.reduceFixup);
- this.reduce_right = n.reduceRight;
- try {
- this.reduceExpression = RED.util.prepareJSONataExpression(exp_reduce, this);
- this.fixupExpression = (exp_fixup !== undefined) ? RED.util.prepareJSONataExpression(exp_fixup, this) : undefined;
- } catch(e) {
- this.error(RED._("join.errors.invalid-expr",{error:e.message}));
- return;
- }
- }
-
- if (this.joinerType === "str") {
- this.joiner = this.joiner.replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g,"\t").replace(/\\e/g,"\e").replace(/\\f/g,"\f").replace(/\\0/g,"\0");
- } else if (this.joinerType === "bin") {
- var joinArray = JSON.parse(n.joiner || "[]");
- if (Array.isArray(joinArray)) {
- this.joiner = Buffer.from(joinArray);
- } else {
- throw new Error("not an array");
- }
- }
-
- this.build = n.build || "array";
- this.accumulate = n.accumulate || "false";
-
- this.output = n.output || "stream";
- this.pending = {};
- this.pending_count = 0;
-
- //this.topic = n.topic;
- var node = this;
- var inflight = {};
-
- var completeSend = function(partId) {
- var group = inflight[partId];
- if (group.timeout) { clearTimeout(group.timeout); }
- if ((node.accumulate !== true) || group.msg.hasOwnProperty("complete")) { delete inflight[partId]; }
- if (group.type === 'array' && group.arrayLen > 1) {
- var newArray = [];
- group.payload.forEach(function(n) {
- newArray = newArray.concat(n);
- })
- group.payload = newArray;
- }
- else if (group.type === 'buffer') {
- var buffers = [];
- var bufferLen = 0;
- if (group.joinChar !== undefined) {
- var joinBuffer = Buffer.from(group.joinChar);
- for (var i=0; i 0) {
- buffers.push(joinBuffer);
- bufferLen += joinBuffer.length;
- }
- if (!Buffer.isBuffer(group.payload[i])) {
- group.payload[i] = Buffer.from(group.payload[i]);
- }
- buffers.push(group.payload[i]);
- bufferLen += group.payload[i].length;
- }
- }
- else {
- bufferLen = group.bufferLen;
- buffers = group.payload;
- }
- group.payload = Buffer.concat(buffers,bufferLen);
- }
-
- if (group.type === 'string') {
- var groupJoinChar = group.joinChar;
- if (typeof group.joinChar !== 'string') {
- groupJoinChar = group.joinChar.toString();
- }
- RED.util.setMessageProperty(group.msg,node.property,group.payload.join(groupJoinChar));
- }
- else {
- if (node.propertyType === 'full') {
- group.msg = RED.util.cloneMessage(group.msg);
- }
- RED.util.setMessageProperty(group.msg,node.property,group.payload);
- }
- if (group.msg.hasOwnProperty('parts') && group.msg.parts.hasOwnProperty('parts')) {
- group.msg.parts = group.msg.parts.parts;
- }
- else {
- delete group.msg.parts;
- }
- delete group.msg.complete;
- group.send(RED.util.cloneMessage(group.msg));
- group.dones.forEach(f => f());
- group.dones = [];
- }
-
- var pendingMessages = [];
- var activeMessage = null;
- // In reduce mode, we must process messages fully in order otherwise
- // groups may overlap and cause unexpected results. The use of JSONata
- // means some async processing *might* occur if flow/global context is
- // accessed.
- var processReduceMessageQueue = function(msgInfo) {
- if (msgInfo) {
- // A new message has arrived - add it to the message queue
- pendingMessages.push(msgInfo);
- if (activeMessage !== null) {
- // The node is currently processing a message, so do nothing
- // more with this message
- return;
- }
- }
- if (pendingMessages.length === 0) {
- // There are no more messages to process, clear the active flag
- // and return
- activeMessage = null;
- return;
- }
-
- // There are more messages to process. Get the next message and
- // start processing it. Recurse back in to check for any more
- var nextMsgInfo = pendingMessages.shift();
- activeMessage = true;
- reduceMessage(node, nextMsgInfo, err => {
- if (err) {
- nextMsgInfo.done(err);//.error(err,nextMsg);
- }
- activeMessage = null;
- processReduceMessageQueue();
- })
- }
-
- this.on("input", function(msg, send, done) {
- try {
- var property;
- var partId = "_";
- if (node.propertyType == "full") {
- property = msg;
- }
- else {
- try {
- property = RED.util.getMessageProperty(msg,node.property);
- } catch(err) {
- node.warn("Message property "+node.property+" not found");
- done();
- return;
- }
- }
-
- if (node.mode === 'auto' && (!msg.hasOwnProperty("parts")||!msg.parts.hasOwnProperty("id"))) {
- // if a blank reset messag erest it all.
- if (msg.hasOwnProperty("reset")) {
- if (inflight && inflight.hasOwnProperty("partId") && inflight[partId].timeout) {
- clearTimeout(inflight[partId].timeout);
- }
- inflight = {};
- }
- else {
- node.warn("Message missing msg.parts property - cannot join in 'auto' mode")
- }
- done();
- return;
- }
-
- var payloadType;
- var propertyKey;
- var targetCount;
- var joinChar;
- var arrayLen;
- var propertyIndex;
- if (node.mode === "auto") {
- // Use msg.parts to identify all of the group information
- partId = msg.parts.id;
- payloadType = msg.parts.type;
- targetCount = msg.parts.count;
- joinChar = msg.parts.ch;
- propertyKey = msg.parts.key;
- arrayLen = msg.parts.len;
- propertyIndex = msg.parts.index;
- }
- else if (node.mode === 'reduce') {
- return processReduceMessageQueue({msg, send, done});
- }
- else {
- // Use the node configuration to identify all of the group information
- payloadType = node.build;
- targetCount = node.count;
- joinChar = node.joiner;
- if (n.count === "" && msg.hasOwnProperty('parts')) {
- targetCount = msg.parts.count || 0;
- }
- if (node.build === 'object') {
- propertyKey = RED.util.getMessageProperty(msg,node.key);
- }
- }
-
- if (msg.hasOwnProperty("restartTimeout")) {
- if (inflight[partId]) {
- if (inflight[partId].timeout) {
- clearTimeout(inflight[partId].timeout);
- }
- if (node.timer > 0) {
- inflight[partId].timeout = setTimeout(function() {
- completeSend(partId)
- }, node.timer)
- }
- }
- }
-
- if (msg.hasOwnProperty("reset")) {
- if (inflight[partId]) {
- if (inflight[partId].timeout) {
- clearTimeout(inflight[partId].timeout);
- }
- inflight[partId].dones.forEach(f => f());
- delete inflight[partId]
- }
- done();
- return;
- }
-
- if ((payloadType === 'object') && (propertyKey === null || propertyKey === undefined || propertyKey === "")) {
- if (node.mode === "auto") {
- node.warn("Message missing 'msg.parts.key' property - cannot add to object");
- }
- else {
- if (msg.hasOwnProperty('complete')) {
- if (inflight[partId]) {
- inflight[partId].msg.complete = msg.complete;
- inflight[partId].send = send;
- completeSend(partId);
- }
- }
- else {
- node.warn("Message missing key property 'msg."+node.key+"' - cannot add to object")
- }
- }
- done();
- return;
- }
-
- if (!inflight.hasOwnProperty(partId)) {
- if (payloadType === 'object' || payloadType === 'merged') {
- inflight[partId] = {
- currentCount:0,
- payload:{},
- targetCount:targetCount,
- type:"object",
- msg:RED.util.cloneMessage(msg),
- send: send,
- dones: []
- };
- }
- else {
- inflight[partId] = {
- currentCount:0,
- payload:[],
- targetCount:targetCount,
- type:payloadType,
- msg:RED.util.cloneMessage(msg),
- send: send,
- dones: []
- };
- if (payloadType === 'string') {
- inflight[partId].joinChar = joinChar;
- } else if (payloadType === 'array') {
- inflight[partId].arrayLen = arrayLen;
- } else if (payloadType === 'buffer') {
- inflight[partId].bufferLen = 0;
- inflight[partId].joinChar = joinChar;
- }
- }
- if (node.timer > 0) {
- inflight[partId].timeout = setTimeout(function() {
- completeSend(partId)
- }, node.timer)
- }
- }
- inflight[partId].dones.push(done);
-
- var group = inflight[partId];
- if (payloadType === 'buffer') {
- if (property !== undefined) {
- if (Buffer.isBuffer(property) || (typeof property === "string") || Array.isArray(property)) {
- inflight[partId].bufferLen += property.length;
- }
- else {
- done(RED._("join.errors.invalid-type",{error:(typeof property)}));
- return;
- }
- }
- }
- if (payloadType === 'object') {
- group.payload[propertyKey] = property;
- group.currentCount = Object.keys(group.payload).length;
- } else if (payloadType === 'merged') {
- if (Array.isArray(property) || typeof property !== 'object') {
- if (!msg.hasOwnProperty("complete")) {
- node.warn("Cannot merge non-object types");
- }
- } else {
- for (propertyKey in property) {
- if (property.hasOwnProperty(propertyKey) && propertyKey !== '_msgid') {
- group.payload[propertyKey] = property[propertyKey];
- }
- }
- group.currentCount = Object.keys(group.payload).length;
- //group.currentCount++;
- }
- } else {
- if (!isNaN(propertyIndex)) {
- if (group.payload[propertyIndex] == undefined) { group.currentCount++; }
- group.payload[propertyIndex] = property;
- } else {
- if (property !== undefined) {
- group.payload.push(property);
- group.currentCount++;
- }
- }
- }
- group.msg = Object.assign(group.msg, msg);
- group.send = send;
- var tcnt = group.targetCount;
- if (msg.hasOwnProperty("parts")) {
- tcnt = group.targetCount || msg.parts.count;
- group.targetCount = tcnt;
- }
- if ((tcnt > 0 && group.currentCount >= tcnt) || msg.hasOwnProperty('complete')) {
- completeSend(partId);
- }
- }
- catch(err) {
- done(err);
- console.log(err.stack);
- }
- });
-
- this.on("close", function() {
- for (var i in inflight) {
- if (inflight.hasOwnProperty(i)) {
- clearTimeout(inflight[i].timeout);
- inflight[i].dones.forEach(d => d());
- }
- }
- });
- }
- RED.nodes.registerType("join",JoinNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/18-sort.html b/packages/node_modules/@node-red/nodes/core/sequence/18-sort.html
deleted file mode 100644
index fd27c8b54..000000000
--- a/packages/node_modules/@node-red/nodes/core/sequence/18-sort.html
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/18-sort.js b/packages/node_modules/@node-red/nodes/core/sequence/18-sort.js
deleted file mode 100644
index 3bcdfb105..000000000
--- a/packages/node_modules/@node-red/nodes/core/sequence/18-sort.js
+++ /dev/null
@@ -1,266 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- var _max_kept_msgs_count;
-
- function max_kept_msgs_count(node) {
- if (_max_kept_msgs_count === undefined) {
- var name = "nodeMessageBufferMaxLength";
- if (RED.settings.hasOwnProperty(name)) {
- _max_kept_msgs_count = RED.settings[name];
- }
- else {
- _max_kept_msgs_count = 0;
- }
- }
- return _max_kept_msgs_count;
- }
-
- // function get_context_val(node, name, dval) {
- // var context = node.context();
- // var val = context.get(name);
- // if (val === undefined) {
- // context.set(name, dval);
- // return dval;
- // }
- // return val;
- // }
-
- function SortNode(n) {
- RED.nodes.createNode(this, n);
- var node = this;
- var pending = {};//get_context_val(node, 'pending', {})
- var pending_count = 0;
- var pending_id = 0;
- var order = n.order || "ascending";
- var as_num = n.as_num || false;
- var target_prop = n.target || "payload";
- var target_is_prop = (n.targetType === 'msg');
- var key_is_exp = target_is_prop ? (n.msgKeyType === "jsonata") : (n.seqKeyType === "jsonata");
- var key_prop = n.seqKey || "payload";
- var key_exp = target_is_prop ? n.msgKey : n.seqKey;
-
- if (key_is_exp) {
- try {
- key_exp = RED.util.prepareJSONataExpression(key_exp, this);
- }
- catch (e) {
- node.error(RED._("sort.invalid-exp",{message:e.toString()}));
- return;
- }
- }
- var dir = (order === "ascending") ? 1 : -1;
- var conv = as_num ? function(x) { return Number(x); }
- : function(x) { return x; };
-
- function generateComparisonFunction(key) {
- return function(x, y) {
- var xp = conv(key(x));
- var yp = conv(key(y));
- if (xp === yp) { return 0; }
- if (xp > yp) { return dir; }
- return -dir;
- };
- }
-
- function sortMessageGroup(group) {
- var promise;
- var msgInfos = group.msgInfos;
- if (key_is_exp) {
- var evaluatedDataPromises = msgInfos.map(mInfo => {
- return new Promise((resolve,reject) => {
- RED.util.evaluateJSONataExpression(key_exp, mInfo.msg, (err, result) => {
- if (err) {
- reject(RED._("sort.invalid-exp",{message:err.toString()}));
- } else {
- resolve({
- item: mInfo,
- sortValue: result
- })
- }
- });
- })
- });
- promise = Promise.all(evaluatedDataPromises).then(evaluatedElements => {
- // Once all of the sort keys are evaluated, sort by them
- var comp = generateComparisonFunction(elem=>elem.sortValue);
- return evaluatedElements.sort(comp).map(elem=>elem.item);
- });
- } else {
- var key = function(msg) {
- return ;
- }
- var comp = generateComparisonFunction(mInfo => RED.util.getMessageProperty(mInfo.msg, key_prop));
- try {
- msgInfos.sort(comp);
- }
- catch (e) {
- return; // not send when error
- }
- promise = Promise.resolve(msgInfos);
- }
- return promise.then(msgInfos => {
- for (let i = 0; i < msgInfos.length; i++) {
- const msg = msgInfos[i].msg;
- msg.parts.index = i;
- msgInfos[i].send(msg);
- msgInfos[i].done();
- }
- });
- }
-
- function sortMessageProperty(msg) {
- var data = RED.util.getMessageProperty(msg, target_prop);
- if (Array.isArray(data)) {
- if (key_is_exp) {
- // key is an expression. Evaluated the expression for each item
- // to get its sort value. As this could be async, need to do
- // it first.
- var evaluatedDataPromises = data.map(elem => {
- return new Promise((resolve,reject) => {
- RED.util.evaluateJSONataExpression(key_exp, elem, (err, result) => {
- if (err) {
- reject(RED._("sort.invalid-exp",{message:err.toString()}));
- } else {
- resolve({
- item: elem,
- sortValue: result
- })
- }
- });
- })
- })
- return Promise.all(evaluatedDataPromises).then(evaluatedElements => {
- // Once all of the sort keys are evaluated, sort by them
- // and reconstruct the original message item with the newly
- // sorted values.
- var comp = generateComparisonFunction(elem=>elem.sortValue);
- data = evaluatedElements.sort(comp).map(elem=>elem.item);
- RED.util.setMessageProperty(msg, target_prop,data);
- return true;
- })
- } else {
- var comp = generateComparisonFunction(elem=>elem);
- try {
- data.sort(comp);
- } catch (e) {
- return Promise.resolve(false);
- }
- return Promise.resolve(true);
- }
- }
- return Promise.resolve(false);
- }
-
- function removeOldestPending() {
- var oldest;
- var oldest_key;
- for(var key in pending) {
- if (pending.hasOwnProperty(key)) {
- var item = pending[key];
- if((oldest === undefined) ||
- (oldest.seq_no > item.seq_no)) {
- oldest = item;
- oldest_key = key;
- }
- }
- }
- if(oldest !== undefined) {
- oldest.msgInfos[oldest.msgInfos.length - 1].done(RED._("sort.too-many"));
- for (let i = 0; i < oldest.msgInfos.length - 1; i++) {
- oldest.msgInfos[i].done();
- }
- delete pending[oldest_key];
- return oldest.msgInfos.length;
- }
- return 0;
- }
-
- function processMessage(msgInfo) {
- const msg = msgInfo.msg;
- if (target_is_prop) {
- sortMessageProperty(msg).then(send => {
- if (send) {
- msgInfo.send(msg);
- }
- msgInfo.done();
- }).catch(err => {
- msgInfo.done(err);
- });
- return;
- }
- var parts = msg.parts;
- if (!parts || !parts.hasOwnProperty("id") || !parts.hasOwnProperty("index")) {
- msgInfo.done();
- return;
- }
- var gid = parts.id;
- if (!pending.hasOwnProperty(gid)) {
- pending[gid] = {
- count: undefined,
- msgInfos: [],
- seq_no: pending_id++
- };
- }
- var group = pending[gid];
- var msgInfos = group.msgInfos;
- msgInfos.push(msgInfo);
- if (parts.hasOwnProperty("count")) {
- group.count = parts.count;
- }
- pending_count++;
- if (group.count === msgInfos.length) {
- delete pending[gid]
- sortMessageGroup(group).catch(err => {
- // throw an error for last message, and just call done() for remaining messages
- msgInfos[msgInfos.length-1].done(err);
- for (let i = 0; i < msgInfos.length - 1; i++) {
- msgInfos[i].done()
- };
- });
- pending_count -= msgInfos.length;
- } else {
- var max_msgs = max_kept_msgs_count(node);
- if ((max_msgs > 0) && (pending_count > max_msgs)) {
- pending_count -= removeOldestPending();
- }
- }
- }
-
- this.on("input", function(msg, send, done) {
- processMessage({msg, send, done});
- });
-
- this.on("close", function() {
- for(var key in pending) {
- if (pending.hasOwnProperty(key)) {
- node.log(RED._("sort.clear"), pending[key].msgInfos[0]);
- const group = pending[key];
- group.msgInfos.forEach(mInfo => {
- mInfo.done();
- });
- delete pending[key];
- }
- }
- pending_count = 0;
- });
- }
-
- RED.nodes.registerType("sort", SortNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.html b/packages/node_modules/@node-red/nodes/core/sequence/19-batch.html
deleted file mode 100644
index 418ac605b..000000000
--- a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.html
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.js b/packages/node_modules/@node-red/nodes/core/sequence/19-batch.js
deleted file mode 100644
index f3f29df6a..000000000
--- a/packages/node_modules/@node-red/nodes/core/sequence/19-batch.js
+++ /dev/null
@@ -1,311 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
-
- var _max_kept_msgs_count = undefined;
-
- function max_kept_msgs_count(node) {
- if (_max_kept_msgs_count === undefined) {
- var name = "nodeMessageBufferMaxLength";
- if (RED.settings.hasOwnProperty(name)) {
- _max_kept_msgs_count = RED.settings[name];
- }
- else {
- _max_kept_msgs_count = 0;
- }
- }
- return _max_kept_msgs_count;
- }
-
- function send_msgs(node, msgInfos, clone_msg) {
- var count = msgInfos.length;
- var msg_id = msgInfos[0].msg._msgid;
- for (var i = 0; i < count; i++) {
- var msg = clone_msg ? RED.util.cloneMessage(msgInfos[i].msg) : msgInfos[i].msg;
- if (!msg.hasOwnProperty("parts")) {
- msg.parts = {};
- }
- var parts = msg.parts;
- parts.id = msg_id;
- parts.index = i;
- parts.count = count;
- msgInfos[i].send(msg);
- //msgInfos[i].done();
- }
- }
-
- function send_interval(node, allow_empty_seq) {
- let msgInfos = node.pending;
- if (msgInfos.length > 0) {
- send_msgs(node, msgInfos, false);
- msgInfos.forEach(e => e.done());
- node.pending = [];
- }
- else {
- if (allow_empty_seq) {
- let mid = RED.util.generateId();
- let msg = {
- payload: null,
- parts: {
- id: mid,
- index: 0,
- count: 1
- }
- };
- node.send(msg);
- }
- }
- }
-
- function is_complete(pending, topic) {
- if (pending.hasOwnProperty(topic)) {
- var p_topic = pending[topic];
- var gids = p_topic.gids;
- if (gids.length > 0) {
- var gid = gids[0];
- var groups = p_topic.groups;
- var group = groups[gid];
- return (group.count === group.msgs.length);
- }
- }
- return false;
- }
-
- function get_msgs_of_topic(pending, topic) {
- var p_topic = pending[topic];
- var groups = p_topic.groups;
- var gids = p_topic.gids;
- var gid = gids[0];
- var group = groups[gid];
- return group.msgs;
- }
-
- function remove_topic(pending, topic) {
- var p_topic = pending[topic];
- var groups = p_topic.groups;
- var gids = p_topic.gids;
- var gid = gids.shift();
- delete groups[gid];
- }
-
- function try_concat(node, pending) {
- var topics = node.topics;
- for (var topic of topics) {
- if (!is_complete(pending, topic)) {
- return;
- }
- }
- var msgInfos = [];
- for (var topic of topics) {
- var t_msgInfos = get_msgs_of_topic(pending, topic);
- msgInfos = msgInfos.concat(t_msgInfos);
- }
- for (var topic of topics) {
- remove_topic(pending, topic);
- }
- send_msgs(node, msgInfos, true);
- msgInfos.forEach(e => e.done() );
- node.pending_count -= msgInfos.length;
- }
-
- function add_to_topic_group(pending, topic, gid, msgInfo) {
- if (!pending.hasOwnProperty(topic)) {
- pending[topic] = { groups: {}, gids: [] };
- }
- var p_topic = pending[topic];
- var groups = p_topic.groups;
- var gids = p_topic.gids;
- if (!groups.hasOwnProperty(gid)) {
- groups[gid] = { msgs: [], count: undefined };
- gids.push(gid);
- }
- var group = groups[gid];
- group.msgs.push(msgInfo);
- if ((group.count === undefined) &&
- msgInfo.msg.parts.hasOwnProperty('count')) {
- group.count = msgInfo.msg.parts.count;
- }
- }
-
- function concat_msg(node, msg, send, done) {
- var topic = msg.topic;
- if(node.topics.indexOf(topic) >= 0) {
- if (!msg.hasOwnProperty("parts") ||
- !msg.parts.hasOwnProperty("id") ||
- !msg.parts.hasOwnProperty("index") ||
- !msg.parts.hasOwnProperty("count")) {
- done(RED._("batch.no-parts"));
- return;
- }
- var gid = msg.parts.id;
- var pending = node.pending;
- add_to_topic_group(pending, topic, gid, {msg, send, done});
- node.pending_count++;
- var max_msgs = max_kept_msgs_count(node);
- if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
- Object.values(node.pending).forEach(p_topic => {
- Object.values(p_topic.groups).forEach(group => {
- group.msgs.forEach(msgInfo => {
- if (msgInfo.msg.id === msg.id) {
- // the message that caused the overflow
- msgInfo.done(RED._("batch.too-many"));
- } else {
- msgInfo.done();
- }
- })
- })
- });
- node.pending = {};
- node.pending_count = 0;
- }
- try_concat(node, pending);
- }
- }
-
- function BatchNode(n) {
- RED.nodes.createNode(this,n);
- var node = this;
- var mode = n.mode || "count";
-
- node.pending_count = 0;
- if (mode === "count") {
- var count = Number(n.count || 1);
- var overlap = Number(n.overlap || 0);
- var is_overlap = (overlap > 0);
- if (count <= overlap) {
- node.error(RED._("batch.count.invalid"));
- return;
- }
- node.pending = [];
- this.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("reset")) {
- node.pending.forEach(e => e.done());
- node.pending = [];
- node.pending_count = 0;
- done();
- return;
- }
- var queue = node.pending;
- queue.push({msg, send, done});
- node.pending_count++;
- if (queue.length === count) {
- send_msgs(node, queue, is_overlap);
- for (let i = 0; i < queue.length-overlap; i++) {
- queue[i].done();
- }
- node.pending =
- (overlap === 0) ? [] : queue.slice(-overlap);
- node.pending_count = 0;
- }
- var max_msgs = max_kept_msgs_count(node);
- if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
- let lastMInfo = node.pending.pop();
- lastMInfo.done(RED._("batch.too-many"));
- node.pending.forEach(e => e.done());
- node.pending = [];
- node.pending_count = 0;
- }
- });
- this.on("close", function() {
- node.pending.forEach(e=> e.done());
- node.pending_count = 0;
- node.pending = [];
- });
- }
- else if (mode === "interval") {
- var interval = Number(n.interval || "0") *1000;
- var allow_empty_seq = n.allowEmptySequence;
- node.pending = []
- function msgHandler() {
- send_interval(node, allow_empty_seq);
- node.pending_count = 0;
- }
- var timer = undefined;
- if (interval > 0) {
- timer = setInterval(msgHandler, interval);
- }
- this.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("reset")) {
- if (timer !== undefined) {
- clearInterval(timer);
- }
- node.pending.forEach(e => e.done());
- node.pending = [];
- node.pending_count = 0;
- done();
- if (interval > 0) {
- timer = setInterval(msgHandler, interval);
- }
- return;
- }
- node.pending.push({msg, send, done});
- node.pending_count++;
- var max_msgs = max_kept_msgs_count(node);
- if ((max_msgs > 0) && (node.pending_count > max_msgs)) {
- let lastMInfo = node.pending.pop();
- lastMInfo.done(RED._("batch.too-many"));
- node.pending.forEach(e => e.done());
- node.pending = [];
- node.pending_count = 0;
- }
- });
- this.on("close", function() {
- if (timer !== undefined) {
- clearInterval(timer);
- }
- node.pending.forEach(e => e.done());
- node.pending = [];
- node.pending_count = 0;
- });
- }
- else if(mode === "concat") {
- node.topics = (n.topics || []).map(function(x) {
- return x.topic;
- });
- node.pending = {};
- this.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("reset")) {
- Object.values(node.pending).forEach(p_topic => {
- Object.values(p_topic.groups).forEach(group => {
- group.msgs.forEach(e => e.done());
- });
- });
- node.pending = {};
- node.pending_count = 0;
- done();
- return;
- }
- concat_msg(node, msg, send, done);
- });
- this.on("close", function() {
- Object.values(node.pending).forEach(p_topic => {
- Object.values(p_topic.groups).forEach(group => {
- group.msgs.forEach(e => e.done());
- });
- });
- node.pending = {};
- node.pending_count = 0;
- });
- }
- else {
- node.error(RED._("batch.unexpected"));
- }
- }
-
- RED.nodes.registerType("batch", BatchNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.html b/packages/node_modules/@node-red/nodes/core/storage/10-file.html
deleted file mode 100755
index b76a01615..000000000
--- a/packages/node_modules/@node-red/nodes/core/storage/10-file.html
+++ /dev/null
@@ -1,347 +0,0 @@
-
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.js b/packages/node_modules/@node-red/nodes/core/storage/10-file.js
deleted file mode 100644
index 079b4e82f..000000000
--- a/packages/node_modules/@node-red/nodes/core/storage/10-file.js
+++ /dev/null
@@ -1,401 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var fs = require("fs-extra");
- var os = require("os");
- var path = require("path");
- var iconv = require("iconv-lite")
-
- function encode(data, enc) {
- if (enc !== "none") {
- return iconv.encode(data, enc);
- }
- return Buffer.from(data);
- }
-
- function decode(data, enc) {
- if (enc !== "none") {
- return iconv.decode(data, enc);
- }
- return data.toString();
- }
-
- function FileNode(n) {
- // Write/delete a file
- RED.nodes.createNode(this,n);
- this.filename = n.filename;
- this.appendNewline = n.appendNewline;
- this.overwriteFile = n.overwriteFile.toString();
- this.createDir = n.createDir || false;
- this.encoding = n.encoding || "none";
- var node = this;
- node.wstream = null;
- node.msgQueue = [];
- node.closing = false;
- node.closeCallback = null;
-
- function processMsg(msg,nodeSend, done) {
- var filename = node.filename || msg.filename || "";
- var fullFilename = filename;
- if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
- fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
- }
- if ((!node.filename) && (!node.tout)) {
- node.tout = setTimeout(function() {
- node.status({fill:"grey",shape:"dot",text:filename});
- clearTimeout(node.tout);
- node.tout = null;
- },333);
- }
- if (filename === "") {
- node.warn(RED._("file.errors.nofilename"));
- done();
- } else if (node.overwriteFile === "delete") {
- fs.unlink(fullFilename, function (err) {
- if (err) {
- node.error(RED._("file.errors.deletefail",{error:err.toString()}),msg);
- }
- else {
- if (RED.settings.verbose) {
- node.log(RED._("file.status.deletedfile",{file:filename}));
- }
- nodeSend(msg);
- }
- done();
- });
- } else if (msg.hasOwnProperty("payload") && (typeof msg.payload !== "undefined")) {
- var dir = path.dirname(fullFilename);
- if (node.createDir) {
- try {
- fs.ensureDirSync(dir);
- }
- catch(err) {
- node.error(RED._("file.errors.createfail",{error:err.toString()}),msg);
- done();
- return;
- }
- }
-
- var data = msg.payload;
- if ((typeof data === "object") && (!Buffer.isBuffer(data))) {
- data = JSON.stringify(data);
- }
- if (typeof data === "boolean") { data = data.toString(); }
- if (typeof data === "number") { data = data.toString(); }
- if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; }
- var buf;
- if (node.encoding === "setbymsg") {
- buf = encode(data, msg.encoding || "none");
- }
- else { buf = encode(data, node.encoding); }
- if (node.overwriteFile === "true") {
- var wstream = fs.createWriteStream(fullFilename, { encoding:'binary', flags:'w', autoClose:true });
- node.wstream = wstream;
- wstream.on("error", function(err) {
- node.error(RED._("file.errors.writefail",{error:err.toString()}),msg);
- done();
- });
- wstream.on("open", function() {
- wstream.once("close", function() {
- nodeSend(msg);
- done();
- });
- wstream.end(buf);
- })
- return;
- }
- else {
- // Append mode
- var recreateStream = !node.wstream || !node.filename;
- if (node.wstream && node.wstreamIno) {
- // There is already a stream open and we have the inode
- // of the file. Check the file hasn't been deleted
- // or deleted and recreated.
- try {
- var stat = fs.statSync(fullFilename);
- // File exists - check the inode matches
- if (stat.ino !== node.wstreamIno) {
- // The file has been recreated. Close the current
- // stream and recreate it
- recreateStream = true;
- node.wstream.end();
- delete node.wstream;
- delete node.wstreamIno;
- }
- }
- catch(err) {
- // File does not exist
- recreateStream = true;
- node.wstream.end();
- delete node.wstream;
- delete node.wstreamIno;
- }
- }
- if (recreateStream) {
- node.wstream = fs.createWriteStream(fullFilename, { encoding:'binary', flags:'a', autoClose:true });
- node.wstream.on("open", function(fd) {
- try {
- var stat = fs.statSync(fullFilename);
- node.wstreamIno = stat.ino;
- } catch(err) {
- }
- });
- node.wstream.on("error", function(err) {
- node.error(RED._("file.errors.appendfail",{error:err.toString()}),msg);
- done();
- });
- }
- if (node.filename) {
- // Static filename - write and reuse the stream next time
- node.wstream.write(buf, function() {
- nodeSend(msg);
- done();
- });
- }
- else {
- // Dynamic filename - write and close the stream
- node.wstream.once("close", function() {
- nodeSend(msg);
- delete node.wstream;
- delete node.wstreamIno;
- done();
- });
- node.wstream.end(buf);
- }
- }
- }
- else {
- done();
- }
- }
-
- function processQueue(queue) {
- var event = queue[0];
- processMsg(event.msg, event.send, function() {
- event.done();
- queue.shift();
- if (queue.length > 0) {
- processQueue(queue);
- }
- else if (node.closing) {
- closeNode();
- }
- });
- }
-
- this.on("input", function(msg,nodeSend,nodeDone) {
- var msgQueue = node.msgQueue;
- msgQueue.push({
- msg: msg,
- send: nodeSend,
- done: nodeDone
- })
- if (msgQueue.length > 1) {
- // pending write exists
- return;
- }
- try {
- processQueue(msgQueue);
- }
- catch (e) {
- node.msgQueue = [];
- if (node.closing) {
- closeNode();
- }
- throw e;
- }
- });
-
- function closeNode() {
- if (node.wstream) { node.wstream.end(); }
- if (node.tout) { clearTimeout(node.tout); }
- node.status({});
- var cb = node.closeCallback;
- node.closeCallback = null;
- node.closing = false;
- if (cb) {
- cb();
- }
- }
-
- this.on('close', function(done) {
- if (node.closing) {
- // already closing
- return;
- }
- node.closing = true;
- if (done) {
- node.closeCallback = done;
- }
- if (node.msgQueue.length > 0) {
- // close after queue processed
- return;
- }
- else {
- closeNode();
- }
- });
- }
- RED.nodes.registerType("file",FileNode);
-
-
- function FileInNode(n) {
- // Read a file
- RED.nodes.createNode(this,n);
- this.filename = n.filename;
- this.format = n.format;
- this.chunk = false;
- this.encoding = n.encoding || "none";
- this.allProps = n.allProps || false;
- if (n.sendError === undefined) {
- this.sendError = true;
- } else {
- this.sendError = n.sendError;
- }
- if (this.format === "lines") { this.chunk = true; }
- if (this.format === "stream") { this.chunk = true; }
- var node = this;
-
- this.on("input",function(msg, nodeSend, nodeDone) {
- var filename = (node.filename || msg.filename || "").replace(/\t|\r|\n/g,'');
- var fullFilename = filename;
- if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) {
- fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename));
- }
- if (!node.filename) {
- node.status({fill:"grey",shape:"dot",text:filename});
- }
- if (filename === "") {
- node.warn(RED._("file.errors.nofilename"));
- nodeDone();
- }
- else {
- msg.filename = filename;
- var lines = Buffer.from([]);
- var spare = "";
- var count = 0;
- var type = "buffer";
- var ch = "";
- if (node.format === "lines") {
- ch = "\n";
- type = "string";
- }
- var getout = false;
-
- var rs = fs.createReadStream(fullFilename)
- .on('readable', function () {
- var chunk;
- var m;
- var hwm = rs._readableState.highWaterMark;
- while (null !== (chunk = rs.read())) {
- if (node.chunk === true) {
- getout = true;
- if (node.format === "lines") {
- spare += decode(chunk, node.encoding);
- var bits = spare.split("\n");
- for (var i=0; i < bits.length - 1; i++) {
- m = {};
- if (node.allProps == true) {
- m = RED.util.cloneMessage(msg);
- }
- else {
- m.topic = msg.topic;
- m.filename = msg.filename;
- }
- m.payload = bits[i];
- m.parts= {index:count, ch:ch, type:type, id:msg._msgid}
- count += 1;
- nodeSend(m);
- }
- spare = bits[i];
- }
- if (node.format === "stream") {
- m = {};
- if (node.allProps == true) {
- m = RED.util.cloneMessage(msg);
- }
- else {
- m.topic = msg.topic;
- m.filename = msg.filename;
- }
- m.payload = chunk;
- m.parts = {index:count, ch:ch, type:type, id:msg._msgid}
- count += 1;
- if (chunk.length < hwm) { // last chunk is smaller that high water mark = eof
- getout = false;
- m.parts.count = count;
- }
- nodeSend(m);
- }
- }
- else {
- lines = Buffer.concat([lines,chunk]);
- }
- }
- })
- .on('error', function(err) {
- node.error(err, msg);
- if (node.sendError) {
- var sendMessage = RED.util.cloneMessage(msg);
- delete sendMessage.payload;
- sendMessage.error = err;
- nodeSend(sendMessage);
- }
- nodeDone();
- })
- .on('end', function() {
- if (node.chunk === false) {
- if (node.format === "utf8") {
- msg.payload = decode(lines, node.encoding);
- }
- else { msg.payload = lines; }
- nodeSend(msg);
- }
- else if (node.format === "lines") {
- var m = {};
- if (node.allProps) {
- m = RED.util.cloneMessage(msg);
- }
- else {
- m.topic = msg.topic;
- m.filename = msg.filename;
- }
- m.payload = spare;
- m.parts = {
- index: count,
- count: count + 1,
- ch: ch,
- type: type,
- id: msg._msgid
- }
- nodeSend(m);
- }
- else if (getout) { // last chunk same size as high water mark - have to send empty extra packet.
- var m = { parts:{index:count, count:count, ch:ch, type:type, id:msg._msgid} };
- nodeSend(m);
- }
- nodeDone();
- });
- }
- });
- this.on('close', function() {
- node.status({});
- });
- }
- RED.nodes.registerType("file in",FileInNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/core/storage/23-watch.html b/packages/node_modules/@node-red/nodes/core/storage/23-watch.html
deleted file mode 100644
index eafbd46bc..000000000
--- a/packages/node_modules/@node-red/nodes/core/storage/23-watch.html
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
diff --git a/packages/node_modules/@node-red/nodes/core/storage/23-watch.js b/packages/node_modules/@node-red/nodes/core/storage/23-watch.js
deleted file mode 100644
index 9b6c4bc62..000000000
--- a/packages/node_modules/@node-red/nodes/core/storage/23-watch.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-module.exports = function(RED) {
- "use strict";
- var Notify = require("fs.notify");
- var fs = require("fs");
- var path = require("path");
-
- var getAllDirs = function (dir, filelist) {
- filelist = filelist || [];
- fs.readdirSync(dir).forEach(file => {
- try {
- if (fs.statSync(path.join(dir, file)).isDirectory() ) {
- filelist.push(path.join(dir, file));
- getAllDirs(path.join(dir, file), filelist);
- }
- } catch (error) {
- //should we raise an error?
- }
- });
- return filelist;
- }
-
- function WatchNode(n) {
- RED.nodes.createNode(this,n);
-
- this.recursive = n.recursive || false;
- this.files = (n.files || "").split(",");
- for (var f=0; f < this.files.length; f++) {
- this.files[f] = this.files[f].trim();
- }
- this.p = (this.files.length === 1) ? this.files[0] : JSON.stringify(this.files);
- var node = this;
-
- if (node.recursive) {
- for (var fi in node.files) {
- if (node.files.hasOwnProperty(fi)) {
- node.files = node.files.concat(getAllDirs( node.files[fi]));
- }
- }
- }
-
- var notifications = new Notify(node.files);
- notifications.on('change', function (file, event, fpath) {
- var stat;
- try {
- if (fs.statSync(fpath).isDirectory()) { fpath = path.join(fpath,file); }
- stat = fs.statSync(fpath);
- } catch(e) { }
- var type = "none";
- var msg = { payload:fpath, topic:node.p, file:file, filename:fpath };
- if (stat) {
- if (stat.isFile()) { type = "file"; msg.size = stat.size; }
- else if (stat.isBlockDevice()) { type = "blockdevice"; }
- else if (stat.isCharacterDevice()) { type = "characterdevice"; }
- else if (stat.isSocket()) { type = "socket"; }
- else if (stat.isFIFO()) { type = "fifo"; }
- else if (stat.isDirectory()) {
- type = "directory";
- if (node.recursive) {
- notifications.add([fpath]);
- notifications.add(getAllDirs(fpath));
- }
- }
- else { type = "n/a"; }
- }
- msg.type = type;
- node.send(msg);
- });
-
- notifications.on('error', function (error, fpath) {
- var msg = { payload:fpath };
- node.error(error,msg);
- });
-
- this.close = function() {
- notifications.close();
- }
- }
- RED.nodes.registerType("watch",WatchNode);
-}
diff --git a/packages/node_modules/@node-red/nodes/examples/common/debug/01 - Output payload value.json b/packages/node_modules/@node-red/nodes/examples/common/debug/01 - Output payload value.json
index 85b334e68..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/common/debug/01 - Output payload value.json
+++ b/packages/node_modules/@node-red/nodes/examples/common/debug/01 - Output payload value.json
@@ -1 +0,0 @@
-[{"id":"87bd706a.aec93","type":"comment","z":"3ae4b3d9.1f77bc","name":"Output payload value to debug sidebar","info":"Debug node can be used to output payload value to debug sidebar.","x":230,"y":60,"wires":[]},{"id":"8035b07f.7547e","type":"inject","z":"3ae4b3d9.1f77bc","name":"","props":[{"p":"payload","v":"Hello, World!","vt":"str"},{"p":"topic","v":"","vt":"string"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":210,"y":100,"wires":[["20d1344f.931e3c"]]},{"id":"20d1344f.931e3c","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":450,"y":100,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/common/debug/02 - Output complete message.json b/packages/node_modules/@node-red/nodes/examples/common/debug/02 - Output complete message.json
index c8cb9c182..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/common/debug/02 - Output complete message.json
+++ b/packages/node_modules/@node-red/nodes/examples/common/debug/02 - Output complete message.json
@@ -1 +0,0 @@
-[{"id":"8c66d039.44465","type":"comment","z":"e6956267.5d174","name":"Output complete object","info":"Debug node can be used to output whole object value to debug sidebar.","x":160,"y":60,"wires":[]},{"id":"dac87e40.90376","type":"inject","z":"e6956267.5d174","name":"","props":[{"p":"payload","v":"Hello, World!","vt":"str"},{"p":"topic","v":"Sample","vt":"string"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Sample","payload":"Hello, World!","payloadType":"str","x":220,"y":100,"wires":[["a77fa5e3.fac248"]]},{"id":"a77fa5e3.fac248","type":"debug","z":"e6956267.5d174","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":410,"y":100,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/common/debug/03 - Output to console.json b/packages/node_modules/@node-red/nodes/examples/common/debug/03 - Output to console.json
index a5866a723..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/common/debug/03 - Output to console.json
+++ b/packages/node_modules/@node-red/nodes/examples/common/debug/03 - Output to console.json
@@ -1 +0,0 @@
-[{"id":"fb1c3ce9.c29ee","type":"comment","z":"395f4b0d.8a8774","name":"Output to console","info":"Debug node can be used to output values to console.","x":130,"y":60,"wires":[]},{"id":"3c24e746.9ff6a8","type":"inject","z":"395f4b0d.8a8774","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":170,"y":100,"wires":[["66cc7b44.82ba74"]]},{"id":"66cc7b44.82ba74","type":"debug","z":"395f4b0d.8a8774","name":"","active":true,"tosidebar":false,"console":true,"tostatus":false,"complete":"payload","targetType":"msg","x":420,"y":100,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/common/debug/04 - Output to node status.json b/packages/node_modules/@node-red/nodes/examples/common/debug/04 - Output to node status.json
index 9f1fb8265..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/common/debug/04 - Output to node status.json
+++ b/packages/node_modules/@node-red/nodes/examples/common/debug/04 - Output to node status.json
@@ -1 +0,0 @@
-[{"id":"33791e6a.973502","type":"comment","z":"55587092.1f2b4","name":"Output to node status area","info":"Debug node can be used to output values to status area below the node.","x":170,"y":60,"wires":[]},{"id":"a5d8e744.a034e8","type":"inject","z":"55587092.1f2b4","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":190,"y":100,"wires":[["b0646a4d.db4bc8"]]},{"id":"b0646a4d.db4bc8","type":"debug","z":"55587092.1f2b4","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":430,"y":100,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/common/debug/05 - Formatting output using JSONata.json b/packages/node_modules/@node-red/nodes/examples/common/debug/05 - Formatting output using JSONata.json
index 1fa64e5af..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/common/debug/05 - Formatting output using JSONata.json
+++ b/packages/node_modules/@node-red/nodes/examples/common/debug/05 - Formatting output using JSONata.json
@@ -1 +0,0 @@
-[{"id":"30ed0a73.fcef86","type":"comment","z":"61feb619.5e3d68","name":"Formatting output using JSONata","info":"Debug node can format output value using JSONata expression.","x":200,"y":60,"wires":[]},{"id":"6f477e7d.3a8da","type":"inject","z":"61feb619.5e3d68","name":"","props":[{"p":"payload","v":"Hello, World!","vt":"str"},{"p":"topic","v":"Sample","vt":"string"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Sample","payload":"Hello, World!","payloadType":"str","x":220,"y":100,"wires":[["19c9408d.ac6d4f"]]},{"id":"19c9408d.ac6d4f","type":"debug","z":"61feb619.5e3d68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"\"[\" & topic & \"] \" & payload","targetType":"jsonata","x":420,"y":100,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/common/link/01 - Link within a tab.json b/packages/node_modules/@node-red/nodes/examples/common/link/01 - Link within a tab.json
index e3304eb97..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/common/link/01 - Link within a tab.json
+++ b/packages/node_modules/@node-red/nodes/examples/common/link/01 - Link within a tab.json
@@ -1 +0,0 @@
-[{"id":"a30d20e6.ec6dc","type":"link in","z":"2f2d9fa4.be6fc","name":"","links":["70d6f012.8fe6d"],"x":235,"y":240,"wires":[["6bf52c5c.d301c4"]]},{"id":"70d6f012.8fe6d","type":"link out","z":"2f2d9fa4.be6fc","name":"","links":["a30d20e6.ec6dc"],"x":315,"y":180,"wires":[]},{"id":"353c85ce.993d0a","type":"inject","z":"2f2d9fa4.be6fc","name":"","topic":"","payload":"Hello, World!","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":180,"wires":[["70d6f012.8fe6d"]]},{"id":"6bf52c5c.d301c4","type":"debug","z":"2f2d9fa4.be6fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":370,"y":240,"wires":[]},{"id":"62ea32aa.d73aac","type":"comment","z":"2f2d9fa4.be6fc","name":"Example: Link Node","info":"Output of link out node can be connected to input of link in node. The connection between links in/out is not shown, so the flow representation can be simplified.","x":130,"y":40,"wires":[]},{"id":"85133fcc.e482","type":"comment","z":"2f2d9fa4.be6fc","name":"Link output of inject node to input of debug node","info":"","x":260,"y":100,"wires":[]},{"id":"c588bc36.87fec","type":"comment","z":"2f2d9fa4.be6fc","name":"↓ connect to link in node","info":"","x":410,"y":140,"wires":[]},{"id":"8abca900.6dfe78","type":"comment","z":"2f2d9fa4.be6fc","name":"↑ connect from link out node","info":"","x":340,"y":280,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/change/02 - Set any property value.json b/packages/node_modules/@node-red/nodes/examples/function/change/02 - Set any property value.json
index e92ad38dc..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/change/02 - Set any property value.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/change/02 - Set any property value.json
@@ -1 +0,0 @@
-[{"id":"26e7643f.13ebcc","type":"comment","z":"f4cb1920.4d58c8","name":"Set any property value","info":"Change node can set value to any message property.","x":160,"y":60,"wires":[]},{"id":"4da2494d.9aff68","type":"inject","z":"f4cb1920.4d58c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["5111e689.62e838"]]},{"id":"58ea5868.0596e8","type":"debug","z":"f4cb1920.4d58c8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"5111e689.62e838","type":"change","z":"f4cb1920.4d58c8","name":"set payload & topic","rules":[{"t":"set","p":"payload","pt":"msg","to":"Hello, World!","tot":"str"},{"t":"set","p":"topic","pt":"msg","to":"Title","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":120,"wires":[["58ea5868.0596e8"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/change/03 - Set value using JSONata.json b/packages/node_modules/@node-red/nodes/examples/function/change/03 - Set value using JSONata.json
index 2c251157a..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/change/03 - Set value using JSONata.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/change/03 - Set value using JSONata.json
@@ -1 +0,0 @@
-[{"id":"a9039cda.3649e","type":"comment","z":"a808932c.4ca77","name":"Set value using JSONata","info":"Change node can set value to using JSONata expression.","x":170,"y":60,"wires":[]},{"id":"bdcdd579.cfe668","type":"inject","z":"a808932c.4ca77","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["28d110a7.ce3e2"]]},{"id":"c6677fa5.8c111","type":"debug","z":"a808932c.4ca77","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"28d110a7.ce3e2","type":"change","z":"a808932c.4ca77","name":"use JSONata","rules":[{"t":"set","p":"payload","pt":"msg","to":"Hello","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"payload & \", World!\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":120,"wires":[["c6677fa5.8c111"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/change/04 - Set value from env var.json b/packages/node_modules/@node-red/nodes/examples/function/change/04 - Set value from env var.json
index 62f7cc509..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/change/04 - Set value from env var.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/change/04 - Set value from env var.json
@@ -1 +0,0 @@
-[{"id":"e9143349.a64f7","type":"comment","z":"a32e6d69.1b13b","name":"Set value from environment variable","info":"Change node can set value from environment variable.","x":200,"y":60,"wires":[]},{"id":"a7c2725.a631f9","type":"inject","z":"a32e6d69.1b13b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":120,"wires":[["e455c302.2f795"]]},{"id":"6f203119.21895","type":"debug","z":"a32e6d69.1b13b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":530,"y":120,"wires":[]},{"id":"e455c302.2f795","type":"change","z":"a32e6d69.1b13b","name":"set env var","rules":[{"t":"set","p":"payload","pt":"msg","to":"HOME","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":120,"wires":[["6f203119.21895"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/change/05 - Set flow context.json b/packages/node_modules/@node-red/nodes/examples/function/change/05 - Set flow context.json
index 8424b1d2b..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/change/05 - Set flow context.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/change/05 - Set flow context.json
@@ -1 +0,0 @@
-[{"id":"6ecac54d.c43ffc","type":"comment","z":"87ace6c0.f01da8","name":"Set flow context","info":"Change node can set flow context.","x":140,"y":60,"wires":[]},{"id":"80e966d3.9d7a78","type":"inject","z":"87ace6c0.f01da8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":234,"wires":[["abaee298.2d77e"]]},{"id":"60ab671d.b0bbf8","type":"debug","z":"87ace6c0.f01da8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":234,"wires":[]},{"id":"abaee298.2d77e","type":"change","z":"87ace6c0.f01da8","name":"increment count","rules":[{"t":"set","p":"count","pt":"flow","to":"$flowContext(\"count\")+1\t","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"count","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":234,"wires":[["60ab671d.b0bbf8"]]},{"id":"2de2bb38.f20ff4","type":"inject","z":"87ace6c0.f01da8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":140,"wires":[["7b96521e.a3cb0c"]]},{"id":"597b63cd.b3218c","type":"debug","z":"87ace6c0.f01da8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":140,"wires":[]},{"id":"7b96521e.a3cb0c","type":"change","z":"87ace6c0.f01da8","name":"set count to 0","rules":[{"t":"set","p":"count","pt":"flow","to":"0","tot":"num"},{"t":"set","p":"payload","pt":"msg","to":"count","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":140,"wires":[["597b63cd.b3218c"]]},{"id":"3d8cdc6d.2620e4","type":"comment","z":"87ace6c0.f01da8","name":"↓ Initialize","info":"","x":200,"y":100,"wires":[]},{"id":"d8069121.80de7","type":"comment","z":"87ace6c0.f01da8","name":"↓ Count up","info":"","x":200,"y":194,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/delay/01 - Delay message.json b/packages/node_modules/@node-red/nodes/examples/function/delay/01 - Delay message.json
index 849c6d9b4..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/delay/01 - Delay message.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/delay/01 - Delay message.json
@@ -1 +0,0 @@
-[{"id":"87bd706a.aec93","type":"comment","z":"3ae4b3d9.1f77bc","name":"Delay message","info":"Delay node can delay sending input message to output port by a specified amount of time.","x":160,"y":60,"wires":[]},{"id":"1d17715c.34170f","type":"inject","z":"3ae4b3d9.1f77bc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":210,"y":120,"wires":[["26b43de5.4df8f2","9930fecd.ee0c8"]]},{"id":"9930fecd.ee0c8","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":410,"y":120,"wires":[]},{"id":"26b43de5.4df8f2","type":"delay","z":"3ae4b3d9.1f77bc","name":"","pauseType":"delay","timeout":"3","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":400,"y":180,"wires":[["c8c2796c.dcb9f8"]]},{"id":"c8c2796c.dcb9f8","type":"change","z":"3ae4b3d9.1f77bc","name":"Goodbye, World!","rules":[{"t":"set","p":"payload","pt":"msg","to":"Goodbye, World!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":180,"wires":[["c58a290e.2fa438"]]},{"id":"c58a290e.2fa438","type":"debug","z":"3ae4b3d9.1f77bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":790,"y":180,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/delay/02 - Delay message by message property.json b/packages/node_modules/@node-red/nodes/examples/function/delay/02 - Delay message by message property.json
index 9b11ad0d3..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/delay/02 - Delay message by message property.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/delay/02 - Delay message by message property.json
@@ -1 +0,0 @@
-[{"id":"c15b8c3e.955ed","type":"comment","z":"6f1773ed.b7c2fc","name":"Delay message by message property","info":"Delay node can delay sending input message to output port by a specified amount of time by `msg.delay` property.","x":210,"y":60,"wires":[]},{"id":"a5ed5817.9df448","type":"inject","z":"6f1773ed.b7c2fc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"delay","v":"1000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"delay 1s","payloadType":"str","x":180,"y":120,"wires":[["5cf53f4.25b7ec","59b7b67a.a8e888"]]},{"id":"59b7b67a.a8e888","type":"debug","z":"6f1773ed.b7c2fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":390,"y":120,"wires":[]},{"id":"5cf53f4.25b7ec","type":"delay","z":"6f1773ed.b7c2fc","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":380,"y":180,"wires":[["fc989f41.c4114"]]},{"id":"fc989f41.c4114","type":"change","z":"6f1773ed.b7c2fc","name":"Goodbye, World!","rules":[{"t":"set","p":"payload","pt":"msg","to":"Goodbye, World!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":180,"wires":[["74ba3d1c.666034"]]},{"id":"74ba3d1c.666034","type":"debug","z":"6f1773ed.b7c2fc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":770,"y":180,"wires":[]},{"id":"6cdf7297.bf5a8c","type":"inject","z":"6f1773ed.b7c2fc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"delay","v":"10000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"delay 10s","payloadType":"str","x":180,"y":180,"wires":[["59b7b67a.a8e888","5cf53f4.25b7ec"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/delay/03 - Reset or flush pending message.json b/packages/node_modules/@node-red/nodes/examples/function/delay/03 - Reset or flush pending message.json
index 0a4e82e50..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/delay/03 - Reset or flush pending message.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/delay/03 - Reset or flush pending message.json
@@ -1 +0,0 @@
-[{"id":"b0200f61.5efa5","type":"comment","z":"86a4fcf3.9f442","name":"Reset or flush pending message","info":"Delay node can reset or flush delayed message by sending it a message with `reset` or `flush` property.","x":170,"y":60,"wires":[]},{"id":"d5cd8991.e6d2e8","type":"inject","z":"86a4fcf3.9f442","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello, World!","payloadType":"str","x":170,"y":120,"wires":[["607f556b.3ec5fc","fd14cb.2044db38"]]},{"id":"fd14cb.2044db38","type":"debug","z":"86a4fcf3.9f442","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":370,"y":120,"wires":[]},{"id":"607f556b.3ec5fc","type":"delay","z":"86a4fcf3.9f442","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"minutes","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":360,"y":180,"wires":[["d1fc6763.2a30c8"]]},{"id":"d1fc6763.2a30c8","type":"change","z":"86a4fcf3.9f442","name":"Goodbye, World!","rules":[{"t":"set","p":"payload","pt":"msg","to":"Goodbye, World!","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":180,"wires":[["15486d4a.80c6f3"]]},{"id":"15486d4a.80c6f3","type":"debug","z":"86a4fcf3.9f442","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":750,"y":180,"wires":[]},{"id":"2b8b28c7.4c8978","type":"inject","z":"86a4fcf3.9f442","name":"reset","props":[{"p":"topic","vt":"str"},{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":180,"wires":[["607f556b.3ec5fc"]]},{"id":"3a7e1bec.8bc3d4","type":"inject","z":"86a4fcf3.9f442","name":"flush","props":[{"p":"topic","vt":"str"},{"p":"flush","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":240,"wires":[["607f556b.3ec5fc"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/delay/05 - Limit message rate for each topic.json b/packages/node_modules/@node-red/nodes/examples/function/delay/05 - Limit message rate for each topic.json
index 8d6bc7518..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/delay/05 - Limit message rate for each topic.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/delay/05 - Limit message rate for each topic.json
@@ -1 +0,0 @@
-[{"id":"3dc5015b.96c97e","type":"comment","z":"73c00795.a13908","name":"Limit rate of message transfer for each topic","info":"Delay node can limit of message transmission from input to output port by a specified number of message per a specified time.\nIf `For each topic` is selected, messages are grouped by `msg.topic` value. When grouping messages by topic, intermediate messages are dropped and the last messages received sent.","x":210,"y":60,"wires":[]},{"id":"bdafe4c6.4d5658","type":"inject","z":"73c00795.a13908","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"topic\":\"apple\",\"payload\":1},{\"topic\":\"apple\",\"payload\":2},{\"topic\":\"apple\",\"payload\":3},{\"topic\":\"orange\",\"payload\":1},{\"topic\":\"orange\",\"payload\":2},{\"topic\":\"orange\",\"payload\":3},{\"topic\":\"banana\",\"payload\":1},{\"topic\":\"banana\",\"payload\":2},{\"topic\":\"banana\",\"payload\":3}]","payloadType":"json","x":150,"y":120,"wires":[["f86dc462.195818"]]},{"id":"e0bdfcc1.cdf48","type":"delay","z":"73c00795.a13908","name":"","pauseType":"timed","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":690,"y":120,"wires":[["29d8beea.6b37f2"]]},{"id":"29d8beea.6b37f2","type":"debug","z":"73c00795.a13908","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":890,"y":120,"wires":[]},{"id":"f86dc462.195818","type":"split","z":"73c00795.a13908","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":290,"y":120,"wires":[["9feb3aac.616c38"]]},{"id":"9feb3aac.616c38","type":"change","z":"73c00795.a13908","name":"set topic&payload","rules":[{"t":"set","p":"topic","pt":"msg","to":"payload.topic","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"payload.payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":120,"wires":[["e0bdfcc1.cdf48"]]},{"id":"949199e8.89bc88","type":"comment","z":"73c00795.a13908","name":"↑ pass last message of each topic","info":"","x":740,"y":160,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/exec/01 - Get standard output from external command.json b/packages/node_modules/@node-red/nodes/examples/function/exec/01 - Get standard output from external command.json
index 365e4405c..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/exec/01 - Get standard output from external command.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/exec/01 - Get standard output from external command.json
@@ -1 +0,0 @@
-[{"id":"6a5f26a9.0cc2d8","type":"inject","z":"835cc8cc.b8cca8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"Hello World!","payloadType":"str","x":190,"y":160,"wires":[["fc2b343c.bbe2f8"]]},{"id":"fc2b343c.bbe2f8","type":"exec","z":"835cc8cc.b8cca8","command":"echo","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":330,"y":160,"wires":[["2f3bcd73.6fedf2"],[],["3280586e.4e3d28"]]},{"id":"2f3bcd73.6fedf2","type":"debug","z":"835cc8cc.b8cca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":160,"wires":[]},{"id":"2b7bc9f1.ab36a6","type":"comment","z":"835cc8cc.b8cca8","name":"Execute external command appending additional args","info":"Exec node can execute external command and can receive its standard output as a payload of first message. Standard error output can be received from second message. The exit code of the command can be obtained from `code` property of third message payload.\n\nIf `Append msg.payload` checkbox is selected, payload value of the input message is appended to command string.\n","x":260,"y":60,"wires":[]},{"id":"3280586e.4e3d28","type":"debug","z":"835cc8cc.b8cca8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":510,"y":220,"wires":[]},{"id":"feba83da.8f227","type":"comment","z":"835cc8cc.b8cca8","name":"↓ execute echo command","info":"","x":390,"y":115,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/exec/02 - Get error output from external command.json b/packages/node_modules/@node-red/nodes/examples/function/exec/02 - Get error output from external command.json
index 992b39df3..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/exec/02 - Get error output from external command.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/exec/02 - Get error output from external command.json
@@ -1 +0,0 @@
-[{"id":"f507b27c.fff1","type":"inject","z":"462f83a6.d3c3cc","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":180,"wires":[["28b4f75a.eae548"]]},{"id":"28b4f75a.eae548","type":"exec","z":"462f83a6.d3c3cc","command":"/non/existing/command","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":350,"y":180,"wires":[[],["27992c1f.a1c964"],["6e7ff001.2412d"]]},{"id":"6e7ff001.2412d","type":"debug","z":"462f83a6.d3c3cc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":240,"wires":[]},{"id":"27992c1f.a1c964","type":"debug","z":"462f83a6.d3c3cc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":180,"wires":[]},{"id":"77e85c7c.a560d4","type":"comment","z":"462f83a6.d3c3cc","name":"Execute external command and get error output","info":"Exec node can execute external command and can receive its standard output as a payload of first message. Standard error output can be received from second message. The exit code of the command can be obtained from `code` property of third message payload.\n","x":220,"y":80,"wires":[]},{"id":"c188c28c.f7d34","type":"comment","z":"462f83a6.d3c3cc","name":"↓ try to execute non-existing command","info":"","x":390,"y":134,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/range/02 - Scale input and round to integer.json b/packages/node_modules/@node-red/nodes/examples/function/range/02 - Scale input and round to integer.json
index f45eb6991..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/range/02 - Scale input and round to integer.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/range/02 - Scale input and round to integer.json
@@ -1 +0,0 @@
-[{"id":"990f33d3.3ffe2","type":"comment","z":"db89ae0c.f52b5","name":"Scale input value & round result to integer","info":"Range node can map input value to output value according to mapping specification.\nThe result value is rounded to nearest integer if `Round result to the nearest integer?` checkbox is checked.","x":240,"y":60,"wires":[]},{"id":"b2639501.5ad638","type":"inject","z":"db89ae0c.f52b5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":190,"y":120,"wires":[["dc4509ee.773038"]]},{"id":"dc4509ee.773038","type":"range","z":"db89ae0c.f52b5","minin":"0","maxin":"9","minout":"0","maxout":"128","action":"scale","round":true,"property":"payload","name":"","x":360,"y":120,"wires":[["50991e7e.2ed24"]]},{"id":"50991e7e.2ed24","type":"debug","z":"db89ae0c.f52b5","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":520,"y":120,"wires":[]},{"id":"335e877f.d24e98","type":"inject","z":"db89ae0c.f52b5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":190,"y":160,"wires":[["dc4509ee.773038"]]},{"id":"5d88207d.4189","type":"inject","z":"db89ae0c.f52b5","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"99","payloadType":"num","x":190,"y":200,"wires":[["dc4509ee.773038"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/range/03 - Limit input.json b/packages/node_modules/@node-red/nodes/examples/function/range/03 - Limit input.json
index c637c86f9..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/range/03 - Limit input.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/range/03 - Limit input.json
@@ -1 +0,0 @@
-[{"id":"f0bc6a80.d52578","type":"comment","z":"bdb79f11.23e1d","name":"Limit input value","info":"Range node can map input value to output value according to mapping specification.\nThe result value is limited to specified range if `Scale and limit to the target range` is selected.","x":140,"y":60,"wires":[]},{"id":"69652849.749198","type":"inject","z":"bdb79f11.23e1d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":170,"y":120,"wires":[["104f6f14.1c72e1"]]},{"id":"104f6f14.1c72e1","type":"range","z":"bdb79f11.23e1d","minin":"0","maxin":"100","minout":"0","maxout":"90","action":"clamp","round":false,"property":"payload","name":"","x":330,"y":120,"wires":[["10fcbed4.9c8d71"]]},{"id":"10fcbed4.9c8d71","type":"debug","z":"bdb79f11.23e1d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":120,"wires":[]},{"id":"93bb4526.7d6e28","type":"inject","z":"bdb79f11.23e1d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":170,"y":160,"wires":[["104f6f14.1c72e1"]]},{"id":"6892dfd8.42386","type":"inject","z":"bdb79f11.23e1d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"100","payloadType":"num","x":170,"y":200,"wires":[["104f6f14.1c72e1"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/range/04 - Scale and wrap input.json b/packages/node_modules/@node-red/nodes/examples/function/range/04 - Scale and wrap input.json
index ce8cb733a..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/range/04 - Scale and wrap input.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/range/04 - Scale and wrap input.json
@@ -1 +0,0 @@
-[{"id":"808e354d.8de148","type":"comment","z":"b1446352.d689e","name":"Scale and wrap input value","info":"Range node can map input value to output value according to mapping specification.\nThe result value is wrapped if `Scale and wrap within the target range` is selected.","x":170,"y":60,"wires":[]},{"id":"2f033c72.51dcc4","type":"inject","z":"b1446352.d689e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":170,"y":120,"wires":[["cdaa82c4.820de"]]},{"id":"cdaa82c4.820de","type":"range","z":"b1446352.d689e","minin":"0","maxin":"9","minout":"0","maxout":"90","action":"roll","round":false,"property":"payload","name":"","x":330,"y":120,"wires":[["77f8872b.2a9968"]]},{"id":"77f8872b.2a9968","type":"debug","z":"b1446352.d689e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":120,"wires":[]},{"id":"84ac6a7e.77b8d8","type":"inject","z":"b1446352.d689e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":170,"y":160,"wires":[["cdaa82c4.820de"]]},{"id":"92f554c3.b08ad8","type":"inject","z":"b1446352.d689e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"100","payloadType":"num","x":170,"y":200,"wires":[["cdaa82c4.820de"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/switch/02 - Check all rules.json b/packages/node_modules/@node-red/nodes/examples/function/switch/02 - Check all rules.json
index 8a51a99f1..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/switch/02 - Check all rules.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/switch/02 - Check all rules.json
@@ -1 +0,0 @@
-[{"id":"6ec19fc7.a32ae","type":"comment","z":"e482b0ab.b1b43","name":"Check all rules","info":"Switch node apply all rules if `checking all rules` is selected in settings panel.","x":120,"y":60,"wires":[]},{"id":"1644e138.f8d1ef","type":"switch","z":"e482b0ab.b1b43","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"10","vt":"num"},{"t":"gt","v":"-10","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":290,"y":140,"wires":[["624b4e9f.37fee"],["a89d6432.b68318"]]},{"id":"a7f64dbf.3e27b","type":"debug","z":"e482b0ab.b1b43","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":100,"wires":[]},{"id":"a89d6432.b68318","type":"change","z":"e482b0ab.b1b43","name":">-10","rules":[{"t":"set","p":"payload","pt":"msg","to":">-10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":180,"wires":[["f1136da2.23516"]]},{"id":"624b4e9f.37fee","type":"change","z":"e482b0ab.b1b43","name":"<10","rules":[{"t":"set","p":"payload","pt":"msg","to":"<10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":100,"wires":[["a7f64dbf.3e27b"]]},{"id":"f1136da2.23516","type":"debug","z":"e482b0ab.b1b43","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":180,"wires":[]},{"id":"c7e952e9.88e5e","type":"inject","z":"e482b0ab.b1b43","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-10","payloadType":"num","x":150,"y":100,"wires":[["1644e138.f8d1ef"]]},{"id":"8cf8babd.b43db8","type":"inject","z":"e482b0ab.b1b43","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":150,"y":180,"wires":[["1644e138.f8d1ef"]]},{"id":"6a43ae86.b92ed","type":"inject","z":"e482b0ab.b1b43","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":150,"y":140,"wires":[["1644e138.f8d1ef"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/switch/03 - Stop after first match.json b/packages/node_modules/@node-red/nodes/examples/function/switch/03 - Stop after first match.json
index 0b41e75e3..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/switch/03 - Stop after first match.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/switch/03 - Stop after first match.json
@@ -1 +0,0 @@
-[{"id":"a12a5708.195688","type":"comment","z":"74b5d6de.372b18","name":"Stop after first match","info":"Switch node stops application of rules if `stopping after first match` is selected in settings panel and a rule evaluates to `true`.","x":160,"y":60,"wires":[]},{"id":"8aebdebf.5d7f2","type":"switch","z":"74b5d6de.372b18","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"10","vt":"num"},{"t":"gt","v":"-10","vt":"num"}],"checkall":"false","repair":false,"outputs":2,"x":310,"y":140,"wires":[["5d1851c.a9c5db"],["e8228605.f32018"]]},{"id":"60248c98.69fd44","type":"debug","z":"74b5d6de.372b18","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":100,"wires":[]},{"id":"e8228605.f32018","type":"change","z":"74b5d6de.372b18","name":">-10","rules":[{"t":"set","p":"payload","pt":"msg","to":">-10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":180,"wires":[["e9a51608.c322b8"]]},{"id":"5d1851c.a9c5db","type":"change","z":"74b5d6de.372b18","name":"<10","rules":[{"t":"set","p":"payload","pt":"msg","to":"<10","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":100,"wires":[["60248c98.69fd44"]]},{"id":"e9a51608.c322b8","type":"debug","z":"74b5d6de.372b18","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":180,"wires":[]},{"id":"49222b4b.647a84","type":"inject","z":"74b5d6de.372b18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"-10","payloadType":"num","x":170,"y":100,"wires":[["8aebdebf.5d7f2"]]},{"id":"39e8c133.a56f7e","type":"inject","z":"74b5d6de.372b18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":170,"y":180,"wires":[["8aebdebf.5d7f2"]]},{"id":"3a22ec96.965a14","type":"inject","z":"74b5d6de.372b18","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":170,"y":140,"wires":[["8aebdebf.5d7f2"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/switch/04 - Select output port by type.json b/packages/node_modules/@node-red/nodes/examples/function/switch/04 - Select output port by type.json
index b5e386fa1..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/switch/04 - Select output port by type.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/switch/04 - Select output port by type.json
@@ -1 +0,0 @@
-[{"id":"6dfd4381.eae2ec","type":"comment","z":"7d002985.82f928","name":"Select output based on type of payload value","info":"Switch node can route input message based on type of payload value.","x":210,"y":40,"wires":[]},{"id":"b139dacf.a0d818","type":"switch","z":"7d002985.82f928","name":"","property":"payload","propertyType":"msg","rules":[{"t":"istype","v":"string","vt":"string"},{"t":"istype","v":"number","vt":"number"}],"checkall":"false","repair":false,"outputs":2,"x":330,"y":120,"wires":[["7c5cd60c.e66b28"],["86cf5262.20f18"]]},{"id":"ca403f12.477a8","type":"debug","z":"7d002985.82f928","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":160,"wires":[]},{"id":"7c5cd60c.e66b28","type":"change","z":"7d002985.82f928","name":"String","rules":[{"t":"set","p":"payload","pt":"msg","to":"string","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":80,"wires":[["d9669648.1177e8"]]},{"id":"86cf5262.20f18","type":"change","z":"7d002985.82f928","name":"Number","rules":[{"t":"set","p":"payload","pt":"msg","to":"number","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":160,"wires":[["ca403f12.477a8"]]},{"id":"d9669648.1177e8","type":"debug","z":"7d002985.82f928","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":80,"wires":[]},{"id":"d3f1c718.dc67e8","type":"inject","z":"7d002985.82f928","name":"Number:128","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"128","payloadType":"num","x":170,"y":80,"wires":[["b139dacf.a0d818"]]},{"id":"a59e275e.6d48c8","type":"inject","z":"7d002985.82f928","name":"String:128","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"128","payloadType":"str","x":160,"y":160,"wires":[["b139dacf.a0d818"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/switch/05 - Use JSONata for switch rule.json b/packages/node_modules/@node-red/nodes/examples/function/switch/05 - Use JSONata for switch rule.json
index f0955a3f1..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/switch/05 - Use JSONata for switch rule.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/switch/05 - Use JSONata for switch rule.json
@@ -1 +0,0 @@
-[{"id":"175ceb0d.8dbe45","type":"comment","z":"17f634f4.e4bc9b","name":"Use JSONata expression for rules","info":"Switch node can use JSONata expression for calculating complex conditions.","x":200,"y":60,"wires":[]},{"id":"d89491c3.793a3","type":"switch","z":"17f634f4.e4bc9b","name":"","property":"payload","propertyType":"msg","rules":[{"t":"jsonata_exp","v":"(payload % 2) = 0","vt":"jsonata"},{"t":"jsonata_exp","v":"(payload % 2) = 1","vt":"jsonata"}],"checkall":"false","repair":false,"outputs":2,"x":310,"y":140,"wires":[["d6cb78a6.872908"],["1f0c62bb.c3d52d"]]},{"id":"9ae9a2aa.a895c","type":"debug","z":"17f634f4.e4bc9b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":100,"wires":[]},{"id":"1f0c62bb.c3d52d","type":"change","z":"17f634f4.e4bc9b","name":"Odd","rules":[{"t":"set","p":"payload","pt":"msg","to":"odd","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":180,"wires":[["34b0a9fb.bafdb6"]]},{"id":"d6cb78a6.872908","type":"change","z":"17f634f4.e4bc9b","name":"Even","rules":[{"t":"set","p":"payload","pt":"msg","to":"even","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":100,"wires":[["9ae9a2aa.a895c"]]},{"id":"34b0a9fb.bafdb6","type":"debug","z":"17f634f4.e4bc9b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":610,"y":180,"wires":[]},{"id":"7beb0333.a55bac","type":"inject","z":"17f634f4.e4bc9b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"7","payloadType":"num","x":170,"y":100,"wires":[["d89491c3.793a3"]]},{"id":"a8db47cf.58ba18","type":"inject","z":"17f634f4.e4bc9b","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"8","payloadType":"num","x":170,"y":180,"wires":[["d89491c3.793a3"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/switch/06 - Use JSONata for switch value.json b/packages/node_modules/@node-red/nodes/examples/function/switch/06 - Use JSONata for switch value.json
index 3404b4ff9..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/switch/06 - Use JSONata for switch value.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/switch/06 - Use JSONata for switch value.json
@@ -1 +0,0 @@
-[{"id":"1c09dc33.934504","type":"comment","z":"166069bc.648516","name":"Use JSONata expression for switch value","info":"Switch node can use JSONata expression for calculating complex switch value.","x":200,"y":60,"wires":[]},{"id":"c7ca4974.d638f8","type":"switch","z":"166069bc.648516","name":"","property":"(payload % 2) = 0","propertyType":"jsonata","rules":[{"t":"true"},{"t":"false"}],"checkall":"false","repair":false,"outputs":2,"x":290,"y":140,"wires":[["ac921b1d.c0dbe8"],["89adcfcc.53d6d"]]},{"id":"ab8972e0.e98b7","type":"debug","z":"166069bc.648516","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":100,"wires":[]},{"id":"89adcfcc.53d6d","type":"change","z":"166069bc.648516","name":"Odd","rules":[{"t":"set","p":"payload","pt":"msg","to":"odd","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":180,"wires":[["426c68cf.64f0e8"]]},{"id":"ac921b1d.c0dbe8","type":"change","z":"166069bc.648516","name":"Even","rules":[{"t":"set","p":"payload","pt":"msg","to":"even","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":100,"wires":[["ab8972e0.e98b7"]]},{"id":"426c68cf.64f0e8","type":"debug","z":"166069bc.648516","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":590,"y":180,"wires":[]},{"id":"63377f1c.2fbfc","type":"inject","z":"166069bc.648516","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"7","payloadType":"num","x":150,"y":100,"wires":[["c7ca4974.d638f8"]]},{"id":"ea2fa596.ff1638","type":"inject","z":"166069bc.648516","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"8","payloadType":"num","x":150,"y":180,"wires":[["c7ca4974.d638f8"]]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/template/01 - Use mustache syntax.json b/packages/node_modules/@node-red/nodes/examples/function/template/01 - Use mustache syntax.json
index de123bbe8..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/template/01 - Use mustache syntax.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/template/01 - Use mustache syntax.json
@@ -1 +0,0 @@
-[{"id":"eaf91a6b.a55da8","type":"comment","z":"73a69428.bf4fec","name":"Advanced mustache example","info":"Template node can create a string value using [Mustache](http://mustache.github.io/mustache.5.html) syntax.","x":200,"y":80,"wires":[]},{"id":"61fbfe34.14a02","type":"inject","z":"73a69428.bf4fec","name":"Price of fruits","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"Fruits","payload":"[{\"name\":\"apple\",\"price\":100},{\"name\":\"orange\",\"price\":80},{\"name\":\"banana\",\"price\":210}]","payloadType":"json","x":210,"y":140,"wires":[["bf0cb02.d8e4b5"]]},{"id":"bf0cb02.d8e4b5","type":"template","z":"73a69428.bf4fec","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"# Price List of {{topic}}\n\n{{! outputs list of prices }}\n{{#payload}}\n- {{name}}: {{price}}\n{{/payload}}\n","output":"str","x":380,"y":140,"wires":[["153eb0ff.5622df"]]},{"id":"153eb0ff.5622df","type":"debug","z":"73a69428.bf4fec","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":550,"y":140,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/template/02 - Parse result as JSON.json b/packages/node_modules/@node-red/nodes/examples/function/template/02 - Parse result as JSON.json
index d2042aa98..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/template/02 - Parse result as JSON.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/template/02 - Parse result as JSON.json
@@ -1 +0,0 @@
-[{"id":"fe821493.2e0e28","type":"comment","z":"1e6bd604.afc8fa","name":"Parse result as JSON","info":"Template node can create a string value using [Mustache](http://mustache.github.io/mustache.5.html) syntax.\nIf `Partsed JSON` output is selected, the created string is parsed as JSON format and JavaScript object is send as an output payload value.","x":160,"y":60,"wires":[]},{"id":"931f94e8.592cd8","type":"inject","z":"1e6bd604.afc8fa","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"message","payload":"Hello, World!","payloadType":"str","x":220,"y":120,"wires":[["bb2b0dad.b24b5"]]},{"id":"bb2b0dad.b24b5","type":"template","z":"1e6bd604.afc8fa","name":"JSON template","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"{\n \"key\" : \"{{topic}}\",\n \"value\": \"{{payload}}\"\n}\n","output":"json","x":440,"y":120,"wires":[["baf2e48.2b97418"]]},{"id":"baf2e48.2b97418","type":"debug","z":"1e6bd604.afc8fa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":120,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/template/03 - Parse result as YAML.json b/packages/node_modules/@node-red/nodes/examples/function/template/03 - Parse result as YAML.json
index dc01b1e3a..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/template/03 - Parse result as YAML.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/template/03 - Parse result as YAML.json
@@ -1 +0,0 @@
-[{"id":"6ad06659.a1e4e8","type":"comment","z":"369312e8.ba755e","name":"Parse result as YAML","info":"Template node can create a string value using [Mustache](http://mustache.github.io/mustache.5.html) syntax.\nIf `Partsed YAML` output is selected, the created string is parsed as YAML format and JavaScript object is send as an output payload value.","x":180,"y":60,"wires":[]},{"id":"8d6be9a2.c3fa58","type":"inject","z":"369312e8.ba755e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"message","payload":"Hello, World!","payloadType":"str","x":240,"y":120,"wires":[["69369c3.4a98164"]]},{"id":"69369c3.4a98164","type":"template","z":"369312e8.ba755e","name":"YAML template","field":"payload","fieldType":"msg","format":"yaml","syntax":"mustache","template":"key: {{topic}}\nvalue: {{payload}}","output":"yaml","x":460,"y":120,"wires":[["11fb2934.f5de27"]]},{"id":"11fb2934.f5de27","type":"debug","z":"369312e8.ba755e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":120,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/function/trigger/01 - Outputs two value with interval.json b/packages/node_modules/@node-red/nodes/examples/function/trigger/01 - Outputs two value with interval.json
index 401e6c681..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/function/trigger/01 - Outputs two value with interval.json
+++ b/packages/node_modules/@node-red/nodes/examples/function/trigger/01 - Outputs two value with interval.json
@@ -1 +0,0 @@
-[{"id":"ec5a531b.68b65","type":"inject","z":"90acd374.2feda","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":100,"wires":[["cb5e0c78.4bf3d"]]},{"id":"1b0f8c3e.1fd7e4","type":"debug","z":"90acd374.2feda","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":490,"y":100,"wires":[]},{"id":"cb5e0c78.4bf3d","type":"trigger","z":"90acd374.2feda","name":"","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"2","extend":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":320,"y":100,"wires":[["1b0f8c3e.1fd7e4"]]},{"id":"4e5bf6b2.b4dd58","type":"comment","z":"90acd374.2feda","name":"Oputputs two values with interval","info":"Outputs 1. Then output 0 after a certain period of time.\n\n*This could be used, for example, to blink an LED attached to a Raspberry Pi GPIO pin.*","x":170,"y":40,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/http/03 - Handle URL parameters.json b/packages/node_modules/@node-red/nodes/examples/network/http/03 - Handle URL parameters.json
index 0a60fa95d..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/http/03 - Handle URL parameters.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/http/03 - Handle URL parameters.json
@@ -1,135 +0,0 @@
-[
- {
- "id": "9b2d7459.8dd598",
- "type": "http in",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "url": "/hello-param/:name",
- "method": "get",
- "upload": false,
- "swaggerDoc": "",
- "x": 290,
- "y": 900,
- "wires": [
- [
- "83753c80.5e271"
- ]
- ]
- },
- {
- "id": "7fe50f46.46209",
- "type": "http response",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "statusCode": "",
- "headers": {},
- "x": 590,
- "y": 900,
- "wires": []
- },
- {
- "id": "6e88d2b.828a92c",
- "type": "comment",
- "z": "d41b4dd3.ecd6a",
- "name": "Handle URL parameters in an HTTP endpoint",
- "info": "Named path parameters (e.g. `:name`) in the URL property can be used to identify parts of the path that can vary between requests.\n\nThe `msg.req.params` property is an object of key/value pairs for each path parameter.",
- "x": 290,
- "y": 860,
- "wires": []
- },
- {
- "id": "214bc398.b3482c",
- "type": "http request",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "method": "GET",
- "ret": "txt",
- "paytoqs": "ignore",
- "url": "http://localhost:1880/hello-param/Nick",
- "tls": "",
- "persist": false,
- "proxy": "",
- "authType": "",
- "x": 390,
- "y": 1000,
- "wires": [
- [
- "70c0eba4.5f0dc4"
- ]
- ]
- },
- {
- "id": "70c0eba4.5f0dc4",
- "type": "debug",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 550,
- "y": 1000,
- "wires": []
- },
- {
- "id": "83753c80.5e271",
- "type": "template",
- "z": "d41b4dd3.ecd6a",
- "name": "page",
- "field": "payload",
- "fieldType": "msg",
- "format": "html",
- "syntax": "mustache",
- "template": "\n \n \n Hello {{req.params.name}}! \n \n",
- "output": "str",
- "x": 470,
- "y": 900,
- "wires": [
- [
- "7fe50f46.46209"
- ]
- ]
- },
- {
- "id": "89523bfe.6e5c18",
- "type": "inject",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 240,
- "y": 1000,
- "wires": [
- [
- "214bc398.b3482c"
- ]
- ]
- },
- {
- "id": "6276a6cd.5c3b18",
- "type": "comment",
- "z": "d41b4dd3.ecd6a",
- "name": "Send HTTP GET request: http://localhost:1880/hello-param/Nick",
- "info": "`http request` node can be used to send **HTTP GET** request.",
- "x": 350,
- "y": 960,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/http/06 - Post file to a flow.json b/packages/node_modules/@node-red/nodes/examples/network/http/06 - Post file to a flow.json
index aec360a91..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/http/06 - Post file to a flow.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/http/06 - Post file to a flow.json
@@ -1,126 +0,0 @@
-[
- {
- "id": "59760c9d.172d94",
- "type": "http in",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "url": "/hello-upload",
- "method": "post",
- "upload": true,
- "swaggerDoc": "",
- "x": 270,
- "y": 1980,
- "wires": [
- [
- "e30073f3.ad429"
- ]
- ]
- },
- {
- "id": "d0b3e8b4.2cfde8",
- "type": "comment",
- "z": "d41b4dd3.ecd6a",
- "name": "Post file to a flow",
- "info": "The `HTTP In` node can listen for POST requests for file upload. Information for uploaded files can be accessed from `msg.req.files`.\n",
- "x": 200,
- "y": 1760,
- "wires": []
- },
- {
- "id": "a888a043.ebb72",
- "type": "http in",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "url": "/hello-upload",
- "method": "get",
- "upload": false,
- "swaggerDoc": "",
- "x": 270,
- "y": 1880,
- "wires": [
- [
- "14b950b.0ed5aaf"
- ]
- ]
- },
- {
- "id": "2ccb67c7.02c568",
- "type": "http response",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "statusCode": "",
- "headers": {},
- "x": 590,
- "y": 1880,
- "wires": []
- },
- {
- "id": "14b950b.0ed5aaf",
- "type": "template",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "field": "payload",
- "fieldType": "msg",
- "format": "html",
- "syntax": "mustache",
- "template": "\n \n \n \n \n",
- "output": "str",
- "x": 440,
- "y": 1880,
- "wires": [
- [
- "2ccb67c7.02c568"
- ]
- ]
- },
- {
- "id": "54f2edb5.62fca4",
- "type": "http response",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "statusCode": "",
- "headers": {},
- "x": 590,
- "y": 1980,
- "wires": []
- },
- {
- "id": "e30073f3.ad429",
- "type": "template",
- "z": "d41b4dd3.ecd6a",
- "name": "",
- "field": "payload",
- "fieldType": "msg",
- "format": "html",
- "syntax": "mustache",
- "template": "\n \n \n Hello {{req.files.0.originalname}} \n \n",
- "output": "str",
- "x": 440,
- "y": 1980,
- "wires": [
- [
- "54f2edb5.62fca4"
- ]
- ]
- },
- {
- "id": "6c3c1bf.48cc2e4",
- "type": "comment",
- "z": "d41b4dd3.ecd6a",
- "name": "Create HTTP page for file upload: open http://localhost:1880/hello-upload \\n from Web browser. Then upload a file.",
- "info": "",
- "x": 440,
- "y": 1820,
- "wires": []
- },
- {
- "id": "c6242caa.8ec63",
- "type": "comment",
- "z": "d41b4dd3.ecd6a",
- "name": "Serve POST request for file upload",
- "info": "",
- "x": 320,
- "y": 1940,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/tcp/01 - Connect to TCP out server.json b/packages/node_modules/@node-red/nodes/examples/network/tcp/01 - Connect to TCP out server.json
index 78c24760c..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/tcp/01 - Connect to TCP out server.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/tcp/01 - Connect to TCP out server.json
@@ -1,92 +0,0 @@
-[
- {
- "id": "73874b9e.d985b4",
- "type": "tcp in",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "server": "client",
- "host": "localhost",
- "port": "1881",
- "datamode": "single",
- "datatype": "utf8",
- "newline": "",
- "topic": "",
- "base64": false,
- "x": 230,
- "y": 240,
- "wires": [
- [
- "ce332113.d2c31"
- ]
- ]
- },
- {
- "id": "a4bd9948.dfeb58",
- "type": "tcp out",
- "z": "cfd9159c.6f73e8",
- "host": "localhost",
- "port": "1881",
- "beserver": "server",
- "base64": false,
- "end": true,
- "name": "",
- "x": 390,
- "y": 180,
- "wires": []
- },
- {
- "id": "9f80f9c7.1e3c98",
- "type": "inject",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 210,
- "y": 180,
- "wires": [
- [
- "a4bd9948.dfeb58"
- ]
- ]
- },
- {
- "id": "ce332113.d2c31",
- "type": "debug",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 410,
- "y": 240,
- "wires": []
- },
- {
- "id": "711ed10d.1d765",
- "type": "comment",
- "z": "cfd9159c.6f73e8",
- "name": "Connect to TCP out server",
- "info": "`TCP in` node can connect to network server using tcp protocol. `TCP out` node can serve a network server using tcp procol.\n",
- "x": 190,
- "y": 120,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/tcp/02 - Connect to TCP in server.json b/packages/node_modules/@node-red/nodes/examples/network/tcp/02 - Connect to TCP in server.json
index 357cbb9ca..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/tcp/02 - Connect to TCP in server.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/tcp/02 - Connect to TCP in server.json
@@ -1,92 +0,0 @@
-[
- {
- "id": "511f8208.c4c20c",
- "type": "tcp in",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "server": "server",
- "host": "localhost",
- "port": "1882",
- "datamode": "single",
- "datatype": "utf8",
- "newline": "",
- "topic": "",
- "base64": false,
- "x": 230,
- "y": 460,
- "wires": [
- [
- "6b8be121.32be9"
- ]
- ]
- },
- {
- "id": "ec0bc4aa.b3c828",
- "type": "tcp out",
- "z": "cfd9159c.6f73e8",
- "host": "localhost",
- "port": "1882",
- "beserver": "client",
- "base64": false,
- "end": true,
- "name": "",
- "x": 390,
- "y": 400,
- "wires": []
- },
- {
- "id": "17cf7d56.9efb03",
- "type": "inject",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 210,
- "y": 400,
- "wires": [
- [
- "ec0bc4aa.b3c828"
- ]
- ]
- },
- {
- "id": "6b8be121.32be9",
- "type": "debug",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 410,
- "y": 460,
- "wires": []
- },
- {
- "id": "76196665.7c23e8",
- "type": "comment",
- "z": "cfd9159c.6f73e8",
- "name": "Connect to TCP in server",
- "info": "`TCP out` node can connect to network server using tcp protocol. `TCP in` node can serve a network server using tcp procol.\n",
- "x": 190,
- "y": 340,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/tcp/03 - Send reply to client of TCP connection.json b/packages/node_modules/@node-red/nodes/examples/network/tcp/03 - Send reply to client of TCP connection.json
index b4a324261..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/tcp/03 - Send reply to client of TCP connection.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/tcp/03 - Send reply to client of TCP connection.json
@@ -1,174 +0,0 @@
-[
- {
- "id": "d9a91d7e.05f0d",
- "type": "tcp in",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "server": "server",
- "host": "localhost",
- "port": "1883",
- "datamode": "stream",
- "datatype": "utf8",
- "newline": "¥n",
- "topic": "",
- "base64": false,
- "x": 230,
- "y": 740,
- "wires": [
- [
- "3871d8af.25e208"
- ]
- ]
- },
- {
- "id": "9fa8f09d.7591b",
- "type": "inject",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "\"Hello, World!¥n\"",
- "payloadType": "jsonata",
- "x": 190,
- "y": 640,
- "wires": [
- [
- "948a8410.ab0a08"
- ]
- ]
- },
- {
- "id": "33df08b.753e9f8",
- "type": "debug",
- "z": "cfd9159c.6f73e8",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 710,
- "y": 640,
- "wires": []
- },
- {
- "id": "948a8410.ab0a08",
- "type": "tcp request",
- "z": "cfd9159c.6f73e8",
- "server": "localhost",
- "port": "1883",
- "out": "char",
- "splitc": "\\n",
- "name": "",
- "x": 350,
- "y": 640,
- "wires": [
- [
- "f6d6be6a.efb4c"
- ]
- ]
- },
- {
- "id": "fbd442d8.cb273",
- "type": "tcp out",
- "z": "cfd9159c.6f73e8",
- "host": "",
- "port": "",
- "beserver": "reply",
- "base64": false,
- "end": false,
- "name": "",
- "x": 530,
- "y": 740,
- "wires": []
- },
- {
- "id": "3871d8af.25e208",
- "type": "change",
- "z": "cfd9159c.6f73e8",
- "name": "set result",
- "rules": [
- {
- "t": "set",
- "p": "payload",
- "pt": "msg",
- "to": "\"Received: \" & payload & \"\b\\n\"",
- "tot": "jsonata"
- }
- ],
- "action": "",
- "property": "",
- "from": "",
- "to": "",
- "reg": false,
- "x": 400,
- "y": 740,
- "wires": [
- [
- "fbd442d8.cb273"
- ]
- ]
- },
- {
- "id": "f6d6be6a.efb4c",
- "type": "function",
- "z": "cfd9159c.6f73e8",
- "name": "Buffer to String",
- "func": "msg.payload = msg.payload.toString();\nreturn msg;",
- "outputs": 1,
- "noerr": 0,
- "initialize": "",
- "finalize": "",
- "x": 540,
- "y": 640,
- "wires": [
- [
- "33df08b.753e9f8"
- ]
- ]
- },
- {
- "id": "e1412987.91dcc8",
- "type": "comment",
- "z": "cfd9159c.6f73e8",
- "name": "Send reply to client of TCP connection",
- "info": "Input message from `TCP in` node may be passed to `TCP out` node to return a reply to client.\n",
- "x": 230,
- "y": 580,
- "wires": []
- },
- {
- "id": "5f43905f.2425d",
- "type": "comment",
- "z": "cfd9159c.6f73e8",
- "name": "↓ Accept request",
- "info": "",
- "x": 220,
- "y": 700,
- "wires": []
- },
- {
- "id": "a6f57329.c87c6",
- "type": "comment",
- "z": "cfd9159c.6f73e8",
- "name": "↓ Reply result",
- "info": "",
- "x": 550,
- "y": 700,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/udp/01 - Transfer data using UDP protocol.json b/packages/node_modules/@node-red/nodes/examples/network/udp/01 - Transfer data using UDP protocol.json
index d53a05da8..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/udp/01 - Transfer data using UDP protocol.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/udp/01 - Transfer data using UDP protocol.json
@@ -1,92 +0,0 @@
-[
- {
- "id": "73279b5.5151664",
- "type": "udp in",
- "z": "92236e19.9e4cb",
- "name": "",
- "iface": "",
- "port": "1881",
- "ipv": "udp4",
- "multicast": "false",
- "group": "",
- "datatype": "utf8",
- "x": 220,
- "y": 220,
- "wires": [
- [
- "d98b60d3.7331e"
- ]
- ]
- },
- {
- "id": "fb19b98f.d5aa58",
- "type": "udp out",
- "z": "92236e19.9e4cb",
- "name": "",
- "addr": "localhost",
- "iface": "",
- "port": "1881",
- "ipv": "udp4",
- "outport": "",
- "base64": false,
- "multicast": "false",
- "x": 410,
- "y": 160,
- "wires": []
- },
- {
- "id": "33f18897.35d5b8",
- "type": "inject",
- "z": "92236e19.9e4cb",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 230,
- "y": 160,
- "wires": [
- [
- "fb19b98f.d5aa58"
- ]
- ]
- },
- {
- "id": "d98b60d3.7331e",
- "type": "debug",
- "z": "92236e19.9e4cb",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 370,
- "y": 220,
- "wires": []
- },
- {
- "id": "f86495aa.8a9848",
- "type": "comment",
- "z": "92236e19.9e4cb",
- "name": "Transfer data using UDP protocol",
- "info": "`UDP in` node can be used to receive data from `UDP out` node using UDP protocol.",
- "x": 230,
- "y": 100,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/websocket/01 - Connect to websocket in server.json b/packages/node_modules/@node-red/nodes/examples/network/websocket/01 - Connect to websocket in server.json
index 5abc5c223..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/websocket/01 - Connect to websocket in server.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/websocket/01 - Connect to websocket in server.json
@@ -1,96 +0,0 @@
-[
- {
- "id": "13410716.69c9d9",
- "type": "websocket in",
- "z": "a8360b47.074ec8",
- "name": "",
- "server": "89db22b6.9aa36",
- "client": "",
- "x": 280,
- "y": 180,
- "wires": [
- [
- "c2541f10.59544"
- ]
- ]
- },
- {
- "id": "c2541f10.59544",
- "type": "debug",
- "z": "a8360b47.074ec8",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 430,
- "y": 180,
- "wires": []
- },
- {
- "id": "6788839e.04576c",
- "type": "inject",
- "z": "a8360b47.074ec8",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 290,
- "y": 120,
- "wires": [
- [
- "438c232a.06c2cc"
- ]
- ]
- },
- {
- "id": "438c232a.06c2cc",
- "type": "websocket out",
- "z": "a8360b47.074ec8",
- "name": "",
- "server": "",
- "client": "63620788.bda128",
- "x": 500,
- "y": 120,
- "wires": []
- },
- {
- "id": "c88f97a9.4410f8",
- "type": "comment",
- "z": "a8360b47.074ec8",
- "name": "Connect to websocket in server",
- "info": "`websocket out` node can connect to web socket server. `websocket in` node can serve a web socket server.\n",
- "x": 290,
- "y": 80,
- "wires": []
- },
- {
- "id": "89db22b6.9aa36",
- "type": "websocket-listener",
- "path": "/ws1",
- "wholemsg": "false"
- },
- {
- "id": "63620788.bda128",
- "type": "websocket-client",
- "path": "ws://localhost:1880/ws1",
- "tls": "",
- "wholemsg": "false"
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/network/websocket/02 - Connect to websocket out server.json b/packages/node_modules/@node-red/nodes/examples/network/websocket/02 - Connect to websocket out server.json
index 667af1a95..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/network/websocket/02 - Connect to websocket out server.json
+++ b/packages/node_modules/@node-red/nodes/examples/network/websocket/02 - Connect to websocket out server.json
@@ -1,96 +0,0 @@
-[
- {
- "id": "759c0b2b.8a0484",
- "type": "websocket in",
- "z": "a8360b47.074ec8",
- "name": "",
- "server": "",
- "client": "1d80bd86.93f372",
- "x": 340,
- "y": 520,
- "wires": [
- [
- "1f7a7454.cb65ec"
- ]
- ]
- },
- {
- "id": "1f7a7454.cb65ec",
- "type": "debug",
- "z": "a8360b47.074ec8",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 550,
- "y": 520,
- "wires": []
- },
- {
- "id": "aa2fe781.e92b28",
- "type": "inject",
- "z": "a8360b47.074ec8",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Goodbye, World!",
- "payloadType": "str",
- "x": 300,
- "y": 460,
- "wires": [
- [
- "f8bdbc9b.d82dd"
- ]
- ]
- },
- {
- "id": "f8bdbc9b.d82dd",
- "type": "websocket out",
- "z": "a8360b47.074ec8",
- "name": "",
- "server": "40bd4295.3e4ecc",
- "client": "",
- "x": 460,
- "y": 460,
- "wires": []
- },
- {
- "id": "c3fbc602.2e7f08",
- "type": "comment",
- "z": "a8360b47.074ec8",
- "name": "Connect to websocket out server",
- "info": "`websocket out` node can connect to web socket server. `websocket in` node can serve a web socket server.\n",
- "x": 290,
- "y": 420,
- "wires": []
- },
- {
- "id": "1d80bd86.93f372",
- "type": "websocket-client",
- "path": "ws://localhost:1880/ws2",
- "tls": "",
- "wholemsg": "false"
- },
- {
- "id": "40bd4295.3e4ecc",
- "type": "websocket-listener",
- "path": "/ws2",
- "wholemsg": "false"
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/01 - Parse CSV with default column name as message sequence.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/01 - Parse CSV with default column name as message sequence.json
index ed75294b1..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/01 - Parse CSV with default column name as message sequence.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/01 - Parse CSV with default column name as message sequence.json
@@ -1,99 +0,0 @@
-[
- {
- "id": "330f4888.cccb28",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 260,
- "y": 180,
- "wires": [
- [
- "ed11f8d6.5e3c88"
- ]
- ]
- },
- {
- "id": "a0288b44.71d488",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": "",
- "hdrout": "none",
- "multi": "one",
- "ret": "\\n",
- "temp": "",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 600,
- "y": 180,
- "wires": [
- [
- "369cbe42.4af9f2"
- ]
- ]
- },
- {
- "id": "ed11f8d6.5e3c88",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "CSV data",
- "field": "payload",
- "fieldType": "msg",
- "format": "text",
- "syntax": "mustache",
- "template": "Apple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
- "output": "str",
- "x": 430,
- "y": 180,
- "wires": [
- [
- "a0288b44.71d488"
- ]
- ]
- },
- {
- "id": "369cbe42.4af9f2",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 780,
- "y": 180,
- "wires": []
- },
- {
- "id": "783cfaa6.52fbe4",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Parse CSV with default column name as messages",
- "info": "CSV node can parse input CSV data.\nParsed CSV record can be sent as a message sequence.\nEach message payload points to an object with `col`*N* as a key and CSV value as a value.\n",
- "x": 330,
- "y": 120,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/02 - Parse CSV with default column name as array.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/02 - Parse CSV with default column name as array.json
index 85a03e486..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/02 - Parse CSV with default column name as array.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/02 - Parse CSV with default column name as array.json
@@ -1,99 +0,0 @@
-[
- {
- "id": "98c9d44d.4457b8",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 260,
- "y": 360,
- "wires": [
- [
- "65476517.3d760c"
- ]
- ]
- },
- {
- "id": "76df98f7.0dcd08",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": "",
- "hdrout": "none",
- "multi": "mult",
- "ret": "\\n",
- "temp": "",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 600,
- "y": 360,
- "wires": [
- [
- "557979e0.e6b588"
- ]
- ]
- },
- {
- "id": "65476517.3d760c",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "CSV data",
- "field": "payload",
- "fieldType": "msg",
- "format": "text",
- "syntax": "mustache",
- "template": "Apple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
- "output": "str",
- "x": 430,
- "y": 360,
- "wires": [
- [
- "76df98f7.0dcd08"
- ]
- ]
- },
- {
- "id": "557979e0.e6b588",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 780,
- "y": 360,
- "wires": []
- },
- {
- "id": "187f4ab3.4c9ab5",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Parse CSV with default column name as array",
- "info": "CSV node can send a single message with array of parsed CSV records.\nEach element of the array consists of objects with key-value pair.",
- "x": 320,
- "y": 300,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/03 - Parse CSV with specified column name as message sequence.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/03 - Parse CSV with specified column name as message sequence.json
index 327a25313..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/03 - Parse CSV with specified column name as message sequence.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/03 - Parse CSV with specified column name as message sequence.json
@@ -1,99 +0,0 @@
-[
- {
- "id": "1216e95b.1b1e87",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 260,
- "y": 560,
- "wires": [
- [
- "e41ffbbc.de2ed8"
- ]
- ]
- },
- {
- "id": "286828bc.9233c8",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": "",
- "hdrout": "none",
- "multi": "one",
- "ret": "\\n",
- "temp": "kind,price,origin",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 600,
- "y": 560,
- "wires": [
- [
- "9d8218c.5550ee8"
- ]
- ]
- },
- {
- "id": "e41ffbbc.de2ed8",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "CSV data",
- "field": "payload",
- "fieldType": "msg",
- "format": "text",
- "syntax": "mustache",
- "template": "Apple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
- "output": "str",
- "x": 430,
- "y": 560,
- "wires": [
- [
- "286828bc.9233c8"
- ]
- ]
- },
- {
- "id": "9d8218c.5550ee8",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 780,
- "y": 560,
- "wires": []
- },
- {
- "id": "aaa1ee8f.21e2c",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Parse CSV with specified column name as messages",
- "info": "CSV node can specify column name of parsed objects in its settings panel.",
- "x": 340,
- "y": 500,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/04 - Parse CSV with column name in first row as message sequence.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/04 - Parse CSV with column name in first row as message sequence.json
index e287b57e7..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/04 - Parse CSV with column name in first row as message sequence.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/04 - Parse CSV with column name in first row as message sequence.json
@@ -1,99 +0,0 @@
-[
- {
- "id": "24093558.0315aa",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 260,
- "y": 740,
- "wires": [
- [
- "80abaee1.5fa7f"
- ]
- ]
- },
- {
- "id": "d4d2ca3f.1d9488",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": true,
- "hdrout": "none",
- "multi": "one",
- "ret": "\\n",
- "temp": "",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 600,
- "y": 740,
- "wires": [
- [
- "b52791c3.08967"
- ]
- ]
- },
- {
- "id": "80abaee1.5fa7f",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "CSV data",
- "field": "payload",
- "fieldType": "msg",
- "format": "text",
- "syntax": "mustache",
- "template": "kind,price,origin\nApple,100,Canada\nOrange,120,USA\nBanana,80,Philippines",
- "output": "str",
- "x": 430,
- "y": 740,
- "wires": [
- [
- "d4d2ca3f.1d9488"
- ]
- ]
- },
- {
- "id": "b52791c3.08967",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 780,
- "y": 740,
- "wires": []
- },
- {
- "id": "85091361.85644",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Parse CSV with column name in first row as messages",
- "info": "CSV node can use first row of input CSV text as a column name of each record object.\n",
- "x": 340,
- "y": 680,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/05 - Convert JavaScript object to CSV.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/05 - Convert JavaScript object to CSV.json
index a97656085..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/05 - Convert JavaScript object to CSV.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/05 - Convert JavaScript object to CSV.json
@@ -1,99 +0,0 @@
-[
- {
- "id": "9e93169c.b763a8",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert JavaScript object to CSV",
- "info": "CSV node can convert a JavaScript object to CSV text.\nEach object contains key-value pair of specified properties.\n",
- "x": 270,
- "y": 860,
- "wires": []
- },
- {
- "id": "8ca41fee.3303d",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 260,
- "y": 920,
- "wires": [
- [
- "c466905b.e8c61"
- ]
- ]
- },
- {
- "id": "65146d20.d78204",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": false,
- "hdrout": "none",
- "multi": "one",
- "ret": "\\n",
- "temp": "kind,price",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 600,
- "y": 920,
- "wires": [
- [
- "92e99e67.a37d8"
- ]
- ]
- },
- {
- "id": "c466905b.e8c61",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
- "output": "json",
- "x": 430,
- "y": 920,
- "wires": [
- [
- "65146d20.d78204"
- ]
- ]
- },
- {
- "id": "92e99e67.a37d8",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 780,
- "y": 920,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/06 - Convert JavaScript object to CSV.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/06 - Convert JavaScript object to CSV.json
index 0266dbe49..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/06 - Convert JavaScript object to CSV.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/06 - Convert JavaScript object to CSV.json
@@ -1,99 +0,0 @@
-[
- {
- "id": "e89019c5.70ae78",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert array of JavaScript objects to CSV",
- "info": "CSV node can convert an array of JavaScript objects to multi-line CSV text.",
- "x": 300,
- "y": 1020,
- "wires": []
- },
- {
- "id": "bd0d82ed.7b28",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 260,
- "y": 1080,
- "wires": [
- [
- "1d857b8d.3a4014"
- ]
- ]
- },
- {
- "id": "66a37667.16ebd8",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": false,
- "hdrout": "none",
- "multi": "one",
- "ret": "\\n",
- "temp": "kind,price",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 600,
- "y": 1080,
- "wires": [
- [
- "859725fd.dc93d8"
- ]
- ]
- },
- {
- "id": "1d857b8d.3a4014",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "[\n {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n },\n {\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n },\n {\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n }\n]",
- "output": "json",
- "x": 430,
- "y": 1080,
- "wires": [
- [
- "66a37667.16ebd8"
- ]
- ]
- },
- {
- "id": "859725fd.dc93d8",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 780,
- "y": 1080,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/07 - Convert array of JavaScript objects to CSV with column name header.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/07 - Convert array of JavaScript objects to CSV with column name header.json
index b1b337a06..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/07 - Convert array of JavaScript objects to CSV with column name header.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/07 - Convert array of JavaScript objects to CSV with column name header.json
@@ -1,99 +0,0 @@
-[
- {
- "id": "2ebdd51e.c5d17a",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert array of JavaScript objects to CSV with column name header",
- "info": "CSV node can convert an array of JavaScript objects to multi-line CSV text with column name header at first line.",
- "x": 390,
- "y": 1200,
- "wires": []
- },
- {
- "id": "2b4d538d.ada07c",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 260,
- "y": 1260,
- "wires": [
- [
- "3e5c9e8.5065b62"
- ]
- ]
- },
- {
- "id": "db02c7be.0984e8",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": false,
- "hdrout": "all",
- "multi": "one",
- "ret": "\\n",
- "temp": "kind,price",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 600,
- "y": 1260,
- "wires": [
- [
- "61f8b772.ddb1f8"
- ]
- ]
- },
- {
- "id": "3e5c9e8.5065b62",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "[\n {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n },\n {\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n },\n {\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n }\n]",
- "output": "json",
- "x": 430,
- "y": 1260,
- "wires": [
- [
- "db02c7be.0984e8"
- ]
- ]
- },
- {
- "id": "61f8b772.ddb1f8",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 780,
- "y": 1260,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/08 - Specify column names in input message.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/08 - Specify column names in input message.json
index 85901ba36..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/08 - Specify column names in input message.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/08 - Specify column names in input message.json
@@ -1,126 +0,0 @@
-[
- {
- "id": "b05816ab.7f2b08",
- "type": "comment",
- "z": "c6ffdacd.d887e8",
- "name": "Specify column names in input message",
- "info": "Column names can be specified by `columns` property of incoming message.\n",
- "x": 240,
- "y": 200,
- "wires": []
- },
- {
- "id": "39205b5c.690684",
- "type": "inject",
- "z": "c6ffdacd.d887e8",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 200,
- "y": 260,
- "wires": [
- [
- "526b59ba.2fa068"
- ]
- ]
- },
- {
- "id": "b78a407e.2d083",
- "type": "csv",
- "z": "c6ffdacd.d887e8",
- "name": "",
- "sep": ",",
- "hdrin": false,
- "hdrout": "all",
- "multi": "one",
- "ret": "\\n",
- "temp": "",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 750,
- "y": 260,
- "wires": [
- [
- "8b7084dd.986f68"
- ]
- ]
- },
- {
- "id": "526b59ba.2fa068",
- "type": "template",
- "z": "c6ffdacd.d887e8",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "[\n {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n },\n {\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n },\n {\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n }\n]",
- "output": "json",
- "x": 370,
- "y": 260,
- "wires": [
- [
- "b204077a.227778"
- ]
- ]
- },
- {
- "id": "8b7084dd.986f68",
- "type": "debug",
- "z": "c6ffdacd.d887e8",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 930,
- "y": 260,
- "wires": []
- },
- {
- "id": "b204077a.227778",
- "type": "change",
- "z": "c6ffdacd.d887e8",
- "name": "",
- "rules": [
- {
- "t": "set",
- "p": "columns",
- "pt": "msg",
- "to": "kind,price",
- "tot": "str"
- }
- ],
- "action": "",
- "property": "",
- "from": "",
- "to": "",
- "reg": false,
- "x": 570,
- "y": 260,
- "wires": [
- [
- "b78a407e.2d083"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/csv/09 - Send column name when reset property set.json b/packages/node_modules/@node-red/nodes/examples/parser/csv/09 - Send column name when reset property set.json
index 81d9b4730..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/csv/09 - Send column name when reset property set.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/csv/09 - Send column name when reset property set.json
@@ -1,200 +0,0 @@
-[
- {
- "id": "1ae28939.9f5fc7",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Send column name when reset property set",
- "info": "CSV node can send column names at first or `reset` property exists in input message.",
- "x": 310,
- "y": 1540,
- "wires": []
- },
- {
- "id": "c16ad95b.4f9ac8",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "Apple",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 250,
- "y": 1600,
- "wires": [
- [
- "7f7bfc72.aed104"
- ]
- ]
- },
- {
- "id": "870620b9.95343",
- "type": "csv",
- "z": "4b63452d.672afc",
- "name": "",
- "sep": ",",
- "hdrin": false,
- "hdrout": "once",
- "multi": "one",
- "ret": "\\n",
- "temp": "kind,price",
- "skip": "0",
- "strings": true,
- "include_empty_strings": "",
- "include_null_values": "",
- "x": 650,
- "y": 1720,
- "wires": [
- [
- "d960de42.619c7"
- ]
- ]
- },
- {
- "id": "7f7bfc72.aed104",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
- "output": "json",
- "x": 470,
- "y": 1600,
- "wires": [
- [
- "870620b9.95343"
- ]
- ]
- },
- {
- "id": "d960de42.619c7",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 830,
- "y": 1720,
- "wires": []
- },
- {
- "id": "6f8296e.f95ca68",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "Orange",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 250,
- "y": 1660,
- "wires": [
- [
- "c37d0dfa.ec1ab"
- ]
- ]
- },
- {
- "id": "c37d0dfa.ec1ab",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Orange\",\n \"price\": 120,\n \"origin\": \"USA\"\n}\n",
- "output": "json",
- "x": 470,
- "y": 1660,
- "wires": [
- [
- "870620b9.95343"
- ]
- ]
- },
- {
- "id": "35209fe2.16926",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "Banana & reset",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- },
- {
- "p": "reset",
- "v": "",
- "vt": "date"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 280,
- "y": 1720,
- "wires": [
- [
- "afd4e6b3.624a28"
- ]
- ]
- },
- {
- "id": "afd4e6b3.624a28",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Banana\",\n \"price\": 80,\n \"origin\": \"Philippines\"\n}",
- "output": "json",
- "x": 470,
- "y": 1720,
- "wires": [
- [
- "870620b9.95343"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/html/01 - Extract array of HTML element by CSS selector.json b/packages/node_modules/@node-red/nodes/examples/parser/html/01 - Extract array of HTML element by CSS selector.json
index 14ef21214..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/html/01 - Extract array of HTML element by CSS selector.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/html/01 - Extract array of HTML element by CSS selector.json
@@ -1,94 +0,0 @@
-[
- {
- "id": "8c5224a6.201b88",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 220,
- "y": 180,
- "wires": [
- [
- "d6c67e51.0d709"
- ]
- ]
- },
- {
- "id": "d6c67e51.0d709",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "HTML text",
- "field": "payload",
- "fieldType": "msg",
- "format": "handlebars",
- "syntax": "plain",
- "template": "\n \n List of Fruits \n \n \n \n Apple \n Orange \n Banana \n \n \n\n",
- "output": "str",
- "x": 390,
- "y": 180,
- "wires": [
- [
- "599a1155.61a5c"
- ]
- ]
- },
- {
- "id": "b0d5cd89.338df",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Extract array of HTML element by CSS selector",
- "info": "HTML node can be used to extract elements in HTML document as an array using CSS selector.",
- "x": 280,
- "y": 120,
- "wires": []
- },
- {
- "id": "599a1155.61a5c",
- "type": "html",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "outproperty": "payload",
- "tag": ".Item",
- "ret": "html",
- "as": "single",
- "x": 550,
- "y": 180,
- "wires": [
- [
- "942b23d1.cce09"
- ]
- ]
- },
- {
- "id": "942b23d1.cce09",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 710,
- "y": 180,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/html/02 - Extract sequence of HTML element by CSS selector.json b/packages/node_modules/@node-red/nodes/examples/parser/html/02 - Extract sequence of HTML element by CSS selector.json
index ccd3bc782..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/html/02 - Extract sequence of HTML element by CSS selector.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/html/02 - Extract sequence of HTML element by CSS selector.json
@@ -1,94 +0,0 @@
-[
- {
- "id": "a44973e8.6319b",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 220,
- "y": 360,
- "wires": [
- [
- "de1b012e.96ec3"
- ]
- ]
- },
- {
- "id": "de1b012e.96ec3",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "HTML text",
- "field": "payload",
- "fieldType": "msg",
- "format": "handlebars",
- "syntax": "plain",
- "template": "\n \n List of Fruits \n \n \n \n Apple \n Orange \n Banana \n \n \n\n",
- "output": "str",
- "x": 390,
- "y": 360,
- "wires": [
- [
- "cee70712.6f3538"
- ]
- ]
- },
- {
- "id": "99e32bc7.c8e508",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Extract sequence of HTML element by CSS selector",
- "info": "HTML node can be used to extract elements in HTML document as a messege sequence using CSS selector.",
- "x": 290,
- "y": 300,
- "wires": []
- },
- {
- "id": "cee70712.6f3538",
- "type": "html",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "outproperty": "payload",
- "tag": ".Item",
- "ret": "html",
- "as": "multi",
- "x": 550,
- "y": 360,
- "wires": [
- [
- "17f25482.d4b56b"
- ]
- ]
- },
- {
- "id": "17f25482.d4b56b",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 710,
- "y": 360,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/html/03 - Extract array of HTML element by CSS selector specified in message.json b/packages/node_modules/@node-red/nodes/examples/parser/html/03 - Extract array of HTML element by CSS selector specified in message.json
index ad2400ef6..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/html/03 - Extract array of HTML element by CSS selector specified in message.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/html/03 - Extract array of HTML element by CSS selector specified in message.json
@@ -1,121 +0,0 @@
-[
- {
- "id": "653ce9aa.b6a1c8",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 220,
- "y": 560,
- "wires": [
- [
- "52a16f7f.447d8"
- ]
- ]
- },
- {
- "id": "52a16f7f.447d8",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "HTML text",
- "field": "payload",
- "fieldType": "msg",
- "format": "handlebars",
- "syntax": "plain",
- "template": "\n \n List of Fruits \n \n \n \n Apple \n Orange \n Banana \n \n \n\n",
- "output": "str",
- "x": 390,
- "y": 560,
- "wires": [
- [
- "a52319c3.89b008"
- ]
- ]
- },
- {
- "id": "8bc35379.31d99",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Extract array of HTML element by CSS selector specified in message",
- "info": "CSS selector for HTML node can be specified by `select` property of input message.",
- "x": 350,
- "y": 500,
- "wires": []
- },
- {
- "id": "9c49de8a.bad25",
- "type": "html",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "outproperty": "payload",
- "tag": "",
- "ret": "html",
- "as": "single",
- "x": 730,
- "y": 560,
- "wires": [
- [
- "d4f4b987.278a68"
- ]
- ]
- },
- {
- "id": "d4f4b987.278a68",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 890,
- "y": 560,
- "wires": []
- },
- {
- "id": "a52319c3.89b008",
- "type": "change",
- "z": "4b63452d.672afc",
- "name": "",
- "rules": [
- {
- "t": "set",
- "p": "select",
- "pt": "msg",
- "to": ".Item",
- "tot": "str"
- }
- ],
- "action": "",
- "property": "",
- "from": "",
- "to": "",
- "reg": false,
- "x": 560,
- "y": 560,
- "wires": [
- [
- "9c49de8a.bad25"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/json/01 - Convert JSON string to JavaScript object.json b/packages/node_modules/@node-red/nodes/examples/parser/json/01 - Convert JSON string to JavaScript object.json
index c95e71a7d..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/json/01 - Convert JSON string to JavaScript object.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/json/01 - Convert JSON string to JavaScript object.json
@@ -1,92 +0,0 @@
-[
- {
- "id": "9976e95d.2f8398",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 240,
- "y": 180,
- "wires": [
- [
- "d94fc083.49d87"
- ]
- ]
- },
- {
- "id": "6684abb1.8eb454",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert JSON string to JS object",
- "info": "JSON node can convert JSON string to JavaScript object.",
- "x": 250,
- "y": 120,
- "wires": []
- },
- {
- "id": "d94fc083.49d87",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JSON string",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
- "output": "str",
- "x": 410,
- "y": 180,
- "wires": [
- [
- "1a3dc54a.78598b"
- ]
- ]
- },
- {
- "id": "8950a55d.023988",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 730,
- "y": 180,
- "wires": []
- },
- {
- "id": "1a3dc54a.78598b",
- "type": "json",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "action": "",
- "pretty": false,
- "x": 570,
- "y": 180,
- "wires": [
- [
- "8950a55d.023988"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/json/02 - Convert JavaScript object to JSON string.json b/packages/node_modules/@node-red/nodes/examples/parser/json/02 - Convert JavaScript object to JSON string.json
index a10cc75b9..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/json/02 - Convert JavaScript object to JSON string.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/json/02 - Convert JavaScript object to JSON string.json
@@ -1,92 +0,0 @@
-[
- {
- "id": "cb13761f.56c328",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 240,
- "y": 380,
- "wires": [
- [
- "c607642a.78c3c8"
- ]
- ]
- },
- {
- "id": "180b1e22.0074e2",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert JS object to JSON string",
- "info": "JSON node can convert JavaScript object to JSON string.",
- "x": 250,
- "y": 320,
- "wires": []
- },
- {
- "id": "c607642a.78c3c8",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
- "output": "json",
- "x": 400,
- "y": 380,
- "wires": [
- [
- "bf309844.fa12e8"
- ]
- ]
- },
- {
- "id": "5b6b130b.72a14c",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 730,
- "y": 380,
- "wires": []
- },
- {
- "id": "bf309844.fa12e8",
- "type": "json",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "action": "",
- "pretty": false,
- "x": 570,
- "y": 380,
- "wires": [
- [
- "5b6b130b.72a14c"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/json/03 - Validate input JSON string.json b/packages/node_modules/@node-red/nodes/examples/parser/json/03 - Validate input JSON string.json
index 6271f00c6..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/json/03 - Validate input JSON string.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/json/03 - Validate input JSON string.json
@@ -1,160 +0,0 @@
-[
- {
- "id": "2b18621b.e2670e",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "OK",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 230,
- "y": 580,
- "wires": [
- [
- "5986faee.aef954"
- ]
- ]
- },
- {
- "id": "59acf99.9a92308",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Validate input JSON string",
- "info": "JSON node can validate input JSON string using [JSON schema](https://json-schema.org/) when converting to JavaScript object.",
- "x": 230,
- "y": 520,
- "wires": []
- },
- {
- "id": "5986faee.aef954",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JSON string",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
- "output": "str",
- "x": 410,
- "y": 580,
- "wires": [
- [
- "f8a67c6d.4f1f1"
- ]
- ]
- },
- {
- "id": "ca27c92c.ad7cb8",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "payload",
- "targetType": "msg",
- "statusVal": "",
- "statusType": "auto",
- "x": 910,
- "y": 580,
- "wires": []
- },
- {
- "id": "2fad9978.ea1916",
- "type": "json",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "action": "",
- "pretty": false,
- "x": 750,
- "y": 580,
- "wires": [
- [
- "ca27c92c.ad7cb8"
- ]
- ]
- },
- {
- "id": "f8a67c6d.4f1f1",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "Schema",
- "field": "schema",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"type\": \"object\",\n \"properties\": {\n \"kind\": {\n \"type\": \"string\"\n },\n \"price\": {\n \"type\": \"number\"\n },\n \"origin\": {\n \"type\": \"string\"\n }\n }\n}",
- "output": "json",
- "x": 590,
- "y": 580,
- "wires": [
- [
- "2fad9978.ea1916"
- ]
- ]
- },
- {
- "id": "8337e847.ac18d8",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "NG",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 230,
- "y": 660,
- "wires": [
- [
- "fa14d8bf.1ac938"
- ]
- ]
- },
- {
- "id": "fa14d8bf.1ac938",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JSON string",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Apple\",\n \"price\": \"100\",\n \"origin\": \"Canada\"\n}",
- "output": "str",
- "x": 410,
- "y": 660,
- "wires": [
- [
- "f8a67c6d.4f1f1"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/xml/01 - Convert JavaScript object to XML.json b/packages/node_modules/@node-red/nodes/examples/parser/xml/01 - Convert JavaScript object to XML.json
index 3a97c8498..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/xml/01 - Convert JavaScript object to XML.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/xml/01 - Convert JavaScript object to XML.json
@@ -1,92 +0,0 @@
-[
- {
- "id": "82f1bd0b.43474",
- "type": "xml",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "attr": "",
- "chr": "",
- "x": 530,
- "y": 180,
- "wires": [
- [
- "1cd4ad02.9a5423"
- ]
- ]
- },
- {
- "id": "84222b92.d65d18",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 200,
- "y": 180,
- "wires": [
- [
- "cdd1c154.3a655"
- ]
- ]
- },
- {
- "id": "7b014430.dfd94c",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert JavaScript object to XML",
- "info": "XML node can convert JavaScript object to XML string.",
- "x": 240,
- "y": 120,
- "wires": []
- },
- {
- "id": "1cd4ad02.9a5423",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 690,
- "y": 180,
- "wires": []
- },
- {
- "id": "cdd1c154.3a655",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n}",
- "output": "json",
- "x": 360,
- "y": 180,
- "wires": [
- [
- "82f1bd0b.43474"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/xml/02 - Convert XML to JavaScript object.json b/packages/node_modules/@node-red/nodes/examples/parser/xml/02 - Convert XML to JavaScript object.json
index 5e46428ef..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/xml/02 - Convert XML to JavaScript object.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/xml/02 - Convert XML to JavaScript object.json
@@ -1,92 +0,0 @@
-[
- {
- "id": "93e423a9.a407d",
- "type": "xml",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "attr": "",
- "chr": "",
- "x": 530,
- "y": 360,
- "wires": [
- [
- "2d0dde7e.a50082"
- ]
- ]
- },
- {
- "id": "ba1dab90.8d1da8",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 200,
- "y": 360,
- "wires": [
- [
- "16617f26.14ced1"
- ]
- ]
- },
- {
- "id": "a9f97b00.57d658",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert XML to JavaScript object",
- "info": "XML node can convert XML string to JavaScript object.",
- "x": 240,
- "y": 300,
- "wires": []
- },
- {
- "id": "2d0dde7e.a50082",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 690,
- "y": 360,
- "wires": []
- },
- {
- "id": "16617f26.14ced1",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "XML string",
- "field": "payload",
- "fieldType": "msg",
- "format": "html",
- "syntax": "plain",
- "template": "\n\n Apple \n 100 \n Canada \n ",
- "output": "str",
- "x": 370,
- "y": 360,
- "wires": [
- [
- "93e423a9.a407d"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/xml/03 - Control conversion using options property.json b/packages/node_modules/@node-red/nodes/examples/parser/xml/03 - Control conversion using options property.json
index 7a3c39f7e..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/xml/03 - Control conversion using options property.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/xml/03 - Control conversion using options property.json
@@ -1,119 +0,0 @@
-[
- {
- "id": "581bd648.636628",
- "type": "xml",
- "z": "4b63452d.672afc",
- "name": "",
- "property": "payload",
- "attr": "",
- "chr": "",
- "x": 710,
- "y": 540,
- "wires": [
- [
- "b74237dc.1e5028"
- ]
- ]
- },
- {
- "id": "d0899f9b.f1ac6",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 200,
- "y": 540,
- "wires": [
- [
- "f04ffb9a.68edb8"
- ]
- ]
- },
- {
- "id": "8a214c05.dc61f",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Control conversion using options property",
- "info": "XML node can control conversion by setting `options` property (defined by [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md#options)) in input message.",
- "x": 260,
- "y": 480,
- "wires": []
- },
- {
- "id": "b74237dc.1e5028",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 870,
- "y": 540,
- "wires": []
- },
- {
- "id": "f04ffb9a.68edb8",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "XML string",
- "field": "payload",
- "fieldType": "msg",
- "format": "html",
- "syntax": "plain",
- "template": "\n\n Apple \n 100 \n Canada \n ",
- "output": "str",
- "x": 370,
- "y": 540,
- "wires": [
- [
- "fedf79.5889c088"
- ]
- ]
- },
- {
- "id": "fedf79.5889c088",
- "type": "change",
- "z": "4b63452d.672afc",
- "name": "set options",
- "rules": [
- {
- "t": "set",
- "p": "options",
- "pt": "msg",
- "to": "{\"explicitArray\":false}",
- "tot": "json"
- }
- ],
- "action": "",
- "property": "",
- "from": "",
- "to": "",
- "reg": false,
- "x": 550,
- "y": 540,
- "wires": [
- [
- "581bd648.636628"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/yaml/01 - Convert JavaScript object to YAML.json b/packages/node_modules/@node-red/nodes/examples/parser/yaml/01 - Convert JavaScript object to YAML.json
index d751a8731..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/yaml/01 - Convert JavaScript object to YAML.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/yaml/01 - Convert JavaScript object to YAML.json
@@ -1,90 +0,0 @@
-[
- {
- "id": "84222b92.d65d18",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 200,
- "y": 180,
- "wires": [
- [
- "cdd1c154.3a655"
- ]
- ]
- },
- {
- "id": "7b014430.dfd94c",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert JavaScript object to YAML",
- "info": "YAML node can convert JavaScript object to YAML string.",
- "x": 240,
- "y": 120,
- "wires": []
- },
- {
- "id": "1cd4ad02.9a5423",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 670,
- "y": 180,
- "wires": []
- },
- {
- "id": "cdd1c154.3a655",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "JS object",
- "field": "payload",
- "fieldType": "msg",
- "format": "json",
- "syntax": "plain",
- "template": "{\n \"fruits\" : {\n \"kind\": \"Apple\",\n \"price\": 100,\n \"origin\": \"Canada\"\n }\n}",
- "output": "json",
- "x": 360,
- "y": 180,
- "wires": [
- [
- "aaf0100b.16628"
- ]
- ]
- },
- {
- "id": "aaf0100b.16628",
- "type": "yaml",
- "z": "4b63452d.672afc",
- "property": "payload",
- "name": "",
- "x": 510,
- "y": 180,
- "wires": [
- [
- "1cd4ad02.9a5423"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/parser/yaml/02 - Convert YAML to JavaScript object.json b/packages/node_modules/@node-red/nodes/examples/parser/yaml/02 - Convert YAML to JavaScript object.json
index d80e0d144..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/parser/yaml/02 - Convert YAML to JavaScript object.json
+++ b/packages/node_modules/@node-red/nodes/examples/parser/yaml/02 - Convert YAML to JavaScript object.json
@@ -1,90 +0,0 @@
-[
- {
- "id": "ba1dab90.8d1da8",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 200,
- "y": 360,
- "wires": [
- [
- "16617f26.14ced1"
- ]
- ]
- },
- {
- "id": "a9f97b00.57d658",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Convert YAML to JavaScript object",
- "info": "YAML node can convert YAML string to JavaScript object.",
- "x": 240,
- "y": 300,
- "wires": []
- },
- {
- "id": "2d0dde7e.a50082",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 690,
- "y": 360,
- "wires": []
- },
- {
- "id": "16617f26.14ced1",
- "type": "template",
- "z": "4b63452d.672afc",
- "name": "YAML string",
- "field": "payload",
- "fieldType": "msg",
- "format": "yaml",
- "syntax": "plain",
- "template": "fruits:\n kind: Apple\n price: 100\n origin: Canada",
- "output": "str",
- "x": 370,
- "y": 360,
- "wires": [
- [
- "e2e4f862.f9d7d8"
- ]
- ]
- },
- {
- "id": "e2e4f862.f9d7d8",
- "type": "yaml",
- "z": "4b63452d.672afc",
- "property": "payload",
- "name": "",
- "x": 530,
- "y": 360,
- "wires": [
- [
- "2d0dde7e.a50082"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/sequence/sort/01 - Sort array payload.json b/packages/node_modules/@node-red/nodes/examples/sequence/sort/01 - Sort array payload.json
index 74bb99eb4..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/sequence/sort/01 - Sort array payload.json
+++ b/packages/node_modules/@node-red/nodes/examples/sequence/sort/01 - Sort array payload.json
@@ -1 +0,0 @@
-[{"id":"6451c8bb.b52278","type":"sort","z":"9f9f8c22.7e6b2","name":"","order":"ascending","as_num":false,"target":"payload","targetType":"msg","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":510,"y":160,"wires":[["cb34307c.ac1dd"]]},{"id":"638546c.38f1fb8","type":"inject","z":"9f9f8c22.7e6b2","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":160,"wires":[["db5d90ac.bbb3f"]]},{"id":"3ec02cae.012ce4","type":"comment","z":"9f9f8c22.7e6b2","name":"Sort array payload as string in ascending order","info":"","x":280,"y":100,"wires":[]},{"id":"db5d90ac.bbb3f","type":"template","z":"9f9f8c22.7e6b2","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"orange\",\n \"banana\",\n \"apple\",\n \"pear\",\n \"kiwi\"\n]","output":"json","x":370,"y":160,"wires":[["6451c8bb.b52278"]]},{"id":"cb34307c.ac1dd","type":"debug","z":"9f9f8c22.7e6b2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":160,"wires":[]},{"id":"a0de8ca4.6601f","type":"sort","z":"9f9f8c22.7e6b2","name":"","order":"ascending","as_num":false,"target":"payload","targetType":"msg","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":510,"y":480,"wires":[["ca74a53e.90fc08"]]},{"id":"23d253dc.5e990c","type":"inject","z":"9f9f8c22.7e6b2","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":480,"wires":[["4ccd5aed.ca24e4"]]},{"id":"19946d36.185313","type":"comment","z":"9f9f8c22.7e6b2","name":"Sort array payload as string","info":"","x":220,"y":420,"wires":[]},{"id":"4ccd5aed.ca24e4","type":"template","z":"9f9f8c22.7e6b2","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"1024\",\n \"86\",\n \"256\",\n \"100\",\n \"9\"\n]","output":"json","x":370,"y":480,"wires":[["a0de8ca4.6601f"]]},{"id":"ca74a53e.90fc08","type":"debug","z":"9f9f8c22.7e6b2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":480,"wires":[]},{"id":"d4b49c22.32685","type":"sort","z":"9f9f8c22.7e6b2","name":"","order":"ascending","as_num":true,"target":"payload","targetType":"msg","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":510,"y":640,"wires":[["45738f07.16416"]]},{"id":"87ce9955.924868","type":"inject","z":"9f9f8c22.7e6b2","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":640,"wires":[["30b81283.f0772e"]]},{"id":"f6e624df.703a88","type":"comment","z":"9f9f8c22.7e6b2","name":"Sort array payload as number","info":"","x":220,"y":580,"wires":[]},{"id":"30b81283.f0772e","type":"template","z":"9f9f8c22.7e6b2","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"1024\",\n \"86\",\n \"256\",\n \"100\",\n \"9\"\n]","output":"json","x":370,"y":640,"wires":[["d4b49c22.32685"]]},{"id":"45738f07.16416","type":"debug","z":"9f9f8c22.7e6b2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":640,"wires":[]},{"id":"b91c19b1.b66b18","type":"sort","z":"9f9f8c22.7e6b2","name":"","order":"ascending","as_num":false,"target":"payload","targetType":"msg","msgKey":"price","msgKeyType":"jsonata","seqKey":"payload","seqKeyType":"msg","x":510,"y":800,"wires":[["32dd80a1.226e4"]]},{"id":"adb0daa2.d85a48","type":"inject","z":"9f9f8c22.7e6b2","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":800,"wires":[["b3ee1b9e.dbf388"]]},{"id":"d1190f8b.9a74b","type":"comment","z":"9f9f8c22.7e6b2","name":"Sort array of objects payload using simple JSONata expression","info":"","x":330,"y":740,"wires":[]},{"id":"b3ee1b9e.dbf388","type":"template","z":"9f9f8c22.7e6b2","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n {\n \"name\": \"orange\", \n \"price\": 80\n },\n {\n \"name\": \"banana\",\n \"price\": 250\n },\n {\n \"name\": \"apple\",\n \"price\": 100\n },\n {\n \"name\": \"pear\",\n \"price\": 150\n },\n {\n \"name\": \"kiwi\",\n \"price\": 320\n }\n]","output":"json","x":370,"y":800,"wires":[["b91c19b1.b66b18"]]},{"id":"32dd80a1.226e4","type":"debug","z":"9f9f8c22.7e6b2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":800,"wires":[]},{"id":"735ec14e.4ed55","type":"sort","z":"9f9f8c22.7e6b2","name":"","order":"descending","as_num":false,"target":"payload","targetType":"msg","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":510,"y":320,"wires":[["e8dc4ae5.f08598"]]},{"id":"c8ce4e74.9db68","type":"inject","z":"9f9f8c22.7e6b2","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":320,"wires":[["ea0384a6.1346b8"]]},{"id":"70333397.d78f6c","type":"comment","z":"9f9f8c22.7e6b2","name":"Sort array payload as string in descending order","info":"","x":280,"y":260,"wires":[]},{"id":"ea0384a6.1346b8","type":"template","z":"9f9f8c22.7e6b2","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"orange\",\n \"banana\",\n \"apple\",\n \"pear\",\n \"kiwi\"\n]","output":"json","x":370,"y":320,"wires":[["735ec14e.4ed55"]]},{"id":"e8dc4ae5.f08598","type":"debug","z":"9f9f8c22.7e6b2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":320,"wires":[]},{"id":"e4025b79.fccdd8","type":"comment","z":"9f9f8c22.7e6b2","name":"↑ sort using object property as sorting key","info":"","x":620,"y":840,"wires":[]},{"id":"2eaa93da.543cac","type":"comment","z":"9f9f8c22.7e6b2","name":"↑ sort payload as array of number","info":"","x":600,"y":680,"wires":[]},{"id":"24da49c5.785676","type":"comment","z":"9f9f8c22.7e6b2","name":"↑ sort payload as array of string","info":"","x":590,"y":520,"wires":[]},{"id":"dc856174.29eb5","type":"comment","z":"9f9f8c22.7e6b2","name":"↑ sort payload as array of string in descending order","info":"","x":650,"y":360,"wires":[]},{"id":"4bab755b.a073dc","type":"comment","z":"9f9f8c22.7e6b2","name":"↑ sort payload as array of string in ascending order","info":"","x":650,"y":200,"wires":[]},{"id":"e947beb9.2ec5e","type":"sort","z":"9f9f8c22.7e6b2","name":"","order":"ascending","as_num":false,"target":"payload","targetType":"msg","msgKey":"$substring(\"0000\" & $string(price), -4) & name","msgKeyType":"jsonata","seqKey":"payload","seqKeyType":"msg","x":510,"y":960,"wires":[["6a4af14a.cafc4"]]},{"id":"d19d7ff5.135f2","type":"inject","z":"9f9f8c22.7e6b2","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":960,"wires":[["5eb37a3e.3c2184"]]},{"id":"91e34f52.e1413","type":"comment","z":"9f9f8c22.7e6b2","name":"Sort array of objects payload using complex JSONata expression","info":"","x":330,"y":900,"wires":[]},{"id":"5eb37a3e.3c2184","type":"template","z":"9f9f8c22.7e6b2","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n {\n \"name\": \"orange\", \n \"price\": 100\n },\n {\n \"name\": \"banana\",\n \"price\": 200\n },\n {\n \"name\": \"apple\",\n \"price\": 100\n },\n {\n \"name\": \"pear\",\n \"price\": 200\n },\n {\n \"name\": \"kiwi\",\n \"price\": 200\n }\n]","output":"json","x":370,"y":960,"wires":[["e947beb9.2ec5e"]]},{"id":"6a4af14a.cafc4","type":"debug","z":"9f9f8c22.7e6b2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":670,"y":960,"wires":[]},{"id":"1b068260.e3200e","type":"comment","z":"9f9f8c22.7e6b2","name":"↑ sort using object two property (price and name) as sorting keys","info":"","x":690,"y":1000,"wires":[]},{"id":"7ced03b9.75dd8c","type":"comment","z":"9f9f8c22.7e6b2","name":"Example: Sort Array Payload","info":"Sort node can be used to message payload that points to a JavaScript array. It can specify sort order and sort key. Sort key can be payload value or JSONata expression. If JSONata expression is used, the expression is applied to `payload` value.\n","x":180,"y":40,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/sequence/sort/02 - Sort message sequence.json b/packages/node_modules/@node-red/nodes/examples/sequence/sort/02 - Sort message sequence.json
index abcd3cfdb..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/sequence/sort/02 - Sort message sequence.json
+++ b/packages/node_modules/@node-red/nodes/examples/sequence/sort/02 - Sort message sequence.json
@@ -1 +0,0 @@
-[{"id":"60b477b9.188ce8","type":"sort","z":"62d2b20a.1a87bc","name":"","order":"ascending","as_num":false,"target":"","targetType":"seq","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":650,"y":180,"wires":[["38fcd115.f147ae"]]},{"id":"35b577bf.827978","type":"inject","z":"62d2b20a.1a87bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":180,"wires":[["5a8dfb10.5ed8b4"]]},{"id":"e8e4517b.e2139","type":"comment","z":"62d2b20a.1a87bc","name":"Sort array payload as string in ascending order","info":"Sort node can be used to message sequence that contains `parts` property. If JSONata expression is used, the expression is applied to input message.","x":280,"y":100,"wires":[]},{"id":"5a8dfb10.5ed8b4","type":"template","z":"62d2b20a.1a87bc","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"orange\",\n \"banana\",\n \"apple\",\n \"pear\",\n \"kiwi\"\n]","output":"json","x":370,"y":180,"wires":[["a509486a.9c32a8"]]},{"id":"38fcd115.f147ae","type":"debug","z":"62d2b20a.1a87bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":180,"wires":[]},{"id":"eca99b1d.c456c8","type":"comment","z":"62d2b20a.1a87bc","name":"↑ sort message sequence in ascending order","info":"","x":770,"y":220,"wires":[]},{"id":"a509486a.9c32a8","type":"split","z":"62d2b20a.1a87bc","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":510,"y":180,"wires":[["60b477b9.188ce8"]]},{"id":"56294459.e2431c","type":"comment","z":"62d2b20a.1a87bc","name":"↓ split array payload to message sequence","info":"","x":620,"y":140,"wires":[]},{"id":"f8ab27f2.b81d78","type":"sort","z":"62d2b20a.1a87bc","name":"","order":"ascending","as_num":false,"target":"","targetType":"seq","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":650,"y":520,"wires":[["75369287.5bb00c"]]},{"id":"df79c07e.d9dce","type":"inject","z":"62d2b20a.1a87bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":520,"wires":[["8e1e5b1e.a979e8"]]},{"id":"de7c57f3.7ecae8","type":"comment","z":"62d2b20a.1a87bc","name":"Sort array payload as string","info":"","x":220,"y":440,"wires":[]},{"id":"8e1e5b1e.a979e8","type":"template","z":"62d2b20a.1a87bc","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"1024\",\n \"86\",\n \"256\",\n \"100\",\n \"9\"\n]","output":"json","x":370,"y":520,"wires":[["4392ddd6.e30404"]]},{"id":"75369287.5bb00c","type":"debug","z":"62d2b20a.1a87bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":520,"wires":[]},{"id":"f9100b9d.065088","type":"sort","z":"62d2b20a.1a87bc","name":"","order":"ascending","as_num":true,"target":"","targetType":"seq","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":650,"y":700,"wires":[["53127c8c.cb4b64"]]},{"id":"c010d098.ac0e8","type":"inject","z":"62d2b20a.1a87bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":700,"wires":[["902c97aa.8b2958"]]},{"id":"8531cf78.dcdfc","type":"comment","z":"62d2b20a.1a87bc","name":"Sort array payload as number","info":"","x":220,"y":620,"wires":[]},{"id":"902c97aa.8b2958","type":"template","z":"62d2b20a.1a87bc","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"1024\",\n \"86\",\n \"256\",\n \"100\",\n \"9\"\n]","output":"json","x":370,"y":700,"wires":[["99461434.772718"]]},{"id":"53127c8c.cb4b64","type":"debug","z":"62d2b20a.1a87bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":700,"wires":[]},{"id":"ea246a52.4b9d88","type":"sort","z":"62d2b20a.1a87bc","name":"","order":"ascending","as_num":false,"target":"","targetType":"seq","msgKey":"price","msgKeyType":"jsonata","seqKey":"payload.price","seqKeyType":"jsonata","x":650,"y":880,"wires":[["2d548e4c.9adbd2"]]},{"id":"d69bd6df.849d68","type":"inject","z":"62d2b20a.1a87bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":880,"wires":[["e6ef0fbc.6fc22"]]},{"id":"ee5f9da5.d21ee","type":"comment","z":"62d2b20a.1a87bc","name":"Sort array of objects payload using simple JSONata expression","info":"","x":330,"y":800,"wires":[]},{"id":"e6ef0fbc.6fc22","type":"template","z":"62d2b20a.1a87bc","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n {\n \"name\": \"orange\", \n \"price\": 80\n },\n {\n \"name\": \"banana\",\n \"price\": 250\n },\n {\n \"name\": \"apple\",\n \"price\": 100\n },\n {\n \"name\": \"pear\",\n \"price\": 150\n },\n {\n \"name\": \"kiwi\",\n \"price\": 320\n }\n]","output":"json","x":370,"y":880,"wires":[["fcfd304c.562c9"]]},{"id":"2d548e4c.9adbd2","type":"debug","z":"62d2b20a.1a87bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":880,"wires":[]},{"id":"4ec23d0b.a4f014","type":"sort","z":"62d2b20a.1a87bc","name":"","order":"descending","as_num":false,"target":"","targetType":"seq","msgKey":"","msgKeyType":"elem","seqKey":"payload","seqKeyType":"msg","x":650,"y":340,"wires":[["b1f8d641.a96a78"]]},{"id":"4aa6a253.159aec","type":"inject","z":"62d2b20a.1a87bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":340,"wires":[["f28101b7.f4b21"]]},{"id":"63d42ecf.fd933","type":"comment","z":"62d2b20a.1a87bc","name":"Sort array payload as string in descending order","info":"","x":280,"y":260,"wires":[]},{"id":"f28101b7.f4b21","type":"template","z":"62d2b20a.1a87bc","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n \"orange\",\n \"banana\",\n \"apple\",\n \"pear\",\n \"kiwi\"\n]","output":"json","x":370,"y":340,"wires":[["685d7c1b.4f92b4"]]},{"id":"b1f8d641.a96a78","type":"debug","z":"62d2b20a.1a87bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":340,"wires":[]},{"id":"c112dd05.1543e","type":"comment","z":"62d2b20a.1a87bc","name":"↑ sort using object property as sorting key","info":"","x":760,"y":920,"wires":[]},{"id":"5c5ff25a.0f22bc","type":"comment","z":"62d2b20a.1a87bc","name":"↑ sort payload as array of number","info":"","x":740,"y":740,"wires":[]},{"id":"d0270e9b.04b7d","type":"comment","z":"62d2b20a.1a87bc","name":"↑ sort payload as array of string","info":"","x":730,"y":560,"wires":[]},{"id":"6ae587cd.cf9478","type":"comment","z":"62d2b20a.1a87bc","name":"↑ sort payload as array of string in descending order","info":"","x":790,"y":380,"wires":[]},{"id":"6fba3dab.8218c4","type":"sort","z":"62d2b20a.1a87bc","name":"","order":"ascending","as_num":false,"target":"","targetType":"seq","msgKey":"$substring(\"0000\" & $string(price), -4) & name","msgKeyType":"jsonata","seqKey":"$substring(\"0000\" & $string(payload.price), -4) & payload.name","seqKeyType":"jsonata","x":650,"y":1060,"wires":[["95f7f1b0.39fac"]]},{"id":"892b1f19.60247","type":"inject","z":"62d2b20a.1a87bc","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":1060,"wires":[["80ca6396.f55bb"]]},{"id":"c2da4a48.d35cd8","type":"comment","z":"62d2b20a.1a87bc","name":"Sort array of objects payload using complex JSONata expression","info":"","x":330,"y":980,"wires":[]},{"id":"80ca6396.f55bb","type":"template","z":"62d2b20a.1a87bc","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"mustache","template":"[\n {\n \"name\": \"orange\", \n \"price\": 100\n },\n {\n \"name\": \"banana\",\n \"price\": 200\n },\n {\n \"name\": \"apple\",\n \"price\": 100\n },\n {\n \"name\": \"pear\",\n \"price\": 200\n },\n {\n \"name\": \"kiwi\",\n \"price\": 200\n }\n]","output":"json","x":370,"y":1060,"wires":[["4cda7453.75eb1c"]]},{"id":"95f7f1b0.39fac","type":"debug","z":"62d2b20a.1a87bc","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":1060,"wires":[]},{"id":"24472c63.d12294","type":"comment","z":"62d2b20a.1a87bc","name":"↑ sort using object two property (price and name) as sorting keys","info":"","x":830,"y":1100,"wires":[]},{"id":"685d7c1b.4f92b4","type":"split","z":"62d2b20a.1a87bc","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":510,"y":340,"wires":[["4ec23d0b.a4f014"]]},{"id":"4392ddd6.e30404","type":"split","z":"62d2b20a.1a87bc","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":510,"y":520,"wires":[["f8ab27f2.b81d78"]]},{"id":"99461434.772718","type":"split","z":"62d2b20a.1a87bc","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":510,"y":700,"wires":[["f9100b9d.065088"]]},{"id":"fcfd304c.562c9","type":"split","z":"62d2b20a.1a87bc","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":510,"y":880,"wires":[["ea246a52.4b9d88"]]},{"id":"4cda7453.75eb1c","type":"split","z":"62d2b20a.1a87bc","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":510,"y":1060,"wires":[["6fba3dab.8218c4"]]},{"id":"1b2b8efc.b5aa51","type":"comment","z":"62d2b20a.1a87bc","name":"↓ split array payload to message sequence","info":"","x":620,"y":300,"wires":[]},{"id":"972a454c.99b5e8","type":"comment","z":"62d2b20a.1a87bc","name":"↓ split array payload to message sequence","info":"","x":620,"y":480,"wires":[]},{"id":"39123b6a.ee5bb4","type":"comment","z":"62d2b20a.1a87bc","name":"↓ split array payload to message sequence","info":"","x":620,"y":660,"wires":[]},{"id":"7809a5ac.eb0f8c","type":"comment","z":"62d2b20a.1a87bc","name":"↓ split array payload to message sequence","info":"","x":620,"y":840,"wires":[]},{"id":"f62c6678.d4da08","type":"comment","z":"62d2b20a.1a87bc","name":"↓ split array payload to message sequence","info":"","x":620,"y":1020,"wires":[]},{"id":"2438c53f.71a0da","type":"comment","z":"62d2b20a.1a87bc","name":"Example: Sort Message Sequence","info":"Sort node can be used to message sequence that contains `parts` property. If JSONata expression is used, the expression is applied to input message.","x":200,"y":40,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/sequence/split/01 - Split message payload.json b/packages/node_modules/@node-red/nodes/examples/sequence/split/01 - Split message payload.json
index 3fb14f0c3..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/sequence/split/01 - Split message payload.json
+++ b/packages/node_modules/@node-red/nodes/examples/sequence/split/01 - Split message payload.json
@@ -1 +0,0 @@
-[{"id":"f94ffc33.76f83","type":"comment","z":"e5679299.d9792","name":"Example: Split Message Payload","info":"Split node can be used to split message payload into multiple messages.","x":190,"y":60,"wires":[]},{"id":"657bb57c.a3f98c","type":"split","z":"e5679299.d9792","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":510,"y":160,"wires":[["14228ff.ae24f7"]]},{"id":"2afece55.b87de2","type":"inject","z":"e5679299.d9792","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":160,"wires":[["cfca3863.d961d8"]]},{"id":"cfca3863.d961d8","type":"template","z":"e5679299.d9792","name":"data","field":"payload","fieldType":"msg","format":"handlebars","syntax":"plain","template":"Apple\nOrange\nBanana","output":"str","x":370,"y":160,"wires":[["657bb57c.a3f98c"]]},{"id":"14228ff.ae24f7","type":"debug","z":"e5679299.d9792","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":660,"y":160,"wires":[]},{"id":"9a3c9494.b5d178","type":"comment","z":"e5679299.d9792","name":"Split input text by specified string","info":"","x":230,"y":120,"wires":[]},{"id":"38c873c.5ae718c","type":"comment","z":"e5679299.d9792","name":"↑ split by newline (\\\\n)","info":"","x":560,"y":200,"wires":[]},{"id":"bdfa12b9.3fbbc","type":"split","z":"e5679299.d9792","name":"","splt":"4","spltType":"len","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":510,"y":280,"wires":[["debf23bb.c0245"]]},{"id":"7c0948db.e35d38","type":"inject","z":"e5679299.d9792","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":280,"wires":[["7f791b7d.94cad4"]]},{"id":"7f791b7d.94cad4","type":"template","z":"e5679299.d9792","name":"data","field":"payload","fieldType":"msg","format":"handlebars","syntax":"plain","template":"Apple\nOrange\nBanana","output":"str","x":370,"y":280,"wires":[["bdfa12b9.3fbbc"]]},{"id":"debf23bb.c0245","type":"debug","z":"e5679299.d9792","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":660,"y":280,"wires":[]},{"id":"f05e98a3.4182c8","type":"comment","z":"e5679299.d9792","name":"Split input text by specified number of characters","info":"","x":280,"y":240,"wires":[]},{"id":"86b52b51.2258d8","type":"comment","z":"e5679299.d9792","name":"↑ split by four characters","info":"","x":570,"y":320,"wires":[]},{"id":"71d7c0e0.c0316","type":"split","z":"e5679299.d9792","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":510,"y":420,"wires":[["bee5b6a2.a955a8"]]},{"id":"1cdc2df9.bebdd2","type":"inject","z":"e5679299.d9792","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":420,"wires":[["f30df13c.19475"]]},{"id":"f30df13c.19475","type":"template","z":"e5679299.d9792","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"plain","template":"[ \n \"Apple\",\n \"Orange\",\n \"Banana\"\n]","output":"json","x":370,"y":420,"wires":[["71d7c0e0.c0316"]]},{"id":"bee5b6a2.a955a8","type":"debug","z":"e5679299.d9792","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":660,"y":420,"wires":[]},{"id":"b2c731fe.abda4","type":"comment","z":"e5679299.d9792","name":"Split input array","info":"","x":180,"y":380,"wires":[]},{"id":"1f557227.d0910e","type":"comment","z":"e5679299.d9792","name":"↑ split array","info":"","x":530,"y":460,"wires":[]},{"id":"c0d43ff4.291d8","type":"split","z":"e5679299.d9792","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"topic","x":510,"y":540,"wires":[["fc9fe458.50fd18"]]},{"id":"6d52ce8a.0c715","type":"inject","z":"e5679299.d9792","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":220,"y":540,"wires":[["bdeb8c21.1c6b7"]]},{"id":"bdeb8c21.1c6b7","type":"template","z":"e5679299.d9792","name":"data","field":"payload","fieldType":"msg","format":"json","syntax":"plain","template":"{ \n \"Apple\": 80,\n \"Orange\": 100,\n \"Banana\": 50\n}","output":"json","x":370,"y":540,"wires":[["c0d43ff4.291d8"]]},{"id":"fc9fe458.50fd18","type":"debug","z":"e5679299.d9792","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":640,"y":540,"wires":[]},{"id":"48956e14.79b86","type":"comment","z":"e5679299.d9792","name":"Split object to key/value pairs","info":"","x":220,"y":500,"wires":[]},{"id":"d528c2c2.6efc7","type":"comment","z":"e5679299.d9792","name":"↑ split object","info":"","x":530,"y":580,"wires":[]}]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/file-in/01 - Read string from a file.json b/packages/node_modules/@node-red/nodes/examples/storage/file-in/01 - Read string from a file.json
index 14d7152c7..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/file-in/01 - Read string from a file.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/file-in/01 - Read string from a file.json
@@ -1,113 +0,0 @@
-[
- {
- "id": "84222b92.d65d18",
- "type": "inject",
- "z": "194a3e4f.a92772",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 230,
- "y": 220,
- "wires": [
- [
- "b4b9f603.739598"
- ]
- ]
- },
- {
- "id": "7b014430.dfd94c",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "Write string to a file, then read from the file",
- "info": "File-in node can read string from a file.",
- "x": 260,
- "y": 140,
- "wires": []
- },
- {
- "id": "b4b9f603.739598",
- "type": "file",
- "z": "194a3e4f.a92772",
- "name": "",
- "filename": "/tmp/hello.txt",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "true",
- "encoding": "none",
- "x": 420,
- "y": 220,
- "wires": [
- [
- "6dc01cac.5c4bf4"
- ]
- ]
- },
- {
- "id": "2587adb9.7e60f2",
- "type": "debug",
- "z": "194a3e4f.a92772",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 810,
- "y": 220,
- "wires": []
- },
- {
- "id": "6dc01cac.5c4bf4",
- "type": "file in",
- "z": "194a3e4f.a92772",
- "name": "",
- "filename": "/tmp/hello.txt",
- "format": "utf8",
- "chunk": false,
- "sendError": false,
- "encoding": "none",
- "x": 620,
- "y": 220,
- "wires": [
- [
- "2587adb9.7e60f2"
- ]
- ]
- },
- {
- "id": "f4b4309a.3b78a",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "↑read result from file",
- "info": "",
- "x": 630,
- "y": 260,
- "wires": []
- },
- {
- "id": "672d3693.3cabd8",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "↓write to /tmp/hello.txt",
- "info": "",
- "x": 440,
- "y": 180,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/file-in/02 - Read data in specified encoding.json b/packages/node_modules/@node-red/nodes/examples/storage/file-in/02 - Read data in specified encoding.json
index d96623fb1..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/file-in/02 - Read data in specified encoding.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/file-in/02 - Read data in specified encoding.json
@@ -1,113 +0,0 @@
-[
- {
- "id": "8997398f.c5d628",
- "type": "inject",
- "z": "194a3e4f.a92772",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "😀",
- "payloadType": "str",
- "x": 210,
- "y": 480,
- "wires": [
- [
- "56e32d23.050f44"
- ]
- ]
- },
- {
- "id": "4e598e65.1799d",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "Read data in specified encoding",
- "info": "File-in node can specify encoding of data read from a file.",
- "x": 230,
- "y": 400,
- "wires": []
- },
- {
- "id": "56e32d23.050f44",
- "type": "file",
- "z": "194a3e4f.a92772",
- "name": "",
- "filename": "/tmp/hello.txt",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "true",
- "encoding": "none",
- "x": 380,
- "y": 480,
- "wires": [
- [
- "38fa0579.f2cd8a"
- ]
- ]
- },
- {
- "id": "d28c8994.99c0a8",
- "type": "debug",
- "z": "194a3e4f.a92772",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 770,
- "y": 480,
- "wires": []
- },
- {
- "id": "38fa0579.f2cd8a",
- "type": "file in",
- "z": "194a3e4f.a92772",
- "name": "",
- "filename": "/tmp/hello.txt",
- "format": "utf8",
- "chunk": false,
- "sendError": false,
- "encoding": "base64",
- "x": 580,
- "y": 480,
- "wires": [
- [
- "d28c8994.99c0a8"
- ]
- ]
- },
- {
- "id": "fa22ca20.ae4528",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "↑read data from file as base64 string",
- "info": "",
- "x": 640,
- "y": 520,
- "wires": []
- },
- {
- "id": "148e25ad.98891a",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "↓write to /tmp/hello.txt",
- "info": "",
- "x": 400,
- "y": 440,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/file-in/03 - Read data breaking lines into messages.json b/packages/node_modules/@node-red/nodes/examples/storage/file-in/03 - Read data breaking lines into messages.json
index b3d35a4da..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/file-in/03 - Read data breaking lines into messages.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/file-in/03 - Read data breaking lines into messages.json
@@ -1,132 +0,0 @@
-[
- {
- "id": "6a0b1d03.d4cee4",
- "type": "inject",
- "z": "194a3e4f.a92772",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 220,
- "y": 740,
- "wires": [
- [
- "d4b00cb7.a5a23"
- ]
- ]
- },
- {
- "id": "f17ea1d1.8ecc3",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "Read data breaking lines into individual messages",
- "info": "File-in node can break read text into messages with individual lines",
- "x": 290,
- "y": 660,
- "wires": []
- },
- {
- "id": "99ae7806.1d6428",
- "type": "file",
- "z": "194a3e4f.a92772",
- "name": "",
- "filename": "/tmp/hello.txt",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "true",
- "encoding": "none",
- "x": 540,
- "y": 740,
- "wires": [
- [
- "70d7892f.d27db8"
- ]
- ]
- },
- {
- "id": "7ed8282c.92b338",
- "type": "debug",
- "z": "194a3e4f.a92772",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 810,
- "y": 800,
- "wires": []
- },
- {
- "id": "70d7892f.d27db8",
- "type": "file in",
- "z": "194a3e4f.a92772",
- "name": "",
- "filename": "/tmp/hello.txt",
- "format": "lines",
- "chunk": false,
- "sendError": false,
- "encoding": "none",
- "x": 620,
- "y": 800,
- "wires": [
- [
- "7ed8282c.92b338"
- ]
- ]
- },
- {
- "id": "c1b7e05.1d94b2",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "↑read data from file breaking lines into messages",
- "info": "",
- "x": 720,
- "y": 840,
- "wires": []
- },
- {
- "id": "a5f647b2.cf27a8",
- "type": "comment",
- "z": "194a3e4f.a92772",
- "name": "↓write to /tmp/hello.txt",
- "info": "",
- "x": 560,
- "y": 700,
- "wires": []
- },
- {
- "id": "d4b00cb7.a5a23",
- "type": "template",
- "z": "194a3e4f.a92772",
- "name": "data",
- "field": "payload",
- "fieldType": "msg",
- "format": "handlebars",
- "syntax": "plain",
- "template": "one\ntwo\nthree!",
- "output": "str",
- "x": 370,
- "y": 740,
- "wires": [
- [
- "99ae7806.1d6428"
- ]
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/file/01 - Write string to a file.json b/packages/node_modules/@node-red/nodes/examples/storage/file/01 - Write string to a file.json
index 2be033021..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/file/01 - Write string to a file.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/file/01 - Write string to a file.json
@@ -1,113 +0,0 @@
-[
- {
- "id": "84222b92.d65d18",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 230,
- "y": 200,
- "wires": [
- [
- "b4b9f603.739598"
- ]
- ]
- },
- {
- "id": "7b014430.dfd94c",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Write string to a file, then read from the file",
- "info": "File node can write string to a file.",
- "x": 260,
- "y": 120,
- "wires": []
- },
- {
- "id": "b4b9f603.739598",
- "type": "file",
- "z": "4b63452d.672afc",
- "name": "",
- "filename": "/tmp/hello.txt",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "true",
- "encoding": "none",
- "x": 420,
- "y": 200,
- "wires": [
- [
- "6dc01cac.5c4bf4"
- ]
- ]
- },
- {
- "id": "2587adb9.7e60f2",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 810,
- "y": 200,
- "wires": []
- },
- {
- "id": "6dc01cac.5c4bf4",
- "type": "file in",
- "z": "4b63452d.672afc",
- "name": "",
- "filename": "/tmp/hello.txt",
- "format": "utf8",
- "chunk": false,
- "sendError": false,
- "encoding": "none",
- "x": 620,
- "y": 200,
- "wires": [
- [
- "2587adb9.7e60f2"
- ]
- ]
- },
- {
- "id": "f4b4309a.3b78a",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "↑read result from file",
- "info": "",
- "x": 630,
- "y": 240,
- "wires": []
- },
- {
- "id": "672d3693.3cabd8",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "↓write to /tmp/hello.txt",
- "info": "",
- "x": 440,
- "y": 160,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/file/02 - Write string to a file specified by property.json b/packages/node_modules/@node-red/nodes/examples/storage/file/02 - Write string to a file specified by property.json
index 6aaff500a..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/file/02 - Write string to a file specified by property.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/file/02 - Write string to a file specified by property.json
@@ -1,118 +0,0 @@
-[
- {
- "id": "704479e1.399388",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "filename",
- "v": "/tmp/hello.txt",
- "vt": "str"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 230,
- "y": 400,
- "wires": [
- [
- "402f3b7e.988014"
- ]
- ]
- },
- {
- "id": "8e876a75.e9beb8",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Write string to a file specied by filename property, the read from the file",
- "info": "File node can target file using `filename` property.",
- "x": 350,
- "y": 320,
- "wires": []
- },
- {
- "id": "402f3b7e.988014",
- "type": "file",
- "z": "4b63452d.672afc",
- "name": "",
- "filename": "",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "true",
- "encoding": "none",
- "x": 390,
- "y": 400,
- "wires": [
- [
- "26e077d6.bbcd98"
- ]
- ]
- },
- {
- "id": "97b6b6b2.a54b38",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 770,
- "y": 400,
- "wires": []
- },
- {
- "id": "26e077d6.bbcd98",
- "type": "file in",
- "z": "4b63452d.672afc",
- "name": "",
- "filename": "/tmp/hello.txt",
- "format": "utf8",
- "chunk": false,
- "sendError": false,
- "encoding": "none",
- "x": 580,
- "y": 400,
- "wires": [
- [
- "97b6b6b2.a54b38"
- ]
- ]
- },
- {
- "id": "85062297.da79",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "↑read result from file",
- "info": "",
- "x": 590,
- "y": 440,
- "wires": []
- },
- {
- "id": "7316c4fc.b1dcdc",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "↓write to file specified by filename property",
- "info": "",
- "x": 500,
- "y": 360,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/file/03 - Delete a file.json b/packages/node_modules/@node-red/nodes/examples/storage/file/03 - Delete a file.json
index fe6ac166b..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/file/03 - Delete a file.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/file/03 - Delete a file.json
@@ -1,85 +0,0 @@
-[
- {
- "id": "4ac00fb0.d5f52",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "",
- "payloadType": "date",
- "x": 220,
- "y": 600,
- "wires": [
- [
- "542cc2f4.92857c"
- ]
- ]
- },
- {
- "id": "671f8295.0e6f6c",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Delete a file",
- "info": "File node can delete a file.",
- "x": 170,
- "y": 540,
- "wires": []
- },
- {
- "id": "542cc2f4.92857c",
- "type": "file",
- "z": "4b63452d.672afc",
- "name": "",
- "filename": "/tmp/hello.txt",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "delete",
- "encoding": "none",
- "x": 420,
- "y": 600,
- "wires": [
- [
- "a24da523.5babe8"
- ]
- ]
- },
- {
- "id": "a24da523.5babe8",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 630,
- "y": 600,
- "wires": []
- },
- {
- "id": "51157051.2f62",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "↓delete a file",
- "info": "",
- "x": 390,
- "y": 560,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/file/04 - Specify encoding of written data.json b/packages/node_modules/@node-red/nodes/examples/storage/file/04 - Specify encoding of written data.json
index 4dabbd670..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/file/04 - Specify encoding of written data.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/file/04 - Specify encoding of written data.json
@@ -1,113 +0,0 @@
-[
- {
- "id": "e4ef1f5e.7cd82",
- "type": "inject",
- "z": "4b63452d.672afc",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "8J+YgA==",
- "payloadType": "str",
- "x": 220,
- "y": 820,
- "wires": [
- [
- "72b37cc8.177054"
- ]
- ]
- },
- {
- "id": "f5997af4.5a9298",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "Specify encoding of written data",
- "info": "File node can specify encoding of data.",
- "x": 230,
- "y": 740,
- "wires": []
- },
- {
- "id": "72b37cc8.177054",
- "type": "file",
- "z": "4b63452d.672afc",
- "name": "",
- "filename": "/tmp/hello.txt",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "true",
- "encoding": "base64",
- "x": 400,
- "y": 820,
- "wires": [
- [
- "2da33ec.f45cac2"
- ]
- ]
- },
- {
- "id": "2e814354.278c8c",
- "type": "debug",
- "z": "4b63452d.672afc",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 790,
- "y": 820,
- "wires": []
- },
- {
- "id": "2da33ec.f45cac2",
- "type": "file in",
- "z": "4b63452d.672afc",
- "name": "",
- "filename": "/tmp/hello.txt",
- "format": "utf8",
- "chunk": false,
- "sendError": false,
- "encoding": "none",
- "x": 600,
- "y": 820,
- "wires": [
- [
- "2e814354.278c8c"
- ]
- ]
- },
- {
- "id": "ec754c99.84bfd",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "↓write string with base64 encoding",
- "info": "",
- "x": 460,
- "y": 780,
- "wires": []
- },
- {
- "id": "3e6704ff.4ce25c",
- "type": "comment",
- "z": "4b63452d.672afc",
- "name": "↑read result from file",
- "info": "",
- "x": 610,
- "y": 860,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/packages/node_modules/@node-red/nodes/examples/storage/watch/01 - Watch change of a file.json b/packages/node_modules/@node-red/nodes/examples/storage/watch/01 - Watch change of a file.json
index 873e99b89..e69de29bb 100644
--- a/packages/node_modules/@node-red/nodes/examples/storage/watch/01 - Watch change of a file.json
+++ b/packages/node_modules/@node-red/nodes/examples/storage/watch/01 - Watch change of a file.json
@@ -1,108 +0,0 @@
-[
- {
- "id": "84222b92.d65d18",
- "type": "inject",
- "z": "a7ac8a68.0f7218",
- "name": "",
- "props": [
- {
- "p": "payload"
- },
- {
- "p": "topic",
- "vt": "str"
- }
- ],
- "repeat": "",
- "crontab": "",
- "once": false,
- "onceDelay": 0.1,
- "topic": "",
- "payload": "Hello, World!",
- "payloadType": "str",
- "x": 230,
- "y": 160,
- "wires": [
- [
- "b4b9f603.739598"
- ]
- ]
- },
- {
- "id": "7b014430.dfd94c",
- "type": "comment",
- "z": "a7ac8a68.0f7218",
- "name": "Watch changes of a file",
- "info": "Watch node can watch and report changes of a file.",
- "x": 200,
- "y": 80,
- "wires": []
- },
- {
- "id": "b4b9f603.739598",
- "type": "file",
- "z": "a7ac8a68.0f7218",
- "name": "",
- "filename": "/tmp/hello.txt",
- "appendNewline": true,
- "createDir": false,
- "overwriteFile": "true",
- "encoding": "none",
- "x": 420,
- "y": 160,
- "wires": [
- []
- ]
- },
- {
- "id": "672d3693.3cabd8",
- "type": "comment",
- "z": "a7ac8a68.0f7218",
- "name": "↓write to /tmp/hello.txt",
- "info": "",
- "x": 440,
- "y": 120,
- "wires": []
- },
- {
- "id": "15f1f5aa.506ffa",
- "type": "watch",
- "z": "a7ac8a68.0f7218",
- "name": "",
- "files": "/tmp/hello.txt",
- "recursive": "",
- "x": 410,
- "y": 200,
- "wires": [
- [
- "a91562b9.ca805"
- ]
- ]
- },
- {
- "id": "a91562b9.ca805",
- "type": "debug",
- "z": "a7ac8a68.0f7218",
- "name": "",
- "active": true,
- "tosidebar": true,
- "console": false,
- "tostatus": false,
- "complete": "false",
- "statusVal": "",
- "statusType": "auto",
- "x": 610,
- "y": 200,
- "wires": []
- },
- {
- "id": "2ab4eba8.267d64",
- "type": "comment",
- "z": "a7ac8a68.0f7218",
- "name": "↑watch changes of /tmp/hello.txt",
- "info": "",
- "x": 470,
- "y": 240,
- "wires": []
- }
-]
\ No newline at end of file
diff --git a/test/editor/editor_helper.js b/test/editor/editor_helper.js
deleted file mode 100644
index 73177c2ca..000000000
--- a/test/editor/editor_helper.js
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require("when");
-var http = require('http');
-var express = require("express");
-var fs = require('fs-extra');
-var path = require('path');
-var app = express();
-
-var RED = require("nr-test-utils").require("node-red/lib/red.js");
-
-var utilPage = require("./pageobjects/util/util_page");
-
-var server;
-var homeDir = './test/resources/home';
-var address = '127.0.0.1';
-var listenPort = 0; // use ephemeral port
-var url;
-/*
- * Set false when you need a flow to reproduce the failed test case.
- * The flow file is under "homeDir" defined above.
- */
-var isDeleteFlow = true;
-
-function getFlowFilename() {
- var orig = Error.prepareStackTrace;
- var err = new Error();
- Error.prepareStackTrace = function (err, stack) {
- return stack;
- };
- // Two level higher caller is the actual caller (e.g. a caller of startServer).
- var filepath = err.stack[2].getFileName();
- var filename = path.basename(filepath, ".js");
- Error.prepareStackTrace = orig;
-
- var flowFile = 'flows_' + filename + '.json';
- return flowFile;
-}
-
-function cleanup(flowFile) {
- var credentialFile = flowFile.replace(/\.json$/, '') + '_cred.json';
- deleteFile(homeDir + "/" + flowFile);
- deleteFile(homeDir + "/." + flowFile + ".backup");
- deleteFile(homeDir + "/" + credentialFile);
- deleteFile(homeDir + "/." + credentialFile + ".backup");
- deleteFile(homeDir + "/package.json");
- deleteFile(homeDir + "/lib/flows");
- deleteFile(homeDir + "/lib");
-}
-
-function deleteFile(flowFile) {
- try {
- fs.statSync(flowFile);
- if (isDeleteFlow) {
- fs.unlinkSync(flowFile);
- }
- } catch (e) {}
-}
-
-module.exports = {
- startServer: function() {
- try{
- utilPage.init();
-
- // Name a flow file including caller filename so that multiple Node-RED servers can run simultaneously.
- // Call this method here because retrieving the caller filename by call stack.
- var flowFilename = getFlowFilename();
- browser.windowHandleMaximize();
- browser.call(function () {
- return new Promise(function(resolve, reject) {
- cleanup(flowFilename);
- server = http.createServer(app);
- var settings = {
- httpAdminRoot: "/",
- httpNodeRoot: "/api",
- userDir: homeDir,
- flowFile: flowFilename,
- functionGlobalContext: { }, // enables global context
- SKIP_BUILD_CHECK: true,
- logging: {console: {level:'off'}}
- };
- RED.init(server, settings);
- app.use(settings.httpAdminRoot,RED.httpAdmin);
- app.use(settings.httpNodeRoot,RED.httpNode);
- server.listen(listenPort, address);
- server.on('listening', function() {
- var port = server.address().port;
- url = 'http://' + address + ':' + port;
- });
- RED.start().then(function() {
- resolve();
- });
- });
- });
- browser.url(url);
- browser.waitForExist(".red-ui-palette-node[data-palette-type='inject']");
- } catch (err) {
- console.log(err);
- throw err;
- }
- },
-
- stopServer: function(done) {
- try {
- // Call this method here because retrieving the caller filename by call stack.
- var flowFilename = getFlowFilename();
- browser.call(function () {
- browser.close(); // need to call this inside browser.call().
- return when.promise(function(resolve, reject) {
- if (server) {
- RED.stop().then(function() {
- server.close(function() {
- cleanup(flowFilename);
- resolve();
- });
- });
- } else {
- cleanup(flowFilename);
- resolve();
- }
- });
- });
- } catch (err) {
- console.log(err);
- throw err;
- }
- },
-
- url: function() {
- return url;
- },
-
- red: function() {
- return RED;
- },
-};
diff --git a/test/editor/pageobjects/editor/debugTab_page.js b/test/editor/pageobjects/editor/debugTab_page.js
deleted file mode 100644
index 5476a28d6..000000000
--- a/test/editor/pageobjects/editor/debugTab_page.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-function open(retainMessage) {
- browser.clickWithWait('#red-ui-tab-debug-link-button');
-
- if (!retainMessage) {
- // Clear old messages
- browser.clickWithWait('//a[@id="red-ui-sidebar-debug-clear"]');
- }
-}
-
-function getMessage(index) {
- index = index ? index : 1;
- var debugMessagePath = '//div[@class="red-ui-debug-content red-ui-debug-content-list"]/div[contains(@class,"red-ui-debug-msg")][' + index + ']//span[contains(@class, "red-ui-debug-msg-type")]';
- return browser.getTextWithWait(debugMessagePath);
-}
-
-function clearMessage() {
- browser.clickWithWait('//a[@id="red-ui-sidebar-debug-clear"]');
-}
-
-module.exports = {
- open: open,
- getMessage: getMessage,
- clearMessage: clearMessage,
-};
diff --git a/test/editor/pageobjects/editor/palette_page.js b/test/editor/pageobjects/editor/palette_page.js
deleted file mode 100644
index 3b484a58c..000000000
--- a/test/editor/pageobjects/editor/palette_page.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var idMap = {
- // common
- "inject": ".red-ui-palette-node[data-palette-type='inject']",
- "debug": ".red-ui-palette-node[data-palette-type='debug']",
- "complete": ".red-ui-palette-node[data-palette-type='complete']",
- "catch": ".red-ui-palette-node[data-palette-type='catch']",
- "status": ".red-ui-palette-node[data-palette-type='status']",
- "comment": ".red-ui-palette-node[data-palette-type='comment']",
- // function
- "function": ".red-ui-palette-node[data-palette-type='function']",
- "switch": ".red-ui-palette-node[data-palette-type='switch']",
- "change": ".red-ui-palette-node[data-palette-type='change']",
- "range": ".red-ui-palette-node[data-palette-type='range']",
- "template": ".red-ui-palette-node[data-palette-type='template']",
- "delay": ".red-ui-palette-node[data-palette-type='delay']",
- "trigger": ".red-ui-palette-node[data-palette-type='trigger']",
- "exec": ".red-ui-palette-node[data-palette-type='exec']",
- // network
- "mqttIn": ".red-ui-palette-node[data-palette-type='mqtt in']",
- "mqttOut": ".red-ui-palette-node[data-palette-type='mqtt out']",
- "httpIn": ".red-ui-palette-node[data-palette-type='http in']",
- "httpResponse": ".red-ui-palette-node[data-palette-type='http response']",
- "httpRequest": ".red-ui-palette-node[data-palette-type='http request']",
- "websocketIn": ".red-ui-palette-node[data-palette-type='websocket in']",
- "websocketOut": ".red-ui-palette-node[data-palette-type='websocket out']",
- // sequence
- "split": ".red-ui-palette-node[data-palette-type='split']",
- "join": ".red-ui-palette-node[data-palette-type='join']",
- "batch": ".red-ui-palette-node[data-palette-type='batch']",
- // parser
- "csv": ".red-ui-palette-node[data-palette-type='csv']",
- "html": ".red-ui-palette-node[data-palette-type='html']",
- "json": ".red-ui-palette-node[data-palette-type='json']",
- "xml": ".red-ui-palette-node[data-palette-type='xml']",
- "yaml": ".red-ui-palette-node[data-palette-type='yaml']",
- // storage
- "fileIn": ".red-ui-palette-node[data-palette-type='file in']",
-};
-
-function getId(type) {
- return idMap[type];
-}
-
-module.exports = {
- getId: getId,
-};
diff --git a/test/editor/pageobjects/editor/workspace_page.js b/test/editor/pageobjects/editor/workspace_page.js
deleted file mode 100644
index 92a725dac..000000000
--- a/test/editor/pageobjects/editor/workspace_page.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require("when");
-var events = require("nr-test-utils").require("@node-red/runtime/lib/events.js");
-var palette = require("./palette_page");
-var nodeFactory = require("../nodes/nodefactory_page");
-var keyPage = require("../util/key_page");
-var flowLayout = {
- flowRightEnd : 600,
- widthInterval : 300,
- heightInterval : 80
-};
-var previousX = -flowLayout.widthInterval;
-var previousY = 0;
-
-function addNode(type, x, y) {
- if (x !== undefined) {
- previousX = x;
- if (y !== undefined) {
- previousY = y;
- }
- } else {
- if (previousX < flowLayout.flowRightEnd) {
- previousX = previousX + flowLayout.widthInterval;
- } else {
- previousX = 0;
- previousY = previousY + flowLayout.heightInterval;
- }
- }
- browser.waitForVisible('#red-ui-palette-search');
- browser.setValue('//*[@id="red-ui-palette-search"]/div/form/input', type.replace(/([A-Z])/g, ' $1').toLowerCase());
- browser.pause(300);
- browser.waitForVisible(palette.getId(type));
- browser.moveToObject(palette.getId(type));
- browser.buttonDown();
- browser.moveToObject("#red-ui-palette-search", previousX + 300, previousY + 100); // adjust to the top-left corner of workspace.
- browser.buttonUp();
- // Last node is the one that has been created right now.
- var nodeElement = browser.elements('//*[contains(concat(" ", normalize-space(@class), " "), " red-ui-flow-node-group ")][last()]');
- var nodeId = nodeElement.getAttribute('id');
- var node = nodeFactory.create(type, nodeId);
- return node;
-}
-
-function deleteAllNodes() {
- browser.waitForVisible('//*[contains(@class, "active")]/a[@class="red-ui-tab-label"]');
- browser.click('//*[contains(@class, "active")]/a[@class="red-ui-tab-label"]');
- browser.pause(1000);
- browser.keys(keyPage.selectAll());
- browser.keys(['Delete']);
-}
-
-function deploy() {
- browser.call(function () {
- return when.promise(function (resolve, reject) {
- events.on("runtime-event", function (event) {
- if (event.id === 'runtime-deploy') {
- events.removeListener("runtime-event", arguments.callee);
- resolve();
- }
- });
- browser.clickWithWait('#red-ui-header-button-deploy');
- });
- });
- browser.waitForText('#red-ui-header-button-deploy', 10000);
- // Need additional wait until buttons becomes clickable.
- browser.pause(50);
-}
-
-function init(width, height) {
- deleteAllNodes();
-
- if (width !== undefined) {
- flowLayout.widthInterval = width;
- }
- if (height !== undefined) {
- flowLayout.heightInterval = height;
- }
- previousX = -flowLayout.widthInterval;
- previousY = 0;
-}
-
-module.exports = {
- addNode: addNode,
- deploy: deploy,
- init: init
-};
diff --git a/test/editor/pageobjects/nodes/core/common/20-inject_page.js b/test/editor/pageobjects/nodes/core/common/20-inject_page.js
deleted file mode 100644
index b7c230e6c..000000000
--- a/test/editor/pageobjects/nodes/core/common/20-inject_page.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function injectNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(injectNode, nodePage);
-
-var payloadTypeList = {
- "msg": 1,
- "flow": 2,
- "global": 3,
- "str": 4,
- "num": 5,
- "bool": 6,
- "json": 7,
- "bin": 8,
- "date": 9,
- "jsonata": 10,
- "env": 11,
-};
-
-var repeatTypeList = {
- "none": 1,
- "interval": 2,
- "intervalBetweenTimes": 3,
- "atASpecificTime": 4,
-};
-
-injectNode.prototype.setPayload = function(payloadType, payload) {
- // Open a payload type list.
- browser.clickWithWait('//*[@id="node-input-property-container"]/li[1]/div/div/div[3]');
- // Select a payload type.
- var payloadTypeXPath = '//*[contains(@class, "red-ui-typedInput-options")]/a[' + payloadTypeList[payloadType] + ']';
- browser.clickWithWait(payloadTypeXPath);
- if (payload) {
- // Input a value.
- browser.setValue('//*[@id="node-input-property-container"]/li[1]/div/div/div[3]/div[1]/input', payload);
- }
-}
-
-injectNode.prototype.setTopic = function(topic) {
- browser.setValue('//*[@id="node-input-property-container"]/li[2]/div/div/div[3]/div[1]/input', topic);
-}
-
-injectNode.prototype.setOnce = function(once) {
- var isChecked = browser.isSelected('#node-input-once');
- if (isChecked !== once) {
- browser.clickWithWait('#node-input-once');
- }
-}
-
-injectNode.prototype.setRepeat = function(repeatType) {
- var repeatTypeXPath = '//*[@id="inject-time-type-select"]/option[' + repeatTypeList[repeatType] + ']';
- browser.clickWithWait(repeatTypeXPath);
-}
-
-injectNode.prototype.setRepeatInterval = function(repeat) {
- browser.setValue('#inject-time-interval-count', repeat);
-}
-
-module.exports = injectNode;
diff --git a/test/editor/pageobjects/nodes/core/common/21-debug_page.js b/test/editor/pageobjects/nodes/core/common/21-debug_page.js
deleted file mode 100644
index 3cec19985..000000000
--- a/test/editor/pageobjects/nodes/core/common/21-debug_page.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function debugNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(debugNode, nodePage);
-
-debugNode.prototype.setOutput = function (complete) {
- // Open a payload type list.
- browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-container")]/button');
- if (complete !== 'true') {
- // Select the "msg" type.
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options")][2]/a[1]');
- // Input the path in msg.
- browser.clickWithWait('//*[contains(@class, "red-ui-typedInput-input")]/input');
- browser.keys(Array('payload'.length).fill('Backspace'));
- browser.setValue('//*[@id="dialog-form"]/div[1]/div/div[1]/input', complete);
- } else {
- // Select the "complete msg object" type.
- browser.clickWithWait('/html/body/div[11]/a[2]');
- }
-}
-
-module.exports = debugNode;
diff --git a/test/editor/pageobjects/nodes/core/common/24-complete_page.js b/test/editor/pageobjects/nodes/core/common/24-complete_page.js
deleted file mode 100644
index 558ee709a..000000000
--- a/test/editor/pageobjects/nodes/core/common/24-complete_page.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function completeNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(completeNode, nodePage);
-
-completeNode.prototype.setScope = function (scope) {
- if (scope) {
- browser.clickWithWait('//*[@id="node-input-complete-target-select"]');
- browser.pause(1000);
- if (Array.isArray(scope)) {
- for (var i = 0; i < scope.length; i++) {
- browser.moveToObject(scope[i].id);
- browser.buttonDown();
- browser.buttonUp();
- }
- } else {
- browser.moveToObject(scope.id);
- browser.buttonDown();
- browser.buttonUp();
- }
- browser.clickWithWait('//*[contains(@class, "red-ui-notification")]/div/button[2]');
- browser.pause(1000);
- }
-}
-
-module.exports = completeNode;
diff --git a/test/editor/pageobjects/nodes/core/common/25-catch_page.js b/test/editor/pageobjects/nodes/core/common/25-catch_page.js
deleted file mode 100644
index 89bcb7f1e..000000000
--- a/test/editor/pageobjects/nodes/core/common/25-catch_page.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function catchNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(catchNode, nodePage);
-
-catchNode.prototype.setScope = function (scope) {
- if (scope) {
- browser.selectWithWait('#node-input-scope-select', 'target');
- browser.clickWithWait('//*[@id="node-input-catch-target-select"]');
- browser.pause(1000);
- if (Array.isArray(scope)) {
- for (var i = 0; i < scope.length; i++) {
- browser.moveToObject(scope[i].id);
- browser.buttonDown();
- browser.buttonUp();
- }
- } else {
- browser.moveToObject(scope.id);
- browser.buttonDown();
- browser.buttonUp();
- }
- browser.clickWithWait('//*[contains(@class, "red-ui-notification")]/div/button[2]');
- browser.pause(1000);
- }
-}
-
-module.exports = catchNode;
diff --git a/test/editor/pageobjects/nodes/core/common/25-status_page.js b/test/editor/pageobjects/nodes/core/common/25-status_page.js
deleted file mode 100644
index 6de0fcde7..000000000
--- a/test/editor/pageobjects/nodes/core/common/25-status_page.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function statusNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(statusNode, nodePage);
-
-statusNode.prototype.setScope = function (scope) {
- if (scope) {
- browser.selectWithWait('#node-input-scope-select', 'target');
- browser.clickWithWait('//*[@id="node-input-status-target-select"]');
- browser.pause(1000);
- if (Array.isArray(scope)) {
- for (var i = 0; i < scope.length; i++) {
- browser.moveToObject(scope[i].id);
- browser.buttonDown();
- browser.buttonUp();
- }
- } else {
- browser.moveToObject(scope.id);
- browser.buttonDown();
- browser.buttonUp();
- }
- browser.clickWithWait('//*[contains(@class, "red-ui-notification")]/div/button[2]');
- browser.pause(1000);
- }
-}
-
-module.exports = statusNode;
diff --git a/test/editor/pageobjects/nodes/core/common/90-comment_page.js b/test/editor/pageobjects/nodes/core/common/90-comment_page.js
deleted file mode 100644
index 2687dacfe..000000000
--- a/test/editor/pageobjects/nodes/core/common/90-comment_page.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function commentNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(commentNode, nodePage);
-
-module.exports = commentNode;
diff --git a/test/editor/pageobjects/nodes/core/function/10-function_page.js b/test/editor/pageobjects/nodes/core/function/10-function_page.js
deleted file mode 100644
index c1bb80a80..000000000
--- a/test/editor/pageobjects/nodes/core/function/10-function_page.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-var keyPage = require("../../../util/key_page");
-
-function functionNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(functionNode, nodePage);
-
-functionNode.prototype.setFunction = function (func) {
- browser.clickWithWait('#node-input-func-editor');
- browser.keys(keyPage.selectAll());
- browser.keys(['Delete']);
- browser.keys(func);
- // Delete the unnecessary code that ace editor does the autocompletion.
- browser.keys(keyPage.selectToEnd());
- browser.keys(['Delete']);
- // Need to wait until ace editor correctly checks the syntax.
- browser.pause(300);
-}
-
-module.exports = functionNode;
diff --git a/test/editor/pageobjects/nodes/core/function/10-switch_page.js b/test/editor/pageobjects/nodes/core/function/10-switch_page.js
deleted file mode 100644
index a04014063..000000000
--- a/test/editor/pageobjects/nodes/core/function/10-switch_page.js
+++ /dev/null
@@ -1,234 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function switchNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(switchNode, nodePage);
-
-var vtType = {
- "msg": 1,
- "flow": 2,
- "global": 3,
- "str": 4,
- "num": 5,
- "jsonata": 6,
- "env": 7,
- "prev": 8
-};
-
-function setT(t, index) {
- browser.selectWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', t);
-}
-
-function setV(v, vt, index) {
- if (vt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + vtType[vt] + ']');
- }
- if (v) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', v);
- }
-}
-
-function setBetweenV(v, vt, v2, v2t, index) {
- if (vt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div[2]/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + vtType[vt] + ']');
- }
- if (v) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div[2]/div[1]/input', v);
- }
- if (v2t) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[3]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + vtType[v2t] + ']');
- }
- if (v2) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[3]/div/div[1]/input', v2);
- }
-}
-
-function setSequenceV(v, vt, index) {
- var sType = {
- "flow": 1,
- "global": 2,
- "num": 3,
- "jsonata": 4,
- "env": 5,
- };
-
- if (vt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div[2]/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + sType[vt] + ']');
- }
- if (v) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div[2]/div[1]/input', v);
- }
-}
-
-switchNode.prototype.ruleEqual = function (v, vt, index) {
- index = index || 1;
- setT('eq', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleNotEqual = function (v, vt, index) {
- index = index || 1;
- setT('neq', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleLessThan = function (v, vt, index) {
- index = index || 1;
- setT('lt', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleLessThanOrEqual = function (v, vt, index) {
- index = index || 1;
- setT('lte', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleGreaterThan = function (v, vt, index) {
- index = index || 1;
- setT('gt', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleGreaterThanOrEqual = function (v, vt, index) {
- index = index || 1;
- setT('gte', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleHasKey = function (v, vt, index) {
- index = index || 1;
- setT('hask', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleIsBetween = function (v, vt, v2, v2t, index) {
- index = index || 1;
- setT('btwn', index);
- setBetweenV(v, vt, v2, v2t, index);
-}
-
-switchNode.prototype.ruleContains = function (v, vt, index) {
- index = index || 1;
- setT('cont', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleMatchesRegex = function (v, vt, index) {
- index = index || 1;
- setT('regex', index);
- setV(v, vt, index);
-}
-
-switchNode.prototype.ruleIsTrue = function (index) {
- index = index || 1;
- setT('true', index);
-}
-
-switchNode.prototype.ruleIsFalse = function (index) {
- index = index || 1;
- setT('false', index);
-}
-
-switchNode.prototype.ruleIsNull = function (index) {
- index = index || 1;
- setT('null', index);
-}
-
-switchNode.prototype.ruleIsNotNull = function (index) {
- index = index || 1;
- setT('nnull', index);
-}
-
-switchNode.prototype.ruleIsOfType = function (t, index) {
- index = index || 1;
- setT('istype', index);
-
- var tType = {
- "str": 1,
- "num": 2,
- "boolean": 3,
- "array": 4,
- "buffer": 5,
- "object": 6,
- "json": 7,
- "undefined": 8,
- "null": 9
- };
-
- if (t) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div[2]/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + tType[t] + ']');
- }
-}
-
-switchNode.prototype.ruleIsEmpty = function (index) {
- index = index || 1;
- setT('empty', index);
-}
-
-switchNode.prototype.ruleIsNotEmpty = function (index) {
- index = index || 1;
- setT('nempty', index);
-}
-
-switchNode.prototype.ruleHead = function (v, vt, index) {
- index = index || 1;
- setT('head', index);
- setSequenceV(v, vt, index);
-}
-
-switchNode.prototype.ruleIndexBetween = function (v, vt, v2, v2t, index) {
- index = index || 1;
- setT('index', index);
- setBetweenV(v, vt, v2, v2t, index);
-}
-
-switchNode.prototype.ruleTail = function (v, vt, index) {
- index = index || 1;
- setT('tail', index);
- setSequenceV(v, vt, index);
-}
-
-switchNode.prototype.ruleJSONataExp = function (v, index) {
- index = index || 1;
- setT('jsonata_exp', index);
- if (v) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div[2]/div[1]/input', v);
- }
-}
-
-switchNode.prototype.ruleOtherwise = function (index) {
- index = index || 1;
- setT('else', index);
-}
-
-switchNode.prototype.addRule = function () {
- browser.clickWithWait('//div[contains(@class, "red-ui-editableList")]/a');
-}
-
-module.exports = switchNode;
diff --git a/test/editor/pageobjects/nodes/core/function/15-change_page.js b/test/editor/pageobjects/nodes/core/function/15-change_page.js
deleted file mode 100644
index eb26f48aa..000000000
--- a/test/editor/pageobjects/nodes/core/function/15-change_page.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function changeNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(changeNode, nodePage);
-
-var totType = {
- "msg": 1,
- "flow": 2,
- "global": 3,
- "str": 4,
- "num": 5,
- "bool": 6,
- "json": 7,
- "bin": 8,
- "date": 9,
- "jsonata": 10,
- "env": 11,
-};
-
-var ptType = {
- "msg": 1,
- "flow": 2,
- "global": 3,
-};
-
-function setT(t, index) {
- browser.selectWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/select', t);
-}
-
-// It is better to create a function whose input value is the object type in the future,
-changeNode.prototype.ruleSet = function (p, pt, to, tot, index) {
- index = index || 1;
- setT('set', index);
- if (pt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + ptType[pt] + ']');
- }
- if (p) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', p);
- }
- if (tot) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + totType[tot] + ']');
- }
- if (to) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[2]/div[2]/div/input', to);
- }
-}
-
-changeNode.prototype.ruleChange = function (p, pt, from, fromt, to, tot, index) {
- index = index || 1;
- setT('change', index);
- if (pt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + ptType[pt] + ']');
- }
- if (p) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', p);
- }
- if (fromt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[3]/div[1]/div[2]/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + totType[pt] + ']');
- }
- if (from) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[3]/div[1]/div[2]/div[1]/input', from);
- }
- if (tot) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[3]/div[2]/div[2]/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + totType[pt] + ']');
- }
- if (to) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[3]/div[2]/div[2]/div[1]/input', to);
- }
-}
-
-changeNode.prototype.ruleDelete = function (p, pt, index) {
- index = index || 1;
- setT('delete', index);
- if (pt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + ptType[pt] + ']');
- }
- if (p) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', p);
- }
-}
-
-changeNode.prototype.ruleMove = function (p, pt, to, tot, index) {
- index = index || 1;
- setT('move', index);
- if (pt) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + ptType[pt] + ']');
- }
- if (p) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[1]/div/div/input', p);
- }
- if (tot) {
- browser.clickWithWait('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[4]/div[2]/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + totType[pt] + ']');
- }
- if (to) {
- browser.setValue('//*[@id="node-input-rule-container"]/li[' + index + ']/div/div[4]/div[2]/div/input', to);
- }
-}
-
-changeNode.prototype.addRule = function () {
- browser.clickWithWait('//div[contains(@class, "red-ui-editableList")]/a');
-}
-
-module.exports = changeNode;
diff --git a/test/editor/pageobjects/nodes/core/function/16-range_page.js b/test/editor/pageobjects/nodes/core/function/16-range_page.js
deleted file mode 100644
index 230929995..000000000
--- a/test/editor/pageobjects/nodes/core/function/16-range_page.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function rangeNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(rangeNode, nodePage);
-
-rangeNode.prototype.setAction = function(action) {
- browser.selectWithWait('#node-input-action', action);
-}
-
-rangeNode.prototype.setRange = function(minin, maxin, minout, maxout) {
- browser.setValue('#node-input-minin', minin);
- browser.setValue('#node-input-maxin', maxin);
- browser.setValue('#node-input-minout', minout);
- browser.setValue('#node-input-maxout', maxout);
-}
-
-module.exports = rangeNode;
diff --git a/test/editor/pageobjects/nodes/core/function/80-template_page.js b/test/editor/pageobjects/nodes/core/function/80-template_page.js
deleted file mode 100644
index bf1786ba2..000000000
--- a/test/editor/pageobjects/nodes/core/function/80-template_page.js
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-var keyPage = require("../../../util/key_page");
-
-function templateNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(templateNode, nodePage);
-
-templateNode.prototype.setSyntax = function (syntax) {
- browser.selectWithWait('#node-input-syntax', syntax);
-}
-
-templateNode.prototype.setFormat = function (format) {
- browser.selectWithWait('#node-input-format', format);
-}
-
-templateNode.prototype.setTemplate = function (template) {
- browser.clickWithWait('#node-input-template-editor');
- browser.keys(keyPage.selectAll());
- browser.keys(['Delete']);
- browser.keys(template);
- browser.keys(keyPage.selectToEnd());
- browser.keys(['Delete']);
- // Need to wait until ace editor correctly checks the syntax.
- browser.pause(300);
-}
-
-module.exports = templateNode;
diff --git a/test/editor/pageobjects/nodes/core/function/89-delay_page.js b/test/editor/pageobjects/nodes/core/function/89-delay_page.js
deleted file mode 100644
index 3604beb67..000000000
--- a/test/editor/pageobjects/nodes/core/function/89-delay_page.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function delayNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(delayNode, nodePage);
-
-delayNode.prototype.setTimeout = function (timeout) {
- browser.setValue('//*[@id="node-input-timeout"]', timeout);
-}
-
-module.exports = delayNode;
diff --git a/test/editor/pageobjects/nodes/core/function/89-trigger_page.js b/test/editor/pageobjects/nodes/core/function/89-trigger_page.js
deleted file mode 100644
index 5d24de380..000000000
--- a/test/editor/pageobjects/nodes/core/function/89-trigger_page.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function triggerNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(triggerNode, nodePage);
-
-triggerNode.prototype.setSend = function (send, sendt) {
- var sendType = {
- "flow": 1,
- "global": 2,
- "str": 3,
- "num": 4,
- "bool": 5,
- "json": 6,
- "bin": 7,
- "date": 8,
- "env": 9,
- "pay": 10,
- "nul": 11
- };
-
- if (sendt) {
- browser.clickWithWait('//*[@id="dialog-form"]/div[1]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + sendType[sendt] + ']');
- }
- if (send) {
- browser.setValue('//*[@id="dialog-form"]/div[1]/div/div[1]/input', send);
- }
-}
-
-triggerNode.prototype.setDuration = function (duration, units) {
- browser.setValue('//*[@id="node-input-duration"]', duration);
- if (units) {
- browser.selectWithWait('//*[@id="node-input-units"]', units);
- }
-}
-
-triggerNode.prototype.setThenSend = function (thenSend, thenSendt) {
- var thenSendType = {
- "flow": 1,
- "global": 2,
- "str": 3,
- "num": 4,
- "bool": 5,
- "json": 6,
- "bin": 7,
- "date": 8,
- "env": 9,
- "pay": 10,
- "payl": 11,
- "nul": 12
- };
-
- if (thenSendt) {
- browser.clickWithWait('//*[@id="dialog-form"]/div[5]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + thenSendType[thenSendt] + ']');
- }
- if (thenSend) {
- browser.setValue('//*[@id="dialog-form"]/div[5]/div/div[1]/input', thenSend);
- }
-}
-
-module.exports = triggerNode;
diff --git a/test/editor/pageobjects/nodes/core/function/90-exec_page.js b/test/editor/pageobjects/nodes/core/function/90-exec_page.js
deleted file mode 100644
index 69b8b6c9a..000000000
--- a/test/editor/pageobjects/nodes/core/function/90-exec_page.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function execNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(execNode, nodePage);
-
-execNode.prototype.setCommand = function (command) {
- browser.setValue('//*[@id="node-input-command"]', command);
-}
-
-execNode.prototype.setAppend = function (checkbox) {
- if (browser.isSelected('#node-input-addpay') !== checkbox) {
- browser.click('#node-input-addpay');
- }
-}
-
-module.exports = execNode;
diff --git a/test/editor/pageobjects/nodes/core/network/10-mqtt_page.js b/test/editor/pageobjects/nodes/core/network/10-mqtt_page.js
deleted file mode 100644
index 4bdd92336..000000000
--- a/test/editor/pageobjects/nodes/core/network/10-mqtt_page.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-var mqttBrokerNode = {};
-
-mqttBrokerNode.setServer = function (broker, port) {
- browser.setValue('#node-config-input-broker', broker);
- port = port ? port : 1883;
- browser.setValue('#node-config-input-port', port);
-};
-
-mqttBrokerNode.clickOk = function () {
- browser.clickWithWait('#node-config-dialog-ok');
- // Wait until an config dialog closes.
- browser.waitForVisible('#node-config-dialog-ok', 10000, true);
-};
-
-mqttBrokerNode.edit = function () {
- browser.waitForVisible('#node-input-lookup-broker');
- browser.click('#node-input-lookup-broker');
- // Wait until a config dialog opens.
- browser.waitForVisible('#node-config-dialog-ok', 10000);
-};
-
-function mqttInNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(mqttInNode, nodePage);
-
-mqttInNode.prototype.setTopic = function (topic) {
- browser.setValue('#node-input-topic', topic);
-};
-
-mqttInNode.prototype.setQoS = function (qos) {
- browser.selectWithWait('#node-input-qos', qos);
-};
-
-mqttInNode.prototype.mqttBrokerNode = mqttBrokerNode;
-module.exports.mqttInNode = mqttInNode;
-
-function mqttOutNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(mqttOutNode, nodePage);
-
-mqttOutNode.prototype.setTopic = function (topic) {
- browser.setValue('#node-input-topic', topic);
-};
-
-mqttOutNode.prototype.setRetain = function (retain) {
- browser.selectWithWait('#node-input-retain', retain);
-};
-
-mqttOutNode.prototype.mqttBrokerNode = mqttBrokerNode;
-module.exports.mqttOutNode = mqttOutNode;
diff --git a/test/editor/pageobjects/nodes/core/network/21-httpin_page.js b/test/editor/pageobjects/nodes/core/network/21-httpin_page.js
deleted file mode 100644
index 9454ef034..000000000
--- a/test/editor/pageobjects/nodes/core/network/21-httpin_page.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function httpInNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(httpInNode, nodePage);
-
-httpInNode.prototype.setMethod = function(method) {
- browser.selectWithWait('#node-input-method', method);
-}
-
-httpInNode.prototype.setUrl = function(url) {
- browser.setValue('#node-input-url', url);
-}
-
-module.exports = httpInNode;
diff --git a/test/editor/pageobjects/nodes/core/network/21-httprequest_page.js b/test/editor/pageobjects/nodes/core/network/21-httprequest_page.js
deleted file mode 100644
index b2ca812e3..000000000
--- a/test/editor/pageobjects/nodes/core/network/21-httprequest_page.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function httpRequestNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(httpRequestNode, nodePage);
-
-httpRequestNode.prototype.setUrl = function(url) {
- browser.setValue('#node-input-url', url);
-}
-
-httpRequestNode.prototype.setMethod = function(method) {
- browser.selectWithWait('#node-input-method', method);
-}
-
-httpRequestNode.prototype.setReturn = function(ret) {
- browser.selectWithWait('#node-input-ret', ret);
-}
-
-module.exports = httpRequestNode;
diff --git a/test/editor/pageobjects/nodes/core/network/21-httpresponse_page.js b/test/editor/pageobjects/nodes/core/network/21-httpresponse_page.js
deleted file mode 100644
index 7fb1886ce..000000000
--- a/test/editor/pageobjects/nodes/core/network/21-httpresponse_page.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function httpResponseNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(httpResponseNode, nodePage);
-
-module.exports = httpResponseNode;
diff --git a/test/editor/pageobjects/nodes/core/network/22-websocket_page.js b/test/editor/pageobjects/nodes/core/network/22-websocket_page.js
deleted file mode 100644
index 8f7dc261e..000000000
--- a/test/editor/pageobjects/nodes/core/network/22-websocket_page.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-var websocketListenerNode = {};
-
-websocketListenerNode.setPath = function (path) {
- browser.setValue('#node-config-input-path', path);
-};
-
-websocketListenerNode.setSendReceive = function (wholemsg) {
- browser.selectWithWait('#node-config-input-wholemsg', wholemsg);
-};
-
-websocketListenerNode.clickOk = function () {
- browser.clickWithWait('#node-config-dialog-ok');
- // Wait until an config dialog closes.
- browser.waitForVisible('#node-config-dialog-ok', 10000, true);
-};
-
-websocketListenerNode.edit = function () {
- browser.waitForVisible('#node-input-lookup-server');
- browser.click('#node-input-lookup-server');
- // Wait until a config dialog opens.
- browser.waitForVisible('#node-config-dialog-ok', 10000);
-};
-
-var websocketClientNode = {};
-
-websocketClientNode.setPath = function (path) {
- browser.setValue('#node-config-input-path', path);
-};
-
-websocketClientNode.setSendReceive = function (wholemsg) {
- browser.selectWithWait('#node-config-input-wholemsg', wholemsg);
-};
-
-websocketClientNode.clickOk = function () {
- browser.clickWithWait('#node-config-dialog-ok');
- // Wait until an config dialog closes.
- browser.waitForVisible('#node-config-dialog-ok', 10000, true);
-};
-
-websocketClientNode.edit = function () {
- browser.waitForVisible('#node-input-lookup-client');
- browser.click('#node-input-lookup-client');
- // Wait until a config dialog opens.
- browser.waitForVisible('#node-config-dialog-ok', 10000);
-};
-
-function websocketInNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(websocketInNode, nodePage);
-
-websocketInNode.prototype.setType = function (type) {
- browser.selectWithWait('#node-input-mode', type);
-};
-
-websocketInNode.prototype.websocketListenerNode = websocketListenerNode;
-websocketInNode.prototype.websocketClientNode = websocketClientNode;
-module.exports.websocketInNode = websocketInNode;
-
-function websocketOutNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(websocketOutNode, nodePage);
-
-websocketOutNode.prototype.setType = function (type) {
- browser.selectWithWait('#node-input-mode', type);
-};
-
-websocketOutNode.prototype.websocketListenerNode = websocketListenerNode;
-websocketOutNode.prototype.websocketClientNode = websocketClientNode;
-module.exports.websocketOutNode = websocketOutNode;
diff --git a/test/editor/pageobjects/nodes/core/parsers/70-CSV_page.js b/test/editor/pageobjects/nodes/core/parsers/70-CSV_page.js
deleted file mode 100644
index e4bc9502c..000000000
--- a/test/editor/pageobjects/nodes/core/parsers/70-CSV_page.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function csvNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(csvNode, nodePage);
-
-csvNode.prototype.setColumns = function (columns) {
- browser.setValue('#node-input-temp', columns);
-}
-
-csvNode.prototype.setSkipLines = function (skip) {
- browser.setValue('#node-input-skip', skip);
-}
-
-csvNode.prototype.setFirstRow4Names = function (checkbox) {
- if (browser.isSelected('#node-input-hdrin') !== checkbox) {
- browser.click('#node-input-hdrin');
- }
-}
-
-csvNode.prototype.setOutput = function (output) {
- browser.selectWithWait('#node-input-multi', output);
-}
-
-csvNode.prototype.setIncludeRow = function (checkbox) {
- if (browser.isSelected('#node-input-hdrout') !== checkbox) {
- browser.click('#node-input-hdrout');
- }
-}
-
-module.exports = csvNode;
diff --git a/test/editor/pageobjects/nodes/core/parsers/70-HTML_page.js b/test/editor/pageobjects/nodes/core/parsers/70-HTML_page.js
deleted file mode 100644
index 243e4c905..000000000
--- a/test/editor/pageobjects/nodes/core/parsers/70-HTML_page.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function htmlNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(htmlNode, nodePage);
-
-htmlNode.prototype.setSelector = function (tag) {
- browser.setValue('#node-input-tag', tag);
-}
-
-module.exports = htmlNode;
diff --git a/test/editor/pageobjects/nodes/core/parsers/70-JSON_page.js b/test/editor/pageobjects/nodes/core/parsers/70-JSON_page.js
deleted file mode 100644
index e0b31dd36..000000000
--- a/test/editor/pageobjects/nodes/core/parsers/70-JSON_page.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function jsonNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(jsonNode, nodePage);
-
-jsonNode.prototype.setAction = function (action) {
- browser.setValue('node-input-action', action);
-}
-
-jsonNode.prototype.setProperty = function (property) {
- browser.setValue('//*[contains(@class, "red-ui-typedInput-container")]/div[1]/input', property);
-}
-
-module.exports = jsonNode;
diff --git a/test/editor/pageobjects/nodes/core/parsers/70-XML_page.js b/test/editor/pageobjects/nodes/core/parsers/70-XML_page.js
deleted file mode 100644
index 696ec59cb..000000000
--- a/test/editor/pageobjects/nodes/core/parsers/70-XML_page.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function xmlNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(xmlNode, nodePage);
-
-xmlNode.prototype.setAction = function (action) {
- browser.setValue('node-input-action', action);
-}
-
-xmlNode.prototype.setProperty = function (property) {
- browser.setValue('//*[contains(@class, "red-ui-typedInput-container")]/div[1]/input', property);
-}
-
-module.exports = xmlNode;
diff --git a/test/editor/pageobjects/nodes/core/parsers/70-YAML_page.js b/test/editor/pageobjects/nodes/core/parsers/70-YAML_page.js
deleted file mode 100644
index 1002f3eb4..000000000
--- a/test/editor/pageobjects/nodes/core/parsers/70-YAML_page.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function yamlNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(yamlNode, nodePage);
-
-yamlNode.prototype.setAction = function (action) {
- browser.setValue('node-input-action', action);
-}
-
-yamlNode.prototype.setProperty = function (property) {
- browser.setValue('//*[contains(@class, "red-ui-typedInput-container")]/div[1]/input', property);
-}
-
-module.exports = yamlNode;
diff --git a/test/editor/pageobjects/nodes/core/sequence/17-split_page.js b/test/editor/pageobjects/nodes/core/sequence/17-split_page.js
deleted file mode 100644
index 8fc32ab1e..000000000
--- a/test/editor/pageobjects/nodes/core/sequence/17-split_page.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function splitNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(splitNode, nodePage);
-
-splitNode.prototype.setSplitUsing = function (splt, spltt) {
- var spltType = {
- "str": 1,
- "bin": 2,
- "len": 3
- };
-
- browser.clickWithWait('//*[@id="dialog-form"]/div[3]/div/button[1]');
- browser.clickWithWait('//div[contains(@class, "red-ui-typedInput-options") and not(contains(@style, "display: none"))]/a[' + spltType[spltt] + ']');
- browser.setValue('//*[@id="dialog-form"]/div[3]/div/div[1]/input', splt);
-};
-
-module.exports.splitNode = splitNode;
-
-function joinNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(joinNode, nodePage);
-
-module.exports.joinNode = joinNode;
diff --git a/test/editor/pageobjects/nodes/core/sequence/19-batch_page.js b/test/editor/pageobjects/nodes/core/sequence/19-batch_page.js
deleted file mode 100644
index 0d7b13028..000000000
--- a/test/editor/pageobjects/nodes/core/sequence/19-batch_page.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require('util');
-
-var nodePage = require('../../node_page');
-
-function batchNode(id) {
- nodePage.call(this, id);
-}
-
-batchNode.prototype.setMode = function (mode) {
- browser.selectWithWait('#node-input-mode', mode);
-}
-
-batchNode.prototype.setCount = function (count) {
- browser.setValue('#node-input-count', count);
-}
-
-batchNode.prototype.setOverlap = function (overlap) {
- browser.setValue('#node-input-overlap', overlap);
-}
-
-util.inherits(batchNode, nodePage);
-
-module.exports = batchNode;
diff --git a/test/editor/pageobjects/nodes/core/storage/10-filein_page.js b/test/editor/pageobjects/nodes/core/storage/10-filein_page.js
deleted file mode 100644
index 942ea63d8..000000000
--- a/test/editor/pageobjects/nodes/core/storage/10-filein_page.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var util = require("util");
-
-var nodePage = require("../../node_page");
-
-function fileInNode(id) {
- nodePage.call(this, id);
-}
-
-util.inherits(fileInNode, nodePage);
-
-var formatType = {
- "utf8": 1,
- "lines": 2,
- "": 3, // a single Buffer object
- "stream": 4
-};
-
-fileInNode.prototype.setFilename = function(filename) {
- browser.setValue('#node-input-filename', filename);
-}
-
-fileInNode.prototype.setOutput = function(format) {
- browser.clickWithWait('#node-input-format');
- var formatTypeXPath = '//*[@id="node-input-format"]/option[' + formatType[format] + ']';
- browser.clickWithWait(formatTypeXPath);
-}
-
-module.exports = fileInNode;
diff --git a/test/editor/pageobjects/nodes/node_page.js b/test/editor/pageobjects/nodes/node_page.js
deleted file mode 100644
index 03e734cab..000000000
--- a/test/editor/pageobjects/nodes/node_page.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-function Node(id) {
- this.id = '//*[@id="' + id + '"]';
-}
-
-Node.prototype.edit = function () {
- browser.waitForVisible(this.id);
- browser.moveToObject(this.id);
- browser.buttonDown();
- browser.buttonUp();
- browser.keys(['Enter']);
- // Wait until an edit dialog opens.
- browser.waitForVisible('#node-dialog-ok', 10000);
-}
-
-Node.prototype.clickOk = function () {
- browser.clickWithWait('#node-dialog-ok');
- // Wait untile an edit dialog closes.
- browser.waitForVisible('#node-dialog-ok', 10000, true);
- browser.pause(50);
-}
-
-Node.prototype.connect = function (targetNode, port) {
- port = port || 1;
- var outputPort = this.id + '/*[@class="red-ui-flow-port-output"][' + port + ']';
- var inputPort = targetNode.id + '/*[@class="red-ui-flow-port-input"]';
- browser.dragAndDrop(outputPort, inputPort);
-}
-
-Node.prototype.clickLeftButton = function () {
- browser.moveToObject(this.id + '/*[@class="red-ui-flow-node-button"]');
- browser.buttonDown();
- browser.buttonUp();
-}
-
-module.exports = Node;
diff --git a/test/editor/pageobjects/nodes/nodefactory_page.js b/test/editor/pageobjects/nodes/nodefactory_page.js
deleted file mode 100644
index 008ecc625..000000000
--- a/test/editor/pageobjects/nodes/nodefactory_page.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var injectNode = require('./core/common/20-inject_page');
-var debugNode = require('./core/common/21-debug_page');
-var completeNode = require('./core/common/24-complete_page');
-var catchNode = require('./core/common/25-catch_page');
-var statusNode = require('./core/common/25-status_page');
-var commentNode = require('./core/common/90-comment_page');
-var functionNode = require('./core/function/10-function_page');
-var switchNode = require('./core/function/10-switch_page');
-var changeNode = require('./core/function/15-change_page');
-var rangeNode = require('./core/function/16-range_page');
-var templateNode = require('./core/function/80-template_page');
-var delayNode = require('./core/function/89-delay_page');
-var triggerNode = require('./core/function/89-trigger_page');
-var execNode = require('./core/function/90-exec_page');
-var mqttInNode = require('./core/network/10-mqtt_page').mqttInNode;
-var mqttOutNode = require('./core/network/10-mqtt_page').mqttOutNode;
-var httpInNode = require('./core/network/21-httpin_page');
-var httpResponseNode = require('./core/network/21-httpresponse_page');
-var httpRequestNode = require('./core/network/21-httprequest_page');
-var websocketInNode = require('./core/network/22-websocket_page').websocketInNode;
-var websocketOutNode = require('./core/network/22-websocket_page').websocketOutNode;
-var splitNode = require('./core/sequence/17-split_page').splitNode;
-var joinNode = require('./core/sequence/17-split_page').joinNode;
-var batchNode = require('./core/sequence/19-batch_page');
-var csvNode = require('./core/parsers/70-CSV_page');
-var htmlNode = require('./core/parsers/70-HTML_page');
-var jsonNode = require('./core/parsers/70-JSON_page');
-var xmlNode = require('./core/parsers/70-XML_page');
-var yamlNode = require('./core/parsers/70-YAML_page');
-var fileInNode = require('./core/storage/10-filein_page');
-
-var nodeCatalog = {
- // common
- "inject": injectNode,
- "debug": debugNode,
- "complete": completeNode,
- "catch": catchNode,
- "status": statusNode,
- "comment": commentNode,
- // function
- "function": functionNode,
- "switch": switchNode,
- "change": changeNode,
- "range": rangeNode,
- "template": templateNode,
- "delay": delayNode,
- "trigger": triggerNode,
- "exec": execNode,
- // network
- "mqttIn": mqttInNode,
- "mqttOut": mqttOutNode,
- "httpIn": httpInNode,
- "httpResponse": httpResponseNode,
- "httpRequest": httpRequestNode,
- "websocketIn": websocketInNode,
- "websocketOut": websocketOutNode,
- // sequence
- "split": splitNode,
- "join": joinNode,
- "batch": batchNode,
- // parser
- "csv": csvNode,
- "html": htmlNode,
- "json": jsonNode,
- "xml": xmlNode,
- "yaml": yamlNode,
- // storage
- "fileIn": fileInNode
-};
-
-function create(type, id) {
- var Node = nodeCatalog[type];
- return new Node(id);
-}
-
-module.exports = {
- create: create,
-};
diff --git a/test/editor/pageobjects/util/key_page.js b/test/editor/pageobjects/util/key_page.js
deleted file mode 100644
index 497a8a141..000000000
--- a/test/editor/pageobjects/util/key_page.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var os = require("os");
-
-var shortCutKeyMap = {
- "selectAll": ['Control', 'a', 'a', 'Control'],
- "selectToEnd": ['Control', 'Shift', 'End', 'Shift', 'Control'],
-};
-
-var shortCutKeyMapForMac = {
- "selectAll": ['Command', 'a', 'a', 'Command'],
- "selectToEnd": ['Command', 'Shift', 'ArrowDown', 'Shift', 'Command'],
-};
-
-function getShortCutKey(type) {
- if (process.env.BROWSERSTACK) {
- if (browser.desiredCapabilities.os === 'OS X') {
- return shortCutKeyMapForMac[type];
- }
- return shortCutKeyMap[type];
- }
- if (os.type() === 'Darwin') {
- return shortCutKeyMapForMac[type];
- }
- return shortCutKeyMap[type];
-}
-
-function selectAll() {
- var key = getShortCutKey('selectAll');
- return key;
-}
-
-function selectToEnd() {
- var key = getShortCutKey('selectToEnd');
- return key;
-}
-
-module.exports = {
- selectAll: selectAll,
- selectToEnd: selectToEnd,
-};
diff --git a/test/editor/pageobjects/util/spec_util_page.js b/test/editor/pageobjects/util/spec_util_page.js
deleted file mode 100644
index f64743664..000000000
--- a/test/editor/pageobjects/util/spec_util_page.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-function pause(msec) {
- browser.pause(msec);
-}
-
- module.exports = {
- pause: pause,
- };
diff --git a/test/editor/pageobjects/util/util_page.js b/test/editor/pageobjects/util/util_page.js
deleted file mode 100644
index 3a764eb93..000000000
--- a/test/editor/pageobjects/util/util_page.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var waitTime = 5000;
-
-function repeatUntilSuccess(operation, args) {
- // Wait at most 10 seconds.
- for (var i = 0; i < 200; i++) {
- try {
- var ret = operation(args);
- return ret;
- } catch (e) {
- if (i === 199) {
- console.trace();
- throw e;
- }
- browser.pause(50);
- }
- }
-}
-
-function init() {
- browser.addCommand("clickWithWait", function(selector) {
- try {
- // This is necessary because there is a case that the target may exist but still moving.
- browser.pause(50);
- browser.waitForVisible(selector);
-
- var ret = repeatUntilSuccess(function(selector) {
- return browser.click(selector);
- }, selector);
- return ret;
- } catch (e) {
- console.trace();
- throw e;
- }
- }, false);
-
- browser.addCommand("getTextWithWait", function(selector) {
- try {
- browser.waitForExist(selector);
- browser.waitForValue(selector);
-
- var ret = repeatUntilSuccess(function(selector) {
- return browser.getText(selector);
- }, selector);
- return ret;
- } catch (e) {
- console.trace();
- throw e;
- }
- }, false);
-
- browser.addCommand("selectWithWait", function(selector, value) {
- try {
- browser.waitForVisible(selector, waitTime);
-
- var ret = repeatUntilSuccess(function(args) {
- return browser.selectByValue(args[0], args[1]);
- }, [selector, value.toString()]);
- return ret;
- } catch (e) {
- console.trace();
- throw e;
- }
- }, false);
-}
-
- module.exports = {
- init: init,
- };
diff --git a/test/editor/specs/editor/workspace_uispec.js b/test/editor/specs/editor/workspace_uispec.js
deleted file mode 100644
index 15de1a044..000000000
--- a/test/editor/specs/editor/workspace_uispec.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require('when');
-var should = require("should");
-var fs = require('fs-extra');
-
-var helper = require("../../editor_helper");
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-
-
-describe('Workspace', function() {
- beforeEach(function() {
- workspace.init();
- });
-
- before(function() {
- helper.startServer();
- });
-
- after(function() {
- helper.stopServer();
- });
-
- it('should have a right title', function () {
- browser.getTitle().should.startWith('Node-RED');
- });
-
- it('should output a timestamp', function() {
- var injectNode = workspace.addNode("inject");
- var debugNode = workspace.addNode("debug");
- injectNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.within(1500000000000, 3000000000000);
- });
-
-});
diff --git a/test/editor/specs/scenario/cookbook_dataformats_uispec.js b/test/editor/specs/scenario/cookbook_dataformats_uispec.js
deleted file mode 100644
index 8321bd924..000000000
--- a/test/editor/specs/scenario/cookbook_dataformats_uispec.js
+++ /dev/null
@@ -1,364 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require('when');
-var should = require('should');
-var fs = require('fs-extra');
-
-var helper = require('../../editor_helper');
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-var specUtil = require('../../pageobjects/util/spec_util_page');
-
-var httpNodeRoot = '/api';
-
-// https://cookbook.nodered.org/
-describe('cookbook', function () {
- beforeEach(function () {
- workspace.init();
- });
-
- before(function () {
- helper.startServer();
- });
-
- after(function () {
- helper.stopServer();
- });
-
- describe('working with data formats', function () {
- it('convert to/from JSON', function () {
- var injectNode1 = workspace.addNode('inject');
- var jsonNode1 = workspace.addNode('json');
- var debugNode1 = workspace.addNode('debug');
-
- injectNode1.edit();
- injectNode1.setPayload('str', '{"a":1}');
- injectNode1.clickOk();
-
- jsonNode1.edit();
- jsonNode1.setProperty('payload');
- jsonNode1.clickOk();
-
- injectNode1.connect(jsonNode1);
- jsonNode1.connect(debugNode1);
-
- var injectNode2 = workspace.addNode('inject');
- var jsonNode2 = workspace.addNode('json');
- var debugNode2 = workspace.addNode('debug');
-
- injectNode2.edit();
- injectNode2.setPayload('json', '{"a":1}');
- injectNode2.clickOk();
-
- jsonNode2.edit();
- jsonNode2.setProperty('payload');
- jsonNode2.clickOk();
-
- injectNode2.connect(jsonNode2);
- jsonNode2.connect(debugNode2);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode1.clickLeftButton();
- debugTab.getMessage().should.eql('1');
- debugTab.clearMessage();
- injectNode2.clickLeftButton();
- debugTab.getMessage().should.eql('"{"a":1}"');
- });
-
- it('convert to/from XML', function () {
- var injectNode1 = workspace.addNode('inject', 0);
- var templateNode1 = workspace.addNode('template', 200);
- var xmlNode1 = workspace.addNode('xml', 400);
- var debugNode1 = workspace.addNode('debug', 600);
-
- injectNode1.edit();
- injectNode1.setPayload('str', '{"a":1}');
- injectNode1.clickOk();
-
- templateNode1.edit();
- templateNode1.setFormat('text');
- templateNode1.setSyntax('plain');
- templateNode1.setTemplate(''
- + ' Nick '
- + ' Dave '
- + ' Reminder '
- + ' Update the website'
- + ' ');
- templateNode1.clickOk();
-
- xmlNode1.edit();
- xmlNode1.setProperty('payload');
- xmlNode1.clickOk();
-
- injectNode1.connect(templateNode1);
- templateNode1.connect(xmlNode1);
- xmlNode1.connect(debugNode1);
-
- var injectNode2 = workspace.addNode('inject');
- var xmlNode2 = workspace.addNode('xml');
- var debugNode2 = workspace.addNode('debug');
-
- injectNode2.edit();
- injectNode2.setPayload('json', '{'
- + ' "note": {'
- + ' "$": { "priority": "high" },'
- + ' "to": [ "Nick" ],'
- + ' "from": [ "Dave" ],'
- + ' "heading": [ "Reminder" ],'
- + ' "body": [ "Update the website" ]'
- + ' }'
- + '}');
- injectNode2.clickOk();
-
- xmlNode2.edit();
- xmlNode2.setProperty('payload');
- xmlNode2.clickOk();
-
- injectNode2.connect(xmlNode2);
- xmlNode2.connect(debugNode2);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode1.clickLeftButton();
- debugTab.getMessage().should.eql('object');
- debugTab.clearMessage();
- injectNode2.clickLeftButton();
- debugTab.getMessage().should.eql('"'
- + ''
- + 'Nick '
- + 'Dave '
- + 'Reminder '
- + 'Update the website'
- + ' "');
- });
-
- it('convert to/from YAML', function () {
- var injectNode1 = workspace.addNode('inject', 0);
- var templateNode1 = workspace.addNode('template', 200);
- var yamlNode1 = workspace.addNode('yaml', 400);
- var debugNode1 = workspace.addNode('debug', 600);
-
- injectNode1.edit();
- injectNode1.setPayload('str', '{"a":1}');
- injectNode1.clickOk();
-
- templateNode1.edit();
- templateNode1.setFormat('yaml');
- templateNode1.setSyntax('plain');
- templateNode1.setTemplate('a: 1\n'
- + 'b:\n'
- + ' - 1\n'
- + '- 2\n'
- + '- 3');
- templateNode1.clickOk();
-
- yamlNode1.edit();
- yamlNode1.setProperty('payload');
- yamlNode1.clickOk();
-
- injectNode1.connect(templateNode1);
- templateNode1.connect(yamlNode1);
- yamlNode1.connect(debugNode1);
-
- var injectNode2 = workspace.addNode('inject');
- var yamlNode2 = workspace.addNode('yaml');
- var debugNode2 = workspace.addNode('debug');
-
- injectNode2.edit();
- injectNode2.setPayload('json', '{"a":1, "b":[1,2,3]}');
- injectNode2.clickOk();
-
- yamlNode2.edit();
- yamlNode2.setProperty('payload');
- yamlNode2.clickOk();
-
- injectNode2.connect(yamlNode2);
- yamlNode2.connect(debugNode2);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode1.clickLeftButton();
- debugTab.getMessage().should.eql([ '1', 'array[3]' ]);
- debugTab.clearMessage();
- injectNode2.clickLeftButton();
- debugTab.getMessage().should.eql('"a: 1↵b:↵ - 1↵ - 2↵ - 3↵"');
- });
-
- it('generate CSV output', function () {
- var injectNode1 = workspace.addNode('inject', 0);
- var changeNode1 = workspace.addNode('change', 200);
- var csvNode1 = workspace.addNode('csv', 400);
- var debugNode1 = workspace.addNode('debug', 600);
-
- changeNode1.edit();
- changeNode1.ruleSet('payload', 'msg', '{'
- + ' "a": $floor(100*$random()),'
- + ' "b": $floor(100*$random()),'
- + ' "c": $floor(100*$random())'
- + '}', 'jsonata');
- changeNode1.clickOk();
-
- csvNode1.edit();
- csvNode1.setColumns('a,b,c');
- csvNode1.clickOk();
-
- injectNode1.connect(changeNode1);
- changeNode1.connect(csvNode1);
- csvNode1.connect(debugNode1);
-
- var injectNode2 = workspace.addNode('inject', 0, 80);
- var changeNode2 = workspace.addNode('change', 200, 80);
- var csvNode2 = workspace.addNode('csv', 400, 80);
- var debugNode2 = workspace.addNode('debug', 600, 80);
-
- changeNode2.edit();
- changeNode2.ruleSet('payload', 'msg', '['
- + ' {'
- + ' "a": $floor(100*$random()),'
- + ' "b": $floor(100*$random()),'
- + ' "c": $floor(100*$random())'
- + ' }, {'
- + ' "a": $floor(100*$random()),'
- + ' "b": $floor(100*$random()),'
- + ' "c": $floor(100*$random())'
- + ' }, {'
- + ' "a": $floor(100*$random()),'
- + ' "b": $floor(100*$random()),'
- + ' "c": $floor(100*$random())'
- + ' }, {'
- + ' "a": $floor(100*$random()),'
- + ' "b": $floor(100*$random()),'
- + ' "c": $floor(100*$random())'
- + ' }'
- + ']', 'jsonata');
- changeNode2.clickOk();
-
- csvNode2.edit();
- csvNode2.setColumns('a,b,c');
- csvNode2.setIncludeRow(true);
- csvNode2.clickOk();
-
- injectNode2.connect(changeNode2);
- changeNode2.connect(csvNode2);
- csvNode2.connect(debugNode2);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode1.clickLeftButton();
- debugTab.getMessage().should.match(/^"([1-9]?[0-9],){2}[1-9]?[0-9]↵"$/);
- debugTab.clearMessage();
- injectNode2.clickLeftButton();
- debugTab.getMessage().should.match(/^"(([1-9]?[0-9],){2}[1-9]?[0-9]↵){4}"$/);
- });
-
- it('parse CSV input', function () {
- var injectNode = workspace.addNode('inject');
- var templateNode = workspace.addNode('template');
- var csvNode = workspace.addNode('csv');
- var debugNode = workspace.addNode('debug');
-
- templateNode.edit();
- templateNode.setFormat('handlebars');
- templateNode.setSyntax('mustache');
- templateNode.setTemplate('# This is some random data\n'
- + 'a,b,c\n'
- + '80,18,2\n'
- + '52,36,10\n'
- + '91,18,61\n'
- + '32,47,65');
- templateNode.clickOk();
-
- csvNode.edit();
- csvNode.setSkipLines(1);
- csvNode.setFirstRow4Names(true);
- csvNode.setOutput('mult');
- csvNode.clickOk();
-
- injectNode.connect(templateNode);
- templateNode.connect(csvNode);
- csvNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql([ 'object', 'object', 'object', 'object' ]);
- });
-
- it('simple GET request', function () {
- var injectNode = workspace.addNode('inject');
- var httpRequestNode = workspace.addNode('httpRequest');
- var htmlNode = workspace.addNode('html');
- var debugNode = workspace.addNode('debug');
-
- httpRequestNode.edit();
- httpRequestNode.setMethod('GET');
- httpRequestNode.setUrl('https://nodered.org');
- httpRequestNode.clickOk();
-
- htmlNode.edit();
- htmlNode.setSelector('.node-red-latest-version');
- htmlNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(htmlNode);
- htmlNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.match(/^"v[0-9]+\.[0-9]+\.[0-9]"$/);
- });
-
- it('split text into one message per line', function () {
- var injectNode = workspace.addNode('inject');
- var templateNode = workspace.addNode('template');
- var splitNode = workspace.addNode('split');
- var changeNode = workspace.addNode('change');
- var joinNode = workspace.addNode('join');
- var debugNode = workspace.addNode('debug');
-
- templateNode.edit();
- templateNode.setFormat('handlebars');
- templateNode.setSyntax('mustache');
- templateNode.setTemplate('one\ntwo\nthree\nfour\nfive');
- templateNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet('payload', 'msg', '(parts.index+1) & ": " & payload', 'jsonata');
- changeNode.clickOk();
-
- injectNode.connect(templateNode);
- templateNode.connect(splitNode);
- splitNode.connect(changeNode);
- changeNode.connect(joinNode);
- joinNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"1: one↵2: two↵3: three↵4: four↵5: five"');
- });
- });
-});
diff --git a/test/editor/specs/scenario/cookbook_errorhandling_uispec.js b/test/editor/specs/scenario/cookbook_errorhandling_uispec.js
deleted file mode 100644
index 5285c5c0f..000000000
--- a/test/editor/specs/scenario/cookbook_errorhandling_uispec.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require('when');
-var should = require('should');
-var fs = require('fs-extra');
-
-var helper = require('../../editor_helper');
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-var specUtil = require('../../pageobjects/util/spec_util_page');
-
-var httpNodeRoot = '/api';
-
-// https://cookbook.nodered.org/
-describe('cookbook', function () {
- beforeEach(function () {
- workspace.init();
- });
-
- before(function () {
- helper.startServer();
- });
-
- after(function () {
- helper.stopServer();
- });
-
- describe('messages', function () {
- it('trigger a flow when a node throws an error', function () {
- var injectNode = workspace.addNode('inject');
- var functionNode = workspace.addNode('function');
- var catchNode = workspace.addNode('catch', 0 , 80);
- var debugNode = workspace.addNode('debug');
-
- functionNode.edit();
- functionNode.setFunction('node.error("an example error", msg);');
- functionNode.clickOk();
-
- catchNode.edit();
- catchNode.setScope(functionNode);
- catchNode.clickOk();
-
- debugNode.edit();
- debugNode.setOutput('error');
- debugNode.clickOk();
-
- injectNode.connect(functionNode);
- catchNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql(['"an example error"', 'function']);
- });
-
- // skip this case since the flow outputs random results.
- it.skip('automatically retry an action after an error');
- });
-});
diff --git a/test/editor/specs/scenario/cookbook_flowcontrol_uispec.js b/test/editor/specs/scenario/cookbook_flowcontrol_uispec.js
deleted file mode 100644
index 724d1c56f..000000000
--- a/test/editor/specs/scenario/cookbook_flowcontrol_uispec.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require('when');
-var should = require('should');
-var fs = require('fs-extra');
-
-var helper = require('../../editor_helper');
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-var specUtil = require('../../pageobjects/util/spec_util_page');
-
-var httpNodeRoot = '/api';
-
-// https://cookbook.nodered.org/
-describe('cookbook', function () {
- beforeEach(function () {
- workspace.init();
- });
-
- before(function () {
- helper.startServer();
- });
-
- after(function () {
- helper.stopServer();
- });
-
- describe('flow control', function () {
- it('trigger a flow whenever Node-RED starts', function () {
- var injectNode = workspace.addNode('inject');
- var debugNode = workspace.addNode('debug');
-
- injectNode.edit();
- injectNode.setPayload('str', 'Started!');
- injectNode.setOnce(true);
- injectNode.clickOk();
- injectNode.connect(debugNode);
-
- debugTab.open();
- workspace.deploy();
- debugTab.getMessage().should.eql('"Started!"');
- });
-
- it('trigger a flow at regular intervals', function () {
- var injectNode = workspace.addNode('inject');
- var debugNode = workspace.addNode('debug');
-
- injectNode.edit();
- injectNode.setRepeat('interval');
- injectNode.setRepeatInterval(1);
- injectNode.clickOk();
- injectNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- specUtil.pause(1000);
- var t1 = Number(debugTab.getMessage(1));
- t1.should.within(1500000000000, 3000000000000);
- specUtil.pause(1000);
- debugTab.getMessage(2).should.within(t1 + 900, 3000000000000);
- });
-
- // skip this case since it needs up to one minite.
- it.skip('trigger a flow at a specific time');
- });
-});
diff --git a/test/editor/specs/scenario/cookbook_httpendpoints_uispec.js b/test/editor/specs/scenario/cookbook_httpendpoints_uispec.js
deleted file mode 100644
index 134498370..000000000
--- a/test/editor/specs/scenario/cookbook_httpendpoints_uispec.js
+++ /dev/null
@@ -1,572 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-
-var helper = require("../../editor_helper");
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-
-var httpNodeRoot = "/api";
-
-// https://cookbook.nodered.org/
-describe('cookbook', function () {
- beforeEach(function () {
- workspace.init();
- });
-
- before(function () {
- helper.startServer();
- });
-
- after(function () {
- helper.stopServer();
- });
-
- describe('HTTP endpoints', function () {
- it('create an HTTP endpoint', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("get");
- httpInNode.setUrl("/hello");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nHello World! \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject");
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello');
- httpRequestNode.setMethod("GET");
- httpRequestNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Hello World!').should.not.eql(-1);
- });
-
- it('handle query parameters passed to an HTTP endpoint', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("get");
- httpInNode.setUrl("/hello-query");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nHello {{req.query.name}}! \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject");
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-query?name=Nick');
- httpRequestNode.setMethod("GET");
- httpRequestNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1);
- });
-
- it('handle url parameters in an HTTP endpoint', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("get");
- httpInNode.setUrl("/hello-param/:name");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nHello {{req.params.name}}! \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject");
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-param/Dave');
- httpRequestNode.setMethod("GET");
- httpRequestNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Hello Dave!').should.not.eql(-1);
- });
-
- it('access HTTP request headers', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("get");
- httpInNode.setUrl("/hello-headers");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nUser agent: {{req.headers.user-agent}} \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject", 0, 100);
- var changeNode = workspace.addNode("change");
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- changeNode.edit();
- changeNode.ruleSet("headers", "msg", '{"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}', "json");
- changeNode.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-headers');
- httpRequestNode.setMethod("GET");
- httpRequestNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Mozilla').should.not.eql(-1);
- });
-
- it('include data captured in another flow', function () {
- var injectNodeTimestamp = workspace.addNode("inject");
- var changeNodeStore = workspace.addNode("change");
-
- var httpInNode = workspace.addNode("httpIn", 0, 100);
- var changeNodeCopy = workspace.addNode("change");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- injectNodeTimestamp.edit();
- injectNodeTimestamp.setPayload("date");
- injectNodeTimestamp.clickOk();
-
- changeNodeStore.edit();
- changeNodeStore.ruleSet("timestamp", "flow", "payload", "msg");
- changeNodeStore.clickOk();
-
- injectNodeTimestamp.connect(changeNodeStore);
-
- httpInNode.edit();
- httpInNode.setMethod("get");
- httpInNode.setUrl("/hello-data");
- httpInNode.clickOk();
-
- changeNodeCopy.edit();
- changeNodeCopy.ruleSet("timestamp", "msg", "timestamp", "flow");
- changeNodeCopy.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nTime: {{ timestamp }} \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(changeNodeCopy);
- changeNodeCopy.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNodeCheck = workspace.addNode("inject", 0, 300);
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- httpRequestNode.edit();
- httpRequestNode.setMethod("GET");
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-data');
- httpRequestNode.clickOk();
-
- injectNodeCheck.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNodeTimestamp.clickLeftButton();
- injectNodeCheck.clickLeftButton();
- var index = debugTab.getMessage().indexOf('Time: ') + 6;
- debugTab.getMessage().substring(index, index + 13).should.within(1500000000000, 3000000000000);
- });
-
- it('serve JSON content', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var changeNode = workspace.addNode("change");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("get");
- httpInNode.setUrl("/hello-json");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate('{ "Hello": "World" }');
- templateNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet("headers", "msg", "{}", "json", "1");
- changeNode.addRule();
- changeNode.ruleSet("headers.content-type", "msg", "application/json", "str", "2");
- changeNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(changeNode);
- changeNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject", 0, 200);
- var httpRequestNode = workspace.addNode("httpRequest");
- var changeNodeCheck = workspace.addNode("change");
- var debugNode = workspace.addNode("debug");
-
- httpRequestNode.edit();
- httpRequestNode.setMethod("GET");
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-json');
- httpRequestNode.clickOk();
-
- changeNodeCheck.edit();
- changeNodeCheck.ruleSet("payload", "msg", "headers.content-type", "msg", "1");
- changeNodeCheck.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(changeNodeCheck);
- changeNodeCheck.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- var messages = debugTab.getMessage();
- messages.indexOf('application/json').should.not.eql(-1);
- });
-
- it('serve a local file', function () {
- var httpInNode = workspace.addNode("httpIn");
- var fileInNode = workspace.addNode("fileIn");
- var changeNode = workspace.addNode("change", 200, 100);
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("get");
- httpInNode.setUrl("/hello-file");
- httpInNode.clickOk();
-
- fileInNode.edit();
- fileInNode.setFilename("test/resources/file-in-node/test.txt");
- fileInNode.setOutput("");
- fileInNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet("headers", "msg", "{}", "json");
- changeNode.addRule();
- changeNode.ruleSet("headers.content-type", "msg", "text/plain", "str", "2");
- changeNode.clickOk();
-
- httpInNode.connect(fileInNode);
- fileInNode.connect(changeNode);
- changeNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject", 0, 200);
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-file');
- httpRequestNode.setMethod("GET");
- httpRequestNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Text file').should.not.eql(-1);
- });
-
- it('post raw data to a flow', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("post");
- httpInNode.setUrl("/hello-raw");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nHello {{ payload }}! \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject");
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- injectNode.edit();
- injectNode.setPayload("str", "Nick");
- injectNode.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-raw');
- httpRequestNode.setMethod("POST");
- httpRequestNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1);
- });
-
- it('post form data to a flow', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("post");
- httpInNode.setUrl("/hello-form");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nHello {{ payload.name }}! \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject", 0, 100);
- var changeNode = workspace.addNode("change");
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- injectNode.edit();
- injectNode.setPayload("str", "name=Nick");
- injectNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet("headers", "msg", '{"content-type":"application/x-www-form-urlencoded"}', "json");
- changeNode.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-form');
- httpRequestNode.setMethod("POST");
- httpRequestNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1);
- });
-
- it('post JSON data to a flow', function () {
- var httpInNode = workspace.addNode("httpIn");
- var templateNode = workspace.addNode("template");
- var httpResponseNode = workspace.addNode("httpResponse");
-
- httpInNode.edit();
- httpInNode.setMethod("post");
- httpInNode.setUrl("/hello-json");
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate("\n\n\nHello {{ payload.name }}! \n\n");
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- // The code for confirmation starts from here.
- var injectNode = workspace.addNode("inject", 0, 100);
- var changeNode = workspace.addNode("change");
- var httpRequestNode = workspace.addNode("httpRequest");
- var debugNode = workspace.addNode("debug");
-
- injectNode.edit();
- injectNode.setPayload("json", '{"name":"Nick"}');
- injectNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet("headers", "msg", '{"content-type":"application/json"}', "json");
- changeNode.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/hello-json');
- httpRequestNode.setMethod("POST");
- httpRequestNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().indexOf('Hello Nick!').should.not.eql(-1);
- });
-
- it('work with cookies', function () {
- var httpInNodeFormat = workspace.addNode("httpIn");
- var functionNodeFormat = workspace.addNode("function", 240);
- var templateNode = workspace.addNode("template", 400);
- var httpResponseNode = workspace.addNode("httpResponse", 600);
-
- var httpInNodeAdd = workspace.addNode("httpIn", 0, 100);
- var functionNodeAdd = workspace.addNode("function", 240);
- var changeNode = workspace.addNode("change", 400);
-
- var httpInNodeClear = workspace.addNode("httpIn", 0, 200);
- var functionNodeClear = workspace.addNode("function", 250);
-
- httpInNodeFormat.edit();
- httpInNodeFormat.setMethod("get");
- httpInNodeFormat.setUrl("/hello-cookie");
- httpInNodeFormat.clickOk();
-
- functionNodeFormat.edit();
- functionNodeFormat.setFunction("msg.payload = JSON.stringify(msg.req.cookies,null,4);\nreturn msg;");
- functionNodeFormat.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax("mustache");
- templateNode.setFormat("handlebars");
- templateNode.setTemplate('\n\n\nCookies \n
Add a cookie • Clear cookies
\n{{ payload }} \n\n');
- templateNode.clickOk();
-
- httpInNodeFormat.connect(functionNodeFormat);
- functionNodeFormat.connect(templateNode);
- templateNode.connect(httpResponseNode);
-
- httpInNodeAdd.edit();
- httpInNodeAdd.setMethod("get");
- httpInNodeAdd.setUrl("/hello-cookie/add");
- httpInNodeAdd.clickOk();
-
- functionNodeAdd.edit();
- functionNodeAdd.setFunction('msg.cookies = { };\n msg.cookies["demo-"+(Math.floor(Math.random()*1000))] = Date.now();\nreturn msg;');
- functionNodeAdd.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet("statusCode", "msg", "302", "num");
- changeNode.addRule();
- changeNode.ruleSet("headers", "msg", "{}", "json", "2");
- changeNode.addRule();
- changeNode.ruleSet("headers.location", "msg", httpNodeRoot + "/hello-cookie", "str", "3");
- changeNode.clickOk();
-
- httpInNodeAdd.connect(functionNodeAdd);
- functionNodeAdd.connect(changeNode);
- changeNode.connect(httpResponseNode);
-
- httpInNodeClear.edit();
- httpInNodeClear.setMethod("get");
- httpInNodeClear.setUrl("/hello-cookie/clear");
- httpInNodeClear.clickOk();
-
- functionNodeClear.edit();
- functionNodeClear.setFunction("var cookieNames = Object.keys(msg.req.cookies).filter(function(cookieName) { return /^demo-/.test(cookieName);});\nmsg.cookies = {};\n\ncookieNames.forEach(function(cookieName) {\n msg.cookies[cookieName] = null;\n});\nreturn msg;\n");
- functionNodeClear.clickOk();
-
- httpInNodeClear.connect(functionNodeClear);
- functionNodeClear.connect(changeNode);
-
- workspace.deploy();
- // This case cannot be checked since http request node does not transfer cookies when redirected.
- });
- });
-});
diff --git a/test/editor/specs/scenario/cookbook_httprequests_uispec.js b/test/editor/specs/scenario/cookbook_httprequests_uispec.js
deleted file mode 100644
index 797b06041..000000000
--- a/test/editor/specs/scenario/cookbook_httprequests_uispec.js
+++ /dev/null
@@ -1,300 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require('when');
-var should = require('should');
-var fs = require('fs-extra');
-
-var helper = require('../../editor_helper');
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-var specUtil = require('../../pageobjects/util/spec_util_page');
-
-var httpNodeRoot = '/api';
-
-// https://cookbook.nodered.org/
-describe('cookbook', function () {
- beforeEach(function () {
- workspace.init();
- });
-
- before(function () {
- helper.startServer();
- });
-
- after(function () {
- helper.stopServer();
- });
-
- describe('HTTP requests', function () {
- it('simple get request', function () {
- var injectNode = workspace.addNode('inject');
- var httpRequestNode = workspace.addNode('httpRequest');
- var htmlNode = workspace.addNode('html');
- var debugNode = workspace.addNode('debug');
-
- httpRequestNode.edit();
- httpRequestNode.setMethod('GET');
- httpRequestNode.setUrl(helper.url());
- httpRequestNode.clickOk();
-
- htmlNode.edit();
- htmlNode.setSelector('title');
- htmlNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(htmlNode);
- htmlNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"Node-RED"');
- });
-
- it('set the URL of a request', function () {
- var injectNode = workspace.addNode('inject');
- var changeNode = workspace.addNode('change');
- var httpRequestNode = workspace.addNode('httpRequest');
- var debugNode = workspace.addNode('debug');
-
- injectNode.edit();
- injectNode.setPayload('str', helper.url());
- injectNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet('url', 'msg', 'payload', 'msg');
- changeNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.containEql('Node-RED ');
- });
-
- it('set the URL of a request using a template', function () {
- var injectNode = workspace.addNode('inject');
- var changeNode = workspace.addNode('change');
- var httpRequestNode = workspace.addNode('httpRequest');
- var debugNode = workspace.addNode('debug');
-
- injectNode.edit();
- injectNode.setPayload('str', 'settings');
- injectNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet('query', 'msg', 'payload', 'msg');
- changeNode.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + '/{{{query}}}');
- httpRequestNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.containEql('httpNodeRoot');
- });
-
- it('set the query string parameters', function () {
- var injectNode = workspace.addNode('inject');
- var changeNode = workspace.addNode('change');
- var httpRequestNode = workspace.addNode('httpRequest');
- var debugNode = workspace.addNode('debug');
-
- injectNode.edit();
- injectNode.setPayload('str', 'Nick');
- injectNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleSet('query', 'msg', 'payload', 'msg');
- changeNode.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setUrl(helper.url() + httpNodeRoot + '/set-query?q={{{query}}}');
- httpRequestNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
-
- // The code for confirmation starts from here.
- var httpInNode = workspace.addNode('httpIn', 0, 200);
- var templateNode = workspace.addNode('template');
- var httpResponseNode = workspace.addNode('httpResponse');
-
- httpInNode.edit();
- httpInNode.setMethod('get');
- httpInNode.setUrl('/set-query');
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax('mustache');
- templateNode.setFormat('handlebars');
- templateNode.setTemplate('Hello {{req.query.q}}');
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"Hello Nick"');
- });
-
- it('get a parsed JSON response', function () {
- var injectNode = workspace.addNode('inject');
- var changeNodeSetPost = workspace.addNode('change');
- var httpRequestNode = workspace.addNode('httpRequest');
- var debugNode = workspace.addNode('debug');
-
- injectNode.edit();
- injectNode.setPayload('str', 'json-response');
- injectNode.clickOk();
-
- changeNodeSetPost.edit();
- changeNodeSetPost.ruleSet('post', 'msg', 'payload', 'msg');
- changeNodeSetPost.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setMethod('GET');
- var url = helper.url() + httpNodeRoot + '/{{post}}';
- httpRequestNode.setUrl(url);
- httpRequestNode.setReturn('obj');
- httpRequestNode.clickOk();
-
- debugNode.edit();
- debugNode.setOutput('payload.title');
- debugNode.clickOk();
-
- injectNode.connect(changeNodeSetPost);
- changeNodeSetPost.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
-
- // The code for confirmation starts from here.
- var httpInNode = workspace.addNode('httpIn', 0, 200);
- var templateNode = workspace.addNode('template');
- var changeNodeSetHeader = workspace.addNode('change');
- var httpResponseNode = workspace.addNode('httpResponse');
-
- httpInNode.edit();
- httpInNode.setMethod('get');
- httpInNode.setUrl('/json-response');
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax('mustache');
- templateNode.setFormat('handlebars');
- templateNode.setTemplate('{"title": "Hello"}');
- templateNode.clickOk();
-
- changeNodeSetHeader.edit();
- changeNodeSetHeader.ruleSet('headers', 'msg', '{"content-type":"application/json"}', 'json');
- changeNodeSetHeader.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(changeNodeSetHeader);
- changeNodeSetHeader.connect(httpResponseNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"Hello"');
- });
-
- it('get a binary response', function () {
- var injectNode = workspace.addNode('inject');
- var httpRequestNode = workspace.addNode('httpRequest');
- var debugNode = workspace.addNode('debug');
-
- httpRequestNode.edit();
- httpRequestNode.setMethod('GET');
- httpRequestNode.setUrl(helper.url() + '/settings');
- httpRequestNode.setReturn('bin');
- httpRequestNode.clickOk();
-
- injectNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
-
- debugTab.getMessage().should.eql(['123', '34', '104', '116', '116', '112', '78', '111', '100', '101']);
- });
-
- it('set a request header', function () {
- var injectNode = workspace.addNode('inject');
- var functionNode = workspace.addNode('function');
- var httpRequestNode = workspace.addNode('httpRequest');
- var debugNode = workspace.addNode('debug');
-
- functionNode.edit();
- functionNode.setFunction('msg.payload = "data to post";\nreturn msg;');
- functionNode.clickOk();
-
- httpRequestNode.edit();
- httpRequestNode.setMethod('POST');
- var url = helper.url() + httpNodeRoot + '/set-header';
- httpRequestNode.setUrl(url);
- httpRequestNode.clickOk();
-
- injectNode.connect(functionNode);
- functionNode.connect(httpRequestNode);
- httpRequestNode.connect(debugNode);
-
- // The code for confirmation starts from here.
- var httpInNode = workspace.addNode('httpIn', 0, 200);
- var templateNode = workspace.addNode('template');
- var httpResponseNode = workspace.addNode('httpResponse');
-
- httpInNode.edit();
- httpInNode.setMethod('post');
- httpInNode.setUrl('/set-header');
- httpInNode.clickOk();
-
- templateNode.edit();
- templateNode.setSyntax('mustache');
- templateNode.setFormat('handlebars');
- templateNode.setTemplate('{{ payload }}');
- templateNode.clickOk();
-
- httpInNode.connect(templateNode);
- templateNode.connect(httpResponseNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"data to post"');
- });
- });
-});
diff --git a/test/editor/specs/scenario/cookbook_messages_uispec.js b/test/editor/specs/scenario/cookbook_messages_uispec.js
deleted file mode 100644
index 78facbcda..000000000
--- a/test/editor/specs/scenario/cookbook_messages_uispec.js
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require('when');
-var should = require('should');
-var fs = require('fs-extra');
-
-var helper = require('../../editor_helper');
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-var specUtil = require('../../pageobjects/util/spec_util_page');
-
-var httpNodeRoot = '/api';
-
-// https://cookbook.nodered.org/
-describe('cookbook', function () {
- beforeEach(function () {
- workspace.init();
- });
-
- before(function () {
- helper.startServer();
- });
-
- after(function () {
- helper.stopServer();
- });
-
- describe('messages', function () {
- it('set a message property to a fixed value', function () {
- var injectNode = workspace.addNode('inject');
- var changeNode = workspace.addNode('change');
- var debugNode = workspace.addNode('debug');
-
- changeNode.edit();
- changeNode.ruleSet('payload', 'msg', 'Hello World!');
- changeNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"Hello World!"');
- });
-
- it('delete a message property', function () {
- var injectNode = workspace.addNode('inject');
- var changeNode = workspace.addNode('change');
- var debugNode = workspace.addNode('debug');
-
- changeNode.edit();
- changeNode.ruleDelete();
- changeNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('undefined');
- });
-
- it('move a message property', function () {
- var injectNode = workspace.addNode('inject');
- var changeNode = workspace.addNode('change');
- var debugNode = workspace.addNode('debug');
-
- injectNode.edit();
- injectNode.setTopic('Hello');
- injectNode.clickOk();
-
- changeNode.edit();
- changeNode.ruleMove('topic', 'msg', 'payload', 'msg');
- changeNode.clickOk();
-
- injectNode.connect(changeNode);
- changeNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"Hello"');
- });
-
- it('map a property between different numeric ranges', function () {
- var injectNode1 = workspace.addNode('inject');
- var injectNode2 = workspace.addNode('inject', 0, 100);
- var injectNode3 = workspace.addNode('inject', 0, 200);
- var rangeNode = workspace.addNode('range', 200, 100);
- var debugNode = workspace.addNode('debug', 400);
-
- injectNode1.edit();
- injectNode1.setPayload('num', 0);
- injectNode1.clickOk();
- injectNode2.edit();
- injectNode2.setPayload('num', 512);
- injectNode2.clickOk();
- injectNode3.edit();
- injectNode3.setPayload('num', 1023);
- injectNode3.clickOk();
-
- rangeNode.edit();
- rangeNode.setAction('clamp');
- rangeNode.setRange(0, 1023, 0, 5);
- rangeNode.clickOk();
-
- injectNode1.connect(rangeNode);
- injectNode2.connect(rangeNode);
- injectNode3.connect(rangeNode);
- rangeNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode1.clickLeftButton();
- debugTab.getMessage(1).should.eql('0');
- injectNode2.clickLeftButton();
- debugTab.getMessage(2).should.eql('2.5024437927663734');
- injectNode3.clickLeftButton();
- debugTab.getMessage(3).should.eql('5');
- });
- });
-});
diff --git a/test/editor/specs/scenario/cookbook_mqtt_uispec.js b/test/editor/specs/scenario/cookbook_mqtt_uispec.js
deleted file mode 100644
index b68170eb5..000000000
--- a/test/editor/specs/scenario/cookbook_mqtt_uispec.js
+++ /dev/null
@@ -1,224 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var when = require('when');
-var should = require("should");
-var fs = require('fs-extra');
-
-var helper = require("../../editor_helper");
-var debugTab = require('../../pageobjects/editor/debugTab_page');
-var workspace = require('../../pageobjects/editor/workspace_page');
-var specUtil = require('../../pageobjects/util/spec_util_page');
-
-var httpNodeRoot = "/api";
-
-var mqttServer;
-var mosca = require('mosca');
-var moscaSettings = {
- port: parseInt(Math.random() * 16383 + 49152),
- persistence: {
- // Needs for retaining messages.
- factory: mosca.persistence.Memory
- }
-};
-
-// https://cookbook.nodered.org/
-describe('cookbook', function () {
- beforeEach(function () {
- workspace.init();
- });
-
- before(function () {
- browser.call(function () {
- return new Promise(function (resolve, reject) {
- mqttServer = new mosca.Server(moscaSettings, function (err) {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
- });
- });
- });
- helper.startServer();
- });
-
- after(function () {
- browser.call(function () {
- return new Promise(function (resolve, reject) {
- mqttServer.close(function () {
- resolve();
- });
- });
- });
- helper.stopServer();
- });
-
- describe('MQTT', function () {
- it('Add an MQTT broker to prepare for UI test', function () {
- var mqttOutNode = workspace.addNode("mqttOut");
-
- mqttOutNode.edit();
- mqttOutNode.mqttBrokerNode.edit();
- mqttOutNode.mqttBrokerNode.setServer("localhost", moscaSettings.port);
- mqttOutNode.mqttBrokerNode.clickOk();
- mqttOutNode.clickOk();
-
- workspace.deploy();
- });
-
- it('Connect to an MQTT broker', function () {
- var injectNode = workspace.addNode("inject");
- var mqttOutNode = workspace.addNode("mqttOut");
-
- var mqttInNode = workspace.addNode("mqttIn", 0, 100);
- var debugNode = workspace.addNode("debug");
-
- injectNode.edit();
- injectNode.setPayload("num", 22);
- injectNode.clickOk();
-
- mqttOutNode.edit();
- mqttOutNode.setTopic("sensors/livingroom/temp");
- mqttOutNode.clickOk();
-
- injectNode.connect(mqttOutNode);
-
- mqttInNode.edit();
- mqttInNode.setTopic("sensors/livingroom/temp");
- mqttInNode.setQoS("2");
- mqttInNode.clickOk();
-
- mqttInNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"22"');
- });
-
- // skip this case since it is same as other cases.
- it.skip('Publish messages to a topic');
-
- it('Set the topic of a published message', function () {
- var injectNode = workspace.addNode("inject");
- var mqttOutNode = workspace.addNode("mqttOut");
-
- injectNode.edit();
- injectNode.setPayload("num", 22);
- injectNode.setTopic("sensors/kitchen/temperature");
- injectNode.clickOk();
-
- mqttOutNode.edit();
- mqttOutNode.clickOk();
-
- injectNode.connect(mqttOutNode);
-
- // The code for confirmation starts from here.
- var mqttInNode = workspace.addNode("mqttIn", 0, 100);
- var debugNode = workspace.addNode("debug");
-
- mqttInNode.edit();
- mqttInNode.setTopic("sensors/kitchen/temperature");
- mqttInNode.clickOk();
-
- mqttInNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql('"22"');
- });
-
- it('Publish a retained message to a topic', function () {
- var injectNode = workspace.addNode("inject");
- var mqttOutNode = workspace.addNode("mqttOut");
-
- injectNode.edit();
- injectNode.setPayload("num", 22);
- injectNode.clickOk();
-
- mqttOutNode.edit();
- mqttOutNode.setTopic("sensors/livingroom/temp");
- mqttOutNode.setRetain("true");
- mqttOutNode.clickOk();
-
- injectNode.connect(mqttOutNode);
-
- workspace.deploy();
- debugTab.open();
- injectNode.clickLeftButton();
-
- // The code for confirmation starts from here.
- var mqttInNode = workspace.addNode("mqttIn", 0, 100);
- var debugNode = workspace.addNode("debug");
-
- mqttInNode.edit();
- mqttInNode.setTopic("sensors/livingroom/temp");
- mqttInNode.clickOk();
-
- mqttInNode.connect(debugNode);
- // The code for confirmation ends here.
-
- workspace.deploy();
- debugTab.open(true);
- debugTab.getMessage().should.eql('"22"');
- });
-
- // skip this case since it is same as other cases.
- it.skip('Subscribe to a topic');
-
- it('Receive a parsed JSON message', function () {
- var injectNode = workspace.addNode("inject");
- var mqttOutNode = workspace.addNode("mqttOut");
-
- var mqttInNode = workspace.addNode("mqttIn", 0, 100);
- var jsonNode = workspace.addNode("json");
- var debugNode = workspace.addNode("debug");
-
- injectNode.edit();
- injectNode.setPayload("json", '{"sensor_id": 1234, "temperature": 13 }');
- injectNode.clickOk();
-
- mqttOutNode.edit();
- mqttOutNode.setTopic("sensors/livingroom/temp");
- mqttOutNode.clickOk();
-
- injectNode.connect(mqttOutNode);
-
- mqttInNode.edit();
- mqttInNode.setTopic("sensors/#");
- mqttInNode.setQoS("2");
- mqttInNode.clickOk();
-
- jsonNode.edit();
- jsonNode.setProperty("payload");
- jsonNode.clickOk();
-
- mqttInNode.connect(jsonNode);
- jsonNode.connect(debugNode);
-
- workspace.deploy();
-
- debugTab.open();
- injectNode.clickLeftButton();
- debugTab.getMessage().should.eql(['1234', '13']);
- });
- });
-});
diff --git a/test/editor/wdio.conf.js b/test/editor/wdio.conf.js
deleted file mode 100644
index 4e5a602e0..000000000
--- a/test/editor/wdio.conf.js
+++ /dev/null
@@ -1,338 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var browserstack = require('browserstack-local');
-exports.config = {
-
- //
- // ==================
- // Specify Test Files
- // ==================
- // Define which test specs should run. The pattern is relative to the directory
- // from which `wdio` was called. Notice that, if you are calling `wdio` from an
- // NPM script (see https://docs.npmjs.com/cli/run-script) then the current working
- // directory is where your package.json resides, so `wdio` will be called from there.
- //
- specs: [
- './test/editor/**/*_uispec.js'
- ],
- // Patterns to exclude.
- exclude: [
- // 'path/to/excluded/files'
- ],
- //
- // ============
- // Capabilities
- // ============
- // Define your capabilities here. WebdriverIO can run multiple capabilities at the same
- // time. Depending on the number of capabilities, WebdriverIO launches several test
- // sessions. Within your capabilities you can overwrite the spec and exclude options in
- // order to group specific specs to a specific capability.
- //
- // First, you can define how many instances should be started at the same time. Let's
- // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
- // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
- // files and you set maxInstances to 10, all spec files will get tested at the same time
- // and 30 processes will get spawned. The property handles how many capabilities
- // from the same test should run tests.
- //
- // maxInstances: 10,
- //
- // If you have trouble getting all important capabilities together, check out the
- // Sauce Labs platform configurator - a great tool to configure your capabilities:
- // https://docs.saucelabs.com/reference/platforms-configurator
- //
- // capabilities: [{
- // maxInstances can get overwritten per capability. So if you have an in-house Selenium
- // grid with only 5 firefox instances available you can make sure that not more than
- // 5 instances get started at a time.
- // maxInstances: 5,
- //
- // browserName: 'firefox'
- // }],
- //
- // ===================
- // Test Configurations
- // ===================
- // Define all options that are relevant for the WebdriverIO instance here
- //
- // By default WebdriverIO commands are executed in a synchronous way using
- // the wdio-sync package. If you still want to run your tests in an async way
- // e.g. using promises you can set the sync option to false.
- sync: true,
- //
- // Level of logging verbosity: silent | verbose | command | data | result | error
- logLevel: 'silent',
- //
- // Enables colors for log output.
- coloredLogs: true,
- //
- // Warns when a deprecated command is used
- deprecationWarnings: false,
- //
- // If you only want to run your tests until a specific amount of tests have failed use
- // bail (default is 0 - don't bail, run all tests).
- bail: 0,
- //
- // Saves a screenshot to a given path if a command fails.
- screenshotPath: './test/errorShots/',
- //
- // Set a base URL in order to shorten url command calls. If your `url` parameter starts
- // with `/`, the base url gets prepended, not including the path portion of your baseUrl.
- // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
- // gets prepended directly.
- baseUrl: 'http://localhost',
- //
- // Default timeout for all waitFor* commands.
- waitforTimeout: 20000,
- //
- // Default timeout in milliseconds for request
- // if Selenium Grid doesn't send response
- connectionRetryTimeout: 90000,
- //
- // Default request retries count
- connectionRetryCount: 3,
- //
- // Initialize the browser instance with a WebdriverIO plugin. The object should have the
- // plugin name as key and the desired plugin options as properties. Make sure you have
- // the plugin installed before running any tests. The following plugins are currently
- // available:
- // WebdriverCSS: https://github.com/webdriverio/webdrivercss
- // WebdriverRTC: https://github.com/webdriverio/webdriverrtc
- // Browserevent: https://github.com/webdriverio/browserevent
- // plugins: {
- // webdrivercss: {
- // screenshotRoot: 'my-shots',
- // failedComparisonsRoot: 'diffs',
- // misMatchTolerance: 0.05,
- // screenWidth: [320,480,640,1024]
- // },
- // webdriverrtc: {},
- // browserevent: {}
- // },
- //
- // Test runner services
- // Services take over a specific job you don't want to take care of. They enhance
- // your test setup with almost no effort. Unlike plugins, they don't add new
- // commands. Instead, they hook themselves up into the test process.
- //services: ['chromedriver'],
- //
- // Framework you want to run your specs with.
- // The following are supported: Mocha, Jasmine, and Cucumber
- // see also: http://webdriver.io/guide/testrunner/frameworks.html
- //
- // Make sure you have the wdio adapter package for the specific framework installed
- // before running any tests.
- framework: 'mocha',
- //
- // Test reporter for stdout.
- // The only one supported by default is 'dot'
- // see also: http://webdriver.io/guide/reporters/dot.html
- reporters: ['spec'],
-
- //
- // Options to be passed to Mocha.
- // See the full list at http://mochajs.org/
- mochaOpts: {
- timeout: 1000000,
- ui: 'bdd'
- },
- //
- // =====
- // Hooks
- // =====
- // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
- // it and to build services around it. You can either apply a single function or an array of
- // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
- // resolved to continue.
- /**
- * Gets executed once before all workers get launched.
- * @param {Object} config wdio configuration object
- * @param {Array.} capabilities list of capabilities details
- */
- onPrepare: function (config, capabilities) {
- if (process.env.BROWSERSTACK) {
- return new Promise(function (resolve, reject) {
- var options = { key: exports.config.key };
- var proxy = process.env.http_proxy || process.env.HTTP_PROXY;
- if (proxy) {
- var proxyConfigs = proxy.match(/^(https?):\/\/(([^:@\/]+):([^:@\/]+)@)?([^:@\/]+)(:([^:@\/]+))?\/?$/);
- if (proxyConfigs) {
- var protocol = proxyConfigs[1];
- var user = proxyConfigs[3];
- var pass = proxyConfigs[4];
- var host = proxyConfigs[5];
- var port = proxyConfigs[7];
- if (!port) {
- if (protocol === 'http') {
- port = 80;
- } else if (protocol === 'https') {
- port = 443;
- }
- }
- if (host) { options.proxyHost = host; }
- if (port) { options.proxyPort = port; }
- if (user) { options.proxyUser = user; }
- if (pass) { options.proxyPass = pass; }
- } else {
- reject('error in parsing the environment variable, http_proxy');
- }
- }
- exports.bs_local = new browserstack.Local();
- exports.bs_local.start(options, function (error) {
- if (error) {
- return reject(error);
- }
- resolve();
- });
- });
- }
- },
- /**
- * Gets executed just before initialising the webdriver session and test framework. It allows you
- * to manipulate configurations depending on the capability or spec.
- * @param {Object} config wdio configuration object
- * @param {Array.} capabilities list of capabilities details
- * @param {Array.} specs List of spec file paths that are to be run
- */
- // beforeSession: function (config, capabilities, specs) {
- // },
- /**
- * Gets executed before test execution begins. At this point you can access to all global
- * variables like `browser`. It is the perfect place to define custom commands.
- * @param {Array.} capabilities list of capabilities details
- * @param {Array.} specs List of spec file paths that are to be run
- */
- // before: function (capabilities, specs) {
- // },
- /**
- * Runs before a WebdriverIO command gets executed.
- * @param {String} commandName hook command name
- * @param {Array} args arguments that command would receive
- */
- // beforeCommand: function (commandName, args) {
- // },
-
- /**
- * Hook that gets executed before the suite starts
- * @param {Object} suite suite details
- */
- // beforeSuite: function (suite) {
- // },
- /**
- * Function to be executed before a test (in Mocha/Jasmine) or a step (in Cucumber) starts.
- * @param {Object} test test details
- */
- // beforeTest: function (test) {
- // },
- /**
- * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
- * beforeEach in Mocha)
- */
- // beforeHook: function () {
- // },
- /**
- * Hook that gets executed _after_ a hook within the suite ends (e.g. runs after calling
- * afterEach in Mocha)
- */
- // afterHook: function () {
- // },
- /**
- * Function to be executed after a test (in Mocha/Jasmine) or a step (in Cucumber) ends.
- * @param {Object} test test details
- */
- // afterTest: function (test) {
- // },
- /**
- * Hook that gets executed after the suite has ended
- * @param {Object} suite suite details
- */
- // afterSuite: function (suite) {
- // },
-
- /**
- * Runs after a WebdriverIO command gets executed
- * @param {String} commandName hook command name
- * @param {Array} args arguments that command would receive
- * @param {Number} result 0 - command success, 1 - command error
- * @param {Object} error error object if any
- */
- // afterCommand: function (commandName, args, result, error) {
- // },
- /**
- * Gets executed after all tests are done. You still have access to all global variables from
- * the test.
- * @param {Number} result 0 - test pass, 1 - test fail
- * @param {Array.} capabilities list of capabilities details
- * @param {Array.} specs List of spec file paths that ran
- */
- // after: function (result, capabilities, specs) {
- // },
- /**
- * Gets executed right after terminating the webdriver session.
- * @param {Object} config wdio configuration object
- * @param {Array.} capabilities list of capabilities details
- * @param {Array.} specs List of spec file paths that ran
- */
- // afterSession: function (config, capabilities, specs) {
- // },
- /**
- * Gets executed after all workers got shut down and the process is about to exit.
- * @param {Object} exitCode 0 - success, 1 - fail
- * @param {Object} config wdio configuration object
- * @param {Array.} capabilities list of capabilities details
- */
- onComplete: function(exitCode, config, capabilities) {
- if (process.env.BROWSERSTACK) {
- exports.bs_local.stop(function () {});
- }
- }
-};
-
-if (process.env.BROWSERSTACK) {
- exports.config.maxInstances = 1;
- if (process.env.BROWSERSTACK_USERNAME && process.env.BROWSERSTACK_ACCESS_KEY) {
- exports.config.user = process.env.BROWSERSTACK_USERNAME;
- exports.config.key = process.env.BROWSERSTACK_ACCESS_KEY;
- } else {
- console.log('You need to set the following environment variables.');
- console.log('BROWSERSTACK_USERNAME=');
- console.log('BROWSERSTACK_ACCESS_KEY=');
- }
- exports.config.services = ['browserstack'];
- var capabilities = [];
- capabilities.push({ os: 'Windows', os_version: '10', browser: 'Chrome', resolution: '1920x1080', 'browserstack.local': true });
- capabilities.push({ os: 'Windows', os_version: '10', browser: 'Firefox', resolution: '1920x1080', 'browserstack.local': true });
- capabilities.push({ os: 'OS X', os_version: 'Catalina', browser: 'Chrome', resolution: '1920x1080', 'browserstack.local': true });
- capabilities.push({ os: 'OS X', os_version: 'Catalina', browser: 'Firefox', resolution: '1920x1080', 'browserstack.local': true });
- exports.config.capabilities = capabilities;
-} else {
- exports.config.maxInstances = 10;
- exports.config.port = 9515;
- exports.config.path = '/';
- exports.config.services = ['chromedriver'];
- exports.config.capabilities = [{
- maxInstances: 2,
- browserName: 'chrome',
- 'goog:chromeOptions': {
- args: process.env.NODE_RED_NON_HEADLESS
- // Runs tests with opening a browser.
- ? ['--disable-gpu', '--no-sandbox']
- // Runs tests without opening a browser.
- : ['--headless', '--disable-gpu', 'window-size=1920,1080', '--no-sandbox']
- }
- }];
-}
diff --git a/test/node_modules/nr-test-utils/index.js b/test/node_modules/nr-test-utils/index.js
deleted file mode 100644
index 56bc369e6..000000000
--- a/test/node_modules/nr-test-utils/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-const path = require("path");
-const fs = require("fs");
-
-const PACKAGE_ROOT = "../../../packages/node_modules";
-
-module.exports = {
- require: function(file) {
- // console.log(path.join(__dirname,PACKAGE_ROOT,file))
- return require(path.join(PACKAGE_ROOT,file));
- },
- resolve: function(file) {
- return path.resolve(path.join(__dirname,PACKAGE_ROOT,file));
- }
-}
diff --git a/test/node_modules/nr-test-utils/package.json b/test/node_modules/nr-test-utils/package.json
deleted file mode 100644
index ee32d2320..000000000
--- a/test/node_modules/nr-test-utils/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "name": "nr-test-utils",
- "version": "0.20.0",
- "license": "Apache-2.0",
- "private": true
-}
diff --git a/test/nodes/core/common/20-inject_spec.js b/test/nodes/core/common/20-inject_spec.js
deleted file mode 100644
index f760bb646..000000000
--- a/test/nodes/core/common/20-inject_spec.js
+++ /dev/null
@@ -1,669 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var injectNode = require("nr-test-utils").require("@node-red/nodes/core/common/20-inject.js");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context");
-var helper = require("node-red-node-test-helper");
-
-describe('inject node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory0: {
- module: "memory"
- },
- memory1: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function(done) {
- helper.unload().then(function () {
- return Context.clean({allNodes: {}});
- }).then(function () {
- return Context.close();
- }).then(function () {
- helper.stopServer(done);
- });
- });
-
- function basicTest(type, val, rval) {
- it('inject value ('+type+')', function (done) {
- var flow = [{id: "n1", type: "inject", topic: "t1", payload: val, payloadType: type, wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- if (rval) {
- msg.should.have.property("payload");
- should.deepEqual(msg.payload, rval);
- }
- else {
- msg.should.have.property("payload", val);
- }
- done();
- } catch (err) {
- done(err);
- }
- });
- n1.receive({});
- });
- });
- }
-
- basicTest("num", 10);
- basicTest("str", "10");
- basicTest("bool", true);
- var val_json = '{ "x":"vx", "y":"vy", "z":"vz" }';
- basicTest("json", val_json, JSON.parse(val_json));
- var val_buf = "[1,2,3,4,5]";
- basicTest("bin", val_buf, Buffer.from(JSON.parse(val_buf)));
-
- it('inject value of environment variable ', function (done) {
- var flow = [{id: "n1", type: "inject", topic: "t1", payload: "NR_TEST", payloadType: "env", wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- msg.should.have.property("payload", "foo");
- done();
- } catch (err) {
- done(err);
- }
- });
- process.env.NR_TEST = 'foo';
- n1.receive({});
- });
- });
-
- it('sets the value of flow context property', function (done) {
- var flow = [{id: "n1", type: "inject", topic: "t1", payload: "flowValue", payloadType: "flow", wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- msg.should.have.property("payload", "changeMe");
- done();
- } catch (err) {
- done(err);
- }
- });
- n1.context().flow.set("flowValue", "changeMe");
- n1.receive({});
- });
- });
-
- it('sets the value of persistable flow context property', function (done) {
- var flow = [{id: "n1", type: "inject", topic: "t1", payload: "#:(memory0)::flowValue", payloadType: "flow", wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- msg.should.have.property("payload", "changeMe");
- done();
- } catch (err) {
- done(err);
- }
- });
- n1.context().flow.set("flowValue", "changeMe", "memory0", function (err) {
- n1.receive({});
- });
- });
- });
- });
-
- it('sets the value of two persistable flow context property', function (done) {
- var flow = [{id: "n0", z: "flow", type: "inject", topic: "t0", payload: "#:(memory0)::val", payloadType: "flow", wires: [["n2"]]},
- {id: "n1", z: "flow", type: "inject", topic: "t1", payload: "#:(memory1)::val", payloadType: "flow", wires: [["n2"]]},
- {id: "n2", z: "flow", type: "helper"}];
- helper.load(injectNode, flow, function () {
- initContext(function () {
- var n0 = helper.getNode("n0");
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic");
- if (msg.topic === "t0") {
- msg.should.have.property("payload", "foo");
- }
- else if (msg.topic === "t1") {
- msg.should.have.property("payload", "bar");
- }
- else {
- done(new Error("unexpected message"));
- }
- count++;
- if (count === 2) {
- done();
- }
- } catch (err) {
- done(err);
- }
- });
- var global = n0.context().flow;
- global.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
- n0.receive({});
- n1.receive({});
- });
- });
- });
- });
- });
-
- it('sets the value of global context property', function (done) {
- var flow = [{id: "n1", type: "inject", topic: "t1", payload: "globalValue", payloadType: "global", wires: [["n2"]]},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- msg.should.have.property("payload", "changeMe");
- done();
- } catch (err) {
- done(err);
- }
- });
- n1.context().global.set("globalValue", "changeMe");
- n1.receive({});
- });
- });
-
- it('sets the value of persistable global context property', function (done) {
- var flow = [{id: "n1", z: "flow", type: "inject", topic: "t1", payload: "#:(memory1)::val", payloadType: "global", wires: [["n2"]]},
- {id: "n2", z: "flow", type: "helper"}];
- helper.load(injectNode, flow, function () {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- msg.should.have.property("payload", "foo");
- done();
- } catch (err) {
- done(err);
- }
- });
- var global = n1.context().global;
- global.set("val", "foo", "memory1", function (err) {
- n1.receive({});
- });
- });
- });
- });
-
- it('sets the value of two persistable global context property', function (done) {
- var flow = [{id: "n0", z: "flow", type: "inject", topic: "t0", payload: "#:(memory0)::val", payloadType: "global", wires: [["n2"]]},
- {id: "n1", z: "flow", type: "inject", topic: "t1", payload: "#:(memory1)::val", payloadType: "global", wires: [["n2"]]},
- {id: "n2", z: "flow", type: "helper"}];
- helper.load(injectNode, flow, function () {
- initContext(function () {
- var n0 = helper.getNode("n0");
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic");
- if (msg.topic === "t0") {
- msg.should.have.property("payload", "foo");
- }
- else if (msg.topic === "t1") {
- msg.should.have.property("payload", "bar");
- }
- else {
- done(new Error("unexpected message"));
- }
- count++;
- if (count === 2) {
- done();
- }
- } catch (err) {
- done(err);
- }
- });
- var global = n0.context().global;
- global.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
- n0.receive({});
- n1.receive({});
- });
- });
- });
- });
- });
-
- it('sets the value of persistable flow & global context property', function (done) {
- var flow = [{id: "n0", z: "flow", type: "inject", topic: "t0", payload: "#:(memory0)::val", payloadType: "flow", wires: [["n2"]]},
- {id: "n1", z: "flow", type: "inject", topic: "t1", payload: "#:(memory1)::val", payloadType: "global", wires: [["n2"]]},
- {id: "n2", z: "flow", type: "helper"}];
- helper.load(injectNode, flow, function () {
- initContext(function () {
- var n0 = helper.getNode("n0");
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic");
- if (msg.topic === "t0") {
- msg.should.have.property("payload", "foo");
- }
- else if (msg.topic === "t1") {
- msg.should.have.property("payload", "bar");
- }
- else {
- done(new Error("unexpected message"));
- }
- count++;
- if (count === 2) {
- done();
- }
- } catch (err) {
- done(err);
- }
- });
- var context = n0.context();
- var flow = context.flow;
- var global = context.global;
- flow.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
- n0.receive({});
- n1.receive({});
- });
- });
- });
- });
- });
-
- it('sets the value of two persistable global context property', function (done) {
- var flow = [{id: "n0", z: "flow", type: "inject", topic: "t0", payload: "#:(memory0)::val", payloadType: "global", wires: [["n2"]]},
- {id: "n1", z: "flow", type: "inject", topic: "t1", payload: "#:(memory1)::val", payloadType: "global", wires: [["n2"]]},
- {id: "n2", z: "flow", type: "helper"}];
- helper.load(injectNode, flow, function () {
- initContext(function () {
- var n0 = helper.getNode("n0");
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic");
- if (msg.topic === "t0") {
- msg.should.have.property("payload", "foo");
- }
- else if (msg.topic === "t1") {
- msg.should.have.property("payload", "bar");
- }
- else {
- done(new Error("unexpected message"));
- }
- count++;
- if (count === 2) {
- done();
- }
- } catch (err) {
- done(err);
- }
- });
- var global = n0.context().global;
- global.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
- n0.receive({});
- n1.receive({});
- });
- });
- });
- });
- });
- it('should inject once with default delay property', function(done) {
- helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
- payload:"",payloadType:"date",
- once: true, wires:[["n2"]] },
- {id:"n2", type:"helper"}],
- function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('onceDelay', 100);
- done();
- });
- });
-
- it('should inject once with default delay', function(done) {
- var timestamp = new Date();
- timestamp.setSeconds(timestamp.getSeconds() + 1);
-
- helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
- payload:"",payloadType:"date",
- once: true, wires:[["n2"]] },
- {id:"n2", type:"helper"}],
- function() {
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 't1');
- msg.should.have.property('payload');
- should(msg.payload).be.lessThan(timestamp.getTime());
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('should inject once with 500 msec. delay', function(done) {
- helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
- payload:"",payloadType:"date",
- once: true, onceDelay: 0.5, wires:[["n2"]] },
- {id:"n2", type:"helper"}],
- function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('onceDelay', 500);
- done();
- });
- });
-
- it('should inject once with delay of two seconds', function(done) {
- this.timeout(2700); // have to wait for the inject with delay of two seconds
-
- var timestamp = new Date();
- timestamp.setSeconds(timestamp.getSeconds() + 1);
-
- helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
- payload:"",payloadType:"date",
- once: true, onceDelay: 2, wires:[["n2"]] },
- {id:"n2", type:"helper"}],
- function() {
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 't1');
- should(msg.payload).be.greaterThan(timestamp.getTime());
- done();
- });
- });
- });
-
- it('should inject repeatedly', function(done) {
-
- helper.load(injectNode, [{id:"n1", type:"inject",
- payload:"payload", topic: "t2",
- repeat: 0.2, wires:[["n2"]] },
- {id:"n2", type:"helper"}],
- function() {
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 't2');
- msg.should.have.property('payload', 'payload');
- count += 1;
- if (count > 2) {
- helper.clearFlows().then(function() {
- done();
- });
- }
- });
- });
- });
-
- it('should inject once with delay of two seconds and repeatedly', function(done) {
- var timestamp = new Date();
- timestamp.setSeconds(timestamp.getSeconds() + 1);
-
- helper.load(injectNode, [{id:"n1", type:"inject", topic: "t1",
- payload:"",payloadType:"date", repeat: 0.2,
- once: true, onceDelay: 1.2, wires:[["n2"]] },
- {id:"n2", type:"helper"}],
- function() {
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 't1');
- should(msg.payload).be.greaterThan(timestamp.getTime());
- count += 1;
- if (count > 2) {
- helper.clearFlows().then(function() {
- done();
- });
- }
- });
- });
- });
-
- it('should inject with cron', function(done) {
- helper.load(injectNode, [{id:"n1", type:"inject",
- payloadType:"date", topic: "t3",
- crontab: "* * * * * *", wires:[["n3"]] },
- {id:"n3", type:"helper"}],
- function() {
- var n3 = helper.getNode("n3");
- n3.on("input", function(msg) {
- msg.should.have.property('topic', 't3');
- msg.should.have.property('payload').be.a.Number();
- helper.clearFlows().then(function() {
- done();
- });
- });
- });
- });
-
-
- it('should inject multiple properties ', function (done) {
- var flow = [{id: "n1", type: "inject", props: [{p:"topic", v:"t1", vt:"str"}, {p:"payload", v:"foo", vt:"str"}, {p:"x", v: 10, "vt":"num"}, {p:"y", v: "x+2", "vt":"jsonata"}], wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- msg.should.have.property("payload", "foo");
- msg.should.have.property("x", 10);
- msg.should.have.property("y", 12);
- done();
- } catch (err) {
- done(err);
- }
- });
- n1.receive({});
- });
- });
-
-
- it('should inject custom properties in message', function (done) {
- //n1: inject node with { topic:"static", payload:"static", bool1:true, str1:"1" }
- var flow = [{id: "n1", type: "inject", props: [{p:"payload", v:"static", vt:"str"}, {p:"topic", v:"static", vt:"str"}, {p:"bool1", v:"true", vt:"bool"}, {p:"str1", v:"1", vt:"str"}], wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.not.have.property("payload"); //payload removed
- msg.should.have.property("topic", "t_override"); //changed value to t_override
- msg.should.have.property("str1", 1);//changed type from str to num
- msg.should.have.property("num1", 1);//new prop
- msg.should.have.property("bool1", false);//changed value to false
- done();
- } catch (err) {
- done(err);
- }
- });
- n1.receive({ __user_inject_props__: [
- {p:"topic", v:"t_override", vt:"str"}, //change value to t_override
- {p:"str1", v:"1", vt:"num"}, //change type
- {p:"num1", v:"1", vt:"num"}, //new prop
- {p:"bool1", v:"false", vt:"bool"}, //change value to false
- ]});
- });
- });
-
-
- it('should inject multiple properties using legacy props if needed', function (done) {
- var flow = [{id: "n1", type: "inject", payload:"123", payloadType:"num", topic:"foo", props: [{p:"topic", vt:"str"}, {p:"payload"}], wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "foo");
- msg.should.have.property("payload", 123);
- done();
- } catch (err) {
- done(err);
- }
- });
- n1.receive({});
- });
- });
-
-
- it('should report invalid JSONata expression', function (done) {
- var flow = [{id: "n1", type: "inject", props: [{p:"topic", v:"t1", vt:"str"}, {p:"payload", v:"@", vt:"jsonata"}], wires: [["n2"]], z: "flow"},
- {id: "n2", type: "helper"}];
- helper.load(injectNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("topic", "t1");
- msg.should.not.have.property("payload");
- count++;
- if (count == 2) {
- done();
- }
- } catch (err) {
- done(err);
- }
- });
- n1.on("call:error", function(err) {
- count++;
- if (count == 2) {
- done();
- }
- });
- n1.receive({});
- });
- });
-
- describe('post', function() {
- it('should inject message', function(done) {
- helper.load(injectNode,
- [{id:"n1", type:"inject",
- payloadType:"str", topic: "t4",payload:"hello",
- wires:[["n4"]] },
- { id:"n4", type:"helper"}], function() {
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- msg.should.have.property('topic', 't4');
- msg.should.have.property('payload', 'hello');
- helper.clearFlows().then(function() {
- done();
- });
- });
- try {
- helper.request()
- .post('/inject/n1')
- .expect(200).end(function(err) {
- if (err) {
- console.log(err);
- return helper.clearFlows()
- .then(function () {
- done(err);
- });
- }
- });
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should inject custom properties in posted message', function(done) {
- var flow = [{id:"n1", type:"inject", payloadType:"str", topic: "t4",payload:"hello", wires:[["n4"]] },
- { id:"n4", type:"helper"}];
- helper.load(injectNode, flow, function() {
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- msg.should.not.have.property("payload"); //payload removed
- msg.should.have.property("topic", "t_override"); //changed value to t_override
- msg.should.have.property("str1", "1"); //injected prop
- msg.should.have.property("num1", 1); //injected prop
- msg.should.have.property("bool1", true); //injected prop
-
- helper.clearFlows().then(function() {
- done();
- });
- });
- try {
- helper.request()
- .post('/inject/n1')
- .send({ __user_inject_props__: [
- {p:"topic", v:"t_override", vt:"str"}, //change value to t_override
- {p:"str1", v:"1", vt:"str"}, //new prop
- {p:"num1", v:"1", vt:"num"}, //new prop
- {p:"bool1", v:"true", vt:"bool"}, //new prop
- ]})
- .expect(200).end(function(err) {
- if (err) {
- console.log(err);
- return helper.clearFlows()
- .then(function () {
- done(err);
- });
- }
- });
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should fail for invalid node', function(done) {
- helper.request().post('/inject/invalid').expect(404).end(done);
- });
- });
-});
diff --git a/test/nodes/core/common/21-debug_spec.js b/test/nodes/core/common/21-debug_spec.js
deleted file mode 100644
index ae0d9a48e..000000000
--- a/test/nodes/core/common/21-debug_spec.js
+++ /dev/null
@@ -1,659 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var debugNode = require("nr-test-utils").require("@node-red/nodes/core/common/21-debug.js");
-var helper = require("node-red-node-test-helper");
-var WebSocket = require('ws');
-
-describe('debug node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- beforeEach(function (done) {
- setTimeout(function() {
- done();
- }, 55);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
-
- it('should be loaded', function(done) {
- var flow = [{id:"n1", type:"debug", name:"Debug", complete:"false" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'Debug');
- n1.should.have.property('complete', "payload");
- done();
- });
- });
-
- it('should publish on input', function(done) {
- var flow = [{id:"n1", type:"debug", name:"Debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"test"});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",name:"Debug",msg:"test",path:"global",
- format:"string[4]",property:"payload"}
- }]);
- }, done);
- });
- });
-
- it('should publish to console', function(done) {
- var flow = [{id:"n1", type:"debug", console:"true"}];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- var count = 0;
- websocket_test(function() {
- n1.emit("input", {payload:"test"});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:"test",property:"payload",format:"string[4]",path:"global"}
- }]);
- count++;
- }, function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "debug";
- });
- logEvents.should.have.length(1);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().INFO, id:'n1',type:'debug',msg:'test', timestamp:tstmp,path:"global"});
-
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('should publish complete message', function(done) {
- var flow = [{id:"n1", type:"debug", complete:"true" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"test"});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",
- data:{id:"n1",msg:'{"payload":"test"}',format:"Object",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish complete message to console', function(done) {
- var flow = [{id:"n1", type:"debug", complete:"true", console:"true" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"test"});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",
- data:{id:"n1",msg:'{"payload":"test"}',format:"Object",path:"global"}
- }]);
- }, function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "debug";
- });
- logEvents.should.have.length(1);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().INFO, id:"n1",type:"debug",msg:'\n{ payload: \'test\' }',timestamp:tstmp,path:"global"});
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('should publish other property', function(done) {
- var flow = [{id:"n1", type:"debug", complete:"foo" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"test", foo:"bar"});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:"bar",property:"foo",format:"string[3]",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish multi-level properties', function(done) {
- var flow = [{id:"n1", type:"debug", complete:"foo.bar" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"test", foo: {bar:"bar"}});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:"bar",property:"foo.bar",format:"string[3]",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish an Error', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: new Error("oops")});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:'{"name":"Error","message":"oops"}',property:"payload",format:"error",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish a boolean', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: true});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg: 'true',property:"payload",format:"boolean",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish a number', function(done) {
- var flow = [{id:"n1", type:"debug", console:"true" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: 7});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:"7",property:"payload",format:"number",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish a NaN', function(done) {
- var flow = [{id:"n1", type:"debug", console:"true" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: Number.NaN});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:"NaN",property:"payload",format:"number",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish with no payload', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"undefined",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish a null', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:null});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:'(undefined)',property:"payload",format:"null",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish an object', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: {type:'foo'}});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",
- data:{id:"n1",msg:'{"type":"foo"}',property:"payload",format:"Object",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish an array', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: [0,1,2,3]});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",
- data:{id:"n1",msg: '[0,1,2,3]',format:"array[4]",
- property:"payload",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should publish an object with circular references', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- var o = { name: 'bar' };
- o.o = o;
- n1.emit("input", {payload: o});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",
- data:{
- id:"n1",
- msg:'{"name":"bar","o":"[Circular ~]"}',
- property:"payload",format:"Object",path:"global"
- }
- }]);
- }, done);
- });
- });
-
- it('should publish an object to console', function(done) {
- var flow = [{id:"n1", type:"debug", console:"true"}];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: {type:'foo'}});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:'{"type":"foo"}',property:"payload",format:"Object",path:"global"}
- }]);
- }, function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "debug";
- });
- logEvents.should.have.length(1);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:'\n{ type: \'foo\' }',timestamp:tstmp,path:"global"});
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('should publish a string after a newline to console if the string contains \\n', function(done) {
- var flow = [{id:"n1", type:"debug", console:"true"}];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"test\ntest"});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:"test\ntest",property:"payload",format:"string[9]",path:"global"}
- }]);
- }, function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "debug";
- });
- logEvents.should.have.length(1);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().INFO,id:"n1",type:"debug",msg:"\ntest\ntest",timestamp:tstmp,path:"global"});
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('should publish complete message with edit', function(done) {
- var flow = [{id:"n1", type:"debug", name:"Debug", complete: "true",
- targetType: "jsonata", complete: '"<" & payload & ">"'}];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"test"});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",name:"Debug",msg:"",
- format:"string[6]",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should truncate a long message', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:Array(1002).join("X")});
- }, function(msg) {
- var a = JSON.parse(msg);
- a.should.eql([{
- topic:"debug",
- data:{
- id:"n1",
- msg: Array(1001).join("X")+'...',
- property:"payload",
- format:"string[1001]",
- path:"global"
- }
- }]);
- }, done);
- });
- });
-
- it('should truncate a long string in the object', function(done) {
- var flow = [{id:"n1", type:"debug"}];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: {foo: Array(1002).join("X")}});
- }, function(msg) {
- var a = JSON.parse(msg);
- a.should.eql([{
- topic:"debug",
- data:{
- id:"n1",
- msg:'{"foo":"'+Array(1001).join("X")+'..."}',
- property:"payload",
- format:"Object",
- path:"global"
- }
- }]);
- }, done);
- });
- });
-
- it('should truncate a large array', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: Array(1001).fill("X")});
- }, function(msg) {
- var a = JSON.parse(msg);
- a.should.eql([{
- topic:"debug",
- data:{
- id:"n1",
- msg:JSON.stringify({
- __enc__: true,
- type: "array",
- data: Array(1000).fill("X"),
- length: 1001
- }),
- property:"payload",
- format:"array[1001]",
- path:"global"
- }
- }]);
- }, done);
- });
- });
-
- it('should truncate a large array in the object', function(done) {
- var flow = [{id:"n1", type:"debug"}];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: {foo: Array(1001).fill("X")}});
- }, function(msg) {
- var a = JSON.parse(msg);
- a.should.eql([{
- topic:"debug",
- data:{
- id:"n1",
- msg:JSON.stringify({
- foo:{
- __enc__: true,
- type: "array",
- data: Array(1000).fill("X"),
- length: 1001
- }
- }),
- property:"payload",
- format:"Object",
- path:"global"
- }
- }]);
- }, done);
- });
- });
-
- it('should truncate a large buffer', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: Buffer.alloc(501,"\"")});
- }, function(msg) {
- var a = JSON.parse(msg);
- a[0].should.eql({
- topic:"debug",
- data:{
- id:"n1",
- msg: Array(1001).join("2"),
- property:"payload",
- format:"buffer[501]",
- path:"global"
- }
- });
- }, done);
- });
- });
-
- it('should truncate a large buffer in the object', function(done) {
- var flow = [{id:"n1", type:"debug"}];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: {foo: Buffer.alloc(1001,"X")}});
- }, function(msg) {
- var a = JSON.parse(msg);
- a[0].should.eql({
- topic:"debug",
- data:{
- id:"n1",
- msg:JSON.stringify({
- foo:{
- type: "Buffer",
- data: Array(1000).fill(88),
- __enc__: true,
- length: 1001
- }
- }),
- property:"payload",
- format:"Object",
- path:"global"
- }
- });
- }, done);
- });
- });
-
- it('should convert Buffer to hex', function(done) {
- var flow = [{id:"n1", type:"debug" }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload: Buffer.from('HELLO', 'utf8')});
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",
- data:{
- id:"n1",
- msg:'48454c4c4f',
- property:"payload",
- format:"buffer[5]",
- path:"global"
- }
- }]);
- }, done);
- });
- });
-
- it('should publish when active', function(done) {
- var flow = [{id:"n1", type:"debug", active: false }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function() {
- n1.emit("input", {payload:"message 1"});
- helper.request()
- .post('/debug/n1/enable')
- .expect(200).end(function(err) {
- if (err) { return done(err); }
- n1.emit("input", {payload:"message 2"});
- });
- }, function(msg) {
- JSON.parse(msg).should.eql([{
- topic:"debug",data:{id:"n1",msg:"message 2",property:"payload",format:"string[9]",path:"global"}
- }]);
- }, done);
- });
- });
-
- it('should not publish when inactive', function(done) {
- var flow = [{id:"n1", type:"debug", active: true }];
- helper.load(debugNode, flow, function() {
- var n1 = helper.getNode("n1");
- websocket_test(function(close) {
- helper.request()
- .post('/debug/n1/disable')
- .expect(201).end(function(err) {
- if (err) {
- close();
- return done(err);
- }
- n1.emit("input", {payload:"message"});
- setTimeout(function() {
- close();
- done();
- }, 200);
- });
- }, function(msg) {
- should.fail(null,null,"unexpected message");
- }, function() {});
- });
- });
-
- describe('post', function() {
- it('should return 404 on invalid state', function(done) {
- var flow = [{id:"n1", type:"debug", active: true }];
- helper.load(debugNode, flow, function() {
- helper.request()
- .post('/debug/n1/foobar')
- .expect(404).end(done);
- });
- });
-
- it('should return 404 on invalid node', function(done) {
- helper.request()
- .post('/debug/n99/enable')
- .expect(404).end(done);
- });
-
- it('should return 400 for invalid bulk disable', function(done) {
- var flow = [{id:"n1", type:"debug", active: true }];
- helper.load(debugNode, flow, function() {
- helper.request()
- .post('/debug/disable')
- .send({})
- .set('Content-type', 'application/json')
- .expect(400).end(done);
- });
-
- })
-
- it('should return success for bulk disable', function(done) {
- var flow = [{id:"n1", type:"debug", active: true }];
- helper.load(debugNode, flow, function() {
- helper.request()
- .post('/debug/disable')
- .send({nodes:['n1']})
- .set('Content-type', 'application/json')
- .expect(201).end(done);
- });
-
- })
- });
-
- describe('get', function() {
- it('should return the view.html', function(done) {
- var flow = [{id:"n1", type:"debug"}];
- helper.load(debugNode, flow, function() {
- helper.request()
- .get('/debug/view/view.html')
- .expect(200)
- .end(done);
- });
- });
- });
-
-});
-
-function websocket_test(open_callback, message_callback, done_callback) {
- var ws = new WebSocket(helper.url() + "/comms");
- var close_callback = function() { ws.close(); };
- ws.on('open', function() { open_callback(close_callback); });
- ws.on('message', function(msg) {
- try {
- message_callback(msg, close_callback);
- ws.close();
- done_callback();
- } catch(err) {
- done_callback(err);
- }
- });
-}
diff --git a/test/nodes/core/common/25-catch_spec.js b/test/nodes/core/common/25-catch_spec.js
deleted file mode 100644
index 466d912d7..000000000
--- a/test/nodes/core/common/25-catch_spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js");
-var helper = require("node-red-node-test-helper");
-
-describe('catch Node', function() {
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should output a message when called', function(done) {
- var flow = [ { id:"n1", type:"catch", name:"catch", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(catchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.should.have.property('name', 'catch');
- n2.on("input", function(msg) {
- msg.should.be.a.Error();
- msg.toString().should.equal("Error: big error");
- done();
- });
- var err = new Error("big error");
- n1.emit("input", err);
- });
- });
-
-});
diff --git a/test/nodes/core/common/25-status_spec.js b/test/nodes/core/common/25-status_spec.js
deleted file mode 100644
index 41b0a79c8..000000000
--- a/test/nodes/core/common/25-status_spec.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-status.js");
-var helper = require("node-red-node-test-helper");
-
-describe('status Node', function() {
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should output a message when called', function(done) {
- var flow = [ { id:"n1", type:"status", name:"status", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(catchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.should.have.property('name', 'status');
- n2.on("input", function(msg) {
- msg.text.should.equal("Oh dear");
- msg.should.have.property('source');
- msg.source.should.have.property('id',"12345");
- msg.source.should.have.property('type',"testnode");
- msg.source.should.have.property('name',"fred");
- done();
- });
- var mst = {
- text: "Oh dear",
- source: {
- id: "12345",
- type: "testnode",
- name: "fred"
- }
- }
- n1.emit("input", mst);
- });
- });
-
-});
diff --git a/test/nodes/core/common/60-link_spec.js b/test/nodes/core/common/60-link_spec.js
deleted file mode 100644
index 5314eed15..000000000
--- a/test/nodes/core/common/60-link_spec.js
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var linkNode = require("nr-test-utils").require("@node-red/nodes/core/common/60-link.js");
-var helper = require("node-red-node-test-helper");
-
-describe('link Node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded (link in)', function(done) {
- var flow = [{id:"n1", type:"link in", name: "link-in" }];
- helper.load(linkNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'link-in');
- done();
- });
- });
-
- it('should be loaded (link out)', function(done) {
- var flow = [{id:"n1", type:"link out", name: "link-out" }];
- helper.load(linkNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'link-out');
- done();
- });
- });
-
- it('should be linked', function(done) {
- var flow = [{id:"n1", type:"link out", name: "link-out", links:["n2"]},
- {id:"n2", type:"link in", name: "link-in", wires:[["n3"]]},
- {id:"n3", type:"helper"}];
- helper.load(linkNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n3 = helper.getNode("n3");
- n3.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 'hello');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"hello"});
- });
- });
-
- it('should be linked to multiple nodes', function(done) {
- var flow = [{id:"n1", type:"link out", name: "link-out", links:["n2", "n3"]},
- {id:"n2", type:"link in", name: "link-in0", wires:[["n4"]]},
- {id:"n3", type:"link in", name: "link-in1", wires:[["n4"]]},
- {id:"n4", type:"helper"} ];
- helper.load(linkNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n4 = helper.getNode("n4");
- var count = 0;
- n4.on("input", function (msg) {
- try {
- msg.should.have.property('payload', 'hello');
- count++;
- if(count == 2) {
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"hello"});
- });
- });
-
- it('should be linked from multiple nodes', function(done) {
- var flow = [{id:"n1", type:"link out", name: "link-out0", links:["n3"]},
- {id:"n2", type:"link out", name: "link-out1", links:["n3"]},
- {id:"n3", type:"link in", name: "link-in", wires:[["n4"]]},
- {id:"n4", type:"helper"} ];
- helper.load(linkNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n4 = helper.getNode("n4");
- var count = 0;
- n4.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 'hello');
- count++;
- if(count == 2) {
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"hello"});
- n2.receive({payload:"hello"});
- });
- });
-
- describe("link-call node", function() {
- it('should call link-in node and get response', function(done) {
- var flow = [{id:"link-in-1", type:"link in", wires: [[ "func"]]},
- {id:"func", type:"helper", wires: [["link-out-1"]]},
- {id:"link-out-1", type:"link out", mode: "return"},
- {id:"link-call", type:"link call", links:["link-in-1"], wires:[["n4"]]},
- {id:"n4", type:"helper"} ];
- helper.load(linkNode, flow, function() {
- var func = helper.getNode("func");
- func.on("input", function(msg, send, done) {
- msg.payload = "123";
- send(msg);
- done();
- })
- var n1 = helper.getNode("link-call");
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '123');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"hello"});
- });
- })
- });
-
- it('should allow nested link-call flows', function(done) {
- var flow = [/** Multiply by 2 link flow **/
- {id:"li1", type:"link in", wires: [[ "m2"]]},
- {id:"m2", type:"helper", wires: [["lo1"]]},
- {id:"lo1", type:"link out", mode: "return"},
- /** Multiply by 3 link flow **/
- {id:"li2", type:"link in", wires: [[ "m3"]]},
- {id:"m3", type:"helper", wires: [["lo2"]]},
- {id:"lo2", type:"link out", mode: "return"},
- /** Multiply by 6 link flow **/
- {id:"li3", type:"link in", wires: [[ "link-call-1"]]},
- {id:"link-call-1", type:"link call", links:["m2"], wires:[["link-call-2"]]},
- {id:"link-call-2", type:"link call", links:["m3"], wires:[["lo3"]]},
- {id:"lo3", type:"link out", mode: "return"},
- /** Test Flow Entry **/
- {id:"link-call", type:"link call", links:["li3"], wires:[["n4"]]},
- {id:"n4", type:"helper"} ];
- helper.load(linkNode, flow, function() {
- var m2 = helper.getNode("m2");
- m2.on("input", function(msg, send, done) { msg.payload *= 2 ; send(msg); done(); })
- var m3 = helper.getNode("m3");
- m3.on("input", function(msg, send, done) { msg.payload *= 3 ; send(msg); done(); })
-
- var n1 = helper.getNode("link-call");
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 24);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:4});
- });
- })
-});
diff --git a/test/nodes/core/common/90-comment_spec.js b/test/nodes/core/common/90-comment_spec.js
deleted file mode 100644
index a6f6a8284..000000000
--- a/test/nodes/core/common/90-comment_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var commentNode = require("nr-test-utils").require("@node-red/nodes/core/common/90-comment.js");
-var helper = require("node-red-node-test-helper");
-
-describe('comment Node', function() {
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"n1", type:"comment", name: "comment" }];
- helper.load(commentNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'comment');
- done();
- });
- });
-
-});
diff --git a/test/nodes/core/common/98-unknown_spec.js b/test/nodes/core/common/98-unknown_spec.js
deleted file mode 100644
index 1b16a5c3b..000000000
--- a/test/nodes/core/common/98-unknown_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var unknown = require("nr-test-utils").require("@node-red/nodes/core/common/98-unknown.js");
-var helper = require("node-red-node-test-helper");
-
-describe('unknown Node', function() {
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"n1", type:"unknown", name: "unknown" }];
- helper.load(unknown, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'unknown');
- done();
- });
- });
-
-});
diff --git a/test/nodes/core/function/10-function_spec.js b/test/nodes/core/function/10-function_spec.js
deleted file mode 100644
index 4f7f0b806..000000000
--- a/test/nodes/core/function/10-function_spec.js
+++ /dev/null
@@ -1,1721 +0,0 @@
-/**
-* Copyright JS Foundation and other contributors, http://js.foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**/
-
-var should = require("should");
-var functionNode = require("nr-test-utils").require("@node-red/nodes/core/function/10-function.js");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context");
-var helper = require("node-red-node-test-helper");
-var RED = require("nr-test-utils").require("node-red/lib/red");
-describe('function node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory1: {
- module: "memory"
- },
- memory2: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function() {
- helper.unload().then(function () {
- return Context.clean({allNodes:{}});
- }).then(function () {
- return Context.close();
- });
- });
-
- it('should send returned message using send()', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"node.send(msg);"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should do something with the catch node', function(done) {
- var flow = [{"id":"funcNode","type":"function","wires":[["goodNode"]],"func":"node.error('This is an error', msg);"},{"id":"goodNode","type":"helper"},{"id":"badNode","type":"helper"},{"id":"catchNode","type":"catch","scope":null,"uncaught":false,"wires":[["badNode"]]}];
- var catchNodeModule = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js")
- helper.load([catchNodeModule, functionNode], flow, function() {
- var funcNode = helper.getNode("funcNode");
- var catchNode = helper.getNode("catchNode");
- var goodNode = helper.getNode("goodNode");
- var badNode = helper.getNode("badNode");
-
- badNode.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- msg.should.have.property('error');
- msg.error.should.have.property('message',"This is an error");
- msg.error.should.have.property('source');
- msg.error.source.should.have.property('id', "funcNode");
- done();
- });
- funcNode.receive({payload:"foo",topic: "bar"});
- });
- });
-
-
-
-
- it('should be loaded', function(done) {
- var flow = [{id:"n1", type:"function", name: "function" }];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'function');
- done();
- });
- });
-
- it('should send returned message', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should send returned message using send()', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"node.send(msg);"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should allow accessing node.id and node.name and node.outputCount', function(done) {
- var flow = [{id:"n1",name:"test-function", outputs: 2, type:"function",wires:[["n2"]],func: "return [{ topic: node.name, payload:node.id, outputCount: node.outputCount }];"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- // Use this form of assert as `msg` is created inside
- // the sandbox and doesn't get all the should.js monkey patching
- should.equal(msg.payload, n1.id);
- should.equal(msg.topic, n1.name);
- should.equal(msg.outputCount, n1.outputs);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:""});
- });
- });
-
- function testSendCloning(args,done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"],["n2"]],func:"node.send("+args+"); msg.payload = 'changed';"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- done();
- } catch(err) {
- done(err);
- }
- });
- var origMessage = {payload:"foo",topic: "bar"};
- n1.receive(origMessage);
- });
- }
- it('should clone single message sent using send()', function(done) {
- testSendCloning("msg",done);
- });
- it('should not clone single message sent using send(,false)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"node.send(msg,false); msg.payload = 'changed';"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'changed');
- done();
- });
- var origMessage = {payload:"foo",topic: "bar"};
- n1.receive(origMessage);
- });
- });
- it('should clone first message sent using send() - array 1', function(done) {
- testSendCloning("[msg]",done);
- });
- it('should clone first message sent using send() - array 2', function(done) {
- testSendCloning("[[msg],[null]]",done);
- });
- it('should clone first message sent using send() - array 3', function(done) {
- testSendCloning("[null,msg]",done);
- });
- it('should clone first message sent using send() - array 3', function(done) {
- testSendCloning("[null,[msg]]",done);
- });
-
- it('should pass through _topic', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- msg.should.have.property('_topic', 'baz');
- done();
- });
- n1.receive({payload:"foo",topic: "bar", _topic: "baz"});
- });
- });
-
- it('should send to multiple outputs', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"],["n3"]],
- func:"return [{payload: '1'},{payload: '2'}];"},
- {id:"n2", type:"helper"}, {id:"n3", type:"helper"} ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var count = 0;
- n2.on("input", function(msg) {
- should(msg).have.property('payload', '1');
- count++;
- if (count == 2) {
- done();
- }
- });
- n3.on("input", function(msg) {
- should(msg).have.property('payload', '2');
- count++;
- if (count == 2) {
- done();
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should send to multiple messages', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],
- func:"return [[{payload: 1},{payload: 2}]];"},
- {id:"n2", type:"helper"} ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- count++;
- try {
- should(msg).have.property('payload', count);
- should(msg).have.property('_msgid', 1234);
- if (count == 2) {
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", topic: "bar",_msgid:1234});
- });
- });
-
- it('should allow input to be discarded by returning null', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return null"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- setTimeout(function() {
- done();
- }, 20);
- n2.on("input", function(msg) {
- should.fail(null,null,"unexpected message");
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should handle null amongst valid messages', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return [[msg,null,msg],null]"},
- {id:"n2", type:"helper"},
- {id:"n3", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n2MsgCount = 0;
- var n3MsgCount = 0;
- n2.on("input", function(msg) {
- n2MsgCount++;
- });
- n3.on("input", function(msg) {
- n3MsgCount++;
- });
- n1.receive({payload:"foo",topic: "bar"});
- setTimeout(function() {
- n2MsgCount.should.equal(2);
- n3MsgCount.should.equal(0);
- done();
- },20);
- });
- });
-
- it('should get keys in global context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=global.keys();return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- function testNonObjectMessage(functionText,done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:functionText},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n2MsgCount = 0;
- n2.on("input", function(msg) {
- n2MsgCount++;
- });
- n1.receive({});
- setTimeout(function() {
- try {
- n2MsgCount.should.equal(0);
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', 'function.error.non-message-returned');
- done();
- } catch(err) {
- done(err);
- }
- },20);
- });
- }
- it('should drop and log non-object message types - string', function(done) {
- testNonObjectMessage('return "foo"', done)
- });
- it('should drop and log non-object message types - buffer', function(done) {
- testNonObjectMessage('return Buffer.from("hello")', done)
- });
- it('should drop and log non-object message types - array', function(done) {
- testNonObjectMessage('return [[[1,2,3]]]', done)
- });
- it('should drop and log non-object message types - boolean', function(done) {
- testNonObjectMessage('return true', done)
- });
- it('should drop and log non-object message types - number', function(done) {
- testNonObjectMessage('return 123', done)
- });
-
- it('should handle and log script error', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"var a = 1;\nretunr"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.receive({payload:"foo",topic: "bar"});
- setTimeout(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', 'ReferenceError: retunr is not defined (line 2, col 1)');
- done();
- } catch(err) {
- done(err);
- }
- },50);
- });
- });
-
- it('should handle node.on()', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"node.on('close',function(){ node.log('closed')});"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.receive({payload:"foo",topic: "bar"});
- setTimeout(function() {
- n1.close().then(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().INFO);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', 'closed');
- done();
- } catch(err) {
- done(err);
- }
- });
- },100);
- });
- });
-
- it('should set node context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set('count','0');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count").should.equal("0");
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should set persistable node context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set('count','0','memory1');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count", "memory1", function (err, val) {
- val.should.equal("0");
- done();
- });
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set two persistable node context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set('count','0','memory1');context.set('count','1','memory2');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count", "memory1", function (err, val1) {
- val1.should.equal("0");
- n1.context().get("count", "memory2", function (err, val2) {
- val2.should.equal("1");
- done();
- });
- });
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set two persistable node context (single call, w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set(['count1','count2'],['0','1'],'memory1');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count1", "memory1", function (err, val1) {
- val1.should.equal("0");
- n1.context().get("count2", "memory1", function (err, val2) {
- val2.should.equal("1");
- done();
- });
- });
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
-
- it('should set persistable node context (w callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set('count','0','memory1', function (err) { node.send(msg); });"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count", "memory1", function (err, val) {
- val.should.equal("0");
- done();
- });
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set two persistable node context (w callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set('count','0','memory1', function (err) { context.set('count', '1', 'memory2', function (err) { node.send(msg); }); });"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count", "memory1", function (err, val1) {
- val1.should.equal("0");
- n1.context().get("count", "memory1", function (err, val2) {
- val2.should.equal("0");
- done();
- });
- });
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set two persistable node context (single call, w callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set(['count1','count2'],['0','1'],'memory1', function(err) { node.send(msg); });"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count1", "memory1", function (err, val1) {
- val1.should.equal("0");
- n1.context().get("count2", "memory1", function (err, val2) {
- val2.should.equal("1");
- done();
- });
- });
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
-
- it('should set default persistable node context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.set('count','0');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n1.context().get("count", "memory1", function (err, val) {
- val.should.equal("0");
- done();
- });
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get node context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.get('count');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- function checkCallbackError(name, done) {
- setTimeout(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', name);
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', 'Error: Callback must be a function');
- done();
- }
- catch (e) {
- done(e);
- }
- },50);
- }
-
- it('should get persistable node context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.get('count','memory1');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().set("count","0","memory1");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get persistable node context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.get('count','memory1',function (err, val) { msg.payload=val; node.send(msg); });"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().set("count","0","memory1");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get keys in node context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.keys();return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should get keys in persistable node context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.keys('memory1');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().set("count","0","memory1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get keys in persistable node context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.keys('memory1', function(err, keys) { msg.payload=keys; node.send(msg); });"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().set("count","0","memory1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get keys in default persistable node context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.keys();return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().set("count","0","memory1");
- n1.context().set("number","1","memory2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set flow context', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.set('count','0');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().flow.get("count").should.equal("0");
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should set persistable flow context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.set('count','0','memory1');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().flow.get("count", "memory1", function (err, val) {
- val.should.equal("0");
- done();
- });
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set two persistable flow context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.set('count','0','memory1');flow.set('count','1','memory2');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().flow.get("count", "memory1", function (err, val1) {
- val1.should.equal("0");
- n2.context().flow.get("count", "memory2", function (err, val2) {
- val2.should.equal("1");
- done();
- });
- });
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set persistable flow context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.set('count','0','memory1', function (err) { node.send(msg); });"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().flow.get("count", "memory1", function (err, val) {
- val.should.equal("0");
- done();
- });
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set two persistable flow context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.set('count','0','memory1', function (err) { flow.set('count','1','memory2', function (err) { node.send(msg); }); });"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().flow.get("count", "memory1", function (err, val1) {
- val1.should.equal("0");
- n2.context().flow.get("count", "memory2", function (err, val2) {
- val2.should.equal("1");
- done();
- });
- });
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get flow context', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=flow.get('count');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should get persistable flow context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=flow.get('count','memory1');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0","memory1");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get persistable flow context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.get('count','memory1', function(err, val) { msg.payload=val; node.send(msg); });"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0","memory1");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get flow context', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=context.flow.get('count');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should get keys in flow context', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=flow.keys();return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should get keys in persistable flow context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=flow.keys('memory1');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0","memory1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get keys in persistable flow context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"flow.keys('memory1', function (err, val) { msg.payload=val; node.send(msg); });"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0","memory1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', ['count']);
- done();
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set global context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"global.set('count','0');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().global.get("count").should.equal("0");
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should set persistable global context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"global.set('count','0','memory1');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().global.get("count", "memory1", function(err, val) {
- val.should.equal("0");
- done();
- });
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should set persistable global context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"global.set('count','0','memory1', function (err) { node.send(msg); });"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- n2.context().global.get("count", "memory1", function(err, val) {
- val.should.equal("0");
- done();
- });
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get global context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=global.get('count');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should get persistable global context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=global.get('count', 'memory1');return msg;"},
- {id:"n2", type:"helper"}];
- initContext(function () {
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("count","0", 'memory1');
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get persistable global context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"global.get('count', 'memory1', function (err, val) { msg.payload=val; node.send(msg); });"},
- {id:"n2", type:"helper"}];
- initContext(function () {
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("count","0", 'memory1');
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get global context', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.global.get('count');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("count","0");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should get persistable global context (w/o callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=context.global.get('count','memory1');return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("count","0", "memory1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should get persistable global context (w/ callback)', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"context.global.get('count','memory1', function (err, val) { msg.payload = val; node.send(msg); });"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("count","0", "memory1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '0');
- done();
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should handle error on get persistable context', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=context.get('count','memory1','callback');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0","memory1");
- n1.receive({payload:"foo",topic: "bar"});
- checkCallbackError('n1', done);
- });
- });
- });
-
- it('should handle error on set persistable context', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=context.set('count','0','memory1','callback');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.receive({payload:"foo",topic: "bar"});
- checkCallbackError('n1', done);
- });
- });
- });
-
- it('should handle error on get keys in persistable context', function(done) {
- var flow = [{id:"n1",type:"function",z:"flowA",wires:[["n2"]],func:"msg.payload=context.keys('memory1','callback');return msg;"},
- {id:"n2", type:"helper",z:"flowA"}];
- helper.load(functionNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("count","0","memory1");
- n1.receive({payload:"foo",topic: "bar"});
- checkCallbackError('n1', done);
- });
- });
- });
-
- it('should handle setTimeout()', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"setTimeout(function(){node.send(msg);},700);"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- var endTime = process.hrtime(startTime);
- var nanoTime = endTime[0] * 1000000000 + endTime[1];
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- if (600000000 < nanoTime && nanoTime < 800000000) {
- done();
- } else {
- try {
- should.fail(null, null, "Delayed time was not between 900 and 1100 ms");
- } catch (err) {
- done(err);
- }
- }
- });
- var startTime = process.hrtime();
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should handle setInterval()', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"setInterval(function(){node.send(msg);},100);"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- count++;
- if (count > 2) {
- done();
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should handle clearInterval()', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"var id=setInterval(null,100);setTimeout(function(){clearInterval(id);node.send(msg);},500);"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should allow accessing node.id', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = node.id; return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', n1.id);
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should allow accessing node.name', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = node.name; return msg;", "name":"name of node"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', n1.name);
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should use the same Date object from outside the sandbox', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload=global.get('typeTest')(new Date());return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("typeTest",function(d) { return d instanceof Date });
- n2.on("input", function(msg) {
- msg.should.have.property('payload', true);
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should allow accessing env vars', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = env.get('_TEST_FOO_'); return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- delete process.env._TEST_FOO_;
-
- n2.on("input", function(msg) {
- try {
- if (count === 0) {
- msg.should.have.property('payload', undefined);
- process.env._TEST_FOO_ = "hello";
- count++;
- n1.receive({payload:"foo",topic: "bar"});
- } else {
- msg.should.have.property('payload', "hello");
- delete process.env._TEST_FOO_;
- done();
- }
- } catch(err) {
- delete process.env._TEST_FOO_;
- done(err);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should execute initialization', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = global.get('X'); return msg;",initialize:"global.set('X','bar');"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property("payload", "bar");
- done();
- });
- n1.receive({payload: "foo"});
- });
- });
-
- it('should wait completion of initialization', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = global.get('X'); return msg;",initialize:"global.set('X', '-'); return new Promise((resolve, reject) => setTimeout(() => { global.set('X','bar'); resolve(); }, 500));"},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property("payload", "bar");
- done();
- });
- n1.receive({payload: "foo"});
- });
- });
-
-
-
- describe("finalize function", function() {
-
- it('should execute', function(done) {
- var flow = [{id:"n1",type:"function",wires:[],func:"return msg;",finalize:"global.set('X','bar');"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var ctx = n1.context().global;
- helper.unload().then(function () {
- ctx.get('X').should.equal("bar");
- done();
- });
- });
- });
-
- it('should allow accessing node.id and node.name and node.outputCount', function(done) {
- var flow = [{id:"n1",name:"test-function", outputs: 2, type:"function",wires:[["n2"]],finalize:"global.set('finalize-data', { topic: node.name, payload:node.id, outputCount: node.outputCount});", func: "return msg;"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var ctx = n1.context().global;
- helper.unload().then(function () {
- const finalizeData = ctx.get('finalize-data');
- should.equal(finalizeData.payload, n1.id);
- should.equal(finalizeData.topic, n1.name);
- should.equal(finalizeData.outputCount, n1.outputs);
- done();
- });
- });
- });
-
- })
-
- describe('externalModules', function() {
- afterEach(function() {
- delete RED.settings.functionExternalModules;
- })
- it('should fail if using OS module with functionExternalModules set to false', function(done) {
- var flow = [
- {id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = os.type(); return msg;", "libs": [{var:"os", module:"os"}]},
- {id:"n2", type:"helper"}
- ];
- RED.settings.functionExternalModules = false;
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- should.not.exist(n1);
- done();
- }).catch(err => done(err));
- })
-
- it('should fail if using OS module without it listed in libs', function(done) {
- var flow = [
- {id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = os.type(); return msg;"},
- {id:"n2", type:"helper"}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var messageReceived = false;
- n2.on("input", function(msg) {
- messageReceived = true;
- });
- n1.receive({payload:"foo",topic: "bar"});
- setTimeout(function() {
- try {
- messageReceived.should.be.false();
- done();
- } catch(err) {
- done(err);
- }
- },20);
- }).catch(err => done(err));
- })
- it('should require the OS module', function(done) {
- var flow = [
- {id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = os.type(); return msg;", "libs": [{var:"os", module:"os"}]},
- {id:"n2", type:"helper"}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', require('os').type());
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- }).catch(err => done(err));
- })
- it('should fail if module variable name clashes with sandbox builtin', function(done) {
- var flow = [
- {id:"n1",type:"function",wires:[["n2"]],func:"msg.payload = os.type(); return msg;", "libs": [{var:"flow", module:"os"}]},
- {id:"n2", type:"helper"}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- should.not.exist(n1);
- done();
- }).catch(err => done(err));
- })
- })
-
-
- describe('Logger', function () {
-
- function testLog(initCode,funcCode,expectedLevel, done) {
- var flow = [{id: "n1", type: "function", wires: [["n2"]], func: funcCode, initialize: initCode}];
- helper.load(functionNode, flow, function () {
- var n1 = helper.getNode("n1");
- n1.receive({payload: "foo", topic: "bar"});
- setTimeout(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log()[expectedLevel]);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', 'test');
- done();
- } catch (err) {
- done(err);
- }
- },10);
- });
- }
-
- it('should log an Info Message', function (done) {
- testLog("","node.log('test');","INFO",done);
- });
- it('should log a Debug Message', function (done) {
- testLog("","node.debug('test');","DEBUG",done);
- });
- it('should log a Trace Message', function (done) {
- testLog("","node.trace('test');","TRACE",done);
- });
- it('should log a Warning Message', function (done) {
- testLog("","node.warn('test');","WARN",done);
- });
- it('should log an Error Message', function (done) {
- testLog("","node.error('test');","ERROR",done);
- });
-
- it('should log an Info Message - initialise', function (done) {
- testLog("node.log('test');","","INFO",done);
- });
- it('should log a Debug Message - initialise', function (done) {
- testLog("node.debug('test');","","DEBUG",done);
- });
- it('should log a Trace Message - initialise', function (done) {
- testLog("node.trace('test');","","TRACE",done);
- });
- it('should log a Warning Message - initialise', function (done) {
- testLog("node.warn('test');","","WARN",done);
- });
- it('should log an Error Message - initialise', function (done) {
- testLog("node.error('test');","","ERROR",done);
- });
-
- it('should catch thrown string', function (done) {
- var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "throw \"small mistake\";"}];
- helper.load(functionNode, flow, function () {
- var n1 = helper.getNode("n1");
- n1.receive({payload: "foo", topic: "bar"});
- setTimeout(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', 'small mistake');
- done();
- } catch (err) {
- done(err);
- }
- },50);
- });
- });
- it('should catch thrown number', function (done) {
- var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "throw 99;"}];
- helper.load(functionNode, flow, function () {
- var n1 = helper.getNode("n1");
- n1.receive({payload: "foo", topic: "bar"});
- setTimeout(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', '99');
- done();
- } catch (err) {
- done(err);
- }
- },50);
- });
- });
- it('should catch thrown object (bad practice)', function (done) {
- var flow = [{id: "n1", type: "function", wires: [["n2"]], func: "throw {a:1};"}];
- helper.load(functionNode, flow, function () {
- var n1 = helper.getNode("n1");
- n1.receive({payload: "foo", topic: "bar"});
- setTimeout(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "function";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'function');
- msg.should.have.property('msg', '{"a":1}');
- done();
- } catch (err) {
- done(err);
- }
- },50);
- });
- });
- });
-
- describe("init function", function() {
-
- it('should delay handling messages until init completes', function(done) {
- var flow = [{id:"n1",type:"function",wires:[["n2"]],initialize: `
- return new Promise((resolve,reject) => {
- setTimeout(resolve,200)
- })`,
- func:"return msg;"
- },
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var receivedMsgs = [];
- n2.on("input", function(msg) {
- msg.delta = Date.now() - msg.payload;
- receivedMsgs.push(msg)
- if (receivedMsgs.length === 5) {
- var errors = receivedMsgs.filter(msg => msg.delta < 200)
- if (errors.length > 0) {
- done(new Error(`Message received before init completed - was ${msg.delta} expected >300`))
- } else {
- done();
- }
- }
- });
- for (var i=0;i<5;i++) {
- n1.receive({payload: Date.now(),topic: "msg"+i});
- }
- });
- });
-
- it('should allow accessing node.id and node.name and node.outputCount and sending message', function(done) {
- var flow = [{id:"n1",name:"test-function", outputs: 1, type:"function",wires:[["n2"]],initialize:"setTimeout(function() { node.send({ topic: node.name, payload:node.id, outputCount: node.outputCount})},10)", func: ""},
- {id:"n2", type:"helper"}];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- // Use this form of assert as `msg` is created inside
- // the sandbox and doesn't get all the should.js monkey patching
- should.equal(msg.payload, n1.id);
- should.equal(msg.topic, n1.name);
- should.equal(msg.outputCount, n1.outputs);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- });
-});
diff --git a/test/nodes/core/function/10-switch_spec.js b/test/nodes/core/function/10-switch_spec.js
deleted file mode 100644
index 180ec9d36..000000000
--- a/test/nodes/core/function/10-switch_spec.js
+++ /dev/null
@@ -1,1153 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-
-var switchNode = require("nr-test-utils").require("@node-red/nodes/core/function/10-switch.js");
-var helper = require("node-red-node-test-helper");
-var RED = require("nr-test-utils").require("node-red/lib/red");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context/");
-
-describe('switch Node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory0: {
- module: "memory"
- },
- memory1: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function(done) {
- helper.unload().then(function () {
- return Context.clean({allNodes: {}});
- }).then(function () {
- return Context.close();
- }).then(function () {
- RED.settings.nodeMessageBufferMaxLength = 0;
- helper.stopServer(done);
- });
- });
-
- it('should be loaded with some defaults', function(done) {
- var flow = [{"id":"switchNode1","type":"switch","name":"switchNode"}];
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- switchNode1.should.have.property('name', 'switchNode');
- switchNode1.should.have.property('checkall', "true");
- switchNode1.should.have.property('rules', []);
- done();
- });
- });
-
- /**
- * Test a switch node where one argument is consumed by the rule (such as greater than).
- * @param rule - the switch rule (see 10-switc.js) string we're using
- * @param ruleWith - whatever the rule should be executed with (say greater than 5)
- * @param aCheckall - whether the switch flow should have the checkall flag set to true/false
- * @param shouldReceive - whether the helper node should receive a payload
- * @param sendPayload - the payload message we're sending
- * @param done - callback when done
- */
- function genericSwitchTest(rule, ruleWith, aCheckall, shouldReceive, sendPayload, done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":rule,"v":ruleWith}],checkall:aCheckall,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, shouldReceive, sendPayload, done);
- }
-
- /**
- * Test a switch node where NO arguments are consumed by the rule (such as TRUE/FALSE)
- * @param rule - the switch rule (see 10-switc.js) string we're using
- * @param aCheckall - whether the switch flow should have the checkall flag set to true/false
- * @param shouldReceive - whether the helper node should receive a payload
- * @param sendPayload - the payload message we're sending
- * @param done - callback when done
- */
- function singularSwitchTest(rule, aCheckall, shouldReceive, sendPayload, done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":rule}],checkall:aCheckall,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, shouldReceive, sendPayload, done);
- }
-
- /**
- * Test a switch node where two arguments are consumed by the rule (such as between).
- * @param rule - the switch rule (see 10-switc.js) string we're using
- * @param ruleWith - whatever the rule should be executed with (say between 5...)
- * @param ruleWith2 - whatever the rule should be executed with (say ...and 5)
- * @param aCheckall - whether the switch flow should have the checkall flag set to true/false
- * @param shouldReceive - whether the helper node should receive a payload
- * @param sendPayload - the payload message we're sending
- * @param done - callback when done
- */
- function twoFieldSwitchTest(rule, ruleWith, ruleWith2, aCheckall, shouldReceive, sendPayload, done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":rule,"v":ruleWith,"v2":ruleWith2}],checkall:aCheckall,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, shouldReceive, sendPayload, done);
- }
-
- /**
- * Execute a switch test. Can specify whether the should node is expected to send a payload onwards to the helper node.
- * The flow and the payload can be customised
- * @param flow - the custom flow to be tested => must contain a switch node (switchNode1) wiring a helper node (helperNode1)
- * @param shouldReceive - whether the helper node should receive a payload
- * @param sendPayload - the payload message we're sending
- * @param done - callback when done
- */
- function customFlowSwitchTest(flow, shouldReceive, sendPayload, done) {
- customFlowMessageSwitchTest(flow,shouldReceive,{payload: sendPayload}, done);
- }
-
- function customFlowMessageSwitchTest(flow, shouldReceive, message, done) {
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- if (shouldReceive === true) {
- should.equal(msg,message);
- done();
- } else {
- should.fail(null, null, "We should never get an input!");
- }
- } catch(err) {
- done(err);
- }
- });
- switchNode1.receive(message);
- if (shouldReceive === false) {
- setTimeout(function() {
- done();
- }, 200);
- }
- });
- }
-
- function customFlowSequenceSwitchTest(flow, seq_in, seq_out, repair, modifier, done) {
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var sid;
- var count = 0;
- if (modifier !== undefined) {
- modifier(switchNode1);
- }
- helperNode1.on("input", function(msg) {
- try {
- msg.should.have.property("payload", seq_out[count]);
- msg.should.have.property("parts");
- var parts = msg.parts;
- parts.should.have.property("id");
- var id = parts.id;
- if (sid === undefined) {
- sid = id;
- }
- else {
- id.should.equal(sid);
- }
- if (repair) {
- parts.should.have.property("index", count);
- parts.should.have.property("count", seq_out.length);
- }
- else {
- parts.should.have.property("index", msg.xindex);
- parts.should.have.property("count", seq_in.length);
- }
- count++;
- if (count === seq_out.length) {
- done();
- }
- } catch (e) {
- done(e);
- }
- });
- var len = seq_in.length;
- for (var i = 0; i < len; i++) {
- var parts = {index:i, count:len, id:222};
- var msg = {payload:seq_in[i], xindex:i, parts:parts};
- switchNode1.receive(msg);
- }
- });
- }
-
- it('should check if payload equals given value', function(done) {
- genericSwitchTest("eq", "Hello", true, true, "Hello", done);
- });
-
- it('should return nothing when the payload doesn\'t equal to desired string', function(done) {
- genericSwitchTest("eq", "Hello", true, false, "Hello!", done);
- });
-
- it('should check if payload NOT equals given value', function(done) {
- genericSwitchTest("neq", "Hello", true, true, "HEllO", done);
- });
-
- it('should return nothing when the payload does equal to desired string', function(done) {
- genericSwitchTest("neq", "Hello", true, false, "Hello", done);
- });
-
- it('should check if payload equals given numeric value', function(done) {
- genericSwitchTest("eq", 3, true, true, 3, done);
- });
-
- it('should return nothing when the payload doesn\'t equal to desired numeric value', function(done) {
- genericSwitchTest("eq", 2, true, false, 4, done);
- });
-
- it('should check if payload NOT equals given numeric value', function(done) {
- genericSwitchTest("neq", 55667744, true, true, -1234, done);
- });
-
- it('should return nothing when the payload does equal to desired numeric value', function(done) {
- genericSwitchTest("neq", 10, true, false, 10, done);
- });
-
- it('should check if payload is less than given value', function(done) {
- genericSwitchTest("lt", 3, true, true, 2, done);
- });
-
- it('should return nothing when the payload is not less than desired string', function(done) {
- genericSwitchTest("lt", 3, true, false, 4, done);
- });
-
- it('should check if payload less than equals given value', function(done) {
- genericSwitchTest("lte", 3, true, true, 3, done);
- });
-
- it('should check if payload is greater than given value', function(done) {
- genericSwitchTest("gt", 3, true, true, 6, done);
- });
-
- it('should return nothing when the payload is not greater than desired string', function(done) {
- genericSwitchTest("gt", 3, true, false, -1, done);
- });
-
- it('should check if payload is greater than/equals given value', function(done) {
- genericSwitchTest("gte", 3, true, true, 3, done);
- });
-
- it('should return nothing when the payload is not greater than desired string', function(done) {
- genericSwitchTest("gt", 3, true, false, -1, done);
- });
-
- it('should check if payload is greater than/equals given value', function(done) {
- genericSwitchTest("gte", 3, true, true, 3, done);
- });
-
- it('should match if a payload has a required property', function(done) {
- genericSwitchTest("hask", "a", true, true, {a:1}, done);
- });
- it('should not match if a payload does not have a required property', function(done) {
- genericSwitchTest("hask", "a", true, false, {b:1}, done);
- });
- it('should not match if the key is not a string', function(done) {
- genericSwitchTest("hask", 1, true, false, {a:1}, done);
- });
- it('should not match if the parent object does not exist - null', function(done) {
- genericSwitchTest("hask", "a", true, false, null, done);
- });
- it('should not match if the parent object does not exist - undefined', function(done) {
- genericSwitchTest("hask", "a", true, false, undefined, done);
- });
- it('should check if payload is between given values', function(done) {
- twoFieldSwitchTest("btwn", "3", "5", true, true, 4, done);
- });
-
- it('should check if payload is between given values in "wrong" order', function(done) {
- twoFieldSwitchTest("btwn", "5", "3", true, true, 4, done);
- });
-
- it('should check if payload is between given string values', function(done) {
- twoFieldSwitchTest("btwn", "c", "e", true, true, "d", done);
- });
-
- it('should check if payload is not between given values', function(done) {
- twoFieldSwitchTest("btwn", 3, 5, true, false, 12, done);
- });
-
- it('should check if payload contains given value', function(done) {
- genericSwitchTest("cont", "Hello", true, true, "Hello World!", done);
- });
-
- it('should return nothing when the payload doesn\'t contain desired string', function(done) {
- genericSwitchTest("cont", "Hello", true, false, "This is not a greeting!", done);
- });
-
- it('should match regex', function(done) {
- genericSwitchTest("regex", "[abc]+", true, true, "abbabac", done);
- });
-
- it('should check if payload if of type string ', function(done) {
- genericSwitchTest("istype", "string", true, true, "Hello", done);
- });
- it('should check if payload if of type number ', function(done) {
- genericSwitchTest("istype", "number", true, true, 999, done);
- });
- it('should check if payload if of type number 0', function(done) {
- genericSwitchTest("istype", "number", true, true, 0, done);
- });
- it('should check if payload if of type boolean true', function(done) {
- genericSwitchTest("istype", "boolean", true, true, true, done);
- });
- it('should check if payload if of type boolean false', function(done) {
- genericSwitchTest("istype", "boolean", true, true, true, done);
- });
- it('should check if payload if of type array ', function(done) {
- genericSwitchTest("istype", "array", true, true, [1,2,3,"a","b"], done);
- });
- it('should check if payload if of type buffer ', function(done) {
- genericSwitchTest("istype", "buffer", true, true, Buffer.from("Hello"), done);
- });
- it('should check if payload if of type object ', function(done) {
- genericSwitchTest("istype", "object", true, true, {a:1,b:"b",c:true}, done);
- });
- it('should check if payload if of type JSON string ', function(done) {
- genericSwitchTest("istype", "json", true, true, JSON.stringify({a:1,b:"b",c:true}), done);
- });
- it('should check if payload if of type JSON string (and fail if not) ', function(done) {
- genericSwitchTest("istype", "json", true, false, "Hello", done);
- });
- it('should check if payload if of type null', function(done) {
- genericSwitchTest("istype", "null", true, true, null, done);
- });
- it('should check if payload if of type undefined', function(done) {
- genericSwitchTest("istype", "undefined", true, true, undefined, done);
- });
-
- it('should handle flow context', function (done) {
- var flow = [{"id": "switchNode1", "type": "switch", "property": "foo", "propertyType": "flow",
- "rules": [{"t": "eq", "v": "bar", "vt": "flow"}],
- "checkall": "true", "outputs": "1", "wires": [["helperNode1"]], "z": "flow"},
- {"id": "helperNode1", "type": "helper", "wires": []}];
- helper.load(switchNode, flow, function () {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function (msg) {
- try {
- msg.payload.should.equal("value");
- done();
- } catch (err) {
- done(err);
- }
- });
- switchNode1.context().flow.set("foo", "flowValue");
- switchNode1.context().flow.set("bar", "flowValue");
- switchNode1.receive({payload: "value"});
- });
- });
-
- it('should handle persistable flow context', function (done) {
- var flow = [{"id": "switchNode1", "type": "switch", "property": "#:(memory1)::foo", "propertyType": "flow",
- "rules": [{"t": "eq", "v": "#:(memory1)::bar", "vt": "flow"}],
- "checkall": "true", "outputs": "1", "wires": [["helperNode1"]], "z": "flow"},
- {"id": "helperNode1", "type": "helper", "wires": []}];
- helper.load(switchNode, flow, function () {
- initContext(function () {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function (msg) {
- try {
- msg.payload.should.equal("value");
- done();
- } catch (err) {
- done(err);
- }
- });
- switchNode1.context().flow.set("foo", "flowValue", "memory1", function (err) {
- switchNode1.context().flow.set("bar", "flowValue", "memory1", function (err) {
- switchNode1.receive({payload: "value"});
- });
- });
- });
- });
- });
-
- it('should handle global context', function (done) {
- var flow = [{"id": "switchNode1", "type": "switch", "property": "foo", "propertyType": "global",
- "rules": [{"t": "eq", "v": "bar", "vt": "global"}],
- "checkall": "true", "outputs": "1", "wires": [["helperNode1"]]},
- {"id": "helperNode1", "type": "helper", "wires": []}];
- helper.load(switchNode, flow, function () {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function (msg) {
- try {
- msg.payload.should.equal("value");
- done();
- } catch (err) {
- done(err);
- }
- });
- switchNode1.context().global.set("foo", "globalValue");
- switchNode1.context().global.set("bar", "globalValue");
- switchNode1.receive({payload: "value"});
- });
- });
-
- it('should handle persistable global context', function (done) {
- var flow = [{"id": "switchNode1", "type": "switch", "property": "#:(memory1)::foo", "propertyType": "global",
- "rules": [{"t": "eq", "v": "#:(memory1)::bar", "vt": "global"}],
- "checkall": "true", "outputs": "1", "wires": [["helperNode1"]]},
- {"id": "helperNode1", "type": "helper", "wires": []}];
- helper.load(switchNode, flow, function () {
- initContext(function () {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function (msg) {
- try {
- msg.payload.should.equal("foo");
- done();
- } catch (err) {
- done(err);
- }
- });
- switchNode1.context().global.set("foo", "globalValue", "memory1", function (err) {
- switchNode1.context().global.set("bar", "globalValue", "memory1", function (err) {
- switchNode1.receive({payload: "foo"});
- });
- });
- });
- });
- });
-
- it('should use a nested message property to compare value - matches', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload[msg.topic]",rules:[{"t":"eq","v":"bar"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowMessageSwitchTest(flow, true, {topic:"foo",payload:{"foo":"bar"}}, done);
- })
- it('should use a nested message property to compare value - no match', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload[msg.topic]",rules:[{"t":"eq","v":"bar"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowMessageSwitchTest(flow, false, {topic:"foo",payload:{"foo":"none"}}, done);
-
- })
-
- it('should use a nested message property to compare nested message property - matches', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload[msg.topic]",rules:[{"t":"eq","v":"payload[msg.topic2]",vt:"msg"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowMessageSwitchTest(flow, true, {topic:"foo",topic2:"foo2",payload:{"foo":"bar","foo2":"bar"}}, done);
- })
- it('should use a nested message property to compare nested message property - no match', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload[msg.topic]",rules:[{"t":"eq","v":"payload[msg.topic2]",vt:"msg"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowMessageSwitchTest(flow, false, {topic:"foo",topic2:"foo2",payload:{"foo":"bar","foo2":"none"}}, done);
- })
-
- it('should match regex with ignore-case flag set true', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"regex","v":"onetwothree","case":true}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, true, "oneTWOthree", done);
- });
- it('should not match regex with ignore-case flag unset', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"regex","v":"onetwothree"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, false, "oneTWOthree", done);
- });
- it('should not match regex with ignore-case flag set false', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"regex","v":"onetwothree",case:false}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, false, "oneTWOthree", done);
- });
-
- it('should return nothing when the payload doesn\'t match regex', function(done) {
- genericSwitchTest("regex", "\\d+", true, false, "This is not a digit", done);
- });
-
- it('should return nothing when the payload doesn\'t contain desired string', function(done) {
- genericSwitchTest("cont", "Hello", true, false, "This is not a greeting!", done);
- });
-
- it('should check if input is true', function(done) {
- singularSwitchTest(true, true, true, true, done);
- });
-
- it('sends nothing when input is false and checking for true', function(done) {
- singularSwitchTest(true, true, false, false, done);
- });
-
- it('should check if input is indeed false', function(done) {
- singularSwitchTest(false, true, true, false, done);
- });
-
- it('sends nothing when input is false and checking for true', function(done) {
- singularSwitchTest(false, true, false, true, done);
- });
-
- it('should check if payload is empty (string)', function(done) {
- singularSwitchTest("empty", true, true, "", done);
- });
- it('should check if payload is empty (array)', function(done) {
- singularSwitchTest("empty", true, true, [], done);
- });
- it('should check if payload is empty (buffer)', function(done) {
- singularSwitchTest("empty", true, true, Buffer.alloc(0), done);
- });
- it('should check if payload is empty (object)', function(done) {
- singularSwitchTest("empty", true, true, {}, done);
- });
- it('should check if payload is empty (non-empty string)', function(done) {
- singularSwitchTest("empty", true, false, "1", done);
- });
- it('should check if payload is empty (non-empty array)', function(done) {
- singularSwitchTest("empty", true, false, [1], done);
- });
- it('should check if payload is empty (non-empty buffer)', function(done) {
- singularSwitchTest("empty", true, false, Buffer.alloc(1), done);
- });
- it('should check if payload is empty (non-empty object)', function(done) {
- singularSwitchTest("empty", true, false, {a:1}, done);
- });
- it('should check if payload is empty (null)', function(done) {
- singularSwitchTest("empty", true, false, null, done);
- });
- it('should check if payload is empty (undefined)', function(done) {
- singularSwitchTest("empty", true, false, undefined, done);
- });
- it('should check if payload is empty (0)', function(done) {
- singularSwitchTest("empty", true, false, 0, done);
- });
-
- it('should check if payload is not empty (string)', function(done) {
- singularSwitchTest("nempty", true, !true, "", done);
- });
- it('should check if payload is not empty (array)', function(done) {
- singularSwitchTest("nempty", true, !true, [], done);
- });
- it('should check if payload is not empty (buffer)', function(done) {
- singularSwitchTest("nempty", true, !true, Buffer.alloc(0), done);
- });
- it('should check if payload is not empty (object)', function(done) {
- singularSwitchTest("nempty", true, !true, {}, done);
- });
- it('should check if payload is not empty (non-empty string)', function(done) {
- singularSwitchTest("nempty", true, !false, "1", done);
- });
- it('should check if payload is not empty (non-empty array)', function(done) {
- singularSwitchTest("nempty", true, !false, [1], done);
- });
- it('should check if payload is not empty (non-empty buffer)', function(done) {
- singularSwitchTest("nempty", true, !false, Buffer.alloc(1), done);
- });
- it('should check if payload is not empty (non-empty object)', function(done) {
- singularSwitchTest("nempty", true, !false, {a:1}, done);
- });
- it('should check if payload is not empty (null)', function(done) {
- singularSwitchTest("nempty", true, false, null, done);
- });
- it('should check if payload is not empty (undefined)', function(done) {
- singularSwitchTest("nempty", true, false, undefined, done);
- });
- it('should check if payload is not empty (0)', function(done) {
- singularSwitchTest("nempty", true, false, 0, done);
- });
-
- it('should check input against a previous value', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{ "t": "gt", "v": "", "vt": "prev" }],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var c = 0;
- helperNode1.on("input", function(msg) {
- if (msg.payload) {
- try {
- if (c === 0) {
- msg.payload.should.equal(1);
- }
- if (c === 1) {
- msg.payload.should.equal(2);
- done();
- }
- c += 1;
- } catch (err) {
- done(err);
- }
- } else {
- done();
- }
- });
- switchNode1.receive({payload:1});
- switchNode1.receive({payload:0});
- switchNode1.receive({payload:-2});
- switchNode1.receive({payload:2});
- });
- });
-
- it('should check input against a previous value (2nd option)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t": "btwn", "v": "10", "vt": "num", "v2": "", "v2t": "prev" }],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var c = 0;
- helperNode1.on("input", function(msg) {
- if (msg.payload) {
- try {
- if (c === 0) {
- msg.payload.should.equal(20);
- }
- if (c === 1) {
- msg.payload.should.equal(25);
- done();
- }
- c += 1;
- } catch (err) {
- done(err);
- }
- } else {
- //done();
- }
- });
- switchNode1.receive({payload:0});
- switchNode1.receive({payload:20}); // between 10 and 0
- switchNode1.receive({payload:30}); // between 10 and 20
- switchNode1.receive({payload:20}); // between 10 and 30 yes
- switchNode1.receive({payload:30}); // between 10 and 20 no
- switchNode1.receive({payload:25}); // between 10 and 30 yes
- });
- });
-
- it('should check if input is indeed null', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"null"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- if (msg.payload === null) {
- done();
- } else {
- console.log("msg is ",msg);
- }
- });
- switchNode1.receive({payload:null});
- });
- });
-
- it('should check if input is indeed undefined', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"null"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- if (msg.payload === undefined) {
- done();
- }
- else {
- console.log("msg is ",msg);
- }
- });
- switchNode1.receive({payload:undefined});
- });
- });
- it('should treat non-existant msg property conditional as undefined', function(done) {
- var flow = [{"id":"switchNode1","type":"switch","z":"feee1df.c3263e","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"this.does.not.exist","vt":"msg"}],"checkall":"true","outputs":1,"x":190,"y":440,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var received = [];
- helperNode1.on("input", function(msg) {
- received.push(msg);
- });
- // First message should be dropped as payload is not undefined
- switchNode1.receive({topic:"messageOne",payload:""});
- // Second message should pass through as payload is undefined
- switchNode1.receive({topic:"messageTwo",payload:undefined});
- setTimeout(function() {
- try {
- received.should.have.lengthOf(1);
- received[0].should.have.a.property("topic","messageTwo");
- done();
- } catch(err) {
- done(err);
- }
- },500)
- });
- });
-
- it('should check if input is indeed not null', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"nnull"}],checkall:false,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- if (msg.payload) {
- done();
- } else {
- try {
- msg.payload.should.equal("Anything here");
- } catch (err) {
- done(err);
- }
- }
- });
- switchNode1.receive({payload:"Anything here"});
- });
- });
-
- it('sends a message when the "else/otherwise" statement is selected' , function(done) {
- singularSwitchTest("else", true, true, 123456, done);
- });
-
- it('handles more than one switch statement' , function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"eq","v":"Hello"},{"t":"cont","v":"ello"}, {"t":"else"}],checkall:true,outputs:3,wires:[["helperNode1"], ["helperNode2"], ["helperNode3"]]},
- {id:"helperNode1", type:"helper", wires:[]},
- {id:"helperNode2", type:"helper", wires:[]},
- {id:"helperNode3", type:"helper", wires:[]}];
-
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var helperNode2 = helper.getNode("helperNode2");
- var helperNode3 = helper.getNode("helperNode3");
-
- var nodeHitCount = 0;
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Hello");
- nodeHitCount++;
- } catch (err) {
- done(err);
- }
- });
- helperNode2.on("input", function(msg) {
- try {
- msg.payload.should.equal("Hello");
- nodeHitCount++;
- if (nodeHitCount == 2) {
- done();
- } else {
- try {
- should.fail(null, null, "Both statements should be triggered!");
- } catch (err) {
- done(err);
- }
- }
- } catch (err) {
- done(err);
- }
- });
- helperNode3.on("input", function(msg) {
- try {
- should.fail(null, null, "The otherwise/else statement should not be triggered here!");
- } catch (err) {
- done(err);
- }
- });
- switchNode1.receive({payload:"Hello"});
- });
- });
-
- it('stops after first statement' , function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"eq","v":"Hello"},{"t":"cont","v":"ello"}, {"t":"else"}],checkall:"false",outputs:3,wires:[["helperNode1"], ["helperNode2"], ["helperNode3"]]},
- {id:"helperNode1", type:"helper", wires:[]},
- {id:"helperNode2", type:"helper", wires:[]},
- {id:"helperNode3", type:"helper", wires:[]}];
-
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var helperNode2 = helper.getNode("helperNode2");
- var helperNode3 = helper.getNode("helperNode3");
-
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Hello");
- done();
- } catch (err) {
- done(err);
- }
- });
- helperNode2.on("input", function(msg) {
- try {
- should.fail(null, null, "The otherwise/else statement should not be triggered here!");
- } catch (err) {
- done(err);
- }
- });
- helperNode3.on("input", function(msg) {
- try {
- should.fail(null, null, "The otherwise/else statement should not be triggered here!");
- } catch (err) {
- done(err);
- }
- });
- switchNode1.receive({payload:"Hello"});
- });
- });
-
- it('should handle JSONata expression', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"$abs(payload)",propertyType:"jsonata",rules:[{"t":"btwn","v":"$sqrt(16)","vt":"jsonata","v2":"$sqrt(36)","v2t":"jsonata"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, true, -5, done);
- });
-
- it('should handle flow and global contexts with JSONata expression', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"$abs($flowContext(\"payload\"))",propertyType:"jsonata",rules:[{"t":"btwn","v":"$flowContext(\"vt\")","vt":"jsonata","v2":"$globalContext(\"v2t\")","v2t":"jsonata"}],checkall:true,outputs:1,wires:[["helperNode1"]],z:"flow"},
- {id:"helperNode1", type:"helper", wires:[],z:"flow"},
- {id:"flow",type:"tab"}];
- helper.load(switchNode, flow, function() {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- switchNode1.context().flow.set("payload",-5);
- switchNode1.context().flow.set("vt",4);
- switchNode1.context().global.set("v2t",6);
- helperNode1.on("input", function(msg) {
- try {
- should.equal(msg.payload,"pass");
- done();
- } catch(err) {
- done(err);
- }
- });
- switchNode1.receive({payload:"pass"});
- });
- });
-
- it('should handle persistable flow and global contexts with JSONata expression', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"$abs($flowContext(\"payload\",\"memory1\"))",propertyType:"jsonata",rules:[{"t":"btwn","v":"$flowContext(\"vt\",\"memory1\")","vt":"jsonata","v2":"$globalContext(\"v2t\",\"memory1\")","v2t":"jsonata"}],checkall:true,outputs:1,wires:[["helperNode1"]],z:"flow"},
- {id:"helperNode1", type:"helper", wires:[],z:"flow"},
- {id:"flow",type:"tab"}];
- helper.load(switchNode, flow, function() {
- initContext(function () {
- var switchNode1 = helper.getNode("switchNode1");
- var helperNode1 = helper.getNode("helperNode1");
- switchNode1.context().flow.set(["payload","vt"],[-7,6],"memory1",function(){
- switchNode1.context().global.set("v2t",8,"memory1",function(){
- helperNode1.on("input", function(msg) {
- try {
- should.equal(msg.payload,"pass");
- done();
- } catch(err) {
- done(err);
- }
- });
- switchNode1.receive({payload:"pass"});
- });
- });
- });
- });
- });
-
- it('should handle env var expression', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"VAR",propertyType:"env",rules:[{"t":"eq","v":"VAL"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- process.env.VAR = "VAL";
- customFlowSwitchTest(flow, true, "OK", done);
- });
-
-
- it('should take head of message sequence (no repair)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"head","v":3}],checkall:false,repair:false,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [0, 1, 2], false, undefined, done);
- });
-
- it('should take head of message sequence (repair)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"head","v":3}],checkall:false,repair:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [0, 1, 2], true, undefined, done);
- });
-
- it('should take head of message sequence (w. context)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"head","v":"count",vt:"global"}],checkall:false,repair:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [0, 1, 2], true,
- function(node) {
- node.context().global.set("count", 3);
- }, done);
- });
-
- it('should take head of message sequence (w. JSONata)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"head","v":"1+4/2",vt:"jsonata"}],checkall:false,repair:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [0, 1, 2], true, undefined, done);
- });
-
- it('should take tail of message sequence (no repair)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"tail","v":3}],checkall:true,repair:false,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [2, 3, 4], false, undefined, done);
- });
-
- it('should take tail of message sequence (repair)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"tail","v":3}],checkall:true,repair:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [2, 3, 4], true, undefined, done);
- });
-
- it('should take slice of message sequence (no repair)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"index","v":1,"v2":3}],checkall:true,repair:false,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [1, 2, 3], false, undefined, done);
- });
-
- it('should take slice of message sequence (repair)', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"index","v":1,"v2":3}],checkall:true,repair:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [1, 2, 3], true, undefined, done);
- });
-
- it('should check JSONata expression is true', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",
- rules:[{"t":"jsonata_exp","v":"payload%2 = 1","vt":"jsonata"}],
- checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSwitchTest(flow, true, 9, done);
- });
-
- it('should be able to use $I in JSONata expression', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"jsonata_exp","v":"$I % 2 = 1",vt:"jsonata"}],checkall:true,repair:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [1, 3], true, undefined, done);
- });
-
- it('should be able to use $N in JSONata expression', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"jsonata_exp","v":"payload >= $N-2",vt:"jsonata"}],checkall:true,repair:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- customFlowSequenceSwitchTest(flow, [0, 1, 2, 3, 4], [3, 4], true, undefined, done);
- });
-
-
- function customFlowSequenceMultiSwitchTest(flow, seq_in, outs, repair, done) {
- helper.load(switchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var port_count = Object.keys(outs).length;
- var sid;
- var ids = new Array(port_count).fill(undefined);
- var counts = new Array(port_count).fill(0);
- var vals = new Array(port_count);
- var recv_count = 0;
- for (var id in outs) {
- if (outs.hasOwnProperty(id)) {
- var out = outs[id];
- vals[out.port] = out.vals;
- recv_count += out.vals.length;
- }
- }
- var count = 0;
- function check_msg(msg, ix, vf) {
- try {
- msg.should.have.property("payload");
- var payload = msg.payload;
- msg.should.have.property("parts");
- vf(payload).should.be.ok();
- var parts = msg.parts;
- var evals = vals[ix];
- parts.should.have.property("id");
- var id = parts.id;
- if (repair) {
- if (ids[ix] === undefined) {
- ids[ix] = id;
- }
- else {
- ids[ix].should.equal(id);
- }
- parts.should.have.property("count", evals.length);
- parts.should.have.property("index", counts[ix]);
- }
- else {
- if (sid === undefined) {
- sid = id;
- }
- else {
- sid.should.equal(id);
- }
- parts.should.have.property("count", seq_in.length);
- parts.should.have.property("index", msg.xindex);
- }
- var index = parts.index;
- var eindex = counts[ix];
- var value = evals[eindex];
- payload.should.equal(value);
- counts[ix]++;
- count++;
- if (count === recv_count) {
- done();
- }
- }
- catch (e) {
- done(e);
- }
- }
- for (var id in outs) {
- if (outs.hasOwnProperty(id)) {
- (function() {
- var node = helper.getNode(id);
- var port = outs[id].port;
- var vf = outs[id].vf;
- node.on("input", function(msg) {
- check_msg(msg, port, vf);
- });
- })();
- }
- }
- for(var i in seq_in) {
- if (seq_in.hasOwnProperty(i)) {
- n1.receive({payload:seq_in[i], xindex:i,
- parts:{index:i, count:seq_in.length, id:222}});
- }
- }
- });
- }
-
- it('should not repair message sequence for each port', function(done) {
- var flow = [{id:"n1",type:"switch",name:"switchNode",property:"payload",
- rules:[{"t":"gt","v":0},{"t":"lt","v":0},{"t":"else"}],
- checkall:true,repair:false,
- outputs:3,wires:[["n2"],["n3"],["n4"]]},
- {id:"n2", type:"helper", wires:[]},
- {id:"n3", type:"helper", wires:[]},
- {id:"n4", type:"helper", wires:[]}
- ];
- var data = [ 1, -2, 2, 0, -1 ];
- var outs = {
- "n2" : { port:0, vals:[1, 2],
- vf:function(x) { return(x > 0); } },
- "n3" : { port:1, vals:[-2, -1],
- vf:function(x) { return(x < 0); } },
- "n4" : { port:2, vals:[0],
- vf:function(x) { return(x == 0); } },
- };
- customFlowSequenceMultiSwitchTest(flow, data, outs, false, done);
- });
-
- it('should repair message sequence for each port', function(done) {
- var flow = [{id:"n1",type:"switch",name:"switchNode",property:"payload",
- rules:[{"t":"gt","v":0},{"t":"lt","v":0},{"t":"else"}],
- checkall:true,repair:true,
- outputs:3,wires:[["n2"],["n3"],["n4"]]},
- {id:"n2", type:"helper", wires:[]}, // >0
- {id:"n3", type:"helper", wires:[]}, // <0
- {id:"n4", type:"helper", wires:[]} // ==0
- ];
- var data = [ 1, -2, 2, 0, -1 ];
- var outs = {
- "n2" : { port:0, vals:[1, 2],
- vf:function(x) { return(x > 0); } },
- "n3" : { port:1, vals:[-2, -1],
- vf:function(x) { return(x < 0); } },
- "n4" : { port:2, vals:[0],
- vf:function(x) { return(x == 0); } },
- };
- customFlowSequenceMultiSwitchTest(flow, data, outs, true, done);
- });
-
- it('should repair message sequence for each port (overlap)', function(done) {
- var flow = [{id:"n1",type:"switch",name:"switchNode",property:"payload",
- rules:[{"t":"gte","v":0},{"t":"lte","v":0},{"t":"else"}],
- checkall:true,repair:true,
- outputs:3,wires:[["n2"],["n3"],["n4"]]},
- {id:"n2", type:"helper", wires:[]}, // >=0
- {id:"n3", type:"helper", wires:[]}, // <=0
- {id:"n4", type:"helper", wires:[]} // none
- ];
- var data = [ 1, -2, 2, 0, -1 ];
- var outs = {
- "n2" : { port:0, vals:[1, 2, 0],
- vf:function(x) { return(x >= 0); } },
- "n3" : { port:1, vals:[-2, 0, -1],
- vf:function(x) { return(x <= 0); } },
- "n4" : { port:2, vals:[],
- vf:function(x) { return(false); } },
- };
- customFlowSequenceMultiSwitchTest(flow, data, outs, true, done);
- });
-
- it('should handle too many pending messages', function(done) {
- var flow = [{id:"n1",type:"switch",name:"switchNode",property:"payload",
- rules:[{"t":"tail","v":2}],
- checkall:true,repair:false,
- outputs:3,wires:[["n2"]]},
- {id:"n2", type:"helper", wires:[]}
- ];
- helper.load(switchNode, flow, function() {
- var n1 = helper.getNode("n1");
- RED.settings.nodeMessageBufferMaxLength = 2;
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "switch";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "switch");
- evt.should.have.property('msg', "switch.errors.too-many");
- done();
- }, 150);
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should handle invalid jsonata expression', function(done) {
-
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"$invalidExpression(payload)",propertyType:"jsonata",rules:[{"t":"btwn","v":"$sqrt(16)","vt":"jsonata","v2":"$sqrt(36)","v2t":"jsonata"}],checkall:true,outputs:1,wires:[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(switchNode, flow, function() {
- var n1 = helper.getNode("switchNode1");
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "switch";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "switchNode1");
- evt.should.have.property('type', "switch");
- done();
- }, 150);
- n1.receive({payload:1});
- });
- });
-
-
- it('should handle empty rule', function(done) {
- var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[],checkall:true,outputs:0,wires:[]}];
- helper.load(switchNode, flow, function() {
- var n1 = helper.getNode("switchNode1");
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "switch";
- });
- if (logEvents.length === 0) {
- done();
- }
- }, 150);
- n1.receive({payload:1});
- });
- });
-});
diff --git a/test/nodes/core/function/15-change_spec.js b/test/nodes/core/function/15-change_spec.js
deleted file mode 100644
index b8d7be03b..000000000
--- a/test/nodes/core/function/15-change_spec.js
+++ /dev/null
@@ -1,1911 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var changeNode = require("nr-test-utils").require("@node-red/nodes/core/function/15-change.js");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context");
-var helper = require("node-red-node-test-helper");
-
-describe('change Node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory0: {
- module: "memory"
- },
- memory1: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function(done) {
- helper.unload().then(function () {
- return Context.clean({allNodes: {}});
- }).then(function () {
- return Context.close();
- }).then(function () {
- helper.stopServer(done);
- });
- });
-
- it('should load node with defaults', function(done) {
- var flow = [{ id: "c1", type: "change", name:"change1" }];
- helper.load(changeNode, flow, function() {
- helper.getNode("c1").should.have.property("name", "change1");
- helper.getNode("c1").should.have.property("rules", [{fromt:'str',pt:'msg',tot:'str',t:undefined,p:''}]);
- done();
- });
- });
- it('should load defaults if set to replace', function(done) {
- var flow = [{ id: "c1", type: "change", name:"change1", action:"replace" }];
- helper.load(changeNode, flow, function() {
- helper.getNode("c1").should.have.property("name", "change1");
- helper.getNode("c1").should.have.property("rules", [ {fromt: 'str', p: '', pt: 'msg', t: 'set', to: '', tot: 'str'} ]);
- done();
- });
- });
- it('should load defaults if set to change', function(done) {
- var flow = [{ id: "c1", type: "change", name:"change1", action:"change" }];
- helper.load(changeNode, flow, function() {
- //console.log(helper.getNode("c1"));
- helper.getNode("c1").should.have.property("name", "change1");
- helper.getNode("c1").should.have.property("rules", [ { from: '', fromRE:/(?:)/g,fromt: 'str', p: '',pt: 'msg', re: undefined, t: 'change', to: '',tot: 'str' } ]);
- done();
- });
- });
- it('should no-op if there are no rules', function(done) {
- var flow = [{"id":"changeNode1","type":"change","rules":[],"action":"","property":"","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.eql(sentMsg);
- done();
- } catch(err) {
- done(err);
- }
- });
- var sentMsg = {payload:"leaveMeAlong"};
- changeNode1.receive(sentMsg);
- });
- });
-
- describe('#set' , function() {
-
- it('sets the value of the message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"payload","from":"","to":"changed","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("changed");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"changeMe"});
- });
- });
-
- it('sets the value of global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t":"set","p":"globalValue","pt":"global","to":"changed","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- changeNode1.context().global.get("globalValue").should.equal("changed");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("globalValue","changeMe");
- changeNode1.receive({payload:""});
- });
- });
-
- it('sets the value of persistable global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t":"set","p":"#:(memory1)::globalValue","pt":"global","to":"changed","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- changeNode1.context().global.get("globalValue", "memory1", function (err, val) {
- val.should.equal("changed");
- done();
- });
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("globalValue","changeMe","memory1", function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('sets the value and type of the message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "set", "p": "payload", "pt": "msg", "to": "12345", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal(12345);
- var t = typeof(msg.payload);
- t.should.equal("number");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"changeMe"});
- });
- });
-
- it('sets the value of an already set multi-level message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"foo.bar","from":"","to":"bar","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.foo.bar.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({foo:{bar:"foo"}});
- });
- });
-
- it('sets the value of an empty multi-level message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"foo.bar","from":"","to":"bar","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.foo.bar.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({});
- });
- });
-
- it('sets the value of a message property to another message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"foo","from":"","to":"msg.fred","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var rule = helper.getNode("changeNode1").rules[0];
- rule.t.should.eql('set');
- rule.tot.should.eql('msg');
- helperNode1.on("input", function(msg) {
- try {
- msg.foo.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({fred:"bar"});
- });
- });
-
- it('sets the value of a multi-level message property to another multi-level message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"foo.bar","from":"","to":"msg.fred.red","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.foo.bar.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({fred:{red:"bar"}});
- });
- });
-
- it('doesn\'t set the value of a message property when the \'to\' message property does not exist', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"foo.bar","from":"","to":"msg.fred.red","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- should.not.exist(msg.foo);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({});
- });
- });
-
- it('overrides the value of a message property when the \'to\' message property does not exist', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"payload","from":"","to":"msg.foo","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- should.not.exist(msg.payload);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello"});
- });
- });
-
- it('sets the message property to null when the \'to\' message property equals null', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"payload","from":"","to":"msg.foo","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- (msg.payload === null).should.be.true();
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello", foo:null});
- });
- });
-
- it('does not set other properties using = inside to property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"payload","from":"","to":"msg.otherProp=10","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- should.not.exist(msg.payload);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"changeMe"});
- });
- });
-
- it('splits dot delimited properties into objects', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"pay.load","from":"","to":"10","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.pay.load.should.equal("10");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({pay:{load:"changeMe"}});
- });
- });
-
- it('changes the value to flow context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"flowValue","tot":"flow"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("Hello World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("flowValue","Hello World!");
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value to persistable flow context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"#:(memory1)::flowValue","tot":"flow"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("Hello World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("flowValue","Hello World!","memory1",function(err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('changes the value to global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"globalValue","tot":"global"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("Hello World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("globalValue","Hello World!");
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value to persistable global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"#:(memory1)::globalValue","tot":"global"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("Hello World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("globalValue","Hello World!","memory1", function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('changes the value to a number', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"123","tot":"num"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql(123);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value to a boolean value', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"true","tot":"bool"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql(true);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value to a js object', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":'{"a":123}',"tot":"json"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql({a:123});
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value to a buffer object', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"[72,101,108,108,111,32,87,111,114,108,100]","tot":"bin"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- var buff = Buffer.from("Hello World");
- msg.payload.should.eql(buff);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:""});
- });
- });
-
- it('sets the value of the message property to the current timestamp', function(done) {
- var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"set","p":"ts","pt":"msg","to":"","tot":"date"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- (Date.now() - msg.ts).should.be.approximately(0,50);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:Date.now()});
- });
- });
-
- describe('env var', function() {
- before(function() {
- process.env.NR_TEST_A = 'foo';
- })
- after(function() {
- delete process.env.NR_TEST_A;
- })
- it('sets the value using env property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","pt":"msg","to":"NR_TEST_A","tot":"env"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("foo");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"123",topic:"ABC"});
- });
- });
-
- it('sets the value using env property from tab', function(done) {
- var flow = [
- {"id":"tab1","type":"tab","env":[
- {"name":"NR_TEST_A", "value":"bar", "type": "str"}
- ]},
- {"id":"changeNode1","type":"change","z":"tab1",rules:[{"t":"set","p":"payload","pt":"msg","to":"NR_TEST_A","tot":"env"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}
- ];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"123",topic:"ABC"});
- });
- });
-
- it('sets the value using env property from group', function(done) {
- var flow = [
- {"id":"group1","type":"group","env":[
- {"name":"NR_TEST_A", "value":"bar", "type": "str"}
- ]},
- {"id":"changeNode1","type":"change","g":"group1",rules:[{"t":"set","p":"payload","pt":"msg","to":"NR_TEST_A","tot":"env"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}
- ];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"123",topic:"ABC"});
- });
- });
-
- it('sets the value using env property from nested group', function(done) {
- var flow = [
- {"id":"group1","type":"group","env":[
- {"name":"NR_TEST_A", "value":"bar", "type": "str"}
- ]},
- {"id":"group2","type":"group","g":"group1","env":[]},
- {"id":"changeNode1","type":"change","g":"group2",rules:[{"t":"set","p":"payload","pt":"msg","to":"NR_TEST_A","tot":"env"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}
- ];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"123",topic:"ABC"});
- });
- });
-
- });
-
- it('changes the value using jsonata', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$length(payload)","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql(12);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World!"});
- });
- });
-
- it('reports invalid jsonata expression', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$invalid(payload)","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- done("Invalid jsonata expression passed message through");
- });
- changeNode1.on("call:error", function(err) {
- // Expect error to be called
- done();
- });
- changeNode1.receive({payload:"Hello World!"});
- });
- });
-
- it('changes the value using flow context with jsonata', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$flowContext(\"foo\")","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"},{"id":"flow","type":"tab"}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- changeNode1.context().flow.set("foo","bar");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World!"});
- });
- });
-
- it('changes the value using global context with jsonata', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$globalContext(\"foo\")","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"},{"id":"flow","type":"tab"}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- changeNode1.context().global.set("foo","bar");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World!"});
- });
- });
-
- it('changes the value using persistable flow context with jsonata', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$flowContext(\"foo\",\"memory1\")","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"},{"id":"flow","type":"tab"}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("foo","bar","memory1",function(err){
- if(err){
- done(err);
- }else{
- changeNode1.context().flow.set("foo","error!");
- changeNode1.receive({payload:"Hello World!"});
- }
- });
- });
- });
- });
-
- it('changes the value using persistable global context with jsonata', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"set","p":"payload","to":"$globalContext(\"foo\",\"memory1\")","tot":"jsonata"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"},{"id":"flow","type":"tab"}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("foo","bar","memory1",function(err){
- if(err){
- done(err);
- }else{
- changeNode1.context().global.set("foo","error!");
- changeNode1.receive({payload:"Hello World!"});
- }
- });
- });
- });
- });
-
- it('sets the value of a message property using a nested property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"lookup[msg.topic]","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal(2);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"",lookup:{a:1,b:2},topic:"b"});
- });
- });
-
- it('sets the value of a nested message property using a message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","name":"","rules":[{"t":"set","p":"lookup[msg.topic]","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.lookup.b.should.equal("newValue");
- done();
- } catch(err) {
- done(err);
- }
- });
- var msg = {
- payload: "newValue",
- lookup:{a:1,b:2},
- topic:"b"
- }
- changeNode1.receive(msg);
- });
- });
-
- it('sets the value of a message property using a nested property in flow context', function(done) {
- var flow = [{"id":"changeNode1","type":"change","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"lookup[msg.topic]","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql(2);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("lookup",{a:1, b:2});
- changeNode1.receive({payload: "", topic: "b"});
- });
- })
-
- it('sets the value of a message property using a nested property in flow context', function(done) {
- var flow = [{"id":"changeNode1","type":"change","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"lookup[msg.topic]","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql(2);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("lookup",{a:1, b:2});
- changeNode1.receive({payload: "", topic: "b"});
- });
- })
-
- it('sets the value of a nested flow context property using a message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","name":"","rules":[{"t":"set","p":"lookup[msg.topic]","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[]}];
-
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.eql("newValue");
- changeNode1.context().flow.get("lookup.b").should.eql("newValue");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("lookup",{a:1, b:2});
- changeNode1.receive({payload: "newValue", topic: "b"});
- });
- })
-
- it('deep copies the property if selected', function(done) {
-
- var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"set","p":"payload","pt":"msg","to":"source","tot":"msg","dc":true}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- // Check payload has been set to a clone of original object
- // - the JSON should match
- JSON.stringify(msg.payload).should.equal(JSON.stringify(originalObject))
- // - but they must be different objects
- msg.payload.should.not.equal(originalObject);
-
- // Modify nested property of original object
- originalObject.a.c = 3;
- // Check that modification hasn't happened on cloned prop
- msg.payload.a.should.not.have.property('c');
-
- done();
- } catch(err) {
- done(err);
- }
- });
- var originalObject = { a: { b: 2 } }
- changeNode1.receive({source:originalObject});
- });
-
- })
- });
- describe('#change', function() {
- it('changes the value of the message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"Hello","to":"Goodbye","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Goodbye World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World!"});
- });
- });
-
- it('changes the value and doesnt change type of the message property for partial match', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "msg", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Change456Me");
- var t = typeof(msg.payload);
- t.should.equal("string");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Change123Me"});
- });
- });
-
- it('changes the value and type of the message property if a complete match', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "msg", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal(456);
- var t = typeof(msg.payload);
- t.should.equal("number");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"123"});
- });
- });
-
- it('changes the value of a multi-level message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"change","property":"foo.bar","from":"Hello","to":"Goodbye","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.foo.bar.should.equal("Goodbye World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({foo:{bar:"Hello World!"}});
- });
- });
-
- it('sends unaltered message if the changed message property does not exist', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"change","property":"foo","from":"Hello","to":"Goodbye","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Hello World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World!"});
- });
- });
-
- it('sends unaltered message if a changed multi-level message property does not exist', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"change","property":"foo.bar","from":"Hello","to":"Goodbye","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Hello World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World!"});
- });
- });
-
- it('changes the value of the message property based on a regex', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"\\d+","to":"NUMBER","reg":true,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Replace all numbers NUMBER and NUMBER");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Replace all numbers 12 and 14"});
- });
- });
-
- it('supports regex groups', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"(Hello)","to":"$1-$1-$1","reg":true,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Hello-Hello-Hello World");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World"});
- });
- });
-
- it('reports invalid regex', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"\\+**+","to":"NUMBER","reg":true,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "change";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', 'changeNode1');
- done();
-
- });
- });
-
- it('supports regex groups - new rule format', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"(Hello)","to":"$1-$1-$1","fromt":"re","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("Hello-Hello-Hello World");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"Hello World"});
- });
- });
-
- it('changes the value - new rule format', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"ABC","to":"123","fromt":"str","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abc123abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"abcABCabc"});
- });
- });
-
- it('changes the value using msg property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"123","fromt":"msg","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abc123abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"abcABCabc",topic:"ABC"});
- });
- });
-
- it('changes the value using flow context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"123","fromt":"flow","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abc123abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("topic","ABC");
- changeNode1.receive({payload:"abcABCabc"});
- });
- });
-
- it('changes the value using persistable flow context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"#:(memory1)::topic","to":"123","fromt":"flow","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abc123abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("topic","ABC","memory1", function (err) {
- changeNode1.receive({payload:"abcABCabc"});
- });
- });
- });
- });
-
- it('changes the value using global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"123","fromt":"global","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abc123abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("topic","ABC");
- changeNode1.receive({payload:"abcABCabc"});
- });
- });
-
- it('changes the value using persistable global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"#:(memory1)::topic","to":"123","fromt":"global","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abc123abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("topic","ABC","memory1",function (err) {
- changeNode1.receive({payload:"abcABCabc"});
- });
- });
- });
- });
-
- it('changes the number using global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"ABC","fromt":"global","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("ABC");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("topic",123);
- changeNode1.receive({payload:123});
- });
- });
-
- it('changes the number using persistable global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"#:(memory1)::topic","to":"ABC","fromt":"global","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("ABC");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("topic",123,"memory1",function (err) {
- changeNode1.receive({payload:123});
- });
- });
- });
- });
-
- it('changes the value using number - string payload', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"123","to":"456","fromt":"num","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("456");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"123"});
- });
- });
-
- it('changes the value using number - number payload', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"123","to":"abc","fromt":"num","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:123});
- });
- });
-
- it('changes the value using boolean - string payload', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"true","to":"xxx","fromt":"bool","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("xxx");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"true"});
- });
- });
-
- it('changes the value using boolean - boolean payload', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"true","to":"xxx","fromt":"bool","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("xxx");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:true});
- });
- });
-
- it('changes the value of the global context', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "global", "from": "Hello", "fromt": "str", "to": "Goodbye", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().global.get("payload").should.equal("Goodbye World!");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("payload","Hello World!");
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value of the persistable global context', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "#:(memory1)::payload", "pt": "global", "from": "Hello", "fromt": "str", "to": "Goodbye", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().global.get("payload","memory1", function (err, val) {
- val.should.equal("Goodbye World!");
- done();
- });
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("payload","Hello World!","memory1",function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('changes the value and doesnt change type of the flow context for partial match', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload").should.equal("Change456Me");
- helperNode1.context().flow.get("payload").should.be.a.String();
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload","Change123Me");
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value and doesnt change type of the persistable flow context for partial match', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "#:(memory1)::payload", "pt": "flow", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload","memory1",function (err, val) {
- val.should.equal("Change456Me");
- val.should.be.a.String();
- done();
- });
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload","Change123Me","memory1",function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('changes the value and type of the flow context if a complete match', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload").should.equal(456);
- helperNode1.context().flow.get("payload").should.be.a.Number();
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload","123");
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value and type of the persistable flow context if a complete match', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "#:(memory1)::payload", "pt": "flow", "from": "123", "fromt": "str", "to": "456", "tot": "num" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload","memory1",function (err, val) {
- val.should.be.a.Number();
- val.should.equal(456);
- done();
- });
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload","123","memory1",function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('changes the value using number - number flow context', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "123", "fromt": "num", "to": "abc", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload").should.equal("abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload",123);
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value using number - number persistable flow context', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "#:(memory1)::payload", "pt": "flow", "from": "123", "fromt": "num", "to": "abc", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload","memory1",function (err, val) {
- val.should.equal("abc");
- done();
- });
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload",123,"memory1",function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('changes the value using boolean - boolean flow context', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "payload", "pt": "flow", "from": "true", "fromt": "bool", "to": "abc", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload").should.equal("abc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload",true);
- changeNode1.receive({payload:""});
- });
- });
-
- it('changes the value using boolean - boolean persistable flow context', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "change", "p": "#:(memory1)::payload", "pt": "flow", "from": "true", "fromt": "bool", "to": "abc", "tot": "str" }],"reg":false,"name":"changeNode","wires":[["helperNode1"]],"z":"flow"},
- {id:"helperNode1", type:"helper", wires:[],"z":"flow"}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- helperNode1.context().flow.get("payload","memory1",function (err, val) {
- val.should.equal("abc");
- done();
- });
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().flow.set("payload",true,"memory1",function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('reports invalid fromValue', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"null","fromt":"msg","to":"abc","tot":"str"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "change";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().ERROR);
- msg.should.have.property('id', 'changeNode1');
- done();
- },25);
- changeNode1.receive({payload:"",null:null});
- });
- });
-
- describe('env var', function() {
- before(function() {
- process.env.NR_TEST_A = 'foo';
- })
- after(function() {
- delete process.env.NR_TEST_A;
- })
- it('changes the value using env property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{"t":"change","p":"payload","from":"topic","to":"NR_TEST_A","fromt":"msg","tot":"env"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("abcfooabc");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"abcABCabc",topic:"ABC"});
- });
- });
- });
-
- });
-
- describe("#delete", function() {
- it('deletes the value of the message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"delete","property":"payload","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.not.have.property('payload');
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"This won't get through!"});
- });
- });
-
- it('deletes the value of global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "delete", "p": "globalValue", "pt": "global"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- changeNode1.context().global.should.not.have.property("globalValue");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("globalValue","Hello World!");
- changeNode1.receive({payload:""});
- });
- });
-
- it('deletes the value of persistable global context property', function(done) {
- var flow = [{"id":"changeNode1","type":"change",rules:[{ "t": "delete", "p": "#:(memory1)::globalValue", "pt": "global"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- changeNode1.context().global.get("globalValue","memory1",function(err,val) {
- should.equal(undefined);
- done();
- });
- } catch(err) {
- done(err);
- }
- });
- changeNode1.context().global.set("globalValue","Hello World!","memory1",function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
-
- it('deletes the value of a multi-level message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"delete","property":"foo.bar","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.not.have.property('foo.bar');
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"This won't get through!", foo:{bar:"This will be deleted!"}});
- });
- });
-
- it('sends unaltered message if the deleted message property does not exist', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"delete","property":"foo","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.not.have.property('foo');
- msg.payload.should.equal('payload');
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"payload"});
- });
- });
-
- it('sends unaltered message if a deleted multi-level message property does not exist', function(done) {
- var flow = [{"id":"changeNode1","type":"change","action":"delete","property":"foo.bar","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.not.have.property('foo.bar');
- msg.payload.should.equal('payload');
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"payload"});
- });
- });
- });
-
- describe("#move", function() {
- it('moves the value of the message property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"topic","pt":"msg","to":"payload","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.not.have.property('topic');
- msg.should.have.property('payload');
- msg.payload.should.equal("You've got to move it move it.");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({topic:"You've got to move it move it.", payload:{foo:"bar"}});
- });
- });
- it('moves the value of a message property object', function(done) {
- var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"topic","pt":"msg","to":"payload","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.not.have.property('topic');
- msg.should.have.property('payload');
- msg.payload.should.have.property('foo');
- msg.payload.foo.should.have.property('bar');
- msg.payload.foo.bar.should.equal(1);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({topic:{foo:{bar:1}}, payload:"String"});
- });
- });
- it('moves the value of a message property object to a sub-property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.foo","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.have.property('foo');
- msg.payload.foo.should.equal("bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:"bar"});
- });
- });
- it('moves the value of a message sub-property object to a property', function(done) {
- var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload.foo","pt":"msg","to":"payload","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.equal("bar");
- (typeof msg.payload).should.equal("string");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({payload:{foo:"bar"}});
- });
- });
- });
-
- describe('- multiple rules', function() {
- it('handles multiple rules', function(done) {
- var flow = [{"id":"changeNode1","type":"change","wires":[["helperNode1"]],
- rules:[
- {t:"set",p:"payload",to:"newValue"},
- {t:"change",p:"changeProperty",from:"this",to:"that"},
- {t:"delete",p:"deleteProperty"}
- ]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("newValue");
- msg.changeProperty.should.equal("change that value");
- should.not.exist(msg.deleteProperty);
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({
- payload:"changeMe",
- changeProperty:"change this value",
- deleteProperty:"delete this value"
- });
- });
- });
-
- it('applies multiple rules in order', function(done) {
- var flow = [{"id":"changeNode1","type":"change","wires":[["helperNode1"]],
- rules:[
- {t:"set",p:"payload",to:"a this (hi)"},
- {t:"change",p:"payload",from:"this",to:"that"},
- {t:"change",p:"payload",from:"\\(.*\\)",to:"[new]",re:true},
- ]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal("a that [new]");
- done();
- } catch(err) {
- done(err);
- }
- });
- changeNode1.receive({
- payload:"changeMe"
- });
- });
- });
-
- it('can access two persistable flow context property', function(done) {
- var flow = [{"id":"changeNode1", "z":"t1", "type":"change",
- "wires":[["helperNode1"]],
- rules:[
- {"t":"set", "p":"val0", "to":"#:(memory0)::val", "tot":"flow"},
- {"t":"set", "p":"val1", "to":"#:(memory1)::val", "tot":"flow"}
- ]},
- {id:"helperNode1", "z":"t1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.have.property("val0", "foo");
- msg.should.have.property("val1", "bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- var flow = changeNode1.context().flow;
- flow.set("val", "foo", "memory0", function (err) {
- flow.set("val", "bar", "memory1", function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
- });
-
- it('can access two persistable global context property', function(done) {
- var flow = [{"id":"changeNode1", "z":"t1", "type":"change",
- "wires":[["helperNode1"]],
- rules:[
- {"t":"set", "p":"val0", "to":"#:(memory0)::val", "tot":"global"},
- {"t":"set", "p":"val1", "to":"#:(memory1)::val", "tot":"global"}
- ]},
- {id:"helperNode1", "z":"t1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.have.property("val0", "foo");
- msg.should.have.property("val1", "bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- var global = changeNode1.context().global;
- global.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
- });
-
- it('can access persistable global & flow context property', function(done) {
- var flow = [{"id":"changeNode1", "z":"t1", "type":"change",
- "wires":[["helperNode1"]],
- rules:[
- {"t":"set", "p":"val0", "to":"#:(memory0)::val", "tot":"flow"},
- {"t":"set", "p":"val1", "to":"#:(memory1)::val", "tot":"global"}
- ]},
- {id:"helperNode1", "z":"t1", type:"helper", wires:[]}];
- helper.load(changeNode, flow, function() {
- initContext(function () {
- var changeNode1 = helper.getNode("changeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.have.property("val0", "foo");
- msg.should.have.property("val1", "bar");
- done();
- } catch(err) {
- done(err);
- }
- });
- var context = changeNode1.context();
- var flow = context.flow;
- var global = context.global;
- flow.set("val", "foo", "memory0", function (err) {
- global.set("val", "bar", "memory1", function (err) {
- changeNode1.receive({payload:""});
- });
- });
- });
- });
- });
-
- });
-});
diff --git a/test/nodes/core/function/16-range_spec.js b/test/nodes/core/function/16-range_spec.js
deleted file mode 100644
index a0dcd0078..000000000
--- a/test/nodes/core/function/16-range_spec.js
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-
-var rangeNode = require("nr-test-utils").require("@node-red/nodes/core/function/16-range.js");
-var helper = require("node-red-node-test-helper");
-
-describe('range Node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- afterEach(function(done) {
- helper.unload();
- helper.stopServer(done);
- });
-
- it('should load some defaults', function(done) {
- var flow = [{"id":"rangeNode1","type":"range","name":"rangeNode"}];
- helper.load(rangeNode, flow, function() {
- var rangeNode1 = helper.getNode("rangeNode1");
- rangeNode1.should.have.property('name', 'rangeNode');
- rangeNode1.should.have.property('round', false);
- done();
- });
- });
-
- /**
- * Run a generic range test
- * @param action - scale/clamp (range limit)/roll (modulo): what action to choose
- * @param minin - map from minimum value
- * @param maxin - map from maximum value
- * @param minout - map to minimum value
- * @param maxout - map to maximum value
- * @param round - whether to round the result to the nearest integer
- * @param aPayload - what payload to send to the range node
- * @param expectedResult - what result we're expecting
- * @param done - the callback to call when test done
- */
- function genericRangeTest(action, minin, maxin, minout, maxout, round, aPayload, expectedResult, done) {
- var flow = [{"id":"rangeNode1","type":"range","minin":minin,"maxin":maxin,"minout":minout,"maxout":maxout,"action":action,"round":round,"name":"rangeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(rangeNode, flow, function() {
- var rangeNode1 = helper.getNode("rangeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.payload.should.equal(expectedResult);
- done();
- } catch(err) {
- done(err);
- }
- });
- rangeNode1.receive({payload:aPayload});
- });
- }
-
- it('ranges numbers up tenfold', function(done) {
- genericRangeTest("scale", 0, 100, 0, 1000, false, 50, 500, done);
- });
-
- it('ranges numbers down such as centimetres to metres', function(done) {
- genericRangeTest("scale", 0, 100, 0, 1, false, 55, 0.55, done);
- });
-
- it('wraps numbers down say for degree/rotation reading 1/2', function(done) {
- genericRangeTest("roll", 0, 10, 0, 360, true, 15, 180, done); // 1/2 around wrap => "one and a half turns"
- });
-
- it('wraps numbers around say for degree/rotation reading 1/3', function(done) {
- genericRangeTest("roll", 0, 10, 0, 360, true, 13.3333, 120, done); // 1/3 around wrap => "one and a third turns"
- });
-
- it('wraps numbers around say for degree/rotation reading 1/4', function(done) {
- genericRangeTest("roll", 0, 10, 0, 360, true, 12.5, 90, done); // 1/4 around wrap => "one and a quarter turns"
- });
-
- it('wraps numbers down say for degree/rotation reading 1/4', function(done) {
- genericRangeTest("roll", 0, 10, 0, 360, true, -12.5, 270, done); // 1/4 backwards wrap => "one and a quarter turns backwards"
- });
-
- it('wraps numbers around say for degree/rotation reading 0', function(done) {
- genericRangeTest("roll", 0, 10, 0, 360, true, -10, 0, done);
- });
-
- it('clamps numbers within a range - over max', function(done) {
- genericRangeTest("clamp", 0, 10, 0, 1000, false, 111, 1000, done);
- });
-
- it('clamps numbers within a range - below min', function(done) {
- genericRangeTest("clamp", 0, 10, 0, 1000, false, -1, 0, done);
- });
-
- it('just passes on msg if payload not present', function(done) {
- var flow = [{"id":"rangeNode1","type":"range","minin":0,"maxin":100,"minout":0,"maxout":100,"action":"scale","round":true,"name":"rangeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(rangeNode, flow, function() {
- var rangeNode1 = helper.getNode("rangeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- msg.should.not.have.property('payload');
- msg.topic.should.equal("pass on");
- done();
- } catch(err) {
- done(err);
- }
- });
- rangeNode1.receive({topic:"pass on"});
- });
- });
-
- it('reports if input is not a number', function(done) {
- var flow = [{"id":"rangeNode1","type":"range","minin":0,"maxin":0,"minout":0,"maxout":0,"action":"scale","round":true,"name":"rangeNode","wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(rangeNode, flow, function() {
- var rangeNode1 = helper.getNode("rangeNode1");
- var helperNode1 = helper.getNode("helperNode1");
- rangeNode1.on("call:log",function(args) {
- var log = args.args[0];
- if (log.indexOf("notnumber") > -1) {
- rangeNode1.log.restore();
- done();
- } else {
- try {
- should.fail(null, null, "Non-number inputs should be reported!");
- } catch (err) {
- rangeNode1.log.restore();
- done(err);
- }
- }
- });
-
- rangeNode1.receive({payload:"NOT A NUMBER"});
- });
- });
-});
diff --git a/test/nodes/core/function/80-template_spec.js b/test/nodes/core/function/80-template_spec.js
deleted file mode 100644
index e944824b3..000000000
--- a/test/nodes/core/function/80-template_spec.js
+++ /dev/null
@@ -1,498 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var templateNode = require("nr-test-utils").require("@node-red/nodes/core/function/80-template.js");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context");
-var helper = require("node-red-node-test-helper");
-
-describe('template node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- beforeEach(function(done) {
- done();
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory0: { // do not use (for excluding effect fallback)
- module: "memory"
- },
- memory1: {
- module: "memory"
- },
- memory2: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function() {
- helper.unload().then(function () {
- return Context.clean({allNodes:{}});
- }).then(function () {
- return Context.close();
- });
- });
-
-
- it('should modify payload using node-configured template', function(done) {
- var flow = [{id:"n1", type:"template", field:"payload", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo');
- msg.should.have.property('template', 'this should be ignored as the node has its own template {{payload}}');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo",topic: "bar", template: "this should be ignored as the node has its own template {{payload}}"});
- });
- });
-
- it('should modify the configured property using msg.template', function(done) {
- var flow = [{id:"n1", type:"template", field:"randomProperty", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- msg.should.have.property('template', 'payload={{payload}}');
- msg.should.have.property('randomProperty', 'payload=foo');
- done();
- });
- n1.receive({payload:"foo", topic: "bar", template: "payload={{payload}}"});
- });
- });
-
- it('should be able to overwrite msg.template using the template from msg.template', function(done) {
- var flow = [{id:"n1", type:"template", field:"payload", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'topic=bar');
- msg.should.have.property('template', 'topic={{topic}}');
- done();
- });
- n1.receive({payload:"foo", topic: "bar", template: "topic={{topic}}"});
- });
- });
-
- it('should modify payload from msg.template', function(done) {
- var flow = [{id:"n1", type:"template", field:"payload", template:"",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var received = [];
- n2.on("input", function(msg) {
- try {
- received.push(msg);
- if (received.length === 3) {
- received[0].should.have.property('topic', 'bar');
- received[0].should.have.property('payload', 'topic=bar');
- received[0].should.have.property('template', 'topic={{topic}}');
-
- received[1].should.have.property('topic', 'another bar');
- received[1].should.have.property('payload', 'topic=another bar');
- received[1].should.have.property('template', 'topic={{topic}}');
-
- received[2].should.have.property('topic', 'bar');
- received[2].should.have.property('payload', 'payload=foo');
- received[2].should.have.property('template', 'payload={{payload}}');
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", topic: "bar", template: "topic={{topic}}"});
- n1.receive({payload:"foo", topic: "another bar", template: "topic={{topic}}"});
- n1.receive({payload:"foo", topic: "bar", template: "payload={{payload}}"});
- });
- });
-
- it('should modify payload from flow context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{flow.value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().flow.set("value","foo");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should modify payload from persistable flow context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{flow[memory1].value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo');
- done();
- });
- n1.context().flow.set("value","foo","memory1",function (err) {
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
- });
-
- it('should handle nested context tags - property not set', function(done) {
- // This comes from the Coursera Node-RED course and is a good example of
- // multiple conditional tags
- var template = `{{#flow.time}}time={{flow.time}}{{/flow.time}}{{^flow.time}}!time{{/flow.time}}{{#flow.random}}random={{flow.random}}randomtime={{flow.randomtime}}{{/flow.random}}{{^flow.random}}!random{{/flow.random}}`;
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:template,wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', '!time!random');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- })
- it('should handle nested context tags - property set', function(done) {
- // This comes from the Coursera Node-RED course and is a good example of
- // multiple conditional tags
- var template = `{{#flow.time}}time={{flow.time}}{{/flow.time}}{{^flow.time}}!time{{/flow.time}}{{#flow.random}}random={{flow.random}}randomtime={{flow.randomtime}}{{/flow.random}}{{^flow.random}}!random{{/flow.random}}`;
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:template,wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'time=123random=456randomtime=789');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.context().flow.set(["time","random","randomtime"],["123","456","789"],function (err) {
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
- })
-
- it('should modify payload from two persistable flow context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{flow[memory1].value}}/{{flow[memory2].value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo/bar');
- done();
- });
- n1.context().flow.set("value","foo","memory1",function (err) {
- n1.context().flow.set("value","bar","memory2",function (err) {
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
- });
- });
-
- it('should modify payload from global context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{global.value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context().global.set("value","foo");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should modify payload from persistable global context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{global[memory1].value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo');
- done();
- });
- n1.context().global.set("value","foo","memory1", function (err) {
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
- });
-
- it('should modify payload from two persistable global context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{global[memory1].value}}/{{global[memory2].value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo/bar');
- done();
- });
- n1.context().global.set("value","foo","memory1", function (err) {
- n1.context().global.set("value","bar","memory2", function (err) {
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
- });
- });
-
- it('should modify payload from persistable flow & global context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{flow[memory1].value}}/{{global[memory1].value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo/bar');
- done();
- });
- n1.context().flow.set("value","foo","memory1", function (err) {
- n1.context().global.set("value","bar","memory1", function (err) {
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
- });
- });
-
- it('should handle missing node context', function(done) {
- // this is artificial test because in flow there is missing z property (probably never happen in real usage)
- var flow = [{id:"n1",type:"template", field:"payload", template:"payload={{flow.value}},{{global.value}}",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=,');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should handle escape characters in Mustache format and JSON output mode', function(done) {
- var flow = [{id:"n1", type:"template", field:"payload", syntax:"mustache", template:"{\"data\":\"{{payload}}\"}", output:"json", wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.payload.should.have.property('data', 'line\t1\nline\\2\r\nline\b3\f');
- done();
- });
- n1.receive({payload:"line\t1\nline\\2\r\nline\b3\f"});
- });
- });
-
- it('should modify payload in plain text mode', function(done) {
- var flow = [{id:"n1", type:"template", field:"payload", syntax:"plain", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload={{payload}}');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should modify flow context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", fieldType:"flow", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- // mesage is intact
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- // result is in flow context
- n2.context().flow.get("payload").should.equal("payload=foo");
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should modify persistable flow context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"#:(memory1)::payload", fieldType:"flow", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- // mesage is intact
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- // result is in flow context
- n2.context().flow.get("payload", "memory1", function (err, val) {
- val.should.equal("payload=foo");
- done();
- });
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should modify global context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"payload", fieldType:"global", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- // mesage is intact
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- // result is in global context
- n2.context().global.get("payload").should.equal("payload=foo");
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should modify persistable global context', function(done) {
- var flow = [{id:"n1",z:"t1", type:"template", field:"#:(memory1)::payload", fieldType:"global", template:"payload={{payload}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
- helper.load(templateNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- // mesage is intact
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'foo');
- // result is in global context
- n2.context().global.get("payload", "memory1", function (err, val) {
- val.should.equal("payload=foo");
- done();
- });
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
- });
-
- it('should handle if the field isn\'t set', function(done) {
- var flow = [{id:"n1", type:"template", template: "payload={{payload}}",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload', 'payload=foo');
- done();
- });
- n1.receive({payload:"foo",topic: "bar"});
- });
- });
-
- it('should handle deeper objects', function(done) {
- var flow = [{id:"n1", type:"template", field: "topic.foo.bar", template: "payload={{payload.doh.rei.me}}",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic');
- msg.topic.should.have.property('foo');
- msg.topic.foo.should.have.a.property('bar', 'payload=foo');
- done();
- });
- n1.receive({payload:{doh:{rei:{me:"foo"}}}});
- });
- });
-
- it('should handle block contexts objects', function(done) {
- var flow = [{id:"n1", type:"template", template: "A{{#payload.A}}{{payload.A}}{{.}}{{/payload.A}}B",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload','AabcabcB');
- done();
- });
- n1.receive({payload:{A:"abc"}});
- });
- });
-
- it('should raise error if passed bad template', function(done) {
- var flow = [{id:"n1", type:"template", field: "payload", template: "payload={{payload",wires:[["n2"]]},{id:"n2",type:"helper"}];
- helper.load(templateNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "template";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("Unclosed tag at ");
- done();
- },25);
- n1.receive({payload:"foo"});
- });
- });
-
-});
diff --git a/test/nodes/core/function/89-delay_spec.js b/test/nodes/core/function/89-delay_spec.js
deleted file mode 100644
index 17958b95b..000000000
--- a/test/nodes/core/function/89-delay_spec.js
+++ /dev/null
@@ -1,1004 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-
-var delayNode = require("nr-test-utils").require("@node-red/nodes/core/function/89-delay.js");
-var helper = require("node-red-node-test-helper");
-var RED = require("nr-test-utils").require("node-red/lib/red");
-
-var GRACE_PERCENTAGE=10;
-
-var nanosToSeconds = 1000000000;
-var millisToSeconds = 1000;
-
-var secondsToMinutes = 60;
-var secondsToHours = 3600;
-var secondsToDays = 86400;
-
-describe('delay Node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- afterEach(function(done) {
- RED.settings.nodeMessageBufferMaxLength = 0;
- helper.unload();
- helper.stopServer(done);
- });
-
- it('should be loaded', function(done) {
- var flow = [{"id":"delayNode1","type":"delay", "nbRateUnits":"1", "name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"day","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- delayNode1.should.have.property('name', 'delayNode');
- delayNode1.should.have.property('rate', 86400000);
- done();
- });
- });
-
- it('should be able to set rate to hour', function(done) {
- var flow = [{"id":"delayNode1","type":"delay", "nbRateUnits":"1", "name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"hour","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- delayNode1.should.have.property('name', 'delayNode');
- delayNode1.should.have.property('rate', 3600000);
- done();
- });
- });
-
- it('should be able to set rate to minute', function(done) {
- var flow = [{"id":"delayNode1","type":"delay", "nbRateUnits":"1", "name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- delayNode1.should.have.property('name', 'delayNode');
- delayNode1.should.have.property('rate', 60000);
- done();
- });
- });
-
- var TimeUnitEnum = {
- MILLIS : "milliseconds",
- SECONDS : "seconds",
- MINUTES : "minutes",
- HOURS : "hours",
- DAYS : "days"
- }
-
- /**
- * Tells whether two numeric values are close enough to each other
- * @param actualValue - the value we're testing
- * @param expectedValue - the value we're matching the test value against
- * @param tolerancePercent - the percentage of tolerated deviation (0 means equals)
- */
- function closeEnough(actualValue, expectedValue, tolerancePercent) {
- var toReturn;
- var toleranceFraction = expectedValue * (tolerancePercent/100);
- var minExpected = expectedValue - toleranceFraction;
- var maxExpected = expectedValue + toleranceFraction;
-
- if (actualValue >= minExpected && actualValue <= maxExpected) {
- toReturn = true;
- } else {
- toReturn = false;
- }
- return toReturn;
- }
-
- /**
- * Runs a delay test
- * @param aTimeout - the timeout quantity
- * @param aTimeoutUnit - the unit of the timeout: milliseconds, seconds, minutes, hours, days
- */
- function genericDelayTest(aTimeout, aTimeoutUnit, done) {
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":aTimeout,"timeoutUnits":aTimeoutUnit,"rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- var endTime = process.hrtime(startTime);
- var runtimeNanos = ( (endTime[0] * nanosToSeconds) + endTime[1] );
- var runtimeSeconds = runtimeNanos / nanosToSeconds;
- var aTimeoutUnifiedToSeconds;
-
- // calculating the timeout in seconds
- if (aTimeoutUnit == TimeUnitEnum.MILLIS) {
- aTimeoutUnifiedToSeconds = aTimeout / millisToSeconds;
- } else if (aTimeoutUnit == TimeUnitEnum.SECONDS) {
- aTimeoutUnifiedToSeconds = aTimeout;
- } else if (aTimeoutUnit == TimeUnitEnum.MINUTES) {
- aTimeoutUnifiedToSeconds = aTimeout * secondsToMinutes;
- } else if (aTimeoutUnit == TimeUnitEnum.HOURS) {
- aTimeoutUnifiedToSeconds = aTimeout * secondsToHours;
- } else if (aTimeoutUnit == TimeUnitEnum.DAYS) {
- aTimeoutUnifiedToSeconds = aTimeout * secondsToDays;
- }
-
- if (closeEnough(runtimeSeconds, aTimeoutUnifiedToSeconds, GRACE_PERCENTAGE)) {
- done();
- } else {
- try {
- should.fail(null, null, "Delayed runtime seconds " + runtimeSeconds + " was not close enough to exlected timeout seconds: " + aTimeoutUnifiedToSeconds);
- } catch (err) {
- done(err);
- }
- }
- } catch(err) {
- done(err);
- }
- });
- var startTime = process.hrtime();
- delayNode1.receive({payload:"delayMe"});
- });
- }
-
- /**
- * We send a message, take a timestamp then when the message is received by the helper node, we take another timestamp.
- * Then check if the message has been delayed by the expected amount.
- */
-
- it('delays the message in seconds', function(done) {
- genericDelayTest(0.5, "seconds", done);
- });
-
- it('delays the message in milliseconds', function(done) {
- genericDelayTest(500, "milliseconds", done);
- });
-
- it('delays the message in minutes', function(done) { // this is also 0.5 seconds
- genericDelayTest(0.00833, "minutes", done);
- });
-
- it('delays the message in hours', function(done) { // this is also 0.5 seconds
- genericDelayTest(0.0001388, "hours", done);
- });
-
- it('delays the message in days', function(done) { // this is also 0.5 seconds
- genericDelayTest(0.000005787, "days", done);
- });
-
- /**
- * Runs a rate limit test - only testing seconds!
- * @param aLimit - the message limit count
- * @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
- * @param runtimeInMillis - when to terminate run and count messages received
- */
- function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, done) {
- var flow = [{"id":"delayNode1","type":"delay","nbRateUnits":nbUnit,"name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var receivedMessagesStack = [];
- var rate = 1000 / aLimit * nbUnit;
-
- var receiveTimestamp;
-
- helperNode1.on("input", function(msg) {
- if (receiveTimestamp) {
- var elapse = process.hrtime(receiveTimestamp);
- var receiveInterval = (elapse[0] * 1000) + ((elapse[1] / nanosToSeconds) * 1000);
- receiveInterval.should.be.above(rate * 0.9);
- }
- receiveTimestamp = process.hrtime();
- receivedMessagesStack.push(msg);
- });
-
- var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
-
- var i = 0;
- for (; i < possibleMaxMessageCount + 1; i++) {
- delayNode1.receive({ payload: i, rate: rateValue });
- }
-
- setTimeout(function() {
- try {
- receivedMessagesStack.length.should.be.lessThan(possibleMaxMessageCount);
- for (var j = 0; j < receivedMessagesStack.length; j++) {
- if (receivedMessagesStack[j].payload === j) {
- if (j === (receivedMessagesStack.length -1)) { // last message, all matched so far
- done();
- }
- } else {
- should.fail(null, null, "Received messages were not received in order. Message was " + receivedMessagesStack[i].payload + " on count " + i);
- }
- }
- } catch (err) {
- done(err);
- }
- }, runtimeInMillis);
- });
- }
-
- it('limits the message rate to 1 per second', function(done) {
- genericRateLimitSECONDSTest(1, 1, 1500, null, done);
- });
-
- it('limits the message rate to 1 per 2 seconds', function(done) {
- this.timeout(6000);
- genericRateLimitSECONDSTest(1, 2, 3000, null, done);
- });
-
- it('limits the message rate to 2 per seconds, 2 seconds', function(done) {
- this.timeout(6000);
- genericRateLimitSECONDSTest(2, 1, 2100, null, done);
- });
-
- it('limits the message rate using msg.rate', function (done) {
- RED.settings.nodeMessageBufferMaxLength = 3;
- genericRateLimitSECONDSTest(1, 1, 1500, 2000, done);
- });
-
- /**
- * Runs a rate limit test with drop support - only testing seconds!
- * @param aLimit - the message limit count
- * @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
- * @param runtimeInMillis - when to terminate run and count messages received
- */
- function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, sendIntermediate, done) {
- if (!done) {
- done = sendIntermediate;
- sendIntermediate = false;
- }
- var outputs = 1;
- if (sendIntermediate) {
- outputs = 2;
- }
- var flow = [
- {"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"nbRateUnits":nbUnit,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,outputs:outputs,"wires":[["helperNode1"],["helperNode2"]]},
- {id:"helperNode1", type:"helper", wires:[]},
- {id:"helperNode2", type:"helper", wires:[]}
- ]
-
- ;
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var helperNode2 = helper.getNode("helperNode2");
- var receivedMessagesStack = [];
- var receivedIntermediateMessagesStack = [];
-
- // Add a small grace to the calculated delay
- var rate = 1000/aLimit + 10;
-
- var receiveTimestamp;
-
- helperNode1.on("input", function(msg) {
- if (receiveTimestamp) {
- var elapse = process.hrtime(receiveTimestamp);
- var receiveInterval = (elapse[0] * 1000) + ((elapse[1] / nanosToSeconds) * 1000);
- receiveInterval.should.be.above(rate * 0.9);
- }
- receiveTimestamp = process.hrtime();
- receivedMessagesStack.push(msg);
- });
- helperNode2.on("input", function(msg) {
- receivedIntermediateMessagesStack.push(msg);
- });
-
- var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
-
- var i = 0;
- delayNode1.receive({ payload: i, rate: rateValue });
- i++;
- for (; i < possibleMaxMessageCount + 1; i++) {
- setTimeout(function() {
- delayNode1.receive({payload:i});
- }, 2 * ((rate * i) / possibleMaxMessageCount) );
- }
-
- //we need to send a message delayed so that it doesn't get dropped
- setTimeout(function() {
- delayNode1.receive({payload:++i});
- }, runtimeInMillis - 300); // should give enough time to squeeze another message in
-
- setTimeout(function() {
- try {
- receivedMessagesStack.length.should.be.lessThan(possibleMaxMessageCount + 1);
- receivedMessagesStack.length.should.be.greaterThan(2); // ensure that we receive more than 1st and last message
- receivedMessagesStack[0].payload.should.be.exactly(0); // means we received the last message injected just before test termination
- var foundAtLeastOneDrop = false;
- for (var i = 0; i < receivedMessagesStack.length; i++) {
- if (i > 0) {
- if (receivedMessagesStack[i].payload - receivedMessagesStack[i - 1].payload > 1) {
- foundAtLeastOneDrop = true;
- }
- }
- }
- foundAtLeastOneDrop.should.be.true();
- if (sendIntermediate) {
- receivedIntermediateMessagesStack.length.should.be.greaterThan(0);
- } else {
- receivedIntermediateMessagesStack.length.should.be.exactly(0);
- }
- done();
- } catch (err) {
- done(err);
- }
- }, runtimeInMillis);
- });
- }
-
- it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) {
- this.timeout(6000);
- dropRateLimitSECONDSTest(1, 1, 4000, null, done);
- });
-
- it('limits the message rate to 1 per 2 seconds, 4 seconds, with drop', function(done) {
- this.timeout(6000);
- dropRateLimitSECONDSTest(1, 2, 4500, null, done);
- });
-
- it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) {
- this.timeout(6000);
- dropRateLimitSECONDSTest(2, 1, 5000, null, done);
- });
-
- it('limits the message rate to 2 per second, 5 seconds, with drop, 2nd output', function(done) {
- this.timeout(6000);
- dropRateLimitSECONDSTest(2, 1, 5000, null, true, done);
- });
-
- it('limits the message rate with drop using msg.rate', function (done) {
- this.timeout(6000);
- RED.settings.nodeMessageBufferMaxLength = 3;
- dropRateLimitSECONDSTest(2, 1, 5000, 1000, done);
- });
-
- /**
- * Returns true if the actualTimeout is gracefully in between the timeoutFrom and timeoutTo
- * values. Gracefully means that inBetween could actually mean smaller/greater values
- * than the timeout range so long as it's within an actual grace percentage.
- * @param timeoutFrom - The expected timeout range (low number)
- * @param timeoutTo - The expected timeout range (high number)
- * @param actualTimeout - The actual measured timeout value of test
- * @param allowedGracePercent - The percentage of grace allowed
- */
- function inBetweenDelays(timeoutFrom, timeoutTo, actualTimeout, allowedGracePercent) {
- if (closeEnough(actualTimeout, timeoutFrom, allowedGracePercent)) {
- return true;
- } else if (closeEnough(actualTimeout, timeoutTo, allowedGracePercent)) {
- return true;
- } else if (timeoutFrom < actualTimeout && timeoutTo > actualTimeout) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Runs a VARIABLE DELAY test, checks if the delay is in between the given timeout values
- * @param aTimeoutFrom - the timeout quantity which is the minimal acceptable wait period
- * @param aTimeoutTo - the timeout quantity which is the maximum acceptable wait period
- * @param aTimeoutUnit - the unit of the timeout: milliseconds, seconds, minutes, hours, days
- * @param delay - the variable delay: milliseconds
- */
- function variableDelayTest(aTimeoutFrom, aTimeoutTo, aTimeoutUnit, delay, done) {
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delayv","timeout":0.5,"timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":aTimeoutFrom,"randomLast":aTimeoutTo,"randomUnits":aTimeoutUnit,"drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- var endTime = process.hrtime(startTime);
- var runtimeNanos = ( (endTime[0] * nanosToSeconds) + endTime[1] );
- var runtimeSeconds = runtimeNanos / nanosToSeconds;
- var aTimeoutFromUnifiedToSeconds;
- var aTimeoutToUnifiedToSeconds;
-
- // calculating the timeout in seconds
- if (aTimeoutUnit == TimeUnitEnum.MILLIS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom / millisToSeconds;
- aTimeoutToUnifiedToSeconds = aTimeoutTo / millisToSeconds;
- } else if (aTimeoutUnit == TimeUnitEnum.SECONDS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom;
- aTimeoutToUnifiedToSeconds = aTimeoutTo;
- } else if (aTimeoutUnit == TimeUnitEnum.MINUTES) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToMinutes;
- aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToMinutes;
- } else if (aTimeoutUnit == TimeUnitEnum.HOURS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToHours;
- aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToHours;
- } else if (aTimeoutUnit == TimeUnitEnum.DAYS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToDays;
- aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToDays;
- }
-
- if (inBetweenDelays(aTimeoutFromUnifiedToSeconds, aTimeoutToUnifiedToSeconds, runtimeSeconds, GRACE_PERCENTAGE)) {
- done();
- } else {
- try {
- should.fail(null, null, "Delayed runtime seconds " + runtimeSeconds + " was not \"in between enough\" enough to expected values of: " + aTimeoutFromUnifiedToSeconds + " and " + aTimeoutToUnifiedToSeconds);
- } catch (err) {
- done(err);
- }
- }
- } catch(err) {
- done(err);
- }
- });
- var startTime = process.hrtime();
- delayNode1.receive({payload:"delayMe", delay:delay});
- });
- }
-
- it('variable delay set by msg.delay the message in milliseconds', function(done) {
- variableDelayTest("200", "300", "milliseconds", 250, done);
- });
-
- it('variable delay is the default if msg.delay not specified', function(done) {
- variableDelayTest("450", "550", "milliseconds", null, done);
- });
-
- it('variable delay is zero if msg.delay is zero', function(done) {
- variableDelayTest("0", "20", "milliseconds", 0, done);
- });
-
- it('variable delay is zero if msg.delay is negative', function(done) {
- variableDelayTest("0", "20", "milliseconds", -250, done);
- });
-
- /**
- * Runs a RANDOM DELAY test, checks if the delay is in between the given timeout values
- * @param aTimeoutFrom - the timeout quantity which is the minimal acceptable wait period
- * @param aTimeoutTo - the timeout quantity which is the maximum acceptable wait period
- * @param aTimeoutUnit - the unit of the timeout: milliseconds, seconds, minutes, hours, days
- */
- function randomDelayTest(aTimeoutFrom, aTimeoutTo, aTimeoutUnit, done) {
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"random","timeout":5,"timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":aTimeoutFrom,"randomLast":aTimeoutTo,"randomUnits":aTimeoutUnit,"drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- helperNode1.on("input", function(msg) {
- try {
- var endTime = process.hrtime(startTime);
- var runtimeNanos = ( (endTime[0] * nanosToSeconds) + endTime[1] );
- var runtimeSeconds = runtimeNanos / nanosToSeconds;
- var aTimeoutFromUnifiedToSeconds;
- var aTimeoutToUnifiedToSeconds;
-
- // calculating the timeout in seconds
- if (aTimeoutUnit == TimeUnitEnum.MILLIS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom / millisToSeconds;
- aTimeoutToUnifiedToSeconds = aTimeoutTo / millisToSeconds;
- } else if (aTimeoutUnit == TimeUnitEnum.SECONDS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom;
- aTimeoutToUnifiedToSeconds = aTimeoutTo;
- } else if (aTimeoutUnit == TimeUnitEnum.MINUTES) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToMinutes;
- aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToMinutes;
- } else if (aTimeoutUnit == TimeUnitEnum.HOURS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToHours;
- aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToHours;
- } else if (aTimeoutUnit == TimeUnitEnum.DAYS) {
- aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToDays;
- aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToDays;
- }
-
- if (inBetweenDelays(aTimeoutFromUnifiedToSeconds, aTimeoutToUnifiedToSeconds, runtimeSeconds, GRACE_PERCENTAGE)) {
- done();
- } else {
- try {
- should.fail(null, null, "Delayed runtime seconds " + runtimeSeconds + " was not \"in between enough\" enough to expected values of: " + aTimeoutFromUnifiedToSeconds + " and " + aTimeoutToUnifiedToSeconds);
- } catch (err) {
- done(err);
- }
- }
- } catch(err) {
- done(err);
- }
- });
- var startTime = process.hrtime();
- delayNode1.receive({payload:"delayMe"});
- });
- }
-
- it('randomly delays the message in seconds', function(done) {
- randomDelayTest(0.4, 0.8, "seconds", done);
- });
-
- it('randomly delays the message in milliseconds', function(done) {
- randomDelayTest("400", "800", "milliseconds", done);
- });
-
- it('randomly delays the message in minutes', function(done) {
- randomDelayTest(0.0066, 0.0133, "minutes", done);
- });
-
- it('delays the message in hours', function(done) {
- randomDelayTest(0.000111111, 0.000222222, "hours", done);
- });
-
- it('delays the message in days', function(done) {
- randomDelayTest(0.0000046296, 0.0000092593, "days", done);
- });
-
- it('handles delay queue', function(done) {
- this.timeout(2000);
- var flow = [{id:"delayNode1", type :"delay","name":"delayNode","nbRateUnits":"1","pauseType":"queue","timeout":1,"timeoutUnits":"seconds","rate":4,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "_none_") {
- msg.payload.should.equal(2);
- (Date.now() - t).should.be.approximately(500,200);
- }
- else if (msg.topic === "A") {
- msg.payload.should.equal(4);
- (Date.now() - t).should.be.approximately(750,200);
- }
- else {
- msg.topic.should.equal("B");
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(1000,200);
- done();
- }
- } catch(e) {
- done(e);
- }
- });
- setTimeout(function() {
- // send test messages
- delayNode1.receive({payload:1}); // send something with blank topic
- delayNode1.receive({payload:1,topic:"A"}); // and something with a fixed topic
- delayNode1.receive({payload:1,topic:"B"}); // and something else with a fixed topic (3rd tick)
- delayNode1.receive({payload:2,topic:"A"}); // these should replace them in queue
- delayNode1.receive({payload:3,topic:"A"}); // ditto
- delayNode1.receive({payload:2}); // so only this should get out on first tick
- delayNode1.receive({payload:4,topic:"A"}); // and this one on second tick
- }, 275); // wait one tick beofre starting.. (to test no messages in queue path.)
- });
- });
-
- it('handles timed queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"timed","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "_none_") {
- msg.payload.should.equal(2);
- (Date.now() - t).should.be.approximately(500,200);
- }
- else if (msg.topic === "A") {
- msg.payload.should.equal(4);
- (Date.now() - t).should.be.approximately(500,200);
- }
- else {
- msg.topic.should.equal("B");
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(500,200);
- done();
- }
- } catch(e) {
- done(e);
- }
- });
-
- // send test messages
- delayNode1.receive({payload:1}); // send something with blank topic
- delayNode1.receive({payload:1,topic:"A"}); // and something with a fixed topic
- delayNode1.receive({payload:1,topic:"B"}); // and something else with a fixed topic
- delayNode1.receive({payload:2,topic:"A"}); // these should replace them in queue
- delayNode1.receive({payload:3,topic:"A"}); // ditto
- delayNode1.receive({payload:2}); // so all should go on first tick
- delayNode1.receive({payload:4,topic:"A"}); // and nothing on second
- });
- });
-
- it('can flush delay queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- var c = 0;
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "foo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(0,100);
- c = c + 1;
- }
- else {
- if (msg.topic === "bar") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(0,100);
- c = c + 1;
- }
- }
- if (c === 5) { done(); }
- } catch(e) {
- done(e);
- }
- });
-
- // send test messages
- delayNode1.receive({payload:1,topic:"foo"}); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({flush:true}); }); // reset the queue
- });
- });
-
- it('can part flush delay queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- var c = 0;
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "foo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(0,100);
- c = c + 1;
- }
- else if (msg.topic === "bar") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(200,100);
- c = c + 1;
- }
- else if (msg.topic === "boo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(400,100);
- c = c + 1;
- }
- if (c === 5) { done(); }
- } catch(e) {
- done(e);
- }
- });
-
- // send test messages
- delayNode1.receive({payload:1,topic:"foo"});
- setImmediate( function() { delayNode1.receive({payload:1,topic:"foo"}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"boo"}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"boo"}); } );
- setImmediate( function() { delayNode1.receive({flush:2}); });
- setTimeout( function() { delayNode1.receive({flush:1}); }, 200);
- setTimeout( function() { delayNode1.receive({flush:4}); }, 400);
- });
- });
-
- it('can reset delay queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- var c = 0;
- helperNode1.on("input", function(msg) {
- c = c + 1;
- });
-
- setTimeout( function() {
- if (c === 0) { done(); }
- }, 700);
-
- // send test messages
- delayNode1.receive({payload:1,topic:"foo"}); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({reset:true}); }); // reset the queue
- });
- });
-
- it('can flush rate limit queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- var c = 0;
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "foo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(0,100);
- c = c + 1;
- }
- else {
- if (msg.topic === "bar") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(0,100);
- c = c + 1;
- }
- }
- if (c === 5) { done(); }
- } catch(e) {
- done(e);
- }
- });
-
- // send test messages
- delayNode1.receive({payload:1,topic:"foo"}); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({flush:true}); }); // reset the queue
- });
- });
-
- it('can part flush rate limit queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- var c = 0;
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "foo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(0,100);
- c = c + 1;
- }
- else if (msg.topic === "bar") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(200,100);
- c = c + 1;
- }
- else if (msg.topic === "boo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(400,100);
- c = c + 1;
- }
- if (c === 5) { done(); }
- } catch(e) {
- done(e);
- }
- });
-
- // send test messages
- delayNode1.receive({payload:1,topic:"foo"});
- setImmediate( function() { delayNode1.receive({payload:1,topic:"foo"}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"foo"}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"boo"}); } );
- setImmediate( function() { delayNode1.receive({flush:2}); });
- setTimeout( function() { delayNode1.receive({flush:1}); }, 200);
- setTimeout( function() { delayNode1.receive({flush:4}); }, 400);
- });
- });
-
- it('can part push to front of rate limit queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":1,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- var c = 0;
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "aoo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(2,50);
- c = c + 1;
- }
- else if (msg.topic === "eoo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(4,50);
- c = c + 1;
- }
- else if (msg.topic === "coo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(202,50);
- c = c + 1;
- }
- else if (msg.topic === "boo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(406,50);
- c = c + 1;
- }
- else if (msg.topic === "doo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(4,50);
- c = c + 1;
- }
- if (c === 5) { done(); }
- } catch(e) {
- done(e);
- }
- });
-
- // send test messages
- delayNode1.receive({payload:1,topic:"aoo"});
- setImmediate( function() { delayNode1.receive({payload:1,topic:"boo"}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"coo",toFront:true}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"doo",toFront:true,flush:1}); } );
- setImmediate( function() { delayNode1.receive({payload:1,topic:"eoo",toFront:true}); } );
- setImmediate( function() { delayNode1.receive({flush:1}); });
- setTimeout( function() { delayNode1.receive({flush:1}); }, 200);
- setTimeout( function() { delayNode1.receive({flush:4}); }, 400);
- });
- });
-
- it('can reset rate limit queue', function(done) {
- this.timeout(2000);
- var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
- {id:"helperNode1", type:"helper", wires:[]}];
- helper.load(delayNode, flow, function() {
- var delayNode1 = helper.getNode("delayNode1");
- var helperNode1 = helper.getNode("helperNode1");
- var t = Date.now();
- var c = 0;
- helperNode1.on("input", function(msg) {
- msg.should.have.a.property('payload');
- msg.should.have.a.property('topic');
- try {
- if (msg.topic === "foo") {
- msg.payload.should.equal(1);
- (Date.now() - t).should.be.approximately(0,100);
- c = c + 1;
- }
- } catch(e) {
- done(e);
- }
- });
-
- setTimeout( function() {
- if (c === 1) { done(); }
- }, 700);
-
- // send test messages
- delayNode1.receive({payload:1,topic:"foo"}); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({payload:1,topic:"bar"}); } ); // send something with blank topic
- setImmediate( function() { delayNode1.receive({reset:true}); }); // reset the queue
- });
- });
-
- /* Messaging API support */
- function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const flow = [{id:"delayNode1",type:"delay",name:"delayNode", pauseType:pauseType, timeout:"1", timeoutUnits: "seconds",
- rate: "1", nbRateUnits: "1", rateUnits: "second", randomFirst:"950", randomLast:"1050",randomUnits:"milliseconds",
- drop: drop, wires: [[]]},
- {id:"completeNode1",type:"complete",scope: ["delayNode1"],uncaught:false,wires:[["helperNode1"]]},
- {id:"helperNode1",type:"helper", wires:[[]]}];
- const numMsgs = msgAndTimings.length;
- helper.load([delayNode, completeNode], flow, function () {
- const delayNode1 = helper.getNode("delayNode1");
- const helperNode1 = helper.getNode("helperNode1");
- const t = Date.now();
- let c = 0;
- helperNode1.on("input", function (msg) {
- msg.should.have.a.property('payload', msgAndTimings[c].msg.payload);
- (Date.now() - t).should.be.approximately(msgAndTimings[c].avr, msgAndTimings[c].var);
- c += 1;
- if ( c === numMsgs) {
- done();
- }
- });
- for (let i = 0; i < numMsgs; i++) {
- setImmediate( function() { delayNode1.receive(msgAndTimings[i].msg); } );
- }
- });
- }
-
- it('calls done when queued message is emitted (type: delay)', function(done) {
- mapiDoneTestHelper(done, "delay", false, [{msg:{payload:1}, avr:1000, var:100}]);
- });
- it('calls done when queued message is emitted (type: delayv)', function(done) {
- mapiDoneTestHelper(done, "delayv", false, [{msg:{payload:1, delay:1000}, avr:1000, var:100}]);
- });
- it('calls done when queued message is emitted (type: delay)', function(done) {
- mapiDoneTestHelper(done, "random", false, [{msg:{payload:1}, avr:1000, var:100}]);
- });
- it('calls done when queued message is cleared (type: delay)', function(done) {
- mapiDoneTestHelper(done, "delay", false, [{msg:{payload:1}, avr:100, var:100},
- {msg:{payload:2,reset:true}, avr:100, var:100}]);
- });
- it('calls done when queued message is cleared (type: delayv)', function(done) {
- mapiDoneTestHelper(done, "delayv", false, [{msg:{payload:1, delay:1000}, avr:100, var:100},
- {msg:{payload:2, reset:true}, avr:100, var:100}]);
- });
- it('calls done when queued message is cleared (type: random)', function(done) {
- mapiDoneTestHelper(done, "random", false, [{msg:{payload:1}, avr:100, var:100},
- {msg:{payload:2,reset:true}, avr:100, var:100}]);
- });
- it('calls done when queued message is flushed (type: delay)', function(done) {
- mapiDoneTestHelper(done, "delay", false, [{msg:{payload:1}, avr:100, var:100},
- {msg:{payload:2,flush:true}, avr:100, var:100}]);
- });
- it('calls done when queued message is flushed (type: delayv)', function(done) {
- mapiDoneTestHelper(done, "delayv", false, [{msg:{payload:1, delay:1000}, avr:100, var:100},
- {msg:{payload:2, flush:true}, avr:100, var:100}]);
- });
- it('calls done when queued message is flushed (type: random)', function(done) {
- mapiDoneTestHelper(done, "random", false, [{msg:{payload:1}, avr:100, var:100},
- {msg:{payload:2,flush:true}, avr:100, var:100}]);
- });
- it('calls done when rated message is emitted (drop: false)', function(done) {
- mapiDoneTestHelper(done, "rate", false, [{msg:{payload:1}, avr:0, var:100},
- {msg:{payload:2}, avr:1000, var:100}]);
- });
- it('calls done when rated message is emitted (drop: true)', function(done) {
- mapiDoneTestHelper(done, "rate", true, [{msg:{payload:1}, avr:0, var:100},
- {msg:{payload:2}, avr:0, var:100}]);
- });
- it('calls done when rated message is flushed', function(done) {
- mapiDoneTestHelper(done, "rate", false, [{msg:{payload:1}, avr:0, var:100},
- {msg:{payload:2}, avr:0, var:100},
- {msg:{payload:3,flush:true}, avr:0, var:100}]);
- });
- it('calls done when queued messages are sent (queue)', function(done) {
- this.timeout(3000);
- mapiDoneTestHelper(done, "queue", false, [{msg:{payload:1,topic:"A"}, avr:1000, var:700},
- {msg:{payload:2,topic:"B"}, avr:2000, var:700}]);
- });
- it('calls done when queued messages are sent (timed)', function(done) {
- mapiDoneTestHelper(done, "timed", false, [{msg:{payload:1,topic:"a"}, avr:500, var:700},
- {msg:{payload:2,topic:"b"}, avr:500, var:700}]);
- });
- it('calls done when queue is reset (queue/timed)', function(done) {
- mapiDoneTestHelper(done, "timed", false, [{msg:{payload:1,topic:"a"}, avr:0, var:500},
- {msg:{payload:2,reset:true}, avr:0, var:500}]);
- });
- it('calls done when queue is flushed (queue/timed)', function(done) {
- mapiDoneTestHelper(done, "timed", false, [{msg:{payload:1,topic:"a"}, avr:0, var:500},
- {msg:{payload:2,flush:true}, avr:0, var:500}]);
- });
-});
diff --git a/test/nodes/core/function/89-trigger_spec.js b/test/nodes/core/function/89-trigger_spec.js
deleted file mode 100644
index 33401e540..000000000
--- a/test/nodes/core/function/89-trigger_spec.js
+++ /dev/null
@@ -1,1198 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var helper = require("node-red-node-test-helper");
-var triggerNode = require("nr-test-utils").require("@node-red/nodes/core/function/89-trigger.js");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context");
-var RED = require("nr-test-utils").require("node-red/lib/red");
-
-describe('trigger node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory0: {
- module: "memory"
- },
- memory1: {
- module: "memory"
- },
- memory2: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function(done) {
- helper.unload().then(function () {
- return Context.clean({allNodes: {}});
- }).then(function () {
- return Context.close();
- }).then(function () {
- helper.stopServer(done);
- });
- });
-
- it("should be loaded with correct defaults", function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", "wires":[[]]}];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'triggerNode');
- n1.should.have.property('op1', '1');
- n1.should.have.property('op2', '0');
- n1.should.have.property('op1type', 'str');
- n1.should.have.property('op2type', 'str');
- n1.should.have.property('extend', "false");
- n1.should.have.property('units', 'ms');
- n1.should.have.property('duration', 250);
- done();
- });
- });
-
- it("should be able to set delay in seconds", function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", units:"s", duration:"1", "wires":[[]]}];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('duration', 1000);
- done();
- });
- });
-
- it("should be able to set delay in minutes", function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", units:"min", duration:"1", "wires":[[]]}];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('duration', 60000);
- done();
- });
- });
-
- it("should be able to set delay in hours", function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", units:"hr", duration:"1", "wires":[[]]}];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('duration', 3600000);
- done();
- });
- });
-
- function basicTest(type, val, rval) {
- it('should output 1st value when triggered ('+type+')', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:val, op1type:type, op2:"", op2type:"null", duration:"20", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- process.env[val] = rval;
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- if (rval) {
- msg.should.have.property("payload");
- should.deepEqual(msg.payload, rval);
- }
- else {
- msg.should.have.property("payload", val);
- }
- delete process.env[val];
- done();
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:null});
- });
- });
-
- it('should output 2st value when triggered ('+type+')', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"foo", op1type:"str", op2:val, op2type:type, duration:"20", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- process.env[val] = rval;
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.property("payload", "foo");
- c++;
- }
- else {
- if (rval) {
- msg.should.have.property("payload");
- should.deepEqual(msg.payload, rval);
- }
- else {
- msg.should.have.property("payload", val);
- }
- delete process.env[val];
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:null});
- });
- });
- }
-
- basicTest("num", 10);
- basicTest("str", "10");
- basicTest("bool", true);
- var val_json = '{ "x":"vx", "y":"vy", "z":"vz" }';
- basicTest("json", val_json, JSON.parse(val_json));
- var val_buf = "[1,2,3,4,5]";
- basicTest("bin", val_buf, Buffer.from(JSON.parse(val_buf)));
- basicTest("env", "NR-TEST", "env-val");
-
- it('should output 1 then 0 when triggered (default)', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:"20", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", '1');
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", '0');
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:null});
- });
- });
-
- it('should ignore any other inputs while triggered if extend is false', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:"50",wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- var errored = false;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", '1');
- }
- else {
- msg.should.have.a.property("payload", '0');
- }
- c+=1;
- }catch(err) {
- errored = true;
- done(err);
- }
- });
- setTimeout( function() {
- if (!errored) {
- try {
- c.should.equal(2);
- done();
- } catch(err) {
- done(err);
- }
- }
- },100);
- n1.emit("input", {payload:null});
- setTimeout( function() {
- n1.emit("input", {payload:null});
- },10);
- setTimeout( function() {
- n1.emit("input", {payload:null});
- },30);
- });
- });
-
- it('should ignore msg.delay if overrideDelay not set', function(done) {
- var flow = [
- {"id":"n1", "type":"trigger", "name":"triggerNode", duration:"50",wires:[["n2"]] },
- {id:"n2", type:"helper"}
- ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- var firstTime;
- n2.on("input", function(msg) {
- if (c === 0) {
- firstTime = Date.now();
- } else if (c === 1) {
- try {
- var delta = Date.now() - firstTime;
- delta.should.be.greaterThan(30);
- delta.should.be.lessThan(100);
- done();
- } catch(err) {
- done(err);
- }
- }
- c++;
- });
- n1.emit("input", {payload:null, delay: 300});
- });
- });
-
- it('should use msg.delay if overrideDelay is set', function(done) {
- var flow = [
- {"id":"n1", "type":"trigger", "name":"triggerNode", overrideDelay: true, duration:"50",wires:[["n2"]] },
- {id:"n2", type:"helper"}
- ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- var firstTime;
- n2.on("input", function(msg) {
- if (c === 0) {
- firstTime = Date.now();
- } else if (c === 1) {
- try {
- var delta = Date.now() - firstTime;
- delta.should.be.greaterThan(270);
- delta.should.be.lessThan(380);
- done();
- } catch(err) {
- done(err);
- }
- }
- c++;
- });
- n1.emit("input", {payload:null, delay: 300});
- });
- });
-
-
- it('should handle true and false as strings and delay of 0', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"true",op1type:"val",op2:"false",op2type:"val",duration:"30", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", true);
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", false);
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.emit("input", {payload:null});
- });
- });
-
- it('should handle multiple topics as one if not asked to handle', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", bytopic:"all", op1:"1", op2:"0", op1type:"num", op2type:"num", duration:"30", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- if (c === 1) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("topic", "A");
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("topic", "A");
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.emit("input", {payload:1,topic:"A"});
- n1.emit("input", {payload:2,topic:"B"});
- n1.emit("input", {payload:3,topic:"C"});
- });
- });
-
- it('should handle multiple topics individually if asked to do so', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", bytopic:"topic", op1:"1", op2:"0", op1type:"num", op2type:"num", duration:"30", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- if (c === 1) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("topic", "A");
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("topic", "B");
- }
- else if (c === 3) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("topic", "C");
- }
- else if (c === 4) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("topic", "A");
- }
- else if (c === 5) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("topic", "B");
- }
- else if (c === 6) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("topic", "C");
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.emit("input", {payload:1,topic:"A"});
- n1.emit("input", {payload:2,topic:"B"});
- n1.emit("input", {payload:3,topic:"C"});
- });
- });
-
- it('should handle multiple topics individually, and extend one, if asked to do so', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", bytopic:"topic", extend:"true", op1:"1", op2:"0", op1type:"num", op2type:"num", duration:"30", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- if (c === 1) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("topic", "A");
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("topic", "B");
- }
- else if (c === 3) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("topic", "C");
- }
- else if (c === 4) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("topic", "A");
- }
- else if (c === 5) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("topic", "C");
- }
- else if (c === 6) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("topic", "B");
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.emit("input", {payload:1,topic:"A"});
- n1.emit("input", {payload:2,topic:"B"});
- n1.emit("input", {payload:3,topic:"C"});
- setTimeout( function() { n1.emit("input", {payload:2,topic:"B"})}, 20 );
- });
- });
-
- it('should handle multiple other properties individually if asked to do so', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", bytopic:"topic", topic:"foo", op1:"1", op2:"0", op1type:"num", op2type:"num", duration:"30", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- if (c === 1) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("foo", "A");
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("foo", "B");
- }
- else if (c === 3) {
- msg.should.have.a.property("payload", 1);
- msg.should.have.a.property("foo", "C");
- }
- else if (c === 4) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("foo", "A");
- }
- else if (c === 5) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("foo", "B");
- }
- else if (c === 6) {
- msg.should.have.a.property("payload", 0);
- msg.should.have.a.property("foo", "C");
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- n1.emit("input", {payload:1,foo:"A"});
- n1.emit("input", {payload:2,foo:"B"});
- n1.emit("input", {payload:3,foo:"C"});
- });
- });
-
- it('should be able to return things from flow and global context variables', function(done) {
- var spy = sinon.stub(RED.util, 'evaluateNodeProperty').callsFake(
- function(arg1, arg2, arg3, arg4, arg5) { if (arg5) { arg5(null, arg1) } else { return arg1; } }
- );
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1:"foo", op1type:"flow", op2:"bar", op2type:"global", duration:"20", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "foo");
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", "bar");
- RED.util.evaluateNodeProperty.restore();
- done();
- }
- }
- catch(err) { RED.util.evaluateNodeProperty.restore(); done(err); }
- });
- n1.emit("input", {payload:null});
- });
- });
-
- it('should be able to return things from persistable flow and global context variables', function (done) {
- var flow = [{"id": "n1", "type": "trigger", "name": "triggerNode", "op1": "#:(memory1)::foo", "op1type": "flow",
- "op2": "#:(memory1)::bar", "op2type": "global", "duration": "20", "wires": [["n2"]], "z": "flow" },
- {"id": "n2", "type": "helper"}];
- helper.load(triggerNode, flow, function () {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function (msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "foo");
- c += 1;
- } else {
- msg.should.have.a.property("payload", "bar");
- done();
- }
- } catch (err) {
- done(err);
- }
- });
- var context = n1.context();
- var flow = context.flow;
- var global = context.global;
- flow.set("foo", "foo", "memory1", function (err) {
- global.set("bar", "bar", "memory1", function (err) {
- n1.emit("input", { payload: null });
- });
- });
- });
- });
- });
-
- it('should be able to return things from multiple persistable global context variables', function (done) {
- var flow = [{"id": "n1", "z": "flow", "type": "trigger",
- "duration": "20", "wires": [["n2"]],
- "op1": "#:(memory1)::val", "op1type": "global",
- "op2": "#:(memory2)::val", "op2type": "global"
- },
- {"id": "n2", "type": "helper"}];
- helper.load(triggerNode, flow, function () {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- if (count === 0) {
- msg.should.have.a.property("payload", "foo");
- }
- else {
- msg.should.have.a.property("payload", "bar");
- }
- count++;
- if (count === 1) {
- done();
- }
- }
- catch (err) {
- done(err);
- }
- });
- var global = n1.context().global;
- global.set("val", "foo", "memory1", function (err) {
- global.set("val", "bar", "memory2", function (err) {
- n1.emit("input", { payload: null });
- });
- });
- });
- });
- });
-
- it('should be able to return things from multiple persistable flow context variables', function (done) {
- var flow = [{"id": "n1", "z": "flow", "type": "trigger",
- "duration": "20", "wires": [["n2"]],
- "op1": "#:(memory1)::val", "op1type": "flow",
- "op2": "#:(memory2)::val", "op2type": "flow"
- },
- {"id": "n2", "type": "helper"}];
- helper.load(triggerNode, flow, function () {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- if (count === 0) {
- msg.should.have.a.property("payload", "foo");
- }
- else {
- msg.should.have.a.property("payload", "bar");
- }
- count++;
- if (count === 1) {
- done();
- }
- }
- catch (err) {
- done(err);
- }
- });
- var flow = n1.context().flow;
- flow.set("val", "foo", "memory1", function (err) {
- flow.set("val", "bar", "memory2", function (err) {
- n1.emit("input", { payload: null });
- });
- });
- });
- });
- });
-
- it('should be able to return things from multiple persistable flow & global context variables', function (done) {
- var flow = [{"id": "n1", "z": "flow", "type": "trigger",
- "duration": "20", "wires": [["n2"]],
- "op1": "#:(memory1)::val", "op1type": "flow",
- "op2": "#:(memory2)::val", "op2type": "global"
- },
- {"id": "n2", "type": "helper"}];
- helper.load(triggerNode, flow, function () {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function (msg) {
- try {
- if (count === 0) {
- msg.should.have.a.property("payload", "foo");
- }
- else {
- msg.should.have.a.property("payload", "bar");
- }
- count++;
- if (count === 1) {
- done();
- }
- }
- catch (err) {
- done(err);
- }
- });
- var context = n1.context();
- var flow = context.flow;
- var global = context.flow;
- flow.set("val", "foo", "memory1", function (err) {
- global.set("val", "bar", "memory2", function (err) {
- n1.emit("input", { payload: null });
- });
- });
- });
- });
- });
-
- it('should be able to not output anything on first trigger', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1type:"nul", op1:"true",op2:"false",op2type:"val",duration:"30", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.a.property("payload", false);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.emit("input", {payload:null});
- });
- });
-
- it('should be able to not output anything on second edge', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op2type:"nul", op1:"true",op1type:"val", op2:"false", duration:"30", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.a.property("payload", true);
- c += 1;
- }
- catch(err) { done(err); }
- });
- setTimeout( function() {
- c.should.equal(1); // should only have had one output.
- done();
- },90);
- n1.emit("input", {payload:null});
- });
- });
-
- it('should be able to reset correctly having not output anything on second edge', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op2type:"nul", op1:"true",op1type:"val", op2:"false", duration:"100", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- var errors = [];
- n2.on("input", function(msg) {
- try {
- msg.should.have.a.property("topic", "pass")
- msg.should.have.a.property("payload", true);
- c += 1;
- }
- catch(err) { errors.push(err) }
- });
- setTimeout( function() {
- if (errors.length > 0) {
- done(errors[0])
- } else {
- c.should.equal(2);
- done();
- }
- },350);
- n1.emit("input", {payload:1, topic:"pass"});
- setTimeout( function() {
- n1.emit("input", {payload:2, topic:"should-block"});
- },50);
- setTimeout( function() {
- n1.emit("input", {payload:3, topic:"pass"});
- },200);
- setTimeout( function() {
- n1.emit("input", {payload:2, topic:"should-block"});
- },250);
- });
- });
-
- it('should be able to extend the delay', function(done) {
- this.timeout(5000); // add extra time for flake
- var spy = sinon.stub(RED.util, 'evaluateNodeProperty').callsFake(
- function(arg1, arg2, arg3, arg4, arg5) { if (arg5) { arg5(null, arg1) } else { return arg1; } }
- );
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"flow", op1:"foo", op2:"bar", op2type:"global", duration:"100", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "foo");
- c += 1;
- }
- else {
- msg.should.have.a.property("payload", "bar");
- //console.log(Date.now() - ss);
- (Date.now() - ss).should.be.greaterThan(149);
- spy.restore();
- done();
- }
- }
- catch(err) { spy.restore(); done(err); }
- });
- var ss = Date.now();
- n1.emit("input", {payload:"Hello"});
- setTimeout( function() {
- n1.emit("input", {payload:null});
- },50);
- });
- });
-
- it('should be able to extend the delay (but with no 2nd output)', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"pay", op2type:"nul", op1:"false", op2:"true", duration:"200", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "Hello");
- c += 1;
- }
- else {
- msg.should.have.a.property("payload", "World");
- (Date.now() - ss).should.be.greaterThan(300);
- done();
- }
- } catch(err) {
- console.log(err);
- done(err);
- }
- });
- var ss = Date.now();
- n1.emit("input", {payload:"Hello"});
- setTimeout( function() {
- n1.emit("input", {payload:"Error"});
- },50);
- setTimeout( function() {
- n1.emit("input", {payload:"Error"});
- },100);
- setTimeout( function() {
- n1.emit("input", {payload:"World"});
- },330);
- });
- });
-
- it('should be able to extend the delay and output the most recent payload', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"true", op1type:"nul", op2type:"payl", op1:"false", op2:"true", duration:"60", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.a.property("payload", "World");
- (Date.now() - ss).should.be.greaterThan(120);
- done();
- }
- catch(err) { done(err); }
- });
- var ss = Date.now();
- n1.emit("input", {payload:"Hello"});
- setTimeout( function() {
- n1.emit("input", {payload:"Goodbye"});
- },40);
- setTimeout( function() {
- n1.emit("input", {payload:"World"});
- },80);
- });
- });
-
- it('should be able output the 2nd payload', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"false", op1type:"nul", op2type:"payl", op1:"false", op2:"true", duration:"50", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "Goodbye");
- msg.should.have.a.property("topic", "test2");
- c += 1;
- }
- else {
- msg.should.have.a.property("payload", "World");
- msg.should.have.a.property("topic", "test3");
- (Date.now() - ss).should.be.greaterThan(70);
- done();
- }
- }
- catch(err) { done(err); }
- });
- var ss = Date.now();
- n1.emit("input", {payload:"Hello", topic:"test1"});
- setTimeout( function() {
- n1.emit("input", {payload:"Goodbye", topic:"test2"});
- },20);
- setTimeout( function() {
- n1.emit("input", {payload:"World", topic:"test3"});
- },80);
- });
- });
-
- it('should be able output the 2nd payload and handle multiple topics', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", extend:"false", op1type:"nul", op2type:"payl", op1:"false", op2:"true", duration:"80", bytopic:"topic", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "Goodbye1");
- msg.should.have.a.property("topic", "test1");
- c += 1;
- }
- else {
- msg.should.have.a.property("payload", "Goodbye2");
- msg.should.have.a.property("topic", "test2");
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:"Hello1", topic:"test1"});
- setTimeout( function() {
- n1.emit("input", {payload:"Hello2", topic:"test2"});
- },20);
- setTimeout( function() {
- n1.emit("input", {payload:"Goodbye2", topic:"test2"});
- },20);
- setTimeout( function() {
- n1.emit("input", {payload:"Goodbye1", topic:"test1"});
- },20);
- });
- });
-
- it('should be able to apply mustache templates to payloads', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1type:"val", op2type:"val", op1:"{{payload}}", op2:"{{topic}}", duration:"50", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "Hello");
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", "World");
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:"Hello",topic:"World"});
- });
- });
-
- it('should be able to send 2nd message to a 2nd output', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1type:"val", op2type:"val", op1:"hello", op2:"world", duration:"50", outputs:2, wires:[["n2"],["n3"]] },
- {id:"n2", type:"helper"}, {id:"n3", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", "hello");
- msg.should.have.a.property("topic", "test");
- c+=1;
- }
- else { done(err); }
- }
- catch(err) { done(err); }
- });
- n3.on("input", function(msg) {
- try {
- if (c === 1) {
- msg.should.have.a.property("payload", "world");
- msg.should.have.a.property("topic", "test");
- done();
- }
- else { done(err); }
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:"go",topic:"test"});
- });
- });
-
- it('should handle string null as null', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1type:"val", op2type:"pay", op1:"null", op2:"null", duration:"40", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", null);
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", "World");
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:"World"});
- });
- });
-
- it('should handle string null as null on op2', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", op1type:"val", op2type:"val", op1:"null", op2:"null", duration:"40", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- if (c === 0) {
- msg.should.have.a.property("payload", null);
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", null);
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:"null"});
- });
- });
-
- it('should be able to set infinite timeout, and clear timeout', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", duration:"0", extend: false, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- msg.should.have.a.property("payload", "1");
- }
- catch(err) { done(err); }
- });
- setTimeout( function() {
- if (c === 2) { done(); }
- else {
- done(new Error("Too many messages received"));
- }
- },20);
- n1.emit("input", {payload:null}); // trigger
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {reset:true}); // clear the blockage
- n1.emit("input", {payload:null}); // trigger
- });
- });
-
- it('should be able to set infinite timeout, and clear timeout by message', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"boo", duration:"0", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- msg.should.have.a.property("payload", "1");
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:null}); // trigger
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {payload:"foo"}); // don't clear the blockage
- n1.emit("input", {payload:"boo"}); // clear the blockage
- n1.emit("input", {payload:null}); // trigger
- setTimeout( function() {
- if (c === 2) { done(); }
- else {
- done(new Error("Too many messages received"));
- }
- },50);
- });
- });
-
- it('should be able to set infinite timeout, and clear timeout by boolean true', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"true", duration:"0", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- msg.should.have.a.property("payload", "1");
- }
- catch(err) { done(err); }
- });
- setTimeout( function() {
- if (c === 2) { done(); }
- else {
- done(new Error("Too many messages received"));
- }
- },20);
- n1.emit("input", {payload:null}); // trigger
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {payload:false}); // don't clear the blockage
- n1.emit("input", {payload:true}); // clear the blockage
- n1.emit("input", {payload:null}); // trigger
- });
- });
-
- it('should be able to set infinite timeout, and clear timeout by boolean false', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"false", duration:"0", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- c += 1;
- msg.should.have.a.property("payload", "1");
- }
- catch(err) { done(err); }
- });
- setTimeout( function() {
- if (c === 2) { done(); }
- else {
- done(new Error("Too many messages received"));
- }
- },20);
- n1.emit("input", {payload:null}); // trigger
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {payload:null}); // blocked
- n1.emit("input", {payload:"foo"}); // don't clear the blockage
- n1.emit("input", {payload:false}); // clear the blockage
- n1.emit("input", {payload:null}); // trigger
- });
- });
-
- it('should be able to set a repeat, and clear loop by reset', function(done) {
- var flow = [{"id":"n1", "type":"trigger", "name":"triggerNode", reset:"boo", op1:"", op1type:"pay", duration:-25, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(triggerNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- c += 1;
- try {
- msg.should.have.property('payload','foo');
- msg.payload = "bar"; // try to provoke pass by reference error
- }
- catch(err) { done(err); }
- });
- n1.emit("input", {payload:"foo"}); // trigger
- n1.emit("input", {payload:"foo"}); // trigger
- setTimeout( function() {
- n1.emit("input", {reset:true}); // reset
- },90);
- setTimeout( function() {
- c.should.within(2,5); // should send foo between 2 and 5 times.
- done();
- },180);
- });
- });
- describe('messaging API', function () {
- function mapiDoneTriggerTestHelper(done, nodeSetting, msgAndTimings) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js");
- const flow = [
- { ...nodeSetting, id: "triggerNode1", type: "trigger", wires: [[]] },
- { id: "completeNode1", type: "complete", scope: ["triggerNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "catchNode1", type: "catch", scope: ["triggerNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "helperNode1", type: "helper", wires: [[]] }];
- const numMsgs = msgAndTimings.length;
- helper.load([triggerNode, completeNode, catchNode], flow, function () {
- const triggerNode1 = helper.getNode("triggerNode1");
- const helperNode1 = helper.getNode("helperNode1");
- RED.settings.nodeMessageBufferMaxLength = 3;
- const t = Date.now();
- let c = 0;
- helperNode1.on("input", function (msg) {
- msg.should.have.a.property('payload');
- (Date.now() - t).should.be.approximately(msgAndTimings[msg.seq].avr, msgAndTimings[msg.seq].var);
- c += 1;
- if (c === numMsgs) {
- done();
- }
- });
- for (let i = 0; i < numMsgs; i++) {
- setTimeout(function () { triggerNode1.receive(msgAndTimings[i].msg); }, msgAndTimings[i].delay);
- }
- });
- }
- it('should call done() when first message has been processed', function (done) {
- // not when second and more messages are emitted.
- mapiDoneTriggerTestHelper(done, { units:"s", duration:"1" }, [
- { msg: { seq: 0, payload: "A"}, delay: 0, avr: 0, var: 100}
- ]);
- });
- it('should call done() when it receives reset message', function (done) {
- mapiDoneTriggerTestHelper(done, {units:"s", duration:"1"}, [
- {msg: { seq: 0, payload: "A", reset:true}, delay: 0, avr: 0, var:100}
- ]);
- })
- });
-});
diff --git a/test/nodes/core/function/90-exec_spec.js b/test/nodes/core/function/90-exec_spec.js
deleted file mode 100644
index c397ea27d..000000000
--- a/test/nodes/core/function/90-exec_spec.js
+++ /dev/null
@@ -1,973 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var helper = require("node-red-node-test-helper");
-var execNode = require("nr-test-utils").require("@node-red/nodes/core/function/90-exec.js");
-var osType = require("os").type();
-
-var child_process = require('child_process');
-
-describe('exec node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- afterEach(function(done) {
- helper.unload().then(function() {
- helper.stopServer(done);
- });
- });
-
- it('should be loaded with any defaults', function(done) {
- var flow = [{id:"n1", type:"exec", name: "exec1"}];
- helper.load(execNode, flow, function() {
- try {
- var n1 = helper.getNode("n1");
- n1.should.have.property("name", "exec1");
- n1.should.have.property("cmd", "");
- n1.should.have.property("append", "");
- n1.should.have.property("addpay","payload");
- n1.should.have.property("timer",0);
- n1.should.have.property("oldrc","false");
- n1.should.have.property("execOpt");
- n1.execOpt.should.have.property("encoding", 'binary');
- n1.execOpt.should.have.property("maxBuffer", 10000000);
- n1.execOpt.should.have.property("windowsHide", false);
- n1.should.have.property("spawnOpt");
- n1.spawnOpt.should.have.property("windowsHide", false);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- describe('calling exec', function() {
-
- it('should exec a simple command', function(done) {
- var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:false, append:"", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- var spy = sinon.stub(child_process, 'exec').callsFake(
- function(arg1, arg2, arg3, arg4) {
- // arg3(error,stdout,stderr);
- arg3(null,arg1,arg1.toUpperCase());
- });
-
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null,null];
- var completeTest = function() {
- received = received + 1;
- if (received < 3) {
- return;
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("echo");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",0);
-
- msg = messages[1];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("ECHO");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",0);
-
- msg = messages[2];
- msg.should.have.property("payload");
- msg.payload.should.have.property("code",0);
-
- child_process.exec.restore();
- done();
- }
- catch(err) {
- child_process.exec.restore();
- done(err);
- }
- };
- n2.on("input", function(msg) {
- messages[0] = msg;
- completeTest();
- });
- n3.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n4.on("input", function(msg) {
- messages[2] = msg;
- completeTest();
- });
- n1.receive({payload:"and"});
- });
- });
-
- it('should exec a simple command with appended value from message', function (done) {
- var flow = [{id:"n1", type:"exec", wires:[["n2"]], command:"echo", addpay:"topic", append:"more", oldrc:"false"},
- {id:"n2", type:"helper"}];
- helper.load(execNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("bar more\n");
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:"foo", topic:"bar"});
- });
- });
-
- it('should exec a simple command with extra parameters', function(done) {
- var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:"payload", append:"more", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- var spy = sinon.stub(child_process, 'exec').callsFake(
- function(arg1, arg2, arg3, arg4) {
- //console.log(arg1);
- // arg3(error,stdout,stderr);
- arg3(null,arg1,arg1.toUpperCase());
- });
-
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null];
- var completeTest = function() {
- received++;
- if (received < 2) {
- return;
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("echo and more");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",0);
-
- msg = messages[1];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("ECHO AND MORE");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",0);
- child_process.exec.restore();
- done();
- }
- catch(err) {
- child_process.exec.restore();
- done(err);
- }
- };
- n2.on("input", function(msg) {
- messages[0] = msg;
- completeTest();
- });
- n3.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n1.receive({payload:"and"});
- });
- });
-
- it('should be able to return a binary buffer', function(done) {
- var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"more", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- var spy = sinon.stub(child_process, 'exec').callsFake(
- function(arg1, arg2, arg3, arg4) {
- //console.log(arg1);
- // arg3(error,stdout,stderr);
- arg3("error",Buffer.from([0x01,0x02,0x03,0x88]),Buffer.from([0x01,0x02,0x03,0x88]));
- });
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n2.on("input", function(msg) {
- //console.log("n2",msg);
- try {
- msg.should.have.property("payload");
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.payload.length.should.equal(4);
- child_process.exec.restore();
- done();
- } catch(err) {
- child_process.exec.restore();
- done(err);
- }
- });
- n1.receive({});
- });
- });
-
- it('should be able to timeout a long running command', function(done) {
- var flow;
- if (osType === "Windows_NT") {
- // Although Windows timeout command is equivalent to sleep, this cannot be used because it promptly outputs a message.
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"0.3", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"0.3", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("signal","SIGTERM");
- done();
- }
- catch(err) { done(err); }
- });
- n1.receive({});
- });
- });
-
- it('should be able to kill a long running command', function(done) {
- var flow;
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",null);
- msg.rc.should.have.property("signal","SIGTERM");
- } catch(err) { done(err); }
- });
- n4.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("signal","SIGTERM");
- done();
- }
- catch(err) { done(err); }
- });
- setTimeout(function() {
- n1.receive({kill:""});
- },150);
- n1.receive({});
- });
- });
-
- it('should be able to kill a long running command - SIGINT', function(done) {
- var flow;
- var sig = "SIGINT";
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",null);
- msg.rc.should.have.property("signal","SIGINT");
- } catch(err) { done(err); }
- });
- n4.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("signal",sig);
- done();
- } catch(err) { done(err); }
- });
- setTimeout(function() {
- n1.receive({kill:"SIGINT"});
- },150);
- n1.receive({});
- });
- });
-
- it('should return the rc for a failing command', function(done) {
- var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"error", addpay:false, append:"", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- var spy = sinon.stub(child_process, 'exec').callsFake(
- function(arg1, arg2, arg3, arg4) {
- //console.log(arg1);
- // arg3(error,stdout,stderr);
- arg3({code: 1},arg1,arg1.toUpperCase());
- });
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null,null];
- var completeTest = function() {
- received++;
- if (received < 3) {
- return;
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("error");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",1);
- msg.rc.should.have.property("message",undefined);
-
- msg = messages[1];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("ERROR");
-
- msg = messages[2];
- msg.should.have.property("payload");
- msg.payload.should.have.property("code",1);
-
- child_process.exec.restore();
- done();
- }
- catch(err) {
- child_process.exec.restore();
- done(err);
- }
- };
- n2.on("input", function(msg) {
- messages[0] = msg;
- completeTest();
- });
- n3.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n4.on("input", function(msg) {
- messages[2] = msg;
- completeTest();
- });
- n1.receive({payload:"and"});
- });
- });
-
- it('should preserve existing properties on msg object', function(done) {
- var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:false, append:"", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- var spy = sinon.stub(child_process, 'exec').callsFake(
- function(arg1, arg2, arg3, arg4) {
- // arg3(error,stdout,stderr);
- arg3(null,arg1,arg1.toUpperCase());
- });
-
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null,null];
- var completeTest = function() {
- received = received + 1;
- if (received < 3) {
- return;
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("echo");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",0);
- msg.should.have.property("foo","bar");
-
- msg = messages[1];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("ECHO");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",0);
- msg.should.have.property("foo","bar");
-
- msg = messages[2];
- msg.should.have.property("payload");
- msg.payload.should.have.property("code",0);
- msg.should.have.property("foo","bar");
-
- child_process.exec.restore();
- done();
- }
- catch(err) {
- child_process.exec.restore();
- done(err);
- }
- };
- n2.on("input", function(msg) {
- messages[0] = msg;
- completeTest();
- });
- n3.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n4.on("input", function(msg) {
- messages[2] = msg;
- completeTest();
- });
- n1.receive({payload:"and", foo:"bar"});
- });
- });
-
- it('should preserve existing properties on msg object for a failing command', function(done) {
- var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"error", addpay:false, append:"", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- var spy = sinon.stub(child_process, 'exec').callsFake(
- function(arg1, arg2, arg3, arg4) {
- // arg3(error,stdout,stderr);
- arg3({code: 1},arg1,arg1.toUpperCase());
- });
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null,null];
- var completeTest = function() {
- received++;
- if (received < 3) {
- return;
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("error");
- msg.should.have.property("rc");
- msg.rc.should.have.property("code",1);
- msg.rc.should.have.property("message",undefined);
- msg.should.have.property("foo",null);
-
- msg = messages[1];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal("ERROR");
- msg.should.have.property("foo",null);
-
- msg = messages[2];
- msg.should.have.property("payload");
- msg.payload.should.have.property("code",1);
- msg.should.have.property("foo",null);
-
- child_process.exec.restore();
- done();
- }
- catch(err) {
- child_process.exec.restore();
- done(err);
- }
- };
- n2.on("input", function(msg) {
- messages[0] = msg;
- completeTest();
- });
- n3.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n4.on("input", function(msg) {
- messages[2] = msg;
- completeTest();
- });
- n1.receive({payload:"and", foo:null});
- });
- });
-
- });
-
- describe('calling spawn', function() {
-
- it('should spawn a simple command', function(done) {
- var flow;
- var expected;
- if (osType === "Windows_NT") {
- // Need to use cmd to spawn a process because Windows echo command is a built-in command and cannot be spawned.
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "hello world\r\n";
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "hello world\n";
- }
- var events = require('events');
-
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var payload = "";
- n2.on("input", function(msg) {
- //console.log(msg);
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- payload += msg.payload;
- if (payload.endsWith("\n")) {
- payload.should.equal(expected);
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.receive({payload:"hello world"});
- });
- });
-
- it('should spawn a simple command with a non string payload parameter', function(done) {
- var flow;
- var expected;
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:" deg C", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "12345 deg C\r\n";
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:" deg C", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "12345 deg C\n";
- }
- var payload = "";
-
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n2.on("input", function(msg) {
- //console.log(msg);
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- payload += msg.payload;
- if (payload.endsWith("\n")) {
- payload.should.equal(expected);
- done();
- }
- }
- catch(err) { done(err); }
- });
- n1.receive({payload:12345});
- });
- });
-
- it('should spawn a simple command and return binary buffer', function(done) {
- var flow;
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo", addpay:true, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo", addpay:true, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
-
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- Buffer.isBuffer(msg.payload).should.be.true();
- if (osType === "Windows_NT") {
- msg.payload.length.should.equalOneOf(6,8);
- } else {
- msg.payload.length.should.equal(7);
- }
- done();
- }
- catch(err) { done(err); }
- });
- n1.receive({payload:Buffer.from([0x01,0x02,0x03,0x88])});
- });
- });
-
- it('should work if passed multiple words to spawn command', function(done) {
- var flow;
- var expected;
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo this now works", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "this now works\r\n";
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo this now works", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "this now works\n";
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null];
- var completeTest = function() {
- received++;
- if (received < 2) {
- return;
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal(expected);
-
- msg = messages[1];
- msg.should.have.property("payload");
- should.exist(msg.payload);
- msg.payload.should.have.property("code",0);
- done();
- }
- catch(err) {
- done(err);
- }
- };
-
- n2.on("input", function(msg) {
- var payload = msg.payload;
- if (messages[0]) {
- messages[0].payload += payload;
- }
- else {
- messages[0] = msg;
- }
- if (payload.endsWith("\n")) {
- completeTest();
- }
- });
- n4.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n1.receive({payload:null,fred:123});
- });
- });
-
- it('should return an error for a bad command', function(done) {
- var flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"madeupcommandshouldfail", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("code");
- msg.payload.code.should.be.below(0);
- done();
- }
- catch(err) { done(err); }
- });
- n1.receive({payload:null});
- });
- });
-
- it('should return an error for a failing command', function(done) {
- var flow;
- var expected;
- var expectedFound = false;
- if (osType === "Windows_NT") {
- // Cannot use mkdir because Windows mkdir command automatically creates non-existent directories.
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "IP address must be specified.";
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"mkdir /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = ' directory';
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n3.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- if (msg.payload.indexOf(expected) >= 0) {
- // The error text on the stderr stream might get sent in more than one piece.
- // We only need to know that it occurred before the return code is sent,
- // as checked below in node n4.
- expectedFound = true;
- }
- }
- catch(err) { done(err); }
- });
- n4.on("input", function(msg) {
- try {
- expectedFound.should.be.true;
- msg.should.have.property("payload");
- msg.payload.should.have.property("code",1);
- done();
- }
- catch(err) { done(err); }
- });
- n1.receive({payload:null});
- });
- });
-
- it('should be able to timeout a long running command', function(done) {
- var flow;
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000", timer:"0.3", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"0.3", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("code",null);
- msg.payload.should.have.property("signal","SIGTERM");
- done();
- }
- catch(err) { done(err); }
- });
- n1.receive({});
- });
- });
-
- it('should be able to kill a long running command', function(done) {
- var flow;
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("signal","SIGTERM");
- done();
- }
- catch(err) { done(err); }
- });
- setTimeout(function() {
- n1.receive({kill:""});
- },150);
- n1.receive({});
- });
- });
-
- it('should be able to kill a long running command - SIGINT', function(done) {
- var flow;
- var sig = "SIGINT";
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping", addpay:false, append:"192.0.2.0 -n 1 -w 1000 > NUL", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"sleep", addpay:false, append:"1", timer:"2", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- n4.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("signal",sig);
- done();
- }
- catch(err) { done(err); }
- });
- setTimeout(function() {
- n1.receive({kill:"SIGINT"});
- },150);
- n1.receive({});
- });
- });
-
- it('should preserve existing properties on msg object', function(done) {
- var flow;
- var expected;
- if (osType === "Windows_NT") {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"cmd /C echo this now works", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "this now works\r\n";
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"echo this now works", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "this now works\n";
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null];
- var completeTest = function() {
- received++;
- if (received < 2) {
- return;
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.payload.should.equal(expected);
- msg.should.have.property("foo",123);
-
- msg = messages[1];
- msg.should.have.property("payload");
- should.exist(msg.payload);
- msg.payload.should.have.property("code",0);
- msg.should.have.property("foo",123);
-
- done();
- }
- catch(err) {
- done(err);
- }
- };
-
- n2.on("input", function(msg) {
- var payload = msg.payload;
- if (messages[0]) {
- messages[0].payload += payload;
- }
- else {
- messages[0] = msg;
- }
- if (payload.endsWith("\n")) {
- completeTest();
- }
- });
- n4.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n1.receive({payload:null,foo:123});
- });
- });
-
- it('should preserve existing properties on msg object for a failing command', function(done) {
- var flow;
- var expected;
- if (osType === "Windows_NT") {
- // Cannot use mkdir because Windows mkdir command automatically creates non-existent directories.
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"ping /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = "IP address must be specified.";
- } else {
- flow = [{id:"n1",type:"exec",wires:[["n2"],["n3"],["n4"]],command:"mkdir /foo/bar/doo/dah", addpay:false, append:"", useSpawn:"true", oldrc:"false"},
- {id:"n2", type:"helper"},{id:"n3", type:"helper"},{id:"n4", type:"helper"}];
- expected = ' directory';
- }
- helper.load(execNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- var n4 = helper.getNode("n4");
- var received = 0;
- var messages = [null,null];
- var completeTest = function() {
- if (messages[0] === null || messages[1] === null) {
- // We have not yet had responses on both ports.
- return
- }
- try {
- var msg = messages[0];
- msg.should.have.property("payload");
- msg.payload.should.be.a.String();
- msg.should.have.property("foo","baz");
-
- msg = messages[1];
- msg.should.have.property("payload");
- msg.payload.should.have.property("code",1);
- msg.should.have.property("foo","baz");
-
- done();
- }
- catch(err) {
- done(err);
- }
- };
-
- n3.on("input", function(msg) {
- messages[0] = msg;
- completeTest();
- });
- n4.on("input", function(msg) {
- messages[1] = msg;
- completeTest();
- });
- n1.receive({payload:null,foo:"baz"});
- });
- });
-
- });
-});
diff --git a/test/nodes/core/function/rbe_spec.js b/test/nodes/core/function/rbe_spec.js
deleted file mode 100644
index 2ef005a27..000000000
--- a/test/nodes/core/function/rbe_spec.js
+++ /dev/null
@@ -1,538 +0,0 @@
-
-var should = require("should");
-var helper = require("node-red-node-test-helper");
-
-var testNode = require("nr-test-utils").require("@node-red/nodes/core/function/rbe.js");
-
-describe('rbe node', function() {
- "use strict";
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- afterEach(function(done) {
- helper.unload().then(function() {
- helper.stopServer(done);
- });
- });
-
- it("should be loaded with correct defaults", function(done) {
- var flow = [{"id":"n1", "type":"rbe", "name":"rbe1", "wires":[[]]}];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property("name", "rbe1");
- n1.should.have.property("func", "rbe");
- n1.should.have.property("gap", "0");
- done();
- });
- });
-
- it('should only send output if payload changes - with multiple topics (rbe)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("payload", "a");
- c+=1;
- }
- else if (c === 1) {
- msg.should.have.a.property("payload", 2);
- c+=1;
- }
- else if (c == 2) {
- msg.should.have.a.property("payload");
- msg.payload.should.have.a.property("b",1);
- msg.payload.should.have.a.property("c",2);
- c+=1;
- }
- else if (c == 3) {
- msg.should.have.a.property("payload",true);
- c+=1;
- }
- else if (c == 4) {
- msg.should.have.a.property("payload",false);
- c+=1;
- }
- else if (c == 5) {
- msg.should.have.a.property("payload",true);
- c+=1;
- }
- else if (c == 6) {
- msg.should.have.a.property("topic","a");
- msg.should.have.a.property("payload",1);
- c+=1;
- }
- else if (c == 7) {
- msg.should.have.a.property("topic","b");
- msg.should.have.a.property("payload",1);
- c+=1;
- }
- else {
- c += 1;
- msg.should.have.a.property("topic","c");
- msg.should.have.a.property("payload",1);
- done();
- }
- });
- n1.emit("input", {payload:"a"});
- n1.emit("input", {payload:"a"});
- n1.emit("input", {payload:"a"});
- n1.emit("input", {payload:2});
- n1.emit("input", {payload:2});
- n1.emit("input", {payload:{b:1,c:2}});
- n1.emit("input", {payload:{c:2,b:1}});
- n1.emit("input", {payload:{c:2,b:1}});
- n1.emit("input", {payload:true});
- n1.emit("input", {payload:false});
- n1.emit("input", {payload:false});
- n1.emit("input", {payload:true});
-
- n1.emit("input", {topic:"a",payload:1});
- n1.emit("input", {topic:"b",payload:1});
- n1.emit("input", {topic:"b",payload:1});
- n1.emit("input", {topic:"a",payload:1});
- n1.emit("input", {topic:"c",payload:1});
-
- });
- });
-
- it('should ignore multiple topics if told to (rbe)', function(done) {
- var flow = [{id:"n1", type:"rbe", func:"rbe", gap:"0", septopics:false, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("payload", "a");
- c+=1;
- }
- else if (c === 1) {
- msg.should.have.a.property("payload", 2);
- c+=1;
- }
- else if (c == 2) {
- msg.should.have.a.property("payload");
- msg.payload.should.have.a.property("b",1);
- msg.payload.should.have.a.property("c",2);
- c+=1;
- }
- else if (c == 3) {
- msg.should.have.a.property("payload",true);
- c+=1;
- }
- else if (c == 4) {
- msg.should.have.a.property("payload",false);
- c+=1;
- }
- else if (c == 5) {
- msg.should.have.a.property("payload",true);
- c+=1;
- }
- else if (c == 6) {
- msg.should.have.a.property("topic","a");
- msg.should.have.a.property("payload",1);
- c+=1;
- }
- else {
- msg.should.have.a.property("topic","a");
- msg.should.have.a.property("payload",2);
- done();
- }
- });
- n1.emit("input", {topic:"a",payload:"a"});
- n1.emit("input", {topic:"b",payload:"a"});
- n1.emit("input", {topic:"c",payload:"a"});
- n1.emit("input", {topic:"a",payload:2});
- n1.emit("input", {topic:"b",payload:2});
- n1.emit("input", {payload:{b:1,c:2}});
- n1.emit("input", {payload:{c:2,b:1}});
- n1.emit("input", {payload:{c:2,b:1}});
- n1.emit("input", {topic:"a",payload:true});
- n1.emit("input", {topic:"b",payload:false});
- n1.emit("input", {topic:"c",payload:false});
- n1.emit("input", {topic:"d",payload:true});
-
- n1.emit("input", {topic:"a",payload:1});
- n1.emit("input", {topic:"b",payload:1});
- n1.emit("input", {topic:"c",payload:1});
- n1.emit("input", {topic:"d",payload:1});
- n1.emit("input", {topic:"a",payload:2});
-
- });
- });
-
- it('should only send output if another chosen property changes - foo (rbe)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", property:"foo", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("foo", "a");
- c+=1;
- }
- else if (c === 1) {
- msg.should.have.a.property("foo", "b");
- c+=1;
- }
- else {
- msg.should.have.a.property("foo");
- msg.foo.should.have.a.property("b",1);
- msg.foo.should.have.a.property("c",2);
- done();
- }
- });
- n1.emit("input", {foo:"a"});
- n1.emit("input", {payload:"a"});
- n1.emit("input", {foo:"a"});
- n1.emit("input", {payload:"a"});
- n1.emit("input", {foo:"a"});
- n1.emit("input", {foo:"b"});
- n1.emit("input", {foo:{b:1,c:2}});
- n1.emit("input", {foo:{c:2,b:1}});
- n1.emit("input", {payload:{c:2,b:1}});
- });
- });
-
- it('should only send output if payload changes - ignoring first value (rbei)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"rbei", gap:"0", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("payload", "b");
- msg.should.have.a.property("topic", "a");
- c+=1;
- }
- else if (c === 1) {
- msg.should.have.a.property("payload", "b");
- msg.should.have.a.property("topic", "b");
- c+=1;
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", "c");
- msg.should.have.a.property("topic", "a");
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", "c");
- msg.should.have.a.property("topic", "b");
- done();
- }
-
- });
- n1.emit("input", {payload:"a", topic:"a"});
- n1.emit("input", {payload:"a", topic:"b"});
- n1.emit("input", {payload:"a", topic:"a"});
- n1.emit("input", {payload:"b", topic:"a"});
- n1.emit("input", {payload:"b", topic:"b"});
- n1.emit("input", {payload:"c", topic:"a"});
- n1.emit("input", {payload:"c", topic:"b"});
- });
- });
-
- it('should send output if queue is reset (rbe)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"rbe", gap:"0", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("payload", "a");
- c+=1;
- }
- else if (c === 1) {
- msg.should.have.a.property("payload", "b");
- c+=1;
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", "a");
- c+=1;
- }
- else if (c === 3) {
- msg.should.have.a.property("payload", "b");
- c+=1;
- }
- else if (c === 4) {
- msg.should.have.a.property("payload", "b");
- c+=1;
- }
- else if (c === 5) {
- msg.should.have.a.property("payload", "b");
- c+=1;
- }
- else if (c === 6) {
- msg.should.have.a.property("payload", "a");
- c+=1;
- }
- else {
- msg.should.have.a.property("payload", "c");
- done();
- }
- });
- n1.emit("input", {topic:"a", payload:"a"});
- n1.emit("input", {topic:"a", payload:"a"});
- n1.emit("input", {topic:"b", payload:"b"});
- n1.emit("input", {reset:true}); // reset all
- n1.emit("input", {topic:"a", payload:"a"});
- n1.emit("input", {topic:"b", payload:"b"});
- n1.emit("input", {topic:"b", payload:"b"});
- n1.emit("input", {topic:"b", reset:""}); // reset b
- n1.emit("input", {topic:"b", payload:"b"});
- n1.emit("input", {topic:"a", payload:"a"});
- n1.emit("input", {reset:""}); // reset all
- n1.emit("input", {topic:"b", payload:"b"});
- n1.emit("input", {topic:"a", payload:"a"});
- n1.emit("input", {topic:"c"}); // don't reset a non topic
- n1.emit("input", {topic:"b", payload:"b"});
- n1.emit("input", {topic:"a", payload:"a"});
- n1.emit("input", {topic:"c", payload:"c"});
- });
- });
-
- it('should only send output if x away from original value (deadbandEq)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"deadbandEq", gap:"10", inout:"out", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- c = c + 1;
- if (c === 1) {
- msg.should.have.a.property("payload", 0);
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 10);
- }
- else if (c == 3) {
- msg.should.have.a.property("payload", 20);
- done();
- }
- });
- n1.emit("input", {payload:0});
- n1.emit("input", {payload:2});
- n1.emit("input", {payload:4});
- n1.emit("input", {payload:6});
- n1.emit("input", {payload:8});
- n1.emit("input", {payload:10});
- n1.emit("input", {payload:15});
- n1.emit("input", {payload:20});
- });
- });
-
- it('should only send output if more than x away from original value (deadband)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- c = c + 1;
- //console.log(c,msg);
- if (c === 1) {
- msg.should.have.a.property("payload", 0);
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 20);
- }
- else {
- msg.should.have.a.property("payload", "5 deg");
- done();
- }
- });
- n1.emit("input", {payload:0});
- n1.emit("input", {payload:2});
- n1.emit("input", {payload:4});
- n1.emit("input", {payload:"6 deg"});
- n1.emit("input", {payload:8});
- n1.emit("input", {payload:20});
- n1.emit("input", {payload:15});
- n1.emit("input", {payload:"5 deg"});
- });
- });
-
- it('should only send output if more than x% away from original value (deadband)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10%", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- c = c + 1;
- if (c === 1) {
- msg.should.have.a.property("payload", 100);
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 111);
- }
- else if (c === 3) {
- msg.should.have.a.property("payload", 135);
- done();
- }
- });
- n1.emit("input", {payload:100});
- n1.emit("input", {payload:95});
- n1.emit("input", {payload:105});
- n1.emit("input", {payload:111});
- n1.emit("input", {payload:120});
- n1.emit("input", {payload:135});
- });
- });
-
- it('should warn if no number found in deadband mode', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"deadband", gap:"10", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- c += 1;
- });
- setTimeout( function() {
- c.should.equal(0);
- helper.log().called.should.be.true;
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "rbe";
- });
- logEvents.should.have.length(1);
- var msg = logEvents[0][0];
- msg.should.have.property('level', helper.log().WARN);
- msg.should.have.property('id', 'n1');
- msg.should.have.property('type', 'rbe');
- msg.should.have.property('msg', 'rbe.warn.nonumber');
- done();
- },50);
- n1.emit("input", {payload:"banana"});
- });
- });
-
- it('should not send output if x away or greater from original value (narrowbandEq)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"narrowbandEq", gap:"10", inout:"out", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- c = c + 1;
- //console.log(c,msg);
- if (c === 1) {
- msg.should.have.a.property("payload", 0);
- }
- else if (c === 2) {
- msg.should.have.a.property("payload", 5);
- }
- else if (c === 3) {
- msg.should.have.a.property("payload", 10);
- done();
- }
- });
- n1.emit("input", {payload:0});
- n1.emit("input", {payload:10});
- n1.emit("input", {payload:5});
- n1.emit("input", {payload:15});
- n1.emit("input", {payload:10});
- n1.emit("input", {payload:20});
- n1.emit("input", {payload:25});
- });
- });
-
- it('should not send output if more than x away from original value (narrowband)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"10", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("payload", 0);
- }
- else if (c === 1) {
- msg.should.have.a.property("payload","6 deg");
- }
- else {
- msg.should.have.a.property("payload", "5 deg");
- done();
- }
- c += 1;
- });
- n1.emit("input", {payload:0});
- n1.emit("input", {payload:20});
- n1.emit("input", {payload:40});
- n1.emit("input", {payload:"6 deg"});
- n1.emit("input", {payload:18});
- n1.emit("input", {payload:20});
- n1.emit("input", {payload:50});
- n1.emit("input", {payload:"5 deg"});
- });
- });
-
- it('should send output if gap is 0 and input doesnt change (narrowband)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"0", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("payload", 1);
- }
- else if (c === 4) {
- msg.should.have.a.property("payload",1);
- done();
- }
- c += 1;
- });
- n1.emit("input", {payload:1});
- n1.emit("input", {payload:1});
- n1.emit("input", {payload:1});
- n1.emit("input", {payload:1});
- n1.emit("input", {payload:0});
- n1.emit("input", {payload:1});
- });
- });
-
- it('should not send output if more than x away from original value (narrowband in step mode)', function(done) {
- var flow = [{"id":"n1", "type":"rbe", func:"narrowband", gap:"10", inout:"in", start:"500", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.a.property("payload", 55);
- }
- else if (c === 1) {
- msg.should.have.a.property("payload", 205);
- done();
- }
- c += 1;
- });
- n1.emit("input", {payload:50});
- n1.emit("input", {payload:55});
- n1.emit("input", {payload:200});
- n1.emit("input", {payload:205});
- });
- });
-});
diff --git a/test/nodes/core/network/21-httprequest_spec.js b/test/nodes/core/network/21-httprequest_spec.js
deleted file mode 100644
index 07bed5a01..000000000
--- a/test/nodes/core/network/21-httprequest_spec.js
+++ /dev/null
@@ -1,2221 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var http = require("http");
-var https = require("https");
-var should = require("should");
-var express = require("express");
-var bodyParser = require('body-parser');
-var stoppable = require('stoppable');
-var helper = require("node-red-node-test-helper");
-var httpRequestNode = require("nr-test-utils").require("@node-red/nodes/core/network/21-httprequest.js");
-var tlsNode = require("nr-test-utils").require("@node-red/nodes/core/network/05-tls.js");
-var httpProxyNode = require("nr-test-utils").require("@node-red/nodes/core/network/06-httpproxy.js");
-var hashSum = require("hash-sum");
-var httpProxy = require('proxy');
-var cookieParser = require('cookie-parser');
-var multer = require("multer");
-var RED = require("nr-test-utils").require("node-red/lib/red");
-var fs = require('fs-extra');
-var auth = require('basic-auth');
-
-describe('HTTP Request Node', function() {
- var testApp;
- var testServer;
- var testPort = 10234;
- var testSslServer;
- var testSslPort = 10334;
- var testProxyServer;
- var testProxyPort = 10444;
- var testProxyServerAuth;
- var testProxyAuthPort = 10554;
- var testSslClientServer;
- var testSslClientPort = 10664;
-
- //save environment variables
- var preEnvHttpProxyLowerCase;
- var preEnvHttpProxyUpperCase;
- var preEnvNoProxyLowerCase;
- var preEnvNoProxyUpperCase;
-
- //rediect cookie variables
- var receivedCookies = {};
-
- function startServer(done) {
- testPort += 1;
- testServer = stoppable(http.createServer(testApp));
- testServer.listen(testPort,function(err) {
- testSslPort += 1;
- console.log("ssl port", testSslPort);
- var sslOptions = {
- key: fs.readFileSync('test/resources/ssl/server.key'),
- cert: fs.readFileSync('test/resources/ssl/server.crt')
- /*
- Country Name (2 letter code) [AU]:
- State or Province Name (full name) [Some-State]:
- Locality Name (eg, city) []:
- Organization Name (eg, company) [Internet Widgits Pty Ltd]:
- Organizational Unit Name (eg, section) []:
- Common Name (e.g. server FQDN or YOUR name) []:localhost
- Email Address []:
-
- Please enter the following 'extra' attributes to be sent with your certificate request
- A challenge password []:
- An optional company name []:
- */
- };
- testSslServer = stoppable(https.createServer(sslOptions,testApp));
- testSslServer.listen(testSslPort, function(err){
- if (err) {
- console.log(err);
- } else {
- console.log("started testSslServer");
- }
- });
-
- testSslClientPort += 1;
- var sslClientOptions = {
- key: fs.readFileSync('test/resources/ssl/server.key'),
- cert: fs.readFileSync('test/resources/ssl/server.crt'),
- ca: fs.readFileSync('test/resources/ssl/server.crt'),
- requestCert: true
- };
- testSslClientServer = stoppable(https.createServer(sslClientOptions, testApp));
- testSslClientServer.listen(testSslClientPort, function(err){
- console.log("ssl-client", err)
- });
-
- testProxyPort += 1;
- testProxyServer = stoppable(httpProxy(http.createServer()))
-
- testProxyServer.on('request', function(req,res){
- if (!res.headersSent) {
- res.setHeader("x-testproxy-header", "foobar")
- }
- })
- testProxyServer.listen(testProxyPort)
-
- testProxyAuthPort += 1
- testProxyServerAuth = stoppable(httpProxy(http.createServer()))
- testProxyServerAuth.authenticate = function(req,callback){
- var authHeader = req.headers['proxy-authorization'];
- if (authHeader) {
- var user = auth.parse(authHeader)
- if (user.name == "foouser" && user.pass == "barpassword") {
- callback(null, true)
- } else {
- callback(null, false)
- }
- } else {
- callback(null, false)
- }
- }
- testProxyServerAuth.on('request', function(req,res){
- if (!res.headersSent) {
- res.setHeader("x-testproxy-header", "foobar")
- }
- })
- testProxyServerAuth.listen(testProxyAuthPort)
-
- done(err);
- });
- }
-
- function getTestURL(url) {
- return "http://localhost:"+testPort+url;
- }
-
- function getSslTestURL(url) {
- return "https://localhost:"+testSslPort+url;
- }
-
- function getSslClientTestURL(url) {
- return "https://localhost:"+testSslClientPort+url;
- }
-
- function getDifferentTestURL(url) {
- return "http://127.0.0.1:"+testPort+url;
- }
-
- function getSslTestURLWithoutProtocol(url) {
- return "localhost:"+testSslPort+url;
- }
-
- function deleteProxySetting() {
- delete process.env.http_proxy;
- delete process.env.HTTP_PROXY;
- delete process.env.no_proxy;
- delete process.env.NO_PROXY;
- }
-
- before(function(done) {
-
- testApp = express();
-
- // The fileupload test needs a different set of middleware - so mount
- // as a separate express instance
- var fileUploadApp = express();
- var mp = multer({ storage: multer.memoryStorage() }).any();
- fileUploadApp.post("/file-upload",function(req,res,next) {
- mp(req,res,function(err) {
- req._body = true;
- next(err);
- })
- },bodyParser.json(),function(req,res) {
- res.json({
- body: req.body,
- files: req.files
- })
- });
- testApp.use(fileUploadApp);
-
- testApp.use(bodyParser.raw({type:"*/*"}));
- testApp.use(cookieParser(undefined,{decode:String}));
- testApp.get('/statusCode204', function(req,res) { res.status(204).end();});
- testApp.get('/text', function(req, res){ res.send('hello'); });
- testApp.get('/redirectToText', function(req, res){ res.status(302).set('Location', getTestURL('/text')).end(); });
- testApp.get('/json-valid', function(req, res){ res.json({a:1}); });
- testApp.get('/json-invalid', function(req, res){ res.set('Content-Type', 'application/json').send("{a:1"); });
- testApp.get('/headersInspect', function(req, res){ res.set('x-test-header', 'bar').send("a"); });
- testApp.get('/timeout', function(req, res){
- setTimeout(function() {
- res.send('hello');
- }, 10000);
- });
- testApp.get('/timeout50ms', function(req, res){
- setTimeout(function() {
- res.send('hello');
- }, 50);
- });
- testApp.get('/checkCookie', function(req, res){
- res.send(req.cookies);
- });
- testApp.get('/setCookie', function(req, res){
- res.cookie('data','hello');
- res.send("");
- });
- testApp.get('/authenticate', function(req, res){
- let result;
- let authHeader = req.headers['authorization'];
- if (/^Basic/.test(authHeader)) {
- result = auth.parse(authHeader);
- result.user = result.name;
- } else if (/^Bearer/.test(authHeader)) {
- result = {
- token: authHeader.substring(7)
- }
- }
- res.json(result);
- });
- testApp.get('/proxyAuthenticate', function(req, res){
- // var user = auth.parse(req.headers['proxy-authorization']);
- var result = {
- //user: user.name,
- //pass: user.pass,
- headers: req.headers
- };
- res.json(result);
- });
- testApp.post('/postInspect', function(req,res) {
- var result = {
- body: req.body.toString(),
- headers: req.headers
- };
- res.json(result);
- });
- testApp.put('/putInspect', function(req,res) {
- var result = {
- body: req.body.toString(),
- headers: req.headers
- };
- res.json(result);
- });
- testApp.delete('/deleteInspect', function(req,res) { res.status(204).end();});
- testApp.head('/headInspect', function(req,res) { res.status(204).end();});
- testApp.patch('/patchInspect', function(req,res) {
- var result = {
- body: req.body.toString(),
- headers: req.headers
- };
- res.json(result);
- });
- testApp.trace('/traceInspect', function(req,res) {
- var result = {
- body: req.body.toString(),
- headers: req.headers
- };
- res.json(result);
- });
- testApp.options('/*', function(req,res) {
- res.status(200).end();
- });
- testApp.get('/redirectToSameDomain', function(req, res) {
- var key = req.headers.host + req.url;
- receivedCookies[key] = req.cookies;
- res.cookie('redirectToSameDomainCookie','same1');
- res.redirect(getTestURL('/redirectReturn'));
- });
- testApp.get('/redirectToDifferentDomain', function(req, res) {
- var key = req.headers.host + req.url;
- receivedCookies[key] = req.cookies;
- res.cookie('redirectToDifferentDomain','different1');
- res.redirect(getDifferentTestURL('/redirectReturn'));
- });
- testApp.get('/redirectMultipleTimes', function(req, res) {
- var key = req.headers.host + req.url;
- receivedCookies[key] = req.cookies;
- res.cookie('redirectMultipleTimes','multiple1');
- res.redirect(getTestURL('/redirectToDifferentDomain'));
- });
- testApp.get('/redirectReturn', function(req, res) {
- var key = req.headers.host + req.url;
- receivedCookies[key] = req.cookies;
- res.cookie('redirectReturn','return1');
- res.status(200).end();
- });
- testApp.get('/getQueryParams', function(req,res) {
- res.json({
- query:req.query,
- url: req.originalUrl
- });
- })
- testApp.get('/returnError/:code', function(req,res) {
- res.status(parseInt(req.params.code)).json({gotError:req.params.code});
- })
-
- testApp.get('/rawHeaders', function(req,res) {
- const result = {};
- for (let i=0;i {
- testProxyServer.stop(() => {
- testProxyServerAuth.stop(() => {
- testSslServer.stop(() => {
- testSslClientServer.stop(() => {
- helper.stopServer(done);
- })
- });
- });
- });
- });
- });
-
- beforeEach(function() {
- preEnvHttpProxyLowerCase = process.env.http_proxy;
- preEnvHttpProxyUpperCase = process.env.HTTP_PROXY;
- preEnvNoProxyLowerCase = process.env.no_proxy;
- preEnvNoProxyUpperCase = process.env.NO_PROXY;
- process.env.no_proxy = 'localhost';
- process.env.NO_PROXY = 'localhost';
- });
-
- afterEach(function() {
- process.env.http_proxy = preEnvHttpProxyLowerCase;
- process.env.HTTP_PROXY = preEnvHttpProxyUpperCase;
- // On Windows, if environment variable of NO_PROXY that includes lower cases
- // such as No_Proxy is replaced with NO_PROXY.
- process.env.no_proxy = preEnvNoProxyLowerCase;
- process.env.NO_PROXY = preEnvNoProxyUpperCase;
- if (preEnvHttpProxyLowerCase == undefined) {
- delete process.env.http_proxy;
- }
- if (preEnvHttpProxyUpperCase == undefined) {
- delete process.env.HTTP_PROXY;
- }
- if (preEnvNoProxyLowerCase == undefined) {
- delete process.env.no_proxy;
- }
- if (preEnvNoProxyUpperCase == undefined) {
- delete process.env.NO_PROXY;
- }
- helper.unload();
- });
-
- describe('request', function() {
- it('should get plain text content', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- msg.redirectList.length.should.equal(0);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should get JSON content', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/json-valid')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload',{a:1});
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-type').which.startWith('application/json');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should send the payload as the body of a POST as application/json', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.body.should.eql('{"foo":"abcde"}');
- msg.payload.headers.should.have.property('content-type').which.startWith('application/json');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-type').which.startWith('application/json');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:{foo:"abcde"}});
- });
- });
-
- it('should send a payload of 0 as the body of a POST as text/plain', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.body.should.eql('0');
- msg.payload.headers.should.have.property('content-length','1');
- msg.payload.headers.should.have.property('content-type').which.startWith('text/plain');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:0, headers: { 'content-type': 'text/plain'}});
- });
- });
-
- it('should send an Object payload as the body of a POST', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.body.should.eql('{"foo":"abcde"}');
- msg.payload.headers.should.have.property('content-type').which.startWith('text/plain');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-type').which.startWith('application/json');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:{foo:"abcde"}, headers: { 'content-type': 'text/plain'}});
- });
- });
-
- it('should send a Buffer as the body of a POST', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.body.should.eql('hello');
- msg.payload.headers.should.have.property('content-type').which.startWith('text/plain');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-type').which.startWith('application/json');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:Buffer.from('hello'), headers: { 'content-type': 'text/plain'}});
- });
- });
-
- it('should send form-based request', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.body.should.equal("foo=1%202%203&bar=");
- msg.payload.should.have.property('headers');
- msg.payload.headers.should.have.property('content-type','application/x-www-form-urlencoded');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:{foo:'1 2 3', bar:''}, headers: { 'content-type': 'application/x-www-form-urlencoded'}});
- });
- });
-
- it('should send PUT request', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"PUT",ret:"obj",url:getTestURL('/putInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.body.should.eql('foo');
- msg.payload.headers.should.have.property('content-type').which.startWith('text/plain');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-type').which.startWith('application/json');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", headers: { 'content-type': 'text/plain'}});
- });
- });
-
- it('should send DELETE request', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"DELETE",ret:"obj",url:getTestURL('/deleteInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','');
- msg.should.have.property('statusCode',204);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:{foo:"abcde"}});
- });
- });
-
- it('should send HEAD request', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"use",ret:"txt",url:getTestURL('/headInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','');
- msg.should.have.property('statusCode',204);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", method:"head"});
- });
- });
-
- it('should send PATCH request', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"PATCH",ret:"obj",url:getTestURL('/patchInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.body.should.eql('foo');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('etag');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", headers: { 'content-type': 'text/plain'}});
- });
- });
-
- it('should send OPTIONS request', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"use",ret:"obj",url:getTestURL('/*')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", method:"options"});
- });
- });
-
- it('should send TRACE request', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"use",ret:"obj",url:getTestURL('/traceInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.body.should.eql('foo');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", method:"trace", headers: { 'content-type': 'text/plain'}});
- });
- });
-
- it('should get Buffer content', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"bin",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-type');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should return plain text when JSON fails to parse', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/json-invalid')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload',"{a:1");
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-type').which.startWith('application/json');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should return the status code', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/statusCode204')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','');
- msg.should.have.property('statusCode',204);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should use msg.url', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", url:"/foo"});
- });
- });
-
- it('should output an error when URL is not provided', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:""},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var inError = false;
- n2.on("input", function(msg) {
- inError = true;
- });
- n1.receive({payload:"foo"});
- setTimeout(function() {
- if (inError) {
- done(new Error("no url allowed though"));
- } else {
- done();
- }
- },20);
- });
- });
-
- it('should allow the message to provide the url', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt"},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo",url:getTestURL('/text')});
- });
- });
-
- it('should allow the url to contain mustache placeholders', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/te{{placeholder}}')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo",placeholder:"xt"});
- });
- });
-
- it('should allow the url to be missing the http:// prefix', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/text').substring("http://".length)},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should reject non http:// schemes - node config', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:"ftp://foo"},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var inError = false;
- n2.on("input", function(msg) {
- inError = true;
- });
- n1.receive({payload:"foo"});
- setTimeout(function() {
- if (inError) {
- done(new Error("non http(s):// scheme allowed through"));
- } else {
- done();
- }
- },20);
- });
- });
-
- it('should reject non http:// schemes - msg.url', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt"},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var inError = false;
- n2.on("input", function(msg) {
- inError = true;
- });
- n1.receive({payload:"foo",url:"ftp://foo"});
- setTimeout(function() {
- if (inError) {
- done(new Error("non http(s):// scheme allowed through"));
- } else {
- done();
- }
- },20);
- });
- });
-
- it('should use msg.method', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", method:"POST"});
- });
- });
-
- it('should allow the message to provide the method', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"use",ret:"txt",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo",method:"get"});
- });
- });
-
- it('should receive msg.responseUrl', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.should.have.property('responseUrl', getTestURL('/text'));
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should receive msg.responseUrl when redirected', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/redirectToText')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('responseUrl', getTestURL('/text'));
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should prevent following redirect when msg.followRedirects is false', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/redirectToText')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',302);
- msg.should.have.property('responseUrl', getTestURL('/redirectToText'));
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo",followRedirects:false});
- });
- });
-
- it('should output an error when request timeout occurred', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/timeout')},
- {id:"n2", type:"helper"}];
- var timeout = RED.settings.httpRequestTimeout;
- RED.settings.httpRequestTimeout = 50;
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode');
- /TIMEDOUT/.test(msg.statusCode).should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == 'http request';
- });
- logEvents.should.have.length(1);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().ERROR, id:'n1',type:'http request',msg:'common.notification.errors.no-response', timestamp:tstmp, path:"global"});
- done();
- } catch(err) {
- done(err);
- } finally {
- RED.settings.httpRequestTimeout = timeout;
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should output an error when request timeout occurred when set via msg.requestTimeout', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/timeout')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode');
- /TIMEDOUT/.test(msg.statusCode).should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == 'http request';
- });
- logEvents.should.have.length(1);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().ERROR, id:'n1',type:'http request',msg:'common.notification.errors.no-response', timestamp:tstmp, path:"global"});
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", requestTimeout: 50});
- });
- });
- it('should show a warning if msg.requestTimeout is not a number', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode', 200);
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == 'http request';
- });
- logEvents.should.have.length(2);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnan', timestamp:tstmp, path:"global"});
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", requestTimeout: "foo"});
- });
- });
- it('should show a warning if msg.requestTimeout is negative', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode', 200);
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == 'http request';
- });
- logEvents.should.have.length(2);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnegative', timestamp:tstmp, path:"global"});
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", requestTimeout: -4});
- });
- });
- it('should show a warning if msg.requestTimeout is set to 0', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode', 200);
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == 'http request';
- });
- logEvents.should.have.length(2);
- var tstmp = logEvents[0][0].timestamp;
- logEvents[0][0].should.eql({level:helper.log().WARN, id:'n1',type:'http request',msg:'httpin.errors.timeout-isnegative', timestamp:tstmp, path:"global"});
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", requestTimeout: 0});
- });
- });
- it('should pass if response time is faster than timeout set via msg.requestTimeout', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/timeout50ms')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", requestTimeout: 100});
- });
- });
- it('should append query params to url - obj', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",paytoqs:true,ret:"obj",url:getTestURL('/getQueryParams')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload',{
- query:{a:'1',b:'2',c:'3'},
- url: '/getQueryParams?a=1&b=2&c=3'
- });
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:{a:1,b:2,c:3}});
- });
- });
-
- it('should send a msg for non-2xx response status - 400', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/returnError/400')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload',{ gotError: '400' });
- msg.should.have.property('statusCode',400);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({});
- })
- });
- it('should send a msg for non-2xx response status - 404', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/returnError/404')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload',{ gotError: '404' });
- msg.should.have.property('statusCode',404);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({});
- })
- });
- it('should send a msg for non-2xx response status - 500', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/returnError/500')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload',{ gotError: '500' });
- msg.should.have.property('statusCode',500);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({});
- })
- });
-
- it('should encode the url to handle special characters', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj"},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload',{
- query:{ a: 'b', c:[ 'T24,0°|H80%|W S8,3m/s' ] },
- url: '/getQueryParams?a=b&c[0].Text=T24,0%C2%B0|H80%25|W%20S8,3m/s'
- });
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({url: getTestURL('/getQueryParams')+"?a=b&c[0].Text=T24,0°|H80%|W%20S8,3m/s"});
- });
- })
- });
-
- describe('HTTP header', function() {
- it('should receive cookie', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/setCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.responseCookies.should.have.property('data');
- msg.responseCookies.data.should.have.property('value','hello');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should send cookie with string', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data','abc');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{data:'abc'}});
- });
- });
-
- it('should send multiple cookies with string', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data','abc');
- msg.payload.should.have.property('foo','bar');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{data:'abc',foo:'bar'}});
- });
- });
-
- it('should send cookie with object data', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data','abc');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{data:{value:'abc'}}});
- });
- });
-
- it('should send multiple cookies with object data', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data','abc');
- msg.payload.should.have.property('foo','bar');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{data:{value:'abc'},foo:{value:'bar'}}});
- });
- });
-
- it('should encode cookie value', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var value = ';,/?:@ &=+$#';
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data',encodeURIComponent(value));
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{data:value}});
- });
- });
-
- it('should encode cookie object', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var value = ';,/?:@ &=+$#';
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data',encodeURIComponent(value));
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{data:{value:value, encode:true}}});
- });
- });
-
- it('should not encode cookie when encode option is false', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var value = '!#$%&\'()*+-./:<>?@[]^_`{|}~';
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data',value);
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{data:{value:value, encode:false}}});
- });
- });
-
- it('should send cookie by msg.headers', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data','abc');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{boo:'123'}, headers:{'cookie':'data=abc'}});
- });
- });
-
- it('should send multiple cookies by msg.headers', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/checkCookie')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property('data','abc');
- msg.payload.should.have.property('foo','bar');
- msg.should.have.property('statusCode',200);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", cookies:{boo:'123'}, headers:{'cookie':'data=abc; foo=bar;'}});
- });
- });
-
- it('should convert all HTTP headers into lower case', function(done) {
- // This is a bad test. Express lower-cases headers in the `req.headers` object,
- // so this is actually testing express, not the original request.
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('headers');
- msg.payload.headers.should.have.property('content-type').which.startWith('text/plain');
- msg.payload.headers.should.have.property('content-length', "3");
- msg.payload.headers.should.have.property('if-modified-since','Sun, 01 Jun 2000 00:00:00 GMT');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", headers: { 'Content-Type':'text/plain', 'Content-Length': "3", 'If-Modified-Since':'Sun, 01 Jun 2000 00:00:00 GMT'}});
- });
- });
-
- it('should keep HTTP header case as provided by the user', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/rawHeaders')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('headers');
- msg.payload.headers.should.have.property('Content-Type').which.startWith('text/plain');
- msg.payload.headers.should.have.property('X-Test-HEAD', "foo");
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", headers: { 'Content-Type':'text/plain', "X-Test-HEAD": "foo"}});
- });
- });
- it('should receive HTTP header', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getTestURL('/headersInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.headers.should.have.property('x-test-header','bar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should ignore unmodified x-node-red-request-node header', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.headers.should.have.property('content-type').which.startWith('application/json');
- msg.payload.headers.should.not.have.property('x-node-red-request-node');
- done();
- } catch(err) {
- done(err);
- }
- });
- // Pass in a headers property with an unmodified x-node-red-request-node hash
- // This should cause the node to ignore the headers
-
- var headers = { 'content-type': 'text/plain' };
- headers['x-node-red-request-node'] = require("hash-sum")(headers);
-
- n1.receive({payload:{foo:"bar"}, headers: headers});
- });
- });
-
- it('should use modified msg.headers property', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.headers.should.have.property('content-type').which.startWith('text/plain');
- msg.payload.headers.should.not.have.property('x-node-red-request-node');
- done();
- } catch(err) {
- done(err);
- }
- });
- // Pass in a headers property with a x-node-red-request-node hash that doesn't match the contents
- // This should cause the node to use the headers
- n1.receive({payload:{foo:"bar"}, headers: { 'content-type': 'text/plain', "x-node-red-request-node":"INVALID_SUM"}});
- });
- });
- });
-
- describe('protocol', function() {
- it('should use msg.rejectUnauthorized', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getSslTestURL('/text')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n2 = helper.getNode("n2");
- var n1 = helper.getNode("n1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- msg.should.have.property('responseUrl').which.startWith('https://');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo", rejectUnauthorized: false});
- });
- });
-
- it('should use tls-config', function(done) {
- var flow = [
- {id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getSslTestURLWithoutProtocol('/text'),tls:"n3"},
- {id:"n2", type:"helper"},
- {id:"n3", type:"tls-config", cert:"test/resources/ssl/server.crt", key:"test/resources/ssl/server.key", ca:"", verifyservercert:false}];
- var testNodes = [httpRequestNode, tlsNode];
- helper.load(testNodes, flow, function() {
- var n3 = helper.getNode("n3");
- var n2 = helper.getNode("n2");
- var n1 = helper.getNode("n1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- msg.should.have.property('responseUrl').which.startWith('https://');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should use tls-config and verify serverCert', function(done) {
- var flow = [
- {id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getSslTestURL('/text'),tls:"n3"},
- {id:"n2", type:"helper"},
- {id:"n3", type:"tls-config", cert:"test/resources/ssl/server.crt", key:"test/resources/ssl/server.key", ca:"test/resources/ssl/server.crt", verifyservercert:true}];
- var testNodes = [httpRequestNode, tlsNode];
- helper.load(testNodes, flow, function() {
- var n3 = helper.getNode("n3");
- var n2 = helper.getNode("n2");
- var n1 = helper.getNode("n1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- msg.should.have.property('responseUrl').which.startWith('https://');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should use tls-config and send client cert', function(done) {
- var flow = [
- {id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"txt",url:getSslClientTestURL('/getClientCert'),tls:"n3"},
- {id:"n2", type:"helper"},
- {id:"n3", type:"tls-config", cert:"test/resources/ssl/server.crt", key:"test/resources/ssl/server.key", ca:"test/resources/ssl/server.crt", verifyservercert:false}];
- var testNodes = [httpRequestNode,tlsNode];
- helper.load(testNodes, flow, function() {
- var n3 = helper.getNode("n3");
- var n2 = helper.getNode("n2");
- var n1 = helper.getNode("n1");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload','hello');
- msg.should.have.property('statusCode',200);
- msg.should.have.property('headers');
- msg.headers.should.have.property('content-length',''+('hello'.length));
- msg.headers.should.have.property('content-type').which.startWith('text/html');
- msg.should.have.property('responseUrl').which.startWith('https://');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- })
- });
-
- //Removing HTTP Proxy testcases as GOT + Proxy_Agent doesn't work with mock'd proxy
- /* */
- it('should use http_proxy', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- deleteProxySetting();
- process.env.http_proxy = "http://localhost:" + testProxyPort;
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('headers');
- //msg.payload.headers.should.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- /* */
-
- it('should use http_proxy when environment variable is invalid', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- deleteProxySetting();
- process.env.http_proxy = "invalidvalue";
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('headers');
- msg.payload.headers.should.not.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- // Remove HTTP-Proxy Authentication tests
- /* */
- it('should use HTTP_PROXY', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- deleteProxySetting();
- process.env.HTTP_PROXY = "http://localhost:" + testProxyPort;
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('headers');
- //msg.payload.headers.should.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- /* */
-
- it('should use no_proxy', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- deleteProxySetting();
- process.env.http_proxy = "http://localhost:" + testProxyPort;
- process.env.no_proxy = "foo,localhost";
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.headers.should.not.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should use NO_PROXY', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect')},
- {id:"n2", type:"helper"}];
- deleteProxySetting();
- process.env.HTTP_PROXY = "http://localhost:" + testProxyPort;
- process.env.NO_PROXY = "foo,localhost";
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.headers.should.not.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- // Remove HTTP-Proxy Authentication tests
- /* */
- it('should use http-proxy-config', function(done) {
- var flow = [
- {id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect'),proxy:"n3"},
- {id:"n2",type:"helper"},
- {id:"n3",type:"http proxy",url:"http://localhost:" + testProxyPort}
- ];
- var testNode = [ httpRequestNode, httpProxyNode ];
- deleteProxySetting();
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('headers');
- //msg.payload.headers.should.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- /* */
-
- it('should not use http-proxy-config when invalid url is specified', function(done) {
- var flow = [
- {id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect'),proxy:"n3"},
- {id:"n2", type:"helper"},
- {id:"n3",type:"http proxy",url:"invalidvalue"}
- ];
- var testNode = [ httpRequestNode, httpProxyNode ];
- deleteProxySetting();
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('headers');
- msg.payload.headers.should.not.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should use http-proxy-config when valid noproxy is specified', function(done) {
- var flow = [
- {id:"n1",type:"http request",wires:[["n2"]],method:"POST",ret:"obj",url:getTestURL('/postInspect'),proxy:"n3"},
- {id:"n2", type:"helper"},
- {id:"n3",type:"http proxy",url:"http://localhost:" + testProxyPort,noproxy:["foo","localhost"]}
- ];
- var testNode = [ httpRequestNode, httpProxyNode ];
- deleteProxySetting();
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.headers.should.not.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- });
- describe('authentication', function() {
-
- it('should authenticate on server - basic', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/authenticate')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.credentials = {user:'userfoo', password:'passwordfoo'};
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('user', 'userfoo');
- msg.payload.should.have.property('pass', 'passwordfoo');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- it('should authenticate on server - basic', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/authenticate')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.credentials = {user:'foo@example.com', password:'passwordfoo'};
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('user', 'foo@example.com');
- msg.payload.should.have.property('pass', 'passwordfoo');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- it('should authenticate on server - bearer', function(done) {
- var flow = [{id:"n1",type:"http request",wires:[["n2"]],method:"GET",ret:"obj",authType:"bearer", url:getTestURL('/authenticate')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.credentials = {password:'passwordfoo'};
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- msg.payload.should.have.property('token', 'passwordfoo');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- // Removed the Proxy Tests until a new mock proxy can be replaced with
- // one that supports HTTP Connect verb
- /* */
- it('should authenticate on proxy server', function(done) {
- var flow = [{id:"n1",type:"http request", wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/proxyAuthenticate')},
- {id:"n2", type:"helper"}];
- deleteProxySetting();
- process.env.http_proxy = "http://foouser:barpassword@localhost:" + testProxyAuthPort;
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- //msg.payload.should.have.property('user', 'foouser');
- //msg.payload.should.have.property('pass', 'barpassword');
- msg.payload.should.have.property('headers');
- //msg.payload.headers.should.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- /*
- it('should output an error when proxy authentication was failed', function(done) {
- var flow = [{id:"n1",type:"http request", wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/proxyAuthenticate')},
- {id:"n2", type:"helper"}];
- deleteProxySetting();
- process.env.http_proxy = "http://xxxuser:barpassword@localhost:" + testProxyAuthPort;
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',407);
- msg.headers.should.have.property('proxy-authenticate', 'BASIC realm="proxy"');
- msg.payload.should.have.property('headers');
- //msg.payload.headers.should.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- */
- it('should authenticate on proxy server(http-proxy-config)', function(done) {
- var flow = [
- {id:"n1",type:"http request", wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/proxyAuthenticate'),proxy:"n3"},
- {id:"n2", type:"helper"},
- {id:"n3",type:"http proxy",url:"http://localhost:" + testProxyAuthPort}
- ];
- var testNode = [ httpRequestNode, httpProxyNode ];
- deleteProxySetting();
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- n3.credentials = {username:'foouser', password:'barpassword'};
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',200);
- // msg.payload.should.have.property('user', 'foouser');
- // msg.payload.should.have.property('pass', 'barpassword');
- msg.payload.should.have.property('headers');
- //msg.payload.headers.should.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- /*
- it('should output an error when proxy authentication was failed(http-proxy-config)', function(done) {
- var flow = [
- {id:"n1",type:"http request", wires:[["n2"]],method:"GET",ret:"obj",url:getTestURL('/proxyAuthenticate'),proxy:"n3"},
- {id:"n2", type:"helper"},
- {id:"n3",type:"http proxy",url:"http://@localhost:" + testProxyAuthPort}
- ];
- var testNode = [ httpRequestNode, httpProxyNode ];
- deleteProxySetting();
- helper.load(testNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var n3 = helper.getNode("n3");
- n3.credentials = {username:'xxxuser', password:'barpassword'};
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('statusCode',407);
- msg.headers.should.have.property('proxy-authenticate', 'BASIC realm="proxy"');
- msg.payload.should.have.property('headers');
- //msg.payload.headers.should.have.property('x-testproxy-header','foobar');
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
- */
-
- });
-
- describe('file-upload', function() {
- it('should upload a file', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'POST',ret:'obj',url:getTestURL('/file-upload')},
- {id:"n2", type:"helper"}];
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property("body",{"other":"123"});
- msg.payload.should.have.property("files");
- msg.payload.files.should.have.length(1);
- msg.payload.files[0].should.have.property('fieldname','file');
- msg.payload.files[0].should.have.property('originalname','file.txt');
- msg.payload.files[0].should.have.property('buffer',{"type":"Buffer","data":[72,101,108,108,111,32,87,111,114,108,100]});
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({
- headers: {
- 'content-type':'multipart/form-data'
- },
- payload: {
- file: {
- value: Buffer.from("Hello World"),
- options: {
- filename: "file.txt"
- }
- },
- other: 123
- }
- });
- });
- })
- })
-
- describe('redirect-cookie', function() {
- it('should send cookies to the same domain when redirected(no cookies)', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToSameDomain')},
- {id:"n2", type:"helper"}];
- receivedCookies = {};
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
- var cookies2 = receivedCookies['localhost:'+testPort+'/redirectReturn'];
- if (cookies1 && Object.keys(cookies1).length != 0) {
- done(new Error('Invalid cookie(path:/rediectToSame)'));
- return;
- }
- if ((cookies2 && Object.keys(cookies2).length != 1) ||
- cookies2['redirectToSameDomainCookie'] !== 'same1') {
- done(new Error('Invalid cookie(path:/rediectReurn)'));
- return;
- }
- var redirect1 = msg.redirectList[0];
- redirect1.location.should.equal('http://localhost:'+testPort+'/redirectReturn');
- redirect1.cookies.redirectToSameDomainCookie.Path.should.equal('/');
- redirect1.cookies.redirectToSameDomainCookie.value.should.equal('same1');
- done();
- } catch(err) { done(err)}
- });
- n1.receive({});
- });
- });
- it('should not send cookies to the different domain when redirected(no cookies)', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToDifferentDomain')},
- {id:"n2", type:"helper"}];
- receivedCookies = {};
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
- var cookies2 = receivedCookies['127.0.0.1:'+testPort+'/redirectReturn'];
- if (cookies1 && Object.keys(cookies1).length != 0) {
- done(new Error('Invalid cookie(path:/rediectToDiffer)'));
- return;
- }
- if (cookies2 && Object.keys(cookies2).length != 0) {
- done(new Error('Invalid cookie(path:/rediectReurn)'));
- return;
- }
- var redirect1 = msg.redirectList[0];
- redirect1.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn');
- redirect1.cookies.redirectToDifferentDomain.Path.should.equal('/');
- redirect1.cookies.redirectToDifferentDomain.value.should.equal('different1');
- done();
- });
- n1.receive({});
- });
- });
- it('should send cookies to the same domain when redirected(msg.cookies)', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToSameDomain')},
- {id:"n2", type:"helper"}];
- receivedCookies = {};
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
- var cookies2 = receivedCookies['localhost:'+testPort+'/redirectReturn'];
- if ((cookies1 && Object.keys(cookies1).length != 1) ||
- cookies1['requestCookie'] !== 'request1') {
- done(new Error('Invalid cookie(path:/rediectToSame)'));
- return;
- }
- if ((cookies2 && Object.keys(cookies2).length != 2) ||
- cookies1['requestCookie'] !== 'request1' ||
- cookies2['redirectToSameDomainCookie'] !== 'same1') {
- done(new Error('Invalid cookie(path:/rediectReurn)'));
- return;
- }
- var redirect1 = msg.redirectList[0];
- redirect1.location.should.equal('http://localhost:'+testPort+'/redirectReturn');
- redirect1.cookies.redirectToSameDomainCookie.Path.should.equal('/');
- redirect1.cookies.redirectToSameDomainCookie.value.should.equal('same1');
- done();
- });
- n1.receive({
- cookies: { requestCookie: 'request1' }
- });
- });
- });
- it('should not send cookies to the different domain when redirected(msg.cookies)', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToDifferentDomain')},
- {id:"n2", type:"helper"}];
- receivedCookies = {};
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToDifferentDomain'];
- var cookies2 = receivedCookies['127.0.0.1:'+testPort+'/redirectReturn'];
- if ((cookies1 && Object.keys(cookies1).length != 1) ||
- cookies1['requestCookie'] !== 'request1') {
- done(new Error('Invalid cookie(path:/rediectToDiffer)'));
- return;
- }
- if (cookies2 && Object.keys(cookies2).length != 0) {
- done(new Error('Invalid cookie(path:/rediectReurn)'));
- return;
- }
- var redirect1 = msg.redirectList[0];
- redirect1.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn');
- redirect1.cookies.redirectToDifferentDomain.Path.should.equal('/');
- redirect1.cookies.redirectToDifferentDomain.value.should.equal('different1');
- done();
- });
- n1.receive({
- cookies: { requestCookie: 'request1' }
- });
- });
- });
- it('should send cookies to the same domain when redirected(msg.headers.cookie)', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToSameDomain')},
- {id:"n2", type:"helper"}];
- receivedCookies = {};
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToSameDomain'];
- var cookies2 = receivedCookies['localhost:'+testPort+'/redirectReturn'];
- if ((cookies1 && Object.keys(cookies1).length != 1) ||
- cookies1['requestCookie'] !== 'request1') {
- done(new Error('Invalid cookie(path:/rediectToSame)'));
- return;
- }
- if ((cookies2 && Object.keys(cookies2).length != 2) ||
- cookies1['requestCookie'] !== 'request1' ||
- cookies2['redirectToSameDomainCookie'] !== 'same1') {
- done(new Error('Invalid cookie(path:/rediectReurn)'));
- return;
- }
- var redirect1 = msg.redirectList[0];
- redirect1.location.should.equal('http://localhost:'+testPort+'/redirectReturn');
- redirect1.cookies.redirectToSameDomainCookie.Path.should.equal('/');
- redirect1.cookies.redirectToSameDomainCookie.value.should.equal('same1');
- done();
- });
- n1.receive({
- headers: { cookie: 'requestCookie=request1' }
- });
- });
- });
- it('should not send cookies to the different domain when redirected(msg.headers.cookie)', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectToDifferentDomain')},
- {id:"n2", type:"helper"}];
- receivedCookies = {};
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- var cookies1 = receivedCookies['localhost:'+testPort+'/redirectToDifferentDomain'];
- var cookies2 = receivedCookies['127.0.0.1:'+testPort+'/redirectReturn'];
- if ((cookies1 && Object.keys(cookies1).length != 1) ||
- cookies1['requestCookie'] !== 'request1') {
- done(new Error('Invalid cookie(path:/rediectToDiffer)'));
- return;
- }
- if (cookies2 && Object.keys(cookies2).length != 0) {
- done(new Error('Invalid cookie(path:/rediectReurn)'));
- return;
- }
- var redirect1 = msg.redirectList[0];
- redirect1.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn');
- redirect1.cookies.redirectToDifferentDomain.Path.should.equal('/');
- redirect1.cookies.redirectToDifferentDomain.value.should.equal('different1');
- done();
- });
- n1.receive({
- headers: { cookie: 'requestCookie=request1' }
- });
- });
- });
- it('should return all redirect information when redirected multiple times', function(done) {
- var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:getTestURL('/redirectMultipleTimes')},
- {id:"n2", type:"helper"}];
- receivedCookies = {};
- helper.load(httpRequestNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- var redirect1 = msg.redirectList[0];
- redirect1.location.should.equal('http://localhost:'+testPort+'/redirectToDifferentDomain');
- redirect1.cookies.redirectMultipleTimes.Path.should.equal('/');
- redirect1.cookies.redirectMultipleTimes.value.should.equal('multiple1');
- var redirect2 = msg.redirectList[1];
- redirect2.location.should.equal('http://127.0.0.1:'+testPort+'/redirectReturn');
- redirect2.cookies.redirectToDifferentDomain.Path.should.equal('/');
- redirect2.cookies.redirectToDifferentDomain.value.should.equal('different1');
- done();
- });
- n1.receive({
- headers: { cookie: 'requestCookie=request1' }
- });
- });
- });
- });
-});
diff --git a/test/nodes/core/network/22-websocket_spec.js b/test/nodes/core/network/22-websocket_spec.js
deleted file mode 100644
index 995248279..000000000
--- a/test/nodes/core/network/22-websocket_spec.js
+++ /dev/null
@@ -1,568 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var ws = require("ws");
-var should = require("should");
-var helper = require("node-red-node-test-helper");
-var websocketNode = require("nr-test-utils").require("@node-red/nodes/core/network/22-websocket.js");
-
-var sockets = [];
-
-function getWsUrl(path) {
- return helper.url().replace(/http/, "ws") + path;
-}
-
-function createClient(listenerid) {
- return new Promise(function(resolve, reject) {
- var node = helper.getNode(listenerid);
- var url = getWsUrl(node.path);
- var sock = new ws(url);
- sockets.push(sock);
-
- sock.on("open", function() {
- resolve(sock);
- });
-
- sock.on("error", function(err) {
- reject(err);
- });
- });
-}
-
-function closeAll() {
- for (var i = 0; i < sockets.length; i++) {
- sockets[i].close();
- }
- sockets = [];
-}
-
-function getSocket(listenerid) {
- var node = helper.getNode(listenerid);
- return node.server;
-}
-
-describe('websocket Node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- closeAll();
- helper.unload();
- });
-
- describe('websocket-listener', function() {
- it('should load', function(done) {
- var flow = [{ id: "n1", type: "websocket-listener", path: "/ws" }];
- helper.load(websocketNode, flow, function() {
- helper.getNode("n1").should.have.property("path", "/ws");
- done();
- });
- });
-
- it('should be server', function(done) {
- var flow = [{ id: "n1", type: "websocket-listener", path: "/ws" }];
- helper.load(websocketNode, flow, function() {
- helper.getNode("n1").should.have.property('isServer', true);
- done();
- });
- });
-
- it('should handle wholemsg property', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "websocket-listener", path: "/ws2", wholemsg: "true" }];
- helper.load(websocketNode, flow, function() {
- helper.getNode("n1").should.have.property("wholemsg", false);
- helper.getNode("n2").should.have.property("wholemsg", true);
- done();
- });
- });
-
- it('should create socket', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "websocket in", server: "n1" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should close socket on delete', function(done) {
- var flow = [{ id: "n1", type: "websocket-listener", path: "/ws" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- sock.on("close", function(code, msg) {
- done();
- });
- helper.clearFlows();
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should receive data', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
- { id: "n3", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- helper.getNode("n3").on("input", function(msg) {
- msg.should.have.property("payload", "hello");
- done();
- });
- sock.send("hello");
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should receive wholemsg', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws", wholemsg: "true" },
- { id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
- { id: "n3", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- sock.send('{"text":"hello"}');
- helper.getNode("n3").on("input", function(msg) {
- msg.should.have.property("text", "hello");
- done();
- });
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should receive wholemsg when data not JSON', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws", wholemsg: "true" },
- { id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
- { id: "n3", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- sock.send('hello');
- helper.getNode("n3").on("input", function(msg) {
- msg.should.have.property("payload", "hello");
- done();
- });
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should receive wholemsg when data not object', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws", wholemsg: "true" },
- { id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
- { id: "n3", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- helper.getNode("n3").on("input", function(msg) {
- msg.should.have.property("payload", 123);
- done();
- });
- sock.send(123);
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should send', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "helper", wires: [["n3"]] },
- { id: "n3", type: "websocket out", server: "n1" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- sock.on("message", function(msg, flags) {
- msg.should.equal("hello");
- done();
- });
- helper.getNode("n2").send({
- payload: "hello"
- });
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should send wholemsg', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws", wholemsg: "true" },
- { id: "n2", type: "websocket out", server: "n1" },
- { id: "n3", type: "helper", wires: [["n2"]] }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- sock.on("message", function(msg, flags) {
- JSON.parse(msg).should.have.property("text", "hello");
- done();
- });
- helper.getNode("n3").send({
- text: "hello"
- });
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should do nothing if no payload', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "helper", wires: [["n3"]] },
- { id: "n3", type: "websocket out", server: "n1" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- logEvents.should.have.length(0);
- done();
- },100);
- helper.getNode("n2").send({topic: "hello"});
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should echo', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
- { id: "n3", type: "websocket out", server: "n1" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- sock.on("message", function(msg, flags) {
- msg.should.equal("hello");
- done();
- });
- sock.send("hello");
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should echo wholemsg', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws", wholemsg: "true" },
- { id: "n2", type: "websocket in", server: "n1", wires: [["n3"]] },
- { id: "n3", type: "websocket out", server: "n1" }];
- helper.load(websocketNode, flow, function() {
- createClient("n1").then(function(sock) {
- sock.on("message", function(msg, flags) {
- JSON.parse(msg).should.have.property("text", "hello");
- done();
- });
- sock.send('{"text":"hello"}');
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- it('should broadcast', function(done) {
- var flow = [
- { id: "n1", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "websocket out", server: "n1" },
- { id: "n3", type: "helper", wires: [["n2"]] }];
- helper.load(websocketNode, flow, function() {
- Promise.all([createClient("n1"), createClient("n1")]).then(function(socks) {
- var promises = [
- new Promise((resolve,reject) => {
- socks[0].on("message", function(msg, flags) {
- try {
- msg.should.equal("hello");
- resolve();
- } catch(err) {
- reject(err);
- }
- });
- }),
- new Promise((resolve,reject) => {
- socks[1].on("message", function(msg, flags) {
- try {
- msg.should.equal("hello");
- resolve();
- } catch(err) {
- reject(err);
- }
- });
- })
- ];
- helper.getNode("n3").send({
- payload: "hello"
- });
- return Promise.all(promises).then(() => {done()});
- }).catch(function(err) {
- done(err);
- });
- });
- });
- });
-
- describe('websocket-client', function() {
- it('should load', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws") }];
- helper.load(websocketNode, flow, function() {
- helper.getNode("n1").should.have.property('path', getWsUrl("/ws"));
- done();
- });
- });
-
- it('should not be server', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws") }];
- helper.load(websocketNode, flow, function() {
- helper.getNode("n1").should.have.property('isServer', false);
- done();
- });
- });
-
- it('should handle wholemsg property', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws") },
- { id: "n2", type: "websocket-client", path: getWsUrl("/ws"), wholemsg: "true" }];
- helper.load(websocketNode, flow, function() {
- helper.getNode("n1").should.have.property("wholemsg", false);
- helper.getNode("n2").should.have.property("wholemsg", true);
- done();
- });
- });
-
- it('should connect to server', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "websocket-client", path: getWsUrl("/ws") }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- done();
- });
-
- });
- });
-
- it('should close on delete', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n2", type: "websocket-client", path: getWsUrl("/ws") }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- sock.on('close', function() {
- done();
- });
- helper.getNode("n2").close();
- });
- });
- });
-
- it('should receive data', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws") },
- { id: "n2", type: "websocket in", client: "n1", wires: [["n3"]] },
- { id: "n3", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- sock.send('hello');
- });
-
- helper.getNode("n3").on("input", function(msg) {
- msg.should.have.property("payload", "hello");
- done();
- });
- });
- });
-
- it('should receive wholemsg data ', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws"), wholemsg: "true" },
- { id: "n2", type: "websocket in", client: "n1", wires: [["n3"]] },
- { id: "n3", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- sock.send('{"text":"hello"}');
- });
- helper.getNode("n3").on("input", function(msg) {
- msg.should.have.property("text", "hello");
- done();
- });
- });
- });
-
- it('should receive wholemsg when data not JSON', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws"), wholemsg: "true" },
- { id: "n2", type: "websocket in", client: "n1", wires: [["n3"]] },
- { id: "n3", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- sock.send('hello');
- });
- helper.getNode("n3").on("input", function(msg) {
- msg.should.have.property("payload", "hello");
- done();
- });
- });
- });
-
- it('should send', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws") },
- { id: "n2", type: "websocket out", client: "n1" },
- { id: "n3", type: "helper", wires: [["n2"]] }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- sock.on('message', function(msg) {
- msg.should.equal("hello");
- done();
- });
- });
- getSocket("n1").on("open", function() {
- helper.getNode("n3").send({
- payload: "hello"
- });
- });
- });
- });
-
- it('should send buffer', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws") },
- { id: "n2", type: "websocket out", client: "n1" },
- { id: "n3", type: "helper", wires: [["n2"]] }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- sock.on('message', function(msg) {
- Buffer.isBuffer(msg).should.be.true();
- msg.should.have.length(5);
- done();
- });
- });
- getSocket("n1").on("open", function() {
- helper.getNode("n3").send({
- payload: Buffer.from("hello")
- });
- });
- });
- });
-
- it('should send wholemsg', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws" },
- { id: "n1", type: "websocket-client", path: getWsUrl("/ws"), wholemsg: "true" },
- { id: "n2", type: "websocket out", client: "n1" },
- { id: "n3", type: "helper", wires: [["n2"]] }];
- helper.load(websocketNode, flow, function() {
- getSocket('server').on('connection', function(sock) {
- sock.on('message', function(msg) {
- JSON.parse(msg).should.have.property("text", "hello");
- done();
- });
- });
- getSocket("n1").on('open', function(){
- helper.getNode("n3").send({
- text: "hello"
- });
- });
- });
- });
-
- it('should NOT feedback more than once', function(done) {
- var flow = [
- { id: "server", type: "websocket-listener", path: "/ws", wholemsg: "true" },
- { id: "client", type: "websocket-client", path: getWsUrl("/ws"), wholemsg: "true" },
- { id: "n1", type: "websocket in", client: "client", wires: [["n2", "output"]] },
- { id: "n2", type: "websocket out", server: "server" },
- { id: "n3", type: "helper", wires: [["n2"]] },
- { id: "output", type: "helper" }];
- helper.load(websocketNode, flow, function() {
- getSocket('client').on('open', function() {
- helper.getNode("n3").send({
- payload: "ping"
- });
- });
- var acc = 0;
- helper.getNode("output").on("input", function(msg) {
- acc = acc + 1;
- });
- setTimeout( function() {
- acc.should.equal(1);
- helper.clearFlows();
- done();
- }, 250);
- });
- });
- });
-
- describe('websocket in node', function() {
- it('should report error if no server config', function(done) {
- var flow = [{ id: "n1", type: "websocket in", mode: "server" }];
- helper.load(websocketNode, flow, function() {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "websocket in";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("websocket.errors.missing-conf");
- done();
- });
- });
- });
-
- describe('websocket out node', function() {
- it('should report error if no server config', function(done) {
- var flow = [{ id: "n1", type: "websocket out", mode: "server" }];
- helper.load(websocketNode, flow, function() {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "websocket out";
- });
- //console.log(logEvents);
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("websocket.errors.missing-conf");
- done();
- });
- });
- });
-});
diff --git a/test/nodes/core/network/31-tcpin_spec.js b/test/nodes/core/network/31-tcpin_spec.js
deleted file mode 100644
index cbe7ced2a..000000000
--- a/test/nodes/core/network/31-tcpin_spec.js
+++ /dev/null
@@ -1,224 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var net = require("net");
-var should = require("should");
-var stoppable = require('stoppable');
-var helper = require("node-red-node-test-helper");
-
-var tcpinNode = require("nr-test-utils").require("@node-red/nodes/core/network/31-tcpin.js");
-
-
-describe('TCP in Node', function() {
- var port = 9200;
- var server = undefined;
- var server_port = 9300;
- var reply_data = undefined;
-
- beforeEach(function(done) {
- startServer(done);
- });
-
- afterEach(function(done) {
- helper.unload();
- stopServer(done);
- });
-
- function sendArray(sock, array) {
- if(array.length > 0) {
- sock.write(array[0], function() {
- sendArray(sock, array.slice(1));
- });
- }
- else {
- sock.end();
- }
- }
-
- function startServer(done) {
- server_port += 1;
- server = stoppable(net.createServer(function(c) {
- sendArray(c, reply_data);
- })).listen(server_port, "localhost", function(err) {
- done(err);
- });
- }
-
- function stopServer(done) {
- server.stop(done);
- }
-
- function send(wdata) {
- var opt = {port:port, host:"localhost"};
- var client = net.createConnection(opt, function() {
- client.write(wdata[0], function() {
- client.end();
- if(wdata.length > 1) {
- send(wdata.slice(1));
- }
- });
- });
- }
-
- function eql(v0, v1) {
- return((v0 === v1) || ((typeof v0) === 'object' && v0.equals(v1)));
- }
-
- function testTCP(flow, wdata, rdata, is_server, done) {
- if(is_server) {
- reply_data = wdata;
- }
- helper.load(tcpinNode, flow, function() {
- var n2 = helper.getNode("n2");
- var rcount = 0;
- n2.on("input", function(msg) {
- if(eql(msg.payload, rdata[rcount])) {
- rcount++;
- }
- else {
- should.fail();
- }
- if(rcount === rdata.length) {
- done();
- }
- });
- if(!is_server) {
- send(wdata);
- }
- });
- }
-
- function testTCP0(flow, wdata, rdata, done) {
- testTCP(flow, wdata, rdata, false, done);
- }
-
- function testTCP1(flow, wdata, rdata, done) {
- testTCP(flow, wdata, rdata, true, done);
- }
-
- it('should recv data (Stream/Buffer)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo"], [Buffer("foo")], done);
- });
-
- it('should recv data (Stream/String/Delimiter:\\n)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo\nbar"], ["foo", "bar"], done);
- });
-
- it('should recv data (Stream/String/No delimiter)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo\nbar"], ["foo\nbar"], done);
- });
-
- it('should recv data (Stream/Base64)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo"], [Buffer("foo").toString('base64')], done);
- });
-
- it('should recv data (Single/Buffer)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"single", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo"], [Buffer("foo")], done);
- });
-
- it('should recv data (Single/String)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"single", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo\nbar\nbaz"], ["foo\nbar\nbaz"], done);
- });
-
- it('should recv data (Stream/Base64)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"single", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo"], [Buffer("foo").toString('base64')], done);
- });
-
- it('should recv multiple data (Stream/Buffer)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo", "bar"], [Buffer("foo"), Buffer("bar")], done);
- });
-
- it('should recv multiple data (Stream/String/Delimiter:\\n)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo", "bar\nbaz"], ["foo", "bar", "baz"], done);
- });
-
- it('should recv multiple data (Stream/String/No delimiter)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP0(flow, ["foo", "bar\nbaz"], ["foo", "bar\nbaz"], done);
- });
-
- it('should recv multiple data (Stream/Base64)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"server", host:"localhost", port:port, datamode:"stream", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- var wdata = ["foo", "bar"];
- var rdata = wdata.map(function(x) {
- return Buffer(x).toString('base64');
- });
- testTCP0(flow, wdata, rdata, done);
- });
-
- it('should connect & recv data (Stream/Buffer)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP1(flow, ["foo"], [Buffer("foo")], done);
- });
-
- it('should connect & recv data (Stream/String/Delimiter:\\n)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP1(flow, ["foo\nbar"], ["foo", "bar"], done);
- });
-
- it('should connect & recv data (Stream/String/No delimiter)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"utf8", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP1(flow, ["foo\nbar"], ["foo\nbar"], done);
- });
-
- it('should connect & recv data (Stream/Base64)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"stream", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP1(flow, ["foo"], [Buffer("foo").toString('base64')], done);
- });
-
- it('should connect & recv data (Single/Buffer)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"single", datatype:"buffer", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP1(flow, ["foo"], [Buffer("foo")], done);
- });
-
- it('should connect & recv data (Single/String)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"single", datatype:"utf8", newline:"\n", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP1(flow, ["foo\nbar\nbaz"], ["foo\nbar\nbaz"], done);
- });
-
- it('should connect & recv data (Stream/Base64)', function(done) {
- var flow = [{id:"n1", type:"tcp in", server:"client", host:"localhost", port:server_port, datamode:"single", datatype:"base64", newline:"", topic:"", base64:false, wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP1(flow, ["foo"], [Buffer("foo").toString('base64')], done);
- });
-
-});
diff --git a/test/nodes/core/network/31-tcprequest_spec.js b/test/nodes/core/network/31-tcprequest_spec.js
deleted file mode 100644
index dc0755c1b..000000000
--- a/test/nodes/core/network/31-tcprequest_spec.js
+++ /dev/null
@@ -1,301 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var net = require("net");
-var should = require("should");
-var stoppable = require('stoppable');
-var helper = require("node-red-node-test-helper");
-var tcpinNode = require("nr-test-utils").require("@node-red/nodes/core/network/31-tcpin.js");
-var RED = require("nr-test-utils").require("node-red/lib/red.js");
-
-
-describe('TCP Request Node', function() {
- var server = undefined;
- var port = 9000;
-
- function startServer(done) {
- port += 1;
- server = stoppable(net.createServer(function(c) {
- c.on('data', function(data) {
- var rdata = "ACK:"+data.toString();
- c.write(rdata);
- });
- c.on('error', function(err) {
- startServer(done);
- });
- })).listen(port, "127.0.0.1", function(err) {
- done();
- });
- }
-
- before(function(done) {
- startServer(done);
- });
-
- after(function(done) {
- server.stop(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- function testTCP(flow, val0, val1, done) {
- helper.load(tcpinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- if (typeof val1 === 'object') {
- msg.should.have.properties(Object.assign({}, val1, {payload: Buffer.from(val1.payload)}));
- } else {
- msg.should.have.property('payload', Buffer.from(val1));
- }
- done();
- } catch(err) {
- done(err);
- }
- });
- if((typeof val0) === 'object') {
- n1.receive(val0);
- } else {
- n1.receive({payload:val0});
- }
- });
- }
-
- function testTCPMany(flow, values, result, done) {
- helper.load(tcpinNode, flow, () => {
- const n1 = helper.getNode("n1");
- const n2 = helper.getNode("n2");
- n2.on("input", msg => {
- try {
- if (typeof result === 'object') {
- msg.should.have.properties(Object.assign({}, result, {payload: Buffer.from(result.payload)}));
- } else {
- msg.should.have.property('payload', Buffer.from(result));
- }
- done();
- } catch(err) {
- done(err);
- }
- });
- values.forEach(value => {
- n1.receive(typeof value === 'object' ? value : {payload: value});
- });
- });
- }
-
- describe('single message', function () {
- it('should send & recv data', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"time", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP(flow, {
- payload: 'foo',
- topic: 'bar'
- }, {
- payload: 'ACK:foo',
- topic: 'bar'
- }, done);
- });
-
- it('should retain complete message', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"time", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP(flow, {
- payload: 'foo',
- topic: 'bar'
- }, {
- payload: 'ACK:foo',
- topic: 'bar'
- }, done);
- });
-
- it('should send & recv data when specified character received', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"char", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP(flow, {
- payload: 'foo0bar0',
- topic: 'bar'
- }, {
- payload: 'ACK:foo0',
- topic: 'bar'
- }, done);
- });
-
- it('should send & recv data after fixed number of chars received', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"count", splitc: "7", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP(flow, {
- payload: 'foo bar',
- topic: 'bar'
- }, {
- payload: 'ACK:foo',
- topic: 'bar'
- }, done);
- });
-
- it('should send & receive, then keep connection', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", splitc: "5", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP(flow, {
- payload: 'foo',
- topic: 'bar'
- }, {
- payload: 'ACK:foo',
- topic: 'bar'
- }, done);
- });
-
- it('should send & recv data to/from server:port from msg', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"", port:"", out:"time", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCP(flow, {
- payload: "foo",
- host: "localhost",
- port: port
- }, {
- payload: "ACK:foo",
- host: 'localhost',
- port: port
- }, done);
- });
- });
-
- describe('many messages', function () {
- it('should send & recv data', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"time", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCPMany(flow, [{
- payload: 'f',
- topic: 'bar'
- }, {
- payload: 'o',
- topic: 'bar'
- }, {
- payload: 'o',
- topic: 'bar'
- }], {
- payload: 'ACK:foo',
- topic: 'bar'
- }, done);
- });
-
- it('should send & recv data when specified character received', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"char", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCPMany(flow, [{
- payload: "foo0",
- topic: 'bar'
- }, {
- payload: "bar0",
- topic: 'bar'
- }], {
- payload: "ACK:foo0",
- topic: 'bar'
- }, done);
- });
-
- it('should send & recv data after fixed number of chars received', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"count", splitc: "7", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCPMany(flow, [{
- payload: "fo",
- topic: 'bar'
- }, {
- payload: "ob",
- topic: 'bar'
- }, {
- payload: "ar",
- topic: 'bar'
- }], {
- payload: "ACK:foo",
- topic: 'bar'
- }, done);
- });
-
- it('should send & receive, then keep connection', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", splitc: "5", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCPMany(flow, [{
- payload: "foo",
- topic: 'bar'
- }, {
- payload: "bar",
- topic: 'bar'
- }, {
- payload: "baz",
- topic: 'bar'
- }], {
- payload: "ACK:foobarbaz",
- topic: 'bar'
- }, done);
- });
-
- it('should send & recv data to/from server:port from msg', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"", port:"", out:"time", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCPMany(flow, [{
- payload: "f",
- host: "localhost",
- port: port
- },
- {
- payload: "o",
- host: "localhost",
- port: port
- },
- {
- payload: "o",
- host: "localhost",
- port: port
- }
- ], {
- payload: "ACK:foo",
- host: 'localhost',
- port: port
- }, done);
- });
-
- it('should limit the queue size', function (done) {
- RED.settings.tcpMsgQueueSize = 10;
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"sit", splitc: "5", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- // create one more msg than is allowed
- const msgs = new Array(RED.settings.tcpMsgQueueSize + 1).fill('x');
- const expected = msgs.slice(0, -1);
- testTCPMany(flow, msgs, "ACK:" + expected.join(''), done);
- });
-
- it('should only retain the latest message', function(done) {
- var flow = [{id:"n1", type:"tcp request", server:"localhost", port:port, out:"time", splitc: "0", wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- testTCPMany(flow, [{
- payload: 'f',
- topic: 'bar'
- }, {
- payload: 'o',
- topic: 'baz'
- }, {
- payload: 'o',
- topic: 'quux'
- }], {
- payload: 'ACK:foo',
- topic: 'quux'
- }, done);
- });
- });
-});
diff --git a/test/nodes/core/network/32-udpin_spec.js b/test/nodes/core/network/32-udpin_spec.js
deleted file mode 100644
index 107c313bf..000000000
--- a/test/nodes/core/network/32-udpin_spec.js
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var dgram = require("dgram");
-var should = require("should");
-var helper = require("node-red-node-test-helper");
-var udpNode = require("nr-test-utils").require("@node-red/nodes/core/network/32-udp.js");
-
-
-describe('UDP in Node', function() {
- var port = 9100;
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- function sendIPv4(msg) {
- var sock = dgram.createSocket('udp4');
- sock.send(msg, 0, msg.length, port, "127.0.0.1", function(msg) {
- sock.close();
- });
- }
-
- function checkRecv(dt, proto, val0, val1, done) {
- var flow = [{id:"n1", type:"udp in",
- group: "", multicast:false,
- port:port, ipv:proto,
- datatype: dt, iface: "",
- wires:[["n2"]] },
- {id:"n2", type:"helper"}];
- helper.load(udpNode, flow, function() {
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- var ip = ((proto === 'udp6') ? '::ffff:':'') +'127.0.0.1';
- msg.should.have.property('ip', ip);
- msg.should.have.property('port');
- msg.should.have.property('payload');
- msg.payload.should.deepEqual(val1);
- done();
- } catch(err) {
- done(err);
- }
- });
- sendIPv4(val0);
- });
- }
-
- it('should recv IPv4 data (Buffer)', function(done) {
- checkRecv('buffer', 'udp4', 'hello', Buffer('hello'), done);
- });
-
- it('should recv IPv4 data (String)', function(done) {
- checkRecv('utf8', 'udp4', 'hello', 'hello', done);
- });
-
- it('should recv IPv4 data (base64)', function(done) {
- checkRecv('base64', 'udp4', 'hello', Buffer('hello').toString('base64'), done);
- });
-
- it('should recv IPv6 data (Buffer)', function(done) {
- checkRecv('buffer', 'udp6', 'hello', Buffer('hello'), done);
- });
-
- it('should recv IPv6 data (String)', function(done) {
- checkRecv('utf8', 'udp6', 'hello', 'hello', done);
- });
-
- it('should recv IPv6 data (base64)', function(done) {
- checkRecv('base64', 'udp6', 'hello', Buffer('hello').toString('base64'), done);
- });
-
-});
diff --git a/test/nodes/core/network/32-udpout_spec.js b/test/nodes/core/network/32-udpout_spec.js
deleted file mode 100644
index ff01c2f10..000000000
--- a/test/nodes/core/network/32-udpout_spec.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var dgram = require("dgram");
-var should = require("should");
-var helper = require("node-red-node-test-helper");
-var udpNode = require("nr-test-utils").require("@node-red/nodes/core/network/32-udp.js");
-
-
-describe('UDP out Node', function() {
- var port = 9200;
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- function recvData(data, done) {
- var sock = dgram.createSocket('udp4');
- sock.on('message', function(msg, rinfo) {
- sock.close(done);
- msg.should.deepEqual(data);
- });
- sock.bind(port, '127.0.0.1');
- port++;
- }
-
- function checkSend(proto, val0, val1, decode, dest_in_msg, done) {
- var dst_ip = dest_in_msg ? undefined : "127.0.0.1";
- var dst_port = dest_in_msg ? undefined : port;
- var flow = [{id:"n1", type:"udp out",
- addr:dst_ip, port:dst_port, iface: "",
- ipv:proto, outport: "",
- base64:decode, multicast:false,
- wires:[] }];
- helper.load(udpNode, flow, function() {
- var n1 = helper.getNode("n1");
- var msg = {};
- if (decode) {
- msg.payload = Buffer.from("hello").toString('base64');
- }
- else {
- msg.payload = "hello";
- }
- if (dest_in_msg) {
- msg.ip = "127.0.0.1";
- msg.port = port;
- }
- recvData(val1, done);
- setTimeout(function() {
- n1.receive(msg);
- }, 200);
- });
- }
-
- it('should send IPv4 data', function(done) {
- checkSend('udp4', 'hello', Buffer.from('hello'), false, false, done);
- });
-
- it('should send IPv4 data (base64)', function(done) {
- checkSend('udp4', 'hello', Buffer.from('hello'), true, false, done);
- });
-
- it('should send IPv4 data with dest from msg', function(done) {
- checkSend('udp4', 'hello', Buffer.from('hello'), false, true, done);
- });
-
-});
diff --git a/test/nodes/core/parsers/70-CSV_spec.js b/test/nodes/core/parsers/70-CSV_spec.js
deleted file mode 100644
index cb8d7ca09..000000000
--- a/test/nodes/core/parsers/70-CSV_spec.js
+++ /dev/null
@@ -1,1062 +0,0 @@
-/* eslint-disable no-undef */
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-// var should = require("should");
-var csvNode = require("nr-test-utils").require("@node-red/nodes/core/parsers/70-CSV.js");
-var helper = require("node-red-node-test-helper");
-// const { neq } = require("semver");
-
-describe('CSV node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded with defaults', function(done) {
- var flow = [{id:"csvNode1", type:"csv", name: "csvNode" }];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("csvNode1");
- n1.should.have.property('name', 'csvNode');
- n1.should.have.property('template','');
- n1.should.have.property('sep', ',');
- n1.should.have.property('quo', '"');
- n1.should.have.property('ret', '\n');
- n1.should.have.property('winflag', false);
- n1.should.have.property('lineend', '\n');
- n1.should.have.property('multi', 'one');
- n1.should.have.property('hdrin', false);
- done();
- });
- });
-
- describe('csv to json', function() {
- var parts_id = undefined;
-
- afterEach(function() {
- parts_id = undefined;
- });
-
- function check_parts(msg, index, count) {
- msg.should.have.property('parts');
- if(parts_id === undefined) {
- parts_id = msg.parts.id;
- }
- else {
- msg.parts.should.have.property('id', parts_id);
- }
- msg.parts.should.have.property('index', index);
- msg.parts.should.have.property('count', count);
- }
-
- it('should convert a simple csv string to a javascript object', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, b: 2, c: 3, d: 4 });
- msg.should.have.property('columns', "a,b,c,d");
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should convert a simple string to a javascript object with | separator (no template)', function(done) {
- var flow = [ { id:"n1", type:"csv", sep:"|", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { col1: 1, col2: 2, col3: 3, col4: 4 });
- msg.should.have.property('columns', "col1,col2,col3,col4");
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1|2|3|4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should convert a simple string to a javascript object with tab separator (with template)', function(done) {
- var flow = [ { id:"n1", type:"csv", sep:"\t", temp:"A,B,,D", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { A: 1, B: 2, D: 4 });
- msg.should.have.property('columns', "A,B,D");
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1\t2\t3\t4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should convert a simple string to a javascript object with space separator (with spaced template)', function(done) {
- var flow = [ { id:"n1", type:"csv", sep:" ", temp:"A, B, , D", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { A: 1, B: 2, D: 4 });
- msg.should.have.property('columns', "A,B,D");
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1 2 3 4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should remove quotes and whitespace from template', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:'"a", "b" , " c "," d " ', wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, b: 2, c: 3, d: 4 });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should create column names if no template provided', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:'', wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { col1: 1, col2: 2, col3: 3, col4: 4 });
- msg.should.have.property('columns', "col1,col2,col3,col4");
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow dropping of fields from the template', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,,,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, d: 4 });
- msg.should.have.property('columns', 'a,d');
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow commas and spaces in the template', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b b,\"c,c\",\" d, d \"", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, "b b":2, "c,c":3, "d, d": 4 });
- msg.should.have.property('columns', 'a,b b,"c,c","d, d"');
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow passing in a template as first line of CSV', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, "b b":2, "c,c":3, "d, d": 4 });
- msg.should.have.property('columns', 'a,b b,"c,c","d, d"');
- check_parts(msg, 0, 1);
- done();
- });
- var testString = 'a,b b,"c,c"," d, d "'+"\n"+"1,2,3,4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow passing in a template as first line of CSV (not comma)', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, sep:";", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, "b b":2, "c;c":3, "d, d": 4 });
- msg.should.have.property('columns', 'a,b b,c;c,"d, d"');
- check_parts(msg, 0, 1);
- done();
- });
- var testString = 'a;b b;"c;c";" d, d "'+"\n"+"1;2;3;4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow passing in a template as first line of CSV (special char /)', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, sep:"/", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, "b b":2, "c/c":3, "d, d": 4 });
- msg.should.have.property('columns', 'a,b b,c/c,"d, d"');
- check_parts(msg, 0, 1);
- done();
- });
- var testString = 'a/b b/"c/c"/" d, d "'+"\n"+"1/2/3/4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow passing in a template as first line of CSV (special char \\)', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, sep:"\\", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, "b b":2, "c\\c":3, "d, d": 4 });
- msg.should.have.property('columns', 'a,b b,c\\c,"d, d"');
- check_parts(msg, 0, 1);
- done();
- });
- var testString = 'a\\b b\\"c\\c"\\" d, d "'+"\n"+"1\\2\\3\\4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should leave numbers starting with 0, e and + as strings (except 0.)', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 123, b: "0123", c: '+123', d: 'e123', e: 'E123', f: -123 });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = '123,0123,+123,e123,E123,-123'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should not parse numbers when told not to do so', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", strings:false, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: "1.23", b: "0123", c: "+123", d: "e123", e: "0", f: "-123", g: "1e3" });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = '1.23,0123,+123,e123,0,-123,1e3'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should parse numbers when told to do so', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1.23, b: -123, c: 1000, d: 0 });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = ' 1.23 , -123,1e3 , 0 '+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should leave handle strings with scientific notation as numbers', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 12000, b: 0.012, c: -12000, d: -0.012 });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = '12E3,12e-3,-12e3,-12E-3'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
-
- it('should allow quotes in the input (but drop blank strings)', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g,h", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- //console.log(msg);
- msg.should.have.property('payload', { a:1, b:-2, c:'+3', d:'04', f:'-05', g:'ab"cd', h:'with,a,comma' });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = '"1","-2","+3","04","","-05","ab""cd","with,a,comma"'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow blank strings in the input if selected', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", include_empty_strings:true, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- //console.log(msg);
- msg.should.have.property('payload', { a: 1, b: '', c: '', d: '', e: '-05', f: 'ab"cd', g: 'with,a,comma' });
- //check_parts(msg, 0, 1);
- done();
- });
- var testString = '"1","","","","-05","ab""cd","with,a,comma"'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should allow missing columns (nulls) in the input if selected', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", include_null_values:true, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- //console.log(msg);
- msg.should.have.property('payload', { a: 1, b: null, c: '+3', d: null, e: '-05', f: 'ab"cd', g: 'with,a,comma' });
- //check_parts(msg, 0, 1);
- done();
- });
- var testString = '"1",,"+3",,"-05","ab""cd","with,a,comma"'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should handle cr and lf in the input', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- //console.log(msg);
- msg.should.have.property('payload', { a: "with a\nnew line", b: "and a\rcarriage return", c: "and why\r\nnot both"});
- check_parts(msg, 0, 1);
- done();
- });
- var testString = '"with a'+String.fromCharCode(10)+'new line","and a'+String.fromCharCode(13)+'carriage return","and why\r\nnot both"'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should recover from an odd number of quotes in the input', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c == 0) {
- c = 1;
- msg.should.have.property('payload', { a: "with,an", b: "odd,number", c: "ofquotes\n" });
- check_parts(msg, 0, 1);
- }
- else {
- msg.should.have.property('payload', { a: "this is", b: "a normal", c: "line" });
- check_parts(msg, 0, 1);
- done();
- }
- });
- var testString = '"with,a"n,odd","num"ber","of"qu"ot"es"'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- n1.emit("input", {payload:'"this is","a normal","line"'});
- });
- });
-
- it('should recover from an odd number of quotes in the input (2)', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e,f,g", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- //console.log(msg)
- if (c == 0) {
- c = 1;
- msg.should.have.property('payload', { a: "with,an", b: "odd,number", c: "ofquotes\nthis is,a normal,line" });
- check_parts(msg, 0, 1);
- }
- else {
- msg.should.have.property('payload', { a: "this is", b: "another", c: "line" });
- check_parts(msg, 0, 1);
- done();
- }
- });
- var testString = '"with,a"n,odd","num"ber","of"qu"ot"es"'+String.fromCharCode(10)+'"this is","a normal","line"'+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- n1.emit("input", {payload:'"this is","another","line"'});
- });
- });
-
- it('should be able to use the first line as a template', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", hdrin:true, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- //console.log(msg);
- if (c === 0) {
- msg.should.have.property('payload', { w: 1, x: 2, y: 3, z: 4 });
- check_parts(msg, 0, 2);
- c += 1;
- }
- else {
- msg.should.have.property('payload', { w: 5, x: 6, y: 7, z: 8 });
- check_parts(msg, 1, 2);
- done();
- }
- });
- var testString = "w,x,y,z\n1,2,3,4\n\n5,6,7,8";
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should be able to output multiple lines as one array', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", multi:"yes", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', [ { a: 1, b: 2, c: 3, d: 4 },{ a: 5, b: -6, c: '07', d: '+8' },{ a: 9, b: 0, c: 'a', d: 'b' },{ a: 'c', b: 'd', c: 'e', d: 'f' } ]);
- msg.should.have.property('columns','a,b,c,d');
- msg.should.not.have.property('parts');
- done();
- });
- var testString = "1,2,3,4\n5,-6,07,+8\n9,0,a,b\nc,d,e,f";
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should be able to create an array from multiple parts', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, multi:"mult", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', [{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]);
- msg.should.have.property('columns','a,b,c');
- msg.should.not.have.property('parts');
- done();
- });
-
- n1.emit("input", {"payload":"a,b,c","parts":{"index":0,"ch":"\n","type":"string","id":"1"}});
- n1.emit("input", {"payload":"1,2,3","parts":{"index":1,"ch":"\n","type":"string","id":"1"}});
- n1.emit("input", {"payload":"4,5,6","parts":{"index":2,"ch":"\n","type":"string","id":"1"}});
- n1.emit("input", {"payload":"7,8,9","parts":{"index":3,count:4,"ch":"\n","type":"string","id":"1"}});
- });
- });
-
- it('should be able to output multiple objects as an array from an input of parts', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, multi:"yes", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', [{"Col1":"V1","Col2":"V2"},{"Col1":"V3","Col2":"V4"},{"Col1":"V5","Col2":"V6"}]);
- msg.should.have.property('columns','Col1,Col2');
- msg.should.have.property('parts');
- done();
- });
- //var testString = "1,2,3,4\n5,-6,07,+8\n9,0,a,b\nc,d,e,f";
- // n1.emit("input", {payload:testString});
- n1.emit("input", {"payload":"Col1,Col2\nV1,V2\nV3,V4\nV5,V6","topic":"","parts":{"id":"3af07e18.865652","type":"array","count":2,"len":1,"index":0}});
- //n1.emit("input", {"payload":"Var1,Var2\nW1,W2\nW3,W4\nW5,W6","topic":"","parts":{"id":"3af07e18.865652","type":"array","count":2,"len":1,"index":1}});
- });
- });
-
- it('should handle numbers in strings but not IP addresses', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d,e", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: "a", b: "127.0.0.1", c: 56.7, d: -32.8, e: "+76.22C" });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "a,127.0.0.1,56.7,-32.8,+76.22C";
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should preserve parts property', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 1, b: 2, c: 3, d: 4 });
- check_parts(msg, 3, 4);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10);
- n1.emit("input", {payload:testString, parts: {id:"X", index:3, count:4} });
- });
- });
-
- it('should be able to use the first of multiple parts as a template if parts are present', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.property('payload', { w: 1, x: 2, y: 3, z: 4 });
- check_parts(msg, 0, 2);
- c += 1;
- }
- else {
- msg.should.have.property('payload', { w: 5, x: 6, y: 7, z: 8 });
- check_parts(msg, 1, 2);
- done();
- }
- });
- var testString1 = "w,x,y,z\n";
- var testString2 = "1,2,3,4\n";
- var testString3 = "5,6,7,8\n";
- n1.emit("input", {payload:testString1, parts:{id:"X", index:0, count:3}});
- n1.emit("input", {payload:testString2, parts:{id:"X", index:1, count:3}});
- n1.emit("input", {payload:testString3, parts:{id:"X", index:2, count:3}});
- });
- });
-
- it('should skip several lines from start if requested', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", skip: 2, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { a: 9, b: 0, c: "A", d: "B" });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10)+"5,6,7,8"+String.fromCharCode(10)+"9,0,A,B"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should skip several lines from start then use next line as a template', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", hdrin:true, skip: 2, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload', { "9": "C", "0": "D", "A": "E", "B": "F" });
- check_parts(msg, 0, 1);
- done();
- });
- var testString = "1,2,3,4"+String.fromCharCode(10)+"5,6,7,8"+String.fromCharCode(10)+"9,0,A,B"+String.fromCharCode(10)+"C,D,E,F"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should skip several lines from start and correct parts', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", skip: 2, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c===0) {
- msg.should.have.property('payload', { a: 9, b: 0, c: "A", d: "B" });
- check_parts(msg, 0, 2);
- c = c+1;
- }
- else {
- msg.should.have.property('payload', { a: "C", b: "D", c: "E", d: "F" });
- check_parts(msg, 1, 2);
- done();
- }
- });
- var testString = "1,2,3,4"+String.fromCharCode(10)+"5,6,7,8"+String.fromCharCode(10)+"9,0,A,B"+String.fromCharCode(10)+"C,D,E,F"+String.fromCharCode(10);
- n1.emit("input", {payload:testString});
- });
- });
-
- it('should be able to skip and then use the first of multiple parts as a template if parts are present', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrin:true, skip:2, wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 0) {
- msg.should.have.property('payload', { w: 1, x: 2, y: 3, z: 4 });
- msg.should.have.property('columns', 'w,x,y,z');
- check_parts(msg, 0, 2);
- c += 1;
- }
- else {
- msg.should.have.property('payload', { w: 5, x: 6, y: 7, z: 8 });
- msg.should.have.property('columns', 'w,x,y,z');
- check_parts(msg, 1, 2);
- done();
- }
- });
- var testStringA = "foo\n";
- var testStringB = "bar\n";
- var testString1 = "w,x,y,z\n";
- var testString2 = "1,2,3,4\n";
- var testString3 = "5,6,7,8\n";
- n1.emit("input", {payload:testStringA, parts:{id:"X", index:0, count:5}});
- n1.emit("input", {payload:testStringB, parts:{id:"X", index:1, count:5}});
- n1.emit("input", {payload:testString1, parts:{id:"X", index:2, count:5}});
- n1.emit("input", {payload:testString2, parts:{id:"X", index:3, count:5}});
- n1.emit("input", {payload:testString3, parts:{id:"X", index:4, count:5}});
- });
- });
-
- });
-
- describe('json object to csv', function() {
-
- it('should convert a simple object back to a csv', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,,e", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '4,foo,true,,0\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = { e:0, d:1, b:"foo", c:true, a:4 };
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert a simple object back to a csv with no template', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:" ", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '1,foo,"ba""r","di,ng"\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng" };
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert a simple object back to a tsv using a tab as a separator', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", sep:"\t", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '1\tfoo\t"ba""r"\tdi,ng\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = { d:1, b:"foo", c:"ba\"r", a:"di,ng" };
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should handle a template with spaces in the property names', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b o,c p,,e", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '4,foo,true,,0\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = { e:0, d:1, "b o":"foo", "c p":true, a:4 };
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert an array of objects to a multi-line csv', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,d,c,b", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '4,1,2,3\n1,4,3,2\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = [{ d: 1, b: 3, c: 2, a: 4 },{d:4,a:1,c:3,b:2}];
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert an array of objects to a multi-line csv and add a header', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", hdrout:"all", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 'a,b,c,d\n4,3,2,1\n1,2,3,4\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = [{ d: 1, b: 3, c: 2, a: 4 },{d:4,a:1,c:3,b:2}];
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert an array of objects to a multi-line csv without a template', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '1,3,2,4\n4,2,3,1\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = [{ d: 1, b: 3, c: 2, a: 4 },{d:4,a:1,c:3,b:2}];
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert an array of objects to a multi-line csv without a template and with a header', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrout:"all", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 'd,b,c,a\n1,3,2,4\n4,2,3,1\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = [{ d: 1, b: 3, c: 2, a: 4 },{d:4,a:1,c:3,b:2}];
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert a simple array back to a csv', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', ',0,1,foo,"ba""r","di,ng"\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = ["",0,1,"foo",'ba"r','di,ng'];
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should convert an array of arrays back to a multi-line csv', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '0,1,2,3,4\n4,3,2,1,0\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = [[0,1,2,3,4],[4,3,2,1,0]];
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should be able to include column names as first row', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", hdrout:true, ret:"\r\n", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 'a,b,c,d\r\n4,3,2,1\r\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = [{ d: 1, b: 3, c: 2, a: 4 }];
- n1.emit("input", {payload:testJson});
- });
- });
-
- it('should be able to include column names as first row, and missing properties', function(done) {
- var flow = [ { id:"n1", type:"csv", hdrout:true, ret:"\r\n", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 'col1,col2,col3,col4\r\nH1,H2,H3,H4\r\nA,B,,\r\nA,,C,\r\nA,,,D\r\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = [{"col1":"H1","col2":"H2","col3":"H3","col4":"H4"},{"col1":"A","col2":"B"},{"col1":"A","col3":"C"},{"col1":"A","col4":"D"}];
- n1.emit("input", {payload:testJson});
- });
- });
-
-
- it('should be able to pass in column names', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"", hdrout:"once", ret:"\r\n", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- count += 1;
- try {
- if (count === 1) {
- msg.should.have.property('payload', 'a,,b,a\r\n4,,3,4\r\n');
- }
- if (count === 3) {
- msg.should.have.property('payload', '4,,3,4\r\n');
- done()
- }
- }
- catch(e) { done(e); }
- });
- var testJson = [{ d: 1, b: 3, c: 2, a: 4 }];
- n1.emit("input", {payload:testJson, columns:"a,,b,a", parts:{index:0}});
- n1.emit("input", {payload:testJson, parts:{index:1}});
- n1.emit("input", {payload:testJson, parts:{index:2}});
- });
- });
-
- it('should be able to pass in column names - with payload as an array', function(done) {
- var flow = [ { id:"n1", type:"csv", hdrout:"once", ret:"\r\n", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', 'a,,b,a\r\n4,,3,4\r\n4,,3,4\r\n4,,3,4\r\n');
- done()
- }
- catch(e) { done(e); }
- });
- var testJson = { d: 1, b: 3, c: 2, a: 4 };
- n1.emit("input", {payload:[testJson,testJson,testJson], columns:"a,,b,a"});
- });
- });
-
- it('should handle quotes and sub-properties', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload', '{},"text,with,commas","This ""is"" a banana","{""sub"":""object""}"\n');
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = { d: {sub:"object"}, b: "text,with,commas", c: 'This "is" a banana', a: {sub2:undefined} };
- n1.emit("input", {payload:testJson});
- });
- });
-
- });
-
- it('should just pass through if no payload provided', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', { a: 4, b: 3, c: 2, d: 1 });
- msg.should.not.have.property('payload');
-
- done();
- }
- catch(e) { done(e); }
- });
- var testJson = { d: 1, b: 3, c: 2, a: 4 };
- n1.emit("input", {topic:testJson});
- });
- });
-
- it('should warn if provided a number or boolean', function(done) {
- var flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[["n2"]] },
- {id:"n2", type:"helper"} ];
- helper.load(csvNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "csv";
- });
- logEvents.should.have.length(2);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith('csv.errors.csv_js');
- logEvents[1][0].should.have.a.property('msg');
- logEvents[1][0].msg.toString().should.startWith('csv.errors.csv_js');
- done();
- } catch(err) {
- done(err);
- }
- },150);
- n1.emit("input", {payload:1});
- n1.emit("input", {payload:true});
- });
- });
-
- it('should call done when message processing is completed', function(done) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[[]]},
- { id:"c1", type:"complete", scope: ["n1"], uncaught:false, wires:[["h1"]]},
- { id:"h1", type:"helper", wires:[[]]} ];
- helper.load([csvNode,completeNode], flow, function() {
- const n1 = helper.getNode("n1");
- const h1 = helper.getNode("h1");
- h1.on("input", function(msg) {
- try {
- msg.should.have.a.property('payload', "1,2,3,4");
- done();
- } catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"1,2,3,4"});
- });
- });
-
- it('should call done when input causes an error', function(done) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const flow = [ { id:"n1", type:"csv", temp:"a,b,c,d", wires:[[]]},
- { id:"c1", type:"complete", scope: ["n1"], uncaught:false, wires:[["h1"]]},
- { id:"h1", type:"helper", wires:[[]]} ];
- helper.load([csvNode,completeNode], flow, function() {
- const n1 = helper.getNode("n1");
- const h1 = helper.getNode("h1");
- h1.on("input", function(msg) {
- try {
- msg.should.have.a.property('payload', 1);
- done();
- } catch (e) {
- done(e);
- }
- });
- n1.receive({payload:1}); // neither object nor string
- });
- });
-});
diff --git a/test/nodes/core/parsers/70-HTML_spec.js b/test/nodes/core/parsers/70-HTML_spec.js
deleted file mode 100644
index da7246e64..000000000
--- a/test/nodes/core/parsers/70-HTML_spec.js
+++ /dev/null
@@ -1,494 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var path = require("path");
-var fs = require('fs-extra');
-
-var htmlNode = require("nr-test-utils").require("@node-red/nodes/core/parsers/70-HTML.js");
-var helper = require("node-red-node-test-helper");
-
-describe('HTML node', function() {
-
- var resourcesDir = __dirname+ path.sep + ".." + path.sep + ".." + path.sep + ".." + path.sep + "resources" + path.sep;
- var file = path.join(resourcesDir, "70-HTML-test-file.html");
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- beforeEach(function() {
- fs.existsSync(file).should.be.true();
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"htmlNode1", type:"html", name: "htmlNode" }];
- helper.load(htmlNode, flow, function() {
- var htmlNode1 = helper.getNode("htmlNode1");
- htmlNode1.should.have.property('name', 'htmlNode');
- done();
- });
- });
-
- it('should retrieve header contents if asked to by msg.select', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- should.equal(msg.payload, 'This is a test page for node 70-HTML');
- done();
- } catch(err) {
- done(err)
- }
- });
- // include 'body' in the select to verify we're in document mode
- // for the parser. See https://github.com/node-red/node-red/issues/3079
- n1.receive({payload:data,topic:"bar",select:"body h1"});
- });
- });
- });
-
- it('should retrieve header contents if asked to by msg.select - alternative in property', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",property:"foo",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.foo[0].should.equal('This is a test page for node 70-HTML');
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({foo:data,topic:"bar",select:"h1"});
- });
- });
- });
-
- it('should retrieve header contents if asked to by msg.select - alternative in and out properties', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",property:"foo",outproperty:"bar",tag:"h1",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.bar[0].should.equal('This is a test page for node 70-HTML');
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({foo:data,topic:"bar"});
- });
- });
- });
-
- it('should emit an empty array if no matching elements', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('payload');
- msg.payload.should.be.empty;
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic:"bar",select:"h4"});
- });
- });
- });
-
- it('should retrieve paragraph contents when specified', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],ret:"text",tag:"p"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- should.equal(msg.payload, 'There\'s nothing to read here.');
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- it('should retrieve list contents as an array of html as default', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ol"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.payload[0].indexOf("Blue ").should.be.above(-1);
- msg.payload[0].indexOf("Red ").should.be.above(-1);
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- it('should retrieve list contents as an array of text', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ol",ret:"text"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.payload[0].indexOf("Blue").should.be.above(-1);
- msg.payload[0].indexOf("Red").should.be.above(-1);
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- it('should fix up a unclosed tag', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"span"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- should.equal(msg.payload, ' ');
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- it('should retrieve an attribute from a tag', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],ret:"attr",tag:"span img"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload[0].should.have.property('src','foo.png');
- msg.should.have.property('topic', 'bar');
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- it('should log on error', function(done) {
- fs.readFile(file,function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"p"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- try {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.receive({payload:null,topic: "bar"});
- setTimeout(function() {
- try {
- helper.log().called.should.be.true();
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "html";
- });
- logEvents.should.have.length(1);
- // Each logEvent is the array of args passed to the function.
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
-
- done();
- } catch(err) { done(err) }
- },50);
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('should pass through if payload empty', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.not.have.property('payload');
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({topic: "bar"});
- });
- });
- });
-
- describe('multiple messages', function(){
- var cnt = 0;
- var parts_id = undefined;
-
- afterEach(function() {
- cnt.should.be.exactly(2);
- cnt = 0;
- parts_id = undefined;
- });
-
- function check_parts(msg, index, count) {
- msg.should.have.property('parts');
- msg.parts.should.have.property('id');
- if(parts_id === undefined) {
- parts_id = msg.parts.id;
- }
- else {
- msg.parts.should.have.property('id', parts_id);
- }
- msg.parts.should.have.property('index', index);
- msg.parts.should.have.property('count', count);
- msg.parts.should.have.property('type', 'string');
- msg.parts.should.have.property('ch', '');
- }
-
- it('should retrieve list contents as html as default with output as multiple msgs', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ul",as:"multi"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- cnt++;
- msg.should.have.property('topic', 'bar');
- check_parts(msg, cnt -1, 2);
- if (cnt !== 1 && cnt !== 2) {
- return false;
- }
- if (cnt === 1) {
- msg.payload.indexOf("Apple ").should.be.above(-1);
- msg.payload.indexOf("Pear ").should.be.above(-1);
- } else if (cnt === 2) {
- msg.payload.indexOf("Potato ").should.be.above(-1);
- msg.payload.indexOf("Parsnip ").should.be.above(-1);
- done();
- }
- } catch(err) {
- done(err)
- }
-
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
-
- it('should retrieve list contents as html as default with output as multiple msgs - alternative property', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",property:"foo",wires:[["n2"]],tag:"ul",as:"multi"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- cnt++;
- msg.should.have.property('topic', 'bar');
- check_parts(msg, cnt -1, 2);
- if (cnt !== 1 && cnt !== 2) {
- return false;
- }
- if (cnt === 1) {
- msg.foo.indexOf("Apple ").should.be.above(-1);
- msg.foo.indexOf("Pear ").should.be.above(-1);
- } else if (cnt === 2) {
- msg.foo.indexOf("Potato ").should.be.above(-1);
- msg.foo.indexOf("Parsnip ").should.be.above(-1);
- done();
- }
- } catch(err) {
- done(err)
- }
- });
- n1.receive({foo:data, topic:"bar"});
- });
- });
- });
-
- it('should retrieve list contents as text with output as multiple msgs ', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ul",ret:"text",as:"multi"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- cnt++;
- msg.should.have.property('topic', 'bar');
- check_parts(msg, cnt -1, 2);
- if (cnt !== 1 && cnt !== 2) {
- return false;
- }
- if (cnt === 1) {
- msg.payload.indexOf("Apple").should.be.above(-1);
- msg.payload.indexOf("Pear").should.be.above(-1);
- } else if (cnt === 2) {
- msg.payload.indexOf("Potato").should.be.above(-1);
- msg.payload.indexOf("Parsnip").should.be.above(-1);
- done();
- }
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- it('should retrieve an attribute from a tag', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],ret:"attr",tag:"span img",as:"multi"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.have.property('src','foo.png');
- msg.should.have.property('topic', 'bar');
- check_parts(msg, 0, 1);
- cnt = 2; // frig the answer as only one img tag
- done();
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- it('should not reuse message', function(done) {
- fs.readFile(file, 'utf8', function(err, data) {
- var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ul",ret:"text",as:"multi"},
- {id:"n2", type:"helper"}];
-
- helper.load(htmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var prev_msg = undefined;
- n2.on("input", function(msg) {
- try {
- cnt++;
- if (prev_msg == undefined) {
- prev_msg = msg;
- }
- else {
- msg.should.not.equal(prev_msg);
- }
- if (cnt == 2) {
- done();
- }
- } catch(err) {
- done(err)
- }
- });
- n1.receive({payload:data,topic: "bar"});
- });
- });
- });
-
- });
-
-});
diff --git a/test/nodes/core/parsers/70-JSON_spec.js b/test/nodes/core/parsers/70-JSON_spec.js
deleted file mode 100644
index ad469bbd5..000000000
--- a/test/nodes/core/parsers/70-JSON_spec.js
+++ /dev/null
@@ -1,546 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var jsonNode = require("nr-test-utils").require("@node-red/nodes/core/parsers/70-JSON.js");
-var helper = require("node-red-node-test-helper");
-
-describe('JSON node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should convert a valid json string to a javascript object', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.payload.should.have.property('employees');
- msg.payload.employees[0].should.have.property('firstName', 'John');
- msg.payload.employees[0].should.have.property('lastName', 'Smith');
- done();
- });
- var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}';
- jn1.receive({payload:jsonString,topic: "bar"});
- });
- });
-
- it('should convert a javascript object to a json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, '{"employees":[{"firstName":"John","lastName":"Smith"}]}');
- done();
- });
- var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
- jn1.receive({payload:obj});
- });
- });
-
- it('should convert a array to a json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, '[1,2,3]');
- done();
- });
- var obj = [1,2,3];
- jn1.receive({payload:obj});
- });
- });
-
- it('should convert a boolean to a json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, 'true');
- done();
- });
- var obj = true;
- jn1.receive({payload:obj});
- });
- });
-
- it('should convert a json string to a boolean', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, true);
- done();
- });
- var obj = "true";
- jn1.receive({payload:obj});
- });
- });
-
- it('should convert a number to a json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, '2019');
- done();
- });
- var obj = 2019;
- jn1.receive({payload:obj});
- });
- });
-
- it('should convert a json string to a number', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, 1962);
- done();
- });
- var obj = '1962';
- jn1.receive({payload:obj});
- });
- });
-
- it('should log an error if asked to parse an invalid json string', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- try {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn1.receive({payload:'foo',topic: "bar"});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.should.startWith("Unexpected token o");
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
- done();
- } catch(err) { done(err) }
- },20);
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should log an error if asked to parse something thats not json or js', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.eql('json.errors.dropped-object');
- done();
- } catch(err) {
- done(err);
- }
- },50);
- jn1.receive({payload:Buffer.from("a")});
- });
- });
-
- it('should pass straight through if no payload set', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.not.have.property('payload');
- done();
- });
- jn1.receive({topic: "bar"});
- });
- });
-
- it('should ensure the result is a json string', function(done) {
- var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- var count = 0;
- jn2.on("input", function(msg) {
- try {
- should.equal(msg.payload, '{"employees":[{"firstName":"John","lastName":"Smith"}]}');
- count++;
- if (count === 2) {
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
- jn1.receive({payload:obj,topic: "bar"});
- jn1.receive({payload:JSON.stringify(obj),topic: "bar"});
- });
- });
-
- it('should ensure the result is a JS Object', function(done) {
- var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- var count = 0;
- jn2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.payload.should.have.property('employees');
- msg.payload.employees[0].should.have.property('firstName', 'John');
- msg.payload.employees[0].should.have.property('lastName', 'Smith');
- count++;
- if (count === 2) {
- done();
- }
- } catch(err) {
- done(err);
- }
- });
- var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
- jn1.receive({payload:obj,topic: "bar"});
- jn1.receive({payload:JSON.stringify(obj),topic: "bar"});
- });
- });
-
- it('should handle any msg property - receive existing string', function(done) {
- var flow = [{id:"jn1",type:"json",property:"one.two",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- try {
- msg.should.have.property('topic', 'bar');
- msg.should.have.property('one');
- msg.one.should.have.property('two');
- msg.one.two.should.have.property('employees');
- msg.one.two.employees[0].should.have.property('firstName', 'John');
- msg.one.two.employees[0].should.have.property('lastName', 'Smith');
- done();
- } catch(err) {
- done(err);
- }
- });
- var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}';
- jn1.receive({payload:"",one:{two:jsonString},topic: "bar"});
-
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- });
- });
-
- it('should handle any msg property - receive existing obj', function(done) {
- var flow = [{id:"jn1",type:"json",property:"one.two",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- try {
- should.equal(msg.one.two, '{"employees":[{"firstName":"John","lastName":"Smith"}]}');
- done();
- } catch(err) {
- done(err);
- }
- });
- var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}';
- jn1.receive({payload:"",one:{two:JSON.parse(jsonString)},topic: "bar"});
-
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- });
- });
-
- it('should pass an object if provided a valid JSON string and schema', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload.number, 3);
- should.equal(msg.payload.string, "allo");
- done();
- });
- var jsonString = '{"number": 3, "string": "allo"}';
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- jn1.receive({payload:jsonString, schema:schema});
- });
- });
-
- it('should pass an object if provided a valid object and schema and action is object', function(done) {
- var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload.number, 3);
- should.equal(msg.payload.string, "allo");
- done();
- });
- var obj = {"number": 3, "string": "allo"};
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- jn1.receive({payload:obj, schema:schema});
- });
- });
-
- it('should pass a string if provided a valid object and schema', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, '{"number":3,"string":"allo"}');
- done();
- });
- var obj = {"number": 3, "string": "allo"};
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- jn1.receive({payload:obj, schema:schema});
- });
- });
-
- it('should pass a string if provided a valid JSON string and schema and action is string', function(done) {
- var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.payload, '{"number":3,"string":"allo"}');
- done();
- });
- var jsonString = '{"number":3,"string":"allo"}';
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- jn1.receive({payload:jsonString, schema:schema});
- });
- });
-
- it('should log an error if passed an invalid object and valid schema', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- try {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- var obj = {"number": "foo", "string": 3};
- jn1.receive({payload:obj, schema:schema});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.should.startWith("json.errors.schema-error");
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
- done();
- } catch(err) { done(err) }
- },50);
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should log an error if passed an invalid object and valid schema and action is object', function(done) {
- var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- try {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- var obj = {"number": "foo", "string": 3};
- jn1.receive({payload:obj, schema:schema});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.should.startWith("json.errors.schema-error");
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
- done();
- } catch(err) { done(err) }
- },50);
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should log an error if passed an invalid JSON string and valid schema', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- try {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- var jsonString = '{"number":"Hello","string":3}';
- jn1.receive({payload:jsonString, schema:schema});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.should.startWith("json.errors.schema-error");
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
- done();
- } catch(err) { done(err) }
- },50);
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should log an error if passed an invalid JSON string and valid schema and action is string', function(done) {
- var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- try {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- var jsonString = '{"number":"Hello","string":3}';
- jn1.receive({payload:jsonString, schema:schema});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.should.startWith("json.errors.schema-error");
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
- done();
- } catch(err) { done(err) }
- },50);
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should log an error if passed a valid object and invalid schema', function(done) {
- var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- try {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- var schema = "garbage";
- var obj = {"number": "foo", "string": 3};
- jn1.receive({payload:obj, schema:schema});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "json";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.should.equal("json.errors.schema-error-compile");
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
- done();
- } catch(err) { done(err) }
- },50);
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('msg.schema property should be deleted before sending to next node (string input)', function(done) {
- var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.schema, undefined);
- done();
- });
- var jsonString = '{"number":3,"string":"allo"}';
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- jn1.receive({payload:jsonString, schema:schema});
- });
- });
-
- it('msg.schema property should be deleted before sending to next node (object input)', function(done) {
- var flow = [{id:"jn1",type:"json",action:"str",wires:[["jn2"]]},
- {id:"jn2", type:"helper"}];
- helper.load(jsonNode, flow, function() {
- var jn1 = helper.getNode("jn1");
- var jn2 = helper.getNode("jn2");
- jn2.on("input", function(msg) {
- should.equal(msg.schema, undefined);
- done();
- });
- var jsonObject = {"number":3,"string":"allo"};
- var schema = {title: "testSchema", type: "object", properties: {number: {type: "number"}, string: {type: "string" }}};
- jn1.receive({payload:jsonObject, schema:schema});
- });
- });
-});
diff --git a/test/nodes/core/parsers/70-XML_spec.js b/test/nodes/core/parsers/70-XML_spec.js
deleted file mode 100644
index e8b281855..000000000
--- a/test/nodes/core/parsers/70-XML_spec.js
+++ /dev/null
@@ -1,198 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var xmlNode = require("nr-test-utils").require("@node-red/nodes/core/parsers/70-XML.js");
-var helper = require("node-red-node-test-helper");
-
-describe('XML node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"xmlNode1", type:"xml", name: "xmlNode" }];
- helper.load(xmlNode, flow, function() {
- var xmlNode1 = helper.getNode("xmlNode1");
- xmlNode1.should.have.property('name', 'xmlNode');
- done();
- });
- });
-
- it('should convert a valid xml string to a javascript object', function(done) {
- var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.payload.should.have.property('employees');
- msg.payload.employees.should.have.property('firstName');
- should.equal(msg.payload.employees.firstName[0], 'John');
- msg.payload.employees.should.have.property('lastName');
- should.equal(msg.payload.employees.lastName[0], 'Smith');
- done();
- });
- var string = 'John Smith ';
- n1.receive({payload:string,topic: "bar"});
- });
- });
-
- it('should convert a valid xml string to a javascript object - alternative property', function(done) {
- var flow = [{id:"n1",type:"xml",property:"foo",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.foo.should.have.property('employees');
- msg.foo.employees.should.have.property('firstName');
- should.equal(msg.foo.employees.firstName[0], 'John');
- msg.foo.employees.should.have.property('lastName');
- should.equal(msg.foo.employees.lastName[0], 'Smith');
- done();
- });
- var string = 'John Smith ';
- n1.receive({foo:string,topic: "bar"});
- });
- });
-
- it('should convert a valid xml string to a javascript object with options', function(done) {
- var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.payload.should.have.property('employees');
- msg.payload.employees.should.have.property('firstName');
- should.equal(msg.payload.employees.firstName[0], 'John');
- msg.payload.employees.should.have.property('lastName');
- should.equal(msg.payload.employees.lastName[0], 'Smith');
- done();
- });
- var string = 'John Smith ';
- n1.receive({payload:string, topic:"bar", options:{trim:true}});
- });
- });
-
- it('should convert a javascript object to an xml string', function(done) {
- var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- var index = msg.payload.indexOf('John Smith ');
- index.should.be.above(-1);
- done();
- });
- var obj = {"employees":{"firstName":["John"],"lastName":["Smith"] }};
- n1.receive({payload:obj,topic: "bar"});
- });
- });
-
- it('should convert a javascript object to an xml string with options - alternative property', function(done) {
- var flow = [{id:"n1",type:"xml",property:"foo",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- var index = msg.foo.indexOf('\n John \n Smith \n ');
- index.should.be.above(-1);
- done();
- });
- var obj = {"employees":{"firstName":["John"],"lastName":["Smith"] }};
- n1.receive({foo:obj, topic:"bar", options:{headless:true}});
- });
- });
-
- it('should log an error if asked to parse an invalid xml string', function(done) {
- var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.receive({payload:'',topic: "bar"});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "xml";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("Error: Attribute without value");
- done();
- } catch(err) {
- done(err);
- }
- },200);
- });
- });
-
- it('should log an error if asked to parse something thats not xml or js', function(done) {
- var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.receive({payload:1,topic: "bar"});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "xml";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg',"xml.errors.xml_js");
- done();
- } catch(err) {
- done(err);
- }
- },200);
- });
- });
-
- it('should just pass through if payload is missing', function(done) {
- var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"},
- {id:"n2", type:"helper"}];
- helper.load(xmlNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.not.have.property('payload');
- done();
- });
- n1.receive({topic: "bar"});
- });
- });
-
-});
diff --git a/test/nodes/core/parsers/70-YAML_spec.js b/test/nodes/core/parsers/70-YAML_spec.js
deleted file mode 100644
index 3441e0946..000000000
--- a/test/nodes/core/parsers/70-YAML_spec.js
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var yamlNode = require("nr-test-utils").require("@node-red/nodes/core/parsers/70-YAML.js");
-var helper = require("node-red-node-test-helper");
-
-describe('YAML node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"yamlNode1", type:"yaml", name: "yamlNode" }];
- helper.load(yamlNode, flow, function() {
- var yamlNode1 = helper.getNode("yamlNode1");
- yamlNode1.should.have.property('name', 'yamlNode');
- done();
- });
- });
-
- it('should convert a valid yaml string to a javascript object', function(done) {
- var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- yn2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.payload.should.have.property('employees');
- msg.payload.employees[0].should.have.property('firstName', 'John');
- msg.payload.employees[0].should.have.property('lastName', 'Smith');
- done();
- });
- var yamlString = "employees:\n - firstName: John\n lastName: Smith\n";
- yn1.receive({payload:yamlString,topic: "bar"});
- });
- });
-
- it('should convert a valid yaml string to a javascript object - using another property', function(done) {
- var flow = [{id:"yn1",type:"yaml",property:"foo",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- yn2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.foo.should.have.property('employees');
- msg.foo.employees[0].should.have.property('firstName', 'John');
- msg.foo.employees[0].should.have.property('lastName', 'Smith');
- done();
- });
- var yamlString = "employees:\n - firstName: John\n lastName: Smith\n";
- yn1.receive({foo:yamlString,topic: "bar"});
- });
- });
-
- it('should convert a javascript object to a yaml string', function(done) {
- var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- yn2.on("input", function(msg) {
- should.equal(msg.payload, "employees:\n - firstName: John\n lastName: Smith\n");
- done();
- });
- var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
- yn1.receive({payload:obj});
- });
- });
-
- it('should convert a javascript object to a yaml string - using another property', function(done) {
- var flow = [{id:"yn1",type:"yaml",property:"foo",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- yn2.on("input", function(msg) {
- should.equal(msg.foo, "employees:\n - firstName: John\n lastName: Smith\n");
- done();
- });
- var obj = {employees:[{firstName:"John", lastName:"Smith"}]};
- yn1.receive({foo:obj});
- });
- });
-
- it('should convert an array to a yaml string', function(done) {
- var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- yn2.on("input", function(msg) {
- should.equal(msg.payload, "- 1\n- 2\n- 3\n");
- done();
- });
- var obj = [1,2,3];
- yn1.receive({payload:obj});
- });
- });
-
- it('should log an error if asked to parse an invalid yaml string', function(done) {
- var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- try {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- yn1.receive({payload:'employees:\n-firstName: John\n- lastName: Smith\n',topic: "bar"});
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "yaml";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.should.startWith("end of the stream");
- logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
- done();
- } catch(err) { done(err) }
- },50);
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('should log an error if asked to parse something thats not yaml or js', function(done) {
- var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "yaml";
- });
- logEvents.should.have.length(3);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.eql('yaml.errors.dropped');
- logEvents[1][0].should.have.a.property('msg');
- logEvents[1][0].msg.toString().should.eql('yaml.errors.dropped');
- logEvents[2][0].should.have.a.property('msg');
- logEvents[2][0].msg.toString().should.eql('yaml.errors.dropped-object');
- done();
- } catch(err) {
- done(err);
- }
- },150);
- yn1.receive({payload:true});
- yn1.receive({payload:1});
- yn1.receive({payload:Buffer.from("a")});
- });
- });
-
- it('should pass straight through if no payload set', function(done) {
- var flow = [{id:"yn1",type:"yaml",wires:[["yn2"]],func:"return msg;"},
- {id:"yn2", type:"helper"}];
- helper.load(yamlNode, flow, function() {
- var yn1 = helper.getNode("yn1");
- var yn2 = helper.getNode("yn2");
- yn2.on("input", function(msg) {
- msg.should.have.property('topic', 'bar');
- msg.should.not.have.property('payload');
- done();
- });
- yn1.receive({topic: "bar"});
- });
- });
-
-});
diff --git a/test/nodes/core/sequence/17-split_spec.js b/test/nodes/core/sequence/17-split_spec.js
deleted file mode 100644
index 370e0cda4..000000000
--- a/test/nodes/core/sequence/17-split_spec.js
+++ /dev/null
@@ -1,1919 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var splitNode = require("nr-test-utils").require("@node-red/nodes/core/sequence/17-split.js");
-var joinNode = require("nr-test-utils").require("@node-red/nodes/core/sequence/17-split.js");
-var helper = require("node-red-node-test-helper");
-var RED = require("nr-test-utils").require("node-red/lib/red.js");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context");
-
-var TimeoutForErrorCase = 20;
-
-describe('SPLIT node', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"splitNode1", type:"split", name:"splitNode" }];
- helper.load(splitNode, flow, function() {
- var splitNode1 = helper.getNode("splitNode1");
- splitNode1.should.have.property('name', 'splitNode');
- done();
- });
- });
-
- it('should split an array into multiple messages', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]]},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count",4);
- msg.parts.should.have.property("type","array");
- msg.parts.should.have.property("index");
- if (msg.parts.index === 0) { msg.payload.should.equal(1); }
- if (msg.parts.index === 1) { msg.payload.should.equal(2); }
- if (msg.parts.index === 2) { msg.payload.should.equal(3); }
- if (msg.parts.index === 3) { msg.payload.should.equal(4); done(); }
- });
- sn1.receive({payload:[1,2,3,4]});
- });
- });
-
- it('should split an array into multiple messages of a specified size', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]], arraySplt:3, arraySpltType:"len"},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count",2);
- msg.parts.should.have.property("type","array");
- msg.parts.should.have.property("index");
- msg.payload.should.be.an.Array();
- if (msg.parts.index === 0) { msg.payload.length.should.equal(3); }
- if (msg.parts.index === 1) { msg.payload.length.should.equal(1); done(); }
- });
- sn1.receive({payload:[1,2,3,4]});
- });
- });
-
- it('should split an object into pieces', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]]},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- var count = 0;
- sn2.on("input", function(msg) {
- msg.should.have.property("payload");
- msg.should.have.property("parts");
- msg.parts.should.have.property("type","object");
- msg.parts.should.have.property("key");
- msg.parts.should.have.property("count");
- msg.parts.should.have.property("index");
- msg.topic.should.equal("foo");
- if (msg.parts.index === 0) { msg.payload.should.equal(1); }
- if (msg.parts.index === 1) { msg.payload.should.equal("2"); }
- if (msg.parts.index === 2) { msg.payload.should.equal(true); done(); }
- });
- sn1.receive({topic:"foo",payload:{a:1,b:"2",c:true}});
- });
- });
-
- it('should split an object into pieces and overwrite their topics', function(done) {
- var flow = [{id:"sn1", type:"split", addname:"topic", wires:[["sn2"]]},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- var count = 0;
- sn2.on("input", function(msg) {
- msg.should.have.property("payload");
- msg.should.have.property("parts");
- msg.parts.should.have.property("type","object");
- msg.parts.should.have.property("key");
- msg.parts.should.have.property("count");
- msg.parts.should.have.property("index");
- if (msg.parts.index === 0) { msg.payload.should.equal(1); msg.topic.should.equal("a"); }
- if (msg.parts.index === 1) { msg.payload.should.equal("2"); msg.topic.should.equal("b"); }
- if (msg.parts.index === 2) { msg.payload.should.equal(true); msg.topic.should.equal("c"); done(); }
- });
- sn1.receive({topic:"foo",payload:{a:1,b:"2",c:true}});
- });
- });
-
- it('should split a string into new-lines', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]]},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count",4);
- msg.parts.should.have.property("type","string");
- msg.parts.should.have.property("index");
- if (msg.parts.index === 0) { msg.payload.should.equal("Da"); }
- if (msg.parts.index === 1) { msg.payload.should.equal("ve"); }
- if (msg.parts.index === 2) { msg.payload.should.equal(" "); }
- if (msg.parts.index === 3) { msg.payload.should.equal("CJ"); done(); }
- });
- sn1.receive({payload:"Da\nve\n \nCJ"});
- });
- });
-
- it('should split a string on a specified char', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]], splt:"\n"},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count",3);
- msg.parts.should.have.property("ch","\n");
- msg.parts.should.have.property("index");
- msg.parts.should.have.property("type","string");
- if (msg.parts.index === 0) { msg.payload.should.equal("1"); }
- if (msg.parts.index === 1) { msg.payload.should.equal("2"); }
- if (msg.parts.index === 2) { msg.payload.should.equal("3"); done(); }
- });
- sn1.receive({payload:"1\n2\n3"});
- });
- });
-
- it('should split a string into lengths', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]], splt:"2", spltType:"len"},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count",4);
- msg.parts.should.have.property("ch","");
- msg.parts.should.have.property("index");
- msg.parts.should.have.property("type","string");
- if (msg.parts.index === 0) { msg.payload.should.equal("12"); }
- if (msg.parts.index === 1) { msg.payload.should.equal("34"); }
- if (msg.parts.index === 2) { msg.payload.should.equal("56"); }
- if (msg.parts.index === 3) { msg.payload.should.equal("78"); done(); }
- });
- sn1.receive({payload:"12345678"});
- });
- });
-
- it('should split a string on a specified char in stream mode', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]], splt:"\n", stream:true},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("ch","\n");
- msg.parts.should.have.property("index");
- msg.parts.should.have.property("type","string");
- if (msg.parts.index === 0) { msg.payload.should.equal("1"); }
- if (msg.parts.index === 1) { msg.payload.should.equal("2"); }
- if (msg.parts.index === 2) { msg.payload.should.equal("3"); }
- if (msg.parts.index === 3) { msg.payload.should.equal("4"); }
- if (msg.parts.index === 4) { msg.payload.should.equal("5"); }
- if (msg.parts.index === 5) { msg.payload.should.equal("6"); done(); }
- });
- sn1.receive({payload:"1\n2\n3\n"});
- sn1.receive({payload:"4\n5\n6\n"});
- });
- });
-
- it('should split a buffer into lengths', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]], splt:"2", spltType:"len"},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- try {
- //console.log(msg);
- msg.should.have.property("parts");
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.parts.should.have.property("count",4);
- msg.parts.should.have.property("index");
- msg.parts.should.have.property("type","buffer");
- if (msg.parts.index === 0) { msg.payload.toString().should.equal("12"); }
- if (msg.parts.index === 1) { msg.payload.toString().should.equal("34"); }
- if (msg.parts.index === 2) { msg.payload.toString().should.equal("56"); }
- if (msg.parts.index === 3) { msg.payload.toString().should.equal("78"); done(); }
- } catch(err) {
- done(err);
- }
- });
- var b = Buffer.from("12345678");
- sn1.receive({payload:b});
- });
- });
-
- it('should split a buffer on another buffer (streaming)', function(done) {
- var flow = [{id:"sn1", type:"split", wires:[["sn2"]], splt:"[52]", spltType:"bin", stream:true},
- {id:"sn2", type:"helper"}];
- helper.load(splitNode, flow, function() {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function(msg) {
- try {
- msg.should.have.property("parts");
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.parts.should.have.property("index");
- msg.parts.should.have.property("type","buffer");
- if (msg.parts.index === 0) { msg.payload.toString().should.equal("123"); }
- if (msg.parts.index === 1) { msg.payload.toString().should.equal("123"); }
- if (msg.parts.index === 2) { msg.payload.toString().should.equal("123"); done(); }
- } catch(err) {
- done(err);
- }
- });
- var b1 = Buffer.from("123412");
- var b2 = Buffer.from("341234");
- sn1.receive({payload:b1});
- sn1.receive({payload:b2});
- });
- });
-
- it('should handle invalid spltType (not an array)', function (done) {
- var flow = [{ id: "sn1", type: "split", splt: "1", spltType: "bin", wires: [["sn2"]] },
- { id: "sn2", type: "helper" }];
- helper.load(splitNode, flow, function () {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- sn2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- sn1.receive({ payload: "123" });
- });
- });
-
- it('should handle invalid splt length', function (done) {
- var flow = [{ id: "sn1", type: "split", splt: 0, spltType: "len", wires: [["sn2"]] },
- { id: "sn2", type: "helper" }];
- helper.load(splitNode, flow, function () {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- sn2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- sn1.receive({ payload: "123" });
- });
- });
-
- it('should handle invalid array splt length', function (done) {
- var flow = [{ id: "sn1", type: "split", arraySplt: 0, arraySpltType: "len", wires: [["sn2"]] },
- { id: "sn2", type: "helper" }];
- helper.load(splitNode, flow, function () {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- sn2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- sn1.receive({ payload: "123" });
- });
- });
-
- it('should ceil count value when msg.payload type is string', function (done) {
- var flow = [{ id: "sn1", type: "split", splt: "2", spltType: "len", wires: [["sn2"]] },
- { id: "sn2", type: "helper" }];
- helper.load(splitNode, flow, function () {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function (msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count", 2);
- msg.parts.should.have.property("index");
- if (msg.parts.index === 0) { msg.payload.length.should.equal(2); }
- if (msg.parts.index === 1) { msg.payload.length.should.equal(1); done(); }
- });
- sn1.receive({ payload: "123" });
- });
- });
-
- it('should handle spltBufferString value of undefined', function (done) {
- var flow = [{ id: "sn1", type: "split", wires: [["sn2"]], splt: "[52]", spltType: "bin" },
- { id: "sn2", type: "helper" }];
- helper.load(splitNode, flow, function () {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function (msg) {
- try {
- msg.should.have.property("parts");
- msg.parts.should.have.property("index");
- if (msg.parts.index === 0) { msg.payload.toString().should.equal("123"); done(); }
- } catch (err) {
- done(err);
- }
- });
- sn1.receive({ payload: "123" });
- });
- });
-
- it('should ceil count value when msg.payload type is Buffer', function (done) {
- var flow = [{ id: "sn1", type: "split", splt: "2", spltType: "len", wires: [["sn2"]] },
- { id: "sn2", type: "helper" }];
- helper.load(splitNode, flow, function () {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function (msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count", 2);
- msg.parts.should.have.property("index");
- if (msg.parts.index === 0) { msg.payload.length.should.equal(2); }
- if (msg.parts.index === 1) { msg.payload.length.should.equal(1); done(); }
- });
- var b = Buffer.from("123");
- sn1.receive({ payload: b });
- });
- });
-
- it('should set msg.parts.ch when node.spltType is str', function (done) {
- var flow = [{ id: "sn1", type: "split", splt: "2", spltType: "str", stream: false, wires: [["sn2"]] },
- { id: "sn2", type: "helper" }];
- helper.load(splitNode, flow, function () {
- var sn1 = helper.getNode("sn1");
- var sn2 = helper.getNode("sn2");
- sn2.on("input", function (msg) {
- msg.should.have.property("parts");
- msg.parts.should.have.property("count", 2);
- msg.parts.should.have.property("index");
- if (msg.parts.index === 0) { msg.payload.length.should.equal(2); }
- if (msg.parts.index === 1) { msg.payload.length.should.equal(1); done(); }
- });
- var b = Buffer.from("123");
- sn1.receive({ payload: b });
- });
- });
-
-});
-
-describe('JOIN node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function(done) {
- helper.unload().then(function(){
- return Context.clean({allNodes:{}});
- }).then(function(){
- return Context.close();
- }).then(function(){
- RED.settings.nodeMessageBufferMaxLength = 0;
- helper.stopServer(done);
- });
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"joinNode1", type:"join", name:"joinNode" }];
- helper.load(joinNode, flow, function() {
- var joinNode1 = helper.getNode("joinNode1");
- joinNode1.should.have.property('name', 'joinNode');
- joinNode1.should.have.property('count', 0);
- joinNode1.should.have.property('timer', 0);
- joinNode1.should.have.property('build', 'array');
- done();
- });
- });
-
- it('should join bits of string back together automatically', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], joiner:",", build:"string", mode:"auto"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal("A,B,C,D");
- done();
- }
- catch(e) {done(e);}
- });
- n1.receive({payload:"A", parts:{id:1, type:"string", ch:",", index:0, count:4}});
- n1.receive({payload:"B", parts:{id:1, type:"string", ch:",", index:1, count:4}});
- n1.receive({payload:"C", parts:{id:1, type:"string", ch:",", index:2, count:4}});
- n1.receive({payload:"D", parts:{id:1, type:"string", ch:",", index:3, count:4}});
- });
- });
- it('should join bits of string back together automatically with a buffer joiner', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], joiner:"[44]", joinerType:"bin", build:"string", mode:"auto"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal("A,B,C,D");
- done();
- }
- catch(e) {done(e);}
- });
- n1.receive({payload:"A", parts:{id:1, type:"string", ch:",", index:0, count:4}});
- n1.receive({payload:"B", parts:{id:1, type:"string", ch:",", index:1, count:4}});
- n1.receive({payload:"C", parts:{id:1, type:"string", ch:",", index:2, count:4}});
- n1.receive({payload:"D", parts:{id:1, type:"string", ch:",", index:3, count:4}});
- });
- });
-
- it('should join bits of buffer back together automatically', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], joiner:",", build:"buffer", mode:"auto"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.payload.toString().should.equal("A-B-C-D");
- done();
- }
- catch(e) {done(e);}
- });
- n1.receive({payload:Buffer.from("A"), parts:{id:1, type:"buffer", ch:Buffer.from("-"), index:0, count:4}});
- n1.receive({payload:Buffer.from("B"), parts:{id:1, type:"buffer", ch:Buffer.from("-"), index:1, count:4}});
- n1.receive({payload:Buffer.from("C"), parts:{id:1, type:"buffer", ch:Buffer.from("-"), index:2, count:4}});
- n1.receive({payload:Buffer.from("D"), parts:{id:1, type:"buffer", ch:Buffer.from("-"), index:3, count:4}});
- });
- });
-
- it('should join things into an array after a count', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], count:3, joiner:",",mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- msg.payload[0].should.equal(1);
- msg.payload[1].should.equal(true);
- //msg.payload[2].a.should.equal(1);
- done();
- }
- catch(e) {done(e);}
- });
- n1.receive({payload:1});
- n1.receive({payload:true});
- n1.receive({payload:{a:1}});
- });
- });
- it('should join things into an array ignoring msg.parts.index in manual mode', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], count:3, joiner:",",mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- msg.payload[0].should.equal(1);
- msg.payload[1].should.equal(true);
- //msg.payload[2].a.should.equal(1);
- done();
- }
- catch(e) {done(e);}
- });
- n1.receive({payload:1, parts: {index: 3}});
- n1.receive({payload:true, parts: {index: 0}});
- n1.receive({payload:{a:1}, parts: {index: 9}});
- });
- });
-
- it('should join things into an array after a count with a buffer join set', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], count:3, joinerType:"bin", joiner:"" ,mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- msg.payload[0].should.equal(1);
- msg.payload[1].should.equal(true);
- //msg.payload[2].a.should.equal(1);
- done();
- }
- catch(e) {done(e);}
- });
- n1.receive({payload:1});
- n1.receive({payload:true});
- n1.receive({payload:{a:1}});
- });
- });
-
- it('should join strings into a buffer after a count', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], count:2, build:"buffer", joinerType:"bin", joiner:"", mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.length.should.equal(10);
- msg.payload.toString().should.equal("helloworld");
- done();
- }
- catch(e) {done(e);}
- });
- n1.receive({payload:"hello"});
- n1.receive({payload:"world"});
- });
- });
-
- it('should join things into an object after a count', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], count:5, build:"object", mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("a",1);
- msg.payload.should.have.property("b","2");
- msg.payload.should.have.property("c",true);
- msg.payload.should.have.property("d");
- msg.payload.d.should.have.property("e",7);
- // msg.payload.should.have.property("g");
- // msg.payload.g.should.have.property("f",6);
- done();
- }
- catch(e) { done(e)}
- });
- n1.receive({payload:1, topic:"a"});
- n1.receive({payload:"2", topic:"b"});
- n1.receive({payload:true, topic:"c"});
- n1.receive({payload:{e:5}, topic:"d"});
- n1.receive({payload:{e:7}, topic:"d"});
- n1.receive({payload:{f:6}, topic:"g"});
- });
- });
-
- it('should merge objects', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], count:5, build:"merged", mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("a",1);
- msg.payload.should.have.property("b",2);
- msg.payload.should.have.property("c",3);
- msg.payload.should.have.property("d",4);
- msg.payload.should.have.property("e",5);
- done();
- }
- catch(e) { done(e)}
- });
- n1.receive({payload:{a:9}, topic:"f"});
- n1.receive({payload:{a:1}, topic:"a"});
- n1.receive({payload:{b:9}, topic:"b"});
- n1.receive({payload:{b:2}, topic:"b"});
- n1.receive({payload:{c:3}, topic:"c"});
- n1.receive({payload:{d:4}, topic:"d"});
- n1.receive({payload:{e:5}, topic:"e"});
- });
- });
-
- it('should merge full msg objects', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], count:6, build:"merged", mode:"custom", propertyType:"full", property:""},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.have.property("payload",7);
- msg.payload.should.have.property("aha",'c');
- msg.payload.should.have.property("bar",'b');
- msg.payload.should.have.property("bingo",'e');
- msg.payload.should.have.property("foo",'d');
- msg.payload.should.have.property("topic",'a');
- done();
- }
- catch(e) { done(e)}
- });
- n1.receive({payload:1, topic:"f"});
- n1.receive({payload:2, topic:"a"});
- n1.receive({payload:3, foo:"b"});
- n1.receive({payload:4, bar:"b"});
- n1.receive({payload:5, aha:"c"});
- n1.receive({payload:6, foo:"d"});
- n1.receive({payload:7, bingo:"e"});
- });
- });
-
- it('should accumulate a merged object', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"merged",mode:"custom",accumulate:true, count:3},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 3) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("a",3);
- msg.payload.should.have.property("b",2);
- msg.payload.should.have.property("c",1);
- done();
- }
- catch(e) { done(e) }
- }
- c += 1;
- });
- n1.receive({payload:{a:1}, topic:"a"});
- n1.receive({payload:{b:2}, topic:"b"});
- n1.receive({payload:{c:3}, topic:"c"});
- n1.receive({payload:{a:3}, topic:"d"});
- n1.receive({payload:{b:2}, topic:"e"});
- n1.receive({payload:{c:1}, topic:"f"});
- });
- });
-
- it('should be able to reset an accumulation', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"merged",accumulate:true,mode:"custom", count:3},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- if (c === 1) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("a",1);
- msg.payload.should.have.property("b",2);
- msg.payload.should.have.property("c",3);
- msg.payload.should.have.property("d",4);
- }
- catch(e) { done(e) }
- }
- if (c === 2) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("e",2);
- msg.payload.should.have.property("f",1);
- }
- catch(e) { done(e) }
- }
- if (c === 3) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("g",2);
- msg.payload.should.have.property("h",1);
- msg.payload.should.have.property("i",3);
- done();
- }
- catch(e) { done(e) }
- }
- c += 1;
- });
- n1.receive({payload:{a:1}, topic:"a"});
- n1.receive({payload:{b:2}, topic:"b"});
- n1.receive({payload:{c:3}, topic:"c"});
- n1.receive({payload:{d:4}, topic:"d", complete:true});
- n1.receive({payload:{e:2}, topic:"e"});
- n1.receive({payload:{f:1}, topic:"f", complete:true});
- n1.receive({payload:{g:2}, topic:"g"});
- n1.receive({payload:{h:1}, topic:"h"});
- n1.receive({reset:true});
- n1.receive({payload:{g:2}, topic:"g"});
- n1.receive({payload:{h:1}, topic:"h"});
- n1.receive({payload:{i:3}, topic:"i"});
- });
- });
-
- it('should accumulate a key/value object', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"object", accumulate:true, mode:"custom", topic:"bar", key:"foo", count:4},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- //msg.should.have.property("topic","bar");
- msg.should.have.property("payload");
- msg.payload.should.have.property("a",1);
- msg.payload.should.have.property("b",2);
- msg.payload.should.have.property("c",3);
- msg.payload.should.have.property("d",4);
- done();
- }
- catch(e) { done(e) }
- });
- n1.receive({payload:2, foo:"b"});
- n1.receive({payload:3, foo:"c"});
- n1.receive({reset:true});
- n1.receive({payload:1, foo:"a"});
- n1.receive({payload:2, foo:"b"});
- n1.receive({payload:3, foo:"c"});
- n1.receive({payload:4, foo:"d"});
- });
- });
-
- it('should join strings with a specifed character after a timeout', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"string", timeout:0.05, count:"", joiner:",",mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal("a,b,c");
- done();
- }
- catch(e) { done(e) }
- });
- n1.receive({payload:"a"});
- n1.receive({payload:"b"});
- n1.receive({payload:"c"});
- });
- });
-
- it('should allow the timeout to be restarted', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"string", timeout:0.5, count:"", joiner:",",mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal("a,b,c");
- const timeTaken = (Date.now() - start)/1000;
- // Node times out after 0.5s.
- // It receives a restartTimeout after 0.4s.
- // So time taken to timeout should be approx 0.9
- timeTaken.should.be.approximately(0.9,0.15);
- done();
- }
- catch(e) { done(e) }
- });
- var start = Date.now();
- n1.receive({payload:"a"});
- setTimeout(function() {
- n1.receive({payload:"b", restartTimeout: true});
- n1.receive({payload:"c"});
- },400);
- });
- });
- it('should join strings with a specifed character and complete when told to', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"string", timeout:5, count:0, joiner:"\n",mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal("Hello\nNodeRED\nWorld\n");
- done();
- }
- catch(e) { done(e) }
- });
- n1.receive({payload:"Hello"});
- n1.receive({payload:"NodeRED"});
- n1.receive({payload:"World"});
- n1.receive({payload:'', complete:true});
- });
- });
-
- it('should join complete message objects into an array after a count', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], build:"array", timeout:0, count:3, propertyType:"full",mode:"custom"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.payload.should.be.an.Array();
- msg.payload[0].should.be.an.Object();
- msg.payload[0].should.have.property("payload","a");
- msg.payload[1].should.be.an.Object();
- msg.payload[1].should.have.property("payload","b");
- msg.payload[2].should.be.an.Object();
- msg.payload[2].should.have.property("payload","c");
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:"a"});
- n1.receive({payload:"b"});
- n1.receive({payload:"c"});
- });
- });
-
- it('should join split things back into an array', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- msg.payload[0].should.equal(1);
- msg.payload[1].should.equal(2);
- msg.payload[2].should.equal(3);
- msg.payload[3].should.equal(4);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, count:4, id:111}});
- n1.receive({payload:2, parts:{index:1, count:4, id:111}});
- n1.receive({payload:4, parts:{index:3, count:4, id:111}});
- n1.receive({payload:1, parts:{index:0, count:4, id:111}});
- });
- });
-
- it('should join split things back into an object', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.have.property("a",1);
- msg.payload.should.have.property("b",2);
- msg.payload.should.have.property("c",3);
- msg.payload.should.have.property("d",4);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, count:4, id:222, key:"c", type:"object"}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222, key:"b", type:"object"}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222, key:"d", type:"object"}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222, key:"a", type:"object"}});
- });
- });
-
- it('should join split things, send when told complete', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], timeout:0.250},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- (msg.payload[0] === undefined).should.be.true();
- msg.payload[1].should.equal(2);
- msg.payload[2].should.equal(3);
- msg.payload[3].should.equal(4);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, count:4, id:444} });
- n1.receive({payload:2, parts:{index:1, count:4, id:444} });
- n1.receive({payload:4, parts:{index:3, count:4, id:444}, complete:true});
- });
- });
-
- it('should manually join things into an array, send when told complete', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], timeout:1, mode:"custom", build:"array"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- msg.payload.length.should.equal(3);
- msg.payload[0].should.equal(1);
- msg.payload[1].should.equal(2);
- msg.payload[2].should.equal(3);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:1, topic:"A"});
- n1.receive({payload:2, topic:"B"});
- n1.receive({payload:3, topic:"C"});
- n1.receive({complete:true});
- });
- });
-
-
- it('should manually join things into an object, send when told complete', function(done) {
- var flow = [{id:"n1", type:"join", wires:[["n2"]], timeout:1, mode:"custom", build:"object"},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Object();
- Object.keys(msg.payload).length.should.equal(3);
- msg.payload.A.should.equal(1);
- msg.payload.B.should.equal(2);
- msg.payload.C.should.equal(3);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:1, topic:"A"});
- n1.receive({payload:2, topic:"B"});
- n1.receive({payload:3, topic:"C"});
- n1.receive({complete:true});
- });
- });
-
- it('should join split strings back into a word', function(done) {
- var flow = [{id:"n1", type:"join", mode:"auto", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.String();
- msg.payload.should.equal("abcd");
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:"a", parts:{type:'string',index:0, count:4, ch:"", id:555}});
- n1.receive({payload:"d", parts:{type:'string',index:3, count:4, ch:"", id:555}});
- n1.receive({payload:"c", parts:{type:'string',index:2, count:4, ch:"", id:555}});
- n1.receive({payload:"b", parts:{type:'string',index:1, count:4, ch:"", id:555}});
- });
- });
-
- it('should allow chained split-split-join-join sequences', function(done) {
- var flow = [{id:"s1", type:"split",wires:[["s2"]]},
- {id:"s2", type:"split",wires:[["j1"]]},
- {id:"j1", type:"join", mode:"auto", wires:[["j2"]]},
- {id:"j2", type:"join", mode:"auto", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var s1 = helper.getNode("s1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.eql([[1,2,3],"a\nb\nc",[7,8,9]]);
- done();
- }
- catch(e) { done(e); }
- });
- s1.receive({payload:[[1,2,3],"a\nb\nc",[7,8,9]]});
- });
- });
-
- it('should reduce messages', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+payload",
- reduceInit:"0",
- reduceInitType:"num",
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(10);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should reduce messages - count only in last part', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+payload",
- reduceInit:"0",
- reduceInitType:"num",
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(10);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, id:222}});
- n1.receive({payload:2, parts:{index:1, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4,id:222}});
- n1.receive({payload:1, parts:{index:0, id:222}});
- });
- });
-
- function checkInitTypes(itype, ival, rval, initializer, checker, done) {
- var flow = [{id:"n1", z:"f0", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A",
- reduceInit:ival,
- reduceInitType:itype,
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- if (!initializer) {
- initializer = (node, cb) => {
- cb();
- };
- }
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- initializer(n1, function () {
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- checker(msg.payload, rval);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- });
- });
- }
-
- function checkInitTypesSimple(itype, val, done) {
- checkInitTypes(itype, val, val, undefined, should.equal, done);
- }
-
- function checkInitTypesComplex(itype, ival, rval, done) {
- checkInitTypes(itype, ival, rval, undefined, should.deepEqual, done);
- }
-
- it('should reduce messages with init types (str)', function(done) {
- checkInitTypesSimple('str', "xyz", done);
- });
-
- it('should reduce messages with init types (num)', function(done) {
- checkInitTypesSimple('num', 10, done);
- });
-
- it('should reduce messages with init types (bool)', function(done) {
- checkInitTypesSimple('bool', true, done);
- });
-
- it('should reduce messages with init types (json)', function(done) {
- var ival = '{"x":"vx", "y":"vy", "z":"vz"}';
- var rval = JSON.parse(ival);
- checkInitTypesComplex('json', ival, rval, done);
- });
-
- it('should reduce messages with init types (bin)', function(done) {
- var ival = "[1,2,3]";
- var rval = Buffer.from(JSON.parse(ival));
- checkInitTypesComplex('bin', ival, rval, done);
- });
-
- it('should reduce messages with init types (JSONata)', function(done) {
- var ival = "1+2+3";
- var rval = 6;
- checkInitTypesComplex('jsonata', ival, rval, done);
- });
-
- it('should reduce messages with init types (env)', function(done) {
- function init(node, cb) {
- process.env.NR_XYZ = "nr_xyz";
- cb();
- }
- function fin(err) {
- delete process.env.NR_XYZ;
- done(err);
- }
- checkInitTypes('env', "NR_XYZ", "nr_xyz", init, should.equal, fin);
- });
-
- it('should reduce messages with init types (flow.name)', function(done) {
- function init(node, cb) {
- var context = node.context();
- context.flow.set("foo", "bar");
- cb();
- }
- checkInitTypes('flow', "foo", "bar", init, should.equal, done);
- });
-
- it('should reduce messages with init types (global.name)', function(done) {
- function init(node, cb) {
- var context = node.context();
- context.global.set("foo", "bar");
- cb();
- }
- checkInitTypes('global', "foo", "bar", init, should.equal, done);
- });
-
- it('should reduce messages using $I', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+$I",
- reduceInit:"0",
- reduceInitType:"num",
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(6);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should reduce messages with fixup', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+payload",
- reduceInit:"0",
- reduceInitType:"num",
- reduceFixup:"$A/$N",
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(2);
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:3, parts:{index:2, count:5, id:222}});
- n1.receive({payload:2, parts:{index:1, count:5, id:222}});
- n1.receive({payload:4, parts:{index:3, count:5, id:222}});
- n1.receive({payload:1, parts:{index:0, count:5, id:222}});
- n1.receive({payload:0, parts:{index:4, count:5, id:222}});
- });
- });
-
- it('should reduce messages (left)', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"'(' & $A & '+' & payload & ')'",
- reduceInit:"0",
- reduceInitType:"str",
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.String();
- msg.payload.should.equal("((((0+1)+2)+3)+4)");
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:'3', parts:{index:2, count:4, id:222}});
- n1.receive({payload:'2', parts:{index:1, count:4, id:222}});
- n1.receive({payload:'4', parts:{index:3, count:4, id:222}});
- n1.receive({payload:'1', parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should reduce messages (right)', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:true,
- reduceExp:"'(' & $A & '+' & payload & ')'",
- reduceInit:"0",
- reduceInitType:"str",
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.String();
- msg.payload.should.equal("((((0+4)+3)+2)+1)");
- done();
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:'3', parts:{index:2, count:4, id:222}});
- n1.receive({payload:'2', parts:{index:1, count:4, id:222}});
- n1.receive({payload:'4', parts:{index:3, count:4, id:222}});
- n1.receive({payload:'1', parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should reduce messages with array result', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$append($A,[payload])",
- reduceInit:"[]",
- reduceInitType:"json",
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- var payload = msg.payload;
- payload.length.should.equal(2);
- if (count == 0) {
- payload[0].should.equal(1);
- payload[1].should.equal(2);
- }
- else if (count == 1){
- payload[0].should.equal(3);
- payload[1].should.equal(4);
- done();
- }
- count++;
- }
- catch(e) { done(e); }
- });
- n1.receive({payload:1, parts:{index:0, count:2, id:222}});
- n1.receive({payload:2, parts:{index:1, count:2, id:222}});
- n1.receive({payload:3, parts:{index:2, count:2, id:333}});
- n1.receive({payload:4, parts:{index:3, count:2, id:333}});
- });
- });
-
- it('should handle too many pending messages for reduce mode', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+payload",
- reduceInit:"0",
- reduceInitType:"num",
- reduceFixup:undefined,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- RED.settings.nodeMessageBufferMaxLength = 2;
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "join";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "join");
- evt.should.have.property('msg', "join.too-many");
- done();
- }, TimeoutForErrorCase);
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should reduce messages with flow context', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+(payload*$flowContext(\"two\"))",
- reduceInit:"$flowContext(\"one\")",
- reduceInitType:"jsonata",
- reduceFixup:"$A*$flowContext(\"three\")",
- wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(((((1+1*2)+2*2)+3*2)+4*2)*3);
- done();
- }
- catch(e) { done(e); }
- });
- n1.context().flow.set("one",1);
- n1.context().flow.set("two",2);
- n1.context().flow.set("three",3);
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should reduce messages with global context', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+(payload/$globalContext(\"two\"))",
- reduceInit:"$globalContext(\"one\")",
- reduceInitType:"jsonata",
- reduceFixup:"$A*$globalContext(\"three\")",
- wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- helper.load(joinNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(((((1+1/2)+2/2)+3/2)+4/2)*3);
- done();
- }
- catch(e) { done(e); }
- });
- n1.context().global.set("one",1);
- n1.context().global.set("two",2);
- n1.context().global.set("three",3);
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- });
- });
-
- it('should reduce messages with persistable flow context', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+(payload*$flowContext(\"two\",\"memory\"))",
- reduceInit:"$flowContext(\"one\",\"memory\")",
- reduceInitType:"jsonata",
- reduceFixup:"$A*$flowContext(\"three\",\"memory\")",
- wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- helper.load(joinNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- try {
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(((((1+1*2)+2*2)+3*2)+4*2)*3);
- done();
- }
- catch(e) { done(e); }
- });
- n1.context().flow.set(["one","two","three"],[1,2,3],"memory",function(err){
- if(err){
- done(err);
- } else{
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- }
- });
- }catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('should reduce messages with persistable global context', function(done) {
- var flow = [{id:"n1", type:"join", mode:"reduce",
- reduceRight:false,
- reduceExp:"$A+(payload/$globalContext(\"two\",\"memory\"))",
- reduceInit:"$globalContext(\"one\",\"memory\")",
- reduceInitType:"jsonata",
- reduceFixup:"$A*$globalContext(\"three\",\"memory\")",
- wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- helper.load(joinNode, flow, function() {
- initContext(function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.equal(((((1+1/2)+2/2)+3/2)+4/2)*3);
- done();
- }
- catch(e) { done(e); }
- });
- n1.context().global.set(["one","two","three"],[1,2,3],"memory",function(err){
- if(err){
- done(err);
- } else{
- n1.receive({payload:3, parts:{index:2, count:4, id:222}});
- n1.receive({payload:2, parts:{index:1, count:4, id:222}});
- n1.receive({payload:4, parts:{index:3, count:4, id:222}});
- n1.receive({payload:1, parts:{index:0, count:4, id:222}});
- }
- });
- });
- });
- });
-
- it('should handle invalid JSONata reduce expression - syntax error"', function (done) {
- var flow = [{
- id: "n1", type: "join", mode: "reduce",
- reduceRight: false,
- reduceExp: "invalid expr",
- reduceInit: "0",
- reduceInitType: "num",
- reduceFixup: undefined,
- wires: [["n2"]]
- },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- n2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- n1.receive({ payload: "A", parts: { id: 1, type: "string", ch: ",", index: 0, count: 1 } });
- });
- });
-
- it('should handle invalid JSONata reduce expression - runtime error"', function (done) {
- var flow = [{
- id: "n1", type: "join", mode: "reduce",
- reduceRight: false,
- reduceExp: "$uknown()",
- reduceInit: "0",
- reduceInitType: "num",
- reduceFixup: undefined,
- wires: [["n2"]]
- },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- n2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- n1.receive({ payload: "A", parts: { id: 1, type: "string", ch: ",", index: 0, count: 1 } });
- });
- });
-
- it('should handle invalid JSONata fixup expression - syntax err"', function (done) {
- var flow = [{
- id: "n1", type: "join", mode: "reduce",
- reduceRight: false,
- reduceExp: "$A",
- reduceInit: "0",
- reduceInitType: "num",
- reduceFixup: "invalid expr",
- wires: [["n2"]]
- },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- n2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- n1.receive({ payload: "A", parts: { id: 1, type: "string", ch: ",", index: 0, count: 1 } });
- });
- });
- it('should handle invalid JSONata fixup expression - runtime err"', function (done) {
- var flow = [{
- id: "n1", type: "join", mode: "reduce",
- reduceRight: false,
- reduceExp: "$A",
- reduceInit: "0",
- reduceInitType: "num",
- reduceFixup: "$unknown()",
- wires: [["n2"]]
- },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- n2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- n1.receive({ payload: "A", parts: { id: 1, type: "string", ch: ",", index: 0, count: 1 } });
- });
- });
-
- it('should concat payload when group.type is array', function (done) {
- var flow = [{ id: "n1", type: "join", wires: [["n2"]], build: "array", mode: "auto" },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.should.be.an.Array();
- msg.payload[0].should.equal("ab");
- msg.payload[1].should.equal("cd");
- msg.payload[2].should.equal("ef");
- done();
- }
- catch (e) { done(e); }
- });
- n1.receive({ payload: "ab", parts: { id: 1, type: "array", ch: ",", index: 0, count: 3, len:2}});
- n1.receive({ payload: "cd", parts: { id: 1, type: "array", ch: ",", index: 1, count: 3, len:2}});
- n1.receive({ payload: "ef", parts: { id: 1, type: "array", ch: ",", index: 2, count: 3, len:2}});
- });
- });
-
- it('should concat payload when group.type is buffer and group.joinChar is undefined', function (done) {
- var flow = [{ id: "n1", type: "join", wires: [["n2"]], joiner: ",", build: "buffer", mode: "auto" },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.payload.toString().should.equal("ABC");
- done();
- }
- catch (e) { done(e); }
- });
- n1.receive({ payload: Buffer.from("A"), parts: { id: 1, type: "buffer", index: 0, count: 3 } });
- n1.receive({ payload: Buffer.from("B"), parts: { id: 1, type: "buffer", index: 1, count: 3 } });
- n1.receive({ payload: Buffer.from("C"), parts: { id: 1, type: "buffer", index: 2, count: 3 } });
- });
- });
-
- it('should concat payload when group.type is string and group.joinChar is not string', function (done) {
- var flow = [{ id: "n1", type: "join", wires: [["n2"]], joiner: ",", build: "buffer", mode: "auto" },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- msg.payload.toString().should.equal("A0B0C");
- done();
- }
- catch (e) { done(e); }
- });
- n1.receive({ payload: Buffer.from("A"), parts: { id: 1, type: "string", ch: Buffer.from("0"), index: 0, count: 3 } });
- n1.receive({ payload: Buffer.from("B"), parts: { id: 1, type: "string", ch: Buffer.from("0"), index: 1, count: 3 } });
- n1.receive({ payload: Buffer.from("C"), parts: { id: 1, type: "string", ch: Buffer.from("0"), index: 2, count: 3 } });
- });
- });
-
- it('should handle msg.parts property when mode is auto and parts or id are missing', function (done) {
- var flow = [{ id: "n1", type: "join", wires: [["n2"]], joiner: "[44]", joinerType: "bin", build: "string", mode: "auto" },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- done(new Error("This path does not go through."));
- });
- n1.receive({ payload: "A", parts: { type: "string", ch: ",", index: 0, count: 2 } });
- n1.receive({ payload: "B", parts: { type: "string", ch: ",", index: 1, count: 2 } });
- setTimeout(function () {
- done();
- }, TimeoutForErrorCase);
- });
- });
-
- it('should handle join an array when mode is auto and duplicate indexed parts arrive', function (done) {
- var flow = [{ id: "n1", type: "join", wires: [["n2"]], joiner: "[44]", joinerType: "bin", build: "array", mode: "auto" },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- msg.payload[0].should.equal("C");
- msg.payload[1].should.equal("D");
- done();
- }
- catch (e) { done(e); }
- });
- n1.receive({ payload: "A", parts: { id:1, type:"array", ch:",", index:0, count:2 } });
- n1.receive({ payload: "B", parts: { id:1, type:"array", ch:",", index:0, count:2 } });
- n1.receive({ payload: "C", parts: { id:1, type:"array", ch:",", index:0, count:2 } });
- n1.receive({ payload: "D", parts: { id:1, type:"array", ch:",", index:1, count:2 } });
- });
- });
-
- it('should handle join an array when using msg.parts and duplicate indexed parts arrive and being reset halfway', function (done) {
- var flow = [{ id: "n1", type: "join", wires: [["n2"]], joiner: "[44]", joinerType: "bin", build: "array", mode: "auto" },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- msg.payload[0].should.equal("D");
- msg.payload[1].should.equal("C");
- done();
- }
- catch (e) { done(e); }
- });
- n1.receive({ payload: "A", parts: { id:1, type:"array", ch:",", index:0, count:2 } });
- n1.receive({ payload: "B", parts: { id:1, type:"array", ch:",", index:0, count:2 } });
- n1.receive({ reset:true });
- n1.receive({ payload: "C", parts: { id:1, type:"array", ch:",", index:1, count:2 } });
- n1.receive({ payload: "D", parts: { id:1, type:"array", ch:",", index:0, count:2 } });
- });
- });
-
- describe('messaging API', function() {
- function mapiDoneSplitTestHelper(done, splt, spltType, stream, msgAndTimings) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js");
- const flow = [
- { id: "splitNode1", type:"split", splt, spltType, stream, wires: [[]]},
- { id: "completeNode1", type: "complete", scope: ["splitNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "catchNode1", type: "catch", scope: ["splitNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "helperNode1", type: "helper", wires: [[]] }];
- const numMsgs = msgAndTimings.length;
- helper.load([splitNode, completeNode, catchNode], flow, function () {
- const splitNode1 = helper.getNode("splitNode1");
- const helperNode1 = helper.getNode("helperNode1");
- RED.settings.nodeMessageBufferMaxLength = 2;
- const t = Date.now();
- let c = 0;
- helperNode1.on("input", function (msg) {
- msg.should.have.a.property('payload');
- (Date.now() - t).should.be.approximately(msgAndTimings[msg.seq].avr, msgAndTimings[msg.seq].var);
- c += 1;
- if (c === numMsgs) {
- done();
- }
- });
- for (let i = 0; i < numMsgs; i++) {
- setTimeout(function () { splitNode1.receive(msgAndTimings[i].msg); }, msgAndTimings[i].delay);
- }
- });
- }
- it('should call done() when message is sent (string)', function (done) {
- mapiDoneSplitTestHelper(done, 2, "len", false, [
- { msg: { seq: 0, payload: "12345" }, delay: 0, avr: 0, var: 100 },
- ]);
- });
- it('should call done() when message is sent (array)', function (done) {
- mapiDoneSplitTestHelper(done, 2, "len", false, [
- { msg: { seq: 0, payload: [0,1,2,3,4] }, delay: 0, avr: 0, var: 100 },
- ]);
- });
- it('should call done() when message is sent (object)', function (done) {
- mapiDoneSplitTestHelper(done, 2, "len", false, [
- { msg: { seq: 0, payload: {a:1,b:2}}, delay: 0, avr: 0, var: 100 },
- ]);
- });
- it('should call done() when consolidated message is emitted (string, len)', function (done) {
- mapiDoneSplitTestHelper(done, 5, "len", true, [
- { msg: { seq: 0, payload: "12"}, delay: 0, avr: 500, var: 100 },
- { msg: { seq: 1, payload: "34"}, delay: 200, avr: 500, var: 100 },
- { msg: { seq: 2, payload: "5"}, delay: 500, avr: 500, var: 100 }
- ]);
- });
- it('should call done() when consolidated message is emitted (Buffer, len)', function (done) {
- mapiDoneSplitTestHelper(done, 5, "len", true, [
- { msg: { seq: 0, payload: Buffer.from("12")}, delay: 0, avr: 500, var: 100 },
- { msg: { seq: 1, payload: Buffer.from("34")}, delay: 200, avr: 500, var: 100 },
- { msg: { seq: 2, payload: Buffer.from("5")}, delay: 500, avr: 500, var: 100 }
- ]);
- });
- it('should call done() when consolidated message is emitted (Buffer, str)', function (done) {
- mapiDoneSplitTestHelper(done, "5", "str", true, [
- { msg: { seq: 0, payload: Buffer.from("12")}, delay: 0, avr: 500, var: 100 },
- { msg: { seq: 1, payload: Buffer.from("34")}, delay: 200, avr: 500, var: 100 },
- { msg: { seq: 2, payload: Buffer.from("5")}, delay: 500, avr: 500, var: 100 }
- ]);
- });
- it('should call done() when consolidated message is emitted (Buffer, bin)', function (done) {
- mapiDoneSplitTestHelper(done, "[53]", "bin", true, [
- { msg: { seq: 0, payload: Buffer.from("12")}, delay: 0, avr: 500, var: 100 },
- { msg: { seq: 1, payload: Buffer.from("34")}, delay: 200, avr: 500, var: 100 },
- { msg: { seq: 2, payload: Buffer.from("5")}, delay: 500, avr: 500, var: 100 }
- ]);
- });
-
- function mapiDoneJoinTestHelper(done, joinNodeSetting, msgAndTimings) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js");
- const flow = [
- { ...joinNodeSetting, id: "joinNode1", type:"join", wires: [[]]},
- { id: "completeNode1", type: "complete", scope: ["joinNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "catchNode1", type: "catch", scope: ["joinNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "helperNode1", type: "helper", wires: [[]] }];
- const numMsgs = msgAndTimings.length;
- helper.load([joinNode, completeNode, catchNode], flow, function () {
- const joinNode1 = helper.getNode("joinNode1");
- const helperNode1 = helper.getNode("helperNode1");
- RED.settings.nodeMessageBufferMaxLength = 3;
- const t = Date.now();
- let c = 0;
- helperNode1.on("input", function (msg) {
- msg.should.have.a.property('payload');
- (Date.now() - t).should.be.approximately(msgAndTimings[msg.seq].avr, msgAndTimings[msg.seq].var);
- c += 1;
- if (c === numMsgs) {
- done();
- }
- });
- for (let i = 0; i < numMsgs; i++) {
- setTimeout(function () { joinNode1.receive(msgAndTimings[i].msg); }, msgAndTimings[i].delay);
- }
- });
- }
- it('should call done() when all messages are joined', function (done) {
- mapiDoneJoinTestHelper(done, {mode:"auto", timeout:1}, [
- { msg: {seq:0, payload:"A", parts:{id:1, type:"string", ch:",", index:0, count:3}}, delay:0, avr:500, var:100},
- { msg: {seq:1, payload:"B", parts:{id:1, type:"string", ch:",", index:1, count:3}}, delay:200, avr:500, var:100},
- { msg: {seq:2, payload:"C", parts:{id:1, type:"string", ch:",", index:2, count:3}}, delay:500, avr:500, var:100}
- ]);
- });
- it('should call done() when the node is reset', function (done) {
- mapiDoneJoinTestHelper(done, {mode:"auto", timeout:1}, [
- { msg: {seq:0, payload:"A", parts:{id:1, type:"string", ch:",", index:0, count:3}}, delay:0, avr:500, var:100},
- { msg: {seq:1, payload:"B", parts:{id:1, type:"string", ch:",", index:1, count:3}}, delay:200, avr:500, var:100},
- { msg: {seq:2, payload:"dummy", reset: true, parts:{id:1}}, delay:500, avr:500, var:100}
- ]);
- });
- it('should call done() when timed out', function (done) {
- mapiDoneJoinTestHelper(done, {mode:"custom", joiner:",", build:"string", timeout:0.5}, [
- { msg: {seq:0, payload:"A"}, delay:0, avr:500, var:100},
- { msg: {seq:1, payload:"B"}, delay:200, avr:500, var:100},
- ]);
- });
- it('should call done() when all messages are reduced', function (done) {
- mapiDoneJoinTestHelper(done, {mode:"reduce", reduceRight:false, reduceExp:"$A+payload", reduceInit:"0",
- reduceInitType:"num", reduceFixup:undefined}, [
- { msg: {seq:0, payload:3, parts: {index:2, count:3, id:222}}, delay:0, avr:500, var:100},
- { msg: {seq:1, payload:2, parts: {index:1, count:3, id:222}}, delay:200, avr:500, var:100},
- { msg: {seq:2, payload:4, parts: {index:0, count:3, id:222}}, delay:500, avr:500, var:100}
- ]);
- });
- it('should call done() regardless of buffer overflow', function (done) {
- mapiDoneJoinTestHelper(done, {mode:"reduce", reduceRight:false, reduceExp:"$A+payload", reduceInit:"0",
- reduceInitType:"num", reduceFixup:undefined}, [
- { msg: {seq:0, payload:3, parts: {index:2, count:5, id:222}}, delay:0, avr:600, var:100},
- { msg: {seq:1, payload:2, parts: {index:1, count:5, id:222}}, delay:200, avr:600, var:100},
- { msg: {seq:2, payload:4, parts: {index:0, count:5, id:222}}, delay:400, avr:600, var:100},
- { msg: {seq:3, payload:1, parts: {index:3, count:5, id:222}}, delay:600, avr:600, var:100},
- ]);
- });
- });
-
- it('should handle msg.parts even if messages are out of order in auto mode if exactly one message has count set', function (done) {
- var flow = [{ id: "n1", type: "join", wires: [["n2"]], mode: "auto" },
- { id: "n2", type: "helper" }];
- helper.load(joinNode, flow, function () {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
-
- n2.on("input", function (msg) {
- msg.payload.length.should.be.eql(5);
- msg.payload.should.be.eql([0,1,2,3,4]);
- done();
- });
-
- var msg = {};
- msg.parts = {
- id: RED.util.generateId()
- };
- for(var elem = 1; elem < 5; ++elem) {
- var _msg = RED.util.cloneMessage(msg);
- _msg.parts.index = elem;
- if(elem == 4) {
- _msg.parts.count = 5;
- }
- _msg.payload = elem;
- n1.receive(_msg);
- }
-
- var _msg = RED.util.cloneMessage(msg);
- delete _msg.parts.count;
- _msg.parts.index = 0;
- _msg.payload = 0;
- n1.receive(_msg);
- });
-
- })
-
-});
diff --git a/test/nodes/core/sequence/18-sort_spec.js b/test/nodes/core/sequence/18-sort_spec.js
deleted file mode 100644
index 955038bfb..000000000
--- a/test/nodes/core/sequence/18-sort_spec.js
+++ /dev/null
@@ -1,554 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sortNode = require("nr-test-utils").require("@node-red/nodes/core/sequence/18-sort.js");
-var helper = require("node-red-node-test-helper");
-var RED = require("nr-test-utils").require("node-red/lib/red.js");
-var Context = require("nr-test-utils").require("@node-red/runtime/lib/nodes/context");
-
-describe('SORT node', function() {
-
- beforeEach(function(done) {
- helper.startServer(done);
- });
-
- function initContext(done) {
- Context.init({
- contextStorage: {
- memory: {
- module: "memory"
- }
- }
- });
- Context.load().then(function () {
- done();
- });
- }
-
- afterEach(function(done) {
- helper.unload().then(function(){
- RED.settings.nodeMessageBufferMaxLength = 0;
- helper.stopServer(done);
- });
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, name: "SortNode", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'SortNode');
- done();
- });
- });
-
- function check_sort0(flow, target, key, key_type, data_in, data_out, done) {
- var sort = flow[0];
- sort.target = target;
- sort.targetType = "msg";
- sort.msgKey = key;
- sort.msgKeyType = key_type;
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property(target);
- var data = msg[target];
- data.length.should.equal(data_out.length);
- for(var i = 0; i < data_out.length; i++) {
- var data0 = data[i];
- var data1 = data_out[i];
- if (typeof data0 === "object") {
- data0.should.deepEqual(data1);
- }
- else {
- data0.should.equal(data1);
- }
- }
- done();
- }
- catch(e) {
- console.log(e);
- }
- });
- var msg = {};
- msg[target] = data_in;
- n1.receive(msg);
- });
- }
-
- function check_sort0A(flow, data_in, data_out, done) {
- check_sort0(flow, "payload", "", "elem", data_in, data_out, done);
- }
-
- function check_sort0B(flow, data_in, data_out, done) {
- check_sort0(flow, "data", "", "elem", data_in, data_out, done);
- }
-
- function check_sort0C(flow, exp, data_in, data_out, done) {
- check_sort0(flow, "data", exp, "jsonata", data_in, data_out, done);
- }
-
- function check_sort1(flow, key, key_type, data_in, data_out, done) {
- function equals(v0, v1) {
- var k0 = Object.keys(v0);
- var k1 = Object.keys(v1);
-
- if (k0.length === k1.length) {
- for (var i = 0; i < k0.length; i++) {
- var k = k0[i];
- if (!v1.hasOwnProperty(k) ||
- (v0[k] !== v1[k])) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
- function indexOf(a, v) {
- for(var i = 0; i < a.length; i++) {
- var av = a[i];
- if ((typeof v === 'object') && equals(v, av)) {
- return i;
- }
- else if (v === av) {
- return i;
- }
- }
- return -1;
- }
- var sort = flow[0];
- var prop = (key_type === "msg") ? key : "payload";
- sort.targetType = "seq";
- sort.seqKey = key;
- sort.seqKeyType = key_type;
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n2.on("input", function(msg) {
- msg.should.have.property(prop);
- msg.should.have.property("parts");
- msg.parts.should.have.property("count", data_out.length);
- var data = msg[prop];
- var index = indexOf(data_out, data);
- msg.parts.should.have.property("index", index);
- count++;
- if (count === data_out.length) {
- done();
- }
- });
- var len = data_in.length;
- for(var i = 0; i < len; i++) {
- var parts = { id: "X", index: i, count: len };
- var msg = {parts: parts};
- msg[prop] = data_in[i];
- n1.receive(msg);
- }
- });
- }
-
- function check_sort1A(flow, data_in, data_out, done) {
- check_sort1(flow, "payload", "msg", data_in, data_out, done);
- }
-
- function check_sort1B(flow, data_in, data_out, done) {
- check_sort1(flow, "data", "msg", data_in, data_out, done);
- }
-
- function check_sort1C(flow, exp, data_in, data_out, done) {
- check_sort1(flow, exp, "jsonata", data_in, data_out, done);
- }
-
- (function() {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var data_in = [ "200", "4", "30", "1000" ];
- var data_out = [ "1000", "200", "30", "4" ];
- it('should sort payload (elem, not number, ascending)', function(done) {
- check_sort0A(flow, data_in, data_out, done);
- });
- it('should sort msg prop (elem, not number, ascending)', function(done) {
- check_sort0B(flow, data_in, data_out, done);
- });
- it('should sort message group/payload (not number, ascending)', function(done) {
- check_sort1A(flow, data_in, data_out, done);
- });
- it('should sort message group/prop (not number, ascending)', function(done) {
- check_sort1B(flow, data_in, data_out, done);
- });
- })();
-
- (function() {
- var flow = [{id:"n1", type:"sort", order:"descending", as_num:false, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var data_in = [ "200", "4", "30", "1000" ];
- var data_out = [ "4", "30", "200", "1000" ];
- it('should sort payload (elem, not number, descending)', function(done) {
- check_sort0A(flow, data_in, data_out, done);
- });
- it('should sort msg prop (elem, not number, descending)', function(done) {
- check_sort0B(flow, data_in, data_out, done);
- });
- it('should sort message group/payload (not number, descending)', function(done) {
- check_sort1A(flow, data_in, data_out, done);
- });
- it('should sort message group/prop (not number, descending)', function(done) {
- check_sort1B(flow, data_in, data_out, done);
- });
- })();
-
- (function() {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:true, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var data_in = [ "200", "4", "30", "1000" ];
- var data_out = [ "4", "30", "200", "1000" ];
- it('should sort payload (elem, number, ascending)', function(done) {
- check_sort0A(flow, data_in, data_out, done);
- });
- it('should sort msg prop (elem, number, ascending)', function(done) {
- check_sort0B(flow, data_in, data_out, done);
- });
- it('should sort message group/payload (number, ascending)', function(done) {
- check_sort1A(flow, data_in, data_out, done);
- });
- it('should sort message group/prop (number, ascending)', function(done) {
- check_sort1B(flow, data_in, data_out, done);
- });
- })();
-
- (function() {
- var flow = [{id:"n1", type:"sort", order:"descending", as_num:true, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var data_in = [ "200", "4", "30", "1000" ];
- var data_out = [ "1000", "200", "30", "4" ];
- it('should sort payload (elem, number, descending)', function(done) {
- check_sort0A(flow, data_in, data_out, done);
- });
- it('should sort msg prop (elem, number, descending)', function(done) {
- check_sort0B(flow, data_in, data_out, done);
- });
- it('should sort message group/payload (number, descending)', function(done) {
- check_sort1A(flow, data_in, data_out, done);
- });
- it('should sort message group/prop (number, descending)', function(done) {
- check_sort1B(flow, data_in, data_out, done);
- });
- })();
-
- (function() {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var data_in = [ "C200", "A4", "B30", "D1000" ];
- var data_out = [ "D1000", "C200", "B30", "A4" ];
- it('should sort payload (exp, not number, ascending)', function(done) {
- check_sort0C(flow, "$substring($,1)", data_in, data_out, done);
- });
- it('should sort message group (exp, not number, ascending)', function(done) {
- check_sort1C(flow, "$substring(payload,1)", data_in, data_out, done);
- });
- })();
-
- (function() {
- var flow = [{id:"n1", type:"sort", order:"descending", as_num:false, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var data_in = [ "C200", "A4", "B30", "D1000" ];
- var data_out = [ "A4", "B30", "C200", "D1000" ];
- it('should sort message group (exp, not number, descending)', function(done) {
- check_sort0C(flow, "$substring($,1)", data_in, data_out, done);
- });
- it('should sort payload (exp, not number, descending)', function(done) {
- check_sort1C(flow, "$substring(payload,1)", data_in, data_out, done);
- });
- })();
-
- (function() {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:true, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var conv = function(x) {
- return x.map(function(v) { return { val:v }; });
- };
- var data_in = conv([ "200", "4", "30", "1000" ]);
- var data_out = conv([ "4", "30", "200", "1000" ]);
- it('should sort payload of objects', function(done) {
- check_sort0C(flow, "val", data_in, data_out, done);
- });
- })();
-
- it('should sort payload by context (exp, not number, ascending)', function(done) {
- var flow = [{id:"n1", type:"sort", target:"data", targetType:"msg", msgKey:"$flowContext($)", msgKeyType:"jsonata", order:"ascending", as_num:false, wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- var data_in = [ "first", "second", "third", "fourth" ];
- var data_out = [ "second", "third", "first", "fourth" ];
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context()["flow"].set("first","3");
- n1.context()["flow"].set("second","1");
- n1.context()["flow"].set("third","2");
- n1.context()["flow"].set("fourth","4");
- n2.on("input", function(msg) {
- msg.should.have.property("data");
- var data = msg["data"];
- data.length.should.equal(data_out.length);
- for(var i = 0; i < data_out.length; i++) {
- data[i].should.equal(data_out[i]);
- }
- done();
- });
- var msg = {};
- msg["data"] = data_in;
- n1.receive(msg);
- });
- });
-
- it('should sort message group by context (exp, not number, ascending)', function(done) {
- var flow = [{id:"n1", type:"sort", target:"data", targetType:"seq", seqKey:"$globalContext(payload)", seqKeyType:"jsonata", order:"ascending", as_num:false, wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- var data_in = [ "first", "second", "third", "fourth" ];
- var data_out = [ "second", "fourth", "third", "first" ];
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n1.context()["global"].set("first","4");
- n1.context()["global"].set("second","1");
- n1.context()["global"].set("third","3");
- n1.context()["global"].set("fourth","2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("payload");
- msg.should.have.property("parts");
- msg.parts.should.have.property("count", data_out.length);
- var data = msg["payload"];
- var index = data_out.indexOf(data);
- msg.parts.should.have.property("index", index);
- count++;
- if (count === data_out.length) {
- done();
- }
- }
- catch(e) {
- done(e);
- }
- });
- var len = data_in.length;
- for(var i = 0; i < len; i++) {
- var parts = { id: "X", index: i, count: len };
- var msg = {parts: parts};
- msg["payload"] = data_in[i];
- n1.receive(msg);
- }
- });
- });
-
- it('should sort payload by persistable context (exp, not number, descending)', function(done) {
- var flow = [{id:"n1", type:"sort", target:"data", targetType:"msg", msgKey:"$globalContext($,\"memory\")", msgKeyType:"jsonata", order:"descending", as_num:false, wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- var data_in = [ "first", "second", "third", "fourth" ];
- var data_out = [ "fourth", "first", "third", "second" ];
- helper.load(sortNode, flow, function() {
- initContext(function(){
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n1.context()["global"].set(["first","second","third","fourth"],["3","1","2","4"],"memory",function(){
- n2.on("input", function(msg) {
- msg.should.have.property("data");
- var data = msg["data"];
- data.length.should.equal(data_out.length);
- for(var i = 0; i < data_out.length; i++) {
- data[i].should.equal(data_out[i]);
- }
- done();
- });
- var msg = {};
- msg["data"] = data_in;
- n1.receive(msg);
- });
- });
- });
- });
-
- it('should sort message group by persistable context (exp, not number, descending)', function(done) {
- var flow = [{id:"n1", type:"sort", target:"data", targetType:"seq", seqKey:"$flowContext(payload,\"memory\")", seqKeyType:"jsonata", order:"descending", as_num:false, wires:[["n2"]],z:"flow"},
- {id:"n2", type:"helper",z:"flow"},
- {id:"flow", type:"tab"}];
- var data_in = [ "first", "second", "third", "fourth" ];
- var data_out = [ "first", "third", "fourth", "second" ];
- helper.load(sortNode, flow, function() {
- initContext(function(){
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- n1.context()["flow"].set(["first","second","third","fourth"],["4","1","3","2"],"memory",function(){
- n2.on("input", function(msg) {
- msg.should.have.property("payload");
- msg.should.have.property("parts");
- msg.parts.should.have.property("count", data_out.length);
- var data = msg["payload"];
- var index = data_out.indexOf(data);
- msg.parts.should.have.property("index", index);
- count++;
- if (count === data_out.length) {
- done();
- }
- });
- var len = data_in.length;
- for(var i = 0; i < len; i++) {
- var parts = { id: "X", index: i, count: len };
- var msg = {parts: parts};
- msg["payload"] = data_in[i];
- n1.receive(msg);
- }
- });
- });
- });
- });
-
- it('should handle JSONata script error', function(done) {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, target:"payload", targetType:"seq", seqKey:"$unknown()", seqKeyType:"jsonata", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "sort";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "sort");
- evt.should.have.property('msg', "sort.invalid-exp");
- done();
- }, 150);
- var msg0 = { payload: "A", parts: { id: "X", index: 0, count: 2} };
- var msg1 = { payload: "B", parts: { id: "X", index: 1, count: 2} };
- n1.receive(msg0);
- n1.receive(msg1);
- });
- });
-
- it('should handle too many pending messages', function(done) {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, target:"payload", targetType:"seq", seqKey:"payload", seqKeyType:"msg", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- RED.settings.nodeMessageBufferMaxLength = 2;
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "sort";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "sort");
- evt.should.have.property('msg', "sort.too-many");
- done();
- }, 150);
- for(var i = 0; i < 4; i++) {
- var msg = { payload: "V"+i,
- parts: { id: "X", index: i, count: 4} };
- n1.receive(msg);
- }
- });
- });
-
- it('should clear pending messages on close', function(done) {
- var flow = [{id:"n1", type:"sort", order:"ascending", as_num:false, target:"payload", targetType:"seq", seqKey:"payload", seqKeyType:"msg", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(sortNode, flow, function() {
- var n1 = helper.getNode("n1");
- var msg = { payload: 0,
- parts: { id: "X", index: 0, count: 2} };
- n1.receive(msg);
- setTimeout(function() {
- n1.close().then(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "sort";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "sort");
- evt.should.have.property('msg', "sort.clear");
- done();
- });
- }, 150);
- });
- });
-
- describe('messaging API', function() {
- function mapiDoneTestHelper(done, targetType, msgAndTimings) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js");
- const flow = [
- {id: "sortNode1", type: "sort", order: "ascending", as_num: false, target: "payload", targetType,
- seqKey: "payload", seqKeyType: "msg", wires: [[]]},
- { id: "completeNode1", type: "complete", scope: ["sortNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "catchNode1", type: "catch", scope: ["sortNode1"], uncaught: false, wires: [["helperNode1"]] },
- { id: "helperNode1", type: "helper", wires: [[]] }];
- const numMsgs = msgAndTimings.length;
- helper.load([sortNode, completeNode, catchNode], flow, function () {
- const sortNode1 = helper.getNode("sortNode1");
- const helperNode1 = helper.getNode("helperNode1");
- RED.settings.nodeMessageBufferMaxLength = 2;
- const t = Date.now();
- let c = 0;
- helperNode1.on("input", function (msg) {
- msg.should.have.a.property('payload');
- (Date.now() - t).should.be.approximately(msgAndTimings[msg.seq].avr, msgAndTimings[msg.seq].var);
- c += 1;
- if (c === numMsgs) {
- done();
- }
- });
- for (let i = 0; i < numMsgs; i++) {
- setTimeout(function () { sortNode1.receive(msgAndTimings[i].msg); }, msgAndTimings[i].delay);
- }
- });
- }
- it('should call done() when message is sent (payload)', function (done) {
- mapiDoneTestHelper(done, "msg", [
- { msg: { seq: 0, payload: [1, 3, 2] }, delay: 0, avr: 0, var: 100 },
- ]);
- });
- it('should call done() when message is sent (sequence)', function (done) {
- mapiDoneTestHelper(done, "seq", [
- { msg: { seq: 0, payload: 3, parts: {id:"A", index: 0, count: 2}}, delay: 0, avr: 500, var: 100 },
- { msg: { seq: 1, payload: 2, parts: {id:"A", index: 1, count: 2}}, delay: 500, avr: 500, var: 100}
- ]);
- });
- it('should call done() regardless of buffer overflow (same group)', function (done) {
- mapiDoneTestHelper(done, "seq", [
- { msg: { seq: 0, payload: 1, parts: {id:"A", index: 0, count: 3}}, delay: 0, avr: 1000, var: 100 },
- { msg: { seq: 1, payload: 3, parts: {id:"A", index: 1, count: 3}}, delay: 500, avr: 1000, var: 100 },
- { msg: { seq: 2, payload: 2, parts: {id:"A", index: 2, count: 3}}, delay: 1000, avr: 1000, var: 100 },
- ]);
- });
- it('should call done() regardless of buffer overflow (different group)', function (done) {
- mapiDoneTestHelper(done, "seq", [
- { msg: { seq: 0, payload: 1, parts: {id:"A", index: 0, count: 2}}, delay: 0, avr: 1000, var: 100 },
- { msg: { seq: 1, payload: 3, parts: {id:"B", index: 0, count: 2}}, delay: 500, avr: 1200, var: 100 },
- { msg: { seq: 2, payload: 5, parts: {id:"C", index: 0, count: 2}}, delay: 1000, avr: 1500, var: 100 },
- { msg: { seq: 3, payload: 2, parts: {id:"B", index: 1, count: 2}}, delay: 1200, avr: 1200, var: 100 },
- { msg: { seq: 4, payload: 4, parts: {id:"C", index: 1, count: 2}}, delay: 1500, avr: 1500, var: 100 },
- ]);
- });
- });
-});
diff --git a/test/nodes/core/sequence/19-batch_spec.js b/test/nodes/core/sequence/19-batch_spec.js
deleted file mode 100644
index 2ebcb8d4d..000000000
--- a/test/nodes/core/sequence/19-batch_spec.js
+++ /dev/null
@@ -1,542 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var batchNode = require("nr-test-utils").require("@node-red/nodes/core/sequence/19-batch.js");
-var helper = require("node-red-node-test-helper");
-var RED = require("nr-test-utils").require("node-red/lib/red.js");
-
-describe('BATCH node', function() {
- this.timeout(8000);
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- RED.settings.nodeMessageBufferMaxLength = 0;
- });
-
- it('should be loaded with defaults', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- n1.should.have.property('name', 'BatchNode');
- done();
- });
- });
-
- function check_parts(msg, id, idx, count) {
- msg.should.have.property("parts");
- var parts = msg.parts;
- parts.should.have.property("id", id);
- parts.should.have.property("index", idx);
- parts.should.have.property("count", count);
- }
-
- function check_data(n1, n2, results, done) {
- var id = undefined;
- var ix0 = 0; // seq no
- var ix1 = 0; // loc. in seq
- var seq = undefined;
- var msgs = [];
- n2.on("input", function(msg) {
- try {
- for (var i = 0; i < msgs.length; i++) {
- msg.should.not.equal(msgs[i]);
- }
- msgs.push(msg);
- if (seq === undefined) {
- seq = results[ix0];
- }
- var val = seq[ix1];
- msg.should.have.property("payload", val);
- if (id === undefined) {
- id = msg.parts.id;
- }
- check_parts(msg, id, ix1, seq.length);
- ix1++;
- if (ix1 === seq.length) {
- ix0++;
- ix1 = 0;
- seq = undefined;
- id = undefined;
- if (ix0 === results.length) {
- done();
- }
- }
- }
- catch (e) {
- done(e);
- }
- });
- }
-
- function check_count(flow, results, done) {
- try {
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- check_data(n1, n2, results, done);
- for(var i = 0; i < 6; i++) {
- n1.receive({payload: i});
- }
- });
- }
- catch (e) {
- done(e);
- }
- }
-
- function delayed_send(receiver, index, count, delay, done) {
- if (index < count) {
- setTimeout(function() {
- receiver.receive({payload: index});
- delayed_send(receiver, index+1, count, delay, done);
- }, delay);
- }
- else if(index === count) {
- if (done) {
- done();
- }
- }
- }
-
- function check_interval(flow, results, delay, done) {
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- check_data(n1, n2, results, done);
- delayed_send(n1, 0, 4, delay);
- });
- }
-
- function check_concat(flow, results, inputs, done) {
- try {
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- check_data(n1, n2, results, done);
- for(var data of inputs) {
- var msg = {
- topic: data[0],
- payload: data[1],
- parts: {
- id: data[0],
- index: data[2],
- count: data[3]
- }
- };
- n1.receive(msg);
- }
- });
- }
- catch (e) {
- done(e);
- }
- }
-
- describe('mode: count', function() {
-
- it('should create seq. with count', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 2, overlap: 0, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [0, 1],
- [2, 3],
- [4, 5]
- ];
- check_count(flow, results, done);
- });
-
- it('should create seq. with count and overlap', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 3, overlap: 2, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [0, 1, 2],
- [1, 2, 3],
- [2, 3, 4],
- [3, 4, 5]
- ];
- check_count(flow, results, done);
- });
-
- it('should handle too many pending messages', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 5, overlap: 0, interval: 10, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- RED.settings.nodeMessageBufferMaxLength = 2;
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "batch";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "batch");
- evt.should.have.property('msg', "batch.too-many");
- done();
- }, 150);
- for(var i = 0; i < 3; i++) {
- n1.receive({payload: i});
- }
- });
- });
-
- it('should handle reset', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "count", count: 2, overlap: 0, interval: 0, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var results = [
- [0, 1],
- [4, 5]
- ];
- check_data(n1, n2, results, done);
- n1.receive({payload:0});
- n1.receive({payload:1});
- n1.receive({payload:2});
- n1.receive({payload:3, reset: true});
- n1.receive({payload:4});
- n1.receive({payload:5});
- });
- });
- });
-
- describe('mode: interval', function() {
- it('should create seq. with interval', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [0, 1],
- [2, 3]
- ];
- check_interval(flow, results, 450, done);
- });
-
- it('should create seq. with interval (in float)', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overlap: 0, interval: 0.5, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [0, 1],
- [2, 3]
- ];
- check_interval(flow, results, 225, done);
- });
-
- it('should create seq. with interval & not send empty seq', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- // 1300, 2600, 3900, 5200,
- [0], [1], [2], [3]
- ];
- check_interval(flow, results, 1300, done);
- });
-
- it('should create seq. with interval & send empty seq', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overlap: 0, interval: 1, allowEmptySequence: true, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- // 1300, 2600, 3900, 5200,
- [null], [0], [1], [2], [null], [3]
- ];
- check_interval(flow, results, 1300, done);
- });
-
- it('should handle too many pending messages', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- RED.settings.nodeMessageBufferMaxLength = 2;
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "batch";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "batch");
- evt.should.have.property('msg', "batch.too-many");
- done();
- }, 150);
- for(var i = 0; i < 3; i++) {
- n1.receive({payload: i});
- }
- });
- });
-
- it('should handle reset', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "interval", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var results = [
- [0, 1],
- [4, 5]
- ];
- check_data(n1, n2, results, done);
- delayed_send(n1, 0, 3, 400, function () {
- setTimeout(function () {
- n1.receive({payload: "3", reset: true});
- delayed_send(n1, 4, 7, 400);
- }, 10);
- });
- });
- });
-
- });
-
- describe('mode: concat', function() {
- it('should concat two seq. (series)', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [2, 3, 0, 1]
- ];
- var inputs = [
- ["TB", 0, 0, 2],
- ["TB", 1, 1, 2],
- ["TA", 2, 0, 2],
- ["TA", 3, 1, 2]
- ];
- check_concat(flow, results, inputs, done);
- });
-
- it('should concat two seq. (mixed)', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [2, 3, 0, 1]
- ];
- var inputs = [
- ["TA", 2, 0, 2],
- ["TB", 0, 0, 2],
- ["TA", 3, 1, 2],
- ["TB", 1, 1, 2]
- ];
- check_concat(flow, results, inputs, done);
- });
-
- it('should concat three seq.', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}, {topic: "TC"}], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [2, 3, 0, 1, 4]
- ];
- var inputs = [
- ["TC", 4, 0, 1],
- ["TB", 0, 0, 2],
- ["TB", 1, 1, 2],
- ["TA", 2, 0, 2],
- ["TA", 3, 1, 2]
- ];
- check_concat(flow, results, inputs, done);
- });
-
- it('should concat same seq.', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TA"}], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = [
- [9, 8, 9, 8]
- ];
- var inputs = [
- ["TA", 9, 0, 2],
- ["TA", 8, 1, 2]
- ];
- check_concat(flow, results, inputs, done);
- });
-
- it('should handle too many pending messages', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- RED.settings.nodeMessageBufferMaxLength = 2;
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function (evt) {
- return evt[0].type == "batch";
- });
- var evt = logEvents[0][0];
- evt.should.have.property('id', "n1");
- evt.should.have.property('type', "batch");
- evt.should.have.property('msg', "batch.too-many");
- done();
- }, 150);
- var C = 3;
- for(var i = 0; i < C; i++) {
- var parts_a = {index:i, count:C, id:"A"};
- var parts_b = {index:i, count:C, id:"B"};
- n1.receive({payload: i, topic: "TA", parts:parts_a});
- n1.receive({payload: i, topic: "TB", parts:parts_b});
- }
- });
- });
-
- it('should handle reset', function(done) {
- var flow = [{id:"n1", type:"batch", name: "BatchNode", mode: "concat", count: 0, overlap: 0, interval: 1, allowEmptySequence: false, topics: [{topic: "TA"}, {topic: "TB"}], wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- try {
- helper.load(batchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var results = [
- [2, 3, 0, 1]
- ];
- check_data(n1, n2, results, done);
- var inputs0 = [
- ["TB", 0, 0, 2],
- ["TA", 1, 0, 2],
- ];
- for(var data of inputs0) {
- var msg = {
- topic: data[0],
- payload: data[1],
- parts: {
- id: data[0],
- index: data[2],
- count: data[3]
- }
- };
- n1.receive(msg);
- }
- n1.receive({payload: undefined, reset: true});
- var inputs1 = [
- ["TB", 0, 0, 2],
- ["TB", 1, 1, 2],
- ["TA", 2, 0, 2],
- ["TA", 3, 1, 2]
- ];
- for(var data of inputs1) {
- var msg = {
- topic: data[0],
- payload: data[1],
- parts: {
- id: data[0],
- index: data[2],
- count: data[3]
- }
- };
- n1.receive(msg);
- }
- });
- }
- catch (e) {
- done(e);
- }
- });
- });
-
- describe('messaging API', function() {
- function mapiDoneTestHelper(done, mode, count, overlap, interval, allowEmptySequence, msgAndTimings) {
- const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
- const catchNode = require("nr-test-utils").require("@node-red/nodes/core/common/25-catch.js");
- const flow = [{id:"batchNode1", type:"batch", name: "BatchNode", mode, count, overlap, interval,
- allowEmptySequence, topics: [{topic: "TA"}], wires:[[]]},
- {id:"completeNode1",type:"complete",scope: ["batchNode1"],uncaught:false,wires:[["helperNode1"]]},
- {id:"catchNode1", type:"catch",scope: ["batchNode1"],uncaught:false,wires:[["helperNode1"]]},
- {id:"helperNode1",type:"helper", wires:[[]]}];
- const numMsgs = msgAndTimings.length;
- helper.load([batchNode, completeNode, catchNode], flow, function () {
- const batchNode1 = helper.getNode("batchNode1");
- const helperNode1 = helper.getNode("helperNode1");
- RED.settings.nodeMessageBufferMaxLength = 2;
- const t = Date.now();
- let c = 0;
- helperNode1.on("input", function (msg) {
- msg.should.have.a.property('payload');
- (Date.now() - t).should.be.approximately(msgAndTimings[msg.payload].avr, msgAndTimings[msg.payload].var);
- c += 1;
- if ( c === numMsgs) {
- done();
- }
- });
- for (let i = 0; i < numMsgs; i++) {
- setTimeout( function() { batchNode1.receive(msgAndTimings[i].msg); }, msgAndTimings[i].delay);
- }
- });
- }
-
- it('should call done() when message is sent (mode: count)', function(done) {
- mapiDoneTestHelper(done, "count", 2, 0, 2, false, [
- { msg: {payload: 0}, delay: 0, avr: 0, var: 100},
- { msg: {payload: 1}, delay: 0, avr: 0, var: 100}
- ]);
- });
- it('should call done() when reset (mode: count)', function(done) {
- mapiDoneTestHelper(done, "count", 2, 0, 2, false, [
- { msg: {payload: 0}, delay: 0, avr: 200, var: 100},
- { msg: {payload: 1, reset:true}, delay: 200, avr: 200, var: 100}
- ]);
- });
- it('should call done() regardless of buffer overflow (mode: count)', function(done) {
- mapiDoneTestHelper(done, "count", 10, 0, 2, false, [
- { msg: {payload: 0}, delay: 0, avr: 500, var: 100},
- { msg: {payload: 1}, delay: 100, avr: 500, var: 100},
- { msg: {payload: 2}, delay: 500, avr: 500, var: 100}
- ]);
- });
- it('should call done() when message is sent (mode: interval)', function(done) {
- mapiDoneTestHelper(done, "interval", 2, 0, 2, false, [
- { msg: {payload: 0}, delay: 0, avr: 2000, var: 100},
- { msg: {payload: 1}, delay: 500, avr: 2000, var: 100}
- ]);
- });
- it('should call done() when reset (mode: interval)', function(done) {
- mapiDoneTestHelper(done, "interval", 2, 0, 2, false, [
- { msg: {payload: 0}, delay: 0, avr: 200, var: 100},
- { msg: {payload: 1, reset:true}, delay: 200, avr: 200, var: 100}
- ]);
- });
- it('should call done() regardless of buffer overflow (mode: interval)', function(done) {
- mapiDoneTestHelper(done, "interval", 2, 0, 2, false, [
- { msg: {payload: 0}, delay: 0, avr: 500, var: 100},
- { msg: {payload: 1}, delay: 100, avr: 500, var: 100},
- { msg: {payload: 2}, delay: 500, avr: 500, var: 100}
- ]);
- });
- it('should call done() when message is sent (mode: concat)', function(done) {
- mapiDoneTestHelper(done, "concat", 2, 0, 2, false, [
- { msg: {topic:"TA", payload: 0, parts: {id: "TA", index: 0, count: 2}}, delay: 0, avr: 1000, var: 100},
- { msg: {topic:"TA", payload: 1, parts: {id: "TA", index: 1, count: 2}}, delay: 1000, avr: 1000, var: 100},
- ]);
- });
- it('should call done() when reset (mode: concat)', function(done) {
- mapiDoneTestHelper(done, "concat", 2, 0, 2, false, [
- { msg: {topic:"TA", payload: 0, parts: {id: "TA", index: 0, count: 2}}, delay: 0, avr: 1000, var: 100},
- { msg: {payload: 1, reset:true}, delay: 1000, avr: 1000, var: 100},
- ]);
- });
- it('should call done() regardless of buffer overflow (mode: concat)', function(done) {
- mapiDoneTestHelper(done, "concat", 2, 0, 2, false, [
- { msg: {topic:"TA", payload: 0, parts: {id: "TA", index: 0, count: 3}}, delay: 0, avr: 1000, var: 100},
- { msg: {topic:"TA", payload: 0, parts: {id: "TA", index: 1, count: 3}}, delay: 500, avr: 1000, var: 100},
- { msg: {topic:"TA", payload: 0, parts: {id: "TA", index: 2, count: 3}}, delay: 1000, avr: 1000, var: 100}
- ]);
- });
- });
-});
diff --git a/test/nodes/core/storage/10-file_spec.js b/test/nodes/core/storage/10-file_spec.js
deleted file mode 100644
index 99ed23978..000000000
--- a/test/nodes/core/storage/10-file_spec.js
+++ /dev/null
@@ -1,1722 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var path = require('path');
-var fs = require('fs-extra');
-var os = require('os');
-var sinon = require("sinon");
-var iconv = require("iconv-lite");
-var fileNode = require("nr-test-utils").require("@node-red/nodes/core/storage/10-file.js");
-var helper = require("node-red-node-test-helper");
-var RED = require("nr-test-utils").require("node-red/lib/red");
-
-describe('file Nodes', function() {
-
- function encode(s, enc) {
- if (enc === "none") {
- return Buffer.from(s);
- }
- return iconv.encode(s, enc);
- }
-
- function decode(data, enc) {
- if (enc === "none") {
- return data.toString();
- }
- return iconv.decode(data, enc);
- }
-
- describe('file out Node', function() {
-
- var relativePathToFile = "50-file-test-file.txt";
- var resourcesDir = path.join(__dirname,"..","..","..","resources");
- var fileToTest = path.join(resourcesDir,relativePathToFile);
- var wait = 250;
-
- beforeEach(function(done) {
- //fs.writeFileSync(fileToTest, "File message line 1\File message line 2\n");
- helper.startServer(done);
- });
-
- afterEach(function(done) {
- delete RED.settings.fileWorkingDirectory;
- fs.removeSync(path.join(resourcesDir,"file-out-node"));
- helper.unload().then(function() {
- //fs.unlinkSync(fileToTest);
- helper.stopServer(done);
- });
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":true}];
- helper.load(fileNode, flow, function() {
- try {
- var fileNode1 = helper.getNode("fileNode1");
- fileNode1.should.have.property('name', 'fileNode');
- done();
- }
- catch (e) {
- done(e);
- }
- });
- });
-
- it('should write to a file', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- n2.on("input", function(msg) {
- try {
- var f = fs.readFileSync(fileToTest);
- f.should.have.length(4);
- fs.unlinkSync(fileToTest);
- msg.should.have.property("payload", "test");
- done();
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"test"});
- });
- });
-
- it('should write to a file using RED.settings.fileWorkingDirectory', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":relativePathToFile, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- helper.load(fileNode, flow, function() {
- RED.settings.fileWorkingDirectory = resourcesDir;
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- n2.on("input", function(msg) {
- try {
- var f = fs.readFileSync(fileToTest);
- f.should.have.length(4);
- fs.unlinkSync(fileToTest);
- msg.should.have.property("payload", "test");
- done();
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"test"});
- });
- });
-
-
- it('should write multi-byte string to a file', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- n2.on("input", function(msg) {
- try {
- var f = fs.readFileSync(fileToTest).toString();
- f.should.have.length(2);
- f.should.equal("試験");
- fs.unlinkSync(fileToTest);
- msg.should.have.property("payload", "試験");
- done();
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"試験"});
- });
- });
-
- it('should append to a file and add newline', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- try {
- fs.unlinkSync(fileToTest);
- } catch(err) {
- }
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- var count = 0;
- var data = ["test2", true, 999, [2]];
-
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- data.should.containDeep([msg.payload]);
- if (count === 3) {
- var f = fs.readFileSync(fileToTest).toString();
- if (os.type() !== "Windows_NT") {
- f.should.have.length(19);
- f.should.equal("test2\ntrue\n999\n[2]\n");
- }
- else {
- f.should.have.length(23);
- f.should.equal("test2\r\ntrue\r\n999\r\n[2]\r\n");
- }
- done();
- }
- count++;
- }
- catch (e) {
- done(e);
- }
- });
-
- n1.receive({payload:"test2"}); // string
- setTimeout(function() {
- n1.receive({payload:true}); // boolean
- },30);
- setTimeout(function() {
- n1.receive({payload:999}); // number
- },60);
- setTimeout(function() {
- n1.receive({payload:[2]}); // object (array)
- },90);
- });
- });
-
- it('should append to a file after it has been deleted ', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- try {
- fs.unlinkSync(fileToTest);
- } catch(err) {
- }
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- var data = ["one", "two", "three", "four"];
- var count = 0;
-
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- data.should.containDeep([msg.payload]);
- try {
- if (count === 1) {
- // Check they got appended as expected
- var f = fs.readFileSync(fileToTest).toString();
- f.should.equal("onetwo");
-
- // Delete the file
- fs.unlinkSync(fileToTest);
- setTimeout(function() {
- // Send two more messages to the file
- n1.receive({payload:"three"});
- n1.receive({payload:"four"});
- }, wait);
- }
- if (count === 3) {
- var f = fs.readFileSync(fileToTest).toString();
- f.should.equal("threefour");
- fs.unlinkSync(fileToTest);
- done();
- }
- } catch(err) {
- done(err);
- }
- count++;
- }
- catch (e) {
- done(e);
- }
- });
-
- // Send two messages to the file
- n1.receive({payload:"one"});
- n1.receive({payload:"two"});
- });
- });
-
- it('should append to a file after it has been recreated ', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- try {
- fs.unlinkSync(fileToTest);
- } catch(err) {
- }
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- var data = ["one", "two", "three", "four"];
- var count = 0;
-
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload");
- data.should.containDeep([msg.payload]);
- if (count == 1) {
- // Check they got appended as expected
- var f = fs.readFileSync(fileToTest).toString();
- f.should.equal("onetwo");
-
- if (os.type() === "Windows_NT") {
- var dummyFile = path.join(resourcesDir,"50-file-test-dummy.txt");
- fs.rename(fileToTest, dummyFile, function() {
- recreateTest(n1, dummyFile);
- });
- } else {
- recreateTest(n1, fileToTest);
- }
- }
- if (count == 3) {
- // Check the file was updated
- try {
- var f = fs.readFileSync(fileToTest).toString();
- f.should.equal("threefour");
- fs.unlinkSync(fileToTest);
- done();
- } catch(err) {
- done(err);
- }
- }
- } catch(err) {
- done(err);
- }
- count++;
- });
-
- // Send two messages to the file
- n1.receive({payload:"one"});
- n1.receive({payload:"two"});
- });
-
- function recreateTest(n1, fileToDelete) {
- // Delete the file
- fs.unlinkSync(fileToDelete);
-
- // Recreate it
- fs.writeFileSync(fileToTest,"");
-
- // Send two more messages to the file
- n1.receive({payload:"three"});
- n1.receive({payload:"four"});
- }
- });
-
-
- it('should use msg.filename if filename not set in node', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "appendNewline":true, "overwriteFile":true, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
-
- n2.on("input", function (msg) {
- try {
- msg.should.have.property("payload", "fine");
- msg.should.have.property("filename", fileToTest);
-
- var f = fs.readFileSync(fileToTest).toString();
- if (os.type() !== "Windows_NT") {
- f.should.have.length(5);
- f.should.equal("fine\n");
- }
- else {
- f.should.have.length(6);
- f.should.equal("fine\r\n");
- }
- done();
- }
- catch (e) {
- done(e);
- }
- });
-
- n1.receive({payload:"fine", filename:fileToTest});
- });
- });
-
- it('should be able to delete the file', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":"delete", wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
-
- n2.on("input", function (msg) {
- try {
- var f = fs.readFileSync(fileToTest).toString();
- f.should.not.equal("fine");
- //done();
- }
- catch(e) {
- e.code.should.equal("ENOENT");
- done();
- }
- });
-
- n1.receive({payload:"fine"});
- });
- });
-
- it('should warn if filename not set', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "appendNewline":true, "overwriteFile":false}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- n1.emit("input", {payload:"nofile"});
- setTimeout(function() {
- try {
- var f = fs.readFileSync(fileToTest).toString();
- f.should.not.equal("fine");
- //done();
- }
- catch(e) {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.equal("file.errors.nofilename");
- done();
- }
- },wait);
- });
- });
-
- it('ignore a missing payload', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var f = fs.readFileSync(fileToTest).toString();
- f.should.not.equal("fine");
- //done();
- }
- catch(e) {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(0);
- done();
- }
- },wait);
- n1.emit("input", {topic:"test"});
- });
- });
-
- it('should fail to write to a ro file', function(done) {
- // Stub file write so we can make writes fail
- var spy = sinon.stub(fs, 'createWriteStream').callsFake(function(arg1,arg2) {
- var ws = {};
- ws.on = function(e,d) { throw("Stub error message"); }
- ws.write = function(e,d) { }
- return ws;
- });
-
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("Stub error message");
- done();
- }
- catch(e) { done(e); }
- finally { fs.createWriteStream.restore(); }
- },wait);
- n1.receive({payload:"test"});
- });
- });
-
- it('should fail to append to a ro file', function(done) {
- // Stub file write so we can make writes fail
- var spy = sinon.stub(fs, 'createWriteStream').callsFake(function(arg1,arg2) {
- var ws = {};
- ws.on = function(e,d) { throw("Stub error message"); }
- ws.write = function(e,d) { }
- return ws;
- });
-
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("Stub error message");
- done();
- }
- catch(e) { done(e); }
- finally { fs.createWriteStream.restore(); }
- },wait);
- n1.receive({payload:"test2"});
- });
- });
-
- it('should cope with failing to delete a file', function(done) {
- // Stub file write so we can make writes fail
- var spy = sinon.stub(fs, 'unlink').callsFake(function(arg,arg2) { arg2(new Error("Stub error message")); });
-
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":"delete"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("file.errors.deletefail");
- done();
- }
- catch(e) { done(e); }
- finally { fs.unlink.restore(); }
- },wait);
- n1.receive({payload:"test2"});
- });
- });
-
- it('should fail to create a new directory if not asked to do so (append)', function(done) {
- // Stub file write so we can make writes fail
- var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
- //var spy = sinon.stub(fs, 'appendFile').callsFake(function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
-
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":false}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("file.errors.appendfail");
- done();
- }
- catch(e) { done(e); }
- //finally { fs.appendFile.restore(); }
- },wait);
- n1.receive({payload:"test2"});
- });
- });
-
- it('should try to create a new directory if asked to do so (append)', function(done) {
- // fs.writeFileSync of afterEach failed on Windows.
- if (os.type() === "Windows_NT") {
- done();
- return;
- }
- // Stub file write so we can make writes fail
- var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
- var spy = sinon.stub(fs, "ensureDir").callsFake(function(arg1,arg2,arg3,arg4) { arg2(null); });
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":false, "createDir":true}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(0);
- done();
- }
- catch(e) { done(e); }
- finally { fs.ensureDir.restore(); }
- },wait);
- n1.receive({payload:"test2"});
- });
- });
-
- it('should fail to create a new directory if not asked to do so (overwrite)', function(done) {
- // Stub file write so we can make writes fail
- var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
- //var spy = sinon.stub(fs, 'appendFile').callsFake(function(arg,arg2,arg3,arg4){ arg4(new Error("Stub error message")); });
-
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":false, "overwriteFile":true}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("file.errors.writefail");
- done();
- }
- catch(e) { done(e); }
- //finally { fs.appendFile.restore(); }
- },wait);
- n1.receive({payload:"test2"});
- });
- });
-
- it('should try to create a new directory if asked to do so (overwrite)', function(done) {
- // Stub file write so we can make writes fail
- var fileToTest2 = path.join(resourcesDir,"file-out-node","50-file-test-file.txt");
- var spy = sinon.stub(fs, "ensureDir").callsFake(function(arg1,arg2,arg3,arg4) { arg2(null); });
-
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest2, "appendNewline":true, "overwriteFile":true, "createDir":true}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- setTimeout(function() {
- try {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file";
- });
- //console.log(logEvents);
- logEvents.should.have.length(0);
- done();
- }
- catch(e) { done(e); }
- finally { fs.ensureDir.restore(); }
- },wait);
- n1.receive({payload:"test2"});
- });
- });
-
- it('should write to multiple files', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "appendNewline":true, "overwriteFile":true, "createDir":true, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- var tmp_path = path.join(resourcesDir, "tmp");
- var len = 1024*1024*10;
- var file_count = 5;
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- count++;
- if (count == file_count) {
- for(var i = 0; i < file_count; i++) {
- var name = path.join(tmp_path, String(i));
- var f = fs.readFileSync(name);
- f.should.have.length(len);
- f[0].should.have.equal(i);
- }
- fs.removeSync(tmp_path);
- done();
- }
- }
- catch (e) {
- try {
- fs.removeSync(tmp_path);
- }
- catch (e1) {
- }
- done(e);
- }
- });
- for(var i = 0; i < file_count; i++) {
- var data = Buffer.alloc?Buffer.alloc(len):new Buffer(len);
- data.fill(i);
- var name = path.join(tmp_path, String(i));
- var msg = {payload:data, filename:name};
- n1.receive(msg);
- }
- });
- });
-
- it('should write to multiple files if node is closed', function(done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "appendNewline":true, "overwriteFile":true, "createDir":true, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- var tmp_path = path.join(resourcesDir, "tmp");
- var len = 1024*1024*10;
- var file_count = 5;
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- var count = 0;
- n2.on("input", function(msg) {
- try {
- count++;
- if (count == file_count) {
- for(var i = 0; i < file_count; i++) {
- var name = path.join(tmp_path, String(i));
- var f = fs.readFileSync(name);
- f.should.have.length(len);
- f[0].should.have.equal(i);
- }
- fs.removeSync(tmp_path);
- done();
- }
- }
- catch (e) {
- try {
- fs.removeSync(tmp_path);
- }
- catch (e1) {
- }
- done(e);
- }
- });
- for(var i = 0; i < file_count; i++) {
- var data = Buffer.alloc?Buffer.alloc(len):new Buffer(len);
- data.fill(i);
- var name = path.join(tmp_path, String(i));
- var msg = {payload:data, filename:name};
- n1.receive(msg);
- }
- n1.close();
- });
- });
-
- describe('encodings', function() {
-
- function checkWriteWithEncoding(enc, data, done) {
- var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":true, encoding:enc, wires: [["helperNode1"]]},
- {id:"helperNode1", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileNode1");
- var n2 = helper.getNode("helperNode1");
- n2.on("input", function(msg) {
- try {
- var f = fs.readFileSync(fileToTest);
- f.equals(encode(data, enc)).should.be.true();
- fs.unlinkSync(fileToTest);
- msg.should.have.property("payload", data);
- done();
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:data});
- });
- }
-
- // default
- it('should write to a file with "none" encoding', function(done) {
- checkWriteWithEncoding("none", "test", done);
- });
-
- // Native
- it('should write to a file with "utf8" encoding', function(done) {
- checkWriteWithEncoding("utf8", "試験", done);
- });
-
- it('should write to a file with "ucs2" encoding', function(done) {
- checkWriteWithEncoding("ucs2", "試験", done);
- });
-
- it('should write to a file with "utf-16le" encoding', function(done) {
- checkWriteWithEncoding("utf-16le", "試験", done);
- });
-
- it('should write to a file with "binary" encoding', function(done) {
- checkWriteWithEncoding("binary", "test", done);
- });
-
- it('should write to a file with "base64" encoding', function(done) {
- checkWriteWithEncoding("base64", "5pel5pys6KqeCg==", done);
- });
-
- it('should write to a file with "hex" encoding', function(done) {
- checkWriteWithEncoding("hex", "deadbeef", done);
- });
-
- // Unicode
- it('should write to a file with "utf-16be" encoding', function(done) {
- checkWriteWithEncoding("utf-16be", "試験", done);
- });
-
- // Japanese
- it('should write to a file with "Shift_JIS" encoding', function(done) {
- checkWriteWithEncoding("Shift_JIS", "試験", done);
- });
-
- it('should write to a file with "Windows-31j" encoding', function(done) {
- checkWriteWithEncoding("Windows-31j", "試験", done);
- });
-
- it('should write to a file with "Windows932" encoding', function(done) {
- checkWriteWithEncoding("Windows932", "試験", done);
- });
-
- it('should write to a file with "EUC-JP" encoding', function(done) {
- checkWriteWithEncoding("EUC-JP", "試験", done);
- });
-
- // following encoding tests should be more specific
- // Chinese
- it('should write to a file with "GB2312" encoding', function(done) {
- checkWriteWithEncoding("GB2312", "test", done);
- });
-
- it('should write to a file with "GBK" encoding', function(done) {
- checkWriteWithEncoding("GBK", "test", done);
- });
-
- it('should write to a file with "GB18030" encoding', function(done) {
- checkWriteWithEncoding("GB18030", "test", done);
- });
-
- it('should write to a file with "Windows936" encoding', function(done) {
- checkWriteWithEncoding("Windows936", "test", done);
- });
-
- it('should write to a file with "EUC-CN" encoding', function(done) {
- checkWriteWithEncoding("EUC-CN", "test", done);
- });
-
- // Korean
- it('should write to a file with "KS_C_5601" encoding', function(done) {
- checkWriteWithEncoding("KS_C_5601", "test", done);
- });
-
- it('should write to a file with "Windows949" encoding', function(done) {
- checkWriteWithEncoding("Windows949", "test", done);
- });
-
- it('should write to a file with "EUC-KR" encoding', function(done) {
- checkWriteWithEncoding("EUC-KR", "test", done);
- });
-
- // Taiwan/Hong Kong
- it('should write to a file with "Big5" encoding', function(done) {
- checkWriteWithEncoding("Big5", "test", done);
- });
-
- it('should write to a file with "Big5-HKSCS" encoding', function(done) {
- checkWriteWithEncoding("Big5-HKSCS", "test", done);
- });
-
- it('should write to a file with "Windows950" encoding', function(done) {
- checkWriteWithEncoding("Windows950", "test", done);
- });
-
- // Windows
- it('should write to a file with "cp874" encoding', function(done) {
- checkWriteWithEncoding("cp874", "test", done);
- });
-
- it('should write to a file with "cp1250" encoding', function(done) {
- checkWriteWithEncoding("cp1250", "test", done);
- });
-
- it('should write to a file with "cp1251" encoding', function(done) {
- checkWriteWithEncoding("cp1251", "test", done);
- });
-
- it('should write to a file with "cp1252" encoding', function(done) {
- checkWriteWithEncoding("cp1252", "test", done);
- });
-
- it('should write to a file with "cp1253" encoding', function(done) {
- checkWriteWithEncoding("cp1253", "test", done);
- });
-
- it('should write to a file with "cp1254" encoding', function(done) {
- checkWriteWithEncoding("cp1254", "test", done);
- });
-
- it('should write to a file with "cp1255" encoding', function(done) {
- checkWriteWithEncoding("cp1255", "test", done);
- });
-
- it('should write to a file with "cp1256" encoding', function(done) {
- checkWriteWithEncoding("cp1256", "test", done);
- });
-
- it('should write to a file with "cp1257" encoding', function(done) {
- checkWriteWithEncoding("cp1257", "test", done);
- });
-
- it('should write to a file with "cp1258" encoding', function(done) {
- checkWriteWithEncoding("cp1258", "test", done);
- });
-
- // IBM
- it('should write to a file with "cp437" encoding', function(done) {
- checkWriteWithEncoding("cp437", "test", done);
- });
-
- it('should write to a file with "cp737" encoding', function(done) {
- checkWriteWithEncoding("cp737", "test", done);
- });
-
- it('should write to a file with "cp775" encoding', function(done) {
- checkWriteWithEncoding("cp775", "test", done);
- });
-
- it('should write to a file with "cp808" encoding', function(done) {
- checkWriteWithEncoding("cp808", "test", done);
- });
-
- it('should write to a file with "cp850" encoding', function(done) {
- checkWriteWithEncoding("cp850", "test", done);
- });
-
- it('should write to a file with "cp852" encoding', function(done) {
- checkWriteWithEncoding("cp852", "test", done);
- });
-
- it('should write to a file with "cp855" encoding', function(done) {
- checkWriteWithEncoding("cp855", "test", done);
- });
-
- it('should write to a file with "cp856" encoding', function(done) {
- checkWriteWithEncoding("cp856", "test", done);
- });
-
- it('should write to a file with "cp857" encoding', function(done) {
- checkWriteWithEncoding("cp857", "test", done);
- });
-
- it('should write to a file with "cp858" encoding', function(done) {
- checkWriteWithEncoding("cp858", "test", done);
- });
-
- it('should write to a file with "cp860" encoding', function(done) {
- checkWriteWithEncoding("cp860", "test", done);
- });
-
- it('should write to a file with "cp861" encoding', function(done) {
- checkWriteWithEncoding("cp861", "test", done);
- });
-
- it('should write to a file with "cp866" encoding', function(done) {
- checkWriteWithEncoding("cp866", "test", done);
- });
-
- it('should write to a file with "cp869" encoding', function(done) {
- checkWriteWithEncoding("cp869", "test", done);
- });
-
- it('should write to a file with "cp922" encoding', function(done) {
- checkWriteWithEncoding("cp922", "test", done);
- });
-
- it('should write to a file with "cp1046" encoding', function(done) {
- checkWriteWithEncoding("cp1046", "test", done);
- });
-
- it('should write to a file with "cp1124" encoding', function(done) {
- checkWriteWithEncoding("cp1124", "test", done);
- });
-
- it('should write to a file with "cp1125" encoding', function(done) {
- checkWriteWithEncoding("cp1125", "test", done);
- });
-
- it('should write to a file with "cp1129" encoding', function(done) {
- checkWriteWithEncoding("cp1129", "test", done);
- });
-
- it('should write to a file with "cp1133" encoding', function(done) {
- checkWriteWithEncoding("cp1133", "test", done);
- });
-
- it('should write to a file with "cp1161" encoding', function(done) {
- checkWriteWithEncoding("cp1161", "test", done);
- });
-
- it('should write to a file with "cp1162" encoding', function(done) {
- checkWriteWithEncoding("cp1162", "test", done);
- });
-
- it('should write to a file with "cp1163" encoding', function(done) {
- checkWriteWithEncoding("cp1163", "test", done);
- });
-
- // Mac
- it('should write to a file with "maccroatian" encoding', function(done) {
- checkWriteWithEncoding("maccroatian", "test", done);
- });
-
- it('should write to a file with "maccyrillic" encoding', function(done) {
- checkWriteWithEncoding("maccyrillic", "test", done);
- });
-
- it('should write to a file with "macgreek" encoding', function(done) {
- checkWriteWithEncoding("macgreek", "test", done);
- });
-
- it('should write to a file with "maciceland" encoding', function(done) {
- checkWriteWithEncoding("maciceland", "test", done);
- });
-
- it('should write to a file with "macroman" encoding', function(done) {
- checkWriteWithEncoding("macroman", "test", done);
- });
-
- it('should write to a file with "macromania" encoding', function(done) {
- checkWriteWithEncoding("macromania", "test", done);
- });
-
- it('should write to a file with "macthai" encoding', function(done) {
- checkWriteWithEncoding("macthai", "test", done);
- });
-
- it('should write to a file with "macturkish" encoding', function(done) {
- checkWriteWithEncoding("macturkish", "test", done);
- });
-
- it('should write to a file with "macukraine" encoding', function(done) {
- checkWriteWithEncoding("macukraine", "test", done);
- });
-
- it('should write to a file with "maccenteuro" encoding', function(done) {
- checkWriteWithEncoding("maccenteuro", "test", done);
- });
-
- it('should write to a file with "macintosh" encoding', function(done) {
- checkWriteWithEncoding("macintosh", "test", done);
- });
-
- // KOI8
- it('should write to a file with "koi8-r" encoding', function(done) {
- checkWriteWithEncoding("koi8-r", "test", done);
- });
-
- it('should write to a file with "koi8-u" encoding', function(done) {
- checkWriteWithEncoding("koi8-u", "test", done);
- });
-
- it('should write to a file with "koi8-ru" encoding', function(done) {
- checkWriteWithEncoding("koi8-ru", "test", done);
- });
-
- it('should write to a file with "koi8-t" encoding', function(done) {
- checkWriteWithEncoding("koi8-t", "test", done);
- });
-
- // Misc
- it('should write to a file with "armscii8" encoding', function(done) {
- checkWriteWithEncoding("armscii8", "test", done);
- });
-
- it('should write to a file with "rk1048" encoding', function(done) {
- checkWriteWithEncoding("rk1048", "test", done);
- });
-
- it('should write to a file with "tcvn" encoding', function(done) {
- checkWriteWithEncoding("tcvn", "test", done);
- });
-
- it('should write to a file with "georgianacademy" encoding', function(done) {
- checkWriteWithEncoding("georgianacademy", "test", done);
- });
-
- it('should write to a file with "georgianps" encoding', function(done) {
- checkWriteWithEncoding("georgianps", "test", done);
- });
-
- it('should write to a file with "pt154" encoding', function(done) {
- checkWriteWithEncoding("pt154", "test", done);
- });
-
- it('should write to a file with "viscii" encoding', function(done) {
- checkWriteWithEncoding("viscii", "test", done);
- });
-
- it('should write to a file with "iso646cn" encoding', function(done) {
- checkWriteWithEncoding("iso646cn", "test", done);
- });
-
- it('should write to a file with "iso646jp" encoding', function(done) {
- checkWriteWithEncoding("iso646jp", "test", done);
- });
-
- it('should write to a file with "hproman8" encoding', function(done) {
- checkWriteWithEncoding("hproman8", "test", done);
- });
-
- it('should write to a file with "tis620" encoding', function(done) {
- checkWriteWithEncoding("tis620", "test", done);
- });
-
- });
- });
-
-
- describe('file in Node', function() {
-
- var relativePathToFile = "50-file-test-file.txt";
- var resourcesDir = path.join(__dirname,"..","..","..","resources");
- var fileToTest = path.join(resourcesDir,relativePathToFile);
- var fileToTest2 = "\t"+path.join(resourcesDir,relativePathToFile)+"\r\n";
- var wait = 150;
-
- beforeEach(function(done) {
- fs.writeFileSync(fileToTest, "File message line 1\nFile message line 2\n");
- helper.startServer(done);
- });
-
- afterEach(function(done) {
- delete RED.settings.fileWorkingDirectory;
- helper.unload().then(function() {
- fs.unlinkSync(fileToTest);
- helper.stopServer(done);
- });
- });
-
- it('should be loaded', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest, "format":"utf8"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- n1.should.have.property('name', 'fileInNode');
- done();
- });
- });
-
- it('should read in a file and output a buffer', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name:"fileInNode", "filename":fileToTest, "format":"", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload');
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.payload.should.have.length(40);
- msg.payload.toString().should.equal('File message line 1\nFile message line 2\n');
- done();
- });
- n1.receive({payload:""});
- });
- });
-
- it('should read in a file and output a utf8 string', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest, "format":"utf8", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.be.a.String();
- msg.payload.should.have.length(40)
- msg.payload.should.equal("File message line 1\nFile message line 2\n");
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:""});
- });
- });
-
-
- it('should read in a file using fileWorkingDirectory to set cwd', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":relativePathToFile, "format":"utf8", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- RED.settings.fileWorkingDirectory = resourcesDir;
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.be.a.String();
- msg.payload.should.have.length(40)
- msg.payload.should.equal("File message line 1\nFile message line 2\n");
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:""});
- });
- });
-
-
- it('should read in a file ending in cr and output a utf8 string', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest2, "format":"utf8", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.be.a.String();
- msg.payload.should.have.length(40)
- msg.payload.should.equal("File message line 1\nFile message line 2\n");
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:""});
- });
- });
-
- it('should read in a file and output split lines with parts', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", filename:fileToTest, format:"lines", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.should.have.property('topic');
- msg.should.not.have.property('foo');
- msg.should.not.have.property('bar');
- msg.payload.should.be.a.String();
- msg.should.have.property('parts');
- msg.parts.should.have.property('index',c);
- msg.parts.should.have.property('type','string');
- msg.parts.should.have.property('ch','\n');
- if (c === 0) {
- msg.payload.should.equal("File message line 1");
- }
- if (c === 1) {
- msg.payload.should.equal("File message line 2");
- }
- if (c === 2) {
- msg.payload.should.equal("");
- done();
- }
- c++;
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"",topic:"A",foo:"bar",bar:"foo"});
- });
- });
-
- it('should read in a file with empty line and output split lines with parts', function(done) {
- var data = ["-", "", "-", ""];
- var line = data.join("\n");
- fs.writeFileSync(fileToTest, line);
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", filename:fileToTest, format:"lines", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.equal(data[c]);
- msg.should.have.property('parts');
- var parts = msg.parts;
- parts.should.have.property('index',c);
- parts.should.have.property('type','string');
- parts.should.have.property('ch','\n');
- c++;
- if (c === data.length) {
- parts.should.have.property('count', data.length);
- done();
- }
- else {
- parts.should.not.have.property('count');
- }
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:""});
- });
- });
-
- it('should read in a file and output split lines with parts and extra props', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", filename:fileToTest, format:"lines", allProps:true, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- var c = 0;
- n2.on("input", function(msg) {
- // console.log(msg)
- try {
- msg.should.have.property('payload');
- msg.payload.should.be.a.String();
- msg.should.have.property('topic');
- msg.should.have.property('foo');
- msg.should.have.property('bar');
- msg.should.have.property('parts');
- msg.parts.should.have.property('index',c);
- msg.parts.should.have.property('type','string');
- msg.parts.should.have.property('ch','\n');
- if (c === 0) {
- msg.payload.should.equal("File message line 1");
- }
- if (c === 1) {
- msg.payload.should.equal("File message line 2");
- }
- if (c === 2) {
- msg.payload.should.equal("");
- done();
- }
- c++;
- }
- catch(e) {
- done(e);
- }
- });
- n1.receive({payload:"",topic:"B",foo:"bar",bar:"foo"});
- });
- });
-
- it('should read in a file and output a buffer with parts', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", filename:fileToTest, format:"stream", wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property('payload');
- Buffer.isBuffer(msg.payload).should.be.true();
- msg.payload.should.have.length(40);
- msg.should.have.property('parts');
- msg.parts.should.have.property('count',1);
- msg.parts.should.have.property('type','buffer');
- msg.parts.should.have.property('ch','');
- done();
- });
- n1.receive({payload:""});
- });
- });
-
- it('should warn if no filename set', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "format":""}];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- setTimeout(function() {
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file in";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.equal("file.errors.nofilename");
- done();
- },wait);
- n1.receive({});
- });
- });
-
- it('should handle a file read error', function(done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":"badfile", "format":"", wires:[["n2"]]},
- {id:"n2", type:"helper"}
- ];
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
-
- n2.on("input", function(msg) {
- try {
- msg.should.not.have.property('payload');
- msg.should.have.property("error");
- msg.error.should.have.property("code","ENOENT");
- var logEvents = helper.log().args.filter(function(evt) {
- return evt[0].type == "file in";
- });
- logEvents.should.have.length(1);
- logEvents[0][0].should.have.a.property('msg');
- logEvents[0][0].msg.toString().should.startWith("Error");
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:""});
- });
- });
-
- describe('encodings', function() {
-
- function checkReadWithEncoding(enc, data, done) {
- var flow = [{id:"fileInNode1", type:"file in", name: "fileInNode", "filename":fileToTest, "format":"utf8", encoding:enc, wires:[["n2"]]},
- {id:"n2", type:"helper"}];
-
- fs.writeFileSync(fileToTest, encode(data, enc));
- helper.load(fileNode, flow, function() {
- var n1 = helper.getNode("fileInNode1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property('payload');
- msg.payload.should.be.a.String();
- msg.payload.should.equal(data);
- done();
- } catch(err) {
- done(err);
- }
- });
- n1.receive({payload:""});
- });
- }
-
- // default
- it('should read in a file with "none" encoding', function(done) {
- checkReadWithEncoding("none", "試験", done);
- });
-
- // Native
- it('should read in a file with "utf8" encoding', function(done) {
- checkReadWithEncoding("utf8", "試験", done);
- });
-
- it('should read in a file with "ucs2" encoding', function(done) {
- checkReadWithEncoding("ucs2", "試験", done);
- });
-
- it('should read in a file with "utf-16le" encoding', function(done) {
- checkReadWithEncoding("utf-16le", "試験", done);
- });
-
- it('should read in a file with "binary" encoding', function(done) {
- checkReadWithEncoding("binary", "test", done);
- });
-
- it('should read in a file with "base64" encoding', function(done) {
- checkReadWithEncoding("base64", "5pel5pys6KqeCg==", done);
- });
-
- it('should read in a file with "hex" encoding', function(done) {
- checkReadWithEncoding("hex", "deadbeef", done);
- });
-
- // Unicode
- it('should read in a file with "utf-16be" encoding', function(done) {
- checkReadWithEncoding("utf-16be", "試験", done);
- });
-
- // Japanese
- it('should read in a file with "Shift_JIS" encoding', function(done) {
- checkReadWithEncoding("Shift_JIS", "試験", done);
- });
-
- it('should read in a file with "Windows-31j" encoding', function(done) {
- checkReadWithEncoding("Windows-31j", "試験", done);
- });
-
- it('should read in a file with "Windows932" encoding', function(done) {
- checkReadWithEncoding("Windows932", "試験", done);
- });
-
- it('should read in a file with "EUC-JP" encoding', function(done) {
- checkReadWithEncoding("EUC-JP", "試験", done);
- });
-
- // following encoding tests should be more specific
- // Chinese
- it('should read in a file with "GB2312" encoding', function(done) {
- checkReadWithEncoding("GB2312", "test", done);
- });
-
- it('should read in a file with "GBK" encoding', function(done) {
- checkReadWithEncoding("GBK", "test", done);
- });
-
- it('should read in a file with "GB18030" encoding', function(done) {
- checkReadWithEncoding("GB18030", "test", done);
- });
-
- it('should read in a file with "Windows936" encoding', function(done) {
- checkReadWithEncoding("Windows936", "test", done);
- });
-
- it('should read in a file with "EUC-CN" encoding', function(done) {
- checkReadWithEncoding("EUC-CN", "test", done);
- });
-
- // Korean
- it('should read in a file with "KS_C_5601" encoding', function(done) {
- checkReadWithEncoding("KS_C_5601", "test", done);
- });
-
- it('should read in a file with "Windows949" encoding', function(done) {
- checkReadWithEncoding("Windows949", "test", done);
- });
-
- it('should read in a file with "EUC-KR" encoding', function(done) {
- checkReadWithEncoding("EUC-KR", "test", done);
- });
-
- // Taiwan/Hong Kong
- it('should read in a file with "Big5" encoding', function(done) {
- checkReadWithEncoding("Big5", "test", done);
- });
-
- it('should read in a file with "Big5-HKSCS" encoding', function(done) {
- checkReadWithEncoding("Big5-HKSCS", "test", done);
- });
-
- it('should read in a file with "Windows950" encoding', function(done) {
- checkReadWithEncoding("Windows950", "test", done);
- });
-
- // Windows
- it('should read in a file with "cp874" encoding', function(done) {
- checkReadWithEncoding("cp874", "test", done);
- });
-
- it('should read in a file with "cp1250" encoding', function(done) {
- checkReadWithEncoding("cp1250", "test", done);
- });
-
- it('should read in a file with "cp1251" encoding', function(done) {
- checkReadWithEncoding("cp1251", "test", done);
- });
-
- it('should read in a file with "cp1252" encoding', function(done) {
- checkReadWithEncoding("cp1252", "test", done);
- });
-
- it('should read in a file with "cp1253" encoding', function(done) {
- checkReadWithEncoding("cp1253", "test", done);
- });
-
- it('should read in a file with "cp1254" encoding', function(done) {
- checkReadWithEncoding("cp1254", "test", done);
- });
-
- it('should read in a file with "cp1255" encoding', function(done) {
- checkReadWithEncoding("cp1255", "test", done);
- });
-
- it('should read in a file with "cp1256" encoding', function(done) {
- checkReadWithEncoding("cp1256", "test", done);
- });
-
- it('should read in a file with "cp1257" encoding', function(done) {
- checkReadWithEncoding("cp1257", "test", done);
- });
-
- it('should read in a file with "cp1258" encoding', function(done) {
- checkReadWithEncoding("cp1258", "test", done);
- });
-
- // IBM
- it('should read in a file with "cp437" encoding', function(done) {
- checkReadWithEncoding("cp437", "test", done);
- });
-
- it('should read in a file with "cp737" encoding', function(done) {
- checkReadWithEncoding("cp737", "test", done);
- });
-
- it('should read in a file with "cp775" encoding', function(done) {
- checkReadWithEncoding("cp775", "test", done);
- });
-
- it('should read in a file with "cp808" encoding', function(done) {
- checkReadWithEncoding("cp808", "test", done);
- });
-
- it('should read in a file with "cp850" encoding', function(done) {
- checkReadWithEncoding("cp850", "test", done);
- });
-
- it('should read in a file with "cp852" encoding', function(done) {
- checkReadWithEncoding("cp852", "test", done);
- });
-
- it('should read in a file with "cp855" encoding', function(done) {
- checkReadWithEncoding("cp855", "test", done);
- });
-
- it('should read in a file with "cp856" encoding', function(done) {
- checkReadWithEncoding("cp856", "test", done);
- });
-
- it('should read in a file with "cp857" encoding', function(done) {
- checkReadWithEncoding("cp857", "test", done);
- });
-
- it('should read in a file with "cp858" encoding', function(done) {
- checkReadWithEncoding("cp858", "test", done);
- });
-
- it('should read in a file with "cp860" encoding', function(done) {
- checkReadWithEncoding("cp860", "test", done);
- });
-
- it('should read in a file with "cp861" encoding', function(done) {
- checkReadWithEncoding("cp861", "test", done);
- });
-
- it('should read in a file with "cp866" encoding', function(done) {
- checkReadWithEncoding("cp866", "test", done);
- });
-
- it('should read in a file with "cp869" encoding', function(done) {
- checkReadWithEncoding("cp869", "test", done);
- });
-
- it('should read in a file with "cp922" encoding', function(done) {
- checkReadWithEncoding("cp922", "test", done);
- });
-
- it('should read in a file with "cp1046" encoding', function(done) {
- checkReadWithEncoding("cp1046", "test", done);
- });
-
- it('should read in a file with "cp1124" encoding', function(done) {
- checkReadWithEncoding("cp1124", "test", done);
- });
-
- it('should read in a file with "cp1125" encoding', function(done) {
- checkReadWithEncoding("cp1125", "test", done);
- });
-
- it('should read in a file with "cp1129" encoding', function(done) {
- checkReadWithEncoding("cp1129", "test", done);
- });
-
- it('should read in a file with "cp1133" encoding', function(done) {
- checkReadWithEncoding("cp1133", "test", done);
- });
-
- it('should read in a file with "cp1161" encoding', function(done) {
- checkReadWithEncoding("cp1161", "test", done);
- });
-
- it('should read in a file with "cp1162" encoding', function(done) {
- checkReadWithEncoding("cp1162", "test", done);
- });
-
- it('should read in a file with "cp1163" encoding', function(done) {
- checkReadWithEncoding("cp1163", "test", done);
- });
-
- // Mac
- it('should read in a file with "maccroatian" encoding', function(done) {
- checkReadWithEncoding("maccroatian", "test", done);
- });
-
- it('should read in a file with "maccyrillic" encoding', function(done) {
- checkReadWithEncoding("maccyrillic", "test", done);
- });
-
- it('should read in a file with "macgreek" encoding', function(done) {
- checkReadWithEncoding("macgreek", "test", done);
- });
-
- it('should read in a file with "maciceland" encoding', function(done) {
- checkReadWithEncoding("maciceland", "test", done);
- });
-
- it('should read in a file with "macroman" encoding', function(done) {
- checkReadWithEncoding("macroman", "test", done);
- });
-
- it('should read in a file with "macromania" encoding', function(done) {
- checkReadWithEncoding("macromania", "test", done);
- });
-
- it('should read in a file with "macthai" encoding', function(done) {
- checkReadWithEncoding("macthai", "test", done);
- });
-
- it('should read in a file with "macturkish" encoding', function(done) {
- checkReadWithEncoding("macturkish", "test", done);
- });
-
- it('should read in a file with "macukraine" encoding', function(done) {
- checkReadWithEncoding("macukraine", "test", done);
- });
-
- it('should read in a file with "maccenteuro" encoding', function(done) {
- checkReadWithEncoding("maccenteuro", "test", done);
- });
-
- it('should read in a file with "macintosh" encoding', function(done) {
- checkReadWithEncoding("macintosh", "test", done);
- });
-
- // KOI8
- it('should read in a file with "koi8-r" encoding', function(done) {
- checkReadWithEncoding("koi8-r", "test", done);
- });
-
- it('should read in a file with "koi8-u" encoding', function(done) {
- checkReadWithEncoding("koi8-u", "test", done);
- });
-
- it('should read in a file with "koi8-ru" encoding', function(done) {
- checkReadWithEncoding("koi8-ru", "test", done);
- });
-
- it('should read in a file with "koi8-t" encoding', function(done) {
- checkReadWithEncoding("koi8-t", "test", done);
- });
-
- // Misc
- it('should read in a file with "armscii8" encoding', function(done) {
- checkReadWithEncoding("armscii8", "test", done);
- });
-
- it('should read in a file with "rk1048" encoding', function(done) {
- checkReadWithEncoding("rk1048", "test", done);
- });
-
- it('should read in a file with "tcvn" encoding', function(done) {
- checkReadWithEncoding("tcvn", "test", done);
- });
-
- it('should read in a file with "georgianacademy" encoding', function(done) {
- checkReadWithEncoding("georgianacademy", "test", done);
- });
-
- it('should read in a file with "georgianps" encoding', function(done) {
- checkReadWithEncoding("georgianps", "test", done);
- });
-
- it('should read in a file with "pt154" encoding', function(done) {
- checkReadWithEncoding("pt154", "test", done);
- });
-
- it('should read in a file with "viscii" encoding', function(done) {
- checkReadWithEncoding("viscii", "test", done);
- });
-
- it('should read in a file with "iso646cn" encoding', function(done) {
- checkReadWithEncoding("iso646cn", "test", done);
- });
-
- it('should read in a file with "iso646jp" encoding', function(done) {
- checkReadWithEncoding("iso646jp", "test", done);
- });
-
- it('should read in a file with "hproman8" encoding', function(done) {
- checkReadWithEncoding("hproman8", "test", done);
- });
-
- it('should read in a file with "tis620" encoding', function(done) {
- checkReadWithEncoding("tis620", "test", done);
- });
-
- });
-
- });
-});
diff --git a/test/nodes/core/storage/23-watch_spec.js b/test/nodes/core/storage/23-watch_spec.js
deleted file mode 100644
index a9942d5b1..000000000
--- a/test/nodes/core/storage/23-watch_spec.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var fs = require("fs-extra");
-var path = require("path");
-var should = require("should");
-var helper = require("node-red-node-test-helper");
-var watchNode = require("nr-test-utils").require("@node-red/nodes/core/storage/23-watch.js");
-
-
-describe('watch Node', function() {
- this.timeout(5000);
-
- var resourcesDir = path.join(__dirname,"..","..","..","resources");
- var baseDir = path.join(resourcesDir, "23-watch-test-dir");
- var count = 0;
-
- function prepareDir() {
- var dirToWatch = path.join(baseDir, "base"+count);
- fs.mkdirSync(dirToWatch);
- count++;
- return {
- dirToWatch:dirToWatch,
- file0ToWatch:path.join(dirToWatch, "file0.txt"),
- file1ToWatch:path.join(dirToWatch, "file1.txt"),
- subDirToWatch:path.join(dirToWatch, "subdir"),
- file2ToWatch:path.join(dirToWatch, "subdir", "file2.txt")
- }
- }
-
- function wait(msec, func) {
- setTimeout(func, msec);
- }
-
- before(function(done) {
- fs.ensureDirSync(baseDir);
- done();
- });
-
- after(function(done) {
- fs.removeSync(baseDir);
- done();
- });
-
- afterEach(function(done) {
- helper.unload();
- done();
- });
-
- function testWatch(flow, change_func, results, done) {
- var processed = {};
- helper.load(watchNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- var count = 0;
- var len = Object.keys(results).length;
- n2.on("input", function(msg) {
- try {
- // console.log(msg);
- msg.should.have.property('file');
-
- var file = msg.file;
- if (file in processed) {
- // multiple messages come in rare case
- return;
- }
- processed[file] = true;
- if (file === 'subdir') {
- // On OSX, we get a change event on subdir when a file inside changes.
- // On Travis, we don't. *sigh*
- return;
- }
- (file in results).should.be.true();
-
- var result = results[file];
- msg.should.have.property('payload', result.payload);
- msg.should.have.property('type', result.type);
- if('size' in result) {
- msg.should.have.property('size', result.size);
- }
- count++;
- if(count === len) {
- n1.close();
- // wait for close
- wait(100, done);
- }
- }catch(err) {
- done(err);
- }
- });
- // wait for preparation
- wait(500, change_func);
- });
- }
-
- it('should watch a file to be changed', function(done) {
- var files = prepareDir();
- fs.writeFileSync(files.file0ToWatch, '');
- var flow = [{id:"n1", type:"watch", name: "watch",
- files: files.file0ToWatch, recursive: false,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = {
- 'file0.txt' : {
- 'payload' : files.file0ToWatch,
- 'topic': files.file0ToWatch,
- 'type': 'file',
- 'size': 5
- }
- };
- testWatch(flow, function() {
- fs.appendFileSync(files.file0ToWatch, "ABCDE");
- }, results, done);
- });
-
- it('should watch multiple files to be changed', function(done) {
- var files = prepareDir();
- fs.writeFileSync(files.file0ToWatch, '');
- fs.writeFileSync(files.file1ToWatch, '');
- var flow = [{id:"n1", type:"watch", name: "watch",
- files: files.file0ToWatch +","+files.file1ToWatch, recursive: false,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = {
- 'file0.txt' : {
- 'payload' : files.file0ToWatch,
- 'topic': files.file0ToWatch,
- 'type': 'file'//,
- // 'size': 5
- },
- 'file1.txt' : {
- 'payload' : files.file1ToWatch,
- 'topic': files.file1ToWatch,
- 'type': 'file'//,
- // 'size': 3
- }
- };
- testWatch(flow, function() {
- fs.appendFileSync(files.file0ToWatch, "ABCDE");
- fs.appendFileSync(files.file1ToWatch, "123");
- }, results, done);
- });
-
- it('should watch attribute of a file to be changed', function(done) {
- var files = prepareDir();
- fs.writeFileSync(files.file0ToWatch, '');
- fs.chmodSync(files.file0ToWatch, 0o444);
- var flow = [{id:"n1", type:"watch", name: "watch",
- files: files.file0ToWatch, recursive: false,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = {
- 'file0.txt' : {
- 'payload' : files.file0ToWatch,
- 'topic': files.file0ToWatch,
- 'type': 'file'//,
- // 'size': 0
- }
- };
- testWatch(flow, function() {
- fs.chmodSync(files.file0ToWatch, 0o777);
- }, results, done);
- });
-
- it('should watch a file in a directory to be changed', function(done) {
- var files = prepareDir();
- fs.writeFileSync(files.file0ToWatch, '');
- var flow = [{id:"n1", type:"watch", name: "watch",
- files: files.dirToWatch, recursive: true,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = {
- 'file0.txt' : {
- 'payload' : files.file0ToWatch,
- 'topic': files.file0ToWatch,
- 'type': 'file'//,
- // 'size': 5
- }
- };
- testWatch(flow, function() {
- fs.appendFileSync(files.file0ToWatch, "ABCDE");
- }, results, done);
- });
-
- it('should watch a sub directory in a directory to be changed', function(done) {
- var files = prepareDir();
- fs.mkdirSync(files.subDirToWatch);
- var flow = [{id:"n1", type:"watch", name: "watch",
- files: files.dirToWatch, recursive: true,
- wires:[["n2"]]},
- {id:"n2", type:"helper"}];
- var results = {
- 'file2.txt': {
- payload: files.file2ToWatch,
- type: 'file'//,
- // size: 5
- }
- };
- testWatch(flow, function() {
- fs.appendFileSync(files.file2ToWatch, "ABCDE");
- }, results, done);
- });
-
-});
diff --git a/test/nodes/subflow/subflow_spec.js b/test/nodes/subflow/subflow_spec.js
deleted file mode 100644
index d5b8d78ae..000000000
--- a/test/nodes/subflow/subflow_spec.js
+++ /dev/null
@@ -1,570 +0,0 @@
-/**
-* Copyright JS Foundation and other contributors, http://js.foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**/
-
-var should = require("should");
-var functionNode = require("nr-test-utils").require("@node-red/nodes/core/function/10-function.js");
-var helper = require("node-red-node-test-helper");
-
-// Notice:
-// - nodes should have x, y, z property when defining subflow.
-
-describe('subflow', function() {
-
- before(function(done) {
- helper.startServer(done);
- });
-
- after(function(done) {
- helper.stopServer(done);
- });
-
- afterEach(function() {
- helper.unload();
- });
-
- it('should define subflow', function(done) {
- var flow = [
- {id:"t1", type:"tab"},
- {id:"n1", z:"t1", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", z:"t1", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"",
- in:[{wires:[ {id:"s1-n1"} ]}],
- out:[{wires:[ {id:"s1-n1", port:0} ]}]},
- {id:"s1-n1", z:"s1", type:"function",
- func:"return msg;", wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- done();
- });
- });
-
- it('should pass data to/from subflow', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.payload = msg.payload+'bar'; return msg;", wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property("payload", "foobar");
- done();
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should pass data to/from nested subflow', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow1
- {id:"s1", type:"subflow", name:"Subflow1", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n2", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"subflow:s2",
- wires:[["s1-n2"]]},
- {id:"s1-n2", x:10, y:10, z:"s1", type:"function",
- func:"msg.payload = msg.payload+'baz'; return msg;", wires:[]},
- // Subflow2
- {id:"s2", type:"subflow", name:"Subflow2", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s2-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s2-n1", port:0} ]
- }]
- },
- {id:"s2-n1", x:10, y:10, z:"s2", type:"function",
- func:"msg.payload=msg.payload+'bar'; return msg;", wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property("payload", "foobarbaz");
- done();
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access env var of subflow template', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"",
- env: [
- {name: "K", type: "str", value: "V"}
- ],
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("V", "V");
- done();
- }
- catch (e) {
- console.log(e);
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access env var of subflow instance', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1",
- env: [
- {name: "K", type: "str", value: "V"}
- ],
- wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("V", "V");
- done();
- }
- catch (e) {
- console.log(e);
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access last env var with same name', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1",
- env: [
- {name: "K", type: "str", value: "V0"},
- {name: "X", type: "str", value: "VX"},
- {name: "K", type: "str", value: "V1"}
- ],
- wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("V", "V1");
- done();
- }
- catch (e) {
- console.log(e);
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access typed value of env var', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1",
- env: [
- {name: "KN", type: "num", value: "100"},
- {name: "KB", type: "bool", value: "true"},
- {name: "KJ", type: "json", value: "[1,2,3]"},
- {name: "Kb", type: "bin", value: "[65,65]"},
- {name: "Ke", type: "env", value: "KS"}
- ],
- wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }],
- env: [
- {name: "KS", type: "str", value: "STR"}
- ]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.VE = env.get('Ke'); msg.VS = env.get('KS'); msg.VN = env.get('KN'); msg.VB = env.get('KB'); msg.VJ = env.get('KJ'); msg.Vb = env.get('Kb'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("VS", "STR");
- msg.should.have.property("VN", 100);
- msg.should.have.property("VB", true);
- msg.should.have.property("VJ", [1,2,3]);
- msg.should.have.property("Vb");
- should.ok(msg.Vb instanceof Buffer);
- msg.should.have.property("VE","STR");
- done();
- }
- catch (e) {
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should overwrite env var of subflow template by env var of subflow instance', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1",
- env: [
- {name: "K", type: "str", value: "V"}
- ],
- wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"",
- env: [
- {name: "K", type: "str", value: "TV"}
- ],
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("V", "V");
- done();
- }
- catch (e) {
- console.log(e);
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access env var of parent subflow template', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow1
- {id:"s1", type:"subflow", name:"Subflow1", info:"",
- env: [
- {name: "K", type: "str", value: "V"},
- ],
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n2", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"subflow:s2",
- wires:[["s1-n2"]]},
- {id:"s1-n2", x:10, y:10, z:"s1", type:"function",
- func:"return msg;", wires:[]},
- // Subflow2
- {id:"s2", type:"subflow", name:"Subflow2", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s2-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s2-n1", port:0} ]
- }]
- },
- {id:"s2-n1", x:10, y:10, z:"s2", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property("V", "V");
- done();
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access env var of parent subflow instance', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1",
- env: [
- {name: "K", type: "str", value: "V"}
- ],
- wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow1
- {id:"s1", type:"subflow", name:"Subflow1", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n2", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"subflow:s2",
- wires:[["s1-n2"]]},
- {id:"s1-n2", x:10, y:10, z:"s1", type:"function",
- func:"return msg;", wires:[]},
- // Subflow2
- {id:"s2", type:"subflow", name:"Subflow2", info:"",
- in:[{
- x:10, y:10,
- wires:[ {id:"s2-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s2-n1", port:0} ]
- }]
- },
- {id:"s2-n1", x:10, y:10, z:"s2", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- msg.should.have.property("V", "V");
- done();
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access env var of tab', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:"", env: [
- {name: "K", type: "str", value: "V"}
- ]},
- {id:"n1", x:10, y:10, z:"t0", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"", env: [],
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("V", "V");
- done();
- }
- catch (e) {
- console.log(e);
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access env var of group', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"g1", z:"t0", type:"group", env:[
- {name: "K", type: "str", value: "V"}
- ]},
- {id:"n1", x:10, y:10, z:"t0", g:"g1", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"", env: [],
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("V", "V");
- done();
- }
- catch (e) {
- console.log(e);
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
- it('should access env var of nested group', function(done) {
- var flow = [
- {id:"t0", type:"tab", label:"", disabled:false, info:""},
- {id:"g1", z:"t0", type:"group", env:[
- {name: "K", type: "str", value: "V"}
- ]},
- {id:"g2", z:"t0", g:"g1", type:"group", env:[]},
- {id:"n1", x:10, y:10, z:"t0", g:"g2", type:"subflow:s1", wires:[["n2"]]},
- {id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
- // Subflow
- {id:"s1", type:"subflow", name:"Subflow", info:"", env: [],
- in:[{
- x:10, y:10,
- wires:[ {id:"s1-n1"} ]
- }],
- out:[{
- x:10, y:10,
- wires:[ {id:"s1-n1", port:0} ]
- }]
- },
- {id:"s1-n1", x:10, y:10, z:"s1", type:"function",
- func:"msg.V = env.get('K'); return msg;",
- wires:[]}
- ];
- helper.load(functionNode, flow, function() {
- var n1 = helper.getNode("n1");
- var n2 = helper.getNode("n2");
- n2.on("input", function(msg) {
- try {
- msg.should.have.property("V", "V");
- done();
- }
- catch (e) {
- console.log(e);
- done(e);
- }
- });
- n1.receive({payload:"foo"});
- });
- });
-
-});
diff --git a/test/resources/70-HTML-test-file.html b/test/resources/70-HTML-test-file.html
deleted file mode 100644
index 2187b8e31..000000000
--- a/test/resources/70-HTML-test-file.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-This is a test page for node 70-HTML
-
-There's nothing to read here.
-
-
- Blue
- Red
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/resources/file-in-node/test.txt b/test/resources/file-in-node/test.txt
deleted file mode 100644
index 68ca53b4d..000000000
--- a/test/resources/file-in-node/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-Text file
\ No newline at end of file
diff --git a/test/resources/icons/test_icon.png b/test/resources/icons/test_icon.png
deleted file mode 100644
index 4b6b7b5e9b10ec790348eb59f73bdac596e2f3b8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 163
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1$P6UK?yS)OQjEnx?oJHr&dIz4a@YcVLR^9L
z|NsA&-kg6IB%S2#?!wT)D(eB{a29w(76Vni0bxeDQVUa{AbW|YuPggKZdPtVo=;b%
zu>pm|JY5_^IIbrr*#Br`l>NUU`M`mYFm{Gnm$g4<{K@tLs$lSR^>bP0l+XkK5O^!s
diff --git a/test/resources/plugin/test-plugin/library-filestore.html b/test/resources/plugin/test-plugin/library-filestore.html
deleted file mode 100644
index 60fbae464..000000000
--- a/test/resources/plugin/test-plugin/library-filestore.html
+++ /dev/null
@@ -1,22 +0,0 @@
-
\ No newline at end of file
diff --git a/test/resources/plugin/test-plugin/library-filestore.js b/test/resources/plugin/test-plugin/library-filestore.js
deleted file mode 100644
index 7c6f1db83..000000000
--- a/test/resources/plugin/test-plugin/library-filestore.js
+++ /dev/null
@@ -1,37 +0,0 @@
-
-module.exports = function(RED) {
- const PLUGIN_TYPE_ID = "node-red-library-filestore";
-
- class FileStorePlugin {
- constructor(config) {
- this.type = PLUGIN_TYPE_ID;
- this.id = config.id;
- this.label = config.label;
- this.config = config.config;
- this.icon = config.icon;
-
- console.log("FileStorePlugin",config)
- }
- async init() {
- console.log("FileStorePlugin.init")
-
- }
- async getEntry(type,path) {
- console.log("FileStorePlugin.getLibraryEntry",type,path)
- return []
- }
- async saveEntry(type,path,meta,body) {
- console.log("FileStorePlugin.saveLibraryEntry",type,path)
- }
- }
-
-
- RED.plugins.registerPlugin(PLUGIN_TYPE_ID, {
- type: "node-red-library-source",
- class: FileStorePlugin,
- defaults: {
- "path": { value: "" },
- // "secret": { type: "password" }
- }
- })
-}
\ No newline at end of file
diff --git a/test/resources/plugin/test-plugin/locales/en-US/library-filestore.json b/test/resources/plugin/test-plugin/locales/en-US/library-filestore.json
deleted file mode 100644
index b9ffa5f17..000000000
--- a/test/resources/plugin/test-plugin/locales/en-US/library-filestore.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "label": {
- "path": "Path"
- },
- "desc": {
- "path":"The local file-system path to the library"
- }
-}
\ No newline at end of file
diff --git a/test/resources/plugin/test-plugin/locales/en-US/test-editor-plugin.json b/test/resources/plugin/test-plugin/locales/en-US/test-editor-plugin.json
deleted file mode 100644
index e990e2ec1..000000000
--- a/test/resources/plugin/test-plugin/locales/en-US/test-editor-plugin.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "plugin": "winning"
-}
\ No newline at end of file
diff --git a/test/resources/plugin/test-plugin/package.json b/test/resources/plugin/test-plugin/package.json
deleted file mode 100644
index 65487c656..000000000
--- a/test/resources/plugin/test-plugin/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name": "test-plugin",
- "version": "1.0.0",
- "description": "",
- "node-red": {
- "plugins": {
- "test": "test.js",
- "test-editor-plugin": "test-editor-plugin.html",
- "test-runtime-plugin": "test-runtime-plugin.js",
- "library-filestore": "library-filestore.js"
- }
- }
-}
diff --git a/test/resources/plugin/test-plugin/test-editor-plugin.html b/test/resources/plugin/test-plugin/test-editor-plugin.html
deleted file mode 100644
index 177813526..000000000
--- a/test/resources/plugin/test-plugin/test-editor-plugin.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
\ No newline at end of file
diff --git a/test/resources/plugin/test-plugin/test-runtime-plugin.js b/test/resources/plugin/test-plugin/test-runtime-plugin.js
deleted file mode 100644
index d9e3ff3c7..000000000
--- a/test/resources/plugin/test-plugin/test-runtime-plugin.js
+++ /dev/null
@@ -1,10 +0,0 @@
-module.exports = function(RED) {
- console.log("Loaded test-plugin/test-runtime-plugin")
-
- RED.plugins.registerPlugin("my-test-runtime-only-plugin", {
- type: "bar",
- onadd: function() {
- console.log("my-test-runtime-only-plugin.onadd called")
- }
- })
-}
\ No newline at end of file
diff --git a/test/resources/plugin/test-plugin/test.html b/test/resources/plugin/test-plugin/test.html
deleted file mode 100644
index 7a43a0528..000000000
--- a/test/resources/plugin/test-plugin/test.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-");
- }
- },
- i18n: {
- determineLangFromHeaders: function(){}
- }
- });
- request(app)
- .get('/nodes')
- .set('Accept', 'text/html')
- .expect(200)
- .expect("")
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns node module info', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getModuleInfo: function(opts) {
- return Promise.resolve({"node-red":{name:"node-red"}}[opts.module]);
- }
- }
- });
- request(app)
- .get('/nodes/node-red')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- done();
- });
- });
-
- it('returns 404 for unknown module', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getModuleInfo: function(opts) {
- var errInstance = new Error("Not Found");
- errInstance.code = "not_found";
- errInstance.status = 404;
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- return p;
- }
- }
- });
- request(app)
- .get('/nodes/node-blue')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns individual node info', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getNodeInfo: function(opts) {
- return Promise.resolve({"node-red/123":{id:"node-red/123"}}[opts.id]);
- }
- }
- });
- request(app)
- .get('/nodes/node-red/123')
- .set('Accept', 'application/json')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","node-red/123");
- done();
- });
- });
-
- it('returns individual node configs', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getNodeConfig: function(opts) {
- return Promise.resolve({"node-red/123":""}[opts.id]);
- }
- },
- i18n: {
- determineLangFromHeaders: function(){}
- }
- });
- request(app)
- .get('/nodes/node-red/123')
- .set('Accept', 'text/html')
- .expect(200)
- .expect("")
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
- it('returns 404 for unknown node', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getNodeInfo: function(opts) {
- var errInstance = new Error("Not Found");
- errInstance.code = "not_found";
- errInstance.status = 404;
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- return p;
- }
- }
- });
- request(app)
- .get('/nodes/node-red/456')
- .set('Accept', 'application/json')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
- });
-
- describe('install', function() {
- it('installs the module and returns module info', function(done) {
- var opts;
- nodes.init({
- settings: {},
- nodes:{
- addModule: function(_opts) {
- opts = _opts;
- return Promise.resolve({
- name:"foo",
- nodes:[{id:"123"}]
- });
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo',version:"1.2.3",url:"https://example/foo-1.2.3.tgz"})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","foo");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("id","123");
- opts.should.have.property("module","foo");
- opts.should.have.property("version","1.2.3");
- opts.should.have.property("url","https://example/foo-1.2.3.tgz");
- done();
- });
- });
- it('returns error', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- addModule: function(opts) {
- var errInstance = new Error("Message");
- errInstance.code = "random_error";
- errInstance.status = 400;
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- return p;
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo',version:"1.2.3",url:"https://example/foo-1.2.3.tgz"})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.a.property('code','random_error');
- done();
- });
- });
- });
- describe('delete', function() {
- it('uninstalls the module', function(done) {
- var opts;
- nodes.init({
- settings: {},
- nodes:{
- removeModule: function(_opts) {
- opts = _opts;
- return Promise.resolve();
- }
- }
- });
- request(app)
- .del('/nodes/123')
- .expect(204)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- opts.should.have.property("module","123");
- done();
- });
- });
- it('returns error', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- removeModule: function(opts) {
- var errInstance = new Error("Message");
- errInstance.code = "random_error";
- errInstance.status = 400;
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- return p;
- }
- }
- });
- request(app)
- .del('/nodes/123')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.a.property('code','random_error');
- done();
- });
- });
- });
-
- describe('enable/disable node set', function() {
- it('returns 400 for invalid request payload', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- setNodeSetState: function(opts) {return Promise.resolve()}
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("code","invalid_request");
- res.body.should.have.property("message","Invalid request");
- done();
- });
- });
-
- it('sets node state and returns node info', function(done) {
- var opts;
- nodes.init({
- settings: {},
- nodes:{
- setNodeSetState: function(_opts) {
- opts = _opts;
- return Promise.resolve({id:"123",enabled: true });
- }
- }
- });
-
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:true})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",true);
- opts.should.have.property("enabled",true);
- opts.should.have.property("id","node-red/foo");
-
- done();
- });
- });
- });
- describe('enable/disable module' ,function() {
- it('returns 400 for invalid request payload', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- setModuleState: function(opts) {return Promise.resolve()}
- }
- });
- request(app)
- .put('/nodes/node-red')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("code","invalid_request");
- res.body.should.have.property("message","Invalid request");
- done();
- });
- });
- it('sets module state and returns module info', function(done) {
- var opts;
- nodes.init({
- settings: {},
- nodes:{
- setModuleState: function(_opts) {
- opts = _opts;
- return Promise.resolve({name:"node-red"});
- }
- }
- });
-
- request(app)
- .put('/nodes/node-red')
- .send({enabled:true})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- opts.should.have.property("enabled",true);
- opts.should.have.property("module","node-red");
-
- done();
- });
- });
- });
-
- describe('get icons', function() {
- it('returns icon list', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getIconList: function() {
- return Promise.resolve({module:[1,2,3]});
- }
- }
- });
- request(app)
- .get('/getIcons')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("module");
- res.body.module.should.be.an.Array();
- res.body.module.should.have.lengthOf(3);
- done();
- });
- });
- });
-
- describe('get module messages', function() {
- it('returns message catalog', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getModuleCatalog: function(opts) {
- return Promise.resolve({a:123});
- }
- }
- });
- request(app)
- .get('/nodes/module/set/messages')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.eql({a:123});
- done();
- });
- });
- it('returns all node catalogs', function(done) {
- nodes.init({
- settings: {},
- nodes:{
- getModuleCatalogs: function(opts) {
- return Promise.resolve({a:1});
- }
- }
- });
- request(app)
- .get('/nodes/messages')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.eql({a:1});
- done();
- });
- });
- })
-});
diff --git a/test/unit/@node-red/editor-api/lib/admin/plugins_spec.js b/test/unit/@node-red/editor-api/lib/admin/plugins_spec.js
deleted file mode 100644
index 74584a1d8..000000000
--- a/test/unit/@node-red/editor-api/lib/admin/plugins_spec.js
+++ /dev/null
@@ -1,111 +0,0 @@
-const should = require("should");
-const request = require('supertest');
-const express = require('express');
-const bodyParser = require("body-parser");
-
-var app;
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var plugins = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/plugins");
-
-describe("api/editor/plugins", function() {
- const pluginList = [
- {
- "id": "test-module/test-set",
- "enabled": true,
- "local": false,
- "plugins": [
- {
- "type": "foo",
- "id": "a-plugin",
- "module": "test-module"
- },
- {
- "type": "bar",
- "id": "a-plugin2",
- "module": "test-module"
- },
- {
- "type": "foo",
- "id": "a-plugin3",
- "module": "test-module"
- }
- ]
- },
- {
- "id": "test-module/test-disabled-set",
- "enabled": false,
- "local": false,
- "plugins": []
- }
- ];
- const pluginConfigs = `
-
-test-module-config`;
-
- const pluginCatalogs = { "test-module": {"foo": "bar"}};
-
- before(function() {
- app = express();
- app.use(bodyParser.json());
- app.get("/plugins",plugins.getAll);
- app.get("/plugins/messages",plugins.getCatalogs);
-
- plugins.init({
- plugins: {
- getPluginList: async function() { return pluginList },
- getPluginConfigs: async function() { return pluginConfigs },
- getPluginCatalogs: async function() { return pluginCatalogs }
- }
- })
- });
-
- it('returns the list of plugins', function(done) {
- request(app)
- .get("/plugins")
- .set('Accept', 'application/json')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- try {
- JSON.stringify(res.body).should.eql(JSON.stringify(pluginList));
- done();
- } catch(err) {
- done(err)
- }
- });
- });
- it('returns the plugin configs', function(done) {
- request(app)
- .get("/plugins")
- .set('Accept', 'text/html')
- .expect(200)
- .expect(pluginConfigs)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- done();
- });
- });
- it('returns the plugin catalogs', function(done) {
- request(app)
- .get("/plugins/messages")
- .set('Accept', 'application/json')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- try {
- JSON.stringify(res.body).should.eql(JSON.stringify(pluginCatalogs));
- done();
- } catch(err) {
- done(err)
- }
- });
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/admin/settings_spec.js b/test/unit/@node-red/editor-api/lib/admin/settings_spec.js
deleted file mode 100644
index 6180f903d..000000000
--- a/test/unit/@node-red/editor-api/lib/admin/settings_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var request = require('supertest');
-var express = require('express');
-var bodyParser = require("body-parser");
-var sinon = require('sinon');
-
-var app;
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var info = NR_TEST_UTILS.require("@node-red/editor-api/lib/admin/settings");
-var theme = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme");
-
-describe("api/editor/settings", function() {
- before(function() {
- sinon.stub(theme,"settings").callsFake(function() { return { existing: 123, test: 456 };});
- app = express();
- app.use(bodyParser.json());
- app.get("/settings",info.runtimeSettings);
- });
-
- after(function() {
- theme.settings.restore();
- });
-
- it('returns the runtime settings', function(done) {
- info.init({},{
- settings: {
- getRuntimeSettings: function(opts) {
- return Promise.resolve({
- a:1,
- b:2,
- editorTheme: { existing: 789 }
- })
- }
- }
- });
- request(app)
- .get("/settings")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property("a",1);
- res.body.should.have.property("b",2);
- res.body.should.have.property("editorTheme",{existing: 789, test:456});
- done();
- });
- });
- it('returns the runtime settings - disableEditor true', function(done) {
- info.init({disableEditor: true},{
- settings: {
- getRuntimeSettings: function(opts) {
- return Promise.resolve({
- a:1,
- b:2
- })
- }
- }
- });
- request(app)
- .get("/settings")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property("a",1);
- res.body.should.have.property("b",2);
- // no editorTheme if disabledEditor true
- res.body.should.not.have.property("editorTheme");
- done();
- });
- });
-
-});
diff --git a/test/unit/@node-red/editor-api/lib/auth/clients_spec.js b/test/unit/@node-red/editor-api/lib/auth/clients_spec.js
deleted file mode 100644
index 1f6263d00..000000000
--- a/test/unit/@node-red/editor-api/lib/auth/clients_spec.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var NR_TEST_UTILS = require("nr-test-utils");
-var Clients = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/clients");
-
-describe("api/auth/clients", function() {
- it('finds the known editor client',function(done) {
- Clients.get("node-red-editor").then(function(client) {
- client.should.have.property("id","node-red-editor");
- client.should.have.property("secret","not_available");
- done();
- });
- });
- it('finds the known admin client',function(done) {
- Clients.get("node-red-admin").then(function(client) {
- client.should.have.property("id","node-red-admin");
- client.should.have.property("secret","not_available");
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- it('returns null for unknown client',function(done) {
- Clients.get("unknown-client").then(function(client) {
- should.not.exist(client);
- done();
- }).catch(function(err) {
- done(err);
- });
-
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/auth/index_spec.js b/test/unit/@node-red/editor-api/lib/auth/index_spec.js
deleted file mode 100644
index 010b6b08a..000000000
--- a/test/unit/@node-red/editor-api/lib/auth/index_spec.js
+++ /dev/null
@@ -1,216 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var passport = require("passport");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var auth = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth");
-var Users = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/users");
-var Tokens = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/tokens");
-var Permissions = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/permissions");
-
-describe("api/auth/index",function() {
-
-
-
- describe("ensureClientSecret", function() {
- before(function() {
- auth.init({},{})
- });
- it("leaves client_secret alone if not present",function(done) {
- var req = {
- body: {
- client_secret: "test_value"
- }
- };
- auth.ensureClientSecret(req,null,function() {
- req.body.should.have.a.property("client_secret","test_value");
- done();
- })
- });
- it("applies a default client_secret if not present",function(done) {
- var req = {
- body: { }
- };
- auth.ensureClientSecret(req,null,function() {
- req.body.should.have.a.property("client_secret","not_available");
- done();
- })
- });
- });
-
- describe("revoke", function() {
- it("revokes a token", function(done) {
- var revokeToken = sinon.stub(Tokens,"revoke").callsFake(function() {
- return Promise.resolve();
- });
-
- var req = { body: { token: "abcdef" } };
-
- var res = { status: function(resp) {
- revokeToken.restore();
-
- resp.should.equal(200);
- return {
- end: done
- }
- }};
-
- auth.revoke(req,res);
- });
- });
-
- describe("login", function() {
- beforeEach(function() {
- sinon.stub(Tokens,"init").callsFake(function(){});
- sinon.stub(Users,"init").callsFake(function(){});
- });
- afterEach(function() {
- Tokens.init.restore();
- Users.init.restore();
- });
- it("returns login details - credentials", function(done) {
- auth.init({adminAuth:{type:"credentials"}},{})
- auth.login(null,{json: function(resp) {
- resp.should.have.a.property("type","credentials");
- resp.should.have.a.property("prompts");
- resp.prompts.should.have.a.lengthOf(2);
- done();
- }});
- });
- it("returns login details - none", function(done) {
- auth.init({},{})
- auth.login(null,{json: function(resp) {
- resp.should.eql({});
- done();
- }});
- });
- it("returns login details - strategy", function(done) {
- auth.init({adminAuth:{type:"strategy",strategy:{label:"test-strategy",icon:"test-icon"}}},{})
- auth.login(null,{json: function(resp) {
- resp.should.have.a.property("type","strategy");
- resp.should.have.a.property("prompts");
- resp.prompts.should.have.a.lengthOf(1);
- resp.prompts[0].should.have.a.property("type","button");
- resp.prompts[0].should.have.a.property("label","test-strategy");
- resp.prompts[0].should.have.a.property("icon","test-icon");
-
- done();
- }});
- });
-
- });
- describe("needsPermission", function() {
- beforeEach(function() {
- sinon.stub(Tokens,"init").callsFake(function(){});
- sinon.stub(Users,"init").callsFake(function(){});
- });
- afterEach(function() {
- Tokens.init.restore();
- Users.init.restore();
- if (passport.authenticate.restore) {
- passport.authenticate.restore();
- }
- if (Permissions.hasPermission.restore) {
- Permissions.hasPermission.restore();
- }
- });
-
-
- it('no-ops if adminAuth not set', function(done) {
- sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
- return function(req,res,next) {
- }
- });
- auth.init({});
- var func = auth.needsPermission("foo");
- func({},{},function() {
- passport.authenticate.called.should.be.false();
- done();
- })
- });
- it('skips auth if req.user undefined', function(done) {
- sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
- return function(req,res,next) {
- next();
- }
- });
- sinon.stub(Permissions,"hasPermission").callsFake(function(perm) { return true });
- auth.init({adminAuth:{}});
- var func = auth.needsPermission("foo");
- func({user:null},{},function() {
- try {
- passport.authenticate.called.should.be.true();
- Permissions.hasPermission.called.should.be.false();
- done();
- } catch(err) {
- done(err);
- }
- })
- });
-
- it('passes for valid user permission', function(done) {
- sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
- return function(req,res,next) {
- next();
- }
- });
- sinon.stub(Permissions,"hasPermission").callsFake(function(perm) { return true });
- auth.init({adminAuth:{}});
- var func = auth.needsPermission("foo");
- func({user:true,authInfo: { scope: "read"}},{},function() {
- try {
- passport.authenticate.called.should.be.true();
- Permissions.hasPermission.called.should.be.true();
- Permissions.hasPermission.lastCall.args[0].should.eql("read");
- Permissions.hasPermission.lastCall.args[1].should.eql("foo");
- done();
- } catch(err) {
- done(err);
- }
- })
- });
-
- it('rejects for invalid user permission', function(done) {
- sinon.stub(passport,"authenticate").callsFake(function(scopes,opts) {
- return function(req,res,next) {
- next();
- }
- });
- sinon.stub(Permissions,"hasPermission").callsFake(function(perm) { return false });
- auth.init({adminAuth:{}});
- var func = auth.needsPermission("foo");
- func({user:true,authInfo: { scope: "read"}},{
- status: function(status) {
- return { end: function() {
- try {
- status.should.eql(401);
- done();
- } catch(err) {
- done(err);
- }
- }}
- }
- },function() {
- done(new Error("hasPermission unexpected passed"))
- });
- });
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/auth/permissions_spec.js b/test/unit/@node-red/editor-api/lib/auth/permissions_spec.js
deleted file mode 100644
index 50c249c34..000000000
--- a/test/unit/@node-red/editor-api/lib/auth/permissions_spec.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var permissions = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/permissions");
-
-describe("api/auth/permissions", function() {
- describe("hasPermission", function() {
- it('a user with no permissions',function() {
- permissions.hasPermission([],"*").should.be.false();
- });
- it('a user with global permissions',function() {
- permissions.hasPermission("*","read").should.be.true();
- permissions.hasPermission(["*"],"write").should.be.true();
- });
- it('a user with read permissions',function() {
- permissions.hasPermission(["read"],"read").should.be.true();
- permissions.hasPermission(["read"],"node.read").should.be.true();
- permissions.hasPermission(["read"],"write").should.be.false();
- permissions.hasPermission(["read"],"node.write").should.be.false();
- permissions.hasPermission(["*.read"],"read").should.be.true();
- permissions.hasPermission(["*.read"],"node.read").should.be.true();
- permissions.hasPermission(["*.read"],"write").should.be.false();
- permissions.hasPermission(["*.read"],"node.write").should.be.false();
- });
- it('a user with foo permissions',function() {
- permissions.hasPermission("foo","foo").should.be.true();
- });
- it('an array of permissions', function() {
- permissions.hasPermission(["*"],["foo.read","foo.write"]).should.be.true();
- permissions.hasPermission("read",["foo.read","foo.write"]).should.be.false();
- permissions.hasPermission("read",["foo.read","bar.read"]).should.be.true();
- permissions.hasPermission(["flows.read"],["flows.read"]).should.be.true();
- permissions.hasPermission(["flows.read"],["flows.write"]).should.be.false();
- permissions.hasPermission(["flows.read","nodes.write"],["flows.write"]).should.be.false();
- permissions.hasPermission(["flows.read","nodes.write"],["nodes.write"]).should.be.true();
- });
- it('permits an empty permission', function() {
- permissions.hasPermission("*","").should.be.true();
- permissions.hasPermission("read",[""]).should.be.true();
- });
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/auth/strategies_spec.js b/test/unit/@node-red/editor-api/lib/auth/strategies_spec.js
deleted file mode 100644
index 9fafc11ed..000000000
--- a/test/unit/@node-red/editor-api/lib/auth/strategies_spec.js
+++ /dev/null
@@ -1,327 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require('sinon');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var strategies = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/strategies");
-var Users = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/users");
-var Tokens = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/tokens");
-var Clients = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/clients");
-
-describe("api/auth/strategies", function() {
- describe("Password Token Exchange", function() {
- var userAuthentication;
- afterEach(function() {
- if (userAuthentication) {
- userAuthentication.restore();
- userAuthentication = null;
- }
- });
-
- it('Handles authentication failure',function(done) {
- userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
- return Promise.resolve(null);
- });
-
- strategies.passwordTokenExchange({},"user","password","scope",function(err,token) {
- try {
- should.not.exist(err);
- token.should.be.false();
- done();
- } catch(e) {
- done(e);
- }
- });
- });
-
- it('Handles scope overreach',function(done) {
- userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
- return Promise.resolve({username:"user",permissions:"read"});
- });
-
- strategies.passwordTokenExchange({},"user","password","*",function(err,token) {
- try {
- should.not.exist(err);
- token.should.be.false();
- done();
- } catch(e) {
- done(e);
- }
- });
- });
-
- it('Creates new token on authentication success',function(done) {
- userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
- return Promise.resolve({username:"user",permissions:"*"});
- });
- var tokenDetails = {};
- var tokenCreate = sinon.stub(Tokens,"create").callsFake(function(username,client,scope) {
- tokenDetails.username = username;
- tokenDetails.client = client;
- tokenDetails.scope = scope;
- return Promise.resolve({accessToken: "123456"});
- });
-
- strategies.passwordTokenExchange({id:"myclient"},"user","password","read",function(err,token) {
- try {
- should.not.exist(err);
- token.should.equal("123456");
- tokenDetails.should.have.property("username","user");
- tokenDetails.should.have.property("client","myclient");
- tokenDetails.should.have.property("scope","read");
- done();
- } catch(e) {
- done(e);
- } finally {
- tokenCreate.restore();
- }
- });
-
- });
- });
-
- describe("Anonymous Strategy", function() {
- it('Succeeds if anon user enabled',function(done) {
- var userDefault = sinon.stub(Users,"default").callsFake(function() {
- return Promise.resolve("anon");
- });
- strategies.anonymousStrategy._success = strategies.anonymousStrategy.success;
- strategies.anonymousStrategy.success = function(user) {
- user.should.equal("anon");
- strategies.anonymousStrategy.success = strategies.anonymousStrategy._success;
- delete strategies.anonymousStrategy._success;
- done();
- };
- strategies.anonymousStrategy.authenticate({});
- });
- it('Fails if anon user not enabled',function(done) {
- var userDefault = sinon.stub(Users,"default").callsFake(function() {
- return Promise.resolve(null);
- });
- strategies.anonymousStrategy._fail = strategies.anonymousStrategy.fail;
- strategies.anonymousStrategy.fail = function(err) {
- err.should.equal(401);
- strategies.anonymousStrategy.fail = strategies.anonymousStrategy._fail;
- delete strategies.anonymousStrategy._fail;
- done();
- };
- strategies.anonymousStrategy.authenticate({});
- });
- afterEach(function() {
- Users.default.restore();
- })
- });
-
- describe("Tokens Strategy", function() {
- it('Succeeds if tokens user enabled custom header',function(done) {
- var userTokens = sinon.stub(Users,"tokens").callsFake(function(token) {
- return Promise.resolve("tokens-"+token);
- });
- var userTokenHeader = sinon.stub(Users,"tokenHeader").callsFake(function(token) {
- return "x-test-token";
- });
- strategies.tokensStrategy._success = strategies.tokensStrategy.success;
- strategies.tokensStrategy.success = function(user) {
- user.should.equal("tokens-1234");
- strategies.tokensStrategy.success = strategies.tokensStrategy._success;
- delete strategies.tokensStrategy._success;
- done();
- };
- strategies.tokensStrategy.authenticate({headers:{"x-test-token":"1234"}});
- });
- it('Succeeds if tokens user enabled default header',function(done) {
- var userTokens = sinon.stub(Users,"tokens").callsFake(function(token) {
- return Promise.resolve("tokens-"+token);
- });
- var userTokenHeader = sinon.stub(Users,"tokenHeader").callsFake(function(token) {
- return "authorization";
- });
- strategies.tokensStrategy._success = strategies.tokensStrategy.success;
- strategies.tokensStrategy.success = function(user) {
- user.should.equal("tokens-1234");
- strategies.tokensStrategy.success = strategies.tokensStrategy._success;
- delete strategies.tokensStrategy._success;
- done();
- };
- strategies.tokensStrategy.authenticate({headers:{"authorization":"Bearer 1234"}});
- });
- it('Fails if tokens user not enabled',function(done) {
- var userTokens = sinon.stub(Users,"tokens").callsFake(function() {
- return Promise.resolve(null);
- });
- var userTokenHeader = sinon.stub(Users,"tokenHeader").callsFake(function(token) {
- return "authorization";
- });
- strategies.tokensStrategy._fail = strategies.tokensStrategy.fail;
- strategies.tokensStrategy.fail = function(err) {
- err.should.equal(401);
- strategies.tokensStrategy.fail = strategies.tokensStrategy._fail;
- delete strategies.tokensStrategy._fail;
- done();
- };
- strategies.tokensStrategy.authenticate({headers:{"authorization":"Bearer 1234"}});
- });
- afterEach(function() {
- Users.tokens.restore();
- Users.tokenHeader.restore();
- })
- });
-
- describe("Bearer Strategy", function() {
- it('Rejects invalid token',function(done) {
- var getToken = sinon.stub(Tokens,"get").callsFake(function(token) {
- return Promise.resolve(null);
- });
-
- strategies.bearerStrategy("1234",function(err,user) {
- try {
- should.not.exist(err);
- user.should.be.false();
- done();
- } catch(e) {
- done(e);
- } finally {
- getToken.restore();
- }
- });
- });
- it('Accepts valid token',function(done) {
- var getToken = sinon.stub(Tokens,"get").callsFake(function(token) {
- return Promise.resolve({user:"user",scope:"scope"});
- });
- var getUser = sinon.stub(Users,"get").callsFake(function(username) {
- return Promise.resolve("aUser");
- });
-
- strategies.bearerStrategy("1234",function(err,user,opts) {
- try {
- should.not.exist(err);
- user.should.equal("aUser");
- opts.should.have.a.property("scope","scope");
- done();
- } catch(e) {
- done(e);
- } finally {
- getToken.restore();
- getUser.restore();
- }
- });
- });
- it('Fail if no user for token',function(done) {
- var getToken = sinon.stub(Tokens,"get").callsFake(function(token) {
- return Promise.resolve({user:"user",scope:"scope"});
- });
- var getUser = sinon.stub(Users,"get").callsFake(function(username) {
- return Promise.resolve(null);
- });
-
- strategies.bearerStrategy("1234",function(err,user,opts) {
- try {
- should.not.exist(err);
- user.should.equal(false);
- should.not.exist(opts);
- done();
- } catch(e) {
- done(e);
- } finally {
- getToken.restore();
- getUser.restore();
- }
- });
- });
- });
-
- describe("Client Password Strategy", function() {
- it('Accepts valid client',function(done) {
- var testClient = {id:"node-red-editor",secret:"not_available"};
- var getClient = sinon.stub(Clients,"get").callsFake(function(client) {
- return Promise.resolve(testClient);
- });
-
- strategies.clientPasswordStrategy(testClient.id,testClient.secret,function(err,client) {
- try {
- should.not.exist(err);
- client.should.eql(testClient);
- done();
- } catch(e) {
- done(e);
- } finally {
- getClient.restore();
- }
- });
- });
- it('Rejects invalid client secret',function(done) {
- var testClient = {id:"node-red-editor",secret:"not_available"};
- var getClient = sinon.stub(Clients,"get").callsFake(function(client) {
- return Promise.resolve(testClient);
- });
-
- strategies.clientPasswordStrategy(testClient.id,"invalid_secret",function(err,client) {
- try {
- should.not.exist(err);
- client.should.be.false();
- done();
- } catch(e) {
- done(e);
- } finally {
- getClient.restore();
- }
- });
- });
- it('Rejects invalid client id',function(done) {
- var getClient = sinon.stub(Clients,"get").callsFake(function(client) {
- return Promise.resolve(null);
- });
- strategies.clientPasswordStrategy("invalid_id","invalid_secret",function(err,client) {
- try {
- should.not.exist(err);
- client.should.be.false();
- done();
- } catch(e) {
- done(e);
- } finally {
- getClient.restore();
- }
- });
- });
-
- var userAuthentication;
- it('Blocks after 5 failures',function(done) {
- userAuthentication = sinon.stub(Users,"authenticate").callsFake(function(username,password) {
- return Promise.resolve(null);
- });
- for (var z=0; z<5; z++) {
- strategies.passwordTokenExchange({},"user","badpassword","scope",function(err,token) {
- });
- }
- strategies.passwordTokenExchange({},"user","badpassword","scope",function(err,token) {
- try {
- err.toString().should.equal("Error: Too many login attempts. Wait 10 minutes and try again");
- token.should.be.false();
- done();
- } catch(e) {
- done(e);
- } finally {
- userAuthentication.restore();
- }
- });
- });
-
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/auth/tokens_spec.js b/test/unit/@node-red/editor-api/lib/auth/tokens_spec.js
deleted file mode 100644
index 9bb231eb5..000000000
--- a/test/unit/@node-red/editor-api/lib/auth/tokens_spec.js
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var Tokens = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/tokens");
-
-
-describe("api/auth/tokens", function() {
- describe("#init",function() {
- it('loads sessions', function(done) {
- Tokens.init({}).then(done);
- });
- });
-
-
- describe("#get",function() {
- it('returns a valid token', function(done) {
- Tokens.init({},{
- getSessions:function() {
- return Promise.resolve({"1234":{"user":"fred","expires":Date.now()+1000}});
- }
- }).then(function() {
- Tokens.get("1234").then(function(token) {
- try {
- token.should.have.a.property("user","fred");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('returns null for an invalid token', function(done) {
- Tokens.init({},{
- getSessions:function() {
- return Promise.resolve({});
- }
- }).then(function() {
- Tokens.get("1234").then(function(token) {
- try {
- should.not.exist(token);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
- it('returns null for an expired token', function(done) {
- var saveSessions = sinon.stub().returns(Promise.resolve());
- var expiryTime = Date.now()+50;
- Tokens.init({},{
- getSessions:function() {
- return Promise.resolve({"1234":{"user":"fred","expires":expiryTime}});
- },
- saveSessions: saveSessions
- }).then(function() {
- Tokens.get("1234").then(function(token) {
- try {
- should.exist(token);
- setTimeout(function() {
- Tokens.get("1234").then(function(token) {
- try {
- should.not.exist(token);
- saveSessions.calledOnce.should.be.true();
- done();
- } catch(err) {
- done(err);
- }
- });
- },100);
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- it('returns a valid api token', function(done) {
- Tokens.init({
- tokens: [{
- token: "1234",
- user: "fred",
- }]
- },{
- getSessions:function() {
- return Promise.resolve({});
- }
- }).then(function() {
- Tokens.get("1234").then(function(token) {
- try {
- token.should.have.a.property("user","fred");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- });
- });
-
- describe("#create",function() {
- it('creates a token', function(done) {
- var savedSession;
- Tokens.init({sessionExpiryTime: 10},{
- getSessions:function() {
- return Promise.resolve({});
- },
- saveSessions:function(sess) {
- savedSession = sess;
- return Promise.resolve();
- }
- });
- var expectedExpiryTime = Date.now()+10000;
-
-
- Tokens.create("user","client","scope").then(function(token) {
- try {
- should.exist(savedSession);
- var sessionKeys = Object.keys(savedSession);
- sessionKeys.should.have.lengthOf(1);
-
- token.should.have.a.property('accessToken',sessionKeys[0]);
- savedSession[sessionKeys[0]].should.have.a.property('user','user');
- savedSession[sessionKeys[0]].should.have.a.property('client','client');
- savedSession[sessionKeys[0]].should.have.a.property('scope','scope');
- savedSession[sessionKeys[0]].should.have.a.property('expires');
- savedSession[sessionKeys[0]].expires.should.be.within(expectedExpiryTime-200,expectedExpiryTime+200);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- describe("#revoke", function() {
- it('revokes a token', function(done) {
- var savedSession;
- Tokens.init({},{
- getSessions:function() {
- return Promise.resolve({"1234":{"user":"fred","expires":Date.now()+1000}});
- },
- saveSessions:function(sess) {
- savedSession = sess;
- return Promise.resolve();
- }
- }).then(function() {
- Tokens.revoke("1234").then(function() {
- try {
- savedSession.should.not.have.a.property("1234");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/editor-api/lib/auth/users_spec.js b/test/unit/@node-red/editor-api/lib/auth/users_spec.js
deleted file mode 100644
index e07a35a03..000000000
--- a/test/unit/@node-red/editor-api/lib/auth/users_spec.js
+++ /dev/null
@@ -1,276 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require('sinon');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var Users = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/users");
-
-describe("api/auth/users", function() {
- after(function() {
- Users.init({});
- })
- describe('Initalised with a credentials object, no anon',function() {
- before(function() {
- Users.init({
- type:"credentials",
- users:{
- username:"fred",
- password:'$2a$08$LpYMefvGZ3MjAfZGzcoyR.1BcfHh4wy4NpbN.cEny5aHnWOqjKOXK',
- // 'password' -> require('bcryptjs').hashSync('password', 8);
- permissions:"*"
- }
- });
- });
- describe('#get',function() {
- it('returns known user',function(done) {
- Users.get("fred").then(function(user) {
- try {
- user.should.have.a.property("username","fred");
- user.should.have.a.property("permissions","*");
- user.should.not.have.a.property("password");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('returns null for unknown user', function(done) {
- Users.get("barney").then(function(user) {
- try {
- should.not.exist(user);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- describe('#default',function() {
- it('returns null for default user', function(done) {
- Users.default().then(function(user) {
- try {
- should.not.exist(user);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
-
- describe('#authenticate',function() {
- it('authenticates a known user', function(done) {
- Users.authenticate('fred','password').then(function(user) {
- try {
- user.should.have.a.property("username","fred");
- user.should.have.a.property("permissions","*");
- user.should.not.have.a.property("password");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- it('rejects invalid password for a known user', function(done) {
- Users.authenticate('fred','wrong').then(function(user) {
- try {
- should.not.exist(user);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('rejects invalid user', function(done) {
- Users.authenticate('barney','wrong').then(function(user) {
- try {
- should.not.exist(user);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
- });
-
- describe('Initalised with a credentials object including anon',function() {
- before(function() {
- Users.init({
- type:"credentials",
- users:[],
- default: { permissions: "*" }
- });
- });
- describe('#default',function() {
- it('returns default user', function(done) {
- Users.default().then(function(user) {
- try {
- user.should.have.a.property('anonymous',true);
- user.should.have.a.property('permissions','*');
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
- });
-
- describe('Initialised with a credentials object with user functions',function() {
- var authUsername = '';
- var authPassword = '';
- before(function() {
- Users.init({
- type:"credentials",
- users:function(username) {
- return Promise.resolve({'username':'dave','permissions':'read'});
- },
- authenticate: function(username,password) {
- authUsername = username;
- authPassword = password;
- return Promise.resolve({'username':'pete','permissions':'write'});
- }
- });
- });
-
- describe('#get',function() {
- it("returns null for tokenHeader", function() {
- should.not.exist(Users.tokenHeader());
- });
-
- it('delegates get user',function(done) {
- Users.get('dave').then(function(user) {
- try {
- user.should.have.a.property("username","dave");
- user.should.have.a.property("permissions","read");
- user.should.not.have.a.property("password");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- it('delegates authenticate user',function(done) {
- Users.authenticate('pete','secret').then(function(user) {
- try {
- user.should.have.a.property("username","pete");
- user.should.have.a.property("permissions","write");
- user.should.not.have.a.property("password");
- authUsername.should.equal('pete');
- authPassword.should.equal('secret');
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
- });
-
- describe('Initialised with bad settings to test else cases',function() {
- before(function() {
- Users.init({
- type:"foo",
- users:{
- username:"fred",
- password:'$2a$08$LpYMefvGZ3MjAfZGzcoyR.1BcfHh4wy4NpbN.cEny5aHnWOqjKOXK',
- permissions:"*"
- }
- });
- });
- describe('#get',function() {
- it('should fail to return user fred',function(done) {
- Users.get("fred").then(function(userf) {
- try {
- should.not.exist(userf);
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- });
- });
-
- describe('Initialised with default set as function',function() {
- before(function() {
- Users.init({
- type:"credentials",
- default: function() { return("Done"); }
- });
- });
- after(function() {
- Users.init({});
- });
- describe('#default',function() {
- it('handles api.default being a function',function(done) {
- Users.should.have.property('default').which.is.a.Function();
- (Users.default()).should.equal("Done");
- done();
- });
- });
- });
-
- describe('Initialised with tokens set as function',function() {
- before(function() {
- Users.init({
- type:"strategy",
- tokens: function(token) { return("Done-"+token); }
- });
- });
- after(function() {
- Users.init({});
- });
- describe('#tokens',function() {
- it('handles api.tokens being a function',function(done) {
- Users.should.have.property('tokens').which.is.a.Function();
- (Users.tokens("1234")).should.equal("Done-1234");
- (Users.tokenHeader()).should.equal("authorization");
- done();
- });
- });
- });
-
- describe('Initialised with tokens set as function and tokenHeader set as token header name',function() {
- before(function() {
- Users.init({
- type:"strategy",
- tokens: function(token) { return("Done-"+token); },
- tokenHeader: "X-TEST-TOKEN"
- });
- });
- after(function() {
- Users.init({});
- });
- describe('#tokens',function() {
- it('handles api.tokens being a function and api.tokenHeader being a header name',function(done) {
- Users.should.have.property('tokens').which.is.a.Function();
- (Users.tokens("1234")).should.equal("Done-1234");
- Users.should.have.property('tokenHeader').which.is.a.Function();
- (Users.tokenHeader()).should.equal("x-test-token");
- done();
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/comms_spec.js b/test/unit/@node-red/editor-api/lib/editor/comms_spec.js
deleted file mode 100644
index 4197dc469..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/comms_spec.js
+++ /dev/null
@@ -1,618 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-const stoppable = require('stoppable');
-
-var http = require('http');
-var express = require('express');
-var app = express();
-var WebSocket = require('ws');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var comms = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/comms");
-var Users = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/users");
-var Tokens = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/tokens");
-var Strategies = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth/strategies");
-var address = '127.0.0.1';
-var listenPort = 0; // use ephemeral port
-
-
-describe("api/editor/comms", function() {
- var connections = [];
- var mockComms = {
- addConnection: function(opts) {
- connections.push(opts.client);
- return Promise.resolve()
- },
- removeConnection: function(opts) {
- for (var i=0;i{});
- return p;
- }
- }
- }
- });
- });
-
- it('returns stored credentials',function(done) {
- request(app)
- .get("/credentials/known-type/n1")
- .expect("Content-Type",/json/)
- .expect(200)
- .end(function(err,res) {
- if (err) {
- done(err);
- } else {
- try {
- res.body.should.have.a.property("user1","abc");
- res.body.should.not.have.a.property("password1");
- res.body.should.have.a.property("has_password1",true);
- done();
- } catch(e) {
- done(e);
- }
- }
- })
- });
- it('returns any error',function(done) {
- request(app)
- .get("/credentials/unknown-type/n2")
- .expect("Content-Type",/json/)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- done(err);
- } else {
- try {
- res.body.should.have.property('code');
- res.body.code.should.be.equal("test_code");
- res.body.should.have.property('message');
- res.body.message.should.be.equal('message');
- done();
- } catch(e) {
- done(e);
- }
- }
- })
- });
-
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/index_spec.js b/test/unit/@node-red/editor-api/lib/editor/index_spec.js
deleted file mode 100644
index 8ed4d88f3..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/index_spec.js
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var request = require("supertest");
-var express = require("express");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var editorApi = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor");
-var comms = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/comms");
-var info = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/settings");
-var auth = NR_TEST_UTILS.require("@node-red/editor-api/lib/auth");
-
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-
-describe("api/editor/index", function() {
- var app;
- describe("disabled the editor", function() {
- beforeEach(function() {
- sinon.stub(comms,'init').callsFake(function(){});
- sinon.stub(info,'init').callsFake(function(){});
- });
- afterEach(function() {
- comms.init.restore();
- info.init.restore();
- });
- it("disables the editor", function() {
- var editorApp = editorApi.init({},{disableEditor:true},{});
- should.not.exist(editorApp);
- comms.init.called.should.be.false();
- info.init.called.should.be.false();
- });
- });
- describe("enables the editor", function() {
- var mockList = [
- 'library','theme','locales','credentials','comms',"settings"
- ]
- var isStarted = true;
- var errors = [];
- var session_data = {};
- before(function() {
- sinon.stub(auth,'needsPermission').callsFake(function(permission) {
- return function(req,res,next) { next(); }
- });
- mockList.forEach(function(m) {
- sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m),"init").callsFake(function(){});
- });
- sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme"),"app").callsFake(function(){ return express()});
- });
- after(function() {
- mockList.forEach(function(m) {
- NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m).init.restore();
- })
- NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme").app.restore();
- auth.needsPermission.restore();
- log.error.restore();
- });
-
- before(function() {
- sinon.stub(log,"error").callsFake(function(err) { errors.push(err)})
- app = editorApi.init({},{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false,exportNodeSettings:function(){}},{
- isStarted: () => Promise.resolve(isStarted)
- });
- });
- it('serves the editor', function(done) {
- request(app)
- .get("/")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- // Index page should probably mention Node-RED somewhere
- res.text.indexOf("Node-RED").should.not.eql(-1);
- done();
- });
- });
- it('serves icons', function(done) {
- request(app)
- .get("/red/images/icons/arrow-in.svg")
- .expect(200)
- .expect("Content-Type", /image\/svg\+xml/)
- .end(function(err,res) {
- done(err);
- });
- });
- it('handles page not there', function(done) {
- request(app)
- .get("/foo")
- .expect(404,done)
- });
- it('warns if runtime not started', function(done) {
- isStarted = false;
- request(app)
- .get("/")
- .expect(503)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.text.should.eql("Not started");
- errors.should.have.lengthOf(1);
- errors[0].should.eql("Node-RED runtime not started");
- done();
- });
- });
- // it.skip('GET /settings', function(done) {
- // request(app).get("/settings").expect(200).end(function(err,res) {
- // if (err) {
- // return done(err);
- // }
- // // permissionChecks.should.have.property('settings.read',1);
- // done();
- // })
- // });
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/library_spec.js b/test/unit/@node-red/editor-api/lib/editor/library_spec.js
deleted file mode 100644
index 4a2c281b7..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/library_spec.js
+++ /dev/null
@@ -1,263 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var request = require('supertest');
-var express = require('express');
-var bodyParser = require('body-parser');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var library = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/library");
-
-var app;
-
-describe("api/editor/library", function() {
-
- before(function() {
- app = express();
- app.use(bodyParser.json());
- app.get(/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,library.getEntry);
- app.post(/library\/([^\/]+)\/([^\/]+)\/(.*)/,library.saveEntry);
- });
- after(function() {
- });
-
- it('returns an individual entry - flow type', function(done) {
- var opts;
- library.init({
- library: {
- getEntry: function(_opts) {
- opts = _opts;
- return Promise.resolve('{"a":1,"b":2}');
- }
- }
- });
- request(app)
- .get('/library/local/flows/abc')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('a',1);
- res.body.should.have.property('b',2);
- opts.should.have.property('library','local');
- opts.should.have.property('type','flows');
- opts.should.have.property('path','abc');
- done();
- });
- })
- it('returns a directory listing - flow type', function(done) {
- var opts;
- library.init({
- library: {
- getEntry: function(_opts) {
- opts = _opts;
- return Promise.resolve({"a":1,"b":2});
- }
- }
- });
- request(app)
- .get('/library/local/flows/abc/def')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('a',1);
- res.body.should.have.property('b',2);
- opts.should.have.property('library','local');
- opts.should.have.property('type','flows');
- opts.should.have.property('path','abc/def');
- done();
- });
- })
- it('returns an individual entry - non-flow type', function(done) {
- var opts;
- library.init({
- library: {
- getEntry: function(_opts) {
- opts = _opts;
- return Promise.resolve('{"a":1,"b":2}');
- }
- }
- });
- request(app)
- .get('/library/local/non-flow/abc')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- opts.should.have.property('library','local');
- opts.should.have.property('type','non-flow');
- opts.should.have.property('path','abc');
- res.text.should.eql('{"a":1,"b":2}');
- done();
- });
- })
- it('returns a directory listing - non-flow type', function(done) {
- var opts;
- library.init({
- library: {
- getEntry: function(_opts) {
- opts = _opts;
- return Promise.resolve({"a":1,"b":2});
- }
- }
- });
- request(app)
- .get('/library/local/non-flow/abc/def')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('a',1);
- res.body.should.have.property('b',2);
- opts.should.have.property('library','local');
- opts.should.have.property('type','non-flow');
- opts.should.have.property('path','abc/def');
- done();
- });
- })
-
- it('returns an error on individual get', function(done) {
- var opts;
- library.init({
- library: {
- getEntry: function(_opts) {
- opts = _opts;
- var err = new Error("message");
- err.code = "random_error";
- err.status = 400;
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- }
- });
- request(app)
- .get('/library/local/flows/123')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- opts.should.have.property('library','local');
- opts.should.have.property('type','flows');
- opts.should.have.property('path','123');
-
- res.body.should.have.property('code');
- res.body.code.should.be.equal("random_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal("message");
- done();
- });
- });
-
-
- it('saves an individual entry - flow type', function(done) {
- var opts;
- library.init({
- library: {
- saveEntry: function(_opts) {
- opts = _opts;
- return Promise.resolve();
- }
- }
- });
- request(app)
- .post('/library/local/flows/abc/def')
- .expect(204)
- .send({a:1,b:2,c:3})
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- opts.should.have.property('library','local');
- opts.should.have.property('type','flows');
- opts.should.have.property('path','abc/def');
- opts.should.have.property('meta',{});
- opts.should.have.property('body',JSON.stringify({a:1,b:2,c:3}));
- done();
- });
- })
-
- it('saves an individual entry - non-flow type', function(done) {
- var opts;
- library.init({
- library: {
- saveEntry: function(_opts) {
- opts = _opts;
- return Promise.resolve();
- }
- }
- });
- request(app)
- .post('/library/local/non-flow/abc/def')
- .expect(204)
- .send({a:1,b:2,text:"123"})
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- opts.should.have.property('library','local');
- opts.should.have.property('type','non-flow');
- opts.should.have.property('path','abc/def');
- opts.should.have.property('meta',{a:1,b:2});
- opts.should.have.property('body',"123");
- done();
- });
- })
-
- it('returns an error on individual save', function(done) {
- var opts;
- library.init({
- library: {
- saveEntry: function(_opts) {
- opts = _opts;
- var err = new Error("message");
- err.code = "random_error";
- err.status = 400;
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- }
- });
- request(app)
- .post('/library/local/non-flow/abc/def')
- .send({a:1,b:2,text:"123"})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- opts.should.have.property('type','non-flow');
- opts.should.have.property('library','local');
- opts.should.have.property('path','abc/def');
-
- res.body.should.have.property('code');
- res.body.code.should.be.equal("random_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal("message");
- done();
- });
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/locales_spec.js b/test/unit/@node-red/editor-api/lib/editor/locales_spec.js
deleted file mode 100644
index fef686a78..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/locales_spec.js
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var request = require('supertest');
-var express = require('express');
-var sinon = require('sinon');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var locales = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/locales");
-var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-describe("api/editor/locales", function() {
- beforeEach(function() {
- })
- afterEach(function() {
- })
- describe('get named resource catalog',function() {
- var app;
- before(function() {
- // locales.init({
- // i18n: {
- // i: {
- // language: function() { return 'en-US'},
- // changeLanguage: function(lang,callback) {
- // if (callback) {
- // callback();
- // }
- // },
- // getResourceBundle: function(lang, namespace) {
- // return {namespace:namespace, lang:lang};
- // }
- // },
- // }
- // });
- locales.init({});
-
- // bit of a mess of internal workings
- sinon.stub(i18n.i,'changeLanguage').callsFake(function(lang,callback) { if (callback) {callback();}});
- if (i18n.i.getResourceBundle) {
- sinon.stub(i18n.i,'getResourceBundle').callsFake(function(lang, namespace) {return {namespace:namespace, lang:lang};});
- } else {
- // If i18n.init has not been called, then getResourceBundle isn't
- // defined - so hardcode a stub
- i18n.i.getResourceBundle = function(lang, namespace) {return {namespace:namespace, lang:lang};};
- i18n.i.getResourceBundle.restore = function() { delete i18n.i.getResourceBundle };
- }
- app = express();
- app.get(/locales\/(.+)\/?$/,locales.get);
- });
- after(function() {
- i18n.i.changeLanguage.restore();
- i18n.i.getResourceBundle.restore();
- })
- it('returns with default language', function(done) {
- request(app)
- .get("/locales/message-catalog")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('namespace','message-catalog');
- done();
- });
- });
- it('returns with selected language', function(done) {
- request(app)
- .get("/locales/message-catalog?lng=fr-FR")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('namespace','message-catalog');
- res.body.should.have.property('lang','fr-FR');
- done();
- });
- });
-
- it('returns for locale defined only with primary tag ', function(done) {
- var orig = i18n.i.getResourceBundle;
- i18n.i.getResourceBundle = function (lang, ns) {
- if (lang === "ja-JP") {
- return undefined;
- }
- return orig(lang, ns);
- };
- request(app)
- // returns `ja` instead of `ja-JP`
- .get("/locales/message-catalog?lng=ja-JP")
- .expect(200)
- .end(function(err,res) {
- i18n.i.getResourceBundle = orig;
- if (err) {
- return done(err);
- }
- res.body.should.have.property('namespace','message-catalog');
- res.body.should.have.property('lang','ja');
- done();
- });
- });
-
- });
-
- // describe('get all node resource catalogs',function() {
- // var app;
- // before(function() {
- // // bit of a mess of internal workings
- // sinon.stub(i18n,'catalog').callsFake(function(namespace, lang) {
- // return {
- // "node-red": "should not return",
- // "test-module-a-id": "test-module-a-catalog",
- // "test-module-b-id": "test-module-b-catalog",
- // "test-module-c-id": "test-module-c-catalog"
- // }[namespace]
- // });
- // locales.init({
- // nodes: {
- // getNodeList: function(opts) {
- // return Promise.resolve([
- // {module:"node-red",id:"node-red-id"},
- // {module:"test-module-a",id:"test-module-a-id"},
- // {module:"test-module-b",id:"test-module-b-id"}
- // ]);
- // }
- // }
- // });
- // app = express();
- // app.get("/locales/nodes",locales.getAllNodes);
- // });
- // after(function() {
- // i18n.catalog.restore();
- // })
- // it('returns with the node catalogs', function(done) {
- // request(app)
- // .get("/locales/nodes")
- // .expect(200)
- // .end(function(err,res) {
- // if (err) {
- // return done(err);
- // }
- // res.body.should.eql({
- // 'test-module-a-id': 'test-module-a-catalog',
- // 'test-module-b-id': 'test-module-b-catalog'
- // });
- // done();
- // });
- // });
- // });
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/projects_spec.js b/test/unit/@node-red/editor-api/lib/editor/projects_spec.js
deleted file mode 100644
index 52b88d0b8..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/projects_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-describe("api/editor/projects", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/settings_spec.js b/test/unit/@node-red/editor-api/lib/editor/settings_spec.js
deleted file mode 100644
index 171dca564..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/settings_spec.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var request = require('supertest');
-var express = require('express');
-var bodyParser = require("body-parser");
-var sinon = require('sinon');
-
-var app;
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var info = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/settings");
-var theme = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme");
-
-describe("api/editor/settings", function() {
- before(function() {
- sinon.stub(theme,"settings").callsFake(function() { return { existing: 123, test: 456 };});
- app = express();
- app.use(bodyParser.json());
- app.get("/settings/user",function(req,res,next) {req.user = "fred"; next()}, info.userSettings);
- app.post("/settings/user",function(req,res,next) {req.user = "fred"; next()},info.updateUserSettings);
- });
-
- after(function() {
- theme.settings.restore();
- });
-
- it('returns the user settings', function(done) {
- info.init({
- settings: {
- getUserSettings: function(opts) {
- if (opts.user !== "fred") {
- return Promise.reject(new Error("Unknown user"));
- }
- return Promise.resolve({
- c:3,
- d:4
- })
- }
- }
- });
- request(app)
- .get("/settings/user")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.eql({c:3,d:4});
- done();
- });
- });
- it('updates the user settings', function(done) {
- var update;
- info.init({
- settings: {
- updateUserSettings: function(opts) {
- if (opts.user !== "fred") {
- return Promise.reject(new Error("Unknown user"));
- }
- update = opts.settings;
- return Promise.resolve()
- }
- }
- });
- request(app)
- .post("/settings/user")
- .send({
- e:4,
- f:5
- })
- .expect(204)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- update.should.eql({e:4,f:5});
- done();
- });
- });
-
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/sshkeys_spec.js b/test/unit/@node-red/editor-api/lib/editor/sshkeys_spec.js
deleted file mode 100644
index 1647cd99d..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/sshkeys_spec.js
+++ /dev/null
@@ -1,333 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var request = require("supertest");
-var express = require("express");
-var NR_TEST_UTILS = require("nr-test-utils");
-var sshkeys = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/sshkeys");
-var bodyParser = require("body-parser");
-
-
-describe("api/editor/sshkeys", function() {
- var app;
- var mockRuntime = {
- settings: {
- getUserKeys: function() {},
- getUserKey: function() {},
- generateUserKey: function() {},
- removeUserKey: function() {}
- }
- }
- before(function() {
- sshkeys.init(mockRuntime);
- app = express();
- app.use(bodyParser.json());
- app.use("/settings/user/keys", sshkeys.app());
- });
-
- beforeEach(function() {
- sinon.stub(mockRuntime.settings, "getUserKeys");
- sinon.stub(mockRuntime.settings, "getUserKey");
- sinon.stub(mockRuntime.settings, "generateUserKey");
- sinon.stub(mockRuntime.settings, "removeUserKey");
- })
- afterEach(function() {
- mockRuntime.settings.getUserKeys.restore();
- mockRuntime.settings.getUserKey.restore();
- mockRuntime.settings.generateUserKey.restore();
- mockRuntime.settings.removeUserKey.restore();
- })
-
- it('GET /settings/user/keys --- return empty list', function(done) {
- mockRuntime.settings.getUserKeys.returns(Promise.resolve([]));
- request(app)
- .get("/settings/user/keys")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('keys');
- res.body.keys.should.be.empty();
- done();
- });
- });
-
- it('GET /settings/user/keys --- return normal list', function(done) {
- var fileList = [
- 'test_key01',
- 'test_key02'
- ];
- var retList = fileList.map(function(elem) {
- return {
- name: elem
- };
- });
- mockRuntime.settings.getUserKeys.returns(Promise.resolve(retList));
- request(app)
- .get("/settings/user/keys")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('keys');
- for (var item of retList) {
- res.body.keys.should.containEql(item);
- }
- done();
- });
- });
-
- it('GET /settings/user/keys --- return Error', function(done) {
- var errInstance = new Error("Messages here.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.getUserKeys.returns(p);
- request(app)
- .get("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal(errInstance.code);
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return 404', function(done) {
- var errInstance = new Error("Not Found.");
- errInstance.code = "not_found";
- errInstance.status = 404;
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.getUserKey.returns(p);
- request(app)
- .get("/settings/user/keys/NOT_REAL")
- .expect(404)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- done();
- });
- });
- it('GET /settings/user/keys --- return Unexpected Error', function(done) {
- var errInstance = new Error();
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.getUserKeys.returns(p)
- request(app)
- .get("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return content', function(done) {
- var key_file_name = "test_key";
- var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
- mockRuntime.settings.getUserKey.returns(Promise.resolve(fileContent));
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- mockRuntime.settings.getUserKey.called.should.be.true();
- mockRuntime.settings.getUserKey.firstCall.args[0].should.eql({ user: undefined, id: 'test_key' });
- res.body.should.be.deepEqual({ publickey: fileContent });
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.getUserKey.returns(p);
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal(errInstance.code);
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return Unexpected Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.getUserKey.returns(p);
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal("Messages.....");
- done();
- });
- });
-
- it('POST /settings/user/keys --- success', function(done) {
- var key_file_name = "test_key";
- mockRuntime.settings.generateUserKey.returns(Promise.resolve(key_file_name));
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- done();
- });
- });
-
- it('POST /settings/user/keys --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.generateUserKey.returns(p);
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal("test_code");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('POST /settings/user/keys --- return Unexpected error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.generateUserKey.returns(p);
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal("Messages.....");
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- success', function(done) {
- var key_file_name = "test_key";
- mockRuntime.settings.removeUserKey.returns(Promise.resolve(true));
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(204)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.be.deepEqual({});
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.removeUserKey.returns(p);
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal("test_code");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- return Unexpected Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.settings.removeUserKey.returns(p);
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('code');
- res.body.code.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal('Messages.....');
- done();
- });
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/theme_spec.js b/test/unit/@node-red/editor-api/lib/editor/theme_spec.js
deleted file mode 100644
index 900be126f..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/theme_spec.js
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var request = require("supertest");
-var express = require('express');
-var sinon = require('sinon');
-var fs = require("fs");
-
-var app = express();
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var theme = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme");
-
-describe("api/editor/theme", function () {
- beforeEach(function () {
- sinon.stub(fs, "statSync").callsFake(function () { return true; });
- });
- afterEach(function () {
- theme.init({settings: {}});
- fs.statSync.restore();
- });
- it("applies the default theme", async function () {
- var result = theme.init({});
- should.not.exist(result);
-
- var context = await theme.context();
- context.should.have.a.property("page");
- context.page.should.have.a.property("title", "Node-RED");
- context.page.should.have.a.property("favicon", "favicon.ico");
- context.page.should.have.a.property("tabicon");
- context.page.tabicon.should.have.a.property("icon", "red/images/node-red-icon-black.svg");
- context.page.tabicon.should.have.a.property("colour", "#8f0000");
- context.should.have.a.property("header");
- context.header.should.have.a.property("title", "Node-RED");
- context.header.should.have.a.property("image", "red/images/node-red.svg");
- context.should.have.a.property("asset");
- context.asset.should.have.a.property("red", "red/red.min.js");
- context.asset.should.have.a.property("main", "red/main.min.js");
- context.asset.should.have.a.property("vendorMonaco", "");
-
- should.not.exist(theme.settings());
- });
-
- it("uses non-minified js files when in dev mode", async function () {
- const previousEnv = process.env.NODE_ENV;
- try {
- process.env.NODE_ENV = 'development'
- theme.init({});
- var context = await theme.context();
- context.asset.should.have.a.property("red", "red/red.js");
- context.asset.should.have.a.property("main", "red/main.js");
- } finally {
- process.env.NODE_ENV = previousEnv;
- }
- });
-
- it("Adds monaco bootstrap when enabled", async function () {
- theme.init({
- editorTheme: {
- codeEditor: {
- lib: 'monaco'
- }
- }
- });
- var context = await theme.context();
- context.asset.should.have.a.property("vendorMonaco", "vendor/monaco/monaco-bootstrap.js");
- });
-
- it("picks up custom theme", async function () {
- theme.init({
- editorTheme: {
- page: {
- title: "Test Page Title",
- favicon: "/absolute/path/to/theme/favicon",
- tabicon: {
- icon: "/absolute/path/to/theme/tabicon",
- colour: "#8f008f"
- },
- css: [
- "/absolute/path/to/custom/css/file.css"
- ],
- scripts: "/absolute/path/to/script.js"
- },
- header: {
- title: "Test Header Title",
- url: "http://nodered.org",
- image: "/absolute/path/to/header/image" // or null to remove image
- },
-
- deployButton: {
- type: "simple",
- label: "Save",
- icon: "/absolute/path/to/deploy/button/image" // or null to remove image
- },
-
- menu: { // Hide unwanted menu items by id. see editor/js/main.js:loadEditor for complete list
- "menu-item-import-library": false,
- "menu-item-export-library": false,
- "menu-item-keyboard-shortcuts": false,
- "menu-item-help": {
- label: "Alternative Help Link Text",
- url: "http://example.com"
- }
- },
-
- userMenu: false, // Hide the user-menu even if adminAuth is enabled
-
- login: {
- image: "/absolute/path/to/login/page/big/image" // a 256x256 image
- },
-
- palette: {
- editable: true,
- catalogues: ['https://catalogue.nodered.org/catalogue.json'],
- theme: [{ category: ".*", type: ".*", color: "#f0f" }]
- },
-
- projects: {
- enabled: false
- }
- }
- });
-
- theme.app();
-
- var context = await theme.context();
- context.should.have.a.property("page");
- context.page.should.have.a.property("title", "Test Page Title");
- context.page.should.have.a.property("favicon", "theme/favicon/favicon");
- context.page.should.have.a.property("tabicon")
- context.page.tabicon.should.have.a.property("icon", "theme/tabicon/tabicon");
- context.page.tabicon.should.have.a.property("colour", "#8f008f")
- context.should.have.a.property("header");
- context.header.should.have.a.property("title", "Test Header Title");
- context.header.should.have.a.property("url", "http://nodered.org");
- context.header.should.have.a.property("image", "theme/header/image");
- context.page.should.have.a.property("css");
- context.page.css.should.have.lengthOf(1);
- context.page.css[0].should.eql('theme/css/file.css');
- context.page.should.have.a.property("scripts");
- context.page.scripts.should.have.lengthOf(1);
- context.page.scripts[0].should.eql('theme/scripts/script.js');
- context.should.have.a.property("login");
- context.login.should.have.a.property("image", "theme/login/image");
-
- var settings = theme.settings();
- settings.should.have.a.property("deployButton");
- settings.deployButton.should.have.a.property("type", "simple");
- settings.deployButton.should.have.a.property("label", "Save");
- settings.deployButton.should.have.a.property("icon", "theme/deploy/image");
- settings.should.have.a.property("userMenu");
- settings.userMenu.should.be.eql(false);
- settings.should.have.a.property("menu");
- settings.menu.should.have.a.property("menu-item-import-library", false);
- settings.menu.should.have.a.property("menu-item-export-library", false);
- settings.menu.should.have.a.property("menu-item-keyboard-shortcuts", false);
- settings.menu.should.have.a.property("menu-item-help", { label: "Alternative Help Link Text", url: "http://example.com" });
- settings.should.have.a.property("palette");
- settings.palette.should.have.a.property("editable", true);
- settings.palette.should.have.a.property("catalogues", ['https://catalogue.nodered.org/catalogue.json']);
- settings.palette.should.have.a.property("theme", [{ category: ".*", type: ".*", color: "#f0f" }]);
- settings.should.have.a.property("projects");
- settings.projects.should.have.a.property("enabled", false);
- });
-
- it("picks up backwards compatible tabicon setting", async function () {
- theme.init({
- editorTheme: {
- page: {
- tabicon: "/absolute/path/to/theme/tabicon",
- }
- }
- });
-
- theme.app();
-
- var context = await theme.context();
- context.should.have.a.property("page");
- context.page.should.have.a.property("tabicon");
- context.page.tabicon.should.have.a.property("icon", "theme/tabicon/tabicon");
- // The colour property should remain as default in this case as the
- // legacy format for defining tabicon doesn't allow specifying a colour
- context.page.tabicon.should.have.a.property("colour", "#8f0000");
-
- });
-
- it("test explicit userMenu set to true in theme setting", function () {
- theme.init({
- editorTheme: {
- userMenu: true,
- }
- });
-
- theme.app();
-
- var settings = theme.settings();
- settings.should.have.a.property("userMenu");
- settings.userMenu.should.be.eql(true);
-
- });
-
-
- it("includes list of plugin themes", function(done) {
- theme.init({},{
- plugins: { getPluginsByType: _ => [{id:"theme-plugin"}] }
- });
- const app = theme.app();
- request(app)
- .get("/")
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- try {
- const response = JSON.parse(res.text);
- response.should.have.property("themes");
- response.themes.should.eql(["theme-plugin"])
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it("includes theme plugin settings", async function () {
- theme.init({
- editorTheme: {
- theme: 'test-theme'
- }
- },{
- plugins: { getPlugin: t => {
- return ({'test-theme':{
- path: '/abosolute/path/to/plugin',
- css: [
- "path/to/custom/css/file1.css",
- "/invalid/path/to/file2.css",
- "../another/invalid/path/file3.css"
- ],
- scripts: [
- "path/to/custom/js/file1.js",
- "/invalid/path/to/file2.js",
- "../another/invalid/path/file3.js"
- ]
- }})[t.id];
- } }
- });
-
- theme.app();
-
- var context = await theme.context();
- context.should.have.a.property("page");
- context.page.should.have.a.property("css");
- context.page.css.should.have.lengthOf(1);
- context.page.css[0].should.eql('theme/css/file1.css');
- context.page.should.have.a.property("scripts");
- context.page.scripts.should.have.lengthOf(1);
- context.page.scripts[0].should.eql('theme/scripts/file1.js');
-
- });
-});
diff --git a/test/unit/@node-red/editor-api/lib/editor/ui_spec.js b/test/unit/@node-red/editor-api/lib/editor/ui_spec.js
deleted file mode 100644
index 0380adcde..000000000
--- a/test/unit/@node-red/editor-api/lib/editor/ui_spec.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var request = require("supertest");
-var express = require("express");
-var fs = require("fs");
-var path = require("path");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var ui = NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/ui");
-
-
-describe("api/editor/ui", function() {
- var app;
-
- before(function() {
- ui.init({
- nodes: {
- getIcon: function(opts) {
- return new Promise(function(resolve,reject) {
- if (opts.icon === "icon.png") {
- fs.readFile(NR_TEST_UTILS.resolve("@node-red/editor-client/src/images/icons/arrow-in.svg"), function(err,data) {
- resolve(data);
- })
- } else {
- resolve(null);
- }
- });
- },
- getModuleResource: async function(opts) {
- if (opts.module !== "test-module" || opts.path !== "a/path/text.txt") {
- return null;
- } else {
- return "Some text data";
- }
- }
- }
- });
- });
- describe("slash handler", function() {
- before(function() {
- app = express();
- app.get("/foo",ui.ensureSlash,function(req,res) { res.sendStatus(200);});
- });
- it('redirects if the path does not end in a slash',function(done) {
- request(app)
- .get('/foo')
- .expect(301,done);
- });
- it('redirects if the path, with query string, does not end in a slash',function(done) {
- request(app)
- .get('/foo?abc=def')
- .expect(301)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.header['location'].should.equal("/foo/?abc=def");
- done();
- });
- });
-
- it('does not redirect if the path ends in a slash',function(done) {
- request(app)
- .get('/foo/')
- .expect(200,done);
- });
- });
-
- describe("icon handler", function() {
- before(function() {
- app = express();
- app.get("/icons/:module/:icon",ui.icon);
- });
-
- function binaryParser(res, callback) {
- res.setEncoding('binary');
- res.data = '';
- res.on('data', function (chunk) {
- res.data += chunk;
- });
- res.on('end', function () {
- callback(null, Buffer.from(res.data, 'binary'));
- });
- }
- function compareBuffers(b1,b2) {
- b1.length.should.equal(b2.length);
- for (var i=0;i layer.name === 'testMiddleware')
- should(middlewareFound).be.empty();
- done();
- });
-
- it('only accepts functions as middleware',function(done) {
- const testMiddleware = function(req, res, next){ next(); };
- api.init({ httpAdminRoot: true, httpAdminMiddleware: testMiddleware },{},{},{});
- const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'testMiddleware')
- should(middlewareFound).be.length(1);
- done();
- });
- });
-
- describe('initialises api with authentication enabled', function(done) {
-
- it('enables an oauth/openID based authentication mechanism',function(done) {
- const stub = sinon.stub(apiAuth, 'genericStrategy').callsFake(function(){});
- const adminAuth = { type: 'strategy', strategy: {} }
- api.init({ httpAdminRoot: true, adminAuth },{},{},{});
- should(stub.called).be.ok();
- stub.restore();
- done();
- });
-
- it('enables password protection',function(done) {
- const adminAuth = { type: 'credentials' }
- api.init({ httpAdminRoot: true, adminAuth },{},{},{});
-
- // is the name ("initialize") of the passport middleware present
- const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'initialize')
- should(middlewareFound).be.length(1);
- done();
- });
-
- });
-
- describe('initialises api with custom cors config', function (done) {
- const httpAdminCors = {
- origin: "*",
- methods: "GET,PUT,POST,DELETE"
- };
-
- it('uses default cors middleware when user settings absent', function(done){
- api.init({ httpAdminRoot: true }, {}, {}, {});
- const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'corsMiddleware')
- should(middlewareFound).be.length(1);
- done();
- })
-
- it('enables custom cors middleware when settings present', function(done){
- api.init({ httpAdminRoot: true, httpAdminCors }, {}, {}, {});
- const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'corsMiddleware')
- should(middlewareFound).be.length(2);
- done();
- })
- });
-
- describe('editor start', function (done) {
-
- it('cannot be started when editor is disabled', function (done) {
- const stub = sinon.stub(apiEditor, 'start').callsFake(function () {
- return Promise.resolve(true);
- });
- api.init({ httpAdminRoot: true, disableEditor: true }, {}, {}, {});
- should(api.start()).resolvedWith(true);
- stub.restore();
- done();
- });
-
- it('can be started when editor enabled', function (done) {
- const stub = sinon.stub(apiEditor, 'start');
- api.init({ httpAdminRoot: true, disableEditor: false }, {}, {}, {});
- api.start();
- should(stub.called).be.true();
- stub.restore();
- done();
- });
-
- });
-
-});
diff --git a/test/unit/@node-red/editor-api/lib/util_spec.js b/test/unit/@node-red/editor-api/lib/util_spec.js
deleted file mode 100644
index 26cd76be8..000000000
--- a/test/unit/@node-red/editor-api/lib/util_spec.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var request = require('supertest');
-var express = require('express');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var apiUtil = NR_TEST_UTILS.require("@node-red/editor-api/lib/util");
-
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-describe("api/util", function() {
- describe("errorHandler", function() {
- var loggedError = null;
- var loggedEvent = null;
- var app;
- before(function() {
- app = express();
- sinon.stub(log,'error').callsFake(function(msg) {loggedError = msg;});
- sinon.stub(log,'audit').callsFake(function(event) {loggedEvent = event;});
- app.get("/tooLarge", function(req,res) {
- var err = new Error();
- err.message = "request entity too large";
- throw err;
- },apiUtil.errorHandler)
- app.get("/stack", function(req,res) {
- var err = new Error();
- err.message = "stacktrace";
- throw err;
- },apiUtil.errorHandler)
- });
- after(function() {
- log.error.restore();
- log.audit.restore();
- })
- beforeEach(function() {
- loggedError = null;
- loggedEvent = null;
- })
- it("logs an error for request entity too large", function(done) {
- request(app).get("/tooLarge").expect(400).end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property("error","unexpected_error");
- res.body.should.have.property("message","Error: request entity too large");
-
- loggedError.should.have.property("message","request entity too large");
-
- loggedEvent.should.have.property("event","api.error");
- loggedEvent.should.have.property("error","unexpected_error");
- loggedEvent.should.have.property("message","Error: request entity too large");
- done();
- });
- })
- it("logs an error plus stack for other errors", function(done) {
- request(app).get("/stack").expect(400).end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property("error","unexpected_error");
- res.body.should.have.property("message","Error: stacktrace");
-
- /Error: stacktrace\s*at.*util_spec.js/m.test(loggedError).should.be.true();
-
- loggedEvent.should.have.property("event","api.error");
- loggedEvent.should.have.property("error","unexpected_error");
- loggedEvent.should.have.property("message","Error: stacktrace");
-
-
-
- done();
- });
- });
- })
-
- describe('determineLangFromHeaders', function() {
- var oldDefaultLang;
- before(function() {
- oldDefaultLang = i18n.defaultLang;
- i18n.defaultLang = "en-US";
- })
- after(function() {
- i18n.defaultLang = oldDefaultLang;
- })
- it('returns the default lang if non provided', function() {
- apiUtil.determineLangFromHeaders(null).should.eql("en-US");
- })
- it('returns the first language accepted', function() {
- apiUtil.determineLangFromHeaders(['fr-FR','en-GB']).should.eql("fr-FR");
- })
- })
-});
diff --git a/test/unit/@node-red/registry/lib/deprecated_spec.js b/test/unit/@node-red/registry/lib/deprecated_spec.js
deleted file mode 100644
index b9c35dd31..000000000
--- a/test/unit/@node-red/registry/lib/deprecated_spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var deprecated = NR_TEST_UTILS.require("@node-red/registry/lib/deprecated.js");
-
-describe('deprecated', function() {
- it('should return info on a node',function() {
- deprecated.get("irc in").should.eql({module:"node-red-node-irc"});
- });
- it('should return null for non-deprecated node',function() {
- should.not.exist(deprecated.get("foo"));
- });
-});
diff --git a/test/unit/@node-red/registry/lib/externalModules_spec.js b/test/unit/@node-red/registry/lib/externalModules_spec.js
deleted file mode 100644
index 2158f93f7..000000000
--- a/test/unit/@node-red/registry/lib/externalModules_spec.js
+++ /dev/null
@@ -1,371 +0,0 @@
- // init: init,
- // register: register,
- // registerSubflow: registerSubflow,
- // checkFlowDependencies: checkFlowDependencies,
- // require: requireModule
- //
-
-const should = require("should");
-const sinon = require("sinon");
-const fs = require("fs-extra");
-const path = require("path");
-const os = require("os");
-
-const NR_TEST_UTILS = require("nr-test-utils");
-const externalModules = NR_TEST_UTILS.require("@node-red/registry/lib/externalModules");
-const exec = NR_TEST_UTILS.require("@node-red/util/lib/exec");
-const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
-
-let homeDir;
-
-async function createUserDir() {
- if (!homeDir) {
- homeDir = path.join(os.tmpdir(),"nr-test-"+Math.floor(Math.random()*100000));
- }
- await fs.ensureDir(homeDir);
-}
-
-async function setupExternalModulesPackage(dependencies) {
- await fs.writeFile(path.join(homeDir,"package.json"),`{
-"name": "Node-RED-External-Modules",
-"description": "These modules are automatically installed by Node-RED to use in Function nodes.",
-"version": "1.0.0",
-"private": true,
-"dependencies": ${JSON.stringify(dependencies)}
-}`)
-}
-
-describe("externalModules api", function() {
- beforeEach(async function() {
- await createUserDir()
- })
- afterEach(async function() {
- hooks.clear();
- await fs.remove(homeDir);
- })
- describe("checkFlowDependencies", function() {
- beforeEach(function() {
- sinon.stub(exec,"run").callsFake(async function(cmd, args, options) {
- let error;
- let moduleName = args[args.length-1];
- if (moduleName === "moduleNotFound") {
- error = new Error();
- error.stderr = "E404";
- } else if (moduleName === "moduleVersionNotFound") {
- error = new Error();
- error.stderr = "ETARGET";
- } else if (moduleName === "moduleFail") {
- error = new Error();
- error.stderr = "Some unexpected install error";
- }
- if (error) {
- throw error;
- }
- })
- })
- afterEach(function() {
- exec.run.restore();
- })
- it("does nothing when no types are registered",async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "foo"}]}
- ])
- exec.run.called.should.be.false();
- });
-
- it("skips install for modules already installed", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- await setupExternalModulesPackage({"foo": "1.2.3", "bar":"2.3.4"});
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "foo"}]}
- ])
- exec.run.called.should.be.false();
- })
-
- it("skips install for built-in modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "fs"}]}
- ])
- exec.run.called.should.be.false();
- })
-
- it("installs missing modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "foo"}]}
- ])
- exec.run.called.should.be.true();
- })
-
-
- it("calls pre/postInstall hooks", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- let receivedPreEvent,receivedPostEvent;
- hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
- hooks.add("postInstall", function(event) { receivedPostEvent = event; })
-
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "foo"}]}
- ])
- exec.run.called.should.be.true();
- // exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'foo' ]);
- receivedPreEvent.should.have.property("module","foo")
- receivedPreEvent.should.have.property("version")
- receivedPreEvent.should.have.property("dir")
- receivedPreEvent.should.eql(receivedPostEvent)
- })
-
- it("skips npm install if preInstall returns false", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- let receivedPreEvent,receivedPostEvent;
- hooks.add("preInstall", function(event) { receivedPreEvent = event; return false })
- hooks.add("postInstall", function(event) { receivedPostEvent = event; })
-
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "foo"}]}
- ])
- exec.run.called.should.be.false();
- receivedPreEvent.should.have.property("module","foo")
- receivedPreEvent.should.have.property("version")
- receivedPreEvent.should.have.property("dir")
- receivedPreEvent.should.eql(receivedPostEvent)
- })
-
-
- it("installs missing modules from inside subflow module", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- externalModules.registerSubflow("sf", {"flow":[{type: "function", libs:[{module: "foo"}]}]});
- await externalModules.checkFlowDependencies([
- {type: "sf"}
- ])
- exec.run.called.should.be.true();
- })
-
- it("reports install fail - 404", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- try {
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "moduleNotFound"}]}
- ])
- throw new Error("checkFlowDependencies did not reject after install fail")
- } catch(err) {
- exec.run.called.should.be.true();
- Array.isArray(err).should.be.true();
- err.should.have.length(1);
- err[0].should.have.property("module");
- err[0].module.should.have.property("module","moduleNotFound");
- err[0].should.have.property("error");
- err[0].error.should.have.property("code",404);
-
- }
- })
- it("reports install fail - target", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- try {
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "moduleVersionNotFound"}]}
- ])
- throw new Error("checkFlowDependencies did not reject after install fail")
- } catch(err) {
- exec.run.called.should.be.true();
- Array.isArray(err).should.be.true();
- err.should.have.length(1);
- err[0].should.have.property("module");
- err[0].module.should.have.property("module","moduleVersionNotFound");
- err[0].should.have.property("error");
- err[0].error.should.have.property("code",404);
- }
- })
-
- it("reports install fail - unexpected", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- try {
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "moduleFail"}]}
- ])
- throw new Error("checkFlowDependencies did not reject after install fail")
- } catch(err) {
- exec.run.called.should.be.true();
- Array.isArray(err).should.be.true();
- err.should.have.length(1);
- err[0].should.have.property("module");
- err[0].module.should.have.property("module","moduleFail");
- err[0].should.have.property("error");
- err[0].error.should.have.property("code","unexpected_error");
- }
- })
- it("reports install fail - multiple", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- externalModules.register("function", "libs");
- try {
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "moduleNotFound"},{module: "moduleFail"}]}
- ])
- throw new Error("checkFlowDependencies did not reject after install fail")
- } catch(err) {
- exec.run.called.should.be.true();
- Array.isArray(err).should.be.true();
- err.should.have.length(2);
- // Sort the array so we know the order to test for
- err.sort(function(A,B) {
- return A.module.module.localeCompare(B.module.module);
- })
- err[1].should.have.property("module");
- err[1].module.should.have.property("module","moduleNotFound");
- err[1].should.have.property("error");
- err[1].error.should.have.property("code",404);
- err[0].should.have.property("module");
- err[0].module.should.have.property("module","moduleFail");
- err[0].should.have.property("error");
- err[0].error.should.have.property("code","unexpected_error");
-
- }
- })
- it("reports install fail - install disabled", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
- modules: {
- allowInstall: false
- }
- }});
- externalModules.register("function", "libs");
- try {
- await externalModules.checkFlowDependencies([
- {type: "function", libs:[{module: "foo"}]}
- ])
- throw new Error("checkFlowDependencies did not reject after install fail")
- } catch(err) {
- // Should not try to install
- exec.run.called.should.be.false();
- Array.isArray(err).should.be.true();
- err.should.have.length(1);
- err[0].should.have.property("module");
- err[0].module.should.have.property("module","foo");
- err[0].should.have.property("error");
- err[0].error.should.have.property("code","install_not_allowed");
- }
- })
-
- it("reports install fail - module disallowed", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
- modules: {
- denyList: ['foo']
- }
- }});
- externalModules.register("function", "libs");
- try {
- await externalModules.checkFlowDependencies([
- // foo disallowed
- // bar allowed
- {type: "function", libs:[{module: "foo"},{module: "bar"}]}
- ])
- throw new Error("checkFlowDependencies did not reject after install fail")
- } catch(err) {
- exec.run.calledOnce.should.be.true();
- Array.isArray(err).should.be.true();
- err.should.have.length(1);
- err[0].should.have.property("module");
- err[0].module.should.have.property("module","foo");
- err[0].should.have.property("error");
- err[0].error.should.have.property("code","install_not_allowed");
- }
- })
-
- it("reports install fail - built-in module disallowed", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
- modules: {
- denyList: ['fs']
- }
- }});
- externalModules.register("function", "libs");
- try {
- await externalModules.checkFlowDependencies([
- // foo disallowed
- // bar allowed
- {type: "function", libs:[{module: "fs"},{module: "bar"}]}
- ])
- throw new Error("checkFlowDependencies did not reject after install fail")
- } catch(err) {
- exec.run.calledOnce.should.be.true();
- Array.isArray(err).should.be.true();
- err.should.have.length(1);
- err[0].should.have.property("module");
- err[0].module.should.have.property("module","fs");
- err[0].should.have.property("error");
- err[0].error.should.have.property("code","module_not_allowed");
- }
- })
- })
- describe("require", async function() {
- it("requires built-in modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- const result = externalModules.require("fs")
- result.should.eql(require("fs"));
- })
- it("rejects unknown modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- try {
- externalModules.require("foo")
- throw new Error("require did not reject after fail")
- } catch(err) {
- err.should.have.property("code","module_not_allowed");
- }
- })
-
- it("rejects disallowed modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
- modules: {
- denyList: ['fs']
- }
- }});
- try {
- externalModules.require("fs")
- throw new Error("require did not reject after fail")
- } catch(err) {
- err.should.have.property("code","module_not_allowed");
- }
- })
- })
- describe("import", async function() {
- it("import built-in modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- const result = await externalModules.import("fs")
- // `result` won't have the `should` property
- should.exist(result);
- should.exist(result.existsSync);
- })
- it("rejects unknown modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}});
- try {
- await externalModules.import("foo")
- throw new Error("import did not reject after fail")
- } catch(err) {
- err.should.have.property("code","module_not_allowed");
- }
- })
-
- it("rejects disallowed modules", async function() {
- externalModules.init({userDir: homeDir, get:()=>{}, set:()=>{}, externalModules: {
- modules: {
- denyList: ['fs']
- }
- }});
- try {
- await externalModules.import("fs")
- throw new Error("import did not reject after fail")
- } catch(err) {
- err.should.have.property("code","module_not_allowed");
- }
- })
- })
-});
diff --git a/test/unit/@node-red/registry/lib/index_spec.js b/test/unit/@node-red/registry/lib/index_spec.js
deleted file mode 100644
index db0629225..000000000
--- a/test/unit/@node-red/registry/lib/index_spec.js
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
-* Copyright JS Foundation and other contributors, http://js.foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**/
-
-var should = require("should");
-var sinon = require("sinon");
-var path = require("path");
-var fs = require("fs");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var registry = NR_TEST_UTILS.require("@node-red/registry");
-
-var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
-var loader = NR_TEST_UTILS.require("@node-red/registry/lib/loader");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
-
-describe('red/registry/index', function() {
- var stubs = [];
- afterEach(function() {
- while(stubs.length) {
- stubs.pop().restore();
- }
- })
- describe('#init',function() {
- it('intialises components', function() {
- stubs.push(sinon.stub(installer,"init"));
- stubs.push(sinon.stub(loader,"init"));
- stubs.push(sinon.stub(typeRegistry,"init"));
-
- registry.init({settings:{}});
- installer.init.called.should.be.true();
- loader.init.called.should.be.true();
- typeRegistry.init.called.should.be.true();
- })
- });
-
- describe('#addModule', function() {
- it('loads the module and returns its info', function(done) {
- stubs.push(sinon.stub(loader,"addModule").callsFake(function(module) {
- return Promise.resolve();
- }));
- stubs.push(sinon.stub(typeRegistry,"getModuleInfo").callsFake(function(module) {
- return "info";
- }));
- registry.addModule("foo").then(function(info) {
- info.should.eql("info");
- done();
- }).catch(function(err) { done(err); });
- });
- it('rejects if loader rejects', function(done) {
- stubs.push(sinon.stub(loader,"addModule").callsFake(function(module) {
- return Promise.reject("error");
- }));
- stubs.push(sinon.stub(typeRegistry,"getModuleInfo").callsFake(function(module) {
- return "info";
- }));
- registry.addModule("foo").then(function(info) {
- done(new Error("unexpected resolve"));
- }).catch(function(err) {
- err.should.eql("error");
- done();
- })
- });
- });
-
- describe('#enableNode',function() {
- it('enables a node set',function(done) {
- stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
- return Promise.resolve();
- }));
- stubs.push(sinon.stub(typeRegistry,"getNodeInfo").callsFake(function() {
- return {id:"node-set",loaded:true};
- }));
- registry.enableNode("node-set").then(function(ns) {
- typeRegistry.enableNodeSet.called.should.be.true();
- ns.should.have.a.property('id','node-set');
- done();
- }).catch(function(err) { done(err); });
- });
-
- it('rejects if node unknown',function() {
- stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
- throw new Error('failure');
- }));
- /*jshint immed: false */
- (function(){
- registry.enableNode("node-set")
- }).should.throw();
- });
-
- it('triggers a node load',function(done) {
- stubs.push(sinon.stub(typeRegistry,"enableNodeSet").callsFake(function() {
- return Promise.resolve();
- }));
- var calls = 0;
- stubs.push(sinon.stub(typeRegistry,"getNodeInfo").callsFake(function() {
- // loaded=false on first call, true on subsequent
- return {id:"node-set",loaded:(calls++>0)};
- }));
- stubs.push(sinon.stub(loader,"loadNodeSet").callsFake(function(){return Promise.resolve();}));
- stubs.push(sinon.stub(typeRegistry,"getFullNodeInfo"));
-
- registry.enableNode("node-set").then(function(ns) {
- typeRegistry.enableNodeSet.called.should.be.true();
- loader.loadNodeSet.called.should.be.true();
- ns.should.have.a.property('id','node-set');
- ns.should.have.a.property('loaded',true);
- done();
- }).catch(function(err) { done(err); });
- });
-
- });
-
-});
diff --git a/test/unit/@node-red/registry/lib/installer_spec.js b/test/unit/@node-red/registry/lib/installer_spec.js
deleted file mode 100644
index 80b96ecfb..000000000
--- a/test/unit/@node-red/registry/lib/installer_spec.js
+++ /dev/null
@@ -1,528 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var path = require("path");
-var fs = require('fs-extra');
-var EventEmitter = require('events');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var installer = NR_TEST_UTILS.require("@node-red/registry/lib/installer");
-var registry = NR_TEST_UTILS.require("@node-red/registry/lib/index");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
-const { events, exec, log, hooks } = NR_TEST_UTILS.require("@node-red/util");
-
-describe('nodes/registry/installer', function() {
-
- var mockLog = {
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- _: function(msg) { return msg }
- }
-
- var execResponse;
-
- beforeEach(function() {
- sinon.stub(exec,"run").callsFake(() => execResponse || Promise.resolve(""))
- installer.init({})
- });
-
- afterEach(function() {
- execResponse = null;
- if (registry.addModule.restore) {
- registry.addModule.restore();
- }
- if (registry.removeModule.restore) {
- registry.removeModule.restore();
- }
- if (typeRegistry.removeModule.restore) {
- typeRegistry.removeModule.restore();
- }
- if (registry.getModuleInfo.restore) {
- registry.getModuleInfo.restore();
- }
- if (typeRegistry.getModuleInfo.restore) {
- typeRegistry.getModuleInfo.restore();
- }
- if (typeRegistry.setModulePendingUpdated.restore) {
- typeRegistry.setModulePendingUpdated.restore();
- }
- if (fs.statSync.restore) {
- fs.statSync.restore();
- }
- exec.run.restore();
- hooks.clear();
- });
-
- describe("installs module", function() {
- it("rejects module name that includes version", function(done) {
- installer.installModule("module@version",null,null).catch(function(err) {
- err.code.should.be.eql('invalid_module_name');
- done();
- }).catch(done);
- });
- it("rejects missing module name", function(done) {
- installer.installModule("",null,null).catch(function(err) {
- err.code.should.be.eql('invalid_module_name');
- done();
- }).catch(done);
- });
- it("rejects null module name", function(done) {
- installer.installModule(null,null,null).catch(function(err) {
- err.code.should.be.eql('invalid_module_name');
- done();
- }).catch(done);
- });
- it("rejects invalid url", function(done) {
- installer.installModule("module",null,"abc").catch(function(err) {
- err.code.should.be.eql('invalid_module_url');
- done();
- });
- });
- it("rejects when npm returns a 404", function(done) {
- var res = {
- code: 1,
- stdout:"",
- stderr:" 404 this_wont_exist"
- }
- var p = Promise.reject(res);
- p.catch((err)=>{});
- execResponse = p;
- installer.installModule("this_wont_exist").catch(function(err) {
- err.should.have.property("code",404);
- done();
- }).catch(done);
- });
- it("rejects when npm does not find specified version", function(done) {
- var res = {
- code: 1,
- stdout:"",
- stderr:" version not found: this_wont_exist@0.1.2"
- }
- var p = Promise.reject(res);
- p.catch((err)=>{});
- execResponse = p;
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- version: "0.1.1"
- }
- });
- installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
- err.code.should.be.eql(404);
- done();
- }).catch(done);
- });
- it("rejects when update requested to existing version", function(done) {
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- user: true,
- version: "0.1.1"
- }
- });
- installer.installModule("this_wont_exist","0.1.1").catch(function(err) {
- err.code.should.be.eql('module_already_loaded');
- done();
- }).catch(done);
- });
- it("rejects when update requested to existing version and url", function(done) {
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- user: true,
- version: "0.1.1"
- }
- });
- installer.installModule("this_wont_exist","0.1.1","https://example/foo-0.1.1.tgz").catch(function(err) {
- err.code.should.be.eql('module_already_loaded');
- done();
- }).catch(done);
- });
- it("rejects with generic error", function(done) {
- var res = {
- code: 1,
- stdout:"",
- stderr:" kaboom!"
- }
- var p = Promise.reject(res);
- p.catch((err)=>{});
- execResponse = p;
- installer.installModule("this_wont_exist").then(function() {
- done(new Error("Unexpected success"));
- }).catch(err => {
- // Expected result
- done()
- });
- });
- it("succeeds when module is found", function(done) {
- var nodeInfo = {nodes:{module:"foo",types:["a"]}};
-
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_wont_exist").then(function(info) {
- info.should.eql(nodeInfo);
- // commsMessages.should.have.length(1);
- // commsMessages[0].topic.should.equal("node/added");
- // commsMessages[0].msg.should.eql(nodeInfo.nodes);
- done();
- }).catch(done);
- });
- it("rejects when non-existant path is provided", function(done) {
- this.timeout(20000);
- var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","NonExistant"));
- installer.installModule(resourcesDir).then(function() {
- done(new Error("Unexpected success"));
- }).catch(function(err) {
- if (err.hasOwnProperty("code")) {
- err.code.should.eql(404);
- done();
- }
- else {
- console.log("ERRROR::"+err.toString()+"::");
- err.toString().should.eql("Error: Install failed");
- done();
- }
- });
- });
- it("succeeds when path is valid node-red module", function(done) {
- var nodeInfo = {nodes:{module:"foo",types:["a"]}};
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
- var resourcesDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule","node_modules","TestNodeModule"));
-
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
- installer.installModule(resourcesDir).then(function(info) {
- info.should.eql(nodeInfo);
- done();
- }).catch(done);
- });
- it("succeeds when url is valid node-red module", function(done) {
- var nodeInfo = {nodes:{module:"foo",types:["a"]}};
-
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_wont_exist",null,"https://example/foo-0.1.1.tgz").then(function(info) {
- info.should.eql(nodeInfo);
- done();
- }).catch(done);
- });
-
- it("triggers preInstall and postInstall hooks", function(done) {
- let receivedPreEvent,receivedPostEvent;
- hooks.add("preInstall", function(event) { event.args = ["a"]; receivedPreEvent = event; })
- hooks.add("postInstall", function(event) { receivedPostEvent = event; })
- var nodeInfo = {nodes:{module:"foo",types:["a"]}};
- var res = {code: 0,stdout:"",stderr:""}
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_wont_exist","1.2.3").then(function(info) {
- exec.run.called.should.be.true();
- exec.run.lastCall.args[1].should.eql([ 'install', 'a', 'this_wont_exist@1.2.3' ]);
- info.should.eql(nodeInfo);
- should.exist(receivedPreEvent)
- receivedPreEvent.should.have.property("module","this_wont_exist")
- receivedPreEvent.should.have.property("version","1.2.3")
- receivedPreEvent.should.have.property("dir")
- receivedPreEvent.should.have.property("url")
- receivedPreEvent.should.have.property("isExisting")
- receivedPreEvent.should.have.property("isUpgrade")
- receivedPreEvent.should.eql(receivedPostEvent)
- done();
- }).catch(done);
- });
-
- it("fails install if preInstall hook fails", function(done) {
- let receivedEvent;
- hooks.add("preInstall", function(event) { throw new Error("preInstall-error"); })
- var nodeInfo = {nodes:{module:"foo",types:["a"]}};
-
- installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
- exec.run.called.should.be.false();
- done();
- }).catch(done);
- });
-
- it("skips invoking npm if preInstall returns false", function(done) {
- let receivedEvent;
- hooks.add("preInstall", function(event) { return false })
- hooks.add("postInstall", function(event) { receivedEvent = event; })
- var nodeInfo = {nodes:{module:"foo",types:["a"]}};
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_wont_exist","1.2.3").then(function() {
- exec.run.called.should.be.false();
- should.exist(receivedEvent);
- done();
- }).catch(done);
- });
-
- it("rollsback install if postInstall hook fails", function(done) {
- hooks.add("postInstall", function(event) { throw new Error("fail"); })
- installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
- exec.run.calledTwice.should.be.true();
- exec.run.firstCall.args[1].includes("install").should.be.true();
- exec.run.secondCall.args[1].includes("remove").should.be.true();
- done();
- }).catch(done);
- });
-
- describe("allowUpdate lists", function() {
- it("rejects when update requested with allowUpdate set to false", function(done) {
- installer.init({ externalModules: { palette: { allowUpdate: false } } })
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- user: true,
- version: "0.1.1"
- }
- });
- installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
- err.code.should.be.eql('update_not_allowed');
- done();
- }).catch(done);
- })
- it("succeeds when update requested with module not on denyUpdateList", function(done) {
- installer.init({ externalModules: { palette: { denyUpdateList: ['this_wont_exist'] } } })
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- user: true,
- version: "0.1.1"
- }
- });
-
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
-
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
- sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_is_allowed","0.1.2").then(function() {
- done();
- }).catch(done);
- })
- it("rejects when update requested with module on denyUpdateList", function(done) {
- installer.init({ externalModules: { palette: { denyUpdateList: ['this_wont_exist'] } } })
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- user: true,
- version: "0.1.1"
- }
- });
-
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
-
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
- sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
- err.code.should.be.eql('update_not_allowed');
- done();
- }).catch(done);
- })
- it("succeeds when update requested with module on allowUpdateList", function(done) {
- installer.init({ externalModules: { palette: { allowUpdateList: ['this_is_allowed'] } } })
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- user: true,
- version: "0.1.1"
- }
- });
-
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
-
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
- sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_is_allowed","0.1.2").then(function() {
- done();
- }).catch(done);
- })
- it("rejects when update requested with module not on allowUpdateList", function(done) {
- installer.init({ externalModules: { palette: { allowUpdateList: ['this_is_allowed'] } } })
- sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
- return {
- user: true,
- version: "0.1.1"
- }
- });
-
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- var nodeInfo = {nodes:{module:"this_wont_exist",types:["a"]}};
-
- var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
- sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
- return Promise.resolve(nodeInfo);
- });
-
- installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
- err.code.should.be.eql('update_not_allowed');
- done();
- }).catch(done);
- })
- });
- });
- describe("uninstalls module", function() {
- it("rejects invalid module names", function(done) {
- var promises = [];
- var rejectedCount = 0;
-
- promises.push(installer.uninstallModule("this_wont_exist ").catch(() => {rejectedCount++}));
- promises.push(installer.uninstallModule("this_wont_exist;no_it_really_wont").catch(() => {rejectedCount++}));
- Promise.all(promises).then(function() {
- rejectedCount.should.eql(2);
- done();
- }).catch(done);
- });
-
- it("rejects with generic error", function(done) {
- var nodeInfo = [{module:"foo",types:["a"]}];
- var removeModule = sinon.stub(registry,"removeModule").callsFake(function(md) {
- return Promise.resolve(nodeInfo);
- });
- var res = {
- code: 1,
- stdout:"",
- stderr:"error"
- }
- var p = Promise.reject(res);
- p.catch((err)=>{});
- execResponse = p;
-
- installer.uninstallModule("this_wont_exist").then(function() {
- done(new Error("Unexpected success"));
- }).catch(err => {
- // Expected result
- done()
- });
- });
- it("succeeds when module is found", function(done) {
- var nodeInfo = [{module:"foo",types:["a"]}];
- var removeModule = sinon.stub(typeRegistry,"removeModule").callsFake(function(md) {
- return nodeInfo;
- });
- var getModuleInfo = sinon.stub(registry,"getModuleInfo").callsFake(function(md) {
- return {nodes:[]};
- });
- var res = {
- code: 0,
- stdout:"",
- stderr:""
- }
- var p = Promise.resolve(res);
- p.catch((err)=>{});
- execResponse = p;
-
- sinon.stub(fs,"statSync").callsFake(function(fn) { return {}; });
-
- installer.uninstallModule("this_wont_exist").then(function(info) {
- info.should.eql(nodeInfo);
- // commsMessages.should.have.length(1);
- // commsMessages[0].topic.should.equal("node/removed");
- // commsMessages[0].msg.should.eql(nodeInfo);
- done();
- }).catch(done);
- });
- });
-});
diff --git a/test/unit/@node-red/registry/lib/library_spec.js b/test/unit/@node-red/registry/lib/library_spec.js
deleted file mode 100644
index 2e0e7e99a..000000000
--- a/test/unit/@node-red/registry/lib/library_spec.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-
-var fs = require("fs");
-var path = require("path");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var library = NR_TEST_UTILS.require("@node-red/registry/lib/library");
-
-describe("library api", function() {
- it('returns null list when no modules have been registered', function() {
- library.init();
- should.not.exist(library.getExampleFlows());
- });
- it('returns null path when module is not known', function() {
- library.init();
- should.not.exist(library.getExampleFlowPath('foo','bar'));
- });
-
- it('returns a valid example path', function(done) {
- library.init();
- library.addExamplesDir("test-module",path.resolve(__dirname+'/resources/examples')).then(function() {
- try {
- var flows = library.getExampleFlows();
- flows.should.deepEqual({"test-module":{"f":["one"]}});
-
- var examplePath = library.getExampleFlowPath('test-module','one');
- examplePath.should.eql(path.resolve(__dirname+'/resources/examples/one.json'))
-
-
- library.removeExamplesDir('test-module');
-
- try {
- should.not.exist(library.getExampleFlows());
- should.not.exist(library.getExampleFlowPath('test-module','one'));
- done();
- } catch(err) {
- done(err);
- }
- }catch(err) {
- done(err);
- }
- });
-
- })
-});
diff --git a/test/unit/@node-red/registry/lib/loader_spec.js b/test/unit/@node-red/registry/lib/loader_spec.js
deleted file mode 100644
index b9da833c8..000000000
--- a/test/unit/@node-red/registry/lib/loader_spec.js
+++ /dev/null
@@ -1,720 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var path = require("path");
-var fs = require("fs-extra");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var loader = NR_TEST_UTILS.require("@node-red/registry/lib/loader");
-
-var localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/localfilesystem");
-var registry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
-
-var nodes = NR_TEST_UTILS.require("@node-red/registry");
-
-var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
-
-describe("red/nodes/registry/loader",function() {
- var stubs = [];
- before(function() {
- sinon.stub(localfilesystem,"init");
- });
- after(function() {
- localfilesystem.init.restore();
- });
- afterEach(function() {
- while(stubs.length) {
- stubs.pop().restore();
- }
- })
-
- describe("#load",function() {
- it("load empty set without settings available", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){ return {};}));
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return {};}));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
- loader.load(true).then(function() {
- localfilesystem.getNodeFiles.called.should.be.true();
- localfilesystem.getNodeFiles.lastCall.args[0].should.be.true();
- registry.saveNodeList.called.should.be.false();
- done();
- })
- });
- it("load empty set with settings available triggers registery save", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){ return {};}));
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return {};}));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.load(true).then(function() {
- registry.saveNodeList.called.should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- })
- });
-
- it("load core node files scanned by lfs - single node single file", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
- var result = {};
- result["node-red"] = {
- "name": "node-red",
- "version": "1.2.3",
- "nodes": {
- "TestNode1": {
- "file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
- "module": "node-red",
- "name": "TestNode1"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
-
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.load().then(function(result) {
- registry.addModule.called.should.be.true();
- var module = registry.addModule.lastCall.args[0];
- module.should.have.property("name","node-red");
- module.should.have.property("version","1.2.3");
- module.should.have.property("nodes");
- module.nodes.should.have.property("TestNode1");
- module.nodes.TestNode1.should.have.property("id","node-red/TestNode1");
- module.nodes.TestNode1.should.have.property("module","node-red");
- module.nodes.TestNode1.should.have.property("name","TestNode1");
- module.nodes.TestNode1.should.have.property("file");
- module.nodes.TestNode1.should.have.property("template");
- module.nodes.TestNode1.should.have.property("enabled",true);
- module.nodes.TestNode1.should.have.property("loaded",true);
- module.nodes.TestNode1.should.have.property("types");
- module.nodes.TestNode1.types.should.have.a.length(1);
- module.nodes.TestNode1.types[0].should.eql('test-node-1');
- module.nodes.TestNode1.should.have.property("config");
- module.nodes.TestNode1.config.should.not.eql("");
- module.nodes.TestNode1.should.have.property("help");
- module.nodes.TestNode1.help.should.have.property("en-US");
- module.nodes.TestNode1.should.have.property("namespace","node-red");
-
- nodes.registerType.calledOnce.should.be.true();
- nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode1');
- nodes.registerType.lastCall.args[1].should.eql('test-node-1');
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it("load core node files scanned by lfs - ignore html if disableEditor true", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
- var result = {};
- result["node-red"] = {
- "name": "node-red",
- "version": "1.2.3",
- "nodes": {
- "TestNode1": {
- "file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
- "module": "node-red",
- "name": "TestNode1"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
-
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{disableEditor: true, available:function(){return true;}}});
- loader.load().then(function(result) {
- registry.addModule.called.should.be.true();
- var module = registry.addModule.lastCall.args[0];
- module.should.have.property("name","node-red");
- module.should.have.property("version","1.2.3");
- module.should.have.property("nodes");
- module.nodes.should.have.property("TestNode1");
- module.nodes.TestNode1.should.have.property("id","node-red/TestNode1");
- module.nodes.TestNode1.should.have.property("module","node-red");
- module.nodes.TestNode1.should.have.property("name","TestNode1");
- module.nodes.TestNode1.should.have.property("file");
- module.nodes.TestNode1.should.have.property("template");
- module.nodes.TestNode1.should.have.property("enabled",true);
- module.nodes.TestNode1.should.have.property("loaded",true);
- // With disableEditor true, the types property is not populated by the
- // html file - but instead is populated as nodes register themselves.
- // But for this test, we have stubbed out registerType, so we won't get any types
- // module.nodes.TestNode1.should.have.property("types");
- // module.nodes.TestNode1.types.should.have.a.length(1);
- // module.nodes.TestNode1.types[0].should.eql('test-node-1');
-
- // With disableEditor set, config should be blank
- module.nodes.TestNode1.should.have.property("config");
- module.nodes.TestNode1.config.should.eql("");
-
- // help should be an empty object
- module.nodes.TestNode1.should.have.property("help");
- module.nodes.TestNode1.help.should.eql({})
- module.nodes.TestNode1.should.have.property("namespace","node-red");
-
- nodes.registerType.calledOnce.should.be.true();
- nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode1');
- nodes.registerType.lastCall.args[1].should.eql('test-node-1');
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it("load core node files scanned by lfs - multiple nodes single file", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
- var result = {};
- result["node-red"] = {
- "name": "node-red",
- "version": "4.5.6",
- "nodes": {
- "MultipleNodes1": {
- "file": path.join(resourcesDir,"MultipleNodes1","MultipleNodes1.js"),
- "module": "node-red",
- "name": "MultipleNodes1"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.load().then(function(result) {
-
- registry.addModule.called.should.be.true();
- var module = registry.addModule.lastCall.args[0];
- module.should.have.property("name","node-red");
- module.should.have.property("version","4.5.6");
- module.should.have.property("nodes");
- module.nodes.should.have.property("MultipleNodes1");
- module.nodes.MultipleNodes1.should.have.property("id","node-red/MultipleNodes1");
- module.nodes.MultipleNodes1.should.have.property("module","node-red");
- module.nodes.MultipleNodes1.should.have.property("name","MultipleNodes1");
- module.nodes.MultipleNodes1.should.have.property("file");
- module.nodes.MultipleNodes1.should.have.property("template");
- module.nodes.MultipleNodes1.should.have.property("enabled",true);
- module.nodes.MultipleNodes1.should.have.property("loaded",true);
- module.nodes.MultipleNodes1.should.have.property("types");
- module.nodes.MultipleNodes1.types.should.have.a.length(2);
- module.nodes.MultipleNodes1.types[0].should.eql('test-node-multiple-1a');
- module.nodes.MultipleNodes1.types[1].should.eql('test-node-multiple-1b');
- module.nodes.MultipleNodes1.should.have.property("config");
- module.nodes.MultipleNodes1.should.have.property("help");
- module.nodes.MultipleNodes1.should.have.property("namespace","node-red");
-
- nodes.registerType.calledTwice.should.be.true();
- nodes.registerType.firstCall.args[0].should.eql('node-red/MultipleNodes1');
- nodes.registerType.firstCall.args[1].should.eql('test-node-multiple-1a');
- nodes.registerType.secondCall.args[0].should.eql('node-red/MultipleNodes1');
- nodes.registerType.secondCall.args[1].should.eql('test-node-multiple-1b');
-
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
-
- it("load core node files scanned by lfs - node with promise", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
- var result = {};
- result["node-red"] = {
- "name": "node-red",
- "version":"2.4.6",
- "nodes": {
- "TestNode2": {
- "file": path.join(resourcesDir,"TestNode2","TestNode2.js"),
- "module": "node-red",
- "name": "TestNode2"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
-
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.load().then(function(result) {
-
- registry.addModule.called.should.be.true();
- var module = registry.addModule.lastCall.args[0];
- module.should.have.property("name","node-red");
- module.should.have.property("version","2.4.6");
- module.should.have.property("nodes");
- module.nodes.should.have.property("TestNode2");
- module.nodes.TestNode2.should.have.property("id","node-red/TestNode2");
- module.nodes.TestNode2.should.have.property("module","node-red");
- module.nodes.TestNode2.should.have.property("name","TestNode2");
- module.nodes.TestNode2.should.have.property("file");
- module.nodes.TestNode2.should.have.property("template");
- module.nodes.TestNode2.should.have.property("enabled",true);
- module.nodes.TestNode2.should.have.property("loaded",true);
- module.nodes.TestNode2.should.have.property("types");
- module.nodes.TestNode2.types.should.have.a.length(1);
- module.nodes.TestNode2.types[0].should.eql('test-node-2');
- module.nodes.TestNode2.should.have.property("config");
- module.nodes.TestNode2.should.have.property("help");
- module.nodes.TestNode2.should.have.property("namespace","node-red");
- module.nodes.TestNode2.should.not.have.property('err');
-
- nodes.registerType.calledOnce.should.be.true();
- nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode2');
- nodes.registerType.lastCall.args[1].should.eql('test-node-2');
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
-
- it("load core node files scanned by lfs - node with rejecting promise", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
- var result = {};
- result["node-red"] = {
- "name": "node-red",
- "version":"1.2.3",
- "nodes": {
- "TestNode3": {
- "file": path.join(resourcesDir,"TestNode3","TestNode3.js"),
- "module": "node-red",
- "name": "TestNode3"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
-
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.load().then(function(result) {
- registry.addModule.called.should.be.true();
- var module = registry.addModule.lastCall.args[0];
- module.should.have.property("name","node-red");
- module.should.have.property("version","1.2.3");
- module.should.have.property("nodes");
- module.nodes.should.have.property("TestNode3");
- module.nodes.TestNode3.should.have.property("id","node-red/TestNode3");
- module.nodes.TestNode3.should.have.property("module","node-red");
- module.nodes.TestNode3.should.have.property("name","TestNode3");
- module.nodes.TestNode3.should.have.property("file");
- module.nodes.TestNode3.should.have.property("template");
- module.nodes.TestNode3.should.have.property("enabled",true);
- module.nodes.TestNode3.should.have.property("loaded",false);
- module.nodes.TestNode3.should.have.property("types");
- module.nodes.TestNode3.types.should.have.a.length(1);
- module.nodes.TestNode3.types[0].should.eql('test-node-3');
- module.nodes.TestNode3.should.have.property("config");
- module.nodes.TestNode3.should.have.property("help");
- module.nodes.TestNode3.should.have.property("namespace","node-red");
- module.nodes.TestNode3.should.have.property('err','fail');
-
- nodes.registerType.called.should.be.false();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it("load core node files scanned by lfs - missing file", function(done) {
- stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
- var result = {};
- result["node-red"] = {
- "name": "node-red",
- "version":"1.2.3",
- "nodes": {
- "DoesNotExist": {
- "file": path.join(resourcesDir,"doesnotexist"),
- "module": "node-red",
- "name": "DoesNotExist"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
-
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.load().then(function(result) {
- registry.addModule.called.should.be.true();
- var module = registry.addModule.lastCall.args[0];
- module.should.have.property("name","node-red");
- module.should.have.property("version","1.2.3");
- module.should.have.property("nodes");
- module.nodes.should.have.property("DoesNotExist");
- module.nodes.DoesNotExist.should.have.property("id","node-red/DoesNotExist");
- module.nodes.DoesNotExist.should.have.property("module","node-red");
- module.nodes.DoesNotExist.should.have.property("name","DoesNotExist");
- module.nodes.DoesNotExist.should.have.property("file");
- module.nodes.DoesNotExist.should.have.property("template");
- module.nodes.DoesNotExist.should.have.property("enabled",true);
- module.nodes.DoesNotExist.should.have.property("loaded",false);
- module.nodes.DoesNotExist.should.have.property("types");
- module.nodes.DoesNotExist.types.should.have.a.length(0);
- module.nodes.DoesNotExist.should.have.property("config","");
- module.nodes.DoesNotExist.should.have.property("help",{});
- module.nodes.DoesNotExist.should.have.property("namespace","node-red");
- module.nodes.DoesNotExist.should.have.property('err');
-
- nodes.registerType.called.should.be.false();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- // it("load core node files scanned by lfs - missing html file", function(done) {
- // // This is now an okay situation
- // stubs.push(sinon.stub(localfilesystem,"getNodeFiles").callsFake(function(){
- // var result = {};
- // result["node-red"] = {
- // "name": "node-red",
- // "version": "1.2.3",
- // "nodes": {
- // "DuffNode": {
- // "file": path.join(resourcesDir,"DuffNode","DuffNode.js"),
- // "module": "node-red",
- // "name": "DuffNode"
- // }
- // }
- // };
- // return result;
- // }));
- //
- // stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return }));
- // stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- // // This module isn't already loaded
- // stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
- //
- // stubs.push(sinon.stub(nodes,"registerType"));
- // loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- // loader.load().then(function(result) {
- //
- // registry.addModule.called.should.be.true();
- // var module = registry.addModule.lastCall.args[0];
- // module.should.have.property("name","node-red");
- // module.should.have.property("version","1.2.3");
- // module.should.have.property("nodes");
- // module.nodes.should.have.property("DuffNode");
- // module.nodes.DuffNode.should.have.property("id","node-red/DuffNode");
- // module.nodes.DuffNode.should.have.property("module","node-red");
- // module.nodes.DuffNode.should.have.property("name","DuffNode");
- // module.nodes.DuffNode.should.have.property("file");
- // module.nodes.DuffNode.should.have.property("template");
- // module.nodes.DuffNode.should.have.property("enabled",true);
- // module.nodes.DuffNode.should.have.property("loaded",false);
- // module.nodes.DuffNode.should.have.property("types");
- // module.nodes.DuffNode.types.should.have.a.length(0);
- // module.nodes.DuffNode.should.have.property("config","");
- // module.nodes.DuffNode.should.have.property("help",{});
- // module.nodes.DuffNode.should.have.property("namespace","node-red");
- // module.nodes.DuffNode.should.have.property('err');
- // module.nodes.DuffNode.err.should.endWith("DuffNode.html does not exist");
- //
- // nodes.registerType.called.should.be.false();
- //
- // done();
- // }).catch(function(err) {
- // done(err);
- // });
- // });
- });
-
- describe("#addModule",function() {
- it("throws error if settings unavailable", function() {
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return false;}}});
- /*jshint immed: false */
- (function(){
- loader.addModule("test-module");
- }).should.throw("Settings unavailable");
- });
-
- it("returns rejected error if module already loaded", function(done) {
- stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){return{}}));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
-
- loader.addModule("test-module").catch(function(err) {
- err.code.should.eql("module_already_loaded");
- done();
- });
- });
- it("returns rejected error if module not found", function(done) {
- stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){return null}));
- stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function() {
- throw new Error("failure");
- }));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.addModule("test-module").catch(function(err) {
- err.message.should.eql("failure");
- done();
- });
-
- });
-
- it("loads module by name", function(done) {
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
- stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){ return null; }));
- stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function(){
- var result = {};
- result["TestNodeModule"] = {
- "name": "TestNodeModule",
- "version": "1.2.3",
- "nodes": {
- "TestNode1": {
- "file": path.join(resourcesDir,"TestNodeModule","node_modules","TestNodeModule","TestNodeModule.js"),
- "module": "TestNodeModule",
- "name": "TestNode1",
- "version": "1.2.3"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return "a node list" }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({nodes:nodes,log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.addModule("TestNodeModule").then(function(result) {
- result.should.eql("TestNodeModule");
-
- registry.addModule.called.should.be.true();
- var module = registry.addModule.lastCall.args[0];
- module.should.have.property("name","TestNodeModule");
- module.should.have.property("version","1.2.3");
- module.should.have.property("nodes");
- module.nodes.should.have.property("TestNode1");
- module.nodes.TestNode1.should.have.property("id","TestNodeModule/TestNode1");
- module.nodes.TestNode1.should.have.property("module","TestNodeModule");
- module.nodes.TestNode1.should.have.property("name","TestNode1");
- module.nodes.TestNode1.should.have.property("file");
- module.nodes.TestNode1.should.have.property("template");
- module.nodes.TestNode1.should.have.property("enabled",true);
- module.nodes.TestNode1.should.have.property("loaded",true);
- module.nodes.TestNode1.should.have.property("types");
- module.nodes.TestNode1.types.should.have.a.length(1);
- module.nodes.TestNode1.types[0].should.eql('test-node-mod-1');
- module.nodes.TestNode1.should.have.property("config");
- module.nodes.TestNode1.should.have.property("help");
- module.nodes.TestNode1.should.have.property("namespace","TestNodeModule");
- module.nodes.TestNode1.should.not.have.property('err');
-
- nodes.registerType.calledOnce.should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it("skips module that fails version check", function(done) {
- // This module isn't already loaded
- stubs.push(sinon.stub(registry,"getNodeInfo").callsFake(function(){ return null; }));
- stubs.push(sinon.stub(registry,"getModuleInfo").callsFake(function(){ return null; }));
- stubs.push(sinon.stub(localfilesystem,"getModuleFiles").callsFake(function(){
- var result = {};
- result["TestNodeModule"] = {
- "name": "TestNodeModule",
- "version": "1.2.3",
- "redVersion":"999.0.0",
- "nodes": {
- "TestNode1": {
- "file": path.join(resourcesDir,"TestNodeModule","node_modules","TestNodeModule","TestNodeModule.js"),
- "module": "TestNodeModule",
- "name": "TestNode1",
- "version": "1.2.3"
- }
- }
- };
- return result;
- }));
-
- stubs.push(sinon.stub(registry,"saveNodeList").callsFake(function(){ return "a node list" }));
- stubs.push(sinon.stub(registry,"addModule").callsFake(function(){ return }));
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.init({log:{"_":function(){},warn:function(){}},nodes:nodes,version: function() { return "0.12.0"}, settings:{available:function(){return true;}}});
- loader.addModule("TestNodeModule").then(function(result) {
- result.should.eql("TestNodeModule");
- registry.addModule.called.should.be.false();
- nodes.registerType.called.should.be.false();
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it.skip('registers a message catalog');
-
-
- });
- describe("#loadNodeSet",function() {
- it("no-ops the load if node is not enabled", function(done) {
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.loadNodeSet({
- "file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
- "module": "node-red",
- "name": "TestNode1",
- "enabled": false
- }).then(function(node) {
- node.enabled.should.be.false();
- nodes.registerType.called.should.be.false();
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it("handles node that errors on require", function(done) {
- stubs.push(sinon.stub(nodes,"registerType"));
- loader.loadNodeSet({
- "file": path.join(resourcesDir,"TestNode4","TestNode4.js"),
- "module": "node-red",
- "name": "TestNode4",
- "enabled": true
- }).then(function(node) {
- node.enabled.should.be.true();
- nodes.registerType.called.should.be.false();
- node.should.have.property('err');
- node.err.toString().should.eql("Error: fail to require (line:1)");
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- });
- describe("#getNodeHelp",function() {
- it("returns preloaded help", function() {
- loader.getNodeHelp({
- help:{
- en:"foo"
- }
- },"en").should.eql("foo");
- });
- it("loads help, caching result", function() {
- stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
- return 'bar';
- }))
- var node = {
- template: "/tmp/node/directory/file.html",
- help:{
- en:"foo"
- }
- };
- loader.getNodeHelp(node,"fr").should.eql("bar");
- node.help['fr'].should.eql("bar");
- fs.readFileSync.calledOnce.should.be.true();
- fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/fr/file.html"));
- loader.getNodeHelp(node,"fr").should.eql("bar");
- fs.readFileSync.calledOnce.should.be.true();
- });
- it("loads help, defaulting to en-US content", function() {
- stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
- throw new Error("not found");
- }))
- var node = {
- template: "/tmp/node/directory/file.html",
- help:{}
- };
- node.help['en-US'] = 'foo';
-
- loader.getNodeHelp(node,"fr").should.eql("foo");
- node.help['fr'].should.eql("foo");
- fs.readFileSync.calledOnce.should.be.true();
- fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/fr/file.html"));
- loader.getNodeHelp(node,"fr").should.eql("foo");
- fs.readFileSync.calledOnce.should.be.true();
- });
- it("loads help, defaulting to en-US content for extra nodes", function() {
- stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
- if (path.indexOf("en-US") >= 0) {
- return 'bar';
- }
- throw new Error("not found");
- }));
- var node = {
- template: "/tmp/node/directory/file.html",
- help:{}
- };
- delete node.help['en-US'];
-
- loader.getNodeHelp(node,"fr").should.eql("bar");
- node.help['fr'].should.eql("bar");
- fs.readFileSync.calledTwice.should.be.true();
- fs.readFileSync.firstCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/fr/file.html"));
- fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/en-US/file.html"));
- loader.getNodeHelp(node,"fr").should.eql("bar");
- fs.readFileSync.calledTwice.should.be.true();
- });
- it("fails to load en-US help content", function() {
- stubs.push(sinon.stub(fs,"readFileSync").callsFake(function(path) {
- throw new Error("not found");
- }));
- var node = {
- template: "/tmp/node/directory/file.html",
- help:{}
- };
- delete node.help['en-US'];
-
- should.not.exist(loader.getNodeHelp(node,"en-US"));
- should.not.exist(node.help['en-US']);
- fs.readFileSync.calledTwice.should.be.true();
- fs.readFileSync.firstCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/en-US/file.html"));
- fs.readFileSync.lastCall.args[0].should.eql(path.normalize("/tmp/node/directory/locales/en/file.html"));
- should.not.exist(loader.getNodeHelp(node,"en-US"));
- fs.readFileSync.callCount.should.eql(4);
- });
-
- });
-});
diff --git a/test/unit/@node-red/registry/lib/localfilesystem_spec.js b/test/unit/@node-red/registry/lib/localfilesystem_spec.js
deleted file mode 100644
index e84761657..000000000
--- a/test/unit/@node-red/registry/lib/localfilesystem_spec.js
+++ /dev/null
@@ -1,276 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var path = require("path");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var localfilesystem = NR_TEST_UTILS.require("@node-red/registry/lib/localfilesystem");
-
-var resourcesDir = path.resolve(path.join(__dirname,"resources","local"));
-var userDir = path.resolve(path.join(__dirname,"resources","userDir"));
-var moduleDir = path.resolve(path.join(__dirname,"resources","local","TestNodeModule"));
-
-var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-describe("red/nodes/registry/localfilesystem",function() {
- beforeEach(function() {
- stubs.push(sinon.stub(i18n,"registerMessageCatalog").callsFake(function() { return Promise.resolve(); }));
- })
-
- var stubs = [];
- afterEach(function() {
- while(stubs.length) {
- stubs.pop().restore();
- }
- })
- function checkNodes(nodes,shouldHaveNodes,shouldNotHaveNodes,module) {
- for (var i=0;i modules[moduleId]);
- sinon.stub(registry,"getModuleList").callsFake(() => modules)
- });
- afterEach(function() {
- events.removeListener("registry:plugin-added",handleEvent);
- registry.getModule.restore();
- registry.getModuleList.restore();
- })
-
- describe("registerPlugin", function() {
- it("registers a plugin", function() {
- let pluginDef = {}
- plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
- receivedEvents.length.should.eql(1);
- receivedEvents[0].should.eql("a-plugin");
- should.exist(modules['test-module'].plugins['test-set'].plugins[0])
- modules['test-module'].plugins['test-set'].plugins[0].should.equal(pluginDef)
- })
- it("calls a plugins onadd function", function() {
- let pluginDef = { onadd: sinon.stub() }
- plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
- pluginDef.onadd.called.should.be.true();
- })
- })
-
- describe("getPlugin", function() {
- it("returns a registered plugin", function() {
- let pluginDef = {}
- plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
- pluginDef.should.equal(plugins.getPlugin("a-plugin"));
- })
- })
- describe("getPluginsByType", function() {
- it("returns a plugins of a given type", function() {
- let pluginDef = {type: "foo"}
- let pluginDef2 = {type: "bar"}
- let pluginDef3 = {type: "foo"}
- plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
- plugins.registerPlugin("test-module/test-set","a-plugin2",pluginDef2);
- plugins.registerPlugin("test-module/test-set","a-plugin3",pluginDef3);
-
- let fooPlugins = plugins.getPluginsByType("foo");
- let barPlugins = plugins.getPluginsByType("bar");
- let noPlugins = plugins.getPluginsByType("none");
-
- noPlugins.should.be.of.length(0);
-
- fooPlugins.should.be.of.length(2);
- fooPlugins.should.containEql(pluginDef);
- fooPlugins.should.containEql(pluginDef3);
-
- barPlugins.should.be.of.length(1);
- barPlugins.should.containEql(pluginDef2);
-
- })
- })
-
- describe("getPluginConfigs", function() {
- it("gets all plugin configs", function() {
- let configs = plugins.getPluginConfigs("en-US");
- configs.should.eql(`
-
-test-module-config`)
- })
- })
-
-
- describe("getPluginList", function() {
- it("returns a plugins of a given type", function() {
- let pluginDef = {type: "foo"}
- let pluginDef2 = {type: "bar"}
- let pluginDef3 = {type: "foo"}
- plugins.registerPlugin("test-module/test-set","a-plugin",pluginDef);
- plugins.registerPlugin("test-module/test-set","a-plugin2",pluginDef2);
- plugins.registerPlugin("test-module/test-set","a-plugin3",pluginDef3);
-
- let pluginList = plugins.getPluginList();
- JSON.stringify(pluginList).should.eql(JSON.stringify(
- [
- {
- "id": "test-module/test-set",
- "enabled": true,
- "local": false,
- "user": false,
- "plugins": [
- {
- "type": "foo",
- "id": "a-plugin",
- "module": "test-module"
- },
- {
- "type": "bar",
- "id": "a-plugin2",
- "module": "test-module"
- },
- {
- "type": "foo",
- "id": "a-plugin3",
- "module": "test-module"
- }
- ]
- },
- {
- "id": "test-module/test-disabled-set",
- "enabled": false,
- "local": false,
- "user": false,
- "plugins": []
- }
- ]
- ))
- })
- })
- describe("exportPluginSettings", function() {
- it("exports plugin settings - default false", function() {
- plugins.init({ "a-plugin": { a: 123, b:234, c: 345} });
- plugins.registerPlugin("test-module/test-set","a-plugin",{
- settings: {
- a: { exportable: true },
- b: {exportable: false },
- d: { exportable: true, value: 456}
-
- }
- });
- var exportedSet = {};
- plugins.exportPluginSettings(exportedSet);
- exportedSet.should.have.property("a-plugin");
- // a is exportable
- exportedSet["a-plugin"].should.have.property("a",123);
- // b is explicitly not exportable
- exportedSet["a-plugin"].should.not.have.property("b");
- // c isn't listed and default false
- exportedSet["a-plugin"].should.not.have.property("c");
- // d has a default value
- exportedSet["a-plugin"].should.have.property("d",456);
- })
- it("exports plugin settings - default true", function() {
- plugins.init({ "a-plugin": { a: 123, b:234, c: 345} });
- plugins.registerPlugin("test-module/test-set","a-plugin",{
- settings: {
- '*': { exportable: true },
- a: { exportable: true },
- b: {exportable: false },
- d: { exportable: true, value: 456}
-
- }
- });
- var exportedSet = {};
- plugins.exportPluginSettings(exportedSet);
- exportedSet.should.have.property("a-plugin");
- // a is exportable
- exportedSet["a-plugin"].should.have.property("a",123);
- // b is explicitly not exportable
- exportedSet["a-plugin"].should.not.have.property("b");
- // c isn't listed, but default true
- exportedSet["a-plugin"].should.have.property("c");
- // d has a default value
- exportedSet["a-plugin"].should.have.property("d",456);
- })
- });
-});
diff --git a/test/unit/@node-red/registry/lib/registry_spec.js b/test/unit/@node-red/registry/lib/registry_spec.js
deleted file mode 100644
index 5501264a7..000000000
--- a/test/unit/@node-red/registry/lib/registry_spec.js
+++ /dev/null
@@ -1,614 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var path = require("path");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry/lib/registry");
-const { events } = NR_TEST_UTILS.require("@node-red/util");
-
-describe("red/nodes/registry/registry",function() {
-
- afterEach(function() {
- typeRegistry.clear();
- });
-
- function stubSettings(s,available,initialConfig) {
- s.available = function() {return available;};
- s.set = sinon.spy(function(s,v) { return Promise.resolve();});
- s.get = function(s) { return initialConfig;};
- return s;
- }
-
- var settings = stubSettings({},false,null);
- var settingsWithStorageAndInitialConfig = stubSettings({},true,{"node-red":{module:"testModule",name:"testName",version:"testVersion",nodes:{"node":{id:"node-red/testName",name:"test",types:["a","b"],enabled:true}}}});
-
- var testNodeSet1 = {
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"]
- };
-
- var testNodeSet2 = {
- id: "test-module/test-name-2",
- module: "test-module",
- name: "test-name-2",
- enabled: true,
- loaded: false,
- config: "configB",
- types: [ "test-c","test-d"]
- };
- var testNodeSet2WithError = {
- id: "test-module/test-name-2",
- module: "test-module",
- name: "test-name-2",
- enabled: true,
- loaded: false,
- err: "I have an error",
- config: "configC",
- types: [ "test-c","test-d"]
- };
- var testNodeSet3 = {
- id: "test-module-2/test-name-3",
- module: "test-module-2",
- name: "test-name-3",
- enabled: true,
- loaded: false,
- config: "configB",
- types: [ "test-a","test-e"]
- };
-
-
-
- describe('#init/load', function() {
- it('loads initial config', function(done) {
- typeRegistry.init(settingsWithStorageAndInitialConfig,null);
- typeRegistry.getNodeList().should.have.lengthOf(0);
- typeRegistry.load();
- typeRegistry.getNodeList().should.have.lengthOf(1);
- done();
- });
-
- it('migrates legacy format', function(done) {
- var legacySettings = {
- available: function() { return true; },
- set: sinon.stub().returns(Promise.resolve()),
- get: function() { return {
- "123": {
- "name": "72-sentiment.js",
- "types": [
- "sentiment"
- ],
- "enabled": true
- },
- "456": {
- "name": "20-inject.js",
- "types": [
- "inject"
- ],
- "enabled": true
- },
- "789": {
- "name": "testModule:a-module.js",
- "types": [
- "example"
- ],
- "enabled":true,
- "module":"testModule"
- }
- }}
- };
- var expected = JSON.parse('{"node-red":{"name":"node-red","nodes":{"sentiment":{"name":"sentiment","types":["sentiment"],"enabled":true,"module":"node-red"},"inject":{"name":"inject","types":["inject"],"enabled":true,"module":"node-red"}}},"testModule":{"name":"testModule","nodes":{"a-module.js":{"name":"a-module.js","types":["example"],"enabled":true,"module":"testModule"}}}}');
- typeRegistry.init(legacySettings,null);
- typeRegistry.load();
- legacySettings.set.calledOnce.should.be.true();
- legacySettings.set.args[0][1].should.eql(expected);
- done();
- });
- });
-
-
- describe.skip('#addNodeSet', function() {
- it('adds a node set for an unknown module', function() {
-
- typeRegistry.init(settings,null);
-
- typeRegistry.getNodeList().should.have.lengthOf(0);
- typeRegistry.getModuleList().should.eql({});
-
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
-
- typeRegistry.getNodeList().should.have.lengthOf(1);
- var moduleList = typeRegistry.getModuleList();
- moduleList.should.have.a.property("test-module");
- moduleList["test-module"].should.have.a.property("name","test-module");
- moduleList["test-module"].should.have.a.property("version","0.0.1");
- moduleList["test-module"].should.have.a.property("nodes");
- moduleList["test-module"].nodes.should.have.a.property("test-name");
-
- moduleList["test-module"].nodes["test-name"].should.eql({
- config: 'configA',
- id: 'test-module/test-name',
- module: 'test-module',
- name: 'test-name',
- enabled: true,
- loaded: false,
- types: [ 'test-a', 'test-b' ]
- });
-
- });
-
- it('adds a node set to an existing module', function() {
-
- typeRegistry.init(settings,null);
- typeRegistry.getNodeList().should.have.lengthOf(0);
- typeRegistry.getModuleList().should.eql({});
-
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
-
- typeRegistry.getNodeList().should.have.lengthOf(1);
- var moduleList = typeRegistry.getModuleList();
- Object.keys(moduleList).should.have.a.lengthOf(1);
- moduleList.should.have.a.property("test-module");
- moduleList["test-module"].should.have.a.property("name","test-module");
- moduleList["test-module"].should.have.a.property("version","0.0.1");
- moduleList["test-module"].should.have.a.property("nodes");
-
- Object.keys(moduleList["test-module"].nodes).should.have.a.lengthOf(1);
- moduleList["test-module"].nodes.should.have.a.property("test-name");
-
-
- typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2);
-
- typeRegistry.getNodeList().should.have.lengthOf(2);
- moduleList = typeRegistry.getModuleList();
- Object.keys(moduleList).should.have.a.lengthOf(1);
- Object.keys(moduleList["test-module"].nodes).should.have.a.lengthOf(2);
- moduleList["test-module"].nodes.should.have.a.property("test-name");
- moduleList["test-module"].nodes.should.have.a.property("test-name-2");
- });
-
- it('doesnt add node set types if node set has an error', function() {
- typeRegistry.init(settings,null);
- typeRegistry.getNodeList().should.have.lengthOf(0);
- typeRegistry.getModuleList().should.eql({});
-
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
-
- typeRegistry.getTypeId("test-a").should.eql("test-module/test-name");
-
- should.not.exist(typeRegistry.getTypeId("test-c"));
-
- typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2WithError, "0.0.1");
-
- should.not.exist(typeRegistry.getTypeId("test-c"));
- });
-
- it('doesnt add node set if type already exists', function() {
- typeRegistry.init(settings,null);
- typeRegistry.getNodeList().should.have.lengthOf(0);
- typeRegistry.getModuleList().should.eql({});
-
- should.not.exist(typeRegistry.getTypeId("test-e"));
-
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
- typeRegistry.getNodeList().should.have.lengthOf(1);
- should.exist(typeRegistry.getTypeId("test-a"));
- typeRegistry.addNodeSet(testNodeSet3.id,testNodeSet3, "0.0.1");
- typeRegistry.getNodeList().should.have.lengthOf(2);
-
- // testNodeSet3 registers a duplicate test-a and unique test-e
- // as test-a is a duplicate, test-e should not get registered
- should.not.exist(typeRegistry.getTypeId("test-e"));
-
- var testNodeSet3Result = typeRegistry.getNodeList()[1];
- should.exist(testNodeSet3Result.err);
- testNodeSet3Result.err.code.should.equal("type_already_registered");
- testNodeSet3Result.err.details.type.should.equal("test-a");
- testNodeSet3Result.err.details.moduleA.should.equal("test-module");
- testNodeSet3Result.err.details.moduleB.should.equal("test-module-2");
-
- //
- // typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2WithError, "0.0.1");
- //
- // should.not.exist(typeRegistry.getTypeId("test-c"));
- });
-
-
- });
-
- describe("#enableNodeSet", function() {
- it('throws error if settings unavailable', function() {
- typeRegistry.init(settings,null);
- /*jshint immed: false */
- (function(){
- typeRegistry.enableNodeSet("test-module/test-name");
- }).should.throw("Settings unavailable");
- });
-
- it('throws error if module unknown', function() {
- typeRegistry.init(settingsWithStorageAndInitialConfig,null);
- /*jshint immed: false */
- (function(){
- typeRegistry.enableNodeSet("test-module/unknown");
- }).should.throw("Unrecognised id: test-module/unknown");
- });
- it.skip('enables the node',function(){})
-
- });
- describe("#disableNodeSet", function() {
- it('throws error if settings unavailable', function() {
- typeRegistry.init(settings,null);
- /*jshint immed: false */
- (function(){
- typeRegistry.disableNodeSet("test-module/test-name");
- }).should.throw("Settings unavailable");
- });
-
- it('throws error if module unknown', function() {
- typeRegistry.init(settingsWithStorageAndInitialConfig,null);
- /*jshint immed: false */
- (function(){
- typeRegistry.disableNodeSet("test-module/unknown");
- }).should.throw("Unrecognised id: test-module/unknown");
- });
- it.skip('disables the node',function(){})
- });
-
- describe('#getNodeConfig', function() {
- it('returns nothing for an unregistered type config', function(done) {
- typeRegistry.init(settings,null);
- var config = typeRegistry.getNodeConfig("imaginary-shark");
- (config === null).should.be.true();
- done();
- });
- });
-
- describe('#saveNodeList',function() {
- it('rejects when settings unavailable',function(done) {
- typeRegistry.init(stubSettings({},false,{}),null);
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {"test-name":{module:"test-module",name:"test-name",types:[]}}});
- typeRegistry.saveNodeList().catch(function(err) {
- done();
- });
- });
- it('saves the list',function(done) {
- var s = stubSettings({},true,{});
- typeRegistry.init(s,null);
-
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":testNodeSet1,
- "test-name-2":testNodeSet2WithError
- }});
-
- typeRegistry.saveNodeList().then(function() {
- s.set.called.should.be.true();
- s.set.lastCall.args[0].should.eql('nodes');
- var nodes = s.set.lastCall.args[1];
- nodes.should.have.property('test-module');
- for (var n in nodes['test-module'].nodes) {
- if (nodes['test-module'].nodes.hasOwnProperty(n)) {
- var nn = nodes['test-module'].nodes[n];
- nn.should.not.have.property('err');
- nn.should.not.have.property('id');
- }
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- describe('#removeModule',function() {
- it('throws error for unknown module', function() {
- var s = stubSettings({},true,{});
- typeRegistry.init(s,null);
- /*jshint immed: false */
- (function(){
- typeRegistry.removeModule("test-module/unknown");
- }).should.throw("Unrecognised module: test-module/unknown");
- });
- it('throws error for unavaiable settings', function() {
- var s = stubSettings({},false,{});
- typeRegistry.init(s,null);
- /*jshint immed: false */
- (function(){
- typeRegistry.removeModule("test-module/unknown");
- }).should.throw("Settings unavailable");
- });
- it('removes a known module', function() {
- var s = stubSettings({},true,{});
- typeRegistry.init(s,null);
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":testNodeSet1
- }});
- var moduleList = typeRegistry.getModuleList();
- moduleList.should.have.a.property("test-module");
- typeRegistry.getNodeList().should.have.lengthOf(1);
-
- var info = typeRegistry.removeModule('test-module');
- moduleList = typeRegistry.getModuleList();
- moduleList.should.not.have.a.property("test-module");
- typeRegistry.getNodeList().should.have.lengthOf(0);
- });
- });
-
- describe('#get[All]NodeConfigs', function() {
- it('returns node config', function() {
- typeRegistry.init(settings,{
- getNodeHelp: function(config) { return "HE"+config.name+"LP" }
- });
-
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"]
- },
- "test-name-2":{
- id: "test-module/test-name-2",
- module: "test-module",
- name: "test-name-2",
- enabled: true,
- loaded: false,
- config: "configB",
- types: [ "test-c","test-d"]
- }
- }});
- typeRegistry.getNodeConfig("test-module/test-name").should.eql('\nconfigAHEtest-nameLP');
- typeRegistry.getNodeConfig("test-module/test-name-2").should.eql('\nconfigBHEtest-name-2LP');
- typeRegistry.getAllNodeConfigs().should.eql('\n\nconfigAHEtest-nameLP\n\nconfigBHEtest-name-2LP');
- });
- });
- describe('#getModuleInfo', function() {
- it('returns module info', function() {
- typeRegistry.init(settings,{});
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }
- }});
- var moduleInfo = typeRegistry.getModuleInfo("test-module");
- moduleInfo.should.have.a.property('name','test-module');
- moduleInfo.should.have.a.property('version','0.0.1');
- moduleInfo.should.have.a.property('nodes');
- moduleInfo.nodes.should.have.a.lengthOf(1);
- moduleInfo.nodes[0].should.have.a.property('id','test-module/test-name');
- moduleInfo.nodes[0].should.not.have.a.property('file');
- });
- });
- describe('#getNodeInfo', function() {
- it('returns node info', function() {
- typeRegistry.init(settings,{});
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }
- }});
- var nodeSetInfo = typeRegistry.getNodeInfo("test-module/test-name");
- nodeSetInfo.should.have.a.property('id',"test-module/test-name");
- nodeSetInfo.should.not.have.a.property('config');
- nodeSetInfo.should.not.have.a.property('file');
- });
- });
- describe('#getFullNodeInfo', function() {
- it('returns node info', function() {
- typeRegistry.init(settings,{});
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
-
- }
- }});
- var nodeSetInfo = typeRegistry.getFullNodeInfo("test-module/test-name");
- nodeSetInfo.should.have.a.property('id',"test-module/test-name");
- nodeSetInfo.should.have.a.property('config');
- nodeSetInfo.should.have.a.property('file');
- });
- });
- describe('#cleanModuleList', function() {
- it.skip("cleans the module list");
- });
- describe('#getNodeList', function() {
- it("returns a filtered list", function() {
- typeRegistry.init(settings,{});
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- },
- "test-name-2":{
- id: "test-module/test-name-2",
- module: "test-module",
- name: "test-name-2",
- enabled: true,
- loaded: false,
- config: "configB",
- types: [ "test-c","test-d"],
- file: "def"
- }
- }});
- var filterCallCount = 0;
- var filteredList = typeRegistry.getNodeList(function(n) { filterCallCount++; return n.name === 'test-name-2';});
- filterCallCount.should.eql(2);
- filteredList.should.have.a.lengthOf(1);
- filteredList[0].should.have.a.property('id',"test-module/test-name-2");
- });
- });
-
- describe('#registerNodeConstructor', function() {
- var TestNodeConstructor;
- beforeEach(function() {
- TestNodeConstructor = function TestNodeConstructor() {};
- sinon.stub(events,'emit');
- });
- afterEach(function() {
- events.emit.restore();
- });
- it('registers a node constructor', function() {
- typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
- events.emit.calledOnce.should.be.true();
- events.emit.lastCall.args[0].should.eql('type-registered');
- events.emit.lastCall.args[1].should.eql('node-type');
- })
- it('throws error on duplicate node registration', function() {
- typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
- events.emit.calledOnce.should.be.true();
- events.emit.lastCall.args[0].should.eql('type-registered');
- events.emit.lastCall.args[1].should.eql('node-type');
- /*jshint immed: false */
- (function(){
- typeRegistry.registerNodeConstructor('node-set','node-type',TestNodeConstructor);
- }).should.throw("node-type already registered");
- events.emit.calledOnce.should.be.true();
- });
- });
-
- describe('#getNodeIconPath', function() {
- it('returns the null when getting an unknown icon', function() {
- var iconPath = typeRegistry.getNodeIconPath('random-module','youwonthaveme.png');
- should.not.exist(iconPath);
- });
-
- it('returns a registered icon' , function() {
- var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
- typeRegistry.init(settings,{});
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }
- },icons: [{path:testIcon,icons:['test_icon.png']}]});
- var iconPath = typeRegistry.getNodeIconPath('test-module','test_icon.png');
- iconPath.should.eql(path.resolve(testIcon+"/test_icon.png"));
- });
-
- it('returns null when getting an unknown module', function() {
- var debugIcon = path.resolve(__dirname+'/../../../public/icons/debug.png');
- var iconPath = typeRegistry.getNodeIconPath('unknown-module', 'debug.png');
- should.not.exist(iconPath);
- });
- });
-
- describe('#getNodeIcons', function() {
- it('returns empty icon list when no modules are registered', function() {
- var iconList = typeRegistry.getNodeIcons();
- iconList.should.eql({});
- });
-
- it('returns an icon list of registered node module', function() {
- var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
- typeRegistry.init(settings,{});
- typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }
- },icons: [{path:testIcon,icons:['test_icon.png']}]});
- var iconList = typeRegistry.getNodeIcons();
- iconList.should.eql({"test-module":["test_icon.png"]});
- });
- });
-
- describe('#getModuleResource', function() {
- beforeEach(function() {
- typeRegistry.init(settings,{});
- typeRegistry.addModule({
- name: "test-module",version:"0.0.1",nodes: {
- "test-name":{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }
- },
- resources: {
- path: path.join(__dirname, "resources","examples")
- }
- });
- });
- it('Returns valid resource path', function() {
- const result = typeRegistry.getModuleResource("test-module","one.json");
- should.exist(result);
- result.should.eql(path.join(__dirname, "resources","examples","one.json"))
- });
- it('Returns null for path that tries to break out', function() {
- // Note - this path exists, but we don't allow .. in the resolved path to
- // avoid breaking out of the resources dir
- const result = typeRegistry.getModuleResource("test-module","../../index_spec.js");
- should.not.exist(result);
- });
- it('Returns null for path that does not exist', function() {
- const result = typeRegistry.getModuleResource("test-module","two.json");
- should.not.exist(result);
- });
- });
-});
diff --git a/test/unit/@node-red/registry/lib/resources/examples/one.json b/test/unit/@node-red/registry/lib/resources/examples/one.json
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/unit/@node-red/registry/lib/resources/local/DuffNode/DuffNode.js b/test/unit/@node-red/registry/lib/resources/local/DuffNode/DuffNode.js
deleted file mode 100644
index 41e2a0059..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/DuffNode/DuffNode.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function DuffNode(n) {}
- RED.nodes.registerType("duff-node",DuffNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.html b/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.html
deleted file mode 100644
index b637ede21..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.js b/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.js
deleted file mode 100644
index e81214169..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/DuplicateTestNode/TestNode1.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function DuplicateTestNode(n) {}
- RED.nodes.registerType("test-node-1",DuplicateTestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.html b/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.html
deleted file mode 100644
index 5359644e5..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.js b/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.js
deleted file mode 100644
index 55747c0b3..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/MultipleNodes1/MultipleNodes1.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode1(n) {}
- RED.nodes.registerType("test-node-multiple-1a",TestNode1);
- function TestNode2(n) {}
- RED.nodes.registerType("test-node-multiple-1b",TestNode2);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.html
deleted file mode 100644
index abc823e8f..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.js
deleted file mode 100644
index cd3148a58..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/NestedNode.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode(n) {}
- RED.nodes.registerType("nested-node-1",TestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png
deleted file mode 100644
index e38f3914600901b736f5fa18786ee11be6d41c28..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 393
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6icy_X9x!n)NrJ90QsB+9+AZi
z3~X;em{G3O!W1YdS>hT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjT8d|Bb%p-
zV~9uR+N-+$hZ97Oeyp#Y$RU!&XX#m>@|$agvYL9Jz$O6}72y^gZVi>ZMeaH^t*Q|!
zLhVk<0xdko8zYVo#8M-LBBd8b>1kw|i?FO)bWqsy_rwQg27N4y
zeX6pqO$_Cex^^A7_NsS@+=bOASA^wN0&GKN(hlAguRU&q-
jTBY?`*L>xN+|S&+7B*edvmQhOgN?z{)z4*}Q$iB}+9!`i
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html
deleted file mode 100644
index ac9235d26..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js
deleted file mode 100644
index 8af249b14..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode(n) {}
- RED.nodes.registerType("should-not-load-1",TestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.html
deleted file mode 100644
index eb7c8a3f9..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.js
deleted file mode 100644
index 623e299b2..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/node_modules/ShouldNotLoad.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode(n) {}
- RED.nodes.registerType("should-not-load-2",TestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html
deleted file mode 100644
index 4212fd589..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js b/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js
deleted file mode 100644
index 5856adada..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode(n) {}
- RED.nodes.registerType("should-not-load-3",TestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.html b/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.html
deleted file mode 100644
index 97dbf1710..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.js b/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.js
deleted file mode 100644
index bfa3b65bd..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode1/TestNode1.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode(n) {}
- RED.nodes.registerType("test-node-1",TestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.html b/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.html
deleted file mode 100644
index 66b65909e..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js b/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js
deleted file mode 100644
index 1bf2fa6c9..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode2/TestNode2.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// A test node that exports a function which returns a resolving promise
-
-module.exports = function(RED) {
- return new Promise(function(resolve,reject) {
- function TestNode(n) {}
- RED.nodes.registerType("test-node-2",TestNode);
- resolve();
- });
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.html b/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.html
deleted file mode 100644
index 9a0f6f7ea..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js b/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js
deleted file mode 100644
index b9ee6a624..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode3/TestNode3.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// A test node that exports a function which returns a rejecting promise
-
-module.exports = function(RED) {
- return new Promise(function(resolve,reject) {
- reject("fail");
- });
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.html b/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.html
deleted file mode 100644
index 9a0f6f7ea..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.js b/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.js
deleted file mode 100644
index c31255852..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNode4/TestNode4.js
+++ /dev/null
@@ -1 +0,0 @@
-throw new Error("fail to require");
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/EmptyModule/file.txt b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/EmptyModule/file.txt
deleted file mode 100644
index 0ce8dcaed..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/EmptyModule/file.txt
+++ /dev/null
@@ -1 +0,0 @@
-This file exists just to ensure the parent directory is in the repository.
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.html
deleted file mode 100644
index 17483f7ca..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.js
deleted file mode 100644
index c79c2ceb6..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode(n) {}
- RED.nodes.registerType("test-node-mod-1",TestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.html
deleted file mode 100644
index a1f1b6c79..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.js
deleted file mode 100644
index d359fb3f2..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/TestNodeModule2.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- throw new Error("fail to load");
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
deleted file mode 100644
index e38f3914600901b736f5fa18786ee11be6d41c28..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 393
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6icy_X9x!n)NrJ90QsB+9+AZi
z3~X;em{G3O!W1YdS>hT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjT8d|Bb%p-
zV~9uR+N-+$hZ97Oeyp#Y$RU!&XX#m>@|$agvYL9Jz$O6}72y^gZVi>ZMeaH^t*Q|!
zLhVk<0xdko8zYVo#8M-LBBd8b>1kw|i?FO)bWqsy_rwQg27N4y
zeX6pqO$_Cex^^A7_NsS@+=bOASA^wN0&GKN(hlAguRU&q-
jTBY?`*L>xN+|S&+7B*edvmQhOgN?z{)z4*}Q$iB}+9!`i
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt
deleted file mode 100644
index 59a29af14..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-This file exists just to ensure the 'icons' directory is in the repository.
-TODO: a future test needs to ensure the right icon files are loaded - this
- directory can be used for that
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/package.json b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/package.json
deleted file mode 100644
index 8eba5b04b..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/TestNodeModule/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name" : "TestNodeModule",
- "version" : "0.0.1",
- "description" : "A test node module",
- "node-red" : {
- "nodes": {
- "TestNodeMod1": "TestNodeModule.js",
- "TestNodeMod2": "TestNodeModule2.js"
- }
- }
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.html
deleted file mode 100644
index 17483f7ca..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.js
deleted file mode 100644
index c79c2ceb6..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- function TestNode(n) {}
- RED.nodes.registerType("test-node-mod-1",TestNode);
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.html b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.html
deleted file mode 100644
index a1f1b6c79..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.js b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.js
deleted file mode 100644
index d359fb3f2..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/TestNodeModule2.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// A test node that exports a function
-module.exports = function(RED) {
- throw new Error("fail to load");
-}
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/icons/file.txt b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/icons/file.txt
deleted file mode 100644
index 59a29af14..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/icons/file.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-This file exists just to ensure the 'icons' directory is in the repository.
-TODO: a future test needs to ensure the right icon files are loaded - this
- directory can be used for that
diff --git a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/package.json b/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/package.json
deleted file mode 100644
index 4f9e46518..000000000
--- a/test/unit/@node-red/registry/lib/resources/local/TestNodeModule/node_modules/VersionMismatchModule/package.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name" : "VersionMismatchModule",
- "version" : "0.0.1",
- "description" : "A test node module",
- "node-red" : {
- "version": "100.0.0",
- "nodes": {
- "VersionMismatchMod1": "TestNodeModule.js",
- "VersionMismatchMod2": "TestNodeModule2.js"
- }
- }
-}
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/file.txt b/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/file.txt
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/test_icon.png b/test/unit/@node-red/registry/lib/resources/userDir/lib/icons/test_icon.png
deleted file mode 100644
index 4b6b7b5e9b10ec790348eb59f73bdac596e2f3b8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 163
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1$P6UK?yS)OQjEnx?oJHr&dIz4a@YcVLR^9L
z|NsA&-kg6IB%S2#?!wT)D(eB{a29w(76Vni0bxeDQVUa{AbW|YuPggKZdPtVo=;b%
zu>pm|JY5_^IIbrr*#Br`l>NUU`M`mYFm{Gnm$g4<{K@tLs$lSR^>bP0l+XkK5O^!s
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.html b/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.html
deleted file mode 100644
index f38a3a24d..000000000
--- a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-this should be filtered out
diff --git a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.js b/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.js
deleted file mode 100644
index c31255852..000000000
--- a/test/unit/@node-red/registry/lib/resources/userDir/nodes/TestNode5/TestNode5.js
+++ /dev/null
@@ -1 +0,0 @@
-throw new Error("fail to require");
diff --git a/test/unit/@node-red/registry/lib/subflow_spec.js b/test/unit/@node-red/registry/lib/subflow_spec.js
deleted file mode 100644
index 2aa7db203..000000000
--- a/test/unit/@node-red/registry/lib/subflow_spec.js
+++ /dev/null
@@ -1,3 +0,0 @@
-describe("red/nodes/registry/subflow",function() {
- it.skip("NEEDS TESTS");
-});
diff --git a/test/unit/@node-red/registry/lib/util_spec.js b/test/unit/@node-red/registry/lib/util_spec.js
deleted file mode 100644
index 7e94d4fe5..000000000
--- a/test/unit/@node-red/registry/lib/util_spec.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-const should = require("should");
-const sinon = require("sinon");
-
-const NR_TEST_UTILS = require("nr-test-utils");
-const registryUtil = NR_TEST_UTILS.require("@node-red/registry/lib/util");
-
-// Get the internal runtime api
-const runtime = NR_TEST_UTILS.require("@node-red/runtime")._;
-
-const i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-describe("red/nodes/registry/util",function() {
- describe("createNodeApi", function() {
- let i18n_;
- let registerType;
- let registerSubflow;
-
- before(function() {
- i18n_ = sinon.stub(i18n,"_").callsFake(function() {
- return Array.prototype.slice.call(arguments,0);
- })
- registerType = sinon.stub(runtime.nodes,"registerType");
- registerSubflow = sinon.stub(runtime.nodes,"registerSubflow");
- });
- after(function() {
- i18n_.restore();
- registerType.restore();
- registerSubflow.restore();
- })
-
- it("builds node-specific view of runtime api", function() {
- registryUtil.init(runtime);
- var result = registryUtil.createNodeApi({id: "my-node", namespace: "my-namespace"})
- // Need a better strategy here.
- // For now, validate the node-custom functions
-
- var message = result._("message");
- // This should prepend the node's namespace to the message
- message.should.eql([ 'my-namespace:message' ]);
-
- var nodeConstructor = () => {};
- var nodeOpts = {};
- result.nodes.registerType("type",nodeConstructor, nodeOpts);
- registerType.called.should.be.true();
- registerType.lastCall.args[0].should.eql("my-node")
- registerType.lastCall.args[1].should.eql("type")
- registerType.lastCall.args[2].should.eql(nodeConstructor)
- registerType.lastCall.args[3].should.eql(nodeOpts)
-
- var subflowDef = {};
- result.nodes.registerSubflow(subflowDef);
- registerSubflow.called.should.be.true();
- registerSubflow.lastCall.args[0].should.eql("my-node")
- registerSubflow.lastCall.args[1].should.eql(subflowDef)
-
- });
- });
- describe("checkModuleAllowed", function() {
- function checkList(module, version, allowList, denyList) {
- return registryUtil.checkModuleAllowed(
- module,
- version,
- registryUtil.parseModuleList(allowList),
- registryUtil.parseModuleList(denyList)
- )
- }
-
- it("allows module with no allow/deny list provided", function() {
- checkList("abc","1.2.3",[],[]).should.be.true();
- })
- it("defaults allow to * when only deny list is provided", function() {
- checkList("abc","1.2.3",["*"],["def"]).should.be.true();
- checkList("def","1.2.3",["*"],["def"]).should.be.false();
- })
- it("uses most specific matching rule", function() {
- checkList("abc","1.2.3",["ab*"],["a*"]).should.be.true();
- checkList("def","1.2.3",["d*"],["de*"]).should.be.false();
- })
- it("checks version string using semver rules", function() {
- // Deny
- checkList("abc","1.2.3",["abc@1.2.2"],["*"]).should.be.false();
- checkList("abc","1.2.3",["abc@1.2.4"],["*"]).should.be.false();
- checkList("abc","1.2.3",["abc@>1.2.3"],["*"]).should.be.false();
- checkList("abc","1.2.3",["abc@>=1.2.3"],["abc"]).should.be.false();
-
-
- checkList("node-red-contrib-foo","1.2.3",["*"],["*contrib*"]).should.be.false();
-
-
- // Allow
- checkList("abc","1.2.3",["abc@1.2.3"],["*"]).should.be.true();
- checkList("abc","1.2.3",["abc@<1.2.4"],["*"]).should.be.true();
- checkList("abc","1.2.3",["abc"],["abc@>1.2.3"]).should.be.true();
- checkList("abc","1.2.3",["abc"],["abc@<1.2.3||>1.2.3"]).should.be.true();
- checkList("node-red-contrib-foo","1.2.3",["*contrib*"],["*"]).should.be.true();
- })
-
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/api/comms_spec.js b/test/unit/@node-red/runtime/lib/api/comms_spec.js
deleted file mode 100644
index 0097f5ce8..000000000
--- a/test/unit/@node-red/runtime/lib/api/comms_spec.js
+++ /dev/null
@@ -1,321 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var comms = NR_TEST_UTILS.require("@node-red/runtime/lib/api/comms");
-var events = NR_TEST_UTILS.require("@node-red/util/lib/events");
-
-describe("runtime-api/comms", function() {
- describe("listens for events", function() {
- var messages = [];
- var clientConnection = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var eventHandlers = {};
- before(function(done) {
- sinon.stub(events,"removeListener").callsFake(function() {})
- sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
- comms.init({
- log: {
- trace: function(){}
- }
- })
- comms.addConnection({client: clientConnection}).then(done);
- })
- after(function(done) {
- comms.removeConnection({client: clientConnection}).then(done);
- events.removeListener.restore();
- events.on.restore();
- })
- afterEach(function() {
- messages = [];
- })
-
- it('runtime events',function(){
- eventHandlers.should.have.property('runtime-event');
- eventHandlers['runtime-event']({
- id: "my-event",
- payload: "my-payload"
- })
- messages.should.have.length(1);
- messages[0].should.have.property("topic","notification/my-event");
- messages[0].should.have.property("data","my-payload")
- })
- it('status events',function(){
- eventHandlers.should.have.property('node-status');
- eventHandlers['node-status']({
- id: "my-event",
- status: {text:"my-status",badProperty:"should be filtered"}
- })
- messages.should.have.length(1);
- messages[0].should.have.property("topic","status/my-event");
- messages[0].should.have.property("data");
- messages[0].data.should.have.property("text","my-status");
- messages[0].data.should.not.have.property("badProperty");
-
- })
- it('comms events',function(){
- eventHandlers.should.have.property('runtime-event');
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-topic");
- messages[0].should.have.property("data","my-payload")
- })
- });
- describe("manages connections", function() {
- var eventHandlers = {};
- var messages = [];
- var clientConnection1 = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var clientConnection2 = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- before(function() {
- sinon.stub(events,"removeListener").callsFake(function() {})
- sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
- comms.init({
- log: {
- trace: function(){}
- }
- })
- })
- after(function() {
- events.removeListener.restore();
- events.on.restore();
- })
- afterEach(function(done) {
- comms.removeConnection({client: clientConnection1}).then(function() {
- comms.removeConnection({client: clientConnection2}).then(done);
- });
- messages = [];
- })
- it('adds new connections',function(done){
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection1}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(1);
- comms.addConnection({client: clientConnection2}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(3);
- done();
- }).catch(done);
- });
- });
- it('removes connections',function(done){
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection1}).then(function() {
- comms.addConnection({client: clientConnection2}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(2);
- comms.removeConnection({client: clientConnection1}).then(function() {
- eventHandlers['comms']({
- topic: "my-topic",
- data: "my-payload"
- })
- messages.should.have.length(3);
- done();
- });
- }).catch(done);
- });
- })
- })
-
- describe("subscriptions", function() {
- var messages = [];
- var clientConnection = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var clientConnection2 = {
- send: function(topic,data) {
- messages.push({topic,data})
- }
- }
- var eventHandlers = {};
- before(function() {
- sinon.stub(events,"removeListener").callsFake(function() {})
- sinon.stub(events,"on").callsFake(function(evt,handler) { eventHandlers[evt] = handler })
- comms.init({
- log: {
- trace: function(){}
- }
- })
- })
- after(function() {
- events.removeListener.restore();
- events.on.restore();
- })
- afterEach(function(done) {
- messages = [];
- comms.removeConnection({client: clientConnection}).then(done);
- })
-
- it('subscribe triggers retained messages',function(done){
- eventHandlers['comms']({
- topic: "my-event",
- data: "my-payload",
- retain: true
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-event");
- messages[0].should.have.property("data","my-payload");
- done();
- });
- }).catch(done);
- })
- it('retains non-blank status message',function(done){
- eventHandlers['node-status']({
- id: "node1234",
- status: {text:"hello"}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","status/node1234");
- messages[0].should.have.property("data",{text:"hello", fill: undefined, shape: undefined});
- done();
- });
- }).catch(done);
- })
- it('does not retain blank status message',function(done){
- eventHandlers['node-status']({
- id: "node1234",
- status: {}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- messages.should.have.length(0);
- done();
- });
- }).catch(done);
- })
- it('does not send blank status if first status',function(done){
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- eventHandlers['node-status']({
- id: "node5678",
- status: {}
- })
- messages.should.have.length(0);
- done()
- })
- }).catch(done);
- });
- it('sends blank status if replacing retained',function(done){
- eventHandlers['node-status']({
- id: "node5678",
- status: {text:"hello"}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
- messages.should.have.length(1);
- eventHandlers['node-status']({
- id: "node5678",
- status: {}
- })
- messages.should.have.length(2);
- done()
- })
- }).catch(done);
- });
-
- it('does not retain initial status blank message',function(done){
- eventHandlers['node-status']({
- id: "my-event",
- status: {}
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-event");
- messages[0].should.have.property("data","my-payload");
- done();
- });
- }).catch(done);
- })
-
- it('retained messages get cleared',function(done) {
- eventHandlers['comms']({
- topic: "my-event",
- data: "my-payload",
- retain: true
- })
- messages.should.have.length(0);
- comms.addConnection({client: clientConnection}).then(function() {
- return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
- messages.should.have.length(1);
- messages[0].should.have.property("topic","my-event");
- messages[0].should.have.property("data","my-payload");
- // Now we have a retained message, clear it
- eventHandlers['comms']({
- topic: "my-event",
- data: "my-payload-cleared"
- });
- messages.should.have.length(2);
- messages[1].should.have.property("topic","my-event");
- messages[1].should.have.property("data","my-payload-cleared");
- // Now add a second client and subscribe - no message should arrive
- return comms.addConnection({client: clientConnection2}).then(function() {
- return comms.subscribe({client: clientConnection2, topic: "my-event"}).then(function() {
- messages.should.have.length(2);
- done();
- });
- });
- });
- }).catch(done);
- });
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/context_spec.js b/test/unit/@node-red/runtime/lib/api/context_spec.js
deleted file mode 100644
index bf23e9cc6..000000000
--- a/test/unit/@node-red/runtime/lib/api/context_spec.js
+++ /dev/null
@@ -1,353 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var context = NR_TEST_UTILS.require("@node-red/runtime/lib/api/context");
-
-var mockLog = () => ({
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc";}
-});
-
-var mockContext = function(contents) {
- return {
- get: function(key,store,callback) {
- if (contents.hasOwnProperty(store) && contents[store].hasOwnProperty(key)) {
- callback(null,contents[store][key]);
- } else {
- callback(null,undefined);
- }
- },
- set: function (key, value, store, callback) {
- if (contents.hasOwnProperty(store)) {
- if (!value) {
- delete contents[store][key];
- callback(null);
- }
- } else {
- callback("err store");
- }
- },
- keys: function (store, callback) {
- if (contents.hasOwnProperty(store)) {
- callback(null, Object.keys(contents[store]));
- } else {
- callback("err store");
- }
- }
- };
-};
-
-describe("runtime-api/context", function() {
- var globalContext, flowContext, nodeContext, contexts;
-
- beforeEach(function() {
- globalContext = { default: { abc: 111 }, file: { abc: 222 } };
- flowContext = { default: { abc: 333 }, file: { abc: 444 } };
- nodeContext = { default: { abc: 555 }, file: { abc: 666 } };
- contexts = {
- global: mockContext(globalContext),
- flow1: mockContext(flowContext)
- };
- context.init({
- nodes: {
- listContextStores: function() {
- return { default: 'default', stores: [ 'default', 'file' ] };
- },
- getContext: function(id) {
- return contexts[id];
- },
- getNode: function(id) {
- if (id === 'known') {
- return {
- context: function() { return mockContext(nodeContext); }
- };
- } else {
- return null;
- }
- }
- },
- settings: {
- functionGlobalContext: {
- fgc:1234
- }
- },
- log: mockLog()
- });
- });
-
- describe("getValue", function() {
- it('gets global value of default store', function() {
- return context.getValue({
- scope: 'global',
- id: undefined,
- store: undefined, // use default
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','111');
- result.should.have.property('format','number');
- });
- });
-
- it('gets global value of specified store', function() {
- return context.getValue({
- scope: 'global',
- id: undefined,
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','222');
- result.should.have.property('format','number');
- });
- });
-
- it('gets flow value of default store', function() {
- return context.getValue({
- scope: 'flow',
- id: 'flow1',
- store: undefined, // use default
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','333');
- result.should.have.property('format','number');
- });
- });
-
- it('gets flow value of specified store', function() {
- return context.getValue({
- scope: 'flow',
- id: 'flow1',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','444');
- result.should.have.property('format','number');
- });
- });
-
- it('gets node value of default store', function() {
- return context.getValue({
- scope: 'node',
- id: 'known',
- store: undefined, // use default
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','555');
- result.should.have.property('format','number');
- });
- });
-
- it('gets node value of specified store', function() {
- return context.getValue({
- scope: 'node',
- id: 'known',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.have.property('msg','666');
- result.should.have.property('format','number');
- });
- });
-
- it('404s for unknown store', function(done) {
- context.getValue({
- scope: 'global',
- id: undefined,
- store: 'unknown',
- key: 'abc'
- }).then(function(result) {
- done("getValue for unknown store should not resolve");
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- });
- });
-
- it('gets all global value properties', function() {
- return context.getValue({
- scope: 'global',
- id: undefined,
- store: undefined, // use default
- key: undefined, //
- }).then(function(result) {
- result.should.eql({
- default: { abc: { msg: '111', format: 'number' } },
- file: { abc: { msg: '222', format: 'number' } }
- });
- });
- });
-
- it('gets all flow value properties', function() {
- return context.getValue({
- scope: 'flow',
- id: 'flow1',
- store: undefined, // use default
- key: undefined, //
- }).then(function(result) {
- result.should.eql({
- default: { abc: { msg: '333', format: 'number' } },
- file: { abc: { msg: '444', format: 'number' } }
- });
- });
- });
-
- it('gets all node value properties', function() {
- return context.getValue({
- scope: 'node',
- id: 'known',
- store: undefined, // use default
- key: undefined, //
- }).then(function(result) {
- result.should.eql({
- default: { abc: { msg: '555', format: 'number' } },
- file: { abc: { msg: '666', format: 'number' } }
- });
- });
- });
-
- it('gets empty object when specified context doesn\'t exist', function() {
- return context.getValue({
- scope: 'node',
- id: 'non-existent',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- result.should.be.an.Object();
- result.should.be.empty();
- });
- });
- });
-
- describe("delete", function () {
- it('deletes global value of default store', function () {
- return context.delete({
- scope: 'global',
- id: undefined,
- store: undefined, // use default
- key: 'abc'
- }).then(function () {
- globalContext.should.eql({
- default: {}, file: { abc: 222 }
- });
- });
- });
-
- it('deletes global value of specified store', function () {
- return context.delete({
- scope: 'global',
- id: undefined,
- store: 'file',
- key: 'abc'
- }).then(function () {
- globalContext.should.eql({
- default: { abc: 111 }, file: {}
- });
- });
- });
-
- it('deletes flow value of default store', function () {
- return context.delete({
- scope: 'flow',
- id: 'flow1',
- store: undefined, // use default
- key: 'abc'
- }).then(function () {
- flowContext.should.eql({
- default: {}, file: { abc: 444 }
- });
- });
- });
-
- it('deletes flow value of specified store', function () {
- return context.delete({
- scope: 'flow',
- id: 'flow1',
- store: 'file',
- key: 'abc'
- }).then(function () {
- flowContext.should.eql({
- default: { abc: 333 }, file: {}
- });
- });
- });
-
- it('deletes node value of default store', function () {
- return context.delete({
- scope: 'node',
- id: 'known',
- store: undefined, // use default
- key: 'abc'
- }).then(function () {
- nodeContext.should.eql({
- default: {}, file: { abc: 666 }
- });
- });
- });
-
- it('deletes node value of specified store', function () {
- return context.delete({
- scope: 'node',
- id: 'known',
- store: 'file',
- key: 'abc'
- }).then(function () {
- nodeContext.should.eql({
- default: { abc: 555 }, file: {}
- });
- });
- });
-
- it('does nothing when specified context doesn\'t exist', function() {
- return context.delete({
- scope: 'node',
- id: 'non-existent',
- store: 'file',
- key: 'abc'
- }).then(function(result) {
- should.not.exist(result);
- nodeContext.should.eql({
- default: { abc: 555 }, file: { abc: 666 }
- });
- });
- });
-
- it('404s for unknown store', function (done) {
- context.delete({
- scope: 'global',
- id: undefined,
- store: 'unknown',
- key: 'abc'
- }).then(function () {
- done("delete for unknown store should not resolve");
- }).catch(function (err) {
- err.should.have.property('code', 'not_found');
- err.should.have.property('status', 404);
- done();
- });
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/api/flows_spec.js b/test/unit/@node-red/runtime/lib/api/flows_spec.js
deleted file mode 100644
index 9062ef52f..000000000
--- a/test/unit/@node-red/runtime/lib/api/flows_spec.js
+++ /dev/null
@@ -1,430 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/api/flows")
-
-var mockLog = () => ({
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-})
-
-describe("runtime-api/flows", function() {
- describe("getFlows", function() {
- it("returns the current flow configuration", function(done) {
- flows.init({
- log: mockLog(),
- flows: {
- getFlows: function() { return [1,2,3] }
- }
- });
- flows.getFlows({}).then(function(result) {
- result.should.eql([1,2,3]);
- done();
- }).catch(done);
- });
- });
-
- describe("setFlows", function() {
- var setFlows;
- var loadFlows;
- var reloadError = false;
- beforeEach(function() {
- setFlows = sinon.spy(function(flows,credentials,type) {
- if (flows[0] === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve("newRev");
- });
- loadFlows = sinon.spy(function() {
- if (!reloadError) {
- return Promise.resolve("newLoadRev");
- } else {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- })
- flows.init({
- log: mockLog(),
- flows: {
- getFlows: function() { return {rev:"currentRev",flows:[]} },
- setFlows: setFlows,
- loadFlows: loadFlows
- }
- })
-
- })
- it("defaults to full deploy", function(done) {
- flows.setFlows({
- flows: {flows:[4,5,6]}
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[2].should.eql("full");
- done();
- }).catch(done);
- });
- it("includes credentials when part of the request", function(done) {
- flows.setFlows({
- flows: {flows:[4,5,6], credentials: {$:"creds"}},
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[1].should.eql({$:"creds"});
- setFlows.lastCall.args[2].should.eql("full");
- done();
- }).catch(done);
- });
- it("passes through other deploy types", function(done) {
- flows.setFlows({
- deploymentType: "nodes",
- flows: {flows:[4,5,6]}
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[2].should.eql("nodes");
- done();
- }).catch(done);
- });
- it("triggers a flow reload", function(done) {
- flows.setFlows({
- deploymentType: "reload"
- }).then(function(result) {
- result.should.eql({rev:"newLoadRev"});
- setFlows.called.should.be.false();
- loadFlows.called.should.be.true();
- done();
- }).catch(done);
- });
- it("allows update when revision matches", function(done) {
- flows.setFlows({
- deploymentType: "nodes",
- flows: {flows:[4,5,6],rev:"currentRev"}
- }).then(function(result) {
- result.should.eql({rev:"newRev"});
- setFlows.called.should.be.true();
- setFlows.lastCall.args[0].should.eql([4,5,6]);
- setFlows.lastCall.args[2].should.eql("nodes");
- done();
- }).catch(done);
- });
- it("rejects update when revision does not match", function(done) {
- flows.setFlows({
- deploymentType: "nodes",
- flows: {flows:[4,5,6],rev:"notTheCurrentRev"}
- }).then(function(result) {
- done(new Error("Did not reject rev mismatch"));
- }).catch(function(err) {
- err.should.have.property('code','version_mismatch');
- err.should.have.property('status',409);
- done();
- }).catch(done);
- });
- it("rejects when reload fails",function(done) {
- reloadError = true;
- flows.setFlows({
- deploymentType: "reload"
- }).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- done();
- }).catch(done);
- });
- it("rejects when update fails",function(done) {
- flows.setFlows({
- deploymentType: "full",
- flows: {flows:["error",5,6]}
- }).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- done();
- }).catch(done);
- });
- });
-
- describe("addFlow", function() {
- var addFlow;
- beforeEach(function() {
- addFlow = sinon.spy(function(flow) {
- if (flow === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve("newId");
- });
- flows.init({
- log: mockLog(),
- flows: {
- addFlow: addFlow
- }
- });
- })
- it("adds a flow", function(done) {
- flows.addFlow({flow:{a:"123"}}).then(function(id) {
- addFlow.called.should.be.true();
- addFlow.lastCall.args[0].should.eql({a:"123"});
- id.should.eql("newId");
- done()
- }).catch(done);
- });
- it("rejects when add fails", function(done) {
- flows.addFlow({flow:"error"}).then(function(id) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- done();
- }).catch(done);
- });
- });
- describe("getFlow", function() {
- var getFlow;
- beforeEach(function() {
- getFlow = sinon.spy(function(flow) {
- if (flow === "unknown") {
- return null;
- }
- return [1,2,3];
- });
- flows.init({
- log: mockLog(),
- flows: {
- getFlow: getFlow
- }
- });
- })
- it("gets a flow", function(done) {
- flows.getFlow({id:"123"}).then(function(flow) {
- flow.should.eql([1,2,3]);
- done()
- }).catch(done);
- });
- it("rejects when flow not found", function(done) {
- flows.getFlow({id:"unknown"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
-
- describe("updateFlow", function() {
- var updateFlow;
- beforeEach(function() {
- updateFlow = sinon.spy(function(id,flow) {
- if (id === "unknown") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = 404;
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (id === "error") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve();
- });
- flows.init({
- log: mockLog(),
- flows: {
- updateFlow: updateFlow
- }
- });
- })
- it("updates a flow", function(done) {
- flows.updateFlow({id:"123",flow:[1,2,3]}).then(function(id) {
- id.should.eql("123");
- updateFlow.called.should.be.true();
- updateFlow.lastCall.args[0].should.eql("123");
- updateFlow.lastCall.args[1].should.eql([1,2,3]);
- done()
- }).catch(done);
- });
- it("rejects when flow not found", function(done) {
- flows.updateFlow({id:"unknown"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- it("rejects when update fails", function(done) {
- flows.updateFlow({id:"error"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
-
- describe("deleteFlow", function() {
- var removeFlow;
- beforeEach(function() {
- removeFlow = sinon.spy(function(flow) {
- if (flow === "unknown") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = 404;
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (flow === "error") {
- var err = new Error();
- // TODO: quirk of internal api - uses .code for .status
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve();
- });
- flows.init({
- log: mockLog(),
- flows: {
- removeFlow: removeFlow
- }
- });
- })
- it("deletes a flow", function(done) {
- flows.deleteFlow({id:"123"}).then(function() {
- removeFlow.called.should.be.true();
- removeFlow.lastCall.args[0].should.eql("123");
- done()
- }).catch(done);
- });
- it("rejects when flow not found", function(done) {
- flows.deleteFlow({id:"unknown"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- it("rejects when delete fails", function(done) {
- flows.deleteFlow({id:"error"}).then(function(flow) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getNodeCredentials", function() {
- beforeEach(function() {
- flows.init({
- log: mockLog(),
- nodes: {
- getCredentials: function(id) {
- if (id === "unknown") {
- return undefined;
- } else if (id === "known") {
- return {
- username: "abc",
- password: "123"
- }
- } else if (id === "known2") {
- return {
- username: "abc",
- password: ""
- }
- } else {
- return {};
- }
- },
- getCredentialDefinition: function(type) {
- if (type === "node") {
- return {
- username: {type:"text"},
- password: {type:"password"}
- }
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns an empty object for an unknown node", function(done) {
- flows.getNodeCredentials({id:"unknown", type:"node"}).then(function(result) {
- result.should.eql({});
- done();
- }).catch(done);
- });
- it("gets the filtered credentials for a known node with password", function(done) {
- flows.getNodeCredentials({id:"known", type:"node"}).then(function(result) {
- result.should.eql({
- username: "abc",
- has_password: true
- });
- done();
- }).catch(done);
- });
- it("gets the filtered credentials for a known node without password", function(done) {
- flows.getNodeCredentials({id:"known2", type:"node"}).then(function(result) {
- result.should.eql({
- username: "abc",
- has_password: false
- });
- done();
- }).catch(done);
- });
- it("gets the empty credentials for a known node without a registered definition", function(done) {
- flows.getNodeCredentials({id:"known2", type:"unknown-type"}).then(function(result) {
- result.should.eql({});
- done();
- }).catch(done);
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/index_spec.js b/test/unit/@node-red/runtime/lib/api/index_spec.js
deleted file mode 100644
index ecedf22ef..000000000
--- a/test/unit/@node-red/runtime/lib/api/index_spec.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var index = NR_TEST_UTILS.require("@node-red/runtime/lib/api/index");
-
-
-describe("runtime-api/index", function() {
- before(function() {
- ["comms","flows","nodes","settings","library","projects"].forEach(n => {
- sinon.stub(NR_TEST_UTILS.require(`@node-red/runtime/lib/api/${n}`),"init").callsFake(()=>{});
- })
- });
- after(function() {
- ["comms","flows","nodes","settings","library","projects"].forEach(n => {
- NR_TEST_UTILS.require(`@node-red/runtime/lib/api/${n}`).init.restore()
- })
- })
- it('isStarted', function(done) {
- index.init({
- isStarted: ()=>true
- });
- index.isStarted({}).then(function(started) {
- started.should.be.true();
- done();
- }).catch(done);
- })
-
- it('isStarted', function(done) {
- index.init({
- version: ()=>"1.2.3.4"
- });
- index.version({}).then(function(version) {
- version.should.eql("1.2.3.4");
- done();
- }).catch(done);
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/library_spec.js b/test/unit/@node-red/runtime/lib/api/library_spec.js
deleted file mode 100644
index 3fa5291d2..000000000
--- a/test/unit/@node-red/runtime/lib/api/library_spec.js
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var library = NR_TEST_UTILS.require("@node-red/runtime/lib/api/library")
-
-var mockLog = {
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-}
-
-describe("runtime-api/library", function() {
- describe("getEntry", function() {
- before(function() {
- library.init({
- log: mockLog,
- library: {
- getEntry: function(library, type,path) {
- if (type === "known") {
- return Promise.resolve("known");
- } else if (type === "forbidden") {
- var err = new Error("forbidden");
- err.code = "forbidden";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "not_found") {
- var err = new Error("forbidden");
- err.code = "not_found";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "error") {
- var err = new Error("error");
- err.code = "unknown_error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "blank") {
- return Promise.reject();
- }
- }
- }
- })
- })
- it("returns a known entry", function(done) {
- library.getEntry({library: "local",type: "known", path: "/abc"}).then(function(result) {
- result.should.eql("known")
- done();
- }).catch(done)
- })
- it("rejects a forbidden entry", function(done) {
- library.getEntry({library: "local",type: "forbidden", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","forbidden");
- err.should.have.property("status",403);
- done();
- }).catch(done)
- })
- it("rejects an unknown entry", function(done) {
- library.getEntry({library: "local",type: "not_found", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","not_found");
- err.should.have.property("status",404);
- done();
- }).catch(done)
- })
- it("rejects a blank (unknown) entry", function(done) {
- library.getEntry({library: "local",type: "blank", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","not_found");
- err.should.have.property("status",404);
- done();
- }).catch(done)
- })
- it("rejects unexpected error", function(done) {
- library.getEntry({library: "local",type: "error", path: "/abc"}).then(function(result) {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("status",400);
- done();
- }).catch(done)
- })
- })
- describe("saveEntry", function() {
- var opts;
- before(function() {
- library.init({
- log: mockLog,
- library: {
- saveEntry: function(library,type,path,meta,body) {
- opts = {type,path,meta,body};
- if (type === "known") {
- return Promise.resolve();
- } else if (type === "forbidden") {
- var err = new Error("forbidden");
- err.code = "forbidden";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else if (type === "not_found") {
- var err = new Error("forbidden");
- err.code = "not_found";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- }
- }
- }
- })
- })
-
- it("saves an entry", function(done) {
- library.saveEntry({library: "local",type: "known", path: "/abc", meta: {a:1}, body:"123"}).then(function() {
- opts.should.have.property("type","known");
- opts.should.have.property("path","/abc");
- opts.should.have.property("meta",{a:1});
- opts.should.have.property("body","123");
- done();
- }).catch(done)
- })
- it("rejects a forbidden entry", function(done) {
- library.saveEntry({library: "local",type: "forbidden", path: "/abc", meta: {a:1}, body:"123"}).then(function() {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("code","forbidden");
- err.should.have.property("status",403);
- done();
- }).catch(done)
- })
- it("rejects an unknown entry", function(done) {
- library.saveEntry({library: "local",type: "not_found", path: "/abc", meta: {a:1}, body:"123"}).then(function() {
- done(new Error("did not reject"));
- }).catch(function(err) {
- err.should.have.property("status",400);
- done();
- }).catch(done)
- })
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/nodes_spec.js b/test/unit/@node-red/runtime/lib/api/nodes_spec.js
deleted file mode 100644
index 60c6d9edd..000000000
--- a/test/unit/@node-red/runtime/lib/api/nodes_spec.js
+++ /dev/null
@@ -1,1005 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var nodes = NR_TEST_UTILS.require("@node-red/runtime/lib/api/nodes")
-
-var mockLog = () => ({
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-})
-
-describe("runtime-api/nodes", function() {
- describe("getNodeInfo", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeInfo: function(id) {
- if (id === "known") {
- return {id:"known"};
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns node info", function(done) {
- nodes.getNodeInfo({id:"known"}).then(function(result) {
- result.should.eql({id:"known"});
- done();
- }).catch(done);
- });
- it("returns 404 if node not known", function(done) {
- nodes.getNodeInfo({id:"unknown"}).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
- describe("getNodeList", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeList: function() {
- return [1,2,3];
- }
- }
- });
- })
- it("returns node list", function(done) {
- nodes.getNodeList({}).then(function(result) {
- result.should.eql([1,2,3]);
- done();
- }).catch(done);
- });
- });
-
- describe("getNodeConfig", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeConfig: function(id,lang) {
- if (id === "known") {
- return id+lang;
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns node config", function(done) {
- nodes.getNodeConfig({id:"known",lang:'lang'}).then(function(result) {
- result.should.eql("knownlang");
- done();
- }).catch(done);
- });
- it("returns 404 if node not known", function(done) {
- nodes.getNodeConfig({id:"unknown",lang:'lang'}).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
-
- describe("getNodeConfigs", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getNodeConfigs: function(lang) {
- return lang;
- }
- }
- });
- })
- it("returns all node configs", function(done) {
- nodes.getNodeConfigs({lang:'lang'}).then(function(result) {
- result.should.eql("lang");
- done();
- }).catch(done);
- });
- });
-
- describe("getModuleInfo", function() {
- beforeEach(function() {
- nodes.init({
- log: mockLog(),
- nodes: {
- getModuleInfo: function(id) {
- if (id === "known") {
- return {module:"known"};
- } else {
- return null;
- }
- }
- }
- });
- })
- it("returns node info", function(done) {
- nodes.getModuleInfo({module:"known"}).then(function(result) {
- result.should.eql({module:"known"});
- done();
- }).catch(done);
- });
- it("returns 404 if node not known", function(done) {
- nodes.getModuleInfo({module:"unknown"}).then(function(result) {
- done(new Error("Did not return internal error"));
- }).catch(function(err) {
- err.should.have.property('code','not_found');
- err.should.have.property('status',404);
- done();
- }).catch(done);
- });
- });
-
- describe.skip("addModule", function() {});
- describe.skip("removeModule", function() {});
- describe.skip("setModuleState", function() {});
- describe.skip("setNodeSetState", function() {});
-
- describe.skip("getModuleCatalogs", function() {});
- describe.skip("getModuleCatalog", function() {});
-
- describe.skip("getIconList", function() {});
- describe.skip("getIcon", function() {});
-
-
-});
-
-/*
-var should = require("should");
-var request = require('supertest');
-var express = require('express');
-var bodyParser = require('body-parser');
-var sinon = require('sinon');
-
-var nodes = require("../../../../red/api/admin/nodes");
-var apiUtil = require("../../../../red/api/util");
-
-describe("api/admin/nodes", function() {
-
- var app;
- function initNodes(runtime) {
- runtime.log = {
- audit:function(e){},//console.log(e)},
- _:function(){},
- info: function(){},
- warn: function(){}
- }
- runtime.events = {
- emit: function(){}
- }
- nodes.init(runtime);
-
- }
-
- before(function() {
- app = express();
- app.use(bodyParser.json());
- app.get("/nodes",nodes.getAll);
- app.post("/nodes",nodes.post);
- app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.getModule);
- app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
- app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
- app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
- app.get("/getIcons",nodes.getIcons);
- app.delete("/nodes/:id",nodes.delete);
- sinon.stub(apiUtil,"determineLangFromHeaders").callsFake(function() {
- return "en-US";
- });
- });
- after(function() {
- apiUtil.determineLangFromHeaders.restore();
- })
-
- describe('get nodes', function() {
- it('returns node list', function(done) {
- initNodes({
- nodes:{
- getNodeList: function() {
- return [1,2,3];
- }
- }
- });
- request(app)
- .get('/nodes')
- .set('Accept', 'application/json')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.be.an.Array();
- res.body.should.have.lengthOf(3);
- done();
- });
- });
-
- it('returns node configs', function(done) {
- initNodes({
- nodes:{
- getNodeConfigs: function() {
- return "";
- }
- },
- i18n: {
- determineLangFromHeaders: function(){}
- }
- });
- request(app)
- .get('/nodes')
- .set('Accept', 'text/html')
- .expect(200)
- .expect("")
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns node module info', function(done) {
- initNodes({
- nodes:{
- getModuleInfo: function(id) {
- return {"node-red":{name:"node-red"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-red')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- done();
- });
- });
-
- it('returns 404 for unknown module', function(done) {
- initNodes({
- nodes:{
- getModuleInfo: function(id) {
- return {"node-red":{name:"node-red"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-blue')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns individual node info', function(done) {
- initNodes({
- nodes:{
- getNodeInfo: function(id) {
- return {"node-red/123":{id:"node-red/123"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-red/123')
- .set('Accept', 'application/json')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","node-red/123");
- done();
- });
- });
-
- it('returns individual node configs', function(done) {
- initNodes({
- nodes:{
- getNodeConfig: function(id) {
- return {"node-red/123":""}[id];
- }
- },
- i18n: {
- determineLangFromHeaders: function(){}
- }
- });
- request(app)
- .get('/nodes/node-red/123')
- .set('Accept', 'text/html')
- .expect(200)
- .expect("")
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 404 for unknown node', function(done) {
- initNodes({
- nodes:{
- getNodeInfo: function(id) {
- return {"node-red/123":{id:"node-red/123"}}[id];
- }
- }
- });
- request(app)
- .get('/nodes/node-red/456')
- .set('Accept', 'application/json')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
- });
-
- describe('install', function() {
-
- it('returns 400 if settings are unavailable', function(done) {
- initNodes({
- settings:{available:function(){return false}}
- });
- request(app)
- .post('/nodes')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 400 if request is invalid', function(done) {
- initNodes({
- settings:{available:function(){return true}}
- });
- request(app)
- .post('/nodes')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- describe('by module', function() {
- it('installs the module and returns module info', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null; },
- installModule: function() {
- return Promise.resolve({
- name:"foo",
- nodes:[{id:"123"}]
- });
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","foo");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("id","123");
- done();
- });
- });
-
- it('fails the install if already installed', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return {nodes:{id:"123"}}; },
- installModule: function() {
- return Promise.resolve({id:"123"});
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('fails the install if module error', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null },
- installModule: function() {
- return Promise.reject(new Error("test error"));
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Error: test error");
- done();
- });
- });
- it('fails the install if module not found', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null },
- installModule: function() {
- var err = new Error("test error");
- err.code = 404;
- return Promise.reject(err);
- }
- }
- });
- request(app)
- .post('/nodes')
- .send({module: 'foo'})
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
- });
- });
- describe('delete', function() {
- it('returns 400 if settings are unavailable', function(done) {
- initNodes({
- settings:{available:function(){return false}}
- });
-
- request(app)
- .del('/nodes/123')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- describe('by module', function() {
- it('uninstalls the module', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return {nodes:[{id:"123"}]} },
- getNodeInfo: function() { return null },
- uninstallModule: function() { return Promise.resolve({id:"123"});}
- }
- });
- request(app)
- .del('/nodes/foo')
- .expect(204)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('fails the uninstall if the module is not installed', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null },
- getNodeInfo: function() { return null }
- }
- });
- request(app)
- .del('/nodes/foo')
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('fails the uninstall if the module is not installed', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return {nodes:[{id:"123"}]} },
- getNodeInfo: function() { return null },
- uninstallModule: function() { return Promise.reject(new Error("test error"));}
- }
- });
- request(app)
- .del('/nodes/foo')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Error: test error");
- done();
- });
- });
- });
-
- });
-
- describe('enable/disable', function() {
- it('returns 400 if settings are unavailable', function(done) {
- initNodes({
- settings:{available:function(){return false}}
- });
- request(app)
- .put('/nodes/123')
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 400 for invalid node payload', function(done) {
- initNodes({
- settings:{available:function(){return true}}
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Invalid request");
- done();
- });
- });
-
- it('returns 400 for invalid module payload', function(done) {
- initNodes({
- settings:{available:function(){return true}}
- });
- request(app)
- .put('/nodes/foo')
- .send({})
- .expect(400)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("message","Invalid request");
-
- done();
- });
- });
-
- it('returns 404 for unknown node', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return null }
- }
- });
-
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:false})
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('returns 404 for unknown module', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function(id) { return null }
- }
- });
-
- request(app)
- .put('/nodes/node-blue')
- .send({enabled:false})
- .expect(404)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- done();
- });
- });
-
- it('enables disabled node', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: false} },
- enableNode: function() { return Promise.resolve({id:"123",enabled: true,types:['a']}); }
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:true})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",true);
-
- done();
- });
- });
-
- it('disables enabled node', function(done) {
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: true} },
- disableNode: function() { return Promise.resolve({id:"123",enabled: false,types:['a']}); }
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:false})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",false);
-
- done();
- });
- });
-
- describe('no-ops if already in the right state', function() {
- function run(state,done) {
- var enableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: true,types:['a']}) });
- var disableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: false,types:['a']}) });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: state} },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.false();
- disableNodeCalled.should.be.false();
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
-
- describe('does not no-op if err on node', function() {
- function run(state,done) {
- var enableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: true,types:['a']}) });
- var disableNode = sinon.spy(function() { return Promise.resolve({id:"123",enabled: false,types:['a']}) });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getNodeInfo: function() { return {id:"123",enabled: state, err:"foo"} },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
- request(app)
- .put('/nodes/node-red/foo')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.equal(state);
- disableNodeCalled.should.be.equal(!state);
- res.body.should.have.property("id","123");
- res.body.should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
-
- it('enables disabled module', function(done) {
- var n1 = {id:"123",enabled:false,types:['a']};
- var n2 = {id:"456",enabled:false,types:['b']};
- var enableNode = sinon.stub();
- enableNode.onFirstCall().returns((function() {
- n1.enabled = true;
- return Promise.resolve(n1);
- })());
- enableNode.onSecondCall().returns((function() {
- n2.enabled = true;
- return Promise.resolve(n2);
- })());
- enableNode.returns(null);
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
- enableNode: enableNode
- }
- });
-
- request(app)
- .put('/nodes/node-red')
- .send({enabled:true})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",true);
- res.body.nodes[1].should.have.property("enabled",true);
-
- done();
- });
- });
-
- it('disables enabled module', function(done) {
- var n1 = {id:"123",enabled:true,types:['a']};
- var n2 = {id:"456",enabled:true,types:['b']};
- var disableNode = sinon.stub();
- disableNode.onFirstCall().returns((function() {
- n1.enabled = false;
- return Promise.resolve(n1);
- })());
- disableNode.onSecondCall().returns((function() {
- n2.enabled = false;
- return Promise.resolve(n2);
- })());
- disableNode.returns(null);
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[n1, n2]} },
- disableNode: disableNode
- }
- });
-
- request(app)
- .put('/nodes/node-red')
- .send({enabled:false})
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",false);
- res.body.nodes[1].should.have.property("enabled",false);
-
- done();
- });
- });
-
- describe('no-ops if a node in module already in the right state', function() {
- function run(state,done) {
- var node = {id:"123",enabled:state,types:['a']};
- var enableNode = sinon.spy(function(id) {
- node.enabled = true;
- return Promise.resolve(node);
- });
- var disableNode = sinon.spy(function(id) {
- node.enabled = false;
- return Promise.resolve(node);
- });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[node]}; },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
- request(app)
- .put('/nodes/node-red')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.false();
- disableNodeCalled.should.be.false();
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
-
- describe('does not no-op if err on a node in module', function() {
- function run(state,done) {
- var node = {id:"123",enabled:state,types:['a'],err:"foo"};
- var enableNode = sinon.spy(function(id) {
- node.enabled = true;
- return Promise.resolve(node);
- });
- var disableNode = sinon.spy(function(id) {
- node.enabled = false;
- return Promise.resolve(node);
- });
-
- initNodes({
- settings:{available:function(){return true}},
- nodes:{
- getModuleInfo: function() { return {name:"node-red", nodes:[node]}; },
- enableNode: enableNode,
- disableNode: disableNode
- }
- });
-
- request(app)
- .put('/nodes/node-red')
- .send({enabled:state})
- .expect(200)
- .end(function(err,res) {
- var enableNodeCalled = enableNode.called;
- var disableNodeCalled = disableNode.called;
- if (err) {
- throw err;
- }
- enableNodeCalled.should.be.equal(state);
- disableNodeCalled.should.be.equal(!state);
- res.body.should.have.property("name","node-red");
- res.body.should.have.property("nodes");
- res.body.nodes[0].should.have.property("enabled",state);
-
- done();
- });
- }
- it('already enabled', function(done) {
- run(true,done);
- });
- it('already disabled', function(done) {
- run(false,done);
- });
- });
- });
-
- describe('get icons', function() {
- it('returns icon list', function(done) {
- initNodes({
- nodes:{
- getNodeIcons: function() {
- return {"module":["1.png","2.png","3.png"]};
- }
- }
- });
- request(app)
- .get('/getIcons')
- .expect(200)
- .end(function(err,res) {
- if (err) {
- throw err;
- }
- console.log(res.body);
- res.body.should.have.property("module");
- res.body.module.should.be.an.Array();
- res.body.module.should.have.lengthOf(3);
- done();
- });
- });
- });
-});
-
-*/
diff --git a/test/unit/@node-red/runtime/lib/api/plugins_spec.js b/test/unit/@node-red/runtime/lib/api/plugins_spec.js
deleted file mode 100644
index 7ae6d8286..000000000
--- a/test/unit/@node-red/runtime/lib/api/plugins_spec.js
+++ /dev/null
@@ -1,68 +0,0 @@
-const should = require("should");
-const sinon = require("sinon");
-
-const NR_TEST_UTILS = require("nr-test-utils");
-const plugins = NR_TEST_UTILS.require("@node-red/runtime/lib/api/plugins")
-
-const mockLog = () => ({
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-})
-
-describe("runtime-api/plugins", function() {
- const pluginList = [{id:"one",module:'test-module'},{id:"two",module:"node-red"}];
- const pluginConfigs = "123";
-
- describe("getPluginList", function() {
- it("gets the plugin list", function() {
- plugins.init({
- log: mockLog(),
- plugins: {
- getPluginList: function() { return pluginList}
- }
- });
- return plugins.getPluginList({}).then(function(result) {
- result.should.eql(pluginList);
- })
- });
- });
- describe("getPluginConfigs", function() {
- it("gets the plugin configs", function() {
- plugins.init({
- log: mockLog(),
- plugins: {
- getPluginConfigs: function() { return pluginConfigs}
- }
- });
- return plugins.getPluginConfigs({}).then(function(result) {
- result.should.eql(pluginConfigs);
- })
- });
- });
- describe("getPluginCatalogs", function() {
- it("gets the plugin catalogs", function() {
- plugins.init({
- log: mockLog(),
- plugins: {
- getPluginList: function() { return pluginList}
- },
- i18n: {
- i: {
- changeLanguage: function(lang,done) { done && done() },
- getResourceBundle: function(lang, id) { return {lang,id}}
- }
- }
- });
- return plugins.getPluginCatalogs({lang: "en-US"}).then(function(result) {
- JSON.stringify(result).should.eql(JSON.stringify({ one: { lang: "en-US", id: "one" } }))
- })
- });
- });
-
-});
\ No newline at end of file
diff --git a/test/unit/@node-red/runtime/lib/api/projects_spec.js b/test/unit/@node-red/runtime/lib/api/projects_spec.js
deleted file mode 100644
index 2fe7ca221..000000000
--- a/test/unit/@node-red/runtime/lib/api/projects_spec.js
+++ /dev/null
@@ -1,1170 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var projects = NR_TEST_UTILS.require("@node-red/runtime/lib/api/projects")
-
-var mockLog = () => ({
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-})
-
-describe("runtime-api/settings", function() {
- describe("available", function() {
- it("resolves true if projects available", function(done) {
- projects.init({
- storage: {
- projects: {}
- }
- });
- projects.available().then(function(result) {
- result.should.be.true();
- done();
- }).catch(done);
- })
- it("resolves false if projects unavailable", function(done) {
- projects.init({
- storage: {
- }
- });
- projects.available().then(function(result) {
- result.should.be.false();
- done();
- }).catch(done);
- })
-
- });
- describe("listProjects", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- listProjects: sinon.spy(function(user) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve([1,2,3]);
- }
- }),
- getActiveProject: function(user) {
- if (user === "noActive") {
- return null;
- }
- return {name:"aProject"};
- }
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("lists the projects, without an active project", function(done) {
- projects.listProjects({user:"noActive"}).then(function(result) {
- result.should.have.property('projects',[1,2,3]);
- result.should.not.have.property('active');
- done();
- }).catch(done);
- });
- it("lists the projects, with an active project", function(done) {
- projects.listProjects({user:"foo"}).then(function(result) {
- result.should.have.property('projects',[1,2,3]);
- result.should.have.property('active','aProject');
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.listProjects({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- err.should.have.property('status',400);
- done();
- }).catch(done);
- });
-
- });
- describe("createProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- createProject: sinon.spy(function(user,project) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve(project);
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("create project", function(done) {
- projects.createProject({user:"known",project:{a:1}}).then(function(result) {
- result.should.eql({a:1});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.createProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("initialiseProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- initialiseProject: sinon.spy(function(user,id,project) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({id,project});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("intialise project", function(done) {
- projects.initialiseProject({user:"known",id:123, project:{a:1}}).then(function(result) {
- result.should.eql({id:123, project:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.initialiseProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getActiveProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getActiveProject: sinon.spy(function(user) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve("123");
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("returns active project", function(done) {
- projects.getActiveProject({user:"known"}).then(function(result) {
- result.should.eql("123");
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getActiveProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("setActiveProject", function() {
- var activeProject;
- var runtime;
- beforeEach(function() {
- runtime = {
- log: mockLog(),
- storage: {projects: {
- getActiveProject: sinon.spy(function() { return activeProject;}),
- setActiveProject: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- projects.init(runtime);
- })
- it("sets project if current project is unset", function(done) {
- activeProject = null;
- projects.setActiveProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("sets project if current project is different", function(done) {
- activeProject = {name:456};
- projects.setActiveProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("no-ops if current project is same", function(done) {
- activeProject = {name:123};
- projects.setActiveProject({user:"known",id:123}).then(function(result) {
- (result === undefined).should.be.true();
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.setActiveProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getProject: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("returns project", function(done) {
- projects.getProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getProject({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("updateProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- updateProject: sinon.spy(function(user,id,project) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,project});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("updates project", function(done) {
- projects.updateProject({user:"known",id:123,project:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,project:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.updateProject({user:"error",id:123,project:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("deleteProject", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- deleteProject: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("deletes project", function(done) {
- projects.deleteProject({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.deleteProject({user:"error",id:123}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getStatus", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getStatus: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets status", function(done) {
- projects.getStatus({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getStatus({user:"error",id:123,project:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("getBranches", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getBranches: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets branches", function(done) {
- projects.getBranches({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getBranches({user:"error",id:123,remote:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("getBranchStatus", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getBranchStatus: sinon.spy(function(user,id,branch) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,branch});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets branch status", function(done) {
- projects.getBranchStatus({user:"known",id:123,branch:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,branch:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getBranchStatus({user:"error",id:123,branch:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("setBranch", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- setBranch: sinon.spy(function(user,id,branch,create) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,branch,create});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("commits", function(done) {
- projects.setBranch({user:"known",id:123,branch:{a:1},create:true}).then(function(result) {
- result.should.eql({user:"known",id:123,branch:{a:1},create:true});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.setBranch({user:"error",id:123,branch:{a:1},create:true}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("deleteBranch", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- deleteBranch: sinon.spy(function(user,id,branch,something,force) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,branch,force});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("commits", function(done) {
- projects.deleteBranch({user:"known",id:123,branch:{a:1},force:true}).then(function(result) {
- result.should.eql({user:"known",id:123,branch:{a:1},force:true});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.deleteBranch({user:"error",id:123,branch:{a:1},force:true}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("commit", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- commit: sinon.spy(function(user,id,message) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,message});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("commits", function(done) {
- projects.commit({user:"known",id:123,message:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,message:{message:{a:1}}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.commit({user:"error",id:123,message:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("getCommit", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getCommit: sinon.spy(function(user,id,sha) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,sha});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets commit", function(done) {
- projects.getCommit({user:"known",id:123,sha:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,sha:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getCommit({user:"error",id:123,sha:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getCommits", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getCommits: sinon.spy(function(user,id,options) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,options});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets commits with default limit/before", function(done) {
- projects.getCommits({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123,options:{limit:20,before:undefined}});
- done();
- }).catch(done);
- });
- it("gets commits with provided limit/before", function(done) {
- projects.getCommits({user:"known",id:123,limit:10,before:456}).then(function(result) {
- result.should.eql({user:"known",id:123,options:{limit:10,before:456}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getCommits({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("abortMerge", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- abortMerge: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("aborts merge", function(done) {
- projects.abortMerge({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.abortMerge({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("resolveMerge", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- resolveMerge: sinon.spy(function(user,id,path,resolution) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path,resolution});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("resolves merge", function(done) {
- projects.resolveMerge({user:"known",id:123,path:"/abc",resolution:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:"/abc",resolution:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.resolveMerge({user:"error",id:123,path:"/abc",resolution:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getFiles", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getFiles: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets files", function(done) {
- projects.getFiles({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getFiles({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getFile: sinon.spy(function(user,id,path,tree) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path,tree});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets file", function(done) {
- projects.getFile({user:"known",id:123,path:"/abc",tree:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:"/abc",tree:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getFile({user:"error",id:123,path:"/abc",tree:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("stageFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- stageFile: sinon.spy(function(user,id,path) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("stages a file", function(done) {
- projects.stageFile({user:"known",id:123,path:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.stageFile({user:"error",id:123,path:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("unstageFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- unstageFile: sinon.spy(function(user,id,path) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("unstages a file", function(done) {
- projects.unstageFile({user:"known",id:123,path:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.unstageFile({user:"error",id:123,path:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("revertFile", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- revertFile: sinon.spy(function(user,id,path) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("reverts a file", function(done) {
- projects.revertFile({user:"known",id:123,path:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.revertFile({user:"error",id:123,path:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getFileDiff", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getFileDiff: sinon.spy(function(user,id,path,type) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,path,type});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets file diff", function(done) {
- projects.getFileDiff({user:"known",id:123,path:{a:1},type:"abc"}).then(function(result) {
- result.should.eql({user:"known",id:123,path:{a:1},type:"abc"});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getFileDiff({user:"error",id:123,path:{a:1},type:"abc"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("getRemotes", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- getRemotes: sinon.spy(function(user,id) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("gets remotes", function(done) {
- projects.getRemotes({user:"known",id:123}).then(function(result) {
- result.should.eql({user:"known",id:123});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.getRemotes({user:"error"}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("addRemote", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- addRemote: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("adds a remote", function(done) {
- projects.addRemote({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.addRemote({user:"error",id:123,remote:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("removeRemote", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- removeRemote: sinon.spy(function(user,id,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("removes a remote", function(done) {
- projects.removeRemote({user:"known",id:123,remote:{a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:{a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.removeRemote({user:"error",id:123,remote:{a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
- describe("updateRemote", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- updateRemote: sinon.spy(function(user,id,name,remote) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,name,remote});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("updates a remote", function(done) {
- projects.updateRemote({user:"known",id:123,remote:{name:"abc",a:1}}).then(function(result) {
- result.should.eql({user:"known",id:123,name:"abc",remote:{name:"abc",a:1}});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.updateRemote({user:"error",id:123,remote:{name:"abc",a:1}}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("pull", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- pull: sinon.spy(function(user,id,remote,track,allowUnrelatedHistories) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote,track,allowUnrelatedHistories});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("pulls", function(done) {
- projects.pull({user:"known",id:123,remote:"abc",track:false,allowUnrelatedHistories:true}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:"abc",track:false,allowUnrelatedHistories:true});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.pull({user:"error",id:123,remote:"abc",track:false,allowUnrelatedHistories:true}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
- describe("push", function() {
- var runtime = {
- log: mockLog(),
- storage: {projects: {
- push: sinon.spy(function(user,id,remote,track) {
- if (user === "error") {
- var err = new Error("error");
- err.code = "error";
- var p = Promise.reject(err);
- p.catch(()=>{});
- return p;
- } else {
- return Promise.resolve({user,id,remote,track});
- }
- })
- }}};
- before(function() {
- projects.init(runtime);
- })
- it("pulls", function(done) {
- projects.push({user:"known",id:123,remote:"abc",track:false}).then(function(result) {
- result.should.eql({user:"known",id:123,remote:"abc",track:false});
- done();
- }).catch(done);
- });
- it("rejects with internal error", function(done) {
- projects.push({user:"error",id:123,remote:"abc",track:false}).then(function(result) {
- done(new Error("Did not reject internal error"));
- }).catch(function(err) {
- err.should.have.property('code','error');
- // err.should.have.property('status',400);
- done();
- }).catch(done);
- });
- });
-
-
-});
diff --git a/test/unit/@node-red/runtime/lib/api/settings_spec.js b/test/unit/@node-red/runtime/lib/api/settings_spec.js
deleted file mode 100644
index 9b3b94229..000000000
--- a/test/unit/@node-red/runtime/lib/api/settings_spec.js
+++ /dev/null
@@ -1,988 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-var should = require("should");
-var sinon = require("sinon");
-var clone = require("clone");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var settings = NR_TEST_UTILS.require("@node-red/runtime/lib/api/settings")
-
-var mockLog = () => ({
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-})
-
-describe("runtime-api/settings", function() {
- describe("getRuntimeSettings", function() {
- it("gets the runtime settings", function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => ["lib1"] },
- storage: {}
- })
- return settings.getRuntimeSettings({}).then(result => {
- result.should.have.property("httpNodeRoot","testHttpNodeRoot");
- result.should.have.property("version","testVersion");
- result.should.have.property("paletteCategories",["red","blue","green"]);
- result.should.have.property("libraries",["lib1"]);
- result.should.have.property("testNodeSetting","helloWorld");
- result.should.have.property("testPluginSettings","helloPluginWorld");
- result.should.not.have.property("foo",123);
- result.should.have.property("flowEncryptionType","test-key-type");
- result.should.not.have.property("user");
- result.should.have.property("externalModules");
- result.externalModules.should.eql({palette:{allowInstall:false, allowUpload: false}});
-
- })
- });
- it("gets the filtered user settings", function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {}
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.have.property("user");
- result.user.should.have.property("username","nick");
- result.user.should.have.property("permissions","*");
- result.user.should.have.property("image","http://example.com");
- result.user.should.have.property("anonymous",false);
- result.user.should.not.have.property("private");
- })
- });
- it("gets the filtered settings when editor disabled ", function() {
- settings.init({
- settings: {
- disableEditor: true,
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- getActiveProject: () => 'test-active-project',
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.have.property("user");
- result.user.should.have.property("username","nick");
- result.user.should.have.property("permissions","*");
- result.user.should.have.property("image","http://example.com");
- result.user.should.have.property("anonymous",false);
- result.user.should.not.have.property("private");
-
- // Filtered out when disableEditor is true
- result.should.not.have.property("paletteCategories",["red","blue","green"]);
- result.should.not.have.property("testNodeSetting","helloWorld");
- result.should.not.have.property("foo",123);
- result.should.not.have.property("flowEncryptionType","test-key-type");
- result.should.not.have.property("project");
- result.should.not.have.property("git");
-
- })
- });
- it('includes project settings if projects available', function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- getActiveProject: () => 'test-active-project',
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.have.property("project","test-active-project");
- result.should.not.have.property("files");
- result.should.have.property("git");
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- });
- });
-
- it('includes existing files details if projects enabled but no active project and files exist', function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- flowFileExists: () => true,
- getActiveProject: () => false,
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- result.should.not.have.property("project");
- result.should.have.property("files");
- result.files.should.have.property("flow",'test-flow-file');
- result.files.should.have.property("credentials",'test-creds-file');
- result.should.have.property("git");
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- });
- });
-
- it('does not include file details if projects enabled but no active project and files do not exist', function() {
- settings.init({
- settings: {
- foo: 123,
- httpNodeRoot: "testHttpNodeRoot",
- version: "testVersion",
- paletteCategories :["red","blue","green"],
- exportNodeSettings: (obj) => {
- obj.testNodeSetting = "helloWorld";
- },
- },
- plugins: {
- exportPluginSettings: (obj) => {
- obj.testPluginSettings = "helloPluginWorld";
- }
- },
- nodes: {
- listContextStores: () => { return {stores:["file","memory"], default: "file"} },
- installerEnabled: () => false,
- getCredentialKeyType: () => "test-key-type"
- },
- library: {getLibraries: () => { ["lib1"]} },
- storage: {
- projects: {
- flowFileExists: () => false,
- getActiveProject: () => false,
- getFlowFilename: () => 'test-flow-file',
- getCredentialsFilename: () => 'test-creds-file',
- getGlobalGitUser: () => {return {name:'foo',email:'foo@example.com'}}
- }
- }
- })
- return settings.getRuntimeSettings({
- user: {
- username: "nick",
- anonymous: false,
- image: "http://example.com",
- permissions: "*",
- private: "secret"
- }
- }).then(result => {
- result.should.not.have.property("project");
- result.should.not.have.property("files");
- result.should.have.property("git");
- result.git.should.have.property("globalUser",{name:'foo',email:'foo@example.com'});
- });
- });
- });
- describe("getUserSettings", function() {
- before(function() {
- settings.init({
- settings: {
- getUserSettings: username => username
- }
- });
- })
- it("returns default user settings", function() {
- return settings.getUserSettings({}).then(result => {
- result.should.eql("_");
- })
- })
- it("returns default user settings for anonymous", function() {
- return settings.getUserSettings({user:{anonymous:true}}).then(result => {
- result.should.eql("_");
- })
- })
- it("returns user settings", function() {
- return settings.getUserSettings({user:{username:'nick'}}).then(result => {
- result.should.eql("nick");
- })
- })
- });
-
- describe("updateUserSettings", function() {
- var userSettings;
- before(function() {
- settings.init({
- settings: {
- getUserSettings: username => clone(userSettings[username]),
- setUserSettings: (username, settings) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- } else if (username === 'throw') {
- throw new Error("thrown error");
- }
- userSettings[username] = clone(settings);
- return Promise.resolve();
- }
- },
- log: mockLog()
- });
- })
- beforeEach(function() {
- userSettings = {
- "_": { abc: 123 },
- "nick": {abc: 456}
- }
- })
- it('sets default user settings', function() {
- return settings.updateUserSettings({settings:{abc:789}}).then(function() {
- userSettings._.abc.should.eql(789)
- })
- })
- it('merges user settings', function() {
- return settings.updateUserSettings({settings:{def:789}}).then(function() {
- userSettings._.abc.should.eql(123)
- userSettings._.def.should.eql(789)
- })
- })
- it('sets default user settings for anonymous user', function() {
- return settings.updateUserSettings({user:{anonymous:true},settings:{def:789}}).then(function() {
- userSettings._.abc.should.eql(123)
- userSettings._.def.should.eql(789)
- })
- })
- it('sets named user settings', function() {
- return settings.updateUserSettings({user:{username:'nick'},settings:{def:789}}).then(function() {
- userSettings.nick.abc.should.eql(456)
- userSettings.nick.def.should.eql(789)
- })
- })
- it('rejects with suitable error', function(done) {
- settings.updateUserSettings({user:{username:'error'},settings:{def:789}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- it('rejects with suitable error - thrown', function(done) {
- settings.updateUserSettings({user:{username:'throw'},settings:{def:789}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
- describe("getUserKeys", function() {
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- listSSHKeys: username => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve([username])
- }
- }
- }
- }
- })
- })
- it('returns the default users keys', function() {
- return settings.getUserKeys({}).then(result => {
- result.should.eql(['__default']);
- })
- })
- it('returns the default users keys for anonymous', function() {
- return settings.getUserKeys({user:{anonymous:true}}).then(result => {
- result.should.eql(['__default']);
- })
- })
- it('returns the users keys', function() {
- return settings.getUserKeys({user:{username:'nick'}}).then(result => {
- result.should.eql(['nick']);
- })
- })
- it('rejects with suitable error', function(done) {
- settings.getUserKeys({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
-
- describe("getUserKey", function() {
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- getSSHKey: (username, id) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- } else if (username === '404') {
- return Promise.resolve(null);
- }
- return Promise.resolve({username,id})
- }
- }
- }
- }
- })
- })
- it('returns the default user key', function() {
- return settings.getUserKey({id:'keyid'}).then(result => {
- result.should.eql({id:'keyid',username:"__default"});
- })
- })
- it('returns the default user key - anonymous', function() {
- return settings.getUserKey({user:{anonymous:true},id:'keyid'}).then(result => {
- result.should.eql({id:'keyid',username:"__default"});
- })
- })
- it('returns the user key', function() {
- return settings.getUserKey({user:{username:'nick'},id:'keyid'}).then(result => {
- result.should.eql({id:'keyid',username:"nick"});
- })
- })
- it('404s for unknown key', function(done) {
- settings.getUserKey({user:{username:'404'},id:'keyid'}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 404);
- err.should.have.property('code', 'not_found');
- done();
- }).catch(done);
- })
- it('rejects with suitable error', function(done) {
- settings.getUserKey({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
- describe("generateUserKey", function() {
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- generateSSHKey: (username, opts) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- }
- return Promise.resolve(JSON.stringify({username,opts}))
- }
- }
- }
- }
- })
- })
- it('generates for the default user', function() {
- return settings.generateUserKey({id:'keyid'}).then(result => {
- var data = JSON.parse(result);
- data.should.eql({opts:{id:'keyid'},username:"__default"});
- })
- })
- it('generates for the default user - anonymous', function() {
- return settings.generateUserKey({user:{anonymous:true},id:'keyid'}).then(result => {
- var data = JSON.parse(result);
- data.should.eql({opts:{user:{anonymous:true},id:'keyid'},username:"__default"});
- })
- })
- it('generates for the user', function() {
- return settings.generateUserKey({user:{username:'nick'},id:'keyid'}).then(result => {
- var data = JSON.parse(result);
- data.should.eql({opts:{user:{username:'nick'},id:'keyid'},username:"nick"});
- })
- })
- it('rejects with suitable error', function(done) {
- settings.generateUserKey({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
-
- });
- describe("removeUserKey", function() {
- var received = {};
- before(function() {
- settings.init({
- storage: {
- projects: {
- ssh: {
- deleteSSHKey: (username, id) => {
- if (username === 'error') {
- var p = Promise.reject(new Error("unknown user"));
- p.catch(()=>{});
- return p;
- }
- received.username = username;
- received.id = id;
- return Promise.resolve();
- }
- }
- }
- }
- })
- });
- beforeEach(function() {
- received.username = "";
- received.id = "";
- })
- it('removes for the default user', function() {
- return settings.removeUserKey({id:'keyid'}).then(() => {
- received.username.should.eql("__default");
- received.id.should.eql("keyid");
- })
- })
- it('removes for the default user key - anonymous', function() {
- return settings.removeUserKey({user:{anonymous:true},id:'keyid'}).then(() => {
- received.username.should.eql("__default");
- received.id.should.eql("keyid");
- })
- })
- it('returns the user key', function() {
- return settings.removeUserKey({user:{username:'nick'},id:'keyid'}).then(() => {
- received.username.should.eql("nick");
- received.id.should.eql("keyid");
- })
- })
- it('rejects with suitable error', function(done) {
- settings.removeUserKey({user:{username:'error'}}).then(result => {
- done("Unexpected resolve for error case");
- }).catch(err => {
- err.should.have.property('status', 400);
- done();
- }).catch(done);
- })
- });
-
-});
-
-
-
-/*
-
-
-var should = require("should");
-var sinon = require("sinon");
-var request = require("supertest");
-var express = require("express");
-var editorApi = require("../../../../red/api/editor");
-var comms = require("../../../../red/api/editor/comms");
-var info = require("../../../../red/api/editor/settings");
-var auth = require("../../../../red/api/auth");
-var sshkeys = require("../../../../red/api/editor/sshkeys");
-var bodyParser = require("body-parser");
-var fs = require("fs-extra");
-var fspath = require("path");
-
-
-describe("api/editor/sshkeys", function() {
- var app;
- var mockList = [
- 'library','theme','locales','credentials','comms'
- ]
- var isStarted = true;
- var errors = [];
- var session_data = {};
-
- var mockRuntime = {
- settings:{
- httpNodeRoot: true,
- httpAdminRoot: true,
- disableEditor: false,
- exportNodeSettings:function(){},
- storage: {
- getSessions: function(){
- return Promise.resolve(session_data);
- },
- setSessions: function(_session) {
- session_data = _session;
- return Promise.resolve();
- }
- }
- },
- log:{audit:function(){},error:function(msg){errors.push(msg)},trace:function(){}},
- storage: {
- projects: {
- ssh: {
- init: function(){},
- listSSHKeys: function(){},
- getSSHKey: function(){},
- generateSSHKey: function(){},
- deleteSSHKey: function(){}
- }
- }
- },
- events:{on:function(){},removeListener:function(){}},
- isStarted: function() { return isStarted; },
- nodes: {installerEnabled: function() { return false }}
- };
-
- before(function() {
- auth.init(mockRuntime);
- app = express();
- app.use(bodyParser.json());
- app.use(editorApi.init({},mockRuntime));
- });
- after(function() {
- })
-
- beforeEach(function() {
- sinon.stub(mockRuntime.storage.projects.ssh, "listSSHKeys");
- sinon.stub(mockRuntime.storage.projects.ssh, "getSSHKey");
- sinon.stub(mockRuntime.storage.projects.ssh, "generateSSHKey");
- sinon.stub(mockRuntime.storage.projects.ssh, "deleteSSHKey");
- })
- afterEach(function() {
- mockRuntime.storage.projects.ssh.listSSHKeys.restore();
- mockRuntime.storage.projects.ssh.getSSHKey.restore();
- mockRuntime.storage.projects.ssh.generateSSHKey.restore();
- mockRuntime.storage.projects.ssh.deleteSSHKey.restore();
- })
-
- it('GET /settings/user/keys --- return empty list', function(done) {
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve([]));
- request(app)
- .get("/settings/user/keys")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('keys');
- res.body.keys.should.be.empty();
- done();
- });
- });
-
- it('GET /settings/user/keys --- return normal list', function(done) {
- var fileList = [
- 'test_key01',
- 'test_key02'
- ];
- var retList = fileList.map(function(elem) {
- return {
- name: elem
- };
- });
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(Promise.resolve(retList));
- request(app)
- .get("/settings/user/keys")
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('keys');
- for (var item of retList) {
- res.body.keys.should.containEql(item);
- }
- done();
- });
- });
-
- it('GET /settings/user/keys --- return Error', function(done) {
- var errInstance = new Error("Messages here.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
- request(app)
- .get("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal(errInstance.code);
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return 404', function(done) {
- mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(null));
- request(app)
- .get("/settings/user/keys/NOT_REAL")
- .expect(404)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- done();
- });
- });
- it('GET /settings/user/keys --- return Unexpected Error', function(done) {
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.listSSHKeys.returns(p);
- request(app)
- .get("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return content', function(done) {
- var key_file_name = "test_key";
- var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
- mockRuntime.storage.projects.ssh.getSSHKey.returns(Promise.resolve(fileContent));
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- mockRuntime.storage.projects.ssh.getSSHKey.called.should.be.true();
- res.body.should.be.deepEqual({ publickey: fileContent });
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal(errInstance.code);
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('GET /settings/user/keys/ --- return Unexpected Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.getSSHKey.returns(p);
- request(app)
- .get("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-
- it('POST /settings/user/keys --- success', function(done) {
- var key_file_name = "test_key";
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(200)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- done();
- });
- });
-
- it('POST /settings/user/keys --- return parameter error', function(done) {
- var key_file_name = "test_key";
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(Promise.resolve(key_file_name));
- request(app)
- .post("/settings/user/keys")
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal("You need to have body or body.name");
- done();
- });
- });
-
- it('POST /settings/user/keys --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("test_code");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('POST /settings/user/keys --- return Unexpected error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.generateSSHKey.returns(p);
- request(app)
- .post("/settings/user/keys")
- .send({ name: key_file_name })
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- success', function(done) {
- var key_file_name = "test_key";
- mockRuntime.storage.projects.ssh.deleteSSHKey.returns(Promise.resolve(true));
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(204)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.be.deepEqual({});
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- return Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- errInstance.code = "test_code";
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("test_code");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.message);
- done();
- });
- });
-
- it('DELETE /settings/user/keys/ --- return Unexpected Error', function(done) {
- var key_file_name = "test_key";
- var errInstance = new Error("Messages.....");
- var p = Promise.reject(errInstance);
- p.catch(()=>{});
- mockRuntime.storage.projects.ssh.deleteSSHKey.returns(p);
- request(app)
- .delete("/settings/user/keys/" + key_file_name)
- .expect(400)
- .end(function(err,res) {
- if (err) {
- return done(err);
- }
- res.body.should.have.property('error');
- res.body.error.should.be.equal("unexpected_error");
- res.body.should.have.property('message');
- res.body.message.should.be.equal(errInstance.toString());
- done();
- });
- });
-});
-*/
diff --git a/test/unit/@node-red/runtime/lib/flows/Flow_spec.js b/test/unit/@node-red/runtime/lib/flows/Flow_spec.js
deleted file mode 100644
index eed4810c4..000000000
--- a/test/unit/@node-red/runtime/lib/flows/Flow_spec.js
+++ /dev/null
@@ -1,1327 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-var should = require("should");
-var sinon = require('sinon');
-var clone = require('clone');
-var util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var flowUtils = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
-var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
-
-
-describe('Flow', function() {
- var getType;
-
- var stoppedNodes = {};
- var stoppedOrder = [];
- var currentNodes = {};
- var rewiredNodes = {};
- var createCount = 0;
-
- beforeEach(function() {
- currentNodes = {};
- stoppedNodes = {};
- stoppedOrder =[];
- rewiredNodes = {};
- createCount = 0;
- Flow.init({settings:{},log:{
- log: sinon.stub(), // function() { console.log("l",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//
- debug: sinon.stub(), // function() { console.log("d",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- trace: sinon.stub(), // function() { console.log("t",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- warn: sinon.stub(), // function() { console.log("w",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- info: sinon.stub(), // function() { console.log("i",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }});
- });
-
- var TestNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- // console.log(this.id,msg.payload);
- node.handled++;
- node.send(msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestNode,Node);
-
- var TestErrorNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.name = n.name;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.error("test error",msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestErrorNode,Node);
-
- var TestAsyncNode = function(n) {
- Node.call(this,n);
- var node = this;
- this.scope = n.scope;
- this.uncaught = n.uncaught;
- this.foo = n.foo;
- this.handled = 0;
- this.messages = [];
- this.stopped = false;
- this.closeDelay = n.closeDelay || 50;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- msg.handled = node.handled;
- node.messages.push(msg);
- node.send(msg);
- });
- this.on('close',function(done) {
- setTimeout(function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- done();
- },node.closeDelay);
- });
- }
- util.inherits(TestAsyncNode,Node);
-
- var TestDoneNode = function(n) {
- Node.call(this,n);
- var node = this;
- this.scope = n.scope;
- this.uncaught = n.uncaught;
- this.foo = n.foo;
- this.handled = 0;
- this.messages = [];
- this.stopped = false;
- this.closeDelay = n.closeDelay || 50;
- currentNodes[node.id] = node;
- this.on('input',function(msg, send, done) {
- node.handled++;
- node.messages.push(msg);
- send(msg);
- done();
- });
- this.on('close',function(done) {
- setTimeout(function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- stoppedOrder.push(node.id)
- delete currentNodes[node.id];
- done();
- },node.closeDelay);
- });
- }
- util.inherits(TestDoneNode,Node);
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- if (type=="test") {
- return TestNode;
- } else if (type=="testError"){
- return TestErrorNode;
- } else if (type=="testDone"){
- return TestDoneNode;
- } else {
- return TestAsyncNode;
- }
- });
- });
- after(function() {
- getType.restore();
- });
-
- describe('#constructor',function() {
- it('called with an empty flow',function() {
- var config = flowUtils.parseConfig([]);
- var flow = Flow.create({},config);
-
- var nodeCount = 0;
- Object.keys(flow.getActiveNodes()).length.should.equal(0);
- });
- });
-
- describe('#start',function() {
- it("instantiates an initial configuration and stops it",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
- flow.getNode('2').should.have.a.property('id','2');
- flow.getNode('3').should.have.a.property('id','3');
- flow.getNode('4').should.have.a.property('id','4');
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["2"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
-
- currentNodes["3"].on("input", function() {
- currentNodes["1"].should.have.a.property("handled",1);
- currentNodes["2"].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
-
- flow.stop().then(function() {
- try {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- currentNodes.should.not.have.a.property("4");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- stoppedNodes.should.have.a.property("4");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- currentNodes["1"].receive({payload:"test"});
- });
-
- it("instantiates config nodes in the right order",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"5"}, // This node depends on #5
- {id:"5",z:"t1",type:"test"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(5);
-
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
- currentNodes.should.have.a.property("5");
-
- currentNodes["1"].should.have.a.property("_index",2);
- currentNodes["2"].should.have.a.property("_index",3);
- currentNodes["3"].should.have.a.property("_index",4);
- currentNodes["4"].should.have.a.property("_index",1);
- currentNodes["5"].should.have.a.property("_index",0);
-
- flow.stop().then(function() {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- currentNodes.should.not.have.a.property("4");
- currentNodes.should.not.have.a.property("5");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- stoppedNodes.should.have.a.property("4");
- stoppedNodes.should.have.a.property("5");
- done();
- });
- });
-
-
- it("detects dependency loops in config nodes",function() {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"node1",z:"t1",type:"test",foo:"node2"}, // This node depends on #5
- {id:"node2",z:"t1",type:"test",foo:"node1"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- /*jshint immed: false */
- (function(){
- flow.start();
- }).should.throw("Circular config node dependency detected: node1");
- });
-
- it("rewires nodes specified by diff",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]}
- ]);
-
- var flow = Flow.create({},config,config.flows["t1"]);
- createCount.should.equal(0);
- flow.start();
- //TODO: use update to pass in new wiring and verify the change
- createCount.should.equal(3);
- flow.start({rewired:["2"]});
- createCount.should.equal(3);
- rewiredNodes.should.have.a.property("2");
- done();
- });
-
- it("instantiates a node with environment variable property values",function(done) {
- after(function() {
- delete process.env.NODE_RED_TEST_VALUE;
- })
- process.env.NODE_RED_TEST_VALUE = "a-value";
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"$(NODE_RED_TEST_VALUE)",wires:[]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:{a:"$(NODE_RED_TEST_VALUE)"},wires:[]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:" $(NODE_RED_TEST_VALUE)",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"$(NODE_RED_TEST_VALUE) ",wires:[]},
- {id:"5",x:10,y:10,z:"t1",type:"test",foo:"$(NODE_RED_TEST_VALUE_NONE)",wires:[]},
- {id:"6",x:10,y:10,z:"t1",type:"test",foo:["$(NODE_RED_TEST_VALUE)"],wires:[]}
- ]);
- var flow = Flow.create({getSetting:v=>process.env[v]},config,config.flows["t1"]);
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].foo.should.equal("a-value");
- activeNodes["2"].foo.a.should.equal("a-value");
- activeNodes["3"].foo.should.equal(" $(NODE_RED_TEST_VALUE)");
- activeNodes["4"].foo.should.equal("$(NODE_RED_TEST_VALUE) ");
- activeNodes["5"].foo.should.equal("$(NODE_RED_TEST_VALUE_NONE)");
- activeNodes["6"].foo[0].should.equal("a-value");
-
- flow.stop().then(function() {
- done();
- });
- });
-
- it("ignores disabled nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",d:true,type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"},
- {id:"5",z:"t1",type:"test",d:true,foo:"a"}
-
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(3);
-
- flow.getNode('1').should.have.a.property('id','1');
- should.not.exist(flow.getNode('2'));
- flow.getNode('3').should.have.a.property('id','3');
- flow.getNode('4').should.have.a.property('id','4');
- should.not.exist(flow.getNode('5'));
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- // Message doesn't reach 3 as 2 is disabled
- currentNodes["3"].should.have.a.property("handled",0);
-
- flow.stop().then(function() {
- try {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- currentNodes.should.not.have.a.property("4");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.not.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- stoppedNodes.should.have.a.property("4");
- done();
- } catch(err) {
- done(err);
- }
- });
- },50);
- });
-
- });
-
- describe('#stop', function() {
-
-
- it("stops all nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"asyncTest",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
-
- flow.stop().then(function() {
- currentNodes.should.not.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- stoppedNodes.should.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- done();
- }).catch(done);
- });
-
- it("stops specified nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
-
- flow.stop(["2"]).then(function() {
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.have.a.property("3");
- stoppedNodes.should.not.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.not.have.a.property("3");
- done();
- });
- });
-
- it("stops config nodes last",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"c1",z:"t1",type:"test"},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"c2",z:"t1",type:"test"},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"c3",z:"t1",type:"test"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("c1");
- currentNodes.should.have.a.property("c2");
- currentNodes.should.have.a.property("c3");
- stoppedOrder.should.have.a.length(0);
-
- flow.stop().then(function() {
- stoppedOrder.should.eql([ '1', '2', '3', 'c1', 'c2', 'c3' ]);
- done();
- }).catch(done);
- });
-
-
- it("Times out a node that fails to close", function(done) {
- Flow.init({settings:{nodeCloseTimeout:50},log:{
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }});
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"testAsync",closeDelay: 80, foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.have.a.property("2");
- currentNodes.should.have.a.property("3");
-
- flow.stop().then(function() {
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.not.have.a.property("3");
- stoppedNodes.should.not.have.a.property("1");
- stoppedNodes.should.have.a.property("2");
- stoppedNodes.should.have.a.property("3");
- setTimeout(function() {
- currentNodes.should.not.have.a.property("1");
- stoppedNodes.should.have.a.property("1");
- done();
- },40)
- });
- });
-
- });
-
- describe('#getNode',function() {
- it("gets a node known to the flow",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
-
- flow.stop().then(() => { done() });
- });
-
- it("passes to parent if node not known locally",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({
- getNode: id => { return {id:id}}
- },config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
-
- flow.getNode('parentNode').should.have.a.property('id','parentNode');
-
-
- flow.stop().then(() => { done() });
- });
-
- it("does not pass to parent if cancelBubble set",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",z:"t1",type:"test",foo:"a"}
- ]);
- var flow = Flow.create({
- getNode: id => { return {id:id}}
- },config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(4);
-
- flow.getNode('1').should.have.a.property('id','1');
-
- should.not.exist(flow.getNode('parentNode',true));
- flow.stop().then(() => { done() });
- });
- });
-
- describe("#handleStatus",function() {
- it("passes a status event to the adjacent status node",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(5);
-
-
- flow.handleStatus(config.flows["t1"].nodes["1"],{text:"my-status",random:"otherProperty"});
-
- setTimeout(function() {
-
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","my-status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","1");
- statusMessage.status.source.should.have.a.property("type","test");
- statusMessage.status.source.should.have.a.property("name","a");
-
- currentNodes["sn2"].should.have.a.property("handled",1);
- statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","my-status");
- statusMessage.status.should.have.a.property("random","otherProperty");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","1");
- statusMessage.status.source.should.have.a.property("type","test");
- statusMessage.status.source.should.have.a.property("name","a");
-
-
- flow.stop().then(function() {
- done();
- });
- },50)
- });
- it("passes a status event to the adjacent scoped status node ",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",scope:["2"],foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"status",scope:["1"],foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(5);
-
-
- flow.handleStatus(config.flows["t1"].nodes["1"],{text:"my-status"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",0);
- currentNodes["sn2"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","my-status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","1");
- statusMessage.status.source.should.have.a.property("type","test");
- statusMessage.status.source.should.have.a.property("name","a");
-
-
- flow.stop().then(function() {
- done();
- });
- },50);
- });
-
- });
-
- describe("#handleError",function() {
- it("passes an error event to the adjacent catch node",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]},
- {id:"sn3",x:10,y:10,z:"t1",type:"catch",uncaught:true,wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(6);
-
-
- flow.handleError(config.flows["t1"].nodes["1"],"my-error",{a:"foo"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- currentNodes["sn2"].should.have.a.property("handled",1);
- statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- // Node sn3 has uncaught:true - so should not get called
- currentNodes["sn3"].should.have.a.property("handled",0);
-
-
- flow.stop().then(function() {
- done();
- });
- },50);
- });
- it("passes an error event to the adjacent scoped catch node ",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",scope:["2"],foo:"a",wires:[]},
- {id:"sn2",x:10,y:10,z:"t1",type:"catch",scope:["1"],foo:"a",wires:[]},
- {id:"sn3",x:10,y:10,z:"t1",type:"catch",uncaught:true,wires:[]},
- {id:"sn4",x:10,y:10,z:"t1",type:"catch",uncaught:true,wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(7);
-
- flow.handleError(config.flows["t1"].nodes["1"],"my-error",{a:"foo"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",0);
- currentNodes["sn2"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn2"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- // Node sn3/4 have uncaught:true - so should not get called
- currentNodes["sn3"].should.have.a.property("handled",0);
- currentNodes["sn4"].should.have.a.property("handled",0);
-
- // Inject error that sn1/2 will ignore - so should get picked up by sn3
- flow.handleError(config.flows["t1"].nodes["3"],"my-error-2",{a:"foo-2"});
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",0);
- currentNodes["sn2"].should.have.a.property("handled",1);
- currentNodes["sn3"].should.have.a.property("handled",1);
- currentNodes["sn4"].should.have.a.property("handled",1);
-
- statusMessage = currentNodes["sn3"].messages[0];
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error-2");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","3");
- statusMessage.error.source.should.have.a.property("type","test");
-
- flow.stop().then(function() {
- done();
- });
- },50);
- },50);
- });
- it("moves any existing error object sideways",function(done){
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- flow.handleError(config.flows["t1"].nodes["1"],"my-error",{a:"foo",error:"existing"});
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("_error","existing");
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","my-error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("id","1");
- statusMessage.error.source.should.have.a.property("type","test");
- statusMessage.error.source.should.have.a.property("name","a");
-
- flow.stop().then(function() {
- done();
- });
- },50);
- });
- it("prevents an error looping more than 10 times",function(){});
- });
-
- describe("#handleComplete",function() {
- it("passes a complete event to the adjacent Complete node",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"testDone",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"testDone",foo:"a",wires:[]},
- {id:"cn",x:10,y:10,z:"t1",type:"complete",scope:["1","3"],foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(4);
-
- var msg = {payload: "hello world"}
- var n1 = currentNodes["1"].receive(msg);
- setTimeout(function() {
- currentNodes["cn"].should.have.a.property("handled",2);
- currentNodes["cn"].messages[0].should.have.a.property("handled",1);
- currentNodes["cn"].messages[1].should.have.a.property("handled",2);
- flow.stop().then(function() {
- done();
- });
- },50);
- });
- });
-
-
- describe("#send", function() {
- it("sends a message - no cloning", function(done) {
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
- var messageReceived = false;
- n2.receive = function(msg) {
- messageReceived = true;
- try {
- msg.should.be.exactly(message);
- shutdownTest();
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var message = {payload:"hello"}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: false
- }])
- messageReceived.should.be.false()
- })
- it("sends a message - cloning", function(done) {
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
-
- n2.receive = function(msg) {
- try {
- // Message should be cloned
- msg.should.be.eql(message);
- msg.should.not.be.exactly(message);
- shutdownTest();
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var message = {payload:"hello"}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- })
- it("sends multiple messages", function(done) {
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
-
- var messageCount = 0;
- n2.receive = function(msg) {
- try {
- msg.should.be.exactly(messages[messageCount++]);
- if (messageCount === 2) {
- shutdownTest();
- }
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var messages = [{payload:"hello"},{payload:"world"}];
-
- flow.send([{
- msg: messages[0],
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined }
- },{
- msg: messages[1],
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined }
- }])
- })
- it("sends a message - triggers hooks", function(done) {
- var hookErrors = [];
- var messageReceived = false;
- var hooksCalled = [];
- hooks.add("onSend", function(sendEvents) {
- hooksCalled.push("onSend")
- try {
- messageReceived.should.be.false()
- sendEvents.should.have.length(1);
- sendEvents[0].msg.should.be.exactly(message);
- } catch(err) {
- hookErrors.push(err);
- }
- })
- hooks.add("preRoute", function(sendEvent) {
- hooksCalled.push("preRoute")
- try {
- messageReceived.should.be.false()
- sendEvent.msg.should.be.exactly(message);
- should.not.exist(sendEvent.destination.node)
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- hooks.add("preDeliver", function(sendEvent) {
- hooksCalled.push("preDeliver")
- try {
- messageReceived.should.be.false()
- // Cloning should have happened
- sendEvent.msg.should.not.be.exactly(message);
- // Destinatino node populated
- should.exist(sendEvent.destination.node)
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- hooks.add("postDeliver", function(sendEvent) {
- hooksCalled.push("postDeliver")
- try {
- messageReceived.should.be.false()
-
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- var shutdownTest = function(err) {
- hooks.clear();
- flow.stop().then(() => { done(err) });
- }
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
-
- Object.keys(flow.getActiveNodes()).should.have.length(2);
-
- var n1 = flow.getNode('1');
- var n2 = flow.getNode('2');
- n2.receive = function(msg) {
- messageReceived = true;
- try {
- msg.should.be.eql(message);
- msg.should.not.be.exactly(message);
- hooksCalled.should.eql(["onSend","preRoute","preDeliver","postDeliver"])
- if (hookErrors.length > 0) {
- shutdownTest(hookErrors[0])
- } else {
- shutdownTest();
- }
- } catch(err) {
- shutdownTest(err);
- }
- }
-
- var message = {payload:"hello"}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- })
-
- describe("errors thrown by hooks are reported to the sending node", function() {
- var flow;
- var n1,n2;
- var messageReceived = false;
- var errorReceived = null;
- before(function() {
- hooks.add("onSend", function(sendEvents) {
- if (sendEvents[0].msg.payload === "trigger-onSend") {
- throw new Error("onSend Error");
- }
- })
- hooks.add("preRoute", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preRoute") {
- throw new Error("preRoute Error");
- }
- })
- hooks.add("preDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preDeliver") {
- throw new Error("preDeliver Error");
- }
- })
- hooks.add("postDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-postDeliver") {
- throw new Error("postDeliver Error");
- }
- })
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
- n1 = flow.getNode('1');
- n2 = flow.getNode('2');
- n2.receive = function(msg) {
- messageReceived = true;
- }
- n1.error = function(err) {
- errorReceived = err;
- }
-
- })
- after(function(done) {
- hooks.clear();
- flow.stop().then(() => { done() });
- })
- beforeEach(function() {
- messageReceived = false;
- errorReceived = null;
- })
- function testHook(hook, msgExpected, done) {
- var message = {payload:"trigger-"+hook}
- flow.send([{
- msg: message,
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- setTimeout(function() {
- try {
- messageReceived.should.equal(msgExpected);
- should.exist(errorReceived)
- errorReceived.toString().should.containEql(hook);
- done();
- } catch(err) {
- done(err);
- }
- },10)
- }
-
- it("onSend", function(done) { testHook("onSend", false, done) })
- it("preRoute", function(done) { testHook("preRoute", false, done) })
- it("preDeliver", function(done) { testHook("preDeliver", false, done) })
- it("postDeliver", function(done) { testHook("postDeliver", true, done) })
- })
-
- describe("hooks can stop the sending of messages", function() {
- var flow;
- var n1,n2;
- var messageReceived = false;
- var errorReceived = false;
- before(function() {
- hooks.add("onSend", function(sendEvents) {
- if (sendEvents[0].msg.payload === "trigger-onSend") {
- return false
- }
- })
- hooks.add("preRoute", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preRoute") {
- return false
- }
- })
- hooks.add("preDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-preDeliver") {
- return false
- }
- })
- hooks.add("postDeliver", function(sendEvent) {
- if (sendEvent.msg.payload === "trigger-postDeliver") {
- return false
- }
- })
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["3"]}
- ]);
- flow = Flow.create({},config,config.flows["t1"]);
- flow.start();
- n1 = flow.getNode('1');
- n2 = flow.getNode('2');
- n2.receive = function(msg) {
- messageReceived = true;
- }
- n1.error = function(err) {
- errorReceived = true;
- }
-
- })
- after(function(done) {
- hooks.clear();
- flow.stop().then(() => { done() });
- })
- function testSend(payload,messageReceivedExpected,errorReceivedExpected,done) {
- messageReceived = false;
- errorReceived = false;
- flow.send([{
- msg: {payload: payload},
- source: { id:"1", node: n1 },
- destination: { id:"2", node: undefined },
- cloneMessage: true
- }])
- setTimeout(function() {
- try {
- messageReceived.should.eql(messageReceivedExpected)
- errorReceived.should.eql(errorReceivedExpected)
- done();
- } catch(err) {
- done(err);
- }
- },10)
- }
- function testHook(hook, done) {
- testSend("pass",true,false,err => {
- if (err) {
- done(err)
- } else {
- testSend("trigger-"+hook,false,false,done);
- }
- })
- }
-
- it("onSend", function(done) { testHook("onSend", done) })
- it("preRoute", function(done) { testHook("preRoute", done) })
- it("preDeliver", function(done) { testHook("preDeliver", done) })
- // postDeliver happens after delivery is scheduled so cannot stop it
- // it("postDeliver", function(done) { testHook("postDeliver", done) })
- })
- })
-
- describe("#env", function () {
- it("can instantiate a node with environment variable property values of group and tab", function (done) {
- try {
- after(function() {
- delete process.env.V0;
- delete process.env.V1;
- })
- process.env.V0 = "gv0";
- process.env.V1 = "gv1";
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab",env:[
- {"name": "V0", value: "v0", type: "str"}
- ]},
- {id:"g1",type:"group",z:"t1",env:[
- {"name": "V0", value: "v1", type: "str"},
- {"name": "V1", value: "v2", type: "str"}
- ]},
- {id:"g2",type:"group",z:"t1",g:"g1",env:[
- {"name": "V1", value: "v3", type: "str"}
- ]},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"$(V0)",wires:[]},
- {id:"2",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"$(V0)",wires:[]},
- {id:"3",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"$(V1)",wires:[]},
- {id:"4",x:10,y:10,z:"t1",g:"g2",type:"test",foo:"$(V1)",wires:[]},
- {id:"5",x:10,y:10,z:"t1",type:"test",foo:"$(V1)",wires:[]},
- ]);
- var flow = Flow.create({getSetting:v=>process.env[v]},config,config.flows["t1"]);
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].foo.should.equal("v0");
- activeNodes["2"].foo.should.equal("v1");
- activeNodes["3"].foo.should.equal("v2");
- activeNodes["4"].foo.should.equal("v3");
- activeNodes["5"].foo.should.equal("gv1");
-
- flow.stop().then(function() {
- done();
- });
- }
- catch (e) {
- console.log(e.stack);
- done(e);
- }
-
- });
- it("can access environment variable property using $parent", function (done) {
- try {
- after(function() {
- delete process.env.V0;
- delete process.env.V1;
- })
- process.env.V0 = "gv0";
- process.env.V1 = "gv1";
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab",env:[
- {"name": "V0", value: "v0", type: "str"}
- ]},
- {id:"g1",type:"group",z:"t1",env:[
- {"name": "V0", value: "v1", type: "str"},
- {"name": "V1", value: "v2", type: "str"}
- ]},
- {id:"g2",type:"group",z:"t1",g:"g1",env:[
- {"name": "V1", value: "v3", type: "str"}
- ]},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"${$parent.V0}",wires:[]},
- {id:"2",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"${$parent.V0}",wires:[]},
- {id:"3",x:10,y:10,z:"t1",g:"g1",type:"test",foo:"${$parent.V1}",wires:[]},
- {id:"4",x:10,y:10,z:"t1",g:"g2",type:"test",foo:"${$parent.V1}",wires:[]},
- {id:"5",x:10,y:10,z:"t1",type:"test",foo:"${$parent.V1}",wires:[]},
- ]);
- var flow = Flow.create({getSetting:v=>process.env[v]},config,config.flows["t1"]);
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].foo.should.equal("gv0");
- activeNodes["2"].foo.should.equal("v0");
- activeNodes["3"].foo.should.equal("gv1");
- activeNodes["4"].foo.should.equal("v2");
- activeNodes["5"].foo.should.equal("gv1");
-
- flow.stop().then(function() {
- done();
- });
- }
- catch (e) {
- console.log(e.stack);
- done(e);
- }
-
- });
-
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js b/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js
deleted file mode 100644
index 0479b5117..000000000
--- a/test/unit/@node-red/runtime/lib/flows/Subflow_spec.js
+++ /dev/null
@@ -1,885 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-var should = require("should");
-var sinon = require('sinon');
-var clone = require('clone');
-var util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var Subflow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Subflow");
-var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
-
-var flowUtils = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
-
-describe('Subflow', function() {
- var getType;
-
- var stoppedNodes = {};
- var currentNodes = {};
- var rewiredNodes = {};
- var createCount = 0;
-
- beforeEach(function() {
- currentNodes = {};
- stoppedNodes = {};
- rewiredNodes = {};
- createCount = 0;
- var runtime = {
- settings:{},
- log:{
- log: sinon.stub(), // function() { console.log("l",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//
- debug: sinon.stub(), // function() { console.log("d",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- trace: sinon.stub(), // function() { console.log("t",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- warn: sinon.stub(), // function() { console.log("w",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- info: sinon.stub(), // function() { console.log("i",[...arguments].map(a => JSON.stringify(a)).join(" ")) },//sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }
- }
- Flow.init(runtime);
- Subflow.init(runtime);
- });
-
- var TestNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- this.received = null;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- // console.log(this.id,msg.payload);
- node.handled++;
- node.received = msg.payload;
- node.send(msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestNode,Node);
-
- var TestErrorNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.name = n.name;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.error("test error",msg);
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestErrorNode,Node);
-
-
- var TestStatusNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.name = n.name;
- var node = this;
- this.foo = n.foo;
- this.handled = 0;
- this.stopped = false;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.status({text:"test status"});
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestStatusNode,Node);
-
- var TestAsyncNode = function(n) {
- Node.call(this,n);
- var node = this;
- this.scope = n.scope;
- this.foo = n.foo;
- this.handled = 0;
- this.messages = [];
- this.stopped = false;
- this.closeDelay = n.closeDelay || 50;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- node.handled++;
- node.messages.push(msg);
- node.send(msg);
- });
- this.on('close',function(done) {
- setTimeout(function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- done();
- },node.closeDelay);
- });
- }
- util.inherits(TestAsyncNode,Node);
-
- var TestEnvNode = function(n) {
- Node.call(this,n);
- this._index = createCount++;
- this.scope = n.scope;
- this.foo = n.foo;
- var node = this;
- this.stopped = false;
- this.received = null;
- currentNodes[node.id] = node;
- this.on('input',function(msg) {
- var flow = node._flow;
- var val = flow.getSetting("__KEY__");
- node.received = val;
- node.send({payload: val});
- });
- this.on('close',function() {
- node.stopped = true;
- stoppedNodes[node.id] = node;
- delete currentNodes[node.id];
- });
- this.__updateWires = this.updateWires;
- this.updateWires = function(newWires) {
- rewiredNodes[node.id] = node;
- node.newWires = newWires;
- node.__updateWires(newWires);
- };
- }
- util.inherits(TestEnvNode,Node);
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- if (type=="test") {
- return TestNode;
- } else if (type=="testError"){
- return TestErrorNode;
- } else if (type=="testStatus"){
- return TestStatusNode;
- } else if (type=="testEnv"){
- return TestEnvNode;
- } else {
- return TestAsyncNode;
- }
- });
- });
- after(function() {
- getType.restore();
- });
- describe('#start',function() {
- it("instantiates a subflow and stops it",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3","4"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-2","port":0}]},{"wires":[{"id":"sf1","port":0}]}]},
- {id:"sf1-1",type:"test","z":"sf1",x:166,y:99,"wires":[["sf1-2"]]},
- {id:"sf1-2",type:"test","z":"sf1",foo:"sf1-cn",x:166,y:99,"wires":[[]]},
- {id:"sf1-cn",type:"test","z":"sf1"}
- ]);
- var flow = Flow.create({handleError: (a,b,c) => { console.log(a,b,c); }},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(4);
- // var sfInstanceId = Object.keys(activeNodes)[5];
- // var sfInstanceId2 = Object.keys(activeNodes)[6];
- var sfConfigId = Object.keys(activeNodes)[4];
-
- flow.getNode('1').should.have.a.property('id','1');
- flow.getNode('2').should.have.a.property('id','2');
- flow.getNode('3').should.have.a.property('id','3');
- flow.getNode('4').should.have.a.property('id','4');
- // flow.getNode(sfInstanceId).should.have.a.property('id',sfInstanceId);
- // flow.getNode(sfInstanceId2).should.have.a.property('id',sfInstanceId2);
- // flow.getNode(sfConfigId).should.have.a.property('id',sfConfigId);
-
- // flow.getNode(sfInstanceId2).should.have.a.property('foo',sfConfigId);
-
- Object.keys(currentNodes).should.have.length(6);
-
- currentNodes.should.have.a.property("1");
- currentNodes.should.not.have.a.property("2");
- currentNodes.should.have.a.property("3");
- currentNodes.should.have.a.property("4");
- // currentNodes.should.have.a.property(sfInstanceId);
- // currentNodes.should.have.a.property(sfInstanceId2);
- // currentNodes.should.have.a.property(sfConfigId);
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
- currentNodes["4"].should.have.a.property("handled",0);
- // currentNodes[sfInstanceId].should.have.a.property("handled",0);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
- currentNodes["4"].should.have.a.property("handled",1);
-
-
-
- flow.stop().then(function() {
- Object.keys(currentNodes).should.have.length(0);
- Object.keys(stoppedNodes).should.have.length(6);
-
- // currentNodes.should.not.have.a.property("1");
- // currentNodes.should.not.have.a.property("3");
- // currentNodes.should.not.have.a.property("4");
- // // currentNodes.should.not.have.a.property(sfInstanceId);
- // // currentNodes.should.not.have.a.property(sfInstanceId2);
- // // currentNodes.should.not.have.a.property(sfConfigId);
- // stoppedNodes.should.have.a.property("1");
- // stoppedNodes.should.have.a.property("3");
- // stoppedNodes.should.have.a.property("4");
- // // stoppedNodes.should.have.a.property(sfInstanceId);
- // // stoppedNodes.should.have.a.property(sfInstanceId2);
- // // stoppedNodes.should.have.a.property(sfConfigId);
- done();
- });
- },150);
- });
- it("instantiates a subflow inside a subflow and stops it",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3","4"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 1","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-2","port":0}]}]},
- {id:"sf2",type:"subflow","name":"Subflow 2","info":"",
- "in":[{wires:[]}],"out":[{"wires":[{"id":"sf2","port":0}]}]},
- {id:"sf1-1",type:"test","z":"sf1",x:166,y:99,"wires":[["sf1-2"]]},
- {id:"sf1-2",type:"subflow:sf2","z":"sf1",x:166,y:99,"wires":[[]]}
-
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
- flow.stop().then(function() {
- Object.keys(currentNodes).should.have.length(0);
- done();
- });
- },150);
- });
- it("rewires a subflow node on update/start",function(done){
-
- var rawConfig = [
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"4",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-2","port":0}]}]},
- {id:"sf1-1",type:"test1","z":"sf1",x:166,y:99,"wires":[["sf1-2"]]},
- {id:"sf1-2",type:"test2","z":"sf1",x:166,y:99,"wires":[[]]}
- ];
-
- var config = flowUtils.parseConfig(clone(rawConfig));
-
- rawConfig[2].wires = [["4"]];
-
- var newConfig = flowUtils.parseConfig(rawConfig);
- var diff = flowUtils.diffConfigs(config,newConfig);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(4);
- // var sfInstanceId = Object.keys(activeNodes)[4];
- // var sfInstanceId2 = Object.keys(activeNodes)[5];
-
- currentNodes["1"].should.have.a.property("handled",0);
- currentNodes["3"].should.have.a.property("handled",0);
- currentNodes["4"].should.have.a.property("handled",0);
-
- currentNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["1"].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId].should.have.a.property("handled",1);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",1);
- currentNodes["3"].should.have.a.property("handled",1);
- currentNodes["4"].should.have.a.property("handled",0);
-
- flow.update(newConfig,newConfig.flows["t1"]);
- flow.start(diff)
-
- currentNodes["1"].receive({payload:"test2"});
- setTimeout(function() {
-
- currentNodes["1"].should.have.a.property("handled",2);
- // currentNodes[sfInstanceId].should.have.a.property("handled",2);
- // currentNodes[sfInstanceId2].should.have.a.property("handled",2);
- currentNodes["3"].should.have.a.property("handled",1);
- currentNodes["4"].should.have.a.property("handled",1);
-
-
- flow.stop().then(function() {
- done();
- });
- },150);
- },150);
- });
- });
- describe('#stop', function() {
- it("stops subflow instance nodes",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",type:"test","z":"sf1",x:166,y:99,"wires":[[]]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
- Object.keys(activeNodes).should.have.length(3);
- Object.keys(stoppedNodes).should.have.length(0);
- flow.stop(["2"]).then(function() {
- Object.keys(currentNodes).should.have.length(2);
- Object.keys(stoppedNodes).should.have.length(1);
- done();
- }).catch(done);
- });
- });
- describe("#handleStatus",function() {
- it("passes a status event to the subflow's parent tab status node - all scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",type:"testStatus",name:"test-status-node","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","test status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("type","testStatus");
- statusMessage.status.source.should.have.a.property("name","test-status-node");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
- it("passes a status event to the subflow's parent tab status node - targetted scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",type:"testStatus",name:"test-status-node","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",scope:["2"],wires:[]}
- ]);
- var parentFlowStatusCalled = false;
-
- var flow = Flow.create({handleStatus:() => { parentFlowStatusCalled = true} },config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- parentFlowStatusCalled.should.be.false();
-
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","test status");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("type","testStatus");
- statusMessage.status.source.should.have.a.property("name","test-status-node");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- });
-
- describe("status node", function() {
- it("emits a status event when a message is passed to a subflow-status node - msg.payload as string", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[{id:"sf1-1", port:0}]}
- },
- {id:"sf1-1",type:"test",name:"test","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test-payload"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","test-payload");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","2");
- statusMessage.status.source.should.have.a.property("type","subflow:sf1");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- it("emits a status event when a message is passed to a subflow-status node - msg.payload as status obj", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[{id:"sf1-1", port:0}]}
- },
- {id:"sf1-1",type:"test",name:"test","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:{text:"payload-obj"}});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","payload-obj");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","2");
- statusMessage.status.source.should.have.a.property("type","subflow:sf1");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- it("emits a status event when a message is passed to a subflow-status node - msg.status", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[{id:"sf1-1", port:0}]}
- },
- {id:"sf1-1",type:"test",name:"test","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({status:{text:"status-obj"}});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("status");
- statusMessage.status.should.have.a.property("text","status-obj");
- statusMessage.status.should.have.a.property("source");
- statusMessage.status.source.should.have.a.property("id","2");
- statusMessage.status.source.should.have.a.property("type","subflow:sf1");
-
- flow.stop().then(function() {
-
- done();
- });
- },150);
- });
- it("does not emit a regular status event if it contains a subflow-status node", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {
- id:"sf1",
- type:"subflow",
- name:"Subflow 2",
- info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-1",port:0}]}],
- status:{wires:[]}
- },
- {id:"sf1-1",type:"testStatus",name:"test-status-node","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"status",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test-payload"});
-
- currentNodes["sn"].should.have.a.property("handled",0);
-
- flow.stop().then(function() {
-
- done();
- });
- });
- })
-
- describe("#handleError",function() {
- it("passes an error event to the subflow's parent tab catch node - all scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",name:"test-error-node",type:"testError","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",foo:"a",wires:[]}
- ]);
- var flow = Flow.create({},config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","test error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("type","testError");
- statusMessage.error.source.should.have.a.property("name","test-error-node");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
- it("passes an error event to the subflow's parent tab catch node - targetted scope",function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",name:"a",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"a",wires:[]},
- {id:"sf1",type:"subflow","name":"Subflow 2","info":"",
- "in":[{"wires":[{"id":"sf1-1"}]}],"out":[{"wires":[{"id":"sf1-1","port":0}]}]},
- {id:"sf1-1",name:"test-error-node",type:"testError","z":"sf1",x:166,y:99,"wires":[[]]},
- {id:"sn",x:10,y:10,z:"t1",type:"catch",scope:["2"],wires:[]}
- ]);
- var parentFlowErrorCalled = false;
- var flow = Flow.create({handleError:() => { parentFlowErrorCalled = true} },config,config.flows["t1"]);
-
- flow.start();
-
- var activeNodes = flow.getActiveNodes();
-
- activeNodes["1"].receive({payload:"test"});
-
- setTimeout(function() {
- parentFlowErrorCalled.should.be.false();
-
- currentNodes["sn"].should.have.a.property("handled",1);
- var statusMessage = currentNodes["sn"].messages[0];
-
- statusMessage.should.have.a.property("error");
- statusMessage.error.should.have.a.property("message","test error");
- statusMessage.error.should.have.a.property("source");
- statusMessage.error.source.should.have.a.property("type","testError");
- statusMessage.error.source.should.have.a.property("name","test-error-node");
-
- flow.stop().then(function() {
- done();
- });
- },150);
-
- });
- });
-
- describe("#env var", function() {
- // should be changed according to internal env var representation
- function setEnv(node, key, val) {
- var flow = node._flow;
- if (flow) {
- var env = flow.env;
- if (!env) {
- env = flow.env = {};
- }
- env[key] = {
- name: key,
- type: "str",
- value: val
- };
- }
- }
-
- it("can access process env var", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]},
- {id:"sf1",type:"subflow",name:"Subflow 2",info:"",
- "in":[ {wires:[{id:"sf1-1"}]} ],
- "out":[ {wires:[{id:"sf1-2",port:0}]} ]},
- {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]},
- {id:"sf1-2",type:"testEnv",z:"sf1",foo:"sf1-cn",x:166,y:99,wires:[[]]}
- ]);
- var flow = Flow.create({
- getSetting: k=> process.env[k],
- handleError: (a,b,c) => { console.log(a,b,c); }
- },config,config.flows["t1"]);
-
- flow.start();
-
- process.env["__KEY__"] = "__VAL__";
-
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL__");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
-
- it("can access subflow env var", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]},
- {id:"sf1",type:"subflow",name:"Subflow 2",info:"",
- "in":[ {wires:[{id:"sf1-1"}]} ],
- "out":[ {wires:[{id:"sf1-2",port:0}]} ]},
- {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]},
- {id:"sf1-2",type:"testEnv",z:"sf1",foo:"sf1.2",x:166,y:99,wires:[[]]}
- ]);
- var flow = Flow.create({
- getSetting: k=> process.env[k],
- handleError: (a,b,c) => { console.log(a,b,c); }
- },config,config.flows["t1"]);
-
- flow.start();
-
- var testenv_node = null;
- for (var n in currentNodes) {
- var node = currentNodes[n];
- if (node.type === "testEnv") {
- testenv_node = node;
- break;
- }
- }
- process.env["__KEY__"] = "__VAL0__";
- setEnv(testenv_node, "__KEY__", "__VAL1__");
-
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL1__");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- });
-
- it("can access nested subflow env var", function(done) {
- var config = flowUtils.parseConfig([
- {id:"t1",type:"tab"},
- {id:"1",x:10,y:10,z:"t1",type:"test",foo:"t1.1",wires:["2"]},
- {id:"2",x:10,y:10,z:"t1",type:"subflow:sf1",wires:["3"]},
- {id:"3",x:10,y:10,z:"t1",type:"test",foo:"t1.3",wires:[]},
- {id:"sf1",type:"subflow",name:"Subflow 1",info:"",
- in:[{wires:[{id:"sf1-1"}]}],
- out:[{wires:[{id:"sf1-2",port:0}]}]},
- {id:"sf2",type:"subflow",name:"Subflow 2",info:"",
- in:[{wires:[{id:"sf2-1"}]}],
- out:[{wires:[{id:"sf2-2",port:0}]}]},
- {id:"sf1-1",type:"test",z:"sf1",foo:"sf1.1",x:166,y:99,wires:[["sf1-2"]]},
- {id:"sf1-2",type:"subflow:sf2",z:"sf1",x:166,y:99,wires:[[]]},
- {id:"sf2-1",type:"test",z:"sf2",foo:"sf2.1",x:166,y:99,wires:[["sf2-2"]]},
- {id:"sf2-2",type:"testEnv",z:"sf2",foo:"sf2.2",x:166,y:99,wires:[[]]},
- ]);
- var flow = Flow.create({
- getSetting: k=> process.env[k],
- handleError: (a,b,c) => { console.log(a,b,c); }
- },config,config.flows["t1"]);
-
- flow.start();
-
- var node_sf1_1 = null;
- var node_sf2_1 = null;
- var testenv_node = null;
- for (var n in currentNodes) {
- var node = currentNodes[n];
- if (node.foo === "sf1.1") {
- node_sf1_1 = node;
- }
- if (node.foo === "sf2.1") {
- node_sf2_1 = node;
- }
- }
-
- process.env["__KEY__"] = "__VAL0__";
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL0__");
-
- setEnv(node_sf1_1, "__KEY__", "__VAL1__");
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL1__");
-
- setEnv(node_sf2_1, "__KEY__", "__VAL2__");
- currentNodes["1"].receive({payload: "test"});
- setTimeout(function() {
- currentNodes["3"].should.have.a.property("received", "__VAL2__");
-
- flow.stop().then(function() {
- done();
- });
- },150);
- },150);
- },150);
- });
-
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/flows/index_spec.js b/test/unit/@node-red/runtime/lib/flows/index_spec.js
deleted file mode 100644
index 737846100..000000000
--- a/test/unit/@node-red/runtime/lib/flows/index_spec.js
+++ /dev/null
@@ -1,669 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var clone = require("clone");
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var RedNode = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var RED = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes");
-var events = NR_TEST_UTILS.require("@node-red/util/lib/events");
-var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry")
-var Flow = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/Flow");
-
-describe('flows/index', function() {
-
- var storage;
- var eventsOn;
- var credentialsClean;
- var credentialsLoad;
- var credentialsAdd;
-
- var flowCreate;
- var getType;
- var checkFlowDependencies;
-
- var mockLog = {
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- _: function() { return "abc"}
- }
-
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- return type.indexOf('missing') === -1;
- });
- checkFlowDependencies = sinon.stub(typeRegistry, "checkFlowDependencies").callsFake(async function(flow) {
- if (flow[0].id === "node-with-missing-modules") {
- throw new Error("Missing module");
- }
- });
- });
-
- after(function() {
- getType.restore();
- checkFlowDependencies.restore();
- });
-
-
- beforeEach(function() {
- eventsOn = sinon.spy(events,"on");
- credentialsClean = sinon.stub(credentials,"clean").callsFake(function(conf) {
- conf.forEach(function(n) {
- delete n.credentials;
- });
- return Promise.resolve();
- });
- credentialsLoad = sinon.stub(credentials,"load").callsFake(function(creds) {
- if (creds && creds.hasOwnProperty("$") && creds['$'] === "fail") {
- return Promise.reject("creds error");
- }
- return Promise.resolve();
- });
- credentialsAdd = sinon.stub(credentials,"add").callsFake(async function(id, conf){})
- flowCreate = sinon.stub(Flow,"create").callsFake(function(parent, global, flow) {
- var id;
- if (typeof flow === 'undefined') {
- flow = global;
- id = '_GLOBAL_';
- } else {
- id = flow.id;
- }
- flowCreate.flows[id] = {
- flow: flow,
- global: global,
- start: sinon.spy(),
- update: sinon.spy(),
- stop: sinon.spy(),
- getActiveNodes: function() {
- return flow.nodes||{};
- },
- handleError: sinon.spy(),
- handleStatus: sinon.spy()
-
- }
- return flowCreate.flows[id];
- });
- flowCreate.flows = {};
-
- storage = {
- saveFlows: function(conf) {
- storage.conf = conf;
- return Promise.resolve();
- }
- }
- });
-
- afterEach(function(done) {
- eventsOn.restore();
- credentialsClean.restore();
- credentialsLoad.restore();
- credentialsAdd.restore();
- flowCreate.restore();
-
- flows.stopFlows().then(done);
-
- });
- // describe('#init',function() {
- // it('registers the type-registered handler', function() {
- // flows.init({},{});
- // eventsOn.calledOnce.should.be.true();
- // });
- // });
-
- describe('#setFlows', function() {
- it('sets the full flow', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- credentialsClean.called.should.be.true();
- storage.hasOwnProperty('conf').should.be.true();
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
-
- });
- it('loads the full flow for type load', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var loadStorage = {
- saveFlows: function(conf) {
- loadStorage.conf = conf;
- return Promise.resolve(456);
- },
- getFlows: function() {
- return Promise.resolve({flows:originalConfig,rev:123})
- }
- }
- flows.init({log:mockLog, settings:{},storage:loadStorage});
- flows.setFlows(originalConfig,"load").then(function() {
- credentialsClean.called.should.be.false();
- // 'load' type does not trigger a save
- loadStorage.hasOwnProperty('conf').should.be.false();
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
-
- });
-
- it('extracts credentials from the full flow', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[],credentials:{"a":1}},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- credentialsClean.called.should.be.true();
- storage.hasOwnProperty('conf').should.be.true();
- var cleanedFlows = flows.getFlows();
- storage.conf.flows.should.eql(cleanedFlows.flows);
- cleanedFlows.flows.should.not.eql(originalConfig);
- cleanedFlows.flows[0].credentials = {"a":1};
- cleanedFlows.flows.should.eql(originalConfig);
- done();
- });
- });
-
- it('sets the full flow including credentials', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var credentials = {"t1-1":{"a":1}};
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig,credentials).then(function() {
- credentialsClean.called.should.be.true();
- credentialsAdd.called.should.be.true();
- credentialsAdd.lastCall.args[0].should.eql("t1-1");
- credentialsAdd.lastCall.args[1].should.eql({"a":1});
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
- });
-
- it('updates existing flows with partial deployment - nodes', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var newConfig = clone(originalConfig);
- newConfig.push({id:"t1-2",x:10,y:10,z:"t1",type:"test",wires:[]});
- newConfig.push({id:"t2",type:"tab"});
- newConfig.push({id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]});
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- events.once('flows:started',function() {
- flows.setFlows(newConfig,"nodes").then(function() {
- flows.getFlows().flows.should.eql(newConfig);
- flowCreate.flows['t1'].update.called.should.be.true();
- flowCreate.flows['t2'].start.called.should.be.true();
- flowCreate.flows['_GLOBAL_'].update.called.should.be.true();
- done();
- })
- });
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- flows.startFlows();
- });
- });
-
- it('updates existing flows with partial deployment - flows', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var newConfig = clone(originalConfig);
- newConfig.push({id:"t1-2",x:10,y:10,z:"t1",type:"test",wires:[]});
- newConfig.push({id:"t2",type:"tab"});
- newConfig.push({id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]});
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
-
- events.once('flows:started',function() {
- flows.setFlows(newConfig,"nodes").then(function() {
- flows.getFlows().flows.should.eql(newConfig);
- flowCreate.flows['t1'].update.called.should.be.true();
- flowCreate.flows['t2'].start.called.should.be.true();
- flowCreate.flows['_GLOBAL_'].update.called.should.be.true();
- flows.stopFlows().then(done);
- })
- });
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- flows.startFlows();
- });
- });
-
- it('returns error if it cannot decrypt credentials', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var credentials = {"$":"fail"};
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig,credentials).then(function() {
- done("Unexpected success when credentials couldn't be decrypted")
- }).catch(function(err) {
- done();
- });
- });
- });
-
- describe('#load', function() {
- it('loads the flow config', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- credentialsLoad.called.should.be.true();
- // 'load' type does not trigger a save
- storage.hasOwnProperty('conf').should.be.false();
- flows.getFlows().flows.should.eql(originalConfig);
- done();
- });
- });
- });
-
- describe('#startFlows', function() {
- it('starts the loaded config', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
-
- events.once('flows:started',function() {
- Object.keys(flowCreate.flows).should.eql(['_GLOBAL_','t1']);
- done();
- });
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- });
- });
- it('does not start if nodes missing', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1-2",x:10,y:10,z:"t1",type:"missing",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- }).then(() => {
- try {
- flowCreate.called.should.be.false();
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('starts when missing nodes registered', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1-2",x:10,y:10,z:"t1",type:"missing",wires:[]},
- {id:"t1-3",x:10,y:10,z:"t1",type:"missing2",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- }).then(() => {
- flowCreate.called.should.be.false();
- events.emit("type-registered","missing");
- setTimeout(function() {
- flowCreate.called.should.be.false();
- events.emit("type-registered","missing2");
- setTimeout(function() {
- flowCreate.called.should.be.true();
- done();
- },10);
- },10);
- });
- });
-
- it('does not start if external modules missing', function(done) {
- var originalConfig = [
- {id:"node-with-missing-modules",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
-
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- var receivedEvent = null;
- var handleEvent = function(payload) {
- receivedEvent = payload;
- }
-
- events.on("runtime-event",handleEvent);
-
- //{id:"runtime-state",payload:{error:"missing-modules", type:"warning",text:"notification.warnings.missing-modules",modules:missingModules},retain:true});"
-
-
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(flows.startFlows).then(() => {
- events.removeListener("runtime-event",handleEvent);
- try {
- flowCreate.called.should.be.false();
- receivedEvent.should.have.property('id','runtime-state');
- receivedEvent.should.have.property('payload',
- { error: 'missing-modules',
- type: 'warning',
- text: 'notification.warnings.missing-modules',
- modules: [] }
- );
-
- done();
- }catch(err) {
- done(err)
- }
- });
- });
-
- });
-
- describe.skip('#get',function() {
-
- });
-
- describe('#eachNode', function() {
- it('iterates the flow nodes', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- var c = 0;
- flows.eachNode(function(node) {
- c++
- })
- c.should.equal(2);
- done();
- });
- });
- });
-
- describe('#stopFlows', function() {
-
- });
- // describe('#handleError', function() {
- // it('passes error to correct flow', function(done) {
- // var originalConfig = [
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- // {id:"t1",type:"tab"}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleError(originalConfig[0],"message",{});
- // flowCreate.flows['t1'].handleError.called.should.be.true();
- // done();
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- // it('passes error to flows that use the originating global config', function(done) {
- // var originalConfig = [
- // {id:"configNode",type:"test"},
- // {id:"t1",type:"tab"},
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",config:"configNode",wires:[]},
- // {id:"t2",type:"tab"},
- // {id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]},
- // {id:"t3",type:"tab"},
- // {id:"t3-1",x:10,y:10,z:"t3",type:"test",config:"configNode",wires:[]}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleError(originalConfig[0],"message",{});
- // try {
- // flowCreate.flows['t1'].handleError.called.should.be.true();
- // flowCreate.flows['t2'].handleError.called.should.be.false();
- // flowCreate.flows['t3'].handleError.called.should.be.true();
- // done();
- // } catch(err) {
- // done(err);
- // }
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- // });
- // describe('#handleStatus', function() {
- // it('passes status to correct flow', function(done) {
- // var originalConfig = [
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- // {id:"t1",type:"tab"}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleStatus(originalConfig[0],"message");
- // flowCreate.flows['t1'].handleStatus.called.should.be.true();
- // done();
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- //
- // it('passes status to flows that use the originating global config', function(done) {
- // var originalConfig = [
- // {id:"configNode",type:"test"},
- // {id:"t1",type:"tab"},
- // {id:"t1-1",x:10,y:10,z:"t1",type:"test",config:"configNode",wires:[]},
- // {id:"t2",type:"tab"},
- // {id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]},
- // {id:"t3",type:"tab"},
- // {id:"t3-1",x:10,y:10,z:"t3",type:"test",config:"configNode",wires:[]}
- // ];
- // storage.getFlows = function() {
- // return Promise.resolve({flows:originalConfig});
- // }
- //
- // events.once('flows:started',function() {
- // flows.handleStatus(originalConfig[0],"message");
- // try {
- // flowCreate.flows['t1'].handleStatus.called.should.be.true();
- // flowCreate.flows['t2'].handleStatus.called.should.be.false();
- // flowCreate.flows['t3'].handleStatus.called.should.be.true();
- // done();
- // } catch(err) {
- // done(err);
- // }
- // });
- //
- // flows.init({log:mockLog, settings:{},storage:storage});
- // flows.load().then(function() {
- // flows.startFlows();
- // });
- // });
- // });
-
- describe('#checkTypeInUse', function() {
-
- before(function() {
- sinon.stub(typeRegistry,"getNodeInfo").callsFake(function(id) {
- if (id === 'unused-module') {
- return {types:['one','two','three']}
- } else {
- return {types:['one','test','three']}
- }
- });
- });
-
- after(function() {
- typeRegistry.getNodeInfo.restore();
- });
-
- it('returns cleanly if type not is use', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- flows.checkTypeInUse("unused-module");
- done();
- });
- });
- it('throws error if type is in use', function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.setFlows(originalConfig).then(function() {
- /*jshint immed: false */
- try {
- flows.checkTypeInUse("used-module");
- done("type_in_use error not thrown");
- } catch(err) {
- err.code.should.eql("type_in_use");
- done();
- }
- });
- });
- });
-
- describe('#addFlow', function() {
- it("rejects duplicate node id",function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- flows.addFlow({
- label:'new flow',
- nodes:[
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]}
- ]
- }).then(function() {
- done(new Error('failed to reject duplicate node id'));
- }).catch(function(err) {
- done();
- })
- });
-
- });
-
- it("addFlow",function(done) {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- storage.getFlows = function() {
- return Promise.resolve({flows:originalConfig});
- }
- storage.setFlows = function() {
- return Promise.resolve();
- }
- flows.init({log:mockLog, settings:{},storage:storage});
- flows.load().then(function() {
- return flows.startFlows();
- }).then(function() {
- flows.addFlow({
- label:'new flow',
- nodes:[
- {id:"t2-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t2-2",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t2-3",z:"t1",type:"test"}
- ]
- }).then(function(id) {
- flows.getFlows().flows.should.have.lengthOf(6);
- var createdFlows = Object.keys(flowCreate.flows);
- createdFlows.should.have.lengthOf(3);
- createdFlows[2].should.eql(id);
- done();
- }).catch(function(err) {
- done(err);
- })
- });
-
- });
- })
- describe('#updateFlow', function() {
- it.skip("updateFlow");
- })
- describe('#removeFlow', function() {
- it.skip("removeFlow");
- })
- describe('#disableFlow', function() {
- it.skip("disableFlow");
- })
- describe('#enableFlow', function() {
- it.skip("enableFlow");
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/flows/util_spec.js b/test/unit/@node-red/runtime/lib/flows/util_spec.js
deleted file mode 100644
index 6a4571e87..000000000
--- a/test/unit/@node-red/runtime/lib/flows/util_spec.js
+++ /dev/null
@@ -1,801 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var clone = require("clone");
-var NR_TEST_UTILS = require("nr-test-utils");
-var flowUtil = NR_TEST_UTILS.require("@node-red/runtime/lib/flows/util");
-var typeRegistry = NR_TEST_UTILS.require("@node-red/registry");
-var redUtil = NR_TEST_UTILS.require("@node-red/util").util;
-
-describe('flows/util', function() {
- var getType;
-
- before(function() {
- getType = sinon.stub(typeRegistry,"get").callsFake(function(type) {
- return type!=='missing';
- });
- });
- after(function() {
- getType.restore();
- });
-
- describe('#mapEnvVarProperties',function() {
- before(function() {
- process.env.foo1 = "bar1";
- process.env.foo2 = "bar2";
- process.env.foo3 = "bar3";
- })
- after(function() {
- delete process.env.foo1;
- delete process.env.foo2;
- delete process.env.foo3;
- })
- it('handles ENV substitutions in an object - $()', function() {
- var foo = {a:"$(foo1)",b:"$(foo2)",c:{d:"$(foo3)"}};
- for (var p in foo) {
- if (foo.hasOwnProperty(p)) {
- flowUtil.mapEnvVarProperties(foo,p,{getSetting: p => process.env[p]});
- }
- }
- foo.should.eql({ a: 'bar1', b: 'bar2', c: { d: 'bar3' } } );
- });
- it('handles ENV substitutions in an object - ${}', function() {
- var foo = {a:"${foo1}",b:"${foo2}",c:{d:"${foo3}"}};
- for (var p in foo) {
- if (foo.hasOwnProperty(p)) {
- flowUtil.mapEnvVarProperties(foo,p,{getSetting: p => process.env[p]});
- }
- }
- foo.should.eql({ a: 'bar1', b: 'bar2', c: { d: 'bar3' } } );
- });
-
- it('gets ENV from parent flow', function() {
- var foo = {a:"$(unknown)",b:"$(foo2)",c:{d:"$(foo3)"}};
- for (var p in foo) {
- if (foo.hasOwnProperty(p)) {
- flowUtil.mapEnvVarProperties(foo,p,{
- getSetting: name => name[0]==='f'?name.toUpperCase():undefined
- });
- }
- }
- foo.should.eql({ a: '$(unknown)', b: 'FOO2', c: { d: 'FOO3' } } );
- });
- });
- describe('#getEnvVar',function() {
- before(function() {
- process.env.foo1 = "bar1";
- })
- after(function() {
- delete process.env.foo1;
- })
- it('returns a known env var', function() {
- flowUtil.init({settings:{}});
- flowUtil.getEnvVar("foo1").should.equal("bar1")
- })
- it('returns undefined for an unknown env var', function() {
- flowUtil.init({settings:{}});
- (flowUtil.getEnvVar("foo2") === undefined).should.be.true()
- })
- it('returns undefined for an excluded env var', function() {
- flowUtil.init({settings:{envVarExcludes:['foo1']}});
- (flowUtil.getEnvVar("foo1") === undefined).should.be.true()
- })
-
- });
-
- describe('#diffNodes',function() {
- it('handles a null old node', function() {
- flowUtil.diffNodes(null,{}).should.be.true();
- });
- it('ignores x/y changes', function() {
- flowUtil.diffNodes({x:10,y:10},{x:20,y:10}).should.be.false();
- flowUtil.diffNodes({x:10,y:10},{x:10,y:20}).should.be.false();
- });
- it('ignores wiring changes', function() {
- flowUtil.diffNodes({wires:[]},{wires:[1,2,3]}).should.be.false();
- });
- it('spots existing property change - string', function() {
- flowUtil.diffNodes({a:"foo"},{a:"bar"}).should.be.true();
- });
- it('spots existing property change - number', function() {
- flowUtil.diffNodes({a:0},{a:1}).should.be.true();
- });
- it('spots existing property change - boolean', function() {
- flowUtil.diffNodes({a:true},{a:false}).should.be.true();
- });
- it('spots existing property change - truthy', function() {
- flowUtil.diffNodes({a:true},{a:1}).should.be.true();
- });
- it('spots existing property change - falsey', function() {
- flowUtil.diffNodes({a:false},{a:0}).should.be.true();
- });
- it('spots existing property change - array', function() {
- flowUtil.diffNodes({a:[0,1,2]},{a:[0,2,3]}).should.be.true();
- });
- it('spots existing property change - object', function() {
- flowUtil.diffNodes({a:{a:[0,1,2]}},{a:{a:[0,2,3]}}).should.be.true();
- flowUtil.diffNodes({a:{a:[0,1,2]}},{a:{b:[0,1,2]}}).should.be.true();
- });
- it('spots added property', function() {
- flowUtil.diffNodes({a:"foo"},{a:"foo",b:"bar"}).should.be.true();
- });
- it('spots removed property', function() {
- flowUtil.diffNodes({a:"foo",b:"bar"},{a:"foo"}).should.be.true();
- });
-
-
- });
-
- describe('#parseConfig',function() {
-
- it('parses a single-tab flow', function() {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t1",type:"tab"}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]},"t1":{"id":"t1","type":"tab"}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a single-tab flow with global config node', function() {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",foo:"cn", wires:[]},
- {id:"cn",type:"test"},
- {id:"t1",type:"tab"}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]},"cn":{"id":"cn","type":"test"},"t1":{"id":"t1","type":"tab"}},"subflows":{},"configs":{"cn":{"id":"cn","type":"test","_users":["t1-1"]}},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a multi-tab flow', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"t2",type:"tab"},
- {id:"t2-1",x:10,y:10,z:"t2",type:"test",wires:[]}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]},"t2":{"id":"t2","type":"tab"},"t2-1":{"id":"t2-1","x":10,"y":10,"z":"t2","type":"test","wires":[]}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]}}},"t2":{"id":"t2","type":"tab","subflows":{},"configs":{},"nodes":{"t2-1":{"id":"t2-1","x":10,"y":10,"z":"t2","type":"test","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a subflow flow', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"subflow:sf1",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",x:10,y:10,z:"sf1",type:"test",wires:[]}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"subflow:sf1","wires":[]},"sf1":{"id":"sf1","type":"subflow"},"sf1-1":{"id":"sf1-1","x":10,"y":10,"z":"sf1","type":"test","wires":[]}},"subflows":{"sf1":{"id":"sf1","type":"subflow","configs":{},"nodes":{"sf1-1":{"id":"sf1-1","x":10,"y":10,"z":"sf1","type":"test","wires":[]}},"instances":[{"id":"t1-1","x":10,"y":10,"z":"t1","type":"subflow:sf1","wires":[],"subflow":"sf1"}]}},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"subflow:sf1","wires":[],"subflow":"sf1"}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a flow with a missing type', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"sf1",wires:[]},
- {id:"t1-2",x:10,y:10,z:"t1",type:"missing",wires:[]},
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- parsedConfig.missingTypes.should.eql(['missing']);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]},"t1-2":{"id":"t1-2","x":10,"y":10,"z":"t1","type":"missing","wires":[]}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"sf1","wires":[]},'t1-2': { id: 't1-2', x: 10, y: 10, z: 't1', type: 'missing', wires: [] }}}},"groups":{},"missingTypes":["missing"]};
- redUtil.compareObjects(parsedConfig,expectedConfig).should.be.true();
- });
-
- it('parses a flow with a missing flow', function() {
- var originalConfig = [
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",foo:"cn", wires:[]},
- {id:"cn",type:"test"},
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]},"cn":{"id":"cn","type":"test"}},"subflows":{},"configs":{"cn":{"id":"cn","type":"test","_users":["t1-1"]}},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","foo":"cn","wires":[]}}}},"groups":{},"missingTypes":[]};
- parsedConfig.should.eql(expectedConfig);
- });
-
- it('parses a flow including a group', function() {
- var originalConfig = [
- {id:"t1",type:"tab"},
- {id:"t1-1",x:10,y:10,z:"t1",type:"test",wires:[]},
- {id:"g1",type:"group",z:"t1"}
- ];
- var parsedConfig = flowUtil.parseConfig(originalConfig);
- var expectedConfig = {"allNodes":{"t1":{"id":"t1","type":"tab"},"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]},"g1":{"id":"g1","type":"group","z":"t1"}},"subflows":{},"configs":{},"flows":{"t1":{"id":"t1","type":"tab","subflows":{},"configs":{},"nodes":{"t1-1":{"id":"t1-1","x":10,"y":10,"z":"t1","type":"test","wires":[]}}}},"groups":{"g1":{"id":"g1","type":"group","z":"t1"}},"missingTypes":[]}
- parsedConfig.should.eql(expectedConfig);
- });
-
- });
-
- describe('#diffConfigs', function() {
-
- it('handles an identical configuration', function() {
- var config = [{id:"123",type:"test",foo:"a",wires:[]}];
-
- var originalConfig = flowUtil.parseConfig(clone(config));
- var changedConfig = flowUtil.parseConfig(clone(config));
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.have.length(0);
- });
-
- it('identifies nodes with changed properties, including downstream linked', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[[1]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[0].foo = "b";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.eql(["1"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.eql(["2"]);
-
- });
- it('identifies nodes with changed properties, including upstream linked', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].bar = "c";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.eql(["2"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.eql(["1"]);
- });
-
- it('identifies nodes with changed credentials, including downstream linked', function() {
- var config = [{id:"1",type:"test",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[0].credentials = {};
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.eql(["1"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.should.eql(["2"]);
- });
-
- it('identifies nodes with changed wiring', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].wires[0][0] = "3";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.eql(["2"]);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('identifies nodes with changed wiring - second connection added', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"2",type:"test",bar:"b",wires:[["1"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].wires[0].push("1");
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.eql(["2"]);
- diffResult.linked.sort().should.eql(["1"]);
- });
-
- it('identifies nodes with changed wiring - node connected', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[["2"]]},{id:"2",type:"test",bar:"b",wires:[[]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig[1].wires.push("3");
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.eql(["2"]);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('identifies new nodes', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig.push({id:"2",type:"test",bar:"b",wires:[["1"]]});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.eql(["2"]);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1"]);
- });
-
- it('identifies deleted nodes', function() {
- var config = [{id:"1",type:"test",foo:"a",wires:[["2"]]},{id:"2",type:"test",bar:"b",wires:[["3"]]},{id:"3",type:"test",foo:"a",wires:[]}];
- var newConfig = clone(config);
- newConfig.splice(1,1);
- newConfig[0].wires = [];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.eql(["2"]);
- diffResult.rewired.should.eql(["1"]);
- diffResult.linked.sort().should.eql(["3"]);
- });
-
- it('identifies config nodes changes, node->config', function() {
- var config = [
- {id:"1",type:"test",foo:"configNode",wires:[["2"]]},
- {id:"2",type:"test",bar:"b",wires:[["3"]]},
- {id:"3",type:"test",foo:"a",wires:[]},
- {id:"configNode",type:"testConfig"}
- ];
- var newConfig = clone(config);
- newConfig[3].foo = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(["1","configNode"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["2","3"]);
- });
-
- it('identifies config nodes changes, node->config->config', function() {
- var config = [
- {id:"1",type:"test",foo:"configNode1",wires:[["2"]]},
- {id:"2",type:"test",bar:"b",wires:[["3"]]},
- {id:"3",type:"test",foo:"a",wires:[]},
- {id:"configNode1",foo:"configNode2",type:"testConfig"},
- {id:"configNode2",type:"testConfig"}
- ];
- var newConfig = clone(config);
- newConfig[4].foo = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(["1","configNode1","configNode2"]);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["2","3"]);
- });
-
- it('marks a parent subflow as changed for an internal property change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",foo:"a",wires:[]},
- {id:"4",type:"subflow:sf1",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[4].foo = "b";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', '4', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
-
-
- });
-
- it('marks a parent subflow as changed for an internal wiring change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[4].wires = [["sf1-2"]];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal node add', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig.push({id:"sf1-3",z:"sf1",type:"test",wires:[]});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
-
- });
-
- it('marks a parent subflow as changed for an internal node delete', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig.splice(5,1);
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(1);
- diffResult.removed.sort().should.eql(['sf1-2']);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
-
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - input removed', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].in[0].wires = [];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - input added', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].in[0].wires.push({"id":"sf1-2"});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - output added', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].out[0].wires.push({"id":"sf1-2","port":0});
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow wiring change - output removed', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow","in": [{"wires": [{"id": "sf1-1"}]}],"out": [{"wires": [{"id": "sf1-2","port": 0}]}]},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[3].out[0].wires = [];
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for a global config node change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf1-1",z:"sf1",prop:"configNode",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"test",wires:[]},
- {id:"configNode",a:"foo",type:"test",wires:[]}
- ];
-
- var newConfig = clone(config);
- newConfig[6].a = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', "configNode", 'sf1']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
- it('marks a parent subflow as changed for an internal subflow instance change', function() {
- var config = [
- {id:"1",type:"test",wires:[["2"]]},
- {id:"2",type:"subflow:sf1",wires:[["3"]]},
- {id:"3",type:"test",wires:[]},
- {id:"sf1",type:"subflow"},
- {id:"sf2",type:"subflow"},
- {id:"sf1-1",z:"sf1",type:"test",wires:[]},
- {id:"sf1-2",z:"sf1",type:"subflow:sf2",wires:[]},
- {id:"sf2-1",z:"sf2",type:"test",wires:[]},
- {id:"sf2-2",z:"sf2",type:"test",wires:[]},
- ];
-
- var newConfig = clone(config);
- newConfig[8].a = "bar";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.sort().should.eql(['2', 'sf1', 'sf2']);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- diffResult.linked.sort().should.eql(["1","3"]);
- });
-
-
- it('ignores tab changes that are immaterial', function() {
- var config = [{id:"1",type:"tab",label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"}];
- var newConfig = clone(config);
- newConfig[0].label = "barney";
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- });
-
-
- it('marks a deleted tab as removed', function() {
- var config = [{id:"f1",type:"tab",label:"fred"},{id:"n1",type:"test",bar:"b",wires:[["1"]],z:"f1"},
- {id:"f2",type:"tab",label:"fred"},{id:"n2",type:"test",bar:"b",wires:[["1"]],z:"f2"}];
- var newConfig = clone(config);
- newConfig = newConfig.slice(0,2);
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.sort().should.eql(['f2', 'n2']);
- diffResult.rewired.should.have.length(0);
- });
-
- it('marks all nodes as added when tab state changes disabled to enabled', function() {
- var config = [{id:"1",type:"tab",disabled:true,label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"},{id:"3",type:"test"}];
- var newConfig = clone(config);
- newConfig[0].disabled = false;
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(2);
- diffResult.added.sort().should.eql(["1","2"]);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(0);
- diffResult.rewired.should.have.length(0);
- });
- it('marks all nodes as removed when tab state changes enabled to disabled', function() {
- var config = [{id:"1",type:"tab",disabled:false,label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"},{id:"3",type:"test"}];
- var newConfig = clone(config);
- newConfig[0].disabled = true;
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(0);
- diffResult.removed.should.have.length(2);
- diffResult.removed.sort().should.eql(["1","2"]);
- diffResult.rewired.should.have.length(0);
- });
-
- it('marks a node as removed when its state changes enabled to disabled', function() {
- var config = [{id:"1",type:"tab",disabled:false,label:"fred"},{id:"2",type:"test",bar:"b",wires:[["1"]],z:"1"},{id:"3",type:"test"}];
- var newConfig = clone(config);
- newConfig[1].d = true;
-
- var originalConfig = flowUtil.parseConfig(config);
- var changedConfig = flowUtil.parseConfig(newConfig);
-
- originalConfig.missingTypes.should.have.length(0);
-
- var diffResult = flowUtil.diffConfigs(originalConfig,changedConfig);
-
- diffResult.added.should.have.length(0);
- diffResult.changed.should.have.length(2);
- diffResult.changed.sort().should.eql(["1","2"]);
- diffResult.removed.should.have.length(1);
- diffResult.removed.sort().should.eql(["2"]);
- diffResult.rewired.should.have.length(0);
- });
-
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/index_spec.js b/test/unit/@node-red/runtime/lib/index_spec.js
deleted file mode 100644
index 9041ba66e..000000000
--- a/test/unit/@node-red/runtime/lib/index_spec.js
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-var sinon = require("sinon");
-var path = require("path");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var api = NR_TEST_UTILS.require("@node-red/runtime/lib/api");
-var runtime = NR_TEST_UTILS.require("@node-red/runtime");
-
-var redNodes = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes");
-var storage = NR_TEST_UTILS.require("@node-red/runtime/lib/storage");
-var settings = NR_TEST_UTILS.require("@node-red/runtime/lib/settings");
-var util = NR_TEST_UTILS.require("@node-red/util");
-
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-describe("runtime", function() {
- afterEach(function() {
- if (console.log.restore) {
- console.log.restore();
- }
- })
-
- before(function() {
- process.env.NODE_RED_HOME = NR_TEST_UTILS.resolve("node-red");
- });
- after(function() {
- delete process.env.NODE_RED_HOME;
- });
- function mockUtil(metrics) {
- sinon.stub(log,"log").callsFake(function(){})
- sinon.stub(log,"warn").callsFake(function(){})
- sinon.stub(log,"info").callsFake(function(){})
- sinon.stub(log,"trace").callsFake(function(){})
- sinon.stub(log,"metric").callsFake(function(){ return !!metrics })
- sinon.stub(log,"_").callsFake(function(){ return "abc"})
- sinon.stub(i18n,"registerMessageCatalog").callsFake(function(){ return Promise.resolve()})
- }
- function unmockUtil() {
- log.log.restore && log.log.restore();
- log.warn.restore && log.warn.restore();
- log.info.restore && log.info.restore();
- log.trace.restore && log.trace.restore();
- log.metric.restore && log.metric.restore();
- log._.restore && log._.restore();
- i18n.registerMessageCatalog.restore && i18n.registerMessageCatalog.restore();
- }
- describe("init", function() {
- beforeEach(function() {
- sinon.stub(log,"init").callsFake(function() {});
- sinon.stub(settings,"init").callsFake(function() {});
- sinon.stub(redNodes,"init").callsFake(function() {})
- mockUtil();
- });
- afterEach(function() {
- log.init.restore();
- settings.init.restore();
- redNodes.init.restore();
- unmockUtil();
- })
-
- it("initialises components", function() {
- runtime.init({testSettings: true, httpAdminRoot:"/"});
- settings.init.called.should.be.true();
- redNodes.init.called.should.be.true();
- });
-
- it("returns version", function() {
- runtime.init({testSettings: true, httpAdminRoot:"/"});
- return runtime.version().then(version => {
- /^\d+\.\d+\.\d+(-.*)?$/.test(version).should.be.true();
- });
-
-
- })
- });
-
- describe("start",function() {
- var storageInit;
- var settingsLoad;
- var redNodesInit;
- var redNodesLoad;
- var redNodesCleanModuleList;
- var redNodesGetNodeList;
- var redNodesLoadFlows;
- var redNodesStartFlows;
- var redNodesLoadContextsPlugin;
-
- beforeEach(function() {
- storageInit = sinon.stub(storage,"init").callsFake(function(settings) {return Promise.resolve();});
- redNodesInit = sinon.stub(redNodes,"init").callsFake(function() {});
- redNodesLoad = sinon.stub(redNodes,"load").callsFake(function() {return Promise.resolve()});
- redNodesCleanModuleList = sinon.stub(redNodes,"cleanModuleList").callsFake(function(){});
- redNodesLoadFlows = sinon.stub(redNodes,"loadFlows").callsFake(function() {return Promise.resolve()});
- redNodesStartFlows = sinon.stub(redNodes,"startFlows").callsFake(function() {});
- redNodesLoadContextsPlugin = sinon.stub(redNodes,"loadContextsPlugin").callsFake(function() {return Promise.resolve()});
- mockUtil();
- });
- afterEach(function() {
- storageInit.restore();
- redNodesInit.restore();
- redNodesLoad.restore();
- redNodesGetNodeList.restore();
- redNodesCleanModuleList.restore();
- redNodesLoadFlows.restore();
- redNodesStartFlows.restore();
- redNodesLoadContextsPlugin.restore();
- unmockUtil();
- });
- it("reports errored/missing modules",function(done) {
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
- return [
- { err:"errored",name:"errName" }, // error
- { module:"module",enabled:true,loaded:false,types:["typeA","typeB"]} // missing
- ].filter(cb);
- });
- runtime.init({testSettings: true, httpAdminRoot:"/", load:function() { return Promise.resolve();}});
- // sinon.stub(console,"log");
- runtime.start().then(function() {
- // console.log.restore();
- try {
- storageInit.calledOnce.should.be.true();
- redNodesInit.calledOnce.should.be.true();
- redNodesLoad.calledOnce.should.be.true();
- redNodesLoadFlows.calledOnce.should.be.true();
-
- log.warn.calledWithMatch("Failed to register 1 node type");
- log.warn.calledWithMatch("Missing node modules");
- log.warn.calledWithMatch(" - module: typeA, typeB");
- redNodesCleanModuleList.calledOnce.should.be.true();
- done();
- } catch(err) {
- done(err);
- }
- }).catch(err=>{done(err)});
- });
- it("initiates load of missing modules",function(done) {
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
- return [
- { err:"errored",name:"errName" }, // error
- { err:"errored",name:"errName" }, // error
- { module:"module",enabled:true,loaded:false,types:["typeA","typeB"]}, // missing
- { module:"node-red",enabled:true,loaded:false,types:["typeC","typeD"]} // missing
- ].filter(cb);
- });
- var serverInstallModule = sinon.stub(redNodes,"installModule").callsFake(function(name) { return Promise.resolve({nodes:[]});});
- runtime.init({testSettings: true, autoInstallModules:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}});
- sinon.stub(console,"log");
- runtime.start().then(function() {
- console.log.restore();
- try {
- log.warn.calledWithMatch("Failed to register 2 node types");
- log.warn.calledWithMatch("Missing node modules");
- log.warn.calledWithMatch(" - module: typeA, typeB");
- log.warn.calledWithMatch(" - node-red: typeC, typeD");
- redNodesCleanModuleList.calledOnce.should.be.false();
- serverInstallModule.calledOnce.should.be.true();
- serverInstallModule.calledWithMatch("module");
- done();
- } catch(err) {
- done(err);
- } finally {
- serverInstallModule.restore();
- }
- }).catch(err=>{done(err)});
- });
- it("reports errored modules when verbose is enabled",function(done) {
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function(cb) {
- return [
- { err:"errored",name:"errName" } // error
- ].filter(cb);
- });
- runtime.init({testSettings: true, verbose:true, httpAdminRoot:"/", load:function() { return Promise.resolve();}});
- sinon.stub(console,"log");
- runtime.start().then(function() {
- console.log.restore();
- try {
- log.warn.neverCalledWithMatch("Failed to register 1 node type");
- log.warn.calledWithMatch("[errName] errored");
- done();
- } catch(err) {
- done(err);
- }
- }).catch(err=>{done(err)});
- });
-
- it("reports runtime metrics",function(done) {
- var stopFlows = sinon.stub(redNodes,"stopFlows").callsFake(function() { return Promise.resolve();} );
- redNodesGetNodeList = sinon.stub(redNodes,"getNodeList").callsFake(function() {return []});
- unmockUtil();
- mockUtil(true);
- runtime.init(
- {testSettings: true, runtimeMetricInterval:200, httpAdminRoot:"/", load:function() { return Promise.resolve();}},
- {},
- undefined);
- // sinon.stub(console,"log");
- runtime.start().then(function() {
- // console.log.restore();
- setTimeout(function() {
- try {
- log.log.args.should.have.lengthOf(3);
- log.log.args[0][0].should.have.property("event","runtime.memory.rss");
- log.log.args[1][0].should.have.property("event","runtime.memory.heapTotal");
- log.log.args[2][0].should.have.property("event","runtime.memory.heapUsed");
- done();
- } catch(err) {
- done(err);
- } finally {
- runtime.stop();
- stopFlows.restore();
- }
- },300);
- }).catch(err=>{done(err)});
- });
-
-
- });
-
- it("stops components", function(done) {
- var stopFlows = sinon.stub(redNodes,"stopFlows").callsFake(function() { return Promise.resolve();} );
- var closeContextsPlugin = sinon.stub(redNodes,"closeContextsPlugin").callsFake(function() { return Promise.resolve();} );
- runtime.stop().then(function(){
- stopFlows.called.should.be.true();
- closeContextsPlugin.called.should.be.true();
- stopFlows.restore();
- closeContextsPlugin.restore();
- done();
- }).catch(function(err){
- stopFlows.restore();
- closeContextsPlugin.restore();
- return done(err)
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/library/examples_spec.js b/test/unit/@node-red/runtime/lib/library/examples_spec.js
deleted file mode 100644
index d7f466d83..000000000
--- a/test/unit/@node-red/runtime/lib/library/examples_spec.js
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var fs = require("fs");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var examplesLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/examples")
-
-var mockLog = {
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-}
-
-describe("runtime/library/examples", function() {
- describe("getEntry", function() {
- before(function() {
- examplesLibrary.init({
- log: mockLog,
- storage: {
- getLibraryEntry: function(type,path) {
- return Promise.resolve({type,path});
- },
- getFlow: function(path) {
- return Promise.resolve({path});
- }
- },
- nodes: {
- getNodeExampleFlows: function() {
- return {
- "test-module": {
- f: ["abc"]
- },
- "@scope/test-module": {
- f: ["abc","throw"]
- }
-
- }
- },
- getNodeExampleFlowPath: function(module,entryPath) {
- if (module === "unknown") {
- return null;
- }
- return "/tmp/"+module+"/"+entryPath;
- }
- }
- });
- sinon.stub(fs,"readFile").callsFake(function(path,opts,callback) {
- if (path === "/tmp/test-module/abc") {
- callback(null,"Example flow result");
- } else if (path === "/tmp/@scope/test-module/abc") {
- callback(null,"Example scope flow result");
- } else if (path === "/tmp/test-module/throw") {
- throw new Error("Instant error")
- } else {
- callback(new Error("Unexpected path:"+path))
- }
- })
- });
- after(function() {
- fs.readFile.restore();
- })
-
- it ('returns a flow example entry', function(done) {
- examplesLibrary.getEntry("flows","test-module/abc").then(function(result) {
- result.should.eql("Example flow result");
- done();
- }).catch(done);
- });
-
- it ('returns a flow example listing - top level', function(done) {
- examplesLibrary.getEntry("flows","").then(function(result) {
- result.should.eql([ 'test-module', '@scope/test-module' ])
- done();
- }).catch(done);
- });
- it ('returns a flow example listing - in module', function(done) {
- examplesLibrary.getEntry("flows","test-module").then(function(result) {
- result.should.eql([{ fn: 'abc' }])
- done();
- }).catch(done);
- });
- it ('returns a flow example listing - in scoped module', function(done) {
- examplesLibrary.getEntry("flows","@scope/test-module").then(function(result) {
- result.should.eql([{ fn: 'abc' }, {fn: 'throw'}])
- done();
- }).catch(done);
- });
- it ('returns a flow example entry from scoped module', function(done) {
- examplesLibrary.getEntry("flows","@scope/test-module/abc").then(function(result) {
- result.should.eql("Example scope flow result");
- done();
- }).catch(done);
- });
- it ('returns an error for unknown flow example entry', function(done) {
- examplesLibrary.getEntry("flows","unknown/abc").then(function(result) {
- done(new Error("No error thrown"))
- }).catch(function(err) {
- err.should.have.property("code","not_found");
- done();
- });
- });
- it ('returns an error for file load error - async', function(done) {
- examplesLibrary.getEntry("flows","test-module/unknown").then(function(result) {
- done(new Error("No error thrown"))
- }).catch(function(err) {
- done();
- });
- });
- it ('returns an error for file load error - sync', function(done) {
- examplesLibrary.getEntry("flows","test-module/throw").then(function(result) {
- done(new Error("No error thrown"))
- }).catch(function(err) {
- done();
- });
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/library/index_spec.js b/test/unit/@node-red/runtime/lib/library/index_spec.js
deleted file mode 100644
index 2499124c7..000000000
--- a/test/unit/@node-red/runtime/lib/library/index_spec.js
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-const should = require("should");
-const sinon = require("sinon");
-
-const NR_TEST_UTILS = require("nr-test-utils");
-const library = NR_TEST_UTILS.require("@node-red/runtime/lib/library/index")
-const localLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/local")
-const examplesLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/examples")
-const events = NR_TEST_UTILS.require("@node-red/util/lib/events")
-
-var mockLog = {
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-}
-
-
-describe("runtime/library", function() {
- before(function() {
- sinon.stub(localLibrary,"getEntry").callsFake(function(type,path) {
- return Promise.resolve({
- library: "local",
- type:type,
- path:path
- })
- });
- sinon.stub(localLibrary,"saveEntry").callsFake(function(type, path, meta, body) {
- return Promise.resolve({
- library: "local",
- type:type,
- path:path,
- meta:meta,
- body:body
- })
- });
- sinon.stub(examplesLibrary,"getEntry").callsFake(function(type,path) {
- return Promise.resolve({
- library: "_examples_",
- type:type,
- path:path
- })
- });
- });
- after(function() {
- localLibrary.getEntry.restore();
- localLibrary.saveEntry.restore();
- examplesLibrary.getEntry.restore();
- })
- describe("register", function() {
- // it("throws error for duplicate type", function() {
- // library.init({});
- // library.register("unknown","/abc");
- // should(()=>{library.register("unknown","/abc")} ).throw();
- // })
- })
-
- describe("getLibraries", function() {
- before(function() {
- library.init({});
- });
- it('returns the default and examples libraries', function() {
- const libs = library.getLibraries();
- libs.should.have.length(2);
- libs[0].should.have.property('id', 'local');
- libs[0].should.have.property('label','editor:library.types.local');
- libs[0].should.have.property("user", false);
- libs[0].should.have.property('icon', 'font-awesome/fa-hdd-o');
-
- libs[1].should.have.property('id', 'examples');
- libs[1].should.have.property('label','editor:library.types.examples');
- libs[1].should.have.property("user", false);
- libs[1].should.have.property('icon', 'font-awesome/fa-life-ring');
- libs[1].should.have.property('readOnly', true);
- libs[1].should.have.property('types', ['flows']);
- });
-
- it('returns the libraries from settings', function() {
- library.init({
- plugins: {
- getPlugin: id => { return {
- id: "test-library-plugin",
- type: "node-red-library-source",
- class: function() {}
- }
- }
- },
- settings: {
- editorTheme: {
- library: {
- sources: [
- {id: "test-plugin-id", type:"test-library-plugin"}
- ]
- }
- }
- }
- });
- let libs = library.getLibraries();
- libs.should.have.length(2);
-
- events.emit("registry:plugin-added","test-library-plugin" )
-
- libs = library.getLibraries();
- libs.should.have.length(3);
- libs[2].should.have.property('id', 'test-plugin-id');
- libs[2].should.have.property("user", false);
- });
- })
-
- describe("getEntry", function() {
- before(function() {
- library.init({});
- });
- it('throws error for unregistered type', function() {
- should(()=>{library.getEntry("local","unknown","/abc")} ).throw();
- });
- it('throws error for unknown library', function() {
- should(()=>{library.getEntry("unknown","unknown","/abc")} ).throw();
- });
-
- it('returns a registered non-flow entry', function(done) {
- library.register("test-module","test-type");
- library.getEntry("local","test-type","/abc").then(function(result) {
- result.should.have.property("library","local")
- result.should.have.property("type","test-type")
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
-
- it ('returns a flow entry', function(done) {
- library.getEntry("local","flows","/abc").then(function(result) {
- result.should.have.property("library","local")
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
-
- it ('returns a flow example entry', function(done) {
- library.getEntry("examples","flows","/test-module/abc").then(function(result) {
- result.should.have.property("library","_examples_")
- result.should.have.property("path","/test-module/abc")
- done();
- }).catch(done);
- });
- });
-
- describe("saveEntry", function() {
- before(function() {
- library.init({});
- });
- it('throws error for unknown library', function() {
- should(()=>{library.saveEntry("unknown","unknown","/abc",{id:"meta"},{id:"body"})} ).throw();
- });
- it('throws error for unregistered type', function() {
- should(()=>{library.saveEntry("local","unknown","/abc",{id:"meta"},{id:"body"})} ).throw();
- });
- it('throws error for save to readonly library', function() {
- should(()=>{library.saveEntry("_examples_","unknown","/abc",{id:"meta"},{id:"body"})} ).throw();
- });
- it('saves a flow entry', function(done) {
- library.saveEntry('local','flows','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("path","/abc");
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
- it('saves a non-flow entry', function(done) {
- library.register("test-module","test-type");
- library.saveEntry('local','test-type','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("type","test-type");
- result.should.have.property("path","/abc");
- result.should.have.property("meta",{id:"meta"});
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
-
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/library/local_spec.js b/test/unit/@node-red/runtime/lib/library/local_spec.js
deleted file mode 100644
index 965e5c87a..000000000
--- a/test/unit/@node-red/runtime/lib/library/local_spec.js
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var localLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/library/local")
-
-var mockLog = {
- log: sinon.stub(),
- debug: sinon.stub(),
- trace: sinon.stub(),
- warn: sinon.stub(),
- info: sinon.stub(),
- metric: sinon.stub(),
- audit: sinon.stub(),
- _: function() { return "abc"}
-}
-
-describe("runtime/library/local", function() {
-
- describe("getEntry", function() {
- before(function() {
- localLibrary.init({
- log: mockLog,
- storage: {
- getLibraryEntry: function(type,path) {
- return Promise.resolve({type,path});
- }
- }
- });
- });
-
- it('returns a registered non-flow entry', function(done) {
- localLibrary.getEntry("test-type","/abc").then(function(result) {
- result.should.have.property("type","test-type")
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
-
- it ('returns a flow entry', function(done) {
- localLibrary.getEntry("flows","/abc").then(function(result) {
- result.should.have.property("path","/abc")
- done();
- }).catch(done);
- });
- });
-
- describe("saveEntry", function() {
- before(function() {
- localLibrary.init({
- log: mockLog,
- storage: {
- saveLibraryEntry: function(type, path, meta, body) {
- return Promise.resolve({type,path,meta,body})
- }
- }
- });
- });
- it('saves a flow entry', function(done) {
- localLibrary.saveEntry('flows','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("path","/abc");
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
- it('saves a non-flow entry', function(done) {
- localLibrary.saveEntry('test-type','/abc',{id:"meta"},{id:"body"}).then(function(result) {
- result.should.have.property("type","test-type");
- result.should.have.property("path","/abc");
- result.should.have.property("meta",{id:"meta"});
- result.should.have.property("body",{id:"body"});
- done();
- }).catch(done);
- })
-
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/Node_spec.js b/test/unit/@node-red/runtime/lib/nodes/Node_spec.js
deleted file mode 100644
index 3fe676f1e..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/Node_spec.js
+++ /dev/null
@@ -1,809 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require('sinon');
-var NR_TEST_UTILS = require("nr-test-utils");
-var RedNode = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-var Log = NR_TEST_UTILS.require("@node-red/util").log;
-var hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-
-describe('Node', function() {
- describe('#constructor',function() {
- it('is called with an id and a type',function() {
- var n = new RedNode({id:'123',type:'abc'});
- n.should.have.property('id','123');
- n.should.have.property('type','abc');
- n.should.not.have.property('name');
- n.wires.should.be.empty();
- });
-
- it('is called with an id, a type and a name',function() {
- var n = new RedNode({id:'123',type:'abc',name:'barney'});
- n.should.have.property('id','123');
- n.should.have.property('type','abc');
- n.should.have.property('name','barney');
- n.wires.should.be.empty();
- });
-
- it('is called with an id, a type and some wires',function() {
- var n = new RedNode({id:'123',type:'abc',wires:['123','456']});
- n.should.have.property('id','123');
- n.should.have.property('type','abc');
- n.should.not.have.property('name');
- n.wires.should.have.length(2);
- });
-
- });
-
- describe('#close', function() {
- it('emits close event when closed',function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- n.on('close',function() {
- done();
- });
- n.close();
- });
-
- it('returns a promise when provided a callback with a done parameter',function(testdone) {
- var n = new RedNode({id:'123',type:'abc'});
- n.on('close',function(done) {
- setTimeout(function() {
- done();
- },50);
- });
- var p = n.close();
- should.exist(p);
- p.then(function() {
- testdone();
- });
- });
- it('accepts a callback with "removed" and "done" parameters', function(testdone) {
- var n = new RedNode({id:'123',type:'abc'});
- var receivedRemoved;
- n.on('close',function(removed,done) {
- receivedRemoved = removed;
- setTimeout(function() {
- done();
- },50);
- });
- var p = n.close(true);
- should.exist(p);
- (receivedRemoved).should.be.true();
- p.then(function() {
- testdone();
- });
- })
- it('allows multiple close handlers to be registered',function(testdone) {
- var n = new RedNode({id:'123',type:'abc'});
- var callbacksClosed = 0;
- n.on('close',function(done) {
- setTimeout(function() {
- callbacksClosed++;
- done();
- },50);
- });
- n.on('close',function(done) {
- setTimeout(function() {
- callbacksClosed++;
- done();
- },75);
- });
- n.on('close',function() {
- callbacksClosed++;
- });
- var p = n.close();
- should.exist(p);
- p.then(function() {
- callbacksClosed.should.eql(3);
- testdone();
- }).catch(function(e) {
- testdone(e);
- });
- });
- });
-
-
- describe('#receive', function() {
- it('emits input event when called', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"hello world"};
- n.on('input',function(msg) {
- should.deepEqual(msg,message);
- done();
- });
- n.receive(message);
- });
-
- it('writes metric info with undefined msg', function(done){
- var n = new RedNode({id:'123',type:'abc'});
- n.on('input',function(msg) {
- (typeof msg).should.not.be.equal("undefined");
- (typeof msg._msgid).should.not.be.equal("undefined");
- done();
- });
- n.receive();
- });
-
- it('writes metric info with null msg', function(done){
- var n = new RedNode({id:'123',type:'abc'});
- n.on('input',function(msg) {
- (typeof msg).should.not.be.equal("undefined");
- (typeof msg._msgid).should.not.be.equal("undefined");
- done();
- });
- n.receive(null);
- });
-
- it('handles thrown errors', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- sinon.stub(n,"error").callsFake(function(err,msg) {});
- var message = {payload:"hello world"};
- n.on('input',function(msg) {
- throw new Error("test error");
- });
- n.receive(message);
- setTimeout(function() {
- n.error.called.should.be.true();
- n.error.firstCall.args[1].should.equal(message);
- done();
- },50);
- });
-
- it('calls parent flow handleComplete when callback provided', function(done) {
- var n = new RedNode({id:'123',type:'abc', _flow: {
- handleComplete: function(node,msg) {
- try {
- msg.should.deepEqual(message);
- done();
- } catch(err) {
- done(err);
- }
- }
- }});
-
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone();
- });
- n.receive(message);
- });
-
- it('triggers onComplete hook when done callback provided', function(done) {
- var handleCompleteCalled = false;
- var hookCalled = false;
- var n = new RedNode({id:'123',type:'abc', _flow: {
- handleComplete: function(node,msg) {
- handleCompleteCalled = true;
- }
- }});
- var hookError;
- hooks.add("onComplete",function(completeEvent) {
- hookCalled = true;
- try {
- handleCompleteCalled.should.be.false("onComplete should be called before handleComplete")
- should.not.exist(completeEvent.error);
- completeEvent.msg.should.deepEqual(message);
- completeEvent.node.id.should.eql("123");
- completeEvent.node.node.should.equal(n);
- } catch(err) {
- hookError = err;
- }
- })
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone();
- });
- n.receive(message);
- setTimeout(function() {
- if (hookError) {
- done(hookError);
- return
- }
- try {
- hookCalled.should.be.true("onComplete hook should be called");
- handleCompleteCalled.should.be.true("handleComplete should be called");
- done();
- } catch(err) {
- done(err);
- }
- })
- });
-
- it('triggers onComplete hook when done callback provided - with error', function(done) {
- var handleCompleteCalled = false;
- var hookCalled = false;
- var errorReported = false;
- var n = new RedNode({id:'123',type:'abc', _flow: {
- handleComplete: function(node,msg) {
- handleCompleteCalled = true;
- }
- }});
- var hookError;
- hooks.add("onComplete",function(completeEvent) {
- hookCalled = true;
- try {
- handleCompleteCalled.should.be.false("onComplete should be called before handleComplete")
- should.exist(completeEvent.error);
- completeEvent.error.toString().should.equal("Error: test error")
- completeEvent.msg.should.deepEqual(message);
- completeEvent.node.id.should.eql("123");
- completeEvent.node.node.should.equal(n);
- } catch(err) {
- hookError = err;
- }
- })
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone(new Error("test error"));
- });
- n.error = function(err,msg) {
- errorReported = true;
- }
- n.receive(message);
- setTimeout(function() {
- if (hookError) {
- done(hookError);
- return
- }
- try {
- hookCalled.should.be.true("onComplete hook should be called");
- handleCompleteCalled.should.be.false("handleComplete should not be called");
- done();
- } catch(err) {
- done(err);
- }
- })
- });
- it('logs error if callback provides error', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- sinon.stub(n,"error").callsFake(function(err,msg) {});
-
- var message = {payload:"hello world"};
- n.on('input',function(msg, nodeSend, nodeDone) {
- nodeDone(new Error("test error"));
- setTimeout(function() {
- try {
- n.error.called.should.be.true();
- n.error.firstCall.args[0].toString().should.equal("Error: test error");
- n.error.firstCall.args[1].should.equal(message);
- done();
- } catch(err) {
- done(err);
- }
- },50);
- });
- n.receive(message);
- });
- it("triggers hooks when receiving a message", function(done) {
- var hookErrors = [];
- var messageReceived = false;
- var hooksCalled = [];
- hooks.add("onReceive", function(receiveEvent) {
- hooksCalled.push("onReceive")
- try {
- messageReceived.should.be.false("Message should not have been received before onReceive")
- receiveEvent.msg.should.be.exactly(message);
- receiveEvent.destination.id.should.equal("123")
- receiveEvent.destination.node.should.equal(n)
- } catch(err) {
- hookErrors.push(err);
- }
- })
- hooks.add("postReceive", function(receiveEvent) {
- hooksCalled.push("postReceive")
- try {
- messageReceived.should.be.true("Message should have been received before postReceive")
- receiveEvent.msg.should.be.exactly(message);
- receiveEvent.destination.id.should.equal("123")
- receiveEvent.destination.node.should.equal(n)
- } catch(err) {
- hookErrors.push(err);
- }
-
- })
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"hello world"};
- n.on('input',function(msg) {
- messageReceived = true;
- try {
- should.strictEqual(this,n);
- hooksCalled.should.eql(["onReceive"])
- should.deepEqual(msg,message);
- } catch(err) {
- hookErrors.push(err)
- }
- });
- n.receive(message);
- setTimeout(function() {
- hooks.clear();
- if (hookErrors.length > 0) {
- done(hookErrors[0])
- } else {
- done();
- }
- },10);
- });
- describe("errors thrown by hooks are reported", function() {
- before(function() {
- hooks.add("onReceive",function(recEvent) {
- if (recEvent.msg.payload === "trigger-onReceive") {
- throw new Error("onReceive Error")
- }
- })
- hooks.add("postReceive",function(recEvent) {
- if (recEvent.msg.payload === "trigger-postReceive") {
- throw new Error("postReceive Error")
- }
- })
- })
- after(function() {
- hooks.clear();
- })
- function testHook(hook, msgExpected, done) {
- var messageReceived = false;
- var errorReceived;
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"trigger-"+hook};
- n.on('input',function(msg) {
- messageReceived = true;
- });
- n.error = function (err) {
- errorReceived = err;
- }
-
- n.receive(message);
-
- setTimeout(function() {
- try {
- messageReceived.should.equal(msgExpected,`Hook ${hook} messageReceived expected ${msgExpected} actual ${messageReceived}`);
- should.exist(errorReceived);
- errorReceived.toString().should.containEql(hook)
- done()
- } catch(err) {
- done(err);
- }
- },10);
- }
- it("onReceive", function(done) { testHook("onReceive", false, done)})
- it("postReceive", function(done) { testHook("postReceive", true, done)})
- })
- });
-
- describe("hooks can halt receive", function() {
- before(function() {
- hooks.add("onReceive",function(recEvent) {
- if (recEvent.msg.payload === "trigger-onReceive") {
- return false;
- }
- })
- })
- after(function() {
- hooks.clear();
- })
-
- function testHook(hook, msgExpected, done) {
- var messageReceived = false;
- var errorReceived;
- var n = new RedNode({id:'123',type:'abc'});
- var message = {payload:"trigger-"+hook};
- n.on('input',function(msg) {
- messageReceived = true;
- });
- n.error = function (err) {
- errorReceived = err;
- }
-
- n.receive(message);
-
- setTimeout(function() {
- try {
- messageReceived.should.equal(msgExpected,`Hook ${hook} messageReceived expected ${msgExpected} actual ${messageReceived}`);
- should.not.exist(errorReceived);
- done()
- } catch(err) {
- done(err);
- }
- },10);
- }
- it("onReceive", function(done) { testHook("onReceive", false, done)})
- })
-
-
- describe('#send', function() {
-
- it('emits a single message', function(done) {
- var flow = {
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(1);
- sendEvents[0].msg.should.equal(message);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0})
- done();
- } catch(err) {
- done(err);
- }
- },
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
- var message = {payload:"hello world"};
- n1.send(message);
- });
-
- it('emits a message with callback provided send', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- handleComplete: (node,msg) => {},
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(1);
- sendEvents[0].msg.should.equal(message);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[0].cloneMessage.should.be.false();
- done();
- } catch(err) {
- done(err);
- }
- },
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
- var message = {payload:"hello world"};
- n1.on('input',function(msg,nodeSend,nodeDone) {
- nodeSend(msg);
- nodeDone();
- });
- n1.receive(message);
- });
-
- it('emits multiple messages on a single output', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(2);
- sendEvents[0].msg.should.equal(messages[0]);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[0].cloneMessage.should.be.false();
-
- sendEvents[1].msg.should.equal(messages[1]);
- sendEvents[1].destination.should.eql({id:"n2", node: undefined});
- sendEvents[1].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[1].cloneMessage.should.be.true();
-
- done();
- } catch(err) {
- done(err);
- }
- },
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
-
- var messages = [
- {payload:"hello world"},
- {payload:"hello world again"}
- ];
-
- n1.send([messages]);
- });
-
- it('emits messages to multiple outputs', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- send: (sendEvents) => {
- try {
- sendEvents.should.have.length(3);
- sendEvents[0].msg.should.equal(messages[0]);
- sendEvents[0].destination.should.eql({id:"n2", node: undefined});
- sendEvents[0].source.should.eql({id:"n1", node: n1, port: 0});
- sendEvents[0].cloneMessage.should.be.false();
- should.exist(sendEvents[0].msg._msgid);
- sendEvents[1].msg.should.equal(messages[2]);
- sendEvents[1].destination.should.eql({id:"n4", node: undefined});
- sendEvents[1].source.should.eql({id:"n1", node: n1, port: 2})
- sendEvents[1].cloneMessage.should.be.true();
- should.exist(sendEvents[1].msg._msgid);
- sendEvents[2].msg.should.equal(messages[2]);
- sendEvents[2].destination.should.eql({id:"n5", node: undefined});
- sendEvents[2].source.should.eql({id:"n1", node: n1, port: 2})
- sendEvents[2].cloneMessage.should.be.true();
- should.exist(sendEvents[2].msg._msgid);
-
- sendEvents[0].msg._msgid.should.eql(sendEvents[1].msg._msgid)
- sendEvents[1].msg._msgid.should.eql(sendEvents[2].msg._msgid)
-
- done();
- } catch(err) {
- done(err);
- }
- }
- };
- var n1 = new RedNode({_flow:flow, id:'n1',type:'abc',wires:[['n2'],['n3'],['n4','n5']]});
- var n2 = new RedNode({_flow:flow, id:'n2',type:'abc'});
- var n3 = new RedNode({_flow:flow, id:'n3',type:'abc'});
- var n4 = new RedNode({_flow:flow, id:'n4',type:'abc'});
- var n5 = new RedNode({_flow:flow, id:'n5',type:'abc'});
- var messages = [
- {payload:"hello world"},
- null,
- {payload:"hello world again"}
- ];
-
- var rcvdCount = 0;
-
- n1.send(messages);
- });
-
- it('emits no messages', function(done) {
- var flow = {
- handleError: (node,logMessage,msg,reportingNode) => {done(logMessage)},
- getNode: (id) => { return {'n1':n1,'n2':n2}[id]},
- };
- var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[['n2']]});
- var n2 = new RedNode({_flow:flow,id:'n2',type:'abc'});
-
- n2.on('input',function(msg) {
- should.fail(null,null,"unexpected message");
- });
-
- setTimeout(function() {
- done();
- }, 200);
-
- n1.send();
- });
-
- // it('emits messages without cloning req or res', function(done) {
- // var flow = {
- // getNode: (id) => { return {'n1':n1,'n2':n2,'n3':n3}[id]},
- // send: (node,dst,msg) => { setImmediate(function() { flow.getNode(dst).receive(msg) })}
- // };
- // var n1 = new RedNode({_flow:flow,id:'n1',type:'abc',wires:[[['n2'],['n3']]]});
- // var n2 = new RedNode({_flow:flow,id:'n2',type:'abc'});
- // var n3 = new RedNode({_flow:flow,id:'n3',type:'abc'});
- //
- // var req = {};
- // var res = {};
- // var cloned = {};
- // var message = {payload: "foo", cloned: cloned, req: req, res: res};
- //
- // var rcvdCount = 0;
- //
- // // first message to be sent, so should not be cloned
- // n2.on('input',function(msg) {
- // should.deepEqual(msg, message);
- // msg.cloned.should.be.exactly(message.cloned);
- // msg.req.should.be.exactly(message.req);
- // msg.res.should.be.exactly(message.res);
- // rcvdCount += 1;
- // if (rcvdCount == 2) {
- // done();
- // }
- // });
- //
- // // second message to be sent, so should be cloned
- // // message uuids wont match since we've cloned
- // n3.on('input',function(msg) {
- // msg.payload.should.equal(message.payload);
- // msg.cloned.should.not.be.exactly(message.cloned);
- // msg.req.should.be.exactly(message.req);
- // msg.res.should.be.exactly(message.res);
- // rcvdCount += 1;
- // if (rcvdCount == 2) {
- // done();
- // }
- // });
- //
- // n1.send(message);
- // });
-
- // it("logs the uuid for all messages sent", function(done) {
- // var logHandler = {
- // msgIds:[],
- // messagesSent: 0,
- // emit: function(event, msg) {
- // if (msg.event == "node.abc.send" && msg.level == Log.METRIC) {
- // this.messagesSent++;
- // this.msgIds.push(msg.msgid);
- // (typeof msg.msgid).should.not.be.equal("undefined");
- // }
- // }
- // };
- //
- // Log.addHandler(logHandler);
- // var flow = {
- // getNode: (id) => { return {'n1':sender,'n2':receiver1,'n3':receiver2}[id]},
- // send: (node,dst,msg) => { setImmediate(function() { flow.getNode(dst).receive(msg) })}
- // };
- //
- // var sender = new RedNode({_flow:flow,id:'n1',type:'abc', wires:[['n2', 'n3']]});
- // var receiver1 = new RedNode({_flow:flow,id:'n2',type:'abc'});
- // var receiver2 = new RedNode({_flow:flow,id:'n3',type:'abc'});
- // sender.send({"some": "message"});
- // setTimeout(function() {
- // try {
- // logHandler.messagesSent.should.equal(1);
- // should.exist(logHandler.msgIds[0])
- // Log.removeHandler(logHandler);
- // done();
- // } catch(err) {
- // Log.removeHandler(logHandler);
- // done(err);
- // }
- // },50)
- // })
- });
-
-
- describe('#log', function() {
- it('produces a log message', function(done) {
- var n = new RedNode({id:'123',type:'abc',z:'789', _flow: {log:function(msg) { loginfo = msg;}}});
- var loginfo = {};
- n.log("a log message");
- should.deepEqual({level:Log.INFO, id:n.id,
- type:n.type, msg:"a log message",z:'789'}, loginfo);
- done();
- });
- it('produces a log message with a name', function(done) {
- var n = new RedNode({id:'123', type:'abc', name:"barney", z:'789', _flow: {log:function(msg) { loginfo = msg;}}});
- var loginfo = {};
- n.log("a log message");
- should.deepEqual({level:Log.INFO, id:n.id, name: "barney",
- type:n.type, msg:"a log message",z:'789'}, loginfo);
- done();
- });
- });
-
- describe('#warn', function() {
- it('produces a warning message', function(done) {
- var n = new RedNode({id:'123',type:'abc',z:'789', _flow: {log:function(msg) { loginfo = msg;}}});
- var loginfo = {};
- n.warn("a warning");
- should.deepEqual({level:Log.WARN, id:n.id,
- type:n.type, msg:"a warning",z:'789'}, loginfo);
- done();
- });
- });
-
- describe('#error', function() {
- it('handles a null error message', function(done) {
- var flow = {
- handleError: sinon.stub(),
- log:sinon.stub()
- }
- var n = new RedNode({_flow:flow, id:'123',type:'abc',z:'789'});
- var message = {a:1};
- n.error(null,message);
-
- flow.handleError.called.should.be.true();
- flow.handleError.args[0][0].should.eql(n);
- flow.handleError.args[0][1].should.eql("");
- flow.handleError.args[0][2].should.eql(message);
-
- done();
- });
-
- it('produces an error message', function(done) {
- var flow = {
- handleError: sinon.stub(),
- log:sinon.stub()
- }
- var n = new RedNode({_flow:flow, id:'123',type:'abc',z:'789'});
- var message = {a:2};
-
- n.error("This is an error",message);
-
- flow.handleError.called.should.be.true();
- flow.handleError.args[0][0].should.eql(n);
- flow.handleError.args[0][1].should.eql("This is an error");
- flow.handleError.args[0][2].should.eql(message);
-
- done();
- });
-
- });
-
- describe('#metric', function() {
- it('produces a metric message', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var loginfo = {};
- sinon.stub(Log, 'log').callsFake(function(msg) {
- loginfo = msg;
- });
- var msg = {payload:"foo", _msgid:"987654321"};
- n.metric("test.metric",msg,"15mb");
- should.deepEqual({value:"15mb", level:Log.METRIC, nodeid:n.id,
- event:"node.abc.test.metric",msgid:"987654321"}, loginfo);
- Log.log.restore();
- done();
- });
- });
-
- describe('#metric', function() {
- it('returns metric value if eventname undefined', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var loginfo = {};
- sinon.stub(Log, 'log').callsFake(function(msg) {
- loginfo = msg;
- });
- var msg = {payload:"foo", _msgid:"987654321"};
- var m = n.metric(undefined,msg,"15mb");
- m.should.be.a.Boolean();
- Log.log.restore();
- done();
- });
- it('returns not defined if eventname defined', function(done) {
- var n = new RedNode({id:'123',type:'abc'});
- var loginfo = {};
- sinon.stub(Log, 'log').callsFake(function(msg) {
- loginfo = msg;
- });
- var msg = {payload:"foo", _msgid:"987654321"};
- var m = n.metric("info",msg,"15mb");
- should(m).be.undefined;
- Log.log.restore();
- done();
- });
- });
-
- describe('#status', function() {
- it('publishes status', function(done) {
- var flow = {
- handleStatus: sinon.stub()
- }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- var status = {fill:"green",shape:"dot",text:"connected"};
-
- n.status(status);
-
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql(status);
- done();
- });
- it('publishes status for plain string', function(done) {
- var flow = { handleStatus: sinon.stub() }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- n.status("text status");
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql({text:"text status"});
- done();
- });
- it('publishes status for plain boolean', function(done) {
- var flow = { handleStatus: sinon.stub() }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- n.status(false);
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql({text:"false"});
- done();
- });
- it('publishes status for plain number', function(done) {
- var flow = { handleStatus: sinon.stub() }
- var n = new RedNode({_flow:flow,id:'123',type:'abc'});
- n.status(123);
- flow.handleStatus.called.should.be.true();
- flow.handleStatus.args[0][0].should.eql(n);
- flow.handleStatus.args[0][1].should.eql({text:"123"});
- done();
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/context/index_spec.js b/test/unit/@node-red/runtime/lib/nodes/context/index_spec.js
deleted file mode 100644
index 7e05eba8f..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/context/index_spec.js
+++ /dev/null
@@ -1,1209 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require('sinon');
-var path = require("path");
-var fs = require('fs-extra');
-var NR_TEST_UTILS = require("nr-test-utils");
-var Context = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/context/index");
-
-describe('context', function() {
- describe('local memory',function() {
- beforeEach(function() {
- Context.init({});
- Context.load();
- });
- afterEach(function() {
- Context.clean({allNodes:{}});
- return Context.close();
- });
- it('stores local property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- should.not.exist(context1.get("foo"));
- context1.set("foo","test");
- context1.get("foo").should.equal("test");
- });
- it('stores local property - creates parent properties',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- context1.set("foo.bar","test");
- context1.get("foo").should.eql({bar:"test"});
- });
- it('deletes local property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- context1.set("foo.abc.bar1","test1");
- context1.set("foo.abc.bar2","test2");
- context1.get("foo.abc").should.eql({bar1:"test1",bar2:"test2"});
- context1.set("foo.abc.bar1",undefined);
- context1.get("foo.abc").should.eql({bar2:"test2"});
- context1.set("foo.abc",undefined);
- should.not.exist(context1.get("foo.abc"));
- context1.set("foo",undefined);
- should.not.exist(context1.get("foo"));
- });
- it('stores flow property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- should.not.exist(context1.flow.get("foo"));
- context1.flow.set("foo","test");
- context1.flow.get("foo").should.equal("test");
- });
- it('stores global property',function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- should.not.exist(context1.global.get("foo"));
- context1.global.set("foo","test");
- context1.global.get("foo").should.equal("test");
- });
-
- it('keeps local context local', function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowA");
-
- should.not.exist(context1.get("foo"));
- should.not.exist(context2.get("foo"));
- context1.set("foo","test");
-
- context1.get("foo").should.equal("test");
- should.not.exist(context2.get("foo"));
- });
- it('flow context accessible to all flow nodes', function() {
- var flowContext = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowA");
-
- should.not.exist(context1.flow.get("foo"));
- should.not.exist(context2.flow.get("foo"));
-
- context1.flow.set("foo","test");
- context1.flow.get("foo").should.equal("test");
- context2.flow.get("foo").should.equal("test");
- });
-
- it('flow context not shared to nodes on other flows', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB")
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowB");
-
- should.not.exist(context1.flow.get("foo"));
- should.not.exist(context2.flow.get("foo"));
-
- context1.flow.set("foo","test");
- context1.flow.get("foo").should.equal("test");
- should.not.exist(context2.flow.get("foo"));
- });
-
- it('global context shared to all nodes', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB")
-
- var context1 = Context.get("1","flowA");
- var context2 = Context.get("2","flowB");
-
- should.not.exist(context1.global.get("foo"));
- should.not.exist(context2.global.get("foo"));
-
- context1.global.set("foo","test");
- context1.global.get("foo").should.equal("test");
- context2.global.get("foo").should.equal("test");
- });
-
- it('context.flow/global are not enumerable', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- Object.keys(context1).length.should.equal(0);
- Object.keys(context1.flow).length.should.equal(0);
- Object.keys(context1.global).length.should.equal(0);
- })
-
- it('context.flow/global cannot be deleted', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context1 = Context.get("1","flowA");
- delete context1.flow;
- should.exist(context1.flow);
- delete context1.global;
- should.exist(context1.global);
- })
-
- it('deletes context',function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- should.not.exist(context.get("foo"));
- context.set("foo","abc");
- context.get("foo").should.equal("abc");
-
- return Context.delete("1","flowA").then(function(){
- context = Context.get("1","flowA");
- should.not.exist(context.get("foo"));
- });
- });
-
- it('enumerates context keys - sync', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
-
- var keys = context.keys();
- keys.should.be.an.Array();
- keys.should.be.empty();
-
- context.set("foo","bar");
- keys = context.keys();
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("abc.def","bar");
- keys = context.keys();
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- });
-
- it('enumerates context keys - async', function(done) {
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
-
- var keys = context.keys(function(err,keys) {
- keys.should.be.an.Array();
- keys.should.be.empty();
- context.set("foo","bar");
- keys = context.keys(function(err,keys) {
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("abc.def","bar");
- keys = context.keys(function(err,keys) {
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- done();
- });
- });
- });
- });
-
- it('should enumerate only context keys when GlobalContext was given - sync', function() {
- Context.init({functionGlobalContext: {foo:"bar"}});
- Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- context.global.set("foo2","bar2");
- var keys = context.global.keys();
- keys.should.have.length(2);
- keys[0].should.equal("foo");
- keys[1].should.equal("foo2");
- });
- });
-
- it('should enumerate only context keys when GlobalContext was given - async', function(done) {
- Context.init({functionGlobalContext: {foo:"bar"}});
- Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- context.global.set("foo2","bar2");
- context.global.keys(function(err,keys) {
- keys.should.have.length(2);
- keys[0].should.equal("foo");
- keys[1].should.equal("foo2");
- done();
- });
- }).catch(done);
- });
-
-
- it('returns functionGlobalContext value if store value undefined', function() {
- Context.init({functionGlobalContext: {foo:"bar"}});
- return Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- var v = context.global.get('foo');
- v.should.equal('bar');
- });
- })
-
- it('returns functionGlobalContext sub-value if store value undefined', function() {
- Context.init({functionGlobalContext: {foo:{bar:123}}});
- return Context.load().then(function(){
- var flowContextA = Context.getFlowContext("flowA")
- var context = Context.get("1","flowA");
- var v = context.global.get('foo.bar');
- should.equal(v,123);
- });
- })
-
- describe("$parent", function() {
- it('should get undefined for $parent without key', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- var parent = context1.get("$parent");
- should.equal(parent, undefined);
- });
-
- it('should get undefined for $parent of root', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- var parent = context1.flow.get("$parent.$parent.K");
- should.equal(parent, undefined);
- });
-
- it('should get undefined for $parent of root - callback', function(done) {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- context1.flow.get("$parent.$parent.K", function(err, result) {
- try {
- should.equal(err, undefined);
- should.equal(result, undefined);
- done();
- } catch(err) {
- done(err);
- }
- });
-
- });
-
- it('should get value in $parent', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- flowContextA.set("K", "v");
- var v = context1.flow.get("$parent.K");
- should.equal(v, "v");
- });
-
- it('should set value in $parent', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- context1.flow.set("$parent.K", "v");
- var v = flowContextA.get("K");
- should.equal(v, "v");
- });
-
- it('should not contain $parent in keys', function() {
- var flowContextA = Context.getFlowContext("flowA")
- var flowContextB = Context.getFlowContext("flowB","flowA")
- var context0 = Context.get("0","flowA");
- var context1 = Context.get("1","flowB");
- var parent = context1.get("$parent");
- flowContextA.set("K0", "v0");
- context1.set("K1", "v1");
- var keys = context1.keys();
- keys.should.have.length(1);
- keys[0].should.equal("K1");
- });
- });
-
- });
-
- describe('external context storage',function() {
- var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
- var sandbox = sinon.createSandbox();
- var stubGet = sandbox.stub();
- var stubSet = sandbox.stub();
- var stubKeys = sandbox.stub();
- var stubDelete = sandbox.stub().returns(Promise.resolve());
- var stubClean = sandbox.stub().returns(Promise.resolve());
- var stubOpen = sandbox.stub().returns(Promise.resolve());
- var stubClose = sandbox.stub().returns(Promise.resolve());
- var stubGet2 = sandbox.stub();
- var stubSet2 = sandbox.stub();
- var stubKeys2 = sandbox.stub();
- var stubDelete2 = sandbox.stub().returns(Promise.resolve());
- var stubClean2 = sandbox.stub().returns(Promise.resolve());
- var stubOpen2 = sandbox.stub().returns(Promise.resolve());
- var stubClose2 = sandbox.stub().returns(Promise.resolve());
- var testPlugin = function(config){
- function Test(){}
- Test.prototype.get = stubGet;
- Test.prototype.set = stubSet;
- Test.prototype.keys = stubKeys;
- Test.prototype.delete = stubDelete;
- Test.prototype.clean = stubClean;
- Test.prototype.open = stubOpen;
- Test.prototype.close = stubClose;
- return new Test(config);
- };
- var testPlugin2 = function(config){
- function Test2(){}
- Test2.prototype.get = stubGet2;
- Test2.prototype.set = stubSet2;
- Test2.prototype.keys = stubKeys2;
- Test2.prototype.delete = stubDelete2;
- Test2.prototype.clean = stubClean2;
- Test2.prototype.open = stubOpen2;
- Test2.prototype.close = stubClose2;
- return new Test2(config);
- };
- var contextStorage={
- test:{
- module: testPlugin,
- config:{}
- }
- };
- var contextDefaultStorage={
- default: {
- module: testPlugin2,
- config:{}
- },
- test:{
- module: testPlugin,
- config:{}
- }
- };
- var contextAlias={
- default: "test",
- test:{
- module: testPlugin,
- config:{}
- }
- };
- var memoryStorage ={
- memory:{
- module: "memory"
- }
- };
-
- afterEach(function() {
- sandbox.reset();
- return Context.clean({allNodes:{}}).then(function(){
- return Context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- describe('load modules',function(){
- it('should call open()', function() {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- stubOpen.called.should.be.true();
- stubOpen2.called.should.be.true();
- });
- });
- it('should load memory module', function() {
- Context.init({contextStorage:{memory:{module:"memory"}}});
- return Context.load();
- });
- it('should load localfilesystem module', function() {
- Context.init({contextStorage:{file:{module:"localfilesystem",config:{dir:resourcesDir}}}});
- return Context.load();
- });
- it('should ignore reserved storage name `_`', function(done) {
- Context.init({contextStorage:{_:{module:testPlugin}}});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow")
- var context = Context.get("1","flow");
- var cb = function(){}
- context.set("foo","bar","_",cb);
- context.get("foo","_",cb);
- context.keys("_",cb);
- stubSet.called.should.be.false();
- stubGet.called.should.be.false();
- stubKeys.called.should.be.false();
- done();
- }).catch(done);
- });
-
- it('should fail when using invalid store name', function(done) {
- Context.init({contextStorage:{'Invalid name':{module:testPlugin}}});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail when using invalid sign character', function (done) {
- Context.init({ contextStorage:{'abc-123':{module:testPlugin}}});
- Context.load().then(function () {
- done("An error was not thrown");
- }).catch(function () {
- done();
- });
- });
- it('should fail when using invalid default context', function(done) {
- Context.init({contextStorage:{default:"noexist"}});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail for the storage with no module', function(done) {
- Context.init({ contextStorage: { test: {}}});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail to load non-existent module', function(done) {
- Context.init({contextStorage:{ file:{module:"nonexistent"} }});
- Context.load().then(function(){
- done("An error was not thrown");
- }).catch(function(){
- done();
- });
- });
- it('should fail to load invalid module', function (done) {
- Context.init({contextStorage: {
- test: {
- module: function (config) {
- throw new Error("invalid plugin was loaded.");
- }
- }
- }});
- Context.load().then(function () {
- done("An error was not thrown");
- }).catch(function () {
- done();
- });
- });
- });
-
- describe('close modules',function(){
- it('should call close()', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- return Context.close().then(function(){
- stubClose.called.should.be.true();
- stubClose2.called.should.be.true();
- done();
- });
- }).catch(done);
- });
- });
-
- describe('store context',function() {
- it('should store local property to external context storage',function(done) {
- Context.init({contextStorage:contextStorage});
- var cb = function(){done("An error occurred")}
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set("foo","bar","test",cb);
- context.get("foo","test",cb);
- context.keys("test",cb);
- stubSet.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
- stubGet.calledWith("1:flow","foo").should.be.true();
- stubKeys.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should store flow property to external context storage',function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.flow.set("foo","bar","test",cb);
- context.flow.get("foo","test",cb);
- context.flow.keys("test",cb);
- stubSet.calledWithExactly("flow","foo","bar",cb).should.be.true();
- stubGet.calledWith("flow","foo").should.be.true();
- stubKeys.calledWithExactly("flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should store global property to external context storage',function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.global.set("foo","bar","test",cb);
- context.global.get("foo","test",cb);
- context.global.keys("test",cb);
- stubSet.calledWithExactly("global","foo","bar",cb).should.be.true();
- stubGet.calledWith("global","foo").should.be.true();
- stubKeys.calledWith("global").should.be.true();
- done();
- }).catch(done);
- });
- it('should store data to the default context when non-existent context storage was specified', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","bar","nonexist",cb);
- context.get("foo","nonexist",cb);
- context.keys("nonexist",cb);
- stubGet.called.should.be.false();
- stubSet.called.should.be.false();
- stubKeys.called.should.be.false();
- stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
- stubGet2.calledWith("1:flow","foo").should.be.true();
- stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should use the default context', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","bar","default",cb);
- context.get("foo","default",cb);
- context.keys("default",cb);
- stubGet.called.should.be.false();
- stubSet.called.should.be.false();
- stubKeys.called.should.be.false();
- stubSet2.calledWithExactly("1:flow","foo","bar",cb).should.be.true();
- stubGet2.calledWith("1:flow","foo").should.be.true();
- stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should use the alias of default context', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","alias",cb);
- context.get("foo",cb);
- context.keys(cb);
- stubGet.called.should.be.false();
- stubSet.called.should.be.false();
- stubKeys.called.should.be.false();
- stubSet2.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
- stubGet2.calledWith("1:flow","foo").should.be.true();
- stubKeys2.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
-
- it('should allow the store name to be provide in the key', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("#:(test)::foo","bar");
- context.get("#:(test)::foo");
- stubGet2.called.should.be.false();
- stubSet2.called.should.be.false();
- stubSet.calledWithExactly("1:flow","foo","bar",undefined).should.be.true();
- stubGet.calledWith("1:flow","foo").should.be.true();
- done();
- }).catch(done);
- });
-
-
- it('should use default as the alias of other context', function(done) {
- Context.init({contextStorage:contextAlias});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.set("foo","alias",cb);
- context.get("foo",cb);
- context.keys(cb);
- stubSet.calledWithExactly("1:flow","foo","alias",cb).should.be.true();
- stubGet.calledWith("1:flow","foo").should.be.true();
- stubKeys.calledWithExactly("1:flow",cb).should.be.true();
- done();
- }).catch(done);
- });
- it('should not throw an error using undefined storage for local context', function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.get("local","nonexist",cb);
- done()
- }).catch(done);
- });
- it('should throw an error using undefined storage for flow context', function(done) {
- Context.init({contextStorage:contextStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- var cb = function(){done("An error occurred")}
- context.flow.get("flow","nonexist",cb);
- done();
- }).catch(done);
- });
-
- it('should return functionGlobalContext value as a default - synchronous', function(done) {
- var fGC = { "foo": 456 };
- Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
- Context.load().then(function() {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- // Get foo - should be value from fGC
- var v = context.global.get("foo");
- v.should.equal(456);
-
- // Update foo - should not touch fGC object
- context.global.set("foo","new value");
- fGC.foo.should.equal(456);
-
- // Get foo - should be the updated value
- v = context.global.get("foo");
- v.should.equal("new value");
- done();
- }).catch(done);
- })
-
- it('should return functionGlobalContext value as a default - async', function(done) {
- var fGC = { "foo": 456 };
- Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
- Context.load().then(function() {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- // Get foo - should be value from fGC
- context.global.get("foo", function(err, v) {
- if (err) {
- done(err)
- } else {
- v.should.equal(456);
- // Update foo - should not touch fGC object
- context.global.set("foo","new value", function(err) {
- if (err) {
- done(err)
- } else {
- fGC.foo.should.equal(456);
- // Get foo - should be the updated value
- context.global.get("foo", function(err, v) {
- if (err) {
- done(err)
- } else {
- v.should.equal("new value");
- done();
- }
- });
- }
- });
- }
- });
- }).catch(done);
- })
-
- it('should return multiple values if key is an array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set("foo1","bar1","memory");
- context.set("foo2","bar2","memory");
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- should.not.exist(foo3);
- done();
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should return multiple functionGlobalContext values if key is an array', function(done) {
- var fGC = { "foo1": 456, "foo2": {"bar":789} };
- Context.init({contextStorage:memoryStorage, functionGlobalContext:fGC });
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.global.get(["foo1","foo2.bar","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- should.equal(foo1, 456);
- should.equal(foo2, 789);
- should.not.exist(foo3);
- done();
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should return an error if an error occurs in getting multiple store values', function(done) {
- Context.init({contextStorage:contextStorage});
- stubGet.onFirstCall().callsArgWith(2, "error2", "bar1");
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow")
- var context = Context.get("1","flow");
- context.global.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err === "error2") {
- done();
- } else {
- done("An error occurred");
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should return a first error if some errors occur in getting multiple store values', function(done) {
- Context.init({contextStorage:contextStorage});
- stubGet.onFirstCall().callsArgWith(2, "error1");
- stubGet.onSecondCall().callsArgWith(2, null, "bar2");
- stubGet.onThirdCall().callsArgWith(2, "error3");
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err === "error1") {
- done();
- } else {
- done("An error occurred");
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should store multiple properties if key and value are arrays', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- foo3.should.be.equal("bar3");
- done();
- }
- });
- }
- });
- });
- });
-
- it('should deletes multiple properties', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- foo3.should.be.equal("bar3");
- context.set(["foo1","foo2","foo3"], new Array(3), "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- should.not.exist(foo1);
- should.not.exist(foo2);
- should.not.exist(foo3);
- done();
- }
- });
- }
- });
- }
- });
- }
- });
- });
- });
-
- it('should use null for missing values if the value array is shorter than the key array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.keys(function(err, keys){
- keys.should.have.length(3);
- keys.should.eql(["foo1","foo2","foo3"]);
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- should(foo3).be.null();
- done();
- }
- });
- });
- }
- });
- });
- });
-
- it('should use null for missing values if the value is not array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], "bar1", "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.keys(function(err, keys){
- keys.should.have.length(3);
- keys.should.eql(["foo1","foo2","foo3"]);
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- should(foo2).be.null();
- should(foo3).be.null();
- done();
- }
- });
- });
- }
- });
- });
- });
-
- it('should ignore the extra values if the value array is longer than the key array', function(done) {
- Context.init({contextStorage:memoryStorage});
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3","ignored"], "memory", function(err){
- if (err) {
- done(err);
- } else {
- context.keys(function(err, keys){
- keys.should.have.length(3);
- keys.should.eql(["foo1","foo2","foo3"]);
- context.get(["foo1","foo2","foo3"], "memory", function(err,foo1,foo2,foo3){
- if (err) {
- done(err);
- } else {
- foo1.should.be.equal("bar1");
- foo2.should.be.equal("bar2");
- foo3.should.be.equal("bar3");
- done();
- }
- });
- });
- }
- });
- });
- });
-
- it('should return an error if an error occurs in storing multiple values', function(done) {
- Context.init({contextStorage:contextStorage});
- stubSet.onFirstCall().callsArgWith(3, "error2");
- Context.load().then(function(){
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1","flow");
- context.set(["foo1","foo2","foo3"], ["bar1","bar2","bar3"], "memory", function(err){
- if (err === "error2") {
- done();
- } else {
- done("An error occurred");
- }
- });
- }).catch(function(err){ done(err); });
- });
-
- it('should throw an error if callback of context.get is not a function', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.get("foo", "memory", "callback");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should not throw an error if callback of context.get is not specified', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.get("foo", "memory");
- done();
- }).catch(done);
- });
-
- it('should throw an error if callback of context.set is not a function', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.set("foo", "bar", "memory", "callback");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should not throw an error if callback of context.set is not specified', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.set("foo", "bar", "memory");
- done();
- }).catch(done);
- });
-
- it('should throw an error if callback of context.keys is not a function', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.keys("memory", "callback");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should not throw an error if callback of context.keys is not specified', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var flowContext = Context.getFlowContext("flow");
- var context = Context.get("1", "flow");
- context.keys("memory");
- done();
- }).catch(done);
- });
- it('should throw an error in context.get if key is empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get("");
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key is an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get({});
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key is a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key array contains an empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(["ok1", "", "ok2"]);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key array contains an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(["ok1", {}, "ok2"]);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.get if key array contains a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get(["ok1", 1, "ok2"]);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should throw an error in context.set if key is empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set("", 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key is an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set({}, 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key is a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(1, 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key array contains an empty string', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(["ok1", "", "ok2"], 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key array contains an object', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(["ok1", {}, "ok2"], 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
- it('should throw an error in context.set if key array contains a number', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set(["ok1", 1, "ok2"], 1);
- done("should throw an error.");
- }).catch(function () {
- done();
- });
- });
-
- it('should have an err set in callback for invalid key in context.get', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.get("", function(err) {
- if(err) {
- done();
- } else {
- done("should throw an error.");
- }
- });
- }).catch(done);
- });
-
- it('should have an err set in callback for invalid key in context.set', function (done) {
- Context.init({ contextStorage: memoryStorage });
- Context.load().then(function () {
- var context = Context.get("1", "flow");
- context.set("", "value", function(err) {
- if(err) {
- done();
- } else {
- done("should throw an error.");
- }
- });
- }).catch(done);
- });
- });
-
- describe('listStores', function () {
- it('should list context storages', function (done) {
- Context.init({ contextStorage: contextDefaultStorage });
- Context.load().then(function () {
- var list = Context.listStores();
- list.default.should.equal("default");
- list.stores.should.eql(["default", "test"]);
- done();
- }).catch(done);
- });
-
- it('should list context storages without default storage', function (done) {
- Context.init({ contextStorage: contextStorage });
- Context.load().then(function () {
- var list = Context.listStores();
- list.default.should.equal("test");
- list.stores.should.eql(["test"]);
- done();
- }).catch(done);
- });
- });
- describe('delete context',function(){
- it('should not call delete() when external context storage is used', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- Context.get("flowA");
- return Context.delete("flowA").then(function(){
- stubDelete.called.should.be.false();
- stubDelete2.called.should.be.false();
- done();
- });
- }).catch(done);
- });
- });
-
- describe('clean context',function(){
- it('should call clean()', function(done) {
- Context.init({contextStorage:contextDefaultStorage});
- Context.load().then(function(){
- return Context.clean({allNodes:{}}).then(function(){
- stubClean.calledWithExactly([]).should.be.true();
- stubClean2.calledWithExactly([]).should.be.true();
- done();
- });
- }).catch(done);
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/context/localfilesystem_spec.js b/test/unit/@node-red/runtime/lib/nodes/context/localfilesystem_spec.js
deleted file mode 100644
index 26f9789f4..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/context/localfilesystem_spec.js
+++ /dev/null
@@ -1,883 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require('should');
-var fs = require('fs-extra');
-var path = require("path");
-var NR_TEST_UTILS = require("nr-test-utils");
-var LocalFileSystem = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/context/localfilesystem");
-
-var resourcesDir = path.resolve(path.join(__dirname,"..","resources","context"));
-
-var defaultContextBase = "context";
-
-describe('localfilesystem',function() {
-
- before(function() {
- return fs.remove(resourcesDir);
- });
-
- describe('#get/set',function() {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- it('should store property',function(done) {
- context.get("nodeX","foo",function(err, value){
- if (err) { return done(err); }
- should.not.exist(value);
- context.set("nodeX","foo","test",function(err){
- if (err) { return done(err); }
- context.get("nodeX","foo",function(err, value){
- if (err) { return done(err); }
- value.should.be.equal("test");
- done();
- });
- });
- });
- });
-
- it('should store property - creates parent properties',function(done) {
- context.set("nodeX","foo.bar","test",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.eql({bar:"test"});
- done();
- });
- });
- });
-
- it('should store local scope property', function (done) {
- context.set("abc:def", "foo.bar", "test", function (err) {
- context.get("abc:def", "foo", function (err, value) {
- value.should.be.eql({ bar: "test" });
- done();
- });
- });
- });
-
- it('should delete property',function(done) {
- context.set("nodeX","foo.abc.bar1","test1",function(err){
- context.set("nodeX","foo.abc.bar2","test2",function(err){
- context.get("nodeX","foo.abc",function(err, value){
- value.should.be.eql({bar1:"test1",bar2:"test2"});
- context.set("nodeX","foo.abc.bar1",undefined,function(err){
- context.get("nodeX","foo.abc",function(err, value){
- value.should.be.eql({bar2:"test2"});
- context.set("nodeX","foo.abc",undefined,function(err){
- context.get("nodeX","foo.abc",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",undefined,function(err){
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- done();
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
-
- it('should not shared context with other scope', function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.get("nodeY","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","testX",function(err){
- context.set("nodeY","foo","testY",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.equal("testX");
- context.get("nodeY","foo",function(err, value){
- value.should.be.equal("testY");
- done();
- });
- });
- });
- });
- });
- });
- });
-
- it('should store string',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","bar",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.String();
- value.should.be.equal("bar");
- context.set("nodeX","foo","1",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.String();
- value.should.be.equal("1");
- done();
- });
- });
- });
- });
- });
- });
-
- it('should store number',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",1,function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Number();
- value.should.be.equal(1);
- done();
- });
- });
- });
- });
-
- it('should store null',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",null,function(err){
- context.get("nodeX","foo",function(err, value){
- should(value).be.null();
- done();
- });
- });
- });
- });
-
- it('should store boolean',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",true,function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Boolean().and.true();
- context.set("nodeX","foo",false,function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Boolean().and.false();
- done();
- });
- });
- });
- });
- });
- });
-
- it('should store object',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",{obj:"bar"},function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Object();
- value.should.eql({obj:"bar"});
- done();
- });
- });
- });
- });
-
- it('should store array',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",["a","b","c"],function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Array();
- value.should.eql(["a","b","c"]);
- context.get("nodeX","foo[1]",function(err, value){
- value.should.be.String();
- value.should.equal("b");
- done();
- });
- });
- });
- });
- });
-
- it('should store array of arrays',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",[["a","b","c"],[1,2,3,4],[true,false]],function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Array();
- value.should.have.length(3);
- value[0].should.have.length(3);
- value[1].should.have.length(4);
- value[2].should.have.length(2);
- context.get("nodeX","foo[1]",function(err, value){
- value.should.be.Array();
- value.should.have.length(4);
- value.should.be.eql([1,2,3,4]);
- done();
- });
- });
- });
- });
- });
-
- it('should store array of objects',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo",[{obj:"bar1"},{obj:"bar2"},{obj:"bar3"}],function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.Array();
- value.should.have.length(3);
- value[0].should.be.Object();
- value[1].should.be.Object();
- value[2].should.be.Object();
- context.get("nodeX","foo[1]",function(err, value){
- value.should.be.Object();
- value.should.be.eql({obj:"bar2"});
- done();
- });
- });
- });
- });
- });
-
- it('should set/get multiple values', function(done) {
- context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
- context.get("nodeX",["one","two"], function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2"])
- done();
- });
- });
- })
- it('should set/get multiple values - get unknown', function(done) {
- context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
- context.get("nodeX",["one","two","unknown"], function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2",undefined])
- done();
- });
- });
- })
- it('should set/get multiple values - single value providd', function(done) {
- context.set("nodeX",["one","two","three"],"test1", function(err) {
- context.get("nodeX",["one","two"], function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1",null])
- done();
- });
- });
- })
-
- it('should throw error if bad key included in multiple keys - get', function(done) {
- context.set("nodeX",["one","two","three"],["test1","test2","test3"], function(err) {
- context.get("nodeX",["one",".foo","three"], function(err) {
- should.exist(err);
- done();
- });
- });
- })
-
- it('should throw error if bad key included in multiple keys - set', function(done) {
- context.set("nodeX",["one",".foo","three"],["test1","test2","test3"], function(err) {
- should.exist(err);
- // Check 'one' didn't get set as a result
- context.get("nodeX","one",function(err,one) {
- should.not.exist(one);
- done();
- })
- });
- })
-
- it('should throw an error when getting a value with invalid key', function (done) {
- context.set("nodeX","foo","bar",function(err) {
- context.get("nodeX"," ",function(err,value) {
- should.exist(err);
- done();
- });
- });
- });
-
- it('should throw an error when setting a value with invalid key',function (done) {
- context.set("nodeX"," ","bar",function (err) {
- should.exist(err);
- done();
- });
- });
-
- it('should throw an error when callback of get() is not a function',function (done) {
- try {
- context.get("nodeX","foo","callback");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should throw an error when callback of get() is not specified',function (done) {
- try {
- context.get("nodeX","foo");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should throw an error when callback of set() is not a function',function (done) {
- try {
- context.set("nodeX","foo","bar","callback");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should not throw an error when callback of set() is not specified', function (done) {
- try {
- context.set("nodeX"," ","bar");
- done();
- } catch (err) {
- done("should not throw an error.");
- }
- });
-
- it('should handle empty context file', function (done) {
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"nodeX","flow.json"),"",function(){
- context.get("nodeX", "foo", function (err, value) {
- should.not.exist(value);
- context.set("nodeX", "foo", "test", function (err) {
- context.get("nodeX", "foo", function (err, value) {
- value.should.be.equal("test");
- done();
- });
- });
- });
- });
- });
-
- it('should throw an error when reading corrupt context file', function (done) {
- fs.outputFile(path.join(resourcesDir, defaultContextBase, "nodeX", "flow.json"),"{abc",function(){
- context.get("nodeX", "foo", function (err, value) {
- should.exist(err);
- done();
- });
- });
- });
- });
-
- describe('#keys',function() {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- it('should enumerate context keys', function(done) {
- context.keys("nodeX",function(err, value){
- value.should.be.an.Array();
- value.should.be.empty();
- context.set("nodeX","foo","bar",function(err){
- context.keys("nodeX",function(err, value){
- value.should.have.length(1);
- value[0].should.equal("foo");
- context.set("nodeX","abc.def","bar",function(err){
- context.keys("nodeX",function(err, value){
- value.should.have.length(2);
- value[1].should.equal("abc");
- done();
- });
- });
- });
- });
- });
- });
-
- it('should enumerate context keys in each scopes', function(done) {
- context.keys("nodeX",function(err, value){
- value.should.be.an.Array();
- value.should.be.empty();
- context.keys("nodeY",function(err, value){
- value.should.be.an.Array();
- value.should.be.empty();
- context.set("nodeX","foo","bar",function(err){
- context.set("nodeY","hoge","piyo",function(err){
- context.keys("nodeX",function(err, value){
- value.should.have.length(1);
- value[0].should.equal("foo");
- context.keys("nodeY",function(err, value){
- value.should.have.length(1);
- value[0].should.equal("hoge");
- done();
- });
- });
- });
- });
- });
- });
- });
-
- it('should throw an error when callback of keys() is not a function', function (done) {
- try {
- context.keys("nodeX", "callback");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
-
- it('should throw an error when callback of keys() is not specified', function (done) {
- try {
- context.keys("nodeX");
- done("should throw an error.");
- } catch (err) {
- done();
- }
- });
- });
-
- describe('#delete',function() {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
- it('should delete context',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.get("nodeY","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","testX",function(err){
- context.set("nodeY","foo","testY",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.be.equal("testX");
- context.get("nodeY","foo",function(err, value){
- value.should.be.equal("testY");
- context.delete("nodeX").then(function(){
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.get("nodeY","foo",function(err, value){
- value.should.be.equal("testY");
- done();
- });
- });
- }).catch(done);
- });
- });
- });
- });
- });
- });
- });
- });
-
- describe('#clean',function() {
- var context;
- var contextGet;
- var contextSet;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- contextGet = function(scope,key) {
- return new Promise((res,rej) => {
- context.get(scope,key, function(err,value) {
- if (err) {
- rej(err);
- } else {
- res(value);
- }
- })
- });
- }
- contextSet = function(scope,key,value) {
- return new Promise((res,rej) => {
- context.set(scope,key,value, function(err) {
- if (err) {
- rej(err);
- } else {
- res();
- }
- })
- });
- }
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close().then(function(){
- return fs.remove(resourcesDir);
- });
- });
- });
- it('should clean unnecessary context',function(done) {
- contextSet("global","foo","testGlobal").then(function() {
- return contextSet("nodeX:flow1","foo","testX");
- }).then(function() {
- return contextSet("nodeY:flow2","foo","testY");
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- value.should.be.equal("testX");
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- value.should.be.equal("testY");
- }).then(function() {
- return context.clean([])
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- should.not.exist(value);
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- should.not.exist(value);
- }).then(function() {
- return contextGet("global","foo");
- }).then(function(value) {
- value.should.eql("testGlobal");
- }).then(done).catch(done);
- });
-
- it('should not clean active context',function(done) {
- contextSet("global","foo","testGlobal").then(function() {
- return contextSet("nodeX:flow1","foo","testX");
- }).then(function() {
- return contextSet("nodeY:flow2","foo","testY");
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- value.should.be.equal("testX");
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- value.should.be.equal("testY");
- }).then(function() {
- return context.clean(["flow1","nodeX"])
- }).then(function() {
- return contextGet("nodeX:flow1","foo");
- }).then(function(value) {
- value.should.be.equal("testX");
- }).then(function() {
- return contextGet("nodeY:flow2","foo");
- }).then(function(value) {
- should.not.exist(value);
- }).then(function() {
- return contextGet("global","foo");
- }).then(function(value) {
- value.should.eql("testGlobal");
- }).then(done).catch(done);
- });
- });
-
- describe('#if cache is enabled',function() {
-
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
-
-
-
- it('should load contexts into the cache',function() {
- var globalData = {key:"global"};
- var flowData = {key:"flow"};
- var nodeData = {key:"node"};
- return Promise.all([
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"global","global.json"), JSON.stringify(globalData,null,4), "utf8"),
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flow","flow.json"), JSON.stringify(flowData,null,4), "utf8"),
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flow","node.json"), JSON.stringify(nodeData,null,4), "utf8")
- ]).then(function(){
- context = LocalFileSystem({dir: resourcesDir, cache: true});
- return context.open();
- }).then(function(){
- return Promise.all([
- fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json")),
- fs.remove(path.join(resourcesDir,defaultContextBase,"flow","flow.json")),
- fs.remove(path.join(resourcesDir,defaultContextBase,"flow","node.json"))
- ]);
- }).then(function(){
- context.get("global","key").should.be.equal("global");
- context.get("flow","key").should.be.equal("flow");
- context.get("node:flow","key").should.be.equal("node");
- });
- });
-
- it('should store property to the cache',function() {
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 1});
- return context.open().then(function(){
- return new Promise(function(resolve, reject){
- context.set("global","foo","bar",function(err){
- if(err){
- reject(err);
- } else {
- fs.readJson(path.join(resourcesDir,defaultContextBase,"global","global.json")).then(function(data) {
- // File should not exist as flush hasn't happened
- reject("File global/global.json should not exist");
- }).catch(function(err) {
- setTimeout(function() {
- fs.readJson(path.join(resourcesDir,defaultContextBase,"global","global.json")).then(function(data) {
- data.should.eql({foo:'bar'});
- resolve();
- }).catch(function(err) {
- reject(err);
- });
- },1100)
- })
- }
- });
- });
- }).then(function(){
- return fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json"));
- }).then(function(){
- context.get("global","foo").should.be.equal("bar");
- })
- });
-
- it('should enumerate context keys in the cache',function() {
- var globalData = {foo:"bar"};
- return fs.outputFile(path.join(resourcesDir,defaultContextBase,"global","global.json"), JSON.stringify(globalData,null,4), "utf8").then(function(){
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2});
- return context.open()
- }).then(function(){
- return fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json"));
- }).then(function(){
- var keys = context.keys("global");
- keys.should.have.length(1);
- keys[0].should.equal("foo");
- return new Promise(function(resolve, reject){
- context.set("global","foo2","bar2",function(err){
- if(err){
- reject(err);
- } else {
- resolve();
- }
- });
- });
- }).then(function(){
- return fs.remove(path.join(resourcesDir,defaultContextBase,"global","global.json"));
- }).then(function(){
- var keys = context.keys("global");
- keys.should.have.length(2);
- keys[1].should.equal("foo2");
- })
- });
-
- it('should delete context in the cache',function() {
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2});
- return context.open().then(function(){
- return new Promise(function(resolve, reject){
- context.set("global","foo","bar",function(err){
- if(err){
- reject(err);
- } else {
- resolve();
- }
- });
- });
- }).then(function(){
- context.get("global","foo").should.be.equal("bar");
- return context.delete("global");
- }).then(function(){
- should.not.exist(context.get("global","foo"))
- })
- });
-
- it('should clean unnecessary context in the cache',function() {
- var flowAData = {key:"flowA"};
- var flowBData = {key:"flowB"};
- return Promise.all([
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flowA","flow.json"), JSON.stringify(flowAData,null,4), "utf8"),
- fs.outputFile(path.join(resourcesDir,defaultContextBase,"flowB","flow.json"), JSON.stringify(flowBData,null,4), "utf8")
- ]).then(function(){
- context = LocalFileSystem({dir: resourcesDir, cache: true, flushInterval: 2});
- return context.open();
- }).then(function(){
- context.get("flowA","key").should.be.equal("flowA");
- context.get("flowB","key").should.be.equal("flowB");
- return context.clean(["flowA"]);
- }).then(function(){
- context.get("flowA","key").should.be.equal("flowA");
- should.not.exist(context.get("flowB","key"));
- });
- });
- });
-
- describe('Configuration', function () {
- var context;
- beforeEach(function() {
- context = LocalFileSystem({dir: resourcesDir, cache: false});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- }).then(function(){
- return fs.remove(resourcesDir);
- });
- });
- it('should change a base directory', function (done) {
- var differentBaseContext = LocalFileSystem({
- base: "contexts2",
- dir: resourcesDir,
- cache: false
- });
- differentBaseContext.open().then(function () {
- differentBaseContext.set("node2", "foo2", "bar2", function (err) {
- differentBaseContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function(err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- });
-
- it('should use userDir', function (done) {
- var userDirContext = LocalFileSystem({
- base: "contexts2",
- cache: false,
- settings: {
- userDir: resourcesDir
- }
- });
- userDirContext.open().then(function () {
- userDirContext.set("node2", "foo2", "bar2", function (err) {
- userDirContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- });
-
- it('should use NODE_RED_HOME', function (done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = resourcesDir;
- fs.ensureDirSync(resourcesDir);
- fs.writeFileSync(path.join(resourcesDir,".config.json"),"");
- var nrHomeContext = LocalFileSystem({
- base: "contexts2",
- cache: false
- });
- try {
- nrHomeContext.open().then(function () {
- nrHomeContext.set("node2", "foo2", "bar2", function (err) {
- nrHomeContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- }
- });
-
- it('should use HOME_PATH', function (done) {
- var oldNRH = process.env.NODE_RED_HOME;
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.NODE_RED_HOME = resourcesDir;
- process.env.HOMEPATH = resourcesDir;
- var homePath = path.join(resourcesDir, ".node-red");
- fs.outputFile(path.join(homePath, ".config.json"),"",function(){
- var homeContext = LocalFileSystem({
- base: "contexts2",
- cache: false
- });
- try {
- homeContext.open().then(function () {
- homeContext.set("node2", "foo2", "bar2", function (err) {
- homeContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOMEPATH = oldHOMEPATH;
- }
- });
- });
-
- it('should use HOME_PATH', function (done) {
- var oldNRH = process.env.NODE_RED_HOME;
- var oldHOMEPATH = process.env.HOMEPATH;
- var oldHOME = process.env.HOME;
- process.env.NODE_RED_HOME = resourcesDir;
- process.env.HOMEPATH = resourcesDir;
- process.env.HOME = resourcesDir;
- var homeContext = LocalFileSystem({
- base: "contexts2",
- cache: false
- });
- try {
- homeContext.open().then(function () {
- homeContext.set("node2", "foo2", "bar2", function (err) {
- homeContext.get("node2", "foo2", function (err, value) {
- value.should.be.equal("bar2");
- context.get("node2", "foo2", function (err, value) {
- should.not.exist(value);
- done();
- });
- });
- });
- });
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOMEPATH = oldHOMEPATH;
- process.env.HOME = oldHOME;
- }
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/context/memory_spec.js b/test/unit/@node-red/runtime/lib/nodes/context/memory_spec.js
deleted file mode 100644
index 663ee46b7..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/context/memory_spec.js
+++ /dev/null
@@ -1,321 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require('should');
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var Memory = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/context/memory");
-
-describe('memory',function() {
- var context;
-
- beforeEach(function() {
- context = Memory({});
- return context.open();
- });
-
- afterEach(function() {
- return context.clean([]).then(function(){
- return context.close();
- });
- });
-
- describe('#get/set',function() {
- describe('sync',function() {
- it('should store property',function() {
- should.not.exist(context.get("nodeX","foo"));
- context.set("nodeX","foo","test");
- context.get("nodeX","foo").should.equal("test");
- });
-
- it('should store property - creates parent properties',function() {
- context.set("nodeX","foo.bar","test");
- context.get("nodeX","foo").should.eql({bar:"test"});
- });
-
- it('should delete property',function() {
- context.set("nodeX","foo.abc.bar1","test1");
- context.set("nodeX","foo.abc.bar2","test2");
- context.get("nodeX","foo.abc").should.eql({bar1:"test1",bar2:"test2"});
- context.set("nodeX","foo.abc.bar1",undefined);
- context.get("nodeX","foo.abc").should.eql({bar2:"test2"});
- context.set("nodeX","foo.abc",undefined);
- should.not.exist(context.get("nodeX","foo.abc"));
- context.set("nodeX","foo",undefined);
- should.not.exist(context.get("nodeX","foo"));
- });
-
- it('should not shared context with other scope', function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","testX");
- context.set("nodeY","foo","testY");
-
- context.get("nodeX","foo").should.equal("testX");
- context.get("nodeY","foo").should.equal("testY");
- });
-
- it('should throw the error if the error occurs', function() {
- try{
- context.set("nodeX",".foo","test");
- should.fail("Error was not thrown");
- }catch(err){
- should.exist(err);
- try{
- context.get("nodeX",".foo");
- should.fail("Error was not thrown");
- }catch(err){
- should.exist(err);
- }
- }
- });
-
- it('should get multiple values - all known', function() {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- var values = context.get("nodeX",["one","two","four"]);
- values.should.eql(["test1","test2","test4"])
- })
- it('should get multiple values - include unknown', function() {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- var values = context.get("nodeX",["one","unknown.with.multiple.levels"]);
- values.should.eql(["test1",undefined])
- })
- it('should throw error if bad key included in multiple keys', function() {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- try{
- var values = context.get("nodeX",["one",".foo","three"]);
- should.fail("Error was not thrown");
- }catch(err){
- should.exist(err);
- }
- })
-
-
- });
-
- describe('async',function() {
- it('should store property',function(done) {
- context.get("nodeX","foo",function(err, value){
- should.not.exist(value);
- context.set("nodeX","foo","test",function(err){
- context.get("nodeX","foo",function(err, value){
- value.should.equal("test");
- done();
- });
- });
- });
- });
-
- it('should pass the error to callback if the error occurs',function(done) {
- context.set("nodeX",".foo","test",function(err, value){
- should.exist(err);
- context.get("nodeX",".foo",function(err){
- should.exist(err);
- done();
- });
- });
- });
-
- it('should get multiple values - all known', function(done) {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- context.get("nodeX",["one","two","four"],function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1","test2","test4"])
- done();
- });
- })
- it('should get multiple values - include unknown', function(done) {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- context.get("nodeX",["one","unknown"],function() {
- Array.prototype.slice.apply(arguments).should.eql([undefined,"test1",undefined])
- done();
- });
- })
- it('should throw error if bad key included in multiple keys', function(done) {
- context.set("nodeX","one","test1");
- context.set("nodeX","two","test2");
- context.set("nodeX","three","test3");
- context.set("nodeX","four","test4");
-
- context.get("nodeX",["one",".foo","three"], function(err) {
- should.exist(err);
- done();
- });
- })
- });
- });
-
- describe('#keys',function() {
- describe('sync',function() {
- it('should enumerate context keys', function() {
- var keys = context.keys("nodeX");
- keys.should.be.an.Array();
- keys.should.be.empty();
-
- context.set("nodeX","foo","bar");
- keys = context.keys("nodeX");
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("nodeX","abc.def","bar");
- keys = context.keys("nodeX");
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- });
-
- it('should enumerate context keys in each scopes', function() {
- var keysX = context.keys("nodeX");
- keysX.should.be.an.Array();
- keysX.should.be.empty();
-
- var keysY = context.keys("nodeY");
- keysY.should.be.an.Array();
- keysY.should.be.empty();
-
- context.set("nodeX","foo","bar");
- context.set("nodeY","hoge","piyo");
- keysX = context.keys("nodeX");
- keysX.should.have.length(1);
- keysX[0].should.equal("foo");
-
- keysY = context.keys("nodeY");
- keysY.should.have.length(1);
- keysY[0].should.equal("hoge");
- });
-
- it('should enumerate global context keys', function () {
- var keys = context.keys("global");
- keys.should.be.an.Array();
- keys.should.be.empty();
-
- context.set("global", "foo", "bar");
- keys = context.keys("global");
- keys.should.have.length(1);
- keys[0].should.equal("foo");
-
- context.set("global", "abc.def", "bar");
- keys = context.keys("global");
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- });
-
- it('should not return specific keys as global context keys', function () {
- var keys = context.keys("global");
-
- context.set("global", "set", "bar");
- context.set("global", "get", "bar");
- context.set("global", "keys", "bar");
- keys = context.keys("global");
- keys.should.have.length(0);
- });
- });
-
- describe('async',function() {
- it('should enumerate context keys', function(done) {
- context.keys("nodeX", function(err, keys) {
- keys.should.be.an.Array();
- keys.should.be.empty();
- context.set("nodeX", "foo", "bar", function(err) {
- context.keys("nodeX", function(err, keys) {
- keys.should.have.length(1);
- keys[0].should.equal("foo");
- context.set("nodeX","abc.def","bar",function(err){
- context.keys("nodeX",function(err, keys){
- keys.should.have.length(2);
- keys[1].should.equal("abc");
- done();
- });
- });
- });
- });
- });
- });
- });
- });
-
- describe('#delete',function() {
- it('should delete context',function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","abc");
- context.set("nodeY","foo","abc");
- context.get("nodeX","foo").should.equal("abc");
- context.get("nodeY","foo").should.equal("abc");
-
- return context.delete("nodeX").then(function(){
- should.not.exist(context.get("nodeX","foo"));
- should.exist(context.get("nodeY","foo"));
- });
- });
- });
-
- describe('#clean',function() {
- it('should clean unnecessary context',function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","abc");
- context.set("nodeY","foo","abc");
- context.get("nodeX","foo").should.equal("abc");
- context.get("nodeY","foo").should.equal("abc");
-
- return context.clean([]).then(function(){
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- });
- });
- it('should not clean active context',function() {
- should.not.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- context.set("nodeX","foo","abc");
- context.set("nodeY","foo","abc");
- context.get("nodeX","foo").should.equal("abc");
- context.get("nodeY","foo").should.equal("abc");
-
- return context.clean(["nodeX"]).then(function(){
- should.exist(context.get("nodeX","foo"));
- should.not.exist(context.get("nodeY","foo"));
- });
- });
- it('should not clean global context', function () {
- context.set("global", "foo", "abc");
- context.get("global", "foo").should.equal("abc");
-
- return context.clean(["global"]).then(function () {
- should.exist(context.get("global", "foo"));
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js b/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js
deleted file mode 100644
index 6db0b867b..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/credentials_spec.js
+++ /dev/null
@@ -1,474 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var index = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/index");
-var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials");
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-
-
-describe('red/runtime/nodes/credentials', function() {
-
- var encryptionDisabledSettings = {
- get: function(key) {
- return false;
- }
- }
-
- afterEach(function() {
- index.clearRegistry();
- });
-
- it('loads provided credentials',function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
-
- return credentials.load({"a":{"b":1,"c":2}}).then(function() {
- credentials.get("a").should.have.property('b',1);
- credentials.get("a").should.have.property('c',2);
- });
- });
- it('adds a new credential',function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
- return credentials.load({"a":{"b":1,"c":2}}).then(function() {
- credentials.dirty().should.be.false();
- should.not.exist(credentials.get("b"));
- return credentials.add("b",{"foo":"bar"}).then(function() {
- credentials.get("b").should.have.property("foo","bar");
- credentials.dirty().should.be.true();
- });
- });
- });
- it('deletes an existing credential',function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
- return credentials.load({"a":{"b":1,"c":2}}).then(function() {
- credentials.dirty().should.be.false();
- credentials.delete("a");
- should.not.exist(credentials.get("a"));
- credentials.dirty().should.be.true();
- });
- });
-
- it('exports the credentials, clearing dirty flag', function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings
- });
- var creds = {"a":{"b":1,"c":2}};
- return credentials.load(creds).then(function() {
- return credentials.add("b",{"foo":"bar"})
- }).then(function() {
- credentials.dirty().should.be.true();
- return credentials.export().then(function(exported) {
- exported.should.eql(creds);
- credentials.dirty().should.be.false();
- })
- });
- })
-
- describe("#clean",function() {
- it("removes credentials of unknown nodes",function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- var creds = {"a":{"b":1,"c":2},"b":{"d":3}};
- return credentials.load(creds).then(function() {
- credentials.dirty().should.be.false();
- should.exist(credentials.get("a"));
- should.exist(credentials.get("b"));
- return credentials.clean([{id:"b"}]).then(function() {
- credentials.dirty().should.be.true();
- should.not.exist(credentials.get("a"));
- should.exist(credentials.get("b"));
- });
- });
- });
- it("extracts credentials of known nodes",function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- credentials.register("testNode",{"b":"text","c":"password"})
- var creds = {"a":{"b":1,"c":2}};
- var newConfig = [{id:"a",type:"testNode",credentials:{"b":"newBValue","c":"newCValue"}}];
- return credentials.load(creds).then(function() {
- credentials.dirty().should.be.false();
- return credentials.clean(newConfig).then(function() {
- credentials.dirty().should.be.true();
- credentials.get("a").should.have.property('b',"newBValue");
- credentials.get("a").should.have.property('c',"newCValue");
- should.not.exist(newConfig[0].credentials);
- });
- });
- });
-
-
- });
-
- it('warns if a node has no credential definition', function() {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- return credentials.load({}).then(function() {
- var node = {id:"node",type:"test",credentials:{
- user1:"newUser",
- password1:"newPassword"
- }};
- sinon.spy(log,"warn");
- credentials.extract(node);
- log.warn.called.should.be.true();
- should.not.exist(node.credentials);
- log.warn.restore();
- });
- })
-
- it('extract credential updates in the provided node', function(done) {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- var defintion = {
- user1:{type:"text"},
- password1:{type:"password"},
- user2:{type:"text"},
- password2:{type:"password"},
- user3:{type:"text"},
- password3:{type:"password"}
-
- };
- credentials.register("test",defintion);
- var def = credentials.getDefinition("test");
- defintion.should.eql(def);
-
- credentials.load({"node":{user1:"abc",password1:"123",user2:"def",password2:"456",user3:"ghi",password3:"789"}}).then(function() {
- var node = {id:"node",type:"test",credentials:{
- // user1 unchanged
- password1:"__PWRD__",
- user2: "",
- password2:" ",
- user3:"newUser",
- password3:"newPassword"
- }};
- credentials.dirty().should.be.false();
- credentials.extract(node);
-
- node.should.not.have.a.property("credentials");
-
- credentials.dirty().should.be.true();
- var newCreds = credentials.get("node");
- newCreds.should.have.a.property("user1","abc");
- newCreds.should.have.a.property("password1","123");
- newCreds.should.not.have.a.property("user2");
- newCreds.should.not.have.a.property("password2");
- newCreds.should.have.a.property("user3","newUser");
- newCreds.should.have.a.property("password3","newPassword");
-
- done();
- });
- });
- it('extract ignores node without credentials', function(done) {
- credentials.init({
- log: log,
- settings: encryptionDisabledSettings,
- nodes: { getType: () => function(){} }
- });
- credentials.load({"node":{user1:"abc",password1:"123"}}).then(function() {
- var node = {id:"node",type:"test"};
-
- credentials.dirty().should.be.false();
- credentials.extract(node);
- credentials.dirty().should.be.false();
- done();
- });
- });
-
- describe("encryption",function() {
- var settings = {};
- var runtime = {
- log: log,
- settings: {
- get: function(key) {
- return settings[key];
- },
- set: function(key,value) {
- settings[key] = value;
- return Promise.resolve();
- },
- delete: function(key) {
- delete settings[key];
- return Promise.resolve();
- }
- },
- nodes: { getType: () => function(){} }
- }
- it('migrates to encrypted and generates default key', function(done) {
- settings = {};
- credentials.init(runtime);
- credentials.load({"node":{user1:"abc",password1:"123"}}).then(function() {
- settings.should.have.a.property("_credentialSecret");
- settings._credentialSecret.should.have.a.length(64);
- credentials.dirty().should.be.true();
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- done();
- })
- });
- });
- });
- it('uses default key', function(done) {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- should.exist(credentials.get("node"));
- credentials.dirty().should.be.false();
- credentials.add("node",{user1:"def",password1:"456"});
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","def");
- credentials.get("node").should.have.a.property("password1","456");
- done();
- })
- });
- });
- });
- it('uses user key', function(done) {
- settings = {
- credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- credentials.dirty().should.be.false();
- should.exist(credentials.get("node"));
- credentials.add("node",{user1:"def",password1:"456"});
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","def");
- credentials.get("node").should.have.a.property("password1","456");
- done();
- })
- });
- });
- });
- it('uses user key - when settings are otherwise unavailable', function(done) {
- var runtime = {
- log: log,
- settings: {
- get: function(key) {
- if (key === 'credentialSecret') {
- return "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a";
- }
- throw new Error();
- },
- set: function(key,value) {
- throw new Error();
- }
- }
- }
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- should.exist(credentials.get("node"));
- credentials.add("node",{user1:"def",password1:"456"});
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","def");
- credentials.get("node").should.have.a.property("password1","456");
- done();
- })
- });
- });
- });
- it('migrates from default key to user key', function() {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a",
- credentialSecret: "aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbcccccccccccccddddddddddddeeeee"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- return credentials.load(cryptedFlows).then(function() {
- credentials.dirty().should.be.true();
- should.exist(credentials.get("node"));
- return credentials.export().then(function(result) {
- result.should.have.a.property("$");
- settings.should.not.have.a.property("_credentialSecret");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- return credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","abc");
- credentials.get("node").should.have.a.property("password1","123");
- })
- });
- });
- });
-
- it('migrates from default key to user key - unencrypted original', function(done) {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a",
- credentialSecret: "aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbcccccccccccccddddddddddddeeeee"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var unencryptedFlows = {"node":{user1:"abc",password1:"123"}};
- credentials.init(runtime);
- credentials.load(unencryptedFlows).then(function() {
- credentials.dirty().should.be.true();
- should.exist(credentials.get("node"));
- credentials.export().then(function(result) {
- result.should.have.a.property("$");
- settings.should.not.have.a.property("_credentialSecret");
-
- // reset everything - but with _credentialSecret still set
- credentials.init(runtime);
- // load the freshly encrypted version
- credentials.load(result).then(function() {
- should.exist(credentials.get("node"));
- credentials.get("node").should.have.a.property("user1","abc");
- credentials.get("node").should.have.a.property("password1","123");
- done();
- })
- });
- });
- });
-
- it('migrates from default key to unencrypted', function(done) {
- settings = {
- _credentialSecret: "e3a36f47f005bf2aaa51ce3fc6fcaafd79da8d03f2b1a9281f8fb0a285e6255a",
- credentialSecret: false
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- credentials.dirty().should.be.true();
- should.exist(credentials.get("node"));
- credentials.export().then(function(result) {
- result.should.not.have.a.property("$");
- settings.should.not.have.a.property("_credentialSecret");
- result.should.eql({"node":{user1:"abc",password1:"123"}});
- done();
- });
- });
- });
- it('handles bad default key - resets credentials', function(done) {
- settings = {
- _credentialSecret: "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- // credentials.dirty().should.be.true();
- // should.not.exist(credentials.get("node"));
- done();
- }).catch(function(err) {
- err.should.have.property('code','credentials_load_failed');
- done();
- });
- });
- it('handles bad user key - resets credentials', function(done) {
- settings = {
- credentialSecret: "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadb"
- };
- // {"node":{user1:"abc",password1:"123"}}
- var cryptedFlows = {"$":"5b89d8209b5158a3c313675561b1a5b5phN1gDBe81Zv98KqS/hVDmc9EKvaKqRIvcyXYvBlFNzzzJtvN7qfw06i"};
- credentials.init(runtime);
- credentials.load(cryptedFlows).then(function() {
- // credentials.dirty().should.be.true();
- // should.not.exist(credentials.get("node"));
- done();
- }).catch(function(err) {
- err.should.have.property('code','credentials_load_failed');
- done();
- });
- });
-
- it('handles unavailable settings - leaves creds unencrypted', function(done) {
- var runtime = {
- log: log,
- settings: {
- get: function(key) {
- throw new Error();
- },
- set: function(key,value) {
- throw new Error();
- }
- },
- nodes: { getType: () => function(){} }
- }
- // {"node":{user1:"abc",password1:"123"}}
- credentials.init(runtime);
- credentials.load({"node":{user1:"abc",password1:"123"}}).then(function() {
- credentials.dirty().should.be.false();
- should.exist(credentials.get("node"));
- credentials.export().then(function(result) {
- result.should.not.have.a.property("$");
- result.should.have.a.property("node");
- done();
- });
- });
- });
- })
-})
diff --git a/test/unit/@node-red/runtime/lib/nodes/index_spec.js b/test/unit/@node-red/runtime/lib/nodes/index_spec.js
deleted file mode 100644
index d6017db45..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/index_spec.js
+++ /dev/null
@@ -1,404 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var fs = require('fs-extra');
-var path = require('path');
-var sinon = require('sinon');
-var inherits = require("util").inherits;
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var index = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/index");
-var flows = NR_TEST_UTILS.require("@node-red/runtime/lib/flows");
-var registry = NR_TEST_UTILS.require("@node-red/registry")
-var Node = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/Node");
-
-describe("red/nodes/index", function() {
- before(function() {
- sinon.stub(index,"startFlows");
- process.env.NODE_RED_HOME = NR_TEST_UTILS.resolve("node-red");
- process.env.foo="bar";
- });
- after(function() {
- index.startFlows.restore();
- delete process.env.NODE_RED_HOME;
- delete process.env.foo;
- });
-
- afterEach(function() {
- index.clearRegistry();
- });
-
- var testFlows = [{"type":"test","id":"tab1","label":"Sheet 1"}];
- var testCredentials = {"tab1":{"b":1, "c":"2", "d":"$(foo)"}};
- var storage = {
- getFlows: function() {
- return Promise.resolve({red:123,flows:testFlows,credentials:testCredentials});
- },
- saveFlows: function(conf) {
- should.deepEqual(testFlows, conf.flows);
- return Promise.resolve(123);
- }
- };
-
- var settings = {
- available: function() { return false },
- get: function() { return false }
- };
-
- var EventEmitter = require('events').EventEmitter;
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:function() {}},
- events: new EventEmitter()
- };
-
- function TestNode(n) {
- this._flow = {getSetting: p => process.env[p]};
- index.createNode(this, n);
- this.on("log", function() {
- // do nothing
- });
- }
-
- it('nodes are initialised with credentials',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- var testnode = new TestNode({id:'tab1',type:'test',name:'barney'});
- testnode.credentials.should.have.property('b',1);
- testnode.credentials.should.have.property('c',"2");
- testnode.credentials.should.have.property('d',"bar");
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('flows should be initialised',function(done) {
- index.init(runtime);
- index.loadFlows().then(function() {
- // console.log(testFlows);
- // console.log(index.getFlows());
- should.deepEqual(testFlows, index.getFlows().flows);
- done();
- }).catch(function(err) {
- done(err);
- });
-
- });
- describe("registerType", function() {
- describe("logs deprecated usage", function() {
- before(function() {
- sinon.stub(registry,"registerType");
- });
- after(function() {
- registry.registerType.restore();
- });
- it("called without node-set name", function() {
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:sinon.spy()},
- events: new EventEmitter()
- }
- index.init(runtime);
-
- index.registerType(/*'test-node-set',*/'test', TestNode, {});
- runtime.log.warn.called.should.be.true();
- registry.registerType.called.should.be.true();
- registry.registerType.firstCall.args[0].should.eql('');
- registry.registerType.firstCall.args[1].should.eql('test');
- registry.registerType.firstCall.args[2].should.eql(TestNode);
- });
- });
- describe("extends constructor with Node constructor", function() {
- var TestNodeConstructor;
- before(function() {
- sinon.stub(registry,"registerType");
- });
- after(function() {
- registry.registerType.restore();
- });
- beforeEach(function() {
- TestNodeConstructor = function TestNodeConstructor() {};
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:sinon.spy()},
- events: new EventEmitter()
- }
- index.init(runtime);
- })
- it('extends a constructor with the Node constructor', function() {
- TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
- index.registerType('node-set','node-type',TestNodeConstructor);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
- });
- it('does not override a constructor prototype', function() {
- function Foo(){};
- inherits(TestNodeConstructor,Foo);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
- TestNodeConstructor.prototype.should.not.be.an.instanceOf(Node);
-
- index.registerType('node-set','node-type',TestNodeConstructor);
-
- TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
-
- index.registerType('node-set','node-type2',TestNodeConstructor);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Node);
- TestNodeConstructor.prototype.should.be.an.instanceOf(Foo);
- });
- });
- describe("register credentials definition", function() {
- var http = require('http');
- var express = require('express');
- var app = express();
- var runtime = NR_TEST_UTILS.require("@node-red/runtime");
- var credentials = NR_TEST_UTILS.require("@node-red/runtime/lib/nodes/credentials");
- var localfilesystem = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem");
- var log = NR_TEST_UTILS.require("@node-red/util").log;
- var RED = NR_TEST_UTILS.require("node-red/lib/red.js");
-
- var userDir = path.join(__dirname,".testUserHome");
- before(function(done) {
- sinon.stub(log,"log").callsFake(function(){});
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,function() {
- sinon.stub(index, 'load').callsFake(function() {
- return new Promise(function(resolve,reject){
- resolve([]);
- });
- });
- sinon.stub(localfilesystem, 'getCredentials').callsFake(function() {
- return new Promise(function(resolve,reject) {
- resolve({"tab1":{"b":1,"c":2}});
- });
- }) ;
- RED.init(http.createServer(function(req,res){app(req,res)}),
- {userDir: userDir});
- runtime.start().then(function () {
- done();
- });
- });
- });
- });
-
- after(function(done) {
- fs.remove(userDir,function() {
- runtime.stop().then(function() {
- index.load.restore();
- localfilesystem.getCredentials.restore();
- log.log.restore();
- done();
- });
- });
- });
-
- it('definition defined',function() {
- index.registerType('test-node-set','test', TestNode, {
- credentials: {
- foo: {type:"test"}
- }
- });
- var testnode = new TestNode({id:'tab1',type:'test',name:'barney', '_alias':'tab1'});
- index.getCredentialDefinition("test").should.have.property('foo');
- });
- });
-
- describe("register settings definition", function() {
- beforeEach(function() {
- sinon.stub(registry,"registerType");
- })
- afterEach(function() {
- registry.registerType.restore();
- })
- it('registers valid settings',function() {
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:function() {}},
- events: new EventEmitter()
- }
- runtime.settings.registerNodeSettings = sinon.spy();
- index.init(runtime);
-
- index.registerType('test-node-set','test', TestNode, {
- settings: {
- testOne: {}
- }
- });
- runtime.settings.registerNodeSettings.called.should.be.true();
- runtime.settings.registerNodeSettings.firstCall.args[0].should.eql('test');
- runtime.settings.registerNodeSettings.firstCall.args[1].should.eql({testOne: {}});
- });
- it('logs invalid settings',function() {
- var runtime = {
- settings: settings,
- storage: storage,
- log: {debug:function() {}, warn:sinon.spy()},
- events: new EventEmitter()
- }
- runtime.settings.registerNodeSettings = function() { throw new Error("pass");}
- index.init(runtime);
-
- index.registerType('test-node-set','test', TestNode, {
- settings: {
- testOne: {}
- }
- });
- runtime.log.warn.called.should.be.true();
- });
- });
- });
-
- describe('allows nodes to be added/removed/enabled/disabled from the registry', function() {
- var randomNodeInfo = {id:"5678",types:["random"]};
-
- beforeEach(function() {
- sinon.stub(registry,"getNodeInfo").callsFake(function(id) {
- if (id == "test") {
- return {id:"1234",types:["test"]};
- } else if (id == "doesnotexist") {
- return null;
- } else {
- return randomNodeInfo;
- }
- });
- sinon.stub(registry,"disableNode").callsFake(function(id) {
- return Promise.resolve(randomNodeInfo);
- });
- });
- afterEach(function() {
- registry.getNodeInfo.restore();
- registry.disableNode.restore();
- });
-
- it('allows an unused node type to be disabled',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- return index.disableNode("5678").then(function(info) {
- registry.disableNode.calledOnce.should.be.true();
- registry.disableNode.calledWith("5678").should.be.true();
- info.should.eql(randomNodeInfo);
- done();
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('prevents disabling a node type that is in use',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.disabledNode("test");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('prevents disabling a node type that is unknown',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.disableNode("doesnotexist");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- });
-
- describe('allows modules to be removed from the registry', function() {
- var randomNodeInfo = {id:"5678",types:["random"]};
- var randomModuleInfo = {
- name:"random",
- nodes: [randomNodeInfo]
- };
-
- before(function() {
- sinon.stub(registry,"getNodeInfo").callsFake(function(id) {
- if (id == "node-red/foo") {
- return {id:"1234",types:["test"]};
- } else if (id == "doesnotexist") {
- return null;
- } else {
- return randomNodeInfo;
- }
- });
- sinon.stub(registry,"getModuleInfo").callsFake(function(module) {
- if (module == "node-red") {
- return {nodes:[{name:"foo"}]};
- } else if (module == "doesnotexist") {
- return null;
- } else {
- return randomModuleInfo;
- }
- });
- sinon.stub(registry,"removeModule").callsFake(function(id) {
- return randomModuleInfo;
- });
- });
- after(function() {
- registry.getNodeInfo.restore();
- registry.getModuleInfo.restore();
- registry.removeModule.restore();
- });
-
- it('prevents removing a module that is in use',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.removeModule("node-red");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('prevents removing a module that is unknown',function(done) {
- index.init(runtime);
- index.registerType('test-node-set','test', TestNode);
- index.loadFlows().then(function() {
- /*jshint immed: false */
- (function() {
- index.removeModule("doesnotexist");
- }).should.throw();
-
- done();
- }).catch(function(err) {
- done(err);
- });
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png b/test/unit/@node-red/runtime/lib/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png
deleted file mode 100644
index e38f3914600901b736f5fa18786ee11be6d41c28..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 393
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6icy_X9x!n)NrJ90QsB+9+AZi
z3~X;em{G3O!W1YdS>hT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjT8d|Bb%p-
zV~9uR+N-+$hZ97Oeyp#Y$RU!&XX#m>@|$agvYL9Jz$O6}72y^gZVi>ZMeaH^t*Q|!
zLhVk<0xdko8zYVo#8M-LBBd8b>1kw|i?FO)bWqsy_rwQg27N4y
zeX6pqO$_Cex^^A7_NsS@+=bOASA^wN0&GKN(hlAguRU&q-
jTBY?`*L>xN+|S&+7B*edvmQhOgN?z{)z4*}Q$iB}+9!`i
diff --git a/test/unit/@node-red/runtime/lib/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png b/test/unit/@node-red/runtime/lib/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
deleted file mode 100644
index 59a29af14..000000000
--- a/test/unit/@node-red/runtime/lib/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
+++ /dev/null
@@ -1,3 +0,0 @@
-This file exists just to ensure the 'icons' directory is in the repository.
-TODO: a future test needs to ensure the right icon files are loaded - this
- directory can be used for that
diff --git a/test/unit/@node-red/runtime/lib/plugins_spec.js b/test/unit/@node-red/runtime/lib/plugins_spec.js
deleted file mode 100644
index a78de643c..000000000
--- a/test/unit/@node-red/runtime/lib/plugins_spec.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const should = require("should");
-const sinon = require("sinon");
-const NR_TEST_UTILS = require("nr-test-utils");
-
-const plugins = NR_TEST_UTILS.require("@node-red/runtime/lib/plugins");
-
-describe("runtime/plugins",function() {
-
- it.skip("delegates all functions to registry module", function() {
- // There's no easy way to test this as we can't stub the registry functions
- // before the plugin module gets a reference to them
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/settings_spec.js b/test/unit/@node-red/runtime/lib/settings_spec.js
deleted file mode 100644
index 51c190fea..000000000
--- a/test/unit/@node-red/runtime/lib/settings_spec.js
+++ /dev/null
@@ -1,333 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var settings = NR_TEST_UTILS.require("@node-red/runtime/lib/settings");
-
-
-describe("runtime/settings", function() {
-
- afterEach(function() {
- settings.reset();
- });
-
- it('wraps the user settings as read-only properties', function() {
- var userSettings = {
- a: 123,
- b: "test",
- c: [1,2,3]
- }
- settings.init(userSettings);
-
- settings.available().should.be.false();
-
- settings.a.should.equal(123);
- settings.b.should.equal("test");
- settings.c.should.be.an.Array();
- settings.c.should.have.lengthOf(3);
-
- settings.get("a").should.equal(123);
- settings.get("b").should.equal("test");
- settings.get("c").should.be.an.Array();
- settings.get("c").should.have.lengthOf(3);
-
- /*jshint immed: false */
- (function() {
- settings.a = 456;
- }).should.throw();
-
- settings.c.push(5);
- settings.c.should.be.an.Array();
- settings.c.should.have.lengthOf(4);
-
- /*jshint immed: false */
- (function() {
- settings.set("a",456);
- }).should.throw();
-
- /*jshint immed: false */
- (function() {
- settings.set("a",456);
- }).should.throw();
-
- /*jshint immed: false */
- (function() {
- settings.get("unknown");
- }).should.throw();
-
- /*jshint immed: false */
- (function() {
- settings.set("unknown",456);
- }).should.throw();
-
- });
-
- it('loads global settings from storage', function(done) {
- var userSettings = {
- a: 123,
- b: "test",
- c: [1,2,3]
- }
- var savedSettings = null;
- var saveCount = 0;
- var storage = {
- getSettings: function() {
- return Promise.resolve({globalA:789});
- },
- saveSettings: function(settings) {
- saveCount++;
- savedSettings = settings;
- return Promise.resolve();
- }
- }
- settings.init(userSettings);
-
- settings.available().should.be.false();
-
- /*jshint immed: false */
- (function() {
- settings.get("unknown");
- }).should.throw();
- settings.load(storage).then(function() {
- settings.available().should.be.true();
- settings.get("globalA").should.equal(789);
- settings.set("globalA","abc").then(function() {
- savedSettings.globalA.should.equal("abc");
- saveCount.should.equal(1);
- settings.set("globalA","abc").then(function() {
- savedSettings.globalA.should.equal("abc");
- // setting to existing value should not trigger save
- saveCount.should.equal(1);
- done();
- });
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('removes persistent settings when reset', function() {
- var userSettings = {
- a: 123,
- b: "test",
- c: [1,2,3]
- }
- settings.init(userSettings);
-
- settings.available().should.be.false();
-
- settings.should.have.property("a",123);
- settings.should.have.property("b","test");
- settings.c.should.be.an.Array();
- settings.c.should.have.lengthOf(3);
-
- settings.reset();
-
- settings.should.not.have.property("a");
- settings.should.not.have.property("d");
- settings.should.not.have.property("c");
-
- });
-
- it('registers node settings and exports them', function() {
- var userSettings = {};
- settings.init(userSettings);
- settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}, injectSize:{value:"100", exportable:true}} );
- settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:false}, mqttSize:{value:"50", exportable:true}} );
- settings.registerNodeSettings("http request", {httpRequest1:{value:"a1", exportable:true}} );
- settings.registerNodeSettings(" http--request<> ", {httpRequest2:{value:"a2", exportable:true}} );
- settings.registerNodeSettings("_http_request_", {httpRequest3:{value:"a3", exportable:true}} );
- settings.registerNodeSettings("mQtT", {mQtTColor:{value:"purple", exportable:true}} );
- settings.registerNodeSettings("abc123", {abc123:{value:"def456", exportable:true}} );
- settings.registerNodeSettings("noValue", {noValueHasValue:{value:"123", exportable:true}, noValueNoValue:{exportable:true}} );
-
- var safeSettings = {};
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "red");
- safeSettings.should.have.property("injectSize", "100");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.have.property("mqttSize", "50");
- safeSettings.should.have.property("httpRequest1", "a1");
- safeSettings.should.have.property("httpRequest2", "a2");
- safeSettings.should.have.property("httpRequest3", "a3");
- safeSettings.should.have.property("mQtTColor", "purple");
- safeSettings.should.have.property("abc123", "def456");
-
- safeSettings.should.have.property("noValueHasValue", "123");
- safeSettings.should.not.have.property("noValueNoValue");
- });
-
- it('prohibits registering the property whose name do not start with type name', function() {
- var userSettings = {};
- settings.init(userSettings);
- (function() {
- settings.registerNodeSettings("inject", {color:{value:"red", exportable:true}} );
- }).should.throw();
- (function() {
- settings.registerNodeSettings("_a_b_1_", {ab1Color:{value:"red", exportable:true}} );
- }).should.throw();
- (function() {
- settings.registerNodeSettings("AB2", {AB2Color:{value:"red", exportable:true}} );
- }).should.throw();
- (function() {
- settings.registerNodeSettings("abcDef", {abcColor:{value:"red", exportable:true}} );
- }).should.throw();
- var safeSettings = {};
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.not.have.property("color");
- safeSettings.should.not.have.property("ab1Color", "blue");
- safeSettings.should.not.have.property("AB2Color");
- safeSettings.should.not.have.property("abcColor");
- });
-
- it('overwrites node settings with user settings', function() {
- var userSettings = {
- injectColor: "green",
- mqttColor: "yellow",
- abColor: [1,2,3]
- }
- settings.init(userSettings);
- settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
- settings.registerNodeSettings("ab", {abColor:{value:"red", exportable:false}} );
- var safeSettings = {};
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "green");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.not.have.property("abColor");
- });
-
- it('disables/enables node settings', function() {
- var userSettings = {};
- settings.init(userSettings);
-
- var safeSettings = {};
- settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
- settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:true}} );
- settings.registerNodeSettings("http request", {httpRequestColor:{value:"yellow", exportable:true}} );
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "red");
- safeSettings.should.have.property("mqttColor", "purple");
- safeSettings.should.have.property("httpRequestColor", "yellow");
-
- safeSettings = {};
- var types = ["inject", "mqtt"];
- settings.disableNodeSettings(types);
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.not.have.property("injectColor");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.have.property("httpRequestColor", "yellow");
-
- safeSettings = {};
- types = ["inject"];
- settings.enableNodeSettings(types);
- settings.exportNodeSettings(safeSettings);
- safeSettings.should.have.property("injectColor", "red");
- safeSettings.should.not.have.property("mqttColor");
- safeSettings.should.have.property("httpRequestColor", "yellow");
- });
-
-
- it('delete global setting', function() {
- // read-only
- var localSettings = {a:1};
- // read-write
- var globalSettings = {b:2};
- var storage = {
- getSettings: function() {
- return Promise.resolve(globalSettings);
- },
- saveSettings: function() {
- return Promise.resolve();
- }
- }
- settings.init(localSettings);
- return settings.load(storage).then(function() {
- settings.get('a').should.eql(1);
- settings.get('b').should.eql(2);
- return settings.delete('b')
- }).then(function() {
- should.not.exist(settings.get('b'));
- })
- });
-
- it('refused to delete local setting', function(done) {
- // read-only
- var localSettings = {a:1};
- // read-write
- var globalSettings = {b:2};
- var storage = {
- getSettings: function() {
- return Promise.resolve(globalSettings);
- }
- }
- settings.init(localSettings);
- settings.load(storage).then(function() {
- settings.get('a').should.eql(1);
- settings.get('b').should.eql(2);
- try {
- settings.delete('a');
- return done("Did not throw error");
- } catch(err) {
- // expected
- }
- done();
- }).catch(done)
- });
-
-
- it('get user settings', function() {
- var userSettings = {
- admin: {a:1}
- }
- var storage = {
- getSettings: function() {
- return Promise.resolve({a:1,users:userSettings});
- }
- }
- settings.init(userSettings);
- return settings.load(storage).then(function() {
- var result = settings.getUserSettings('admin');
- result.should.eql(userSettings.admin);
- // Check it has been cloned
- result.should.not.equal(userSettings.admin);
- })
- })
- it('set user settings', function() {
- var userSettings = {
- admin: {a:1}
- }
- var savedSettings;
- var storage = {
- getSettings: function() {
- return Promise.resolve({c:3,users:userSettings});
- },
- saveSettings: function(s) {
- savedSettings = s;
- return Promise.resolve();
- }
- }
- settings.init(userSettings);
- return settings.load(storage).then(function() {
- return settings.setUserSettings('admin',{b:2})
- }).then(function() {
- savedSettings.should.have.property("c",3);
- savedSettings.should.have.property('users');
- savedSettings.users.should.eql({admin:{b:2}})
- })
- })
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/index_spec.js b/test/unit/@node-red/runtime/lib/storage/index_spec.js
deleted file mode 100644
index dd9fa6e9b..000000000
--- a/test/unit/@node-red/runtime/lib/storage/index_spec.js
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-var paff = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var storage = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/index");
-
-describe("red/storage/index", function() {
-
- it('rejects the promise when settings suggest loading a bad module', function(done) {
-
- var wrongModule = {
- settings:{
- storageModule : "thisaintloading"
- }
- };
-
- storage.init(wrongModule).then( function() {
- var one = 1;
- var zero = 0;
- try {
- zero.should.equal(one, "The initialization promise should never get resolved");
- } catch(err) {
- done(err);
- }
- }).catch(function(e) {
- done(); //successfully rejected promise
- });
- });
-
- it('non-string storage module', function(done) {
- var initSetsMeToTrue = false;
-
- var moduleWithBooleanSettingInit = {
- init : function() {
- initSetsMeToTrue = true;
- }
- };
-
- var setsBooleanModule = {
- settings: {
- storageModule : moduleWithBooleanSettingInit
- }
- };
-
- storage.init(setsBooleanModule);
- initSetsMeToTrue.should.be.true();
- done();
- });
-
- it('respects storage interface', function(done) {
- var calledFlagGetFlows = false;
- var calledFlagGetCredentials = false;
- var calledFlagGetAllFlows = false;
- var calledInit = false;
- var calledFlagGetSettings = false;
- var calledFlagGetSessions = false;
-
- var interfaceCheckerModule = {
- init : function (settings) {
- settings.should.be.an.Object();
- calledInit = true;
- },
- getFlows : function() {
- calledFlagGetFlows = true;
- return Promise.resolve([]);
- },
- saveFlows : function (flows) {
- flows.should.be.an.Array();
- flows.should.have.lengthOf(0);
- return Promise.resolve("");
- },
- getCredentials : function() {
- calledFlagGetCredentials = true;
- return Promise.resolve({});
- },
- saveCredentials : function(credentials) {
- credentials.should.be.true();
- },
- getSettings : function() {
- calledFlagGetSettings = true;
- },
- saveSettings : function(settings) {
- settings.should.be.true();
- },
- getSessions : function() {
- calledFlagGetSessions = true;
- },
- saveSessions : function(sessions) {
- sessions.should.be.true();
- },
- getAllFlows : function() {
- calledFlagGetAllFlows = true;
- },
- getFlow : function(fn) {
- fn.should.equal("name");
- },
- saveFlow : function(fn, data) {
- fn.should.equal("name");
- data.should.be.true();
- },
- getLibraryEntry : function(type, path) {
- type.should.be.true();
- path.should.equal("name");
- },
- saveLibraryEntry : function(type, path, meta, body) {
- type.should.be.true();
- path.should.equal("name");
- meta.should.be.true();
- body.should.be.true();
- }
- };
-
- var moduleToLoad = {
- settings: {
- storageModule : interfaceCheckerModule
- }
- };
-
- var promises = [];
- storage.init(moduleToLoad);
- promises.push(storage.getFlows());
- promises.push(storage.saveFlows({flows:[],credentials:{}}));
- storage.getSettings();
- storage.saveSettings(true);
- storage.getSessions();
- storage.saveSessions(true);
- storage.getAllFlows();
- storage.getFlow("name");
- storage.saveFlow("name", true);
- storage.getLibraryEntry(true, "name");
- storage.saveLibraryEntry(true, "name", true, true);
-
- Promise.all(promises).then(function() {
- try {
- calledInit.should.be.true();
- calledFlagGetFlows.should.be.true();
- calledFlagGetCredentials.should.be.true();
- calledFlagGetAllFlows.should.be.true();
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- describe('respects deprecated flow library functions', function() {
-
- var savePath;
- var saveContent;
- var saveMeta;
- var saveType;
-
- var interfaceCheckerModule = {
- init : function (settings) {
- settings.should.be.an.Object();
- },
- getLibraryEntry : function(type, path) {
- if (type === "flows") {
- if (path === "/" || path === "\\") {
- return Promise.resolve(["a",{fn:"test.json"}]);
- } else if (path == "/a" || path == "\\a") {
- return Promise.resolve([{fn:"test2.json"}]);
- } else if (path == paff.join("","a","test2.json")) {
- return Promise.resolve("test content");
- }
- }
- },
- saveLibraryEntry : function(type, path, meta, body) {
- saveType = type;
- savePath = path;
- saveContent = body;
- saveMeta = meta;
- return Promise.resolve();
- }
- };
-
- var moduleToLoad = {
- settings: {
- storageModule : interfaceCheckerModule
- }
- };
- before(function() {
- storage.init(moduleToLoad);
- });
- it('getAllFlows',function(done) {
- storage.getAllFlows().then(function (res) {
- try {
- res.should.eql({ d: { a: { f: ['test2'] } }, f: [ 'test' ] });
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it('getFlow',function(done) {
- storage.getFlow(paff.join("a","test2.json")).then(function(res) {
- try {
- res.should.eql("test content");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
-
- it ('saveFlow', function (done) {
- storage.saveFlow(paff.join("a","test2.json"),"new content").then(function(res) {
- try {
- savePath.should.eql(paff.join("a","test2.json"));
- saveContent.should.eql("new content");
- saveMeta.should.eql({});
- saveType.should.eql("flows");
- done();
- } catch(err) {
- done(err);
- }
- });
-
- });
- });
-
- describe('handles missing settings/sessions interface', function() {
- before(function() {
- var interfaceCheckerModule = {
- init : function () {}
- };
- storage.init({settings:{storageModule: interfaceCheckerModule}});
- });
-
- it('defaults missing getSettings',function(done) {
- storage.getSettings().then(function(settings) {
- should.not.exist(settings);
- done();
- });
- });
- it('defaults missing saveSettings',function(done) {
- storage.saveSettings({}).then(function() {
- done();
- });
- });
- it('defaults missing getSessions',function(done) {
- storage.getSessions().then(function(settings) {
- should.not.exist(settings);
- done();
- });
- });
- it('defaults missing saveSessions',function(done) {
- storage.saveSessions({}).then(function() {
- done();
- });
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js
deleted file mode 100644
index 65826c9f4..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/index_spec.js
+++ /dev/null
@@ -1,518 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var fs = require('fs-extra');
-var path = require('path');
-var sinon = require('sinon');
-var NR_TEST_UTILS = require("nr-test-utils");
-var process = require("process");
-
-var localfilesystem = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem");
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-
-describe('storage/localfilesystem', function() {
- var mockRuntime = {
- log:{
- _:function() { return "placeholder message"},
- info: function() { },
- warn: function() { },
- trace: function() {}
- }
- };
- var userDir = path.join(__dirname,".testUserHome");
- var testFlow = [{"type":"tab","id":"d8be2a6d.2741d8","label":"Sheet 1"}];
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
-
- it('should initialise the user directory',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(path.join(userDir,"lib")).should.be.true();
- fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
-
- it('should set userDir to NRH if .config.json presents',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- fs.mkdirSync(process.env.NODE_RED_HOME);
- fs.writeFileSync(path.join(process.env.NODE_RED_HOME,".config.json"),"{}","utf8");
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.NODE_RED_HOME,"lib")).should.be.true();
- fs.existsSync(path.join(process.env.NODE_RED_HOME,"lib",'flows')).should.be.true();
- settings.userDir.should.equal(process.env.NODE_RED_HOME);
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should set userDir to HOMEPATH/.node-red if .config.json presents',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
- fs.mkdirSync(process.env.HOMEPATH);
- fs.mkdirSync(path.join(process.env.HOMEPATH,".node-red"));
- fs.writeFileSync(path.join(process.env.HOMEPATH,".node-red",".config.json"),"{}","utf8");
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.HOMEPATH,".node-red","lib")).should.be.true();
- fs.existsSync(path.join(process.env.HOMEPATH,".node-red","lib",'flows')).should.be.true();
- settings.userDir.should.equal(path.join(process.env.HOMEPATH,".node-red"));
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.NODE_HOMEPATH = oldHOMEPATH;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should set userDir to HOME/.node-red',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- var oldHOME = process.env.HOME;
- process.env.HOME = path.join(userDir,"HOME");
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
-
- fs.mkdirSync(process.env.HOME);
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.HOME,".node-red","lib")).should.be.true();
- fs.existsSync(path.join(process.env.HOME,".node-red","lib",'flows')).should.be.true();
- settings.userDir.should.equal(path.join(process.env.HOME,".node-red"));
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOME = oldHOME;
- process.env.HOMEPATH = oldHOMEPATH;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should set userDir to USERPROFILE/.node-red',function(done) {
- var oldNRH = process.env.NODE_RED_HOME;
- process.env.NODE_RED_HOME = path.join(userDir,"NRH");
- var oldHOME = process.env.HOME;
- process.env.HOME = "";
- var oldHOMEPATH = process.env.HOMEPATH;
- process.env.HOMEPATH = path.join(userDir,"HOMEPATH");
- var oldUSERPROFILE = process.env.USERPROFILE;
- process.env.USERPROFILE = path.join(userDir,"USERPROFILE");
-
- fs.mkdirSync(process.env.USERPROFILE);
- var settings = {getUserSettings: () => {{}}};
- localfilesystem.init(settings, mockRuntime).then(function() {
- try {
- fs.existsSync(path.join(process.env.USERPROFILE,".node-red","lib")).should.be.true();
- fs.existsSync(path.join(process.env.USERPROFILE,".node-red","lib",'flows')).should.be.true();
- settings.userDir.should.equal(path.join(process.env.USERPROFILE,".node-red"));
- done();
- } catch(err) {
- done(err);
- } finally {
- process.env.NODE_RED_HOME = oldNRH;
- process.env.HOME = oldHOME;
- process.env.HOMEPATH = oldHOMEPATH;
- process.env.USERPROFILE = oldUSERPROFILE;
- }
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle missing flow file',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- fs.existsSync(flowFilePath).should.be.false();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle empty flow file, no backup',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
- fs.closeSync(fs.openSync(flowFilePath, 'w'));
- fs.existsSync(flowFilePath).should.be.true();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle empty flow file, restores backup',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
- fs.closeSync(fs.openSync(flowFilePath, 'w'));
- fs.existsSync(flowFilePath).should.be.true();
- fs.existsSync(flowFileBackupPath).should.be.false();
- fs.writeFileSync(flowFileBackupPath,JSON.stringify(testFlow));
- fs.existsSync(flowFileBackupPath).should.be.true();
- setTimeout(function() {
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- },50);
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should save flows to the default file',function(done) {
- localfilesystem.init({userDir:userDir,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- var flowFile = 'flows_'+require('os').hostname()+'.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
- fs.existsSync(flowFilePath).should.be.false();
- fs.existsSync(flowFileBackupPath).should.be.false();
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(flowFilePath).should.be.true();
- fs.existsSync(flowFileBackupPath).should.be.false();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should save flows to the specified file',function(done) {
- var defaultFlowFile = 'flows_'+require('os').hostname()+'.json';
- var defaultFlowFilePath = path.join(userDir,defaultFlowFile);
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.false();
-
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.true();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should format the flows file when flowFilePretty specified',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,flowFilePretty:true,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- localfilesystem.saveFlows(testFlow).then(function() {
- var content = fs.readFileSync(flowFilePath,"utf8");
- content.split("\n").length.should.be.above(1);
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should fsync the flows file',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- localfilesystem.init({editorTheme:{projects:{enabled:false}},userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- sinon.spy(fs,"fsync");
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.fsync.callCount.should.be.greaterThan(0);
- fs.fsync.restore();
- done();
- }).catch(function(err) {
- fs.fsync.restore();
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should log fsync errors and continue',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- sinon.stub(fs,"fsync").callsFake(function(fd, cb) {
- cb(new Error());
- });
- sinon.spy(log,"warn");
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.fsync.callCount.should.be.greaterThan(0);
- log.warn.restore();
- fs.fsync.callCount.should.be.greaterThan(0);
- fs.fsync.restore();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should backup the flows file', function(done) {
- var defaultFlowFile = 'flows_'+require('os').hostname()+'.json';
- var defaultFlowFilePath = path.join(userDir,defaultFlowFile);
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var flowFileBackupPath = path.join(userDir,"."+flowFile+".backup");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.false();
- fs.existsSync(flowFileBackupPath).should.be.false();
-
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(flowFileBackupPath).should.be.false();
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.true();
- var content = fs.readFileSync(flowFilePath,'utf8');
- var testFlow2 = [{"type":"tab","id":"bc5672ad.2741d8","label":"Sheet 2"}];
-
- localfilesystem.saveFlows(testFlow2).then(function() {
- fs.existsSync(flowFileBackupPath).should.be.true();
- fs.existsSync(defaultFlowFilePath).should.be.false();
- fs.existsSync(flowFilePath).should.be.true();
- var backupContent = fs.readFileSync(flowFileBackupPath,'utf8');
- content.should.equal(backupContent);
- var content2 = fs.readFileSync(flowFilePath,'utf8');
- content2.should.not.equal(backupContent);
- done();
-
- }).catch(function(err) {
- done(err);
- });
-
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
-
-
- });
-
- it('should handle missing credentials', function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
- fs.existsSync(credFile).should.be.false();
-
- localfilesystem.getCredentials().then(function(creds) {
- creds.should.eql({});
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle credentials', function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
-
- fs.existsSync(credFile).should.be.false();
-
- var credentials = {"abc":{"type":"creds"}};
-
- localfilesystem.saveCredentials(credentials).then(function() {
- fs.existsSync(credFile).should.be.true();
- localfilesystem.getCredentials().then(function(creds) {
- creds.should.eql(credentials);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
-
- it('should backup existing credentials', function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
- var credFileBackup = path.join(userDir,".test_cred.json.backup");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath,getUserSettings: () => {{}}}, mockRuntime).then(function() {
-
- fs.writeFileSync(credFile,"{}","utf8");
-
- fs.existsSync(credFile).should.be.true();
- fs.existsSync(credFileBackup).should.be.false();
-
- var credentials = {"abc":{"type":"creds"}};
-
- localfilesystem.saveCredentials(credentials).then(function() {
- fs.existsSync(credFile).should.be.true();
- fs.existsSync(credFileBackup).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should format the creds file when flowFilePretty specified',function(done) {
- var flowFile = 'test.json';
- var flowFilePath = path.join(userDir,flowFile);
- var credFile = path.join(userDir,"test_cred.json");
-
- localfilesystem.init({userDir:userDir, flowFile:flowFilePath, flowFilePretty:true,getUserSettings: () => {{}}}, mockRuntime).then(function() {
-
- fs.existsSync(credFile).should.be.false();
-
- var credentials = {"abc":{"type":"creds"}};
-
- localfilesystem.saveCredentials(credentials).then(function() {
- fs.existsSync(credFile).should.be.true();
- var content = fs.readFileSync(credFile,"utf8");
- content.split("\n").length.should.be.above(1);
- localfilesystem.getCredentials().then(function(creds) {
- creds.should.eql(credentials);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle flow file in random unc path and non-existent subfolder',function(done) {
- // only test on win32
- if (process.platform !== 'win32') {
- console.log('skipped test as not win32');
- done();
- return;
- }
-
- // get a real windows path
- var flowFile = path.win32.resolve(userDir+'/some/random/path');
- var rootdir = path.win32.resolve(userDir+'/some');
- // make it into a local UNC path
- flowFile = flowFile.replace('C:\\', '\\\\localhost\\c$\\');
- localfilesystem.init({userDir:userDir, flowFile:flowFile}, mockRuntime).then(function() {
- fs.existsSync(flowFile).should.be.false();
- localfilesystem.saveFlows(testFlow).then(function() {
- fs.existsSync(flowFile).should.be.true();
- localfilesystem.getFlows().then(function(flows) {
- flows.should.eql(testFlow);
- // cleanup
- fs.removeSync(rootdir);
- done();
- }).catch(function(err) {
- // cleanup
- fs.removeSync(rootdir);
- done(err);
- });
- }).catch(function(err) {
- // cleanup
- fs.removeSync(rootdir);
- done(err);
- });
- }).catch(function(err) {
- // cleanup
- fs.removeSync(rootdir);
- done(err);
- });
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/library_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/library_spec.js
deleted file mode 100644
index 69b6e3da6..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/library_spec.js
+++ /dev/null
@@ -1,244 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var fs = require('fs-extra');
-var path = require('path');
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var localfilesystemLibrary = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/library");
-
-describe('storage/localfilesystem/library', function() {
- var userDir = path.join(__dirname,".testUserHome");
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
-
- it('should return an empty list of library objects',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- localfilesystemLibrary.getLibraryEntry('object','').then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return an empty list of library objects (path=/)',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- localfilesystemLibrary.getLibraryEntry('object','/').then(function(flows) {
- flows.should.eql([]);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return an error for a non-existent library object',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- localfilesystemLibrary.getLibraryEntry('object','A/B').then(function(flows) {
- should.fail(null,null,"non-existent flow");
- }).catch(function(err) {
- should.exist(err);
- done();
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- function createObjectLibrary(type) {
- type = type || "object";
- var objLib = path.join(userDir, "lib", type);
- try {
- fs.mkdirSync(objLib);
- } catch (err) {
- }
- fs.mkdirSync(path.join(objLib, "A"));
- fs.mkdirSync(path.join(objLib, "B"));
- fs.mkdirSync(path.join(objLib, "B", "C"));
- fs.mkdirSync(path.join(objLib, "D"));
- if (type === "functions" || type === "object") {
- fs.writeFileSync(path.join(objLib, "file1.js"), "// abc: def\n// not a metaline \n\n Hi", 'utf8');
- fs.writeFileSync(path.join(objLib, "B", "file2.js"), "// ghi: jkl\n// not a metaline \n\n Hi", 'utf8');
- fs.writeFileSync(path.join(objLib, "D", "file3.js"), "// mno: 日本語テスト\n\nこんにちわ", 'utf8');
- }
- if (type === "flows" || type === "object") {
- fs.writeFileSync(path.join(objLib, "B", "flow.json"), "Hi", 'utf8');
- }
- }
-
- it('should return a directory listing of library objects', function (done) {
- localfilesystemLibrary.init({userDir: userDir}).then(function () {
- createObjectLibrary();
-
- localfilesystemLibrary.getLibraryEntry('object', '').then(function (flows) {
- flows.should.eql([ 'A', 'B', 'D', { abc: 'def', fn: 'file1.js' }]);
- localfilesystemLibrary.getLibraryEntry('object', 'B').then(function (flows) {
- flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' }, { fn: 'flow.json' }]);
- localfilesystemLibrary.getLibraryEntry('object', 'B/C').then(function (flows) {
- flows.should.eql([]);
- localfilesystemLibrary.getLibraryEntry('object', 'D').then(function (flows) {
- flows.should.eql([{ mno: '日本語テスト', fn: 'file3.js' }]);
- done();
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- }).catch(function (err) {
- done(err);
- });
- });
-
- it('should load a flow library object with .json unspecified', function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("flows");
- localfilesystemLibrary.getLibraryEntry('flows','B/flow').then(function(flows) {
- flows.should.eql("Hi");
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- });
-
- it('should return a library object',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary();
- localfilesystemLibrary.getLibraryEntry('object','B/file2.js').then(function(body) {
- body.should.eql("// not a metaline \n\n Hi");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return a newly saved library function',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("functions");
- localfilesystemLibrary.getLibraryEntry('functions','B').then(function(flows) {
- flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]);
- var ft = path.join("B","D","file3.js");
- localfilesystemLibrary.saveLibraryEntry('functions',ft,{mno:'pqr'},"// another non meta line\n\n Hi There").then(function() {
- setTimeout(function() {
- localfilesystemLibrary.getLibraryEntry('functions',path.join("B","D")).then(function(flows) {
- flows.should.eql([ { mno: 'pqr', fn: 'file3.js' } ]);
- localfilesystemLibrary.getLibraryEntry('functions',ft).then(function(body) {
- body.should.eql("// another non meta line\n\n Hi There");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- })
- }, 50);
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return a newly saved library flow',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("flows");
- localfilesystemLibrary.getLibraryEntry('flows','B').then(function(flows) {
- flows.should.eql([ 'C', {fn:'flow.json'} ]);
- var ft = path.join("B","D","file3");
- localfilesystemLibrary.saveLibraryEntry('flows',ft,{mno:'pqr'},"Hi").then(function() {
- setTimeout(function() {
- localfilesystemLibrary.getLibraryEntry('flows',path.join("B","D")).then(function(flows) {
- flows.should.eql([ { mno: 'pqr', fn: 'file3.json' } ]);
- localfilesystemLibrary.getLibraryEntry('flows',ft+".json").then(function(body) {
- body.should.eql("Hi");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- })
- }, 50);
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should return a newly saved library flow (multi-byte character)',function(done) {
- localfilesystemLibrary.init({userDir:userDir}).then(function() {
- createObjectLibrary("flows");
- localfilesystemLibrary.getLibraryEntry('flows','B').then(function(flows) {
- flows.should.eql([ 'C', {fn:'flow.json'} ]);
- var ft = path.join("B","D","file4");
- localfilesystemLibrary.saveLibraryEntry('flows',ft,{mno:'pqr'},"こんにちわこんにちわこんにちわ").then(function() {
- setTimeout(function() {
- localfilesystemLibrary.getLibraryEntry('flows',path.join("B","D")).then(function(flows) {
- flows.should.eql([ { mno: 'pqr', fn: 'file4.json' } ]);
- localfilesystemLibrary.getLibraryEntry('flows',ft+".json").then(function(body) {
- body.should.eql("こんにちわこんにちわこんにちわ");
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- })
- }, 50);
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/Project_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/Project_spec.js
deleted file mode 100644
index ecf24cf40..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/Project_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-describe("storage/localfilesystem/projects/Project", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-})
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet_spec.js
deleted file mode 100644
index 3fab5a45c..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-var should = require("should");
-var NR_TEST_UTILS = require("nr-test-utils");
-var defaultFileSet = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/defaultFileSet");
-
-describe('storage/localfilesystem/projects/defaultFileSet', function() {
- var runtime = {
- i18n: {
- "_": function(name) {
- return name;
- }
- }
- };
- it('generates package.json for a project', function() {
- var generated = defaultFileSet["package.json"]({
- name: "A TEST NAME",
- summary: "A TEST SUMMARY",
- files: {
- flow: "MY FLOW FILE",
- credentials: "MY CREDENTIALS FILE"
- }
- }, runtime);
-
- var parsed = JSON.parse(generated);
- parsed.should.have.property('name',"A TEST NAME");
- parsed.should.have.property('description',"A TEST SUMMARY");
- parsed.should.have.property('node-red');
- parsed['node-red'].should.have.property('settings');
- parsed['node-red'].settings.should.have.property('flowFile',"MY FLOW FILE");
- parsed['node-red'].settings.should.have.property('credentialsFile',"MY CREDENTIALS FILE");
- });
-
- it('generates README.md for a project', function() {
- var generated = defaultFileSet["README.md"]({
- name: "A TEST NAME",
- summary: "A TEST SUMMARY"
- }, runtime);
- generated.should.match(/A TEST NAME/);
- generated.should.match(/A TEST SUMMARY/);
- });
- it('generates .gitignore for a project', function() {
- var generated = defaultFileSet[".gitignore"]({
- name: "A TEST NAME",
- summary: "A TEST SUMMARY"
- }, runtime);
- generated.length.should.be.greaterThan(0);
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache_spec.js
deleted file mode 100644
index c1617bf90..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache_spec.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var authCache = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/git/authCache")
-
-describe("localfilesystem/projects/git/authCache", function() {
-
- beforeEach(function() {
- authCache.init();
- });
- afterEach(function() {
- authCache.init();
- });
-
- it('sets/clears auth details for a given project/remote/user', function() {
- should.not.exist(authCache.get("project","remote1","user1"));
- should.not.exist(authCache.get("project","remote1","user2"));
-
- authCache.set("project","remote1","user1",{foo1:"bar1"});
- authCache.set("project","remote1","user2",{foo2:"bar2"});
-
- var result = authCache.get("project","remote1","user1");
- result.should.have.property("foo1","bar1");
-
- result = authCache.get("project","remote1","user2");
- result.should.have.property("foo2","bar2");
-
- authCache.clear("project","remote1","user1");
- should.not.exist(authCache.get("project","remote1","user1"));
- should.exist(authCache.get("project","remote1","user2"));
-
- });
-
-
- it('clears auth details for all users on a given project/remote', function() {
-
- authCache.set("project","remote1","user1",{foo1:"bar1"});
- authCache.set("project","remote1","user2",{foo2:"bar2"});
- authCache.set("project","remote2","user1",{foo3:"bar3"});
-
- should.exist(authCache.get("project","remote1","user1"));
- should.exist(authCache.get("project","remote1","user2"));
- should.exist(authCache.get("project","remote2","user1"));
-
- authCache.clear("project","remote1");
- should.not.exist(authCache.get("project","remote1","user1"));
- should.not.exist(authCache.get("project","remote1","user2"));
- should.exist(authCache.get("project","remote2","user1"));
- });
-
- it('clears auth details for all remotes/users on a given project', function() {
-
- authCache.set("project1","remote1","user1",{foo1:"bar1"});
- authCache.set("project1","remote1","user2",{foo2:"bar2"});
- authCache.set("project2","remote2","user1",{foo3:"bar3"});
-
- should.exist(authCache.get("project1","remote1","user1"));
- should.exist(authCache.get("project1","remote1","user2"));
- should.exist(authCache.get("project2","remote2","user1"));
-
- authCache.clear("project2");
- should.exist(authCache.get("project1","remote1","user1"));
- should.exist(authCache.get("project1","remote1","user2"));
- should.not.exist(authCache.get("project2","remote2","user1"));
- });
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer_spec.js
deleted file mode 100644
index 9b789a66b..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer_spec.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var net = require("net");
-var path = require("path");
-var os = require("os");
-var should = require("should");
-var sinon = require("sinon");
-var child_process = require("child_process");
-var fs = require("fs-extra");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var authServer = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/git/authServer");
-
-
-var sendPrompt = function(localPath, prompt) {
- return new Promise(function(resolve,reject) {
- var response;
- var socket = net.connect(localPath, function() {
- socket.on('data', function(data) { response = data; socket.end() });
- socket.on('end', function() {
- resolve(response);
- });
- socket.on('error',reject);
- socket.write(prompt+"\n", 'utf8');
- });
- socket.setEncoding('utf8');
- });
-}
-
-
-describe("localfilesystem/projects/git/authServer", function() {
- it("listens for user/pass prompts and returns provided auth", function(done) {
- authServer.ResponseServer({username: "TEST_USER", password: "TEST_PASS"}).then(function(rs) {
- sendPrompt(rs.path,"Username").then(function(response) {
- response.should.eql("TEST_USER");
- return sendPrompt(rs.path,"Password");
- }).then(function(response) {
- response.should.eql("TEST_PASS");
- }).then(() => {
- rs.close();
- done();
- }).catch(function(err) {
- rs.close();
- done(err);
- })
-
- })
- });
-
- it("listens for ssh prompts and returns provided auth", function(done) {
- authServer.ResponseSSHServer({passphrase: "TEST_PASSPHRASE"}).then(function(rs) {
- sendPrompt(rs.path,"The").then(function(response) {
- // TODO:
- response.should.eql("yes");
- return sendPrompt(rs.path,"Enter");
- }).then(function(response) {
- response.should.eql("TEST_PASSPHRASE");
- }).then(() => {
- rs.close();
- done();
- }).catch(function(err) {
- rs.close();
- done(err);
- })
-
- })
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter_spec.js
deleted file mode 100644
index c80cb8ad1..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter_spec.js
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var net = require("net");
-var path = require("path");
-var os = require("os");
-var should = require("should");
-var sinon = require("sinon");
-var child_process = require("child_process");
-var fs = require("fs-extra");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var authWriter = NR_TEST_UTILS.resolve("@node-red/runtime/lib/storage/localfilesystem/projects/git/authWriter");
-
-function getListenPath() {
- var seed = (0x100000+Math.random()*0x999999).toString(16);
- var fn = 'node-red-git-askpass-'+seed+'-sock';
- var listenPath;
- if (process.platform === 'win32') {
- listenPath = '\\\\.\\pipe\\'+fn;
- } else {
- listenPath = path.join(process.env['XDG_RUNTIME_DIR'] || os.tmpdir(), fn);
- }
- // console.log(listenPath);
- return listenPath;
-}
-
-
-describe("localfilesystem/projects/git/authWriter", function() {
- it("connects to port and sends passphrase", function(done) {
- var receivedData = "";
- var server = net.createServer(function(connection) {
- connection.setEncoding('utf8');
- connection.on('data', function(data) {
- receivedData += data;
- var m = data.indexOf("\n");
- if (m !== -1) {
- connection.end();
- }
- });
- });
-
- var listenPath = getListenPath();
-
- server.listen(listenPath, function(ready) {
- child_process.exec('"'+process.execPath+'" "'+authWriter+'" "'+listenPath+'" TEST_PHRASE_FOO',{cwd:__dirname}, (error,stdout,stderr) => {
- server.close();
- try {
- should.not.exist(error);
- receivedData.should.eql("TEST_PHRASE_FOO\n");
- done();
- } catch(err) {
- done(err);
- }
- });
- });
- server.on('close', function() {
- // console.log("Closing response server");
- fs.removeSync(listenPath);
- });
- server.on('error',function(err) {
- console.log("ResponseServer unexpectedError:",err.toString());
- server.close();
- done(err);
- });
-
-
- })
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/index_spec.js
deleted file mode 100644
index 773342fa6..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/git/index_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-describe("storage/localfilesystem/projects/git/index", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-})
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/index_spec.js
deleted file mode 100644
index f63a20522..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/index_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-describe("storage/localfilesystem/projects/index", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-})
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index_spec.js
deleted file mode 100644
index c6d0c533e..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/index_spec.js
+++ /dev/null
@@ -1,433 +0,0 @@
-/**
-* Copyright JS Foundation and other contributors, http://js.foundation
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-**/
-var should = require("should");
-var fs = require('fs-extra');
-var path = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var sshkeys = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/ssh");
-
-describe("storage/localfilesystem/projects/ssh", function() {
- var userDir = path.join(__dirname,".testSSHKeyUserHome");
- var mockSettings = {
- userDir: userDir
- };
- var mockRuntime = {
- log:{
- _:function() { return "placeholder message"},
- info: function() { },
- log: function() { },
- trace: function() { }
- }
- };
- var oldHOME;
-
- beforeEach(function(done) {
- oldHOME = process.env.HOME;
- process.env.HOME = "/tmp/doesnt/exist";
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- process.env.HOME = oldHOME;
- fs.remove(userDir,done);
- });
-
- it('should create sshkey directory when sshkey initializes', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- var ret = fs.existsSync(sshkeyDirPath);
- ret.should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey empty list if there is no sshkey file', function(done) {
- var username = 'test';
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(0);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey list', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filenameList = ['test-key01', 'test-key02'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not get sshkey file if there is only private key', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filenameList = ['test-key01', 'test-key02'];
- var onlyPrivateKeyFilenameList = ['test-key03', 'test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of onlyPrivateKeyFilenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var filename of onlyPrivateKeyFilenameList) {
- retObj.should.not.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not get sshkey file if there is only public key', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filenameList = ['test-key01', 'test-key02'];
- var directoryList = ['test-key03', '.test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of directoryList) {
- fs.ensureDirSync(path.join(sshkeyDirPath,filename));
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var directoryname of directoryList) {
- retObj.should.not.containEql({ name: directoryname });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey list that does not have directory', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var otherUsername = 'other';
- var filenameList = ['test-key01', 'test-key02'];
- var otherUserFilenameList = ['test-key03', 'test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of otherUserFilenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename+".pub"),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var filename of otherUserFilenameList) {
- retObj.should.not.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey list that have keys of specified user', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var otherUsername = 'other';
- var filenameList = ['test-key01', 'test-key02'];
- var otherUserFilenameList = ['test-key03', 'test-key04'];
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- for(var filename of filenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),"","utf8");
- }
- for(var filename of otherUserFilenameList) {
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,otherUsername+"_"+filename+".pub"),"","utf8");
- }
- sshkeys.listSSHKeys(username).then(function(retObj) {
- retObj.should.be.instanceOf(Array).and.have.lengthOf(filenameList.length);
- for(var filename of filenameList) {
- retObj.should.containEql({ name: filename });
- }
- for(var filename of otherUserFilenameList) {
- retObj.should.not.containEql({ name: filename });
- }
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with empty data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- name: 'test-key01'
- };
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with only comment data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01'
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with password data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- password: 'testtest'
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with size data', function(done) {
- this.timeout(20000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- size: 4096
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should generate sshkey file with password & size data', function(done) {
- this.timeout(20000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- password: 'testtest',
- size: 4096
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- retObj.should.be.equal(options.name);
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name)).should.be.true();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+options.name+'.pub')).should.be.true();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not generate sshkey file with illegal size data', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- size: 1023
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- done(new Error('Does NOT throw error!'));
- }).catch(function(err) {
- try {
- err.should.have.property('code', 'key_length_too_short');
- done();
- }
- catch (error) {
- done(error);
- }
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should not generate sshkey file with illegal password', function(done) {
- this.timeout(10000);
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var options = {
- comment: 'test@test.com',
- name: 'test-key01',
- password: 'aa'
- };
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- sshkeys.generateSSHKey(username, options).then(function(retObj) {
- done(new Error('Does NOT throw error!'));
- }).catch(function(err) {
- try {
- err.should.have.property('code', 'key_passphrase_too_short');
- done();
- }
- catch (error) {
- done(error);
- }
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should get sshkey file content', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filename = 'test-key01';
- var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),fileContent,"utf8");
- sshkeys.getSSHKey(username, filename).then(function(retObj) {
- retObj.should.be.equal(fileContent);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should delete sshkey files', function(done) {
- var sshkeyDirPath = path.join(userDir, 'projects', '.sshkeys');
- var username = 'test';
- var filename = 'test-key01';
- var fileContent = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD3a+sgtgzSbbliWxmOq5p6+H/mE+0gjWfLWrkIVmHENd1mifV4uCmIHAR2NfuadUYMQ3+bQ90kpmmEKTMYPsyentsKpHQZxTzG7wOCAIpJnbPTHDMxEJhVTaAwEjbVyMSIzTTPfnhoavWIBu0+uMgKDDlBm+RjlgkFlyhXyCN6UwFrIUUMH6Gw+eQHLiooKIl8ce7uDxIlt+9b7hFCU+sQ3kvuse239DZluu6+8buMWqJvrEHgzS9adRFKku8nSPAEPYn85vDi7OgVAcLQufknNgs47KHBAx9h04LeSrFJ/P5J1b//ItRpMOIme+O9d1BR46puzhvUaCHLdvO9czj+OmW+dIm+QIk6lZIOOMnppG72kZxtLfeKT16ur+2FbwAdL9ItBp4BI/YTlBPoa5mLMxpuWfmX1qHntvtGc9wEwS1P7YFfmF3XiK5apxalzrn0Qlr5UmDNbVIqJb1OlbC0w03Z0oktti1xT+R2DGOLWM4lBbpXDHV1BhQ7oYOvbUD8Cnof55lTP0WHHsOHlQc/BGDti1XA9aBX/OzVyzBUYEf0pkimsD0RYo6aqt7QwehJYdlz9x1NBguBffT0s4NhNb9IWr+ASnFPvNl2sw4XH/8U0J0q8ZkMpKkbLM1Zdp1Fv00GF0f5UNRokai6uM3w/ccantJ3WvZ6GtctqytWrw== \n";
-
- sshkeys.init(mockSettings, mockRuntime).then(function() {
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename),"","utf8");
- fs.writeFileSync(path.join(sshkeyDirPath,username+"_"+filename+".pub"),fileContent,"utf8");
- sshkeys.deleteSSHKey(username, filename).then(function() {
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+filename)).should.be.false();
- fs.existsSync(path.join(sshkeyDirPath,username+'_'+filename+'.pub')).should.be.false();
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen_spec.js
deleted file mode 100644
index f3487277b..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen_spec.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var sinon = require("sinon");
-var child_process = require('child_process');
-var EventEmitter = require("events");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var keygen = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/projects/ssh/keygen")
-
-describe("localfilesystem/projects/ssh/keygen", function() {
-
- afterEach(function() {
- if (child_process.spawn.restore) {
- child_process.spawn.restore();
- }
- })
-
- it("invokes sshkeygen", function(done) {
- var command;
- var args;
- var opts;
- sinon.stub(child_process,"spawn").callsFake(function(_command,_args,_opts) {
- _command = command;
- _args = args;
- _opts = opts;
-
- var e = new EventEmitter();
- e.stdout = new EventEmitter();
- e.stderr = new EventEmitter();
- setTimeout(function() {
- e.stdout.emit("data","result");
- e.emit("close",0);
- },50)
- return e;
- });
-
- keygen.generateKey({
- size: 1024,
- location: 'location',
- comment: 'comment',
- password: 'password'
- }).then(function(output) {
- output.should.equal("result");
- done();
- }).catch(function(err) {
- done(err);
- })
- })
-
- it("reports passphrase too short", function(done) {
- var command;
- var args;
- var opts;
-
- try {
- keygen.generateKey({
- size: 1024,
- location: 'location',
- comment: 'comment',
- password: '123'
- }).then(function(output) {
- done(new Error("Error not thrown"));
- }).catch(function(err) {
- done(new Error("Error not thrown"));
- })
- } catch(err) {
- err.should.have.property("code","key_passphrase_too_short");
- done();
- }
- });
-
- it("reports key length too short", function(done) {
- var command;
- var args;
- var opts;
- try {
- keygen.generateKey({
- size: 123,
- location: 'location',
- comment: 'comment',
- password: 'password'
- }).then(function(output) {
- done(new Error("Error not thrown"));
- }).catch(function(err) {
- done(new Error("Error not thrown"));
- })
- } catch(err) {
- err.should.have.property("code","key_length_too_short");
- done();
-
- }
- });
-
-
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/sessions_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/sessions_spec.js
deleted file mode 100644
index 685886d67..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/sessions_spec.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var fs = require('fs-extra');
-var path = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-var localfilesystemSessions = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/sessions");
-
-describe('storage/localfilesystem/sessions', function() {
- var userDir = path.join(__dirname,".testUserHome");
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
- it('should handle non-existent sessions', function(done) {
- var sessionsFile = path.join(userDir,".sessions.json");
-
- localfilesystemSessions.init({userDir:userDir});
- fs.existsSync(sessionsFile).should.be.false();
- localfilesystemSessions.getSessions().then(function(sessions) {
- sessions.should.eql({});
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle corrupt sessions', function(done) {
- var sessionsFile = path.join(userDir,".sessions.json");
- fs.writeFileSync(sessionsFile,"[This is not json","utf8");
- localfilesystemSessions.init({userDir:userDir});
- fs.existsSync(sessionsFile).should.be.true();
- localfilesystemSessions.getSessions().then(function(sessions) {
- sessions.should.eql({});
- done();
- }).catch(function(err) {
- done(err);
- });
- });
-
- it('should handle sessions', function(done) {
- var sessionsFile = path.join(userDir,".sessions.json");
-
- localfilesystemSessions.init({userDir:userDir});
- fs.existsSync(sessionsFile).should.be.false();
-
- var sessions = {"abc":{"type":"creds"}};
-
- localfilesystemSessions.saveSessions(sessions).then(function() {
- fs.existsSync(sessionsFile).should.be.true();
- localfilesystemSessions.getSessions().then(function(_sessions) {
- _sessions.should.eql(sessions);
- done();
- }).catch(function(err) {
- done(err);
- });
- }).catch(function(err) {
- done(err);
- });
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/settings_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/settings_spec.js
deleted file mode 100644
index bd07ca27f..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/settings_spec.js
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-const should = require("should");
-const fs = require('fs-extra');
-const path = require('path');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var localfilesystemSettings = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/settings");
-
-describe('storage/localfilesystem/settings', function() {
- var userDir = path.join(__dirname,".testUserHome");
- beforeEach(function(done) {
- fs.remove(userDir,function(err) {
- fs.mkdir(userDir,done);
- });
- });
- afterEach(function(done) {
- fs.remove(userDir,done);
- });
-
- it('should handle non-existent settings', function(done) {
- var settingsFile = path.join(userDir,".config.json");
- localfilesystemSettings.init({userDir:userDir}).then(function() {
- fs.existsSync(settingsFile).should.be.false();
- return localfilesystemSettings.getSettings();
- }).then(function(settings) {
- settings.should.eql({});
- done();
- }).catch(err => { done(err)});
- });
-
- it('should migrate single config.json to multiple files', function(done) {
- var settingsFile = path.join(userDir,".config.json");
- fs.writeFileSync(settingsFile,JSON.stringify({
- nodes:{a:1},
- _credentialSecret: "foo",
- users:{b:2},
- projects: {c:3}
- }),"utf8");
-
- async function checkFile(sectionName, expectedContents) {
- const file = path.join(userDir,".config."+sectionName+".json");
- fs.existsSync(file).should.be.true();
- var contents = await fs.readFile(file,'utf8');
- var data = JSON.parse(contents);
- data.should.eql(expectedContents)
- }
-
- localfilesystemSettings.init({userDir:userDir}).then(async function() {
- // (For now) leave the old settings file in place
- fs.existsSync(settingsFile).should.be.true();
- await checkFile("nodes",{a:1})
- await checkFile("users",{b:2})
- await checkFile("projects",{c:3})
- await checkFile("runtime",{_credentialSecret:"foo"})
- done();
- }).catch(err => { done(err)});
- });
-
- it('should load separate settings file', async function() {
- await fs.writeFile( path.join(userDir,".config.nodes.json"),JSON.stringify({a:1}),"utf8");
- await fs.writeFile( path.join(userDir,".config.users.json"),JSON.stringify({b:2}),"utf8");
- await fs.writeFile( path.join(userDir,".config.projects.json"),JSON.stringify({c:3}),"utf8");
- await fs.writeFile( path.join(userDir,".config.runtime.json"),JSON.stringify({_credentialSecret:"foo"}),"utf8");
-
- return localfilesystemSettings.init({userDir:userDir})
- .then(localfilesystemSettings.getSettings)
- .then(settings => {
- settings.should.eql({
- nodes:{a:1},
- _credentialSecret: "foo",
- users:{b:2},
- projects: {c:3}
- })
- })
- });
-
- it('should write only the files that need writing', async function() {
- await fs.writeFile( path.join(userDir,".config.nodes.json"),JSON.stringify({a:1}),"utf8");
- await fs.writeFile( path.join(userDir,".config.users.json"),JSON.stringify({b:2}),"utf8");
- await fs.writeFile( path.join(userDir,".config.projects.json"),JSON.stringify({c:3}),"utf8");
- await fs.writeFile( path.join(userDir,".config.runtime.json"),JSON.stringify({_credentialSecret:"foo"}),"utf8");
-
- const fsStatNodes = await fs.stat(path.join(userDir,".config.nodes.json"))
- const fsStatUsers = await fs.stat(path.join(userDir,".config.users.json"))
- const fsStatProjects = await fs.stat(path.join(userDir,".config.projects.json"))
- const fsStatRuntime = await fs.stat(path.join(userDir,".config.runtime.json"))
-
- return localfilesystemSettings.init({userDir:userDir}).then(function() {
- return new Promise(res => {
- setTimeout(function() {
- res();
- },10)
- });
- }).then(() => {
- return localfilesystemSettings.saveSettings({
- nodes:{d:4},
- _credentialSecret: "bar",
- users:{b:2},
- projects: {c:3}
- })
- }).then(async function() {
-
- const newFsStatNodes = await fs.stat(path.join(userDir,".config.nodes.json"))
- const newFsStatUsers = await fs.stat(path.join(userDir,".config.users.json"))
- const newFsStatProjects = await fs.stat(path.join(userDir,".config.projects.json"))
- const newFsStatRuntime = await fs.stat(path.join(userDir,".config.runtime.json"))
-
- // Not changed
- newFsStatUsers.mtimeMs.should.eql(fsStatUsers.mtimeMs);
- newFsStatProjects.mtimeMs.should.eql(fsStatProjects.mtimeMs);
-
- // Changed
- newFsStatNodes.mtimeMs.should.not.eql(fsStatNodes.mtimeMs);
- newFsStatRuntime.mtimeMs.should.not.eql(fsStatRuntime.mtimeMs);
-
- })
- });
-});
diff --git a/test/unit/@node-red/runtime/lib/storage/localfilesystem/util_spec.js b/test/unit/@node-red/runtime/lib/storage/localfilesystem/util_spec.js
deleted file mode 100644
index fa1e4bdb7..000000000
--- a/test/unit/@node-red/runtime/lib/storage/localfilesystem/util_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var should = require("should");
-var NR_TEST_UTILS = require("nr-test-utils");
-var util = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/util");
-
-describe('storage/localfilesystem/util', function() {
- describe('parseJSON', function() {
- it('returns parsed JSON', function() {
- var result = util.parseJSON('{"a":123}');
- result.should.eql({a:123});
- })
- it('ignores BOM character', function() {
- var result = util.parseJSON('\uFEFF{"a":123}');
- result.should.eql({a:123});
- })
- })
-});
diff --git a/test/unit/@node-red/util/index_spec.js b/test/unit/@node-red/util/index_spec.js
deleted file mode 100644
index ee46fc504..000000000
--- a/test/unit/@node-red/util/index_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-describe("node-red/red", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-});
diff --git a/test/unit/@node-red/util/lib/events_spec.js b/test/unit/@node-red/util/lib/events_spec.js
deleted file mode 100644
index 09f5d2ae0..000000000
--- a/test/unit/@node-red/util/lib/events_spec.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-describe("@node-red/util/events", function() {
- it('can be required without errors', function() {
- NR_TEST_UTILS.require("@node-red/util/lib/events");
- });
- it.skip('more tests needed', function(){})
-});
diff --git a/test/unit/@node-red/util/lib/exec_spec.js b/test/unit/@node-red/util/lib/exec_spec.js
deleted file mode 100644
index 9b02fb3f1..000000000
--- a/test/unit/@node-red/util/lib/exec_spec.js
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-var sinon = require("sinon");
-var path = require("path");
-var EventEmitter = require("events").EventEmitter;
-
-
-var child_process = require('child_process');
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var events = NR_TEST_UTILS.require("@node-red/util/lib/events");
-var exec = NR_TEST_UTILS.require("@node-red/util/lib/exec");
-
-describe("runtime/exec", function() {
- var logEvents;
- var mockProcess;
- const eventLogHandler = function(ev) {
- logEvents.push(ev);
- }
-
- beforeEach(function() {
-
- logEvents = [];
- events.on("event-log", eventLogHandler);
-
- mockProcess = new EventEmitter();
- mockProcess.stdout = new EventEmitter();
- mockProcess.stderr = new EventEmitter();
- sinon.stub(child_process,'spawn').callsFake(function(command,args,options) {
- mockProcess._args = {command,args,options};
- return mockProcess;
- });
- });
-
- afterEach(function() {
- events.removeListener("event-log", eventLogHandler);
- if (child_process.spawn.restore) {
- child_process.spawn.restore();
- }
- });
-
- it("runs command and resolves on success - no emit", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts).then(function(result) {
- command.should.eql(mockProcess._args.command);
- args.should.eql(mockProcess._args.args);
- opts.should.eql(mockProcess._args.options);
- logEvents.length.should.eql(0);
- result.code.should.eql(0);
- result.stdout.should.eql("123");
- result.stderr.should.eql("abc");
- done();
- }).catch(done);
-
- mockProcess.stdout.emit('data',"1");
- mockProcess.stderr.emit('data',"a");
- mockProcess.stderr.emit('data',"b");
- mockProcess.stdout.emit('data',"2");
- mockProcess.stdout.emit('data',"3");
- mockProcess.stderr.emit('data',"c");
- mockProcess.emit('close',0);
- });
-
- it("runs command and resolves on success - emit", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts,true).then(function(result) {
- logEvents.length.should.eql(8);
- done();
- }).catch(done);
-
- mockProcess.stdout.emit('data',"1");
- mockProcess.stderr.emit('data',"a");
- mockProcess.stderr.emit('data',"b");
- mockProcess.stdout.emit('data',"2");
- mockProcess.stdout.emit('data',"3");
- mockProcess.stderr.emit('data',"c");
- mockProcess.emit('close',0);
- })
-
- it("runs command and rejects on error - close", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts).then(function() {
- done("Command should have rejected");
- }).catch(function(result) {
- result
- result.code.should.eql(123);
- result.stdout.should.eql("123");
- result.stderr.should.eql("abc");
- done();
- }).catch(done);
-
- mockProcess.stdout.emit('data',"1");
- mockProcess.stderr.emit('data',"a");
- mockProcess.stderr.emit('data',"b");
- mockProcess.stdout.emit('data',"2");
- mockProcess.stdout.emit('data',"3");
- mockProcess.stderr.emit('data',"c");
- mockProcess.emit('close',123);
- })
-
- it("runs command and rejects on error - error", function(done) {
- var command = "cmd";
- var args = [1,2,3];
- var opts = { a: true };
- exec.run(command,args,opts).then(function() {
- done("Command should have rejected");
- }).catch(function(result) {
- result
- result.code.should.eql(456);
- result.stdout.should.eql("");
- result.stderr.should.eql("test-error");
- done();
- }).catch(done);
-
- mockProcess.emit('error',"test-error");
- mockProcess.emit('close',456);
- })
-
-});
diff --git a/test/unit/@node-red/util/lib/hooks_spec.js b/test/unit/@node-red/util/lib/hooks_spec.js
deleted file mode 100644
index 4b25f33d2..000000000
--- a/test/unit/@node-red/util/lib/hooks_spec.js
+++ /dev/null
@@ -1,338 +0,0 @@
-const should = require("should");
-const NR_TEST_UTILS = require("nr-test-utils");
-
-const hooks = NR_TEST_UTILS.require("@node-red/util/lib/hooks");
-
-describe("util/hooks", function() {
- afterEach(function() {
- hooks.clear();
- })
- it("allows a hook to be registered", function(done) {
- let calledWith = null;
- hooks.has("onSend").should.be.false();
- hooks.add("onSend", function(payload) { calledWith = payload } )
- hooks.has("onSend").should.be.true();
- let data = { a: 1 };
- hooks.trigger("onSend",data,err => {
- calledWith.should.equal(data);
- done(err);
- })
- })
- it("rejects invalid hook id", function(done) {
- try {
- hooks.add("foo", function(payload) {})
- done(new Error("Invalid hook accepted"))
- } catch(err) {
- done();
- }
- })
- it("calls hooks in the order they were registered", function(done) {
- hooks.add("onSend", function(payload) { payload.order.push("A") } )
- hooks.add("onSend", function(payload) { payload.order.push("B") } )
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- done(err);
- })
- })
-
- it("does not allow multiple hooks with same id.label", function() {
- hooks.has("onSend.one").should.be.false();
- hooks.has("onSend").should.be.false();
- hooks.add("onSend.one", function(payload) { payload.order.push("A") } );
- hooks.has("onSend.one").should.be.true();
- hooks.has("onSend").should.be.true();
- (function() {
- hooks.add("onSend.one", function(payload) { payload.order.push("B") } )
- }).should.throw();
- })
-
- it("removes labelled hook", function(done) {
- hooks.has("onSend.A").should.be.false();
- hooks.has("onSend.B").should.be.false();
- hooks.has("onSend").should.be.false();
-
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
-
- hooks.has("onSend.A").should.be.true();
- hooks.has("onSend.B").should.be.false();
- hooks.has("onSend").should.be.true();
-
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- hooks.has("onSend.A").should.be.true();
- hooks.has("onSend.B").should.be.true();
- hooks.has("onSend").should.be.true();
-
- hooks.remove("onSend.A");
-
- hooks.has("onSend.A").should.be.false();
- hooks.has("onSend.B").should.be.true();
- hooks.has("onSend").should.be.true();
-
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- try {
- data.order.should.eql(["B"])
-
- hooks.remove("onSend.B");
-
- hooks.has("onSend.A").should.be.false();
- hooks.has("onSend.B").should.be.false();
- hooks.has("onSend").should.be.false();
-
- done(err);
- } catch(err2) {
- done(err2);
- }
- })
- })
-
- it("cannot remove unlabelled hook", function() {
- hooks.add("onSend", function(payload) { payload.order.push("A") } );
- (function() {
- hooks.remove("onSend")
- }).should.throw();
- })
- it("removes all hooks with same label", function(done) {
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
- hooks.add("preRoute.A", function(payload) { payload.order.push("C") } )
- hooks.add("preRoute.B", function(payload) { payload.order.push("D") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- hooks.trigger("preRoute", data, err => {
- data.order.should.eql(["A","B","C","D"])
-
- data.order = [];
-
- hooks.remove("*.A");
-
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["B"])
- hooks.trigger("preRoute", data, err => {
- data.order.should.eql(["B","D"])
- })
- done(err);
- })
- })
- })
- })
- it("allows a hook to remove itself whilst being called", function(done) {
- let data = { order: [] }
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
- hooks.add("onSend.B", function(payload) {
- hooks.remove("*.B");
- })
- hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
- hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
-
- hooks.trigger("onSend", data, err => {
- try {
- should.not.exist(err);
- data.order.should.eql(["A","C","D"])
- done();
- } catch(e) {
- done(e);
- }
- })
- });
-
- it("allows a hook to remove itself and others whilst being called", function(done) {
- let data = { order: [] }
- hooks.add("onSend.A", function(payload) { payload.order.push("A") } )
- hooks.add("onSend.B", function(payload) {
- hooks.remove("*.B");
- hooks.remove("*.C");
- })
- hooks.add("onSend.C", function(payload) { payload.order.push("C") } )
- hooks.add("onSend.D", function(payload) { payload.order.push("D") } )
-
- hooks.trigger("onSend", data, err => {
- try {
- should.not.exist(err);
- data.order.should.eql(["A","D"])
- done();
- } catch(e) {
- done(e);
- }
- })
- });
-
- it("halts execution on return false", function(done) {
- hooks.add("onSend.A", function(payload) { payload.order.push("A"); return false } )
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- err.should.be.false();
- done();
- })
- })
- it("halts execution on thrown error", function(done) {
- hooks.add("onSend.A", function(payload) { payload.order.push("A"); throw new Error("error") } )
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- should.exist(err);
- err.should.not.be.false()
- done();
- })
- })
-
- it("handler can use callback function", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done()
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- done(err);
- })
- })
-
- it("handler can use callback function - halt execution", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done(false)
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- err.should.be.false()
- done();
- })
- })
- it("handler can use callback function - halt on error", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- done(new Error("test error"))
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql([])
- should.exist(err);
- err.should.not.be.false()
- done();
- })
- })
-
- it("handler be an async function", function(done) {
- hooks.add("onSend.A", async function(payload) {
- return new Promise(resolve => {
- setTimeout(function() {
- payload.order.push("A")
- resolve()
- },30)
- });
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A","B"])
- done(err);
- })
- })
-
- it("handler be an async function - halt execution", function(done) {
- hooks.add("onSend.A", async function(payload) {
- return new Promise(resolve => {
- setTimeout(function() {
- payload.order.push("A")
- resolve(false)
- },30)
- });
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql(["A"])
- done(err);
- })
- })
- it("handler be an async function - halt on error", function(done) {
- hooks.add("onSend.A", async function(payload) {
- return new Promise((resolve,reject) => {
- setTimeout(function() {
- reject(new Error("test error"))
- },30)
- });
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data,err => {
- data.order.should.eql([])
- should.exist(err);
- err.should.not.be.false()
- done();
- })
- })
-
-
- it("handler can use callback function - promise API", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done()
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data).then(() => {
- data.order.should.eql(["A","B"])
- done()
- }).catch(done)
- })
-
- it("handler can halt execution - promise API", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- setTimeout(function() {
- payload.order.push("A")
- done(false)
- },30)
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data).then(() => {
- data.order.should.eql(["A"])
- done()
- }).catch(done)
- })
-
- it("handler can halt execution on error - promise API", function(done) {
- hooks.add("onSend.A", function(payload, done) {
- throw new Error("error");
- })
- hooks.add("onSend.B", function(payload) { payload.order.push("B") } )
-
- let data = { order:[] };
- hooks.trigger("onSend",data).then(() => {
- done("hooks.trigger resolved unexpectedly")
- }).catch(err => {
- done();
- })
- })
-});
diff --git a/test/unit/@node-red/util/lib/i18n_spec.js b/test/unit/@node-red/util/lib/i18n_spec.js
deleted file mode 100644
index 5deaba032..000000000
--- a/test/unit/@node-red/util/lib/i18n_spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-
-
- var NR_TEST_UTILS = require("nr-test-utils");
-
- var i18n = NR_TEST_UTILS.require("@node-red/util").i18n;
-
-
-describe("@node-red/util/i18n", function() {
- it.skip('more tests needed', function(){})
-});
diff --git a/test/unit/@node-red/util/lib/index_spec.js b/test/unit/@node-red/util/lib/index_spec.js
deleted file mode 100644
index 3cf2347c1..000000000
--- a/test/unit/@node-red/util/lib/index_spec.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-describe("@node-red/util", function() {
- it.skip('more tests needed', function(){})
-});
diff --git a/test/unit/@node-red/util/lib/log_spec.js b/test/unit/@node-red/util/lib/log_spec.js
deleted file mode 100644
index 056f37672..000000000
--- a/test/unit/@node-red/util/lib/log_spec.js
+++ /dev/null
@@ -1,252 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-var sinon = require("sinon");
-var util = require("util");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var log = NR_TEST_UTILS.require("@node-red/util").log;
-
-
-describe("@node-red/util/log", function() {
- beforeEach(function () {
- var spy = sinon.stub(util, 'log').callsFake(function(arg){});
- var settings = {logging: { console: { level: 'metric', metrics: true } } };
- log.init(settings);
- });
-
- afterEach(function() {
- util.log.restore();
- });
-
- it('it can raise an error', function() {
- var ret = log.error("This is an error");
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- });
-
- it('it can raise a trace', function() {
- var ret = log.trace("This is a trace");
- sinon.assert.calledWithMatch(util.log,"[trace] This is a trace");
- });
-
- it('it can raise a debug', function() {
- var ret = log.debug("This is a debug");
- sinon.assert.calledWithMatch(util.log,"[debug] This is a debug");
- });
-
- it('it can raise a info', function() {
- var ret = log.info("This is an info");
- sinon.assert.calledWithMatch(util.log,"[info] This is an info");
- });
-
- it('it can raise a warn', function() {
- var ret = log.warn("This is a warn");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- });
-
- it('it can raise a metric', function() {
- var metrics = {};
- metrics.level = log.METRIC;
- metrics.nodeid = "testid";
- metrics.event = "node.test.testevent";
- metrics.msgid = "12345";
- metrics.value = "the metric payload";
- var ret = log.log(metrics);
- util.log.calledOnce.should.be.true();
- util.log.firstCall.args[0].indexOf("[metric] ").should.equal(0);
- var body = JSON.parse(util.log.firstCall.args[0].substring(9));
- body.should.have.a.property("nodeid","testid");
- body.should.have.a.property("event","node.test.testevent");
- body.should.have.a.property("msgid","12345");
- body.should.have.a.property("value","the metric payload");
- body.should.have.a.property("timestamp");
- body.should.have.a.property("level",log.METRIC);
- });
-
- it('it checks metrics are enabled', function() {
- log.metric().should.equal(true);
- var sett = {logging: { console: { level: 'info', metrics: false } } };
- log.init(sett);
- log.metric().should.equal(false);
- });
-
- it('it logs node type and name if provided',function() {
- log.log({level:log.INFO,type:"nodeType",msg:"test",name:"nodeName",id:"nodeId"});
- util.log.calledOnce.should.be.true();
- util.log.firstCall.args[0].indexOf("[nodeType:nodeName]").should.not.equal(-1);
- });
- it('it logs node type and id if no name provided',function() {
- log.log({level:log.INFO,type:"nodeType",msg:"test",id:"nodeId"});
- util.log.calledOnce.should.be.true();
- util.log.firstCall.args[0].indexOf("[nodeType:nodeId]").should.not.equal(-1);
- });
-
- it('ignores lower level messages and metrics', function() {
- var settings = {logging: { console: { level: 'warn', metrics: false } } };
- log.init(settings);
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
- });
- it('ignores lower level messages but accepts metrics', function() {
- var settings = {logging: { console: { level: 'log', metrics: true } } };
- log.init(settings);
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.calledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.calledWithMatch(util.log,"[metric] ");
- });
-
- it('default settings set to INFO and metrics off', function() {
- log.init({logging:{}});
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.calledWithMatch(util.log,"[error] This is an error");
- sinon.assert.calledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.calledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
- });
- it('no logger used if custom logger handler does not exist', function() {
- var settings = {logging: { customLogger: { level: 'trace', metrics: true } } };
- log.init(settings);
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
- sinon.assert.neverCalledWithMatch(util.log,"[error] This is an error");
- sinon.assert.neverCalledWithMatch(util.log,"[warn] This is a warn");
- sinon.assert.neverCalledWithMatch(util.log,"[info] This is an info");
- sinon.assert.neverCalledWithMatch(util.log,"[debug] This is a debug");
- sinon.assert.neverCalledWithMatch(util.log,"[trace] This is a trace");
- sinon.assert.neverCalledWithMatch(util.log,"[metric] ");
- });
-
- it('add a custom log handler directly', function() {
- var settings = {};
- log.init(settings);
-
- var logEvents = [];
- var loggerOne = {
- emit: function(event,msg) {
- logEvents.push({logger:1,msg:msg});
- }
- };
- var loggerTwo = {
- emit: function(event,msg) {
- logEvents.push({logger:2,msg:msg});
- }
- };
- log.addHandler(loggerOne);
- log.addHandler(loggerTwo);
-
- log.error("This is an error");
- log.warn("This is a warn");
- log.info("This is an info");
- log.debug("This is a debug");
- log.trace("This is a trace");
- log.log({level:log.METRIC,msg:"testMetric"});
-
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(6);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(6);
- });
-
- it('remove a custom log handler directly', function() {
- var settings = {};
- log.init(settings);
-
- var logEvents = [];
- var loggerOne = {
- emit: function(event,msg) {
- logEvents.push({logger:1,msg:msg});
- }
- };
- var loggerTwo = {
- emit: function(event,msg) {
- logEvents.push({logger:2,msg:msg});
- }
- };
- log.addHandler(loggerOne);
- log.addHandler(loggerTwo);
-
- log.info("This is an info");
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(1);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(1);
-
-
- log.removeHandler(loggerTwo);
- log.info("This is an info");
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(2);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(1);
-
- log.removeHandler(loggerOne);
- log.info("This is an info");
- logEvents.filter(function(evt) { return evt.logger === 1}).should.have.lengthOf(2);
- logEvents.filter(function(evt) { return evt.logger === 2}).should.have.lengthOf(1);
-
-
- });
- it('it can log without exception', function() {
- var msg = {
- msg: {
- mystrangeobj:"hello",
- },
- };
- msg.msg.toString = function(){
- throw new Error('Exception in toString - should have been caught');
- }
- msg.msg.constructor = { name: "strangeobj" };
- var ret = log.info(msg.msg);
- });
- it('it can log an object but use .message', function() {
- var msg = {
- msg: {
- message: "my special message",
- mystrangeobj:"hello",
- },
- };
- var ret = log.info(msg.msg);
- sinon.assert.calledWithMatch(util.log,"my special message");
- });
-
-
-
-});
diff --git a/test/unit/@node-red/util/lib/util_spec.js b/test/unit/@node-red/util/lib/util_spec.js
deleted file mode 100644
index 5007fe5c5..000000000
--- a/test/unit/@node-red/util/lib/util_spec.js
+++ /dev/null
@@ -1,1092 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var util = NR_TEST_UTILS.require("@node-red/util").util;
-
-describe("@node-red/util/util", function() {
- describe('generateId', function() {
- it('generates an id', function() {
- var id = util.generateId();
- var id2 = util.generateId();
- id.should.not.eql(id2);
- });
- });
- describe('compareObjects', function() {
- it('numbers', function() {
- util.compareObjects(0,0).should.equal(true);
- util.compareObjects(0,1).should.equal(false);
- util.compareObjects(1000,1001).should.equal(false);
- util.compareObjects(1000,1000).should.equal(true);
- util.compareObjects(0,"0").should.equal(false);
- util.compareObjects(1,"1").should.equal(false);
- util.compareObjects(0,null).should.equal(false);
- util.compareObjects(0,undefined).should.equal(false);
- });
- it('strings', function() {
- util.compareObjects("","").should.equal(true);
- util.compareObjects("a","a").should.equal(true);
- util.compareObjects("",null).should.equal(false);
- util.compareObjects("",undefined).should.equal(false);
- });
-
- it('arrays', function() {
- util.compareObjects(["a"],["a"]).should.equal(true);
- util.compareObjects(["a"],["a","b"]).should.equal(false);
- util.compareObjects(["a","b"],["b"]).should.equal(false);
- util.compareObjects(["a"],"a").should.equal(false);
- util.compareObjects([[1],["a"]],[[1],["a"]]).should.equal(true);
- util.compareObjects([[1],["a"]],[["a"],[1]]).should.equal(false);
- });
- it('objects', function() {
- util.compareObjects({"a":1},{"a":1,"b":1}).should.equal(false);
- util.compareObjects({"a":1,"b":1},{"a":1,"b":1}).should.equal(true);
- util.compareObjects({"b":1,"a":1},{"a":1,"b":1}).should.equal(true);
- });
- it('Buffer', function() {
- util.compareObjects(Buffer.from("hello"),Buffer.from("hello")).should.equal(true);
- util.compareObjects(Buffer.from("hello"),Buffer.from("hello ")).should.equal(false);
- util.compareObjects(Buffer.from("hello"),"hello").should.equal(false);
- });
-
- });
-
- describe('ensureString', function() {
- it('strings are preserved', function() {
- util.ensureString('string').should.equal('string');
- });
- it('Buffer is converted', function() {
- var s = util.ensureString(Buffer.from('foo'));
- s.should.equal('foo');
- (typeof s).should.equal('string');
- });
- it('Object is converted to JSON', function() {
- var s = util.ensureString({foo: "bar"});
- (typeof s).should.equal('string');
- should.deepEqual(JSON.parse(s), {foo:"bar"});
- });
- it('stringifies other things', function() {
- var s = util.ensureString(123);
- (typeof s).should.equal('string');
- s.should.equal('123');
- });
- });
-
- describe('ensureBuffer', function() {
- it('Buffers are preserved', function() {
- var b = Buffer.from('');
- util.ensureBuffer(b).should.equal(b);
- });
- it('string is converted', function() {
- var b = util.ensureBuffer('foo');
- var expected = Buffer.from('foo');
- for (var i = 0; i < expected.length; i++) {
- b[i].should.equal(expected[i]);
- }
- Buffer.isBuffer(b).should.equal(true);
- });
- it('Object is converted to JSON', function() {
- var obj = {foo: "bar"}
- var b = util.ensureBuffer(obj);
- Buffer.isBuffer(b).should.equal(true);
- should.deepEqual(JSON.parse(b), obj);
- });
- it('stringifies other things', function() {
- var b = util.ensureBuffer(123);
- Buffer.isBuffer(b).should.equal(true);
- var expected = Buffer.from('123');
- for (var i = 0; i < expected.length; i++) {
- b[i].should.equal(expected[i]);
- }
- });
- });
-
- describe('cloneMessage', function() {
- it('clones a simple message', function() {
- var msg = {string:"hi",array:[1,2,3],object:{a:1,subobject:{b:2}}};
-
- var cloned = util.cloneMessage(msg);
-
- cloned.should.eql(msg);
-
- cloned.should.not.equal(msg);
- cloned.array.should.not.equal(msg.string);
- cloned.object.should.not.equal(msg.object);
- cloned.object.subobject.should.not.equal(msg.object.subobject);
-
- cloned.should.not.have.property("req");
- cloned.should.not.have.property("res");
- });
- it('does not clone http req/res properties', function() {
- var msg = {req:{a:1},res:{b:2}};
-
- var cloned = util.cloneMessage(msg);
-
- cloned.should.eql(msg);
- cloned.should.not.equal(msg);
-
- cloned.req.should.equal(msg.req);
- cloned.res.should.equal(msg.res);
- });
- it('handles undefined values without throwing an error', function() {
- var result = util.cloneMessage(undefined);
- should.not.exist(result);
- })
- });
- describe('getObjectProperty', function() {
- it('gets a property beginning with "msg."', function() {
- // getMessageProperty strips off `msg.` prefixes.
- // getObjectProperty does not
- var obj = { msg: { a: "foo"}, a: "bar"};
- var v = util.getObjectProperty(obj,"msg.a");
- v.should.eql("foo");
- })
- });
- describe('getMessageProperty', function() {
- it('retrieves a simple property', function() {
- var v = util.getMessageProperty({a:"foo"},"msg.a");
- v.should.eql("foo");
- var v2 = util.getMessageProperty({a:"foo"},"a");
- v2.should.eql("foo");
- });
- it('retrieves a nested property', function() {
- var v = util.getMessageProperty({a:"foo",b:{foo:1,bar:2}},"msg.b[msg.a]");
- v.should.eql(1);
- var v2 = util.getMessageProperty({a:"bar",b:{foo:1,bar:2}},"b[msg.a]");
- v2.should.eql(2);
- });
-
- it('should return undefined if property does not exist', function() {
- var v = util.getMessageProperty({a:"foo"},"msg.b");
- should.not.exist(v);
- });
- it('should throw error if property parent does not exist', function() {
- /*jshint immed: false */
- (function() {
- util.getMessageProperty({a:"foo"},"msg.a.b.c");
- }).should.throw();
- });
- it('retrieves a property with array syntax', function() {
- var v = util.getMessageProperty({a:["foo","bar"]},"msg.a[0]");
- v.should.eql("foo");
- var v2 = util.getMessageProperty({a:[null,{b:"foo"}]},"a[1].b");
- v2.should.eql("foo");
- var v3 = util.getMessageProperty({a:[[["foo"]]]},"a[0][0][0]");
- v3.should.eql("foo");
- });
-
- });
- describe('setObjectProperty', function() {
- it('set a property beginning with "msg."', function() {
- // setMessageProperty strips off `msg.` prefixes.
- // setObjectProperty does not
- var obj = {};
- var result = util.setObjectProperty(obj,"msg.a","bar");
- result.should.be.true();
- obj.should.have.property("msg");
- obj.msg.should.have.property("a","bar");
- })
- });
- describe('setMessageProperty', function() {
- it('sets a property', function() {
- var msg = {a:"foo"};
- var result = util.setMessageProperty(msg,"msg.a","bar");
- result.should.be.true();
- msg.a.should.eql('bar');
- });
- it('sets a deep level property', function() {
- var msg = {a:{b:{c:"foo"}}};
- var result = util.setMessageProperty(msg,"msg.a.b.c","bar");
- result.should.be.true();
- msg.a.b.c.should.eql('bar');
- });
- it('creates missing parent properties by default', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b.c","bar");
- result.should.be.true();
- msg.a.b.c.should.eql('bar');
- })
- it('does not create missing parent properties', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b.c","bar",false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not create missing parent properties of array', function () {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg, "msg.a.b[1].c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
- it('does not create missing parent properties of string', function() {
- var msg = {a:"foo"};
- var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not set property of existing string property', function() {
- var msg = {a:"foo"};
- var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
- it('does not set property of existing number property', function() {
- var msg = {a:123};
- var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not create missing parent properties of number', function() {
- var msg = {a:123};
- var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
- it('does not set property of existing boolean property', function() {
- var msg = {a:true};
- var result = util.setMessageProperty(msg, "msg.a.b", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
- it('does not create missing parent properties of boolean', function() {
- var msg = {a:true};
- var result = util.setMessageProperty(msg, "msg.a.b.c", "bar", false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- })
-
-
- it('deletes property if value is undefined', function() {
- var msg = {a:{b:{c:"foo"}}};
- var result = util.setMessageProperty(msg,"msg.a.b.c",undefined);
- result.should.be.true();
- should.not.exist(msg.a.b.c);
- })
- it('does not create missing parent properties if value is undefined', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b.c",undefined);
- result.should.be.false();
- should.not.exist(msg.a.b);
- });
- it('sets a property with array syntax', function() {
- var msg = {a:{b:["foo",{c:["",""]}]}};
- var result = util.setMessageProperty(msg,"msg.a.b[1].c[1]","bar");
- result.should.be.true();
- msg.a.b[1].c[1].should.eql('bar');
- });
- it('creates missing array elements - final property', function() {
- var msg = {a:[]};
- var result = util.setMessageProperty(msg,"msg.a[2]","bar");
- result.should.be.true();
- msg.a.should.have.length(3);
- msg.a[2].should.eql("bar");
- });
- it('creates missing array elements - mid property', function() {
- var msg = {};
- var result = util.setMessageProperty(msg,"msg.a[2].b","bar");
- result.should.be.true();
- msg.a.should.have.length(3);
- msg.a[2].b.should.eql("bar");
- });
- it('creates missing array elements - multi-arrays', function() {
- var msg = {};
- var result = util.setMessageProperty(msg,"msg.a[2][2]","bar");
- result.should.be.true();
- msg.a.should.have.length(3);
- msg.a.should.be.instanceOf(Array);
- msg.a[2].should.have.length(3);
- msg.a[2].should.be.instanceOf(Array);
- msg.a[2][2].should.eql("bar");
- });
- it('does not create missing array elements - mid property', function () {
- var msg = {a:[]};
- var result = util.setMessageProperty(msg, "msg.a[1][1]", "bar", false);
- result.should.be.false();
- msg.a.should.empty();
- });
- it('does not create missing array elements - final property', function() {
- var msg = {a:{}};
- var result = util.setMessageProperty(msg,"msg.a.b[2]","bar",false);
- result.should.be.false();
- should.not.exist(msg.a.b);
- // check it has not been misinterpreted
- msg.a.should.not.have.property("b[2]");
- });
- it('deletes property inside array if value is undefined', function() {
- var msg = {a:[1,2,3]};
- var result = util.setMessageProperty(msg,"msg.a[1]",undefined);
- result.should.be.true();
- msg.a.should.have.length(2);
- msg.a[0].should.eql(1);
- msg.a[1].should.eql(3);
- })
- it('handles nested message property references', function() {
- var obj = {a:"foo",b:{}};
- var result = util.setObjectProperty(obj,"b[msg.a]","bar");
- result.should.be.true();
- obj.b.should.have.property("foo","bar");
- });
- it('handles nested message property references', function() {
- var obj = {a:"foo",b:{"foo":[0,0,0]}};
- var result = util.setObjectProperty(obj,"b[msg.a][2]","bar");
- result.should.be.true();
- obj.b.foo.should.eql([0,0,"bar"])
- });
- });
-
- describe('evaluateNodeProperty', function() {
- it('returns string',function() {
- var result = util.evaluateNodeProperty('hello','str');
- result.should.eql('hello');
- });
- it('returns number',function() {
- var result = util.evaluateNodeProperty('0123','num');
- result.should.eql(123);
- });
- it('returns evaluated json',function() {
- var result = util.evaluateNodeProperty('{"a":123}','json');
- result.should.eql({a:123});
- });
- it('returns regex',function() {
- var result = util.evaluateNodeProperty('^abc$','re');
- result.toString().should.eql("/^abc$/");
- });
- it('returns boolean',function() {
- var result = util.evaluateNodeProperty('true','bool');
- result.should.be.true();
- result = util.evaluateNodeProperty('TrUe','bool');
- result.should.be.true();
- result = util.evaluateNodeProperty('false','bool');
- result.should.be.false();
- result = util.evaluateNodeProperty('','bool');
- result.should.be.false();
- });
- it('returns date',function() {
- var result = util.evaluateNodeProperty('','date');
- (Date.now() - result).should.be.approximately(0,50);
- });
- it('returns bin', function () {
- var result = util.evaluateNodeProperty('[1, 2]','bin');
- result[0].should.eql(1);
- result[1].should.eql(2);
- });
- it('returns msg property',function() {
- var result = util.evaluateNodeProperty('foo.bar','msg',{},{foo:{bar:"123"}});
- result.should.eql("123");
- });
- it('throws an error if callback is not defined', function (done) {
- try {
- util.evaluateNodeProperty(' ','msg',{},{foo:{bar:"123"}});
- done("should throw an error");
- } catch (err) {
- done();
- }
- });
- it('returns flow property',function() {
- var result = util.evaluateNodeProperty('foo.bar','flow',{
- context:function() { return {
- flow: { get: function(k) {
- if (k === 'foo.bar') {
- return '123';
- } else {
- return null;
- }
- }}
- }}
- },{});
- result.should.eql("123");
- });
- it('returns global property',function() {
- var result = util.evaluateNodeProperty('foo.bar','global',{
- context:function() { return {
- global: { get: function(k) {
- if (k === 'foo.bar') {
- return '123';
- } else {
- return null;
- }
- }}
- }}
- },{});
- result.should.eql("123");
- });
- it('returns jsonata result', function () {
- var result = util.evaluateNodeProperty('$abs(-1)','jsonata',{},{});
- result.should.eql(1);
- });
- it('returns null', function() {
- var result = util.evaluateNodeProperty(null,'null');
- (result === null).should.be.true();
- })
- describe('environment variable', function() {
- before(function() {
- process.env.NR_TEST_A = "foo";
- process.env.NR_TEST_B = "${NR_TEST_A}";
- })
- after(function() {
- delete process.env.NR_TEST_A;
- delete process.env.NR_TEST_B;
- })
-
- it('returns an environment variable - NR_TEST_A', function() {
- var result = util.evaluateNodeProperty('NR_TEST_A','env');
- result.should.eql('foo');
- });
- it('returns an environment variable - ${NR_TEST_A}', function() {
- var result = util.evaluateNodeProperty('${NR_TEST_A}','env');
- result.should.eql('foo');
- });
- it('returns an environment variable - ${NR_TEST_A', function() {
- var result = util.evaluateNodeProperty('${NR_TEST_A','env');
- result.should.eql('');
- });
- it('returns an environment variable - foo${NR_TEST_A}bar', function() {
- var result = util.evaluateNodeProperty('123${NR_TEST_A}456','env');
- result.should.eql('123foo456');
- });
- it('returns an environment variable - foo${NR_TEST_B}bar', function() {
- var result = util.evaluateNodeProperty('123${NR_TEST_B}456','env');
- result.should.eql('123${NR_TEST_A}456');
- });
-
- });
- });
-
- describe('normalisePropertyExpression', function() {
- function testABC(input,expected) {
- var result = util.normalisePropertyExpression(input);
- // console.log("+",input);
- // console.log(result);
- result.should.eql(expected);
- }
- function testABCWithMessage(input,msg,expected) {
- var result = util.normalisePropertyExpression(input,msg);
- // console.log("+",input);
- // console.log(result);
- result.should.eql(expected);
- }
- function testInvalid(input,msg) {
- /*jshint immed: false */
- (function() {
- util.normalisePropertyExpression(input,msg);
- }).should.throw();
- }
- function testToString(input,msg,expected) {
- var result = util.normalisePropertyExpression(input,msg,true);
- console.log("+",input);
- console.log(result);
- result.should.eql(expected);
- }
- it('pass a.b.c',function() { testABC('a.b.c',['a','b','c']); })
- it('pass a["b"]["c"]',function() { testABC('a["b"]["c"]',['a','b','c']); })
- it('pass a["b"].c',function() { testABC('a["b"].c',['a','b','c']); })
- it("pass a['b'].c",function() { testABC("a['b'].c",['a','b','c']); })
-
- it("pass a[0].c",function() { testABC("a[0].c",['a',0,'c']); })
- it("pass a.0.c",function() { testABC("a.0.c",['a',0,'c']); })
- it("pass a['a.b[0]'].c",function() { testABC("a['a.b[0]'].c",['a','a.b[0]','c']); })
- it("pass a[0][0][0]",function() { testABC("a[0][0][0]",['a',0,0,0]); })
- it("pass '1.2.3.4'",function() { testABC("'1.2.3.4'",['1.2.3.4']); })
- it("pass 'a.b'[1]",function() { testABC("'a.b'[1]",['a.b',1]); })
- it("pass 'a.b'.c",function() { testABC("'a.b'.c",['a.b','c']); })
-
- it("pass a[msg.b]",function() { testABC("a[msg.b]",["a",["msg","b"]]); })
- it("pass a[msg[msg.b]]",function() { testABC("a[msg[msg.b]]",["a",["msg",["msg","b"]]]); })
- it("pass a[msg.b]",function() { testABC("a[msg.b]",["a",["msg","b"]]); })
- it("pass a[msg.b]",function() { testABC("a[msg.b]",["a",["msg","b"]]); })
- it("pass a[msg['b]\"[']]",function() { testABC("a[msg['b]\"[']]",["a",["msg","b]\"["]]); })
- it("pass a[msg['b][']]",function() { testABC("a[msg['b][']]",["a",["msg","b]["]]); })
- it("pass b[msg.a][2]",function() { testABC("b[msg.a][2]",["b",["msg","a"],2])})
-
- it("pass b[msg.a][2] (with message)",function() { testABCWithMessage("b[msg.a][2]",{a: "foo"},["b","foo",2])})
-
- it('pass a.$b.c',function() { testABC('a.$b.c',['a','$b','c']); })
- it('pass a["$b"].c',function() { testABC('a["$b"].c',['a','$b','c']); })
- it('pass a._b.c',function() { testABC('a._b.c',['a','_b','c']); })
- it('pass a["_b"].c',function() { testABC('a["_b"].c',['a','_b','c']); })
-
- it("pass a['a.b[0]'].c",function() { testToString("a['a.b[0]'].c",null,'a["a.b[0]"]["c"]'); })
- it("pass a.b.c",function() { testToString("a.b.c",null,'a["b"]["c"]'); })
- it('pass a[msg.c][0]["fred"]',function() { testToString('a[msg.c][0]["fred"]',{c:"123"},'a["123"][0]["fred"]'); })
-
- it("fail a'b'.c",function() { testInvalid("a'b'.c"); })
- it("fail a['b'.c",function() { testInvalid("a['b'.c"); })
- it("fail a[]",function() { testInvalid("a[]"); })
- it("fail a]",function() { testInvalid("a]"); })
- it("fail a[",function() { testInvalid("a["); })
- it("fail a[0d]",function() { testInvalid("a[0d]"); })
- it("fail a['",function() { testInvalid("a['"); })
- it("fail a[']",function() { testInvalid("a[']"); })
- it("fail a[0']",function() { testInvalid("a[0']"); })
- it("fail a.[0]",function() { testInvalid("a.[0]"); })
- it("fail [0]",function() { testInvalid("[0]"); })
- it("fail a[0",function() { testInvalid("a[0"); })
- it("fail a.",function() { testInvalid("a."); })
- it("fail .a",function() { testInvalid(".a"); })
- it("fail a. b",function() { testInvalid("a. b"); })
- it("fail a.b",function() { testInvalid(" a.b"); })
- it("fail a[0].[1]",function() { testInvalid("a[0].[1]"); })
- it("fail a['']",function() { testInvalid("a['']"); })
- it("fail 'a.b'c",function() { testInvalid("'a.b'c"); })
- it("fail ",function() { testInvalid("");})
- it("fail a[b]",function() { testInvalid("a[b]"); })
- it("fail a[msg.]",function() { testInvalid("a[msg.]"); })
- it("fail a[msg[]",function() { testInvalid("a[msg[]"); })
- it("fail a[msg.[]]",function() { testInvalid("a[msg.[]]"); })
- it("fail a[msg['af]]",function() { testInvalid("a[msg['af]]"); })
- it("fail b[msg.undefined][2] (with message)",function() { testInvalid("b[msg.undefined][2]",{})})
-
- });
-
- describe('normaliseNodeTypeName', function() {
- function normalise(input, expected) {
- var result = util.normaliseNodeTypeName(input);
- result.should.eql(expected);
- }
-
- it('pass blank',function() { normalise("", "") });
- it('pass ab1',function() { normalise("ab1", "ab1") });
- it('pass AB1',function() { normalise("AB1", "aB1") });
- it('pass a b 1',function() { normalise("a b 1", "aB1") });
- it('pass a-b-1',function() { normalise("a-b-1", "aB1") });
- it('pass ab1 ',function() { normalise(" ab1 ", "ab1") });
- it('pass _a_b_1_',function() { normalise("_a_b_1_", "aB1") });
- it('pass http request',function() { normalise("http request", "httpRequest") });
- it('pass HttpRequest',function() { normalise("HttpRequest", "httpRequest") });
- });
-
- describe('prepareJSONataExpression', function() {
- it('prepares an expression', function() {
- var result = util.prepareJSONataExpression('payload',{});
- result.should.have.property('evaluate');
- result.should.have.property('assign');
- result.should.have.property('_legacyMode', false);
- });
- it('prepares a legacyMode expression', function() {
- var result = util.prepareJSONataExpression('msg.payload',{});
- result.should.have.property('evaluate');
- result.should.have.property('assign');
- result.should.have.property('_legacyMode', true);
- });
- });
- describe('evaluateJSONataExpression', function() {
- it('evaluates an expression', function() {
- var expr = util.prepareJSONataExpression('payload',{});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- result.should.eql("hello");
- });
- it('evaluates a legacyMode expression', function() {
- var expr = util.prepareJSONataExpression('msg.payload',{});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- result.should.eql("hello");
- });
- it('accesses flow context from an expression', function() {
- var expr = util.prepareJSONataExpression('$flowContext("foo")',{context:function() { return {flow:{get: function(key) { return {'foo':'bar'}[key]}}}}});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- result.should.eql("bar");
- });
- it('accesses undefined environment variable from an expression', function() {
- var expr = util.prepareJSONataExpression('$env("UTIL_ENV")',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('');
- });
- it('accesses environment variable from an expression', function() {
- process.env.UTIL_ENV = 'foo';
- var expr = util.prepareJSONataExpression('$env("UTIL_ENV")',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('foo');
- });
- it('accesses moment from an expression', function() {
- var expr = util.prepareJSONataExpression('$moment("2020-05-27", "YYYY-MM-DD").add(7, "days").add(1, "months").format("YYYY-MM-DD")',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('2020-07-03');
- });
- it('accesses moment-timezone from an expression', function() {
- var expr = util.prepareJSONataExpression('$moment("2013-11-18 11:55Z").tz("Asia/Taipei").format()',{});
- var result = util.evaluateJSONataExpression(expr,{});
- result.should.eql('2013-11-18T19:55:00+08:00');
- });
- it('handles non-existant flow context variable', function() {
- var expr = util.prepareJSONataExpression('$flowContext("nonExistant")',{context:function() { return {flow:{get: function(key) { return {'foo':'bar'}[key]}}}}});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- should.not.exist(result);
- });
- it('handles non-existant global context variable', function() {
- var expr = util.prepareJSONataExpression('$globalContext("nonExistant")',{context:function() { return {global:{get: function(key) { return {'foo':'bar'}[key]}}}}});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"});
- should.not.exist(result);
- });
- it('handles async flow context access', function(done) {
- var expr = util.prepareJSONataExpression('$flowContext("foo")',{context:function() { return {flow:{get: function(key,store,callback) { setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('handles async global context access', function(done) {
- var expr = util.prepareJSONataExpression('$globalContext("foo")',{context:function() { return {global:{get: function(key,store,callback) { setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('handles persistable store in flow context access', function(done) {
- var storeName;
- var expr = util.prepareJSONataExpression('$flowContext("foo", "flowStoreName")',{context:function() { return {flow:{get: function(key,store,callback) { storeName = store;setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- storeName.should.equal("flowStoreName");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('handles persistable store in global context access', function(done) {
- var storeName;
- var expr = util.prepareJSONataExpression('$globalContext("foo", "globalStoreName")',{context:function() { return {global:{get: function(key,store,callback) { storeName = store;setTimeout(()=>{callback(null,{'foo':'bar'}[key])},10)}}}}});
- util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value) {
- try {
- should.not.exist(err);
- value.should.eql("bar");
- storeName.should.equal("globalStoreName");
- done();
- } catch(err2) {
- done(err2);
- }
- });
- })
- it('callbacks with error when invalid expression was specified', function (done) {
- var expr = util.prepareJSONataExpression('$abc(1)',{});
- var result = util.evaluateJSONataExpression(expr,{payload:"hello"},function(err,value){
- should.exist(err);
- done();
- });
- });
- });
-
- describe('encodeObject', function () {
- it('encodes Error with message', function() {
- var err = new Error("encode error");
- err.name = 'encodeError';
- var msg = {msg:err};
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var resultJson = JSON.parse(result.msg);
- resultJson.name.should.eql('encodeError');
- resultJson.message.should.eql('encode error');
- });
- it('encodes Error without message', function() {
- var err = new Error();
- err.name = 'encodeError';
- err.toString = function(){return 'error message';}
- var msg = {msg:err};
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var resultJson = JSON.parse(result.msg);
- resultJson.name.should.eql('encodeError');
- resultJson.message.should.eql('error message');
- });
- it('encodes Buffer', function() {
- var msg = {msg:Buffer.from("abc")};
- var result = util.encodeObject(msg,{maxLength:4});
- result.format.should.eql("buffer[3]");
- result.msg[0].should.eql('6');
- result.msg[1].should.eql('1');
- result.msg[2].should.eql('6');
- result.msg[3].should.eql('2');
- });
- it('encodes function', function() {
- var msg = {msg:function(){}};
- var result = util.encodeObject(msg);
- result.format.should.eql("function");
- result.msg.should.eql('[function]');
- });
- it('encodes boolean', function() {
- var msg = {msg:true};
- var result = util.encodeObject(msg);
- result.format.should.eql("boolean");
- result.msg.should.eql('true');
- });
- it('encodes number', function() {
- var msg = {msg:123};
- var result = util.encodeObject(msg);
- result.format.should.eql("number");
- result.msg.should.eql('123');
- });
- it('encodes 0', function() {
- var msg = {msg:0};
- var result = util.encodeObject(msg);
- result.format.should.eql("number");
- result.msg.should.eql('0');
- });
- it('encodes null', function() {
- var msg = {msg:null};
- var result = util.encodeObject(msg);
- result.format.should.eql("null");
- result.msg.should.eql('(undefined)');
- });
- it('encodes undefined', function() {
- var msg = {msg:undefined};
- var result = util.encodeObject(msg);
- result.format.should.eql("undefined");
- result.msg.should.eql('(undefined)');
- });
- it('encodes string', function() {
- var msg = {msg:'1234567890'};
- var result = util.encodeObject(msg,{maxLength:6});
- result.format.should.eql("string[10]");
- result.msg.should.eql('123456...');
- });
-
- it('encodes Map', function() {
- const m = new Map();
- m.set("a",1);
- m.set("b",2);
- var msg = {msg:m};
- var result = util.encodeObject(msg);
- result.format.should.eql("map");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("__enc__",true);
- resultJson.should.have.property("type","map");
- resultJson.should.have.property("data",{"a":1,"b":2});
- resultJson.should.have.property("length",2)
- });
-
- it('encodes Set', function() {
- const m = new Set();
- m.add("a");
- m.add("b");
- var msg = {msg:m};
- var result = util.encodeObject(msg);
- result.format.should.eql("set[2]");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("__enc__",true);
- resultJson.should.have.property("type","set");
- resultJson.should.have.property("data",["a","b"]);
- resultJson.should.have.property("length",2)
- });
-
-
- describe('encode object', function() {
- it('object', function() {
- var msg = { msg:{"foo":"bar"} };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.foo.should.eql('bar');
- });
- it('object whose name includes error', function() {
- function MyErrorObj(){
- this.name = 'my error obj';
- this.message = 'my error message';
- };
- var msg = { msg:new MyErrorObj() };
- var result = util.encodeObject(msg);
- result.format.should.eql("MyErrorObj");
- var resultJson = JSON.parse(result.msg);
- resultJson.name.should.eql('my error obj');
- resultJson.message.should.eql('my error message');
- });
-
- it('object with undefined property', function() {
- var msg = { msg:{a:1,b:undefined,c:3 } };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("a",1);
- resultJson.should.have.property("c",3);
- resultJson.should.have.property("b");
- resultJson.b.should.have.property("__enc__", true);
- resultJson.b.should.have.property("type", "undefined");
- });
- it('object with Map property', function() {
- const m = new Map();
- m.set("a",1);
- m.set("b",2);
- var msg = {msg:{"aMap":m}};
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("aMap");
- resultJson.aMap.should.have.property("__enc__",true);
- resultJson.aMap.should.have.property("type","map");
- resultJson.aMap.should.have.property("data",{"a":1,"b":2});
- resultJson.aMap.should.have.property("length",2)
- });
- it('object with Set property', function() {
- const m = new Set();
- m.add("a");
- m.add("b");
- var msg = {msg:{"aSet":m}};
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.have.property("aSet");
- resultJson.aSet.should.have.property("__enc__",true);
- resultJson.aSet.should.have.property("type","set");
- resultJson.aSet.should.have.property("data",["a","b"]);
- resultJson.aSet.should.have.property("length",2)
- });
- it('constructor of IncomingMessage', function() {
- function IncomingMessage(){};
- var msg = { msg:new IncomingMessage() };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.empty();
- });
- it('_req key in msg', function() {
- function Socket(){};
- var msg = { msg:{"_req":123} };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson._req.__enc__.should.eql(true);
- resultJson._req.type.should.eql('internal');
- });
- it('_res key in msg', function() {
- function Socket(){};
- var msg = { msg:{"_res":123} };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson._res.__enc__.should.eql(true);
- resultJson._res.type.should.eql('internal');
- });
- it('array of error', function() {
- var msg = { msg:[new Error("encode error")] };
- var result = util.encodeObject(msg);
- result.format.should.eql("array[1]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].should.eql('Error: encode error');
- });
- it('long array in msg', function() {
- var msg = {msg:{array:[1,2,3,4]}};
- var result = util.encodeObject(msg,{maxLength:2});
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.array.__enc__.should.eql(true);
- resultJson.array.data[0].should.eql(1);
- resultJson.array.data[1].should.eql(2);
- resultJson.array.length.should.eql(4);
- });
- it('array of string', function() {
- var msg = { msg:["abcde","12345"] };
- var result = util.encodeObject(msg,{maxLength:3});
- result.format.should.eql("array[2]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].should.eql('abc...');
- resultJson[1].should.eql('123...');
- });
- it('array containing undefined', function() {
- var msg = { msg:[1,undefined,3]};
- var result = util.encodeObject(msg);
- result.format.should.eql("array[3]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].should.eql(1);
- resultJson[2].should.eql(3);
- resultJson[1].__enc__.should.be.true();
- resultJson[1].type.should.eql("undefined");
- });
- it('array of function', function() {
- var msg = { msg:[function(){}] };
- var result = util.encodeObject(msg);
- result.format.should.eql("array[1]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].__enc__.should.eql(true);
- resultJson[0].type.should.eql('function');
- });
- it('array of number', function() {
- var msg = { msg:[1,2,3] };
- var result = util.encodeObject(msg,{maxLength:2});
- result.format.should.eql("array[3]");
- var resultJson = JSON.parse(result.msg);
- resultJson.__enc__.should.eql(true);
- resultJson.data[0].should.eql(1);
- resultJson.data[1].should.eql(2);
- resultJson.data.length.should.eql(2);
- resultJson.length.should.eql(3);
- });
- it('array of special number', function() {
- var msg = { msg:[NaN,Infinity,-Infinity] };
- var result = util.encodeObject(msg);
- result.format.should.eql("array[3]");
- var resultJson = JSON.parse(result.msg);
- resultJson[0].__enc__.should.eql(true);
- resultJson[0].type.should.eql('number');
- resultJson[0].data.should.eql('NaN');
- resultJson[1].data.should.eql('Infinity');
- resultJson[2].data.should.eql('-Infinity');
- });
- it('constructor of Buffer in msg', function() {
- var msg = { msg:{buffer:Buffer.from([1,2,3,4])} };
- var result = util.encodeObject(msg,{maxLength:2});
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.buffer.__enc__.should.eql(true);
- resultJson.buffer.length.should.eql(4);
- resultJson.buffer.data[0].should.eql(1);
- resultJson.buffer.data[1].should.eql(2);
- });
- it('constructor of ServerResponse', function() {
- function ServerResponse(){};
- var msg = { msg: new ServerResponse() };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.should.eql('[internal]');
- });
- it('constructor of Socket in msg', function() {
- function Socket(){};
- var msg = { msg: { socket: new Socket() } };
- var result = util.encodeObject(msg);
- result.format.should.eql("Object");
- var resultJson = JSON.parse(result.msg);
- resultJson.socket.should.eql('[internal]');
- });
- it('object which fails to serialise', function(done) {
- var msg = {
- msg: {
- obj:{
- cantserialise:{
- message:'this will not be displayed',
- toJSON: function(val) {
- throw 'this exception should have been caught';
- return 'should not display because we threw first';
- },
- },
- canserialise:{
- message:'this should be displayed',
- }
- },
- }
- };
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var success = (result.msg.indexOf('cantserialise') > 0);
- success &= (result.msg.indexOf('this exception should have been caught') > 0);
- success &= (result.msg.indexOf('canserialise') > 0);
- success.should.eql(1);
- done();
- });
- it('object which fails to serialise - different error type', function(done) {
- var msg = {
- msg: {
- obj:{
- cantserialise:{
- message:'this will not be displayed',
- toJSON: function(val) {
- throw new Error('this exception should have been caught');
- return 'should not display because we threw first';
- },
- },
- canserialise:{
- message:'this should be displayed',
- }
- },
- }
- };
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var success = (result.msg.indexOf('cantserialise') > 0);
- success &= (result.msg.indexOf('this exception should have been caught') > 0);
- success &= (result.msg.indexOf('canserialise') > 0);
- success.should.eql(1);
- done();
- });
- it('very large object which fails to serialise should be truncated', function(done) {
- var msg = {
- msg: {
- obj:{
- big:"",
- cantserialise:{
- message:'this will not be displayed',
- toJSON: function(val) {
- throw new Error('this exception should have been caught');
- return 'should not display because we threw first';
- },
- },
- canserialise:{
- message:'this should be displayed',
- }
- },
- }
- };
-
- for (var i = 0; i < 1000; i++) {
- msg.msg.obj.big += 'some more string ';
- }
-
- var result = util.encodeObject(msg);
- result.format.should.eql("error");
- var resultJson = JSON.parse(result.msg);
- var success = (resultJson.message.length <= 1000);
- success.should.eql(true);
- done();
- });
- it('test bad toString', function(done) {
- var msg = {
- msg: {
- mystrangeobj:"hello",
- },
- };
- msg.msg.toString = function(){
- throw new Error('Exception in toString - should have been caught');
- }
- msg.msg.constructor = { name: "strangeobj" };
-
- var result = util.encodeObject(msg);
- var success = (result.msg.indexOf('[Type not printable]') >= 0);
- success.should.eql(true);
- done();
- });
- it('test bad object constructor', function(done) {
- var msg = {
- msg: {
- mystrangeobj:"hello",
- constructor: {
- get name(){
- throw new Error('Exception in constructor name');
- }
- }
- },
- };
- var result = util.encodeObject(msg);
- done();
- });
-
- });
- });
-
-});
diff --git a/test/unit/_spec.js b/test/unit/_spec.js
deleted file mode 100644
index d099836f3..000000000
--- a/test/unit/_spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-/**
- * This test simply checks that for every .js file there exists
- * a *_spec.js file under ./test correspondingly.
- */
-
-/**
- * Currently we're only checking the core components under ./red
- * TODO: Increase the scope of this check
- */
-
-var fs = require("fs-extra");
-var should = require("should");
-var path = require('path');
-
-// Directories to check with .js files and _spec.js files respectively
-var rootdir = path.resolve(__dirname, "../..");
-var jsdir = path.resolve(__dirname, "../../packages/node_modules/");
-var testdir = path.resolve(__dirname);
-
-var walkDirectory = function(dir) {
- var p = fs.readdir(dir);
- var errors = [];
- return p.then(function(list) {
- var promises = [];
- list.forEach(function(file) {
- var filePath = path.join(dir,file);
-
- if (!/@node-red\/(editor-client|nodes)/.test(filePath) && !/node-red\/settings\.js/.test(filePath) && !/\/docs\//.test(filePath)) {
- promises.push(fs.stat(filePath).then(function(stat){
- if (stat.isDirectory()) {
- return walkDirectory(filePath).then(function(results) {
- if (results) {
- errors = errors.concat(results);
- }
- });
- } else if (/\.js$/.test(filePath)) {
- var testFile = filePath.replace(jsdir, testdir).replace(".js", "_spec.js");
- return fs.exists(testFile).then(function(exists) {
- if (!exists) {
- errors.push(testFile.substring(rootdir.length+1));
- } else {
- return fs.stat(testFile).then(function(stat) {
- if (stat.size === 0) {
- errors.push("[empty] "+testFile.substring(rootdir.length+1));
- }
- })
- }
- });
- }
- }));
- }
- });
- return Promise.all(promises).then(function() {
- return errors;
- })
- });
-}
-
-describe('_spec.js', function() {
- this.timeout(50000); // we might not finish within the Mocha default timeout limit, project will also grow
- it('is checking if all .js files have a corresponding _spec.js test file.', function(done) {
- walkDirectory(jsdir).then(function(errors) {
- if (errors.length > 0) {
- var error = new Error("Missing/empty _spec files:\n\t"+errors.join("\n\t"));
- done(error);
- } else {
- done();
- }
- });
- });
-});
diff --git a/test/unit/node-red/lib/red_spec.js b/test/unit/node-red/lib/red_spec.js
deleted file mode 100644
index 4cd430822..000000000
--- a/test/unit/node-red/lib/red_spec.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-var should = require("should");
-var sinon = require("sinon");
-var fs = require("fs");
-var path = require("path");
-
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-var api = NR_TEST_UTILS.require("@node-red/runtime/lib/api");
-
-var RED = NR_TEST_UTILS.require("node-red");
-
-var runtime = NR_TEST_UTILS.require("@node-red/runtime");
-var api = NR_TEST_UTILS.require("@node-red/runtime/lib/api");
-
-
-describe("red/red", function() {
-
- // describe("check build", function() {
- // beforeEach(function() {
- // sinon.stub(runtime,"init").callsFake(function() {});
- // sinon.stub(api,"init").callsFake(function() {});
- // // sinon.stub(RED,"version").callsFake(function() { return "version";});
- // });
- // afterEach(function() {
- // runtime.init.restore();
- // api.init.restore();
- // fs.statSync.restore();
- // // RED.version.restore();
- // });
- // it.skip('warns if build has not been run',function() {
- // sinon.stub(fs,"statSync").callsFake(function() { throw new Error();});
- //
- // /*jshint immed: false */
- // (function() {
- // RED.init({},{});
- // }).should.throw("Node-RED not built");
- // });
- // it('passed if build has been run',function() {
- // sinon.stub(fs,"statSync").callsFake(function() { });
- // RED.init({},{});
- // });
- // });
-
- describe("externals", function() {
- it('reports version', function() {
- /\d+\.\d+\.\d+(-git)?/.test(RED.version()).should.be.true();
- });
- it.skip('access server externals', function() {
- // TODO: unstubable accessors - need to make this testable
- // RED.app;
- // RED.httpAdmin;
- // RED.httpNode;
- // RED.server;
- });
- it.skip('only initialises api component if httpAdmin enabled');
- it.skip('stubs httpAdmin if httpAdmin disabled');
- it.skip('stubs httpNode if httpNode disabled');
- });
-
-});
diff --git a/test/unit/node-red/red_spec.js b/test/unit/node-red/red_spec.js
deleted file mode 100644
index ee46fc504..000000000
--- a/test/unit/node-red/red_spec.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Copyright JS Foundation and other contributors, http://js.foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-
-var NR_TEST_UTILS = require("nr-test-utils");
-
-describe("node-red/red", function() {
- it.skip("NEEDS TESTS WRITING",function() {});
-});