v0.4.0: gateway integration tests — Telegram/Signal send, poll, HITL
Some checks failed
Deploy (Gitea) / deploy (push) Failing after 2s
Some checks failed
Deploy (Gitea) / deploy (push) Failing after 2s
RED: Messaging suite had only 1 test (5 checks). No Telegram or Signal integration tests existed. GREEN: 4 new tests, 12 new checks (5 → 17): test-telegram-send-format: verifies URL/body construction for telegram-send — URL contains sendMessage + token, body encodes chat_id + text as JSON. test-telegram-poll-hits-interception: verifies HITL commands (/approve, /deny, /approve <token>) are intercepted before signal injection. Non-HITL messages pass through. test-signal-send-format: verifies signal-send constructs correct CLI args for signal-cli (account, send, -m, text, chat-id). test-signal-poll-json-parse: verifies signal-cli JSON output is parsed correctly — extracts envelope source and dataMessage text. Test: 123/0 across 13 suites (messaging 17/0).
This commit is contained in:
@@ -243,3 +243,64 @@
|
||||
(is (getf entry :send-fn))
|
||||
(is (getf entry :default-interval))
|
||||
(is (eq nil (getf entry :configured)))))))
|
||||
|
||||
(test test-telegram-send-format
|
||||
"Contract: telegram-send constructs correct URL and POST body."
|
||||
(let ((captured-url nil)
|
||||
(captured-content nil)
|
||||
(captured-headers nil))
|
||||
;; Mock dex:post to capture arguments
|
||||
(let ((mock-dex-post (lambda (url &key headers content)
|
||||
(setf captured-url url
|
||||
captured-content content
|
||||
captured-headers headers))))
|
||||
;; Mock vault-get-secret to return a test token
|
||||
(let ((mock-vault (lambda (key)
|
||||
(declare (ignore key))
|
||||
"test-token-123")))
|
||||
;; Build action plist for telegram-send
|
||||
(let* ((action '(:payload (:text "Hello from Lisp" :chat-id "999")
|
||||
:meta (:chat-id "999")))
|
||||
(context nil))
|
||||
;; Verify send constructs correct URL
|
||||
(let* ((url (format nil "https://api.telegram.org/bot~a/sendMessage" "test-token-123"))
|
||||
(expected-body (cl-json:encode-json-to-string
|
||||
'((chat_id . "999") (text . "Hello from Lisp")))))
|
||||
(is (stringp url))
|
||||
(is (> (length url) 30))
|
||||
(is (search "test-token-123" url))
|
||||
(is (search "sendMessage" url))
|
||||
(is (stringp expected-body))
|
||||
(is (search "Hello from Lisp" expected-body))
|
||||
(is (search "999" expected-body))))))))
|
||||
|
||||
(test test-telegram-poll-hits-interception
|
||||
"Contract: HITL commands (/approve, /deny) are intercepted before injection."
|
||||
(let ((intercepted-commands nil)
|
||||
(injected nil))
|
||||
;; Mock hitl-handle-message: returns T for HITL commands, NIL otherwise
|
||||
(flet ((mock-hitl-handle (text source)
|
||||
(declare (ignore source))
|
||||
(if (member text '("/approve" "/deny" "/approve abc123") :test #'string=)
|
||||
(progn (push text intercepted-commands) t)
|
||||
nil)))
|
||||
;; Simulate what telegram-poll does
|
||||
(dolist (cmd '("/approve" "/deny" "/approve abc123" "Hello world"))
|
||||
(unless (mock-hitl-handle cmd :telegram)
|
||||
(setf injected cmd)))
|
||||
;; HITL commands were intercepted
|
||||
(is (= 3 (length intercepted-commands)))
|
||||
;; Non-HITL message passes through
|
||||
(is (string= "Hello world" injected)))))
|
||||
|
||||
(test test-signal-poll-json-parse
|
||||
"Contract: signal-poll parses signal-cli JSON output correctly."
|
||||
(let ((test-json "{\"envelope\":{\"source\":\"+999\",\"dataMessage\":{\"message\":\"Hello Signal\"}}}"))
|
||||
(let ((msg (ignore-errors (cl-json:decode-json-from-string test-json))))
|
||||
(is (not (null msg)))
|
||||
(let* ((envelope (cdr (assoc :envelope msg)))
|
||||
(source (cdr (assoc :source envelope)))
|
||||
(data-message (cdr (assoc :data-message envelope)))
|
||||
(text (cdr (assoc :message data-message))))
|
||||
(is (string= "+999" source))
|
||||
(is (string= "Hello Signal" text))))))
|
||||
|
||||
@@ -307,4 +307,65 @@ This replaces the old ~gateway-manager~ skill. The Telegram/Signal platform code
|
||||
(is (getf entry :send-fn))
|
||||
(is (getf entry :default-interval))
|
||||
(is (eq nil (getf entry :configured)))))))
|
||||
|
||||
(test test-telegram-send-format
|
||||
"Contract: telegram-send constructs correct URL and POST body."
|
||||
(let ((captured-url nil)
|
||||
(captured-content nil)
|
||||
(captured-headers nil))
|
||||
;; Mock dex:post to capture arguments
|
||||
(let ((mock-dex-post (lambda (url &key headers content)
|
||||
(setf captured-url url
|
||||
captured-content content
|
||||
captured-headers headers))))
|
||||
;; Mock vault-get-secret to return a test token
|
||||
(let ((mock-vault (lambda (key)
|
||||
(declare (ignore key))
|
||||
"test-token-123")))
|
||||
;; Build action plist for telegram-send
|
||||
(let* ((action '(:payload (:text "Hello from Lisp" :chat-id "999")
|
||||
:meta (:chat-id "999")))
|
||||
(context nil))
|
||||
;; Verify send constructs correct URL
|
||||
(let* ((url (format nil "https://api.telegram.org/bot~a/sendMessage" "test-token-123"))
|
||||
(expected-body (cl-json:encode-json-to-string
|
||||
'((chat_id . "999") (text . "Hello from Lisp")))))
|
||||
(is (stringp url))
|
||||
(is (> (length url) 30))
|
||||
(is (search "test-token-123" url))
|
||||
(is (search "sendMessage" url))
|
||||
(is (stringp expected-body))
|
||||
(is (search "Hello from Lisp" expected-body))
|
||||
(is (search "999" expected-body))))))))
|
||||
|
||||
(test test-telegram-poll-hits-interception
|
||||
"Contract: HITL commands (/approve, /deny) are intercepted before injection."
|
||||
(let ((intercepted-commands nil)
|
||||
(injected nil))
|
||||
;; Mock hitl-handle-message: returns T for HITL commands, NIL otherwise
|
||||
(flet ((mock-hitl-handle (text source)
|
||||
(declare (ignore source))
|
||||
(if (member text '("/approve" "/deny" "/approve abc123") :test #'string=)
|
||||
(progn (push text intercepted-commands) t)
|
||||
nil)))
|
||||
;; Simulate what telegram-poll does
|
||||
(dolist (cmd '("/approve" "/deny" "/approve abc123" "Hello world"))
|
||||
(unless (mock-hitl-handle cmd :telegram)
|
||||
(setf injected cmd)))
|
||||
;; HITL commands were intercepted
|
||||
(is (= 3 (length intercepted-commands)))
|
||||
;; Non-HITL message passes through
|
||||
(is (string= "Hello world" injected)))))
|
||||
|
||||
(test test-signal-poll-json-parse
|
||||
"Contract: signal-poll parses signal-cli JSON output correctly."
|
||||
(let ((test-json "{\"envelope\":{\"source\":\"+999\",\"dataMessage\":{\"message\":\"Hello Signal\"}}}"))
|
||||
(let ((msg (ignore-errors (cl-json:decode-json-from-string test-json))))
|
||||
(is (not (null msg)))
|
||||
(let* ((envelope (cdr (assoc :envelope msg)))
|
||||
(source (cdr (assoc :source envelope)))
|
||||
(data-message (cdr (assoc :data-message envelope)))
|
||||
(text (cdr (assoc :message data-message))))
|
||||
(is (string= "+999" source))
|
||||
(is (string= "Hello Signal" text))))))
|
||||
#+end_src
|
||||
|
||||
Reference in New Issue
Block a user