Просмотр исходного кода

test: stop three cases assuming the runner shares a host with the webserver

http-error-status-fails, http-body-base64 and
config-defaults-ttl-zero-http-request each gave an http-request node the URL
http://localhost:8090. The node runs wherever the RUNNER is, so that only
holds while the runner and the webserver are on one machine. Split across two
they failed with

  HTTP request failed: Could not connect to server (after 1 attempt(s))

which reads like a broken http-request node rather than a test that had
quietly baked in the deployment topology.

They now write {{API}}, which the harness substitutes from SMARTBOTIC_RUNNER_API
(falling back to SMARTBOTIC_API, then to localhost:8090 - so nothing changes
for a single-host run). The harness's own base URL is overridable the same way,
since it need not run on the webserver's host either.
fszontagh 3 недель назад
Родитель
Сommit
96c931d944

+ 18 - 2
scripts/verify-node.py

@@ -7,13 +7,26 @@ precondition this machine does not meet - reported as a skip, never as a pass.
 """
 import base64
 import json
+import os
 import sys
 import time
 import urllib.error
 import urllib.parse
 import urllib.request
 
-BASE = "http://localhost:8090/api/v1"
+# Where the API is. Overridable because the harness does not have to run on the
+# webserver's host - and, more importantly, because a few cases ask a NODE to
+# fetch a URL, and the node runs wherever the runner is. Those cases used to
+# hardcode http://localhost:8090; the day the runner moved to a different
+# machine from the webserver they failed with "Could not connect to server",
+# which looks like a broken http-request node rather than a test that assumed
+# the two were co-located.
+API_ROOT = os.environ.get("SMARTBOTIC_API", "http://localhost:8090").rstrip("/")
+BASE = API_ROOT + "/api/v1"
+
+# What a node should use to reach the API. Same thing by default; set it when
+# the runner reaches the webserver by a different name than the harness does.
+RUNNER_API_ROOT = os.environ.get("SMARTBOTIC_RUNNER_API", API_ROOT).rstrip("/")
 
 
 def call(method, path, token=None, body=None):
@@ -203,7 +216,10 @@ def precondition_unmet(case):
 def main():
     if len(sys.argv) != 2:
         raise SystemExit("usage: verify-node.py <case.json>")
-    case = json.load(open(sys.argv[1]))
+    raw_case = open(sys.argv[1]).read()
+    # {{API}} is what a case writes when it needs a URL the RUNNER can fetch.
+    raw_case = raw_case.replace("{{API}}", RUNNER_API_ROOT)
+    case = json.loads(raw_case)
 
     unmet = precondition_unmet(case)
     if unmet:

+ 1 - 1
tests/nodes/config-defaults-ttl-zero-http-request.json

@@ -29,7 +29,7 @@
       },
       "config": {
         "method": "GET",
-        "url": "http://localhost:8090/index.html",
+        "url": "{{API}}/index.html",
         "responseMode": "binary",
         "storeDownload": true,
         "downloadCollection": "ttl0_download_probe",

+ 1 - 1
tests/nodes/http-body-base64.json

@@ -3,7 +3,7 @@
   "nodes": [
     {"id": "n1", "name": "Trigger", "type": "click-trigger", "position": {"x": 0, "y": 0}, "config": {}},
     {"id": "n2", "name": "Raw Body Is Sent", "type": "code", "position": {"x": 0, "y": 100},
-     "config": {"code": "const payload = JSON.stringify({ username: 'admin', password: 'admin' });\n\nconst viaBase64 = smartbotic.http.request({\n    method: 'POST',\n    url: 'http://localhost:8090/api/v1/auth/login',\n    headers: { 'Content-Type': 'application/json' },\n    bodyBase64: smartbotic.utils.base64Encode(payload),\n    timeout: 15000\n});\n\nlet parsed = viaBase64.data;\nif (typeof parsed === 'string') { parsed = JSON.parse(parsed); }\n\nconst garbled = smartbotic.http.request({\n    method: 'POST',\n    url: 'http://localhost:8090/api/v1/auth/login',\n    headers: { 'Content-Type': 'application/json' },\n    bodyBase64: smartbotic.utils.base64Encode('{\"username\":\"admin\",\"password\":\"wrong\"}'),\n    timeout: 15000\n});\n\nreturn {\n    status: viaBase64.status,\n    gotToken: typeof parsed.accessToken === 'string' && parsed.accessToken.length > 20,\n    wrongPasswordRejected: garbled.status >= 400\n};"}}
+     "config": {"code": "const payload = JSON.stringify({ username: 'admin', password: 'admin' });\n\nconst viaBase64 = smartbotic.http.request({\n    method: 'POST',\n    url: '{{API}}/api/v1/auth/login',\n    headers: { 'Content-Type': 'application/json' },\n    bodyBase64: smartbotic.utils.base64Encode(payload),\n    timeout: 15000\n});\n\nlet parsed = viaBase64.data;\nif (typeof parsed === 'string') { parsed = JSON.parse(parsed); }\n\nconst garbled = smartbotic.http.request({\n    method: 'POST',\n    url: '{{API}}/api/v1/auth/login',\n    headers: { 'Content-Type': 'application/json' },\n    bodyBase64: smartbotic.utils.base64Encode('{\"username\":\"admin\",\"password\":\"wrong\"}'),\n    timeout: 15000\n});\n\nreturn {\n    status: viaBase64.status,\n    gotToken: typeof parsed.accessToken === 'string' && parsed.accessToken.length > 20,\n    wrongPasswordRejected: garbled.status >= 400\n};"}}
   ],
   "connections": [
     {"sourceNodeId": "n1", "sourceOutput": "main", "targetNodeId": "n2", "targetInput": "data"}

+ 2 - 2
tests/nodes/http-error-status-fails.json

@@ -22,7 +22,7 @@
       },
       "config": {
         "method": "GET",
-        "url": "http://localhost:8090/api/v1/workflows",
+        "url": "{{API}}/api/v1/workflows",
         "responseMode": "text",
         "timeout": 30000,
         "retries": 0
@@ -38,7 +38,7 @@
       },
       "config": {
         "method": "GET",
-        "url": "http://localhost:8090/api/v1/workflows",
+        "url": "{{API}}/api/v1/workflows",
         "responseMode": "text",
         "timeout": 30000,
         "retries": 0,