Deadmon commited on
Commit
47cee22
·
verified ·
1 Parent(s): 93e49e4

Update test_webhook_and_start.py

Browse files
Files changed (1) hide show
  1. test_webhook_and_start.py +177 -144
test_webhook_and_start.py CHANGED
@@ -1,4 +1,4 @@
1
- import unittest
2
  import json
3
  import hmac
4
  import hashlib
@@ -6,9 +6,10 @@ import requests
6
  from unittest.mock import patch
7
  import logging
8
  import os
 
9
 
10
  # Configure logging to write to both file and console
11
- LOG_FILE = "pipecat/test.log"
12
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
13
  logging.basicConfig(
14
  level=logging.INFO,
@@ -20,161 +21,193 @@ logging.basicConfig(
20
  )
21
  logger = logging.getLogger(__name__)
22
 
23
- # Base URL of your Hugging Face Space
24
- BASE_URL="https://deadmon-pipecat.hf.space/webhook" # Replace with your endpoint
25
- WEBHOOK_SECRET="eW91ci1zZWNyZXQtc3RyaW5n" # Base64-encoded secret
26
-
27
- class TestPipecatWebhookAndStart(unittest.TestCase):
28
- def setUp(self):
29
- """Set up test case with common variables."""
30
- logger.info("Setting up test case")
31
- self.webhook_url = f"{BASE_URL}/webhook"
32
- self.start_url = f"{BASE_URL}/start"
33
- self.valid_payload = {
34
- "event": "dialin.connected",
35
- "callId": "test-call-123",
36
- "callDomain": "test.daily.co",
37
- "From": "+12345678901",
38
- "To": "+12345678902",
39
- "timestamp": "2025-05-11T01:33:07.000Z"
40
- }
41
- self.stopped_payload = {
42
- "event": "dialin.stopped",
43
- "callId": "test-call-123",
44
- "callDomain": "test.daily.co",
45
- "timestamp": "2025-05-11T01:33:07.000Z"
46
- }
47
-
48
- def generate_signature(self, payload):
49
- """Generate HMAC-SHA256 signature for a payload."""
50
- logger.debug("Generating HMAC signature")
51
- payload_str = json.dumps(payload)
52
- computed = hmac.new(
53
- WEBHOOK_SECRET.encode('utf-8'),
54
- payload_str.encode('utf-8'),
55
- hashlib.sha256
56
- ).hexdigest()
57
- return computed
58
-
59
- def test_server_availability(self):
60
- """Test that the server is running and accessible."""
61
- logger.info("Starting test_server_availability")
62
- try:
63
- response = requests.get(BASE_URL, timeout=5)
64
- self.assertIn(response.status_code, [200, 404], f"Server not accessible: {response.status_code}")
65
- logger.info(f"Server availability test passed: Status code {response.status_code}")
66
- except requests.RequestException as e:
67
- logger.error(f"Server not reachable: {str(e)}")
68
- self.fail(f"Server not reachable: {str(e)}")
69
-
70
- def test_webhook_dialin_connected(self):
71
- """Test webhook handling of dialin.connected event."""
72
- logger.info("Starting test_webhook_dialin_connected")
73
- headers = {"X-Daily-Signature": self.generate_signature(self.valid_payload)}
74
- with patch('requests.post') as mocked_post:
75
- mocked_post.return_value.status_code = 200
76
- mocked_post.return_value.text = '{"status": "Bot started"}'
77
-
78
- try:
79
- response = requests.post(
80
- self.webhook_url,
81
- json=self.valid_payload,
82
- headers=headers,
83
- timeout=5
84
- )
85
- self.assertEqual(response.status_code, 200, f"Webhook failed: {response.text}")
86
- self.assertEqual(response.json(), {"status": "Event received"})
87
- mocked_post.assert_called_once_with(
88
- self.start_url,
89
- json=self.valid_payload,
90
- timeout=5
91
- )
92
- logger.info("Webhook dialin.connected test passed")
93
- except Exception as e:
94
- logger.error(f"Webhook dialin.connected test failed: {str(e)}")
95
- raise
96
-
97
- def test_webhook_dialin_stopped(self):
98
- """Test webhook handling of dialin.stopped event."""
99
- logger.info("Starting test_webhook_dialin_stopped")
100
- headers = {"X-Daily-Signature": self.generate_signature(self.stopped_payload)}
101
- try:
102
- response = requests.post(
103
- self.webhook_url,
104
- json=self.stopped_payload,
105
- headers=headers,
106
- timeout=5
107
- )
108
- self.assertEqual(response.status_code, 200, f"Webhook failed: {response.text}")
109
- self.assertEqual(response.json(), {"status": "Event received"})
110
- logger.info("Webhook dialin.stopped test passed")
111
- except Exception as e:
112
- logger.error(f"Webhook dialin.stopped test failed: {str(e)}")
113
- raise
114
 
115
- def test_webhook_invalid_signature(self):
116
- """Test webhook rejects requests with invalid signature."""
117
- logger.info("Starting test_webhook_invalid_signature")
118
- headers = {"X-Daily-Signature": "invalid-signature"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  try:
120
  response = requests.post(
121
- self.webhook_url,
122
- json=self.valid_payload,
123
  headers=headers,
124
  timeout=5
125
  )
126
- self.assertEqual(response.status_code, 401, f"Expected 401 for invalid signature: {response.status_code}")
127
- logger.info("Webhook invalid signature test passed")
128
- except Exception as e:
129
- logger.error(f"Webhook invalid signature test failed: {str(e)}")
130
- raise
131
-
132
- def test_start_endpoint_valid_payload(self):
133
- """Test /start endpoint with valid dial-in payload."""
134
- logger.info("Starting test_start_endpoint_valid_payload")
135
- try:
136
- response = requests.post(
137
- self.start_url,
138
- json=self.valid_payload,
139
  timeout=5
140
  )
141
- self.assertEqual(response.status_code, 200, f"Start endpoint failed: {response.text}")
142
- response_json = response.json()
143
- self.assertEqual(response_json.get("status"), "Bot started")
144
- self.assertEqual(response_json.get("bot_type"), "call_transfer")
145
- logger.info("Start endpoint valid payload test passed")
146
  except Exception as e:
147
- logger.error(f"Start endpoint valid payload test failed: {str(e)}")
148
  raise
149
 
150
- def test_start_endpoint_invalid_payload(self):
151
- """Test /start endpoint with invalid payload."""
152
- logger.info("Starting test_start_endpoint_invalid_payload")
153
- invalid_payload = {"invalid": "data"}
154
- try:
155
- response = requests.post(
156
- self.start_url,
157
- json=invalid_payload,
158
- timeout=5
159
- )
160
- self.assertEqual(response.status_code, 400, f"Expected 400 for invalid payload: {response.status_code}")
161
- logger.info("Start endpoint invalid payload test passed")
162
- except Exception as e:
163
- logger.error(f"Start endpoint invalid payload test failed: {str(e)}")
164
- raise
 
 
165
 
166
- def test_404_on_root(self):
167
- """Test that root endpoint returns 404 (as seen in logs)."""
168
- logger.info("Starting test_404_on_root")
169
- try:
170
- response = requests.get(f"{BASE_URL}/?__theme=dark", timeout=5)
171
- self.assertEqual(response.status_code, 404, f"Expected 404 for root endpoint: {response.status_code}")
172
- logger.info("Root endpoint 404 test passed")
173
- except Exception as e:
174
- logger.error(f"Root endpoint 404 test failed: {str(e)}")
175
- raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
  if __name__ == '__main__':
178
  logger.info("Starting test suite")
179
- unittest.main()
180
  logger.info("Test suite completed")
 
1
+ import pytest
2
  import json
3
  import hmac
4
  import hashlib
 
6
  from unittest.mock import patch
7
  import logging
8
  import os
9
+ from http.client import HTTPConnection
10
 
11
  # Configure logging to write to both file and console
12
+ LOG_FILE = "/app/test.log"
13
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
14
  logging.basicConfig(
15
  level=logging.INFO,
 
21
  )
22
  logger = logging.getLogger(__name__)
23
 
24
+ # Base URL of your Hugging Face Space or local server
25
+ BASE_URL = "https://<your-space>.hf.space" # Replace with your Space URL
26
+ WEBHOOK_SECRET = "your-base64-encoded-secret" # Replace with your webhook secret
27
+
28
+ @pytest.fixture
29
+ def webhook_url():
30
+ """Fixture for webhook URL."""
31
+ return f"{BASE_URL}/webhook"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ @pytest.fixture
34
+ def start_url():
35
+ """Fixture for start URL."""
36
+ return f"{BASE_URL}/start"
37
+
38
+ @pytest.fixture
39
+ def valid_dialin_payload():
40
+ """Fixture for valid dialin.connected payload."""
41
+ return {
42
+ "event": "dialin.connected",
43
+ "callId": "test-call-123",
44
+ "callDomain": "test.daily.co",
45
+ "From": "+12345678901",
46
+ "To": "+12345678902",
47
+ "timestamp": "2025-05-11T01:33:07.000Z"
48
+ }
49
+
50
+ @pytest.fixture
51
+ def stopped_payload():
52
+ """Fixture for dialin.stopped payload."""
53
+ return {
54
+ "event": "dialin.stopped",
55
+ "callId": "test-call-123",
56
+ "callDomain": "test.daily.co",
57
+ "timestamp": "2025-05-11T01:33:07.000Z"
58
+ }
59
+
60
+ @pytest.fixture
61
+ def invalid_payload():
62
+ """Fixture for invalid payload."""
63
+ return {"invalid": "data"}
64
+
65
+ def generate_signature(payload):
66
+ """Generate HMAC-SHA256 signature for a payload."""
67
+ logger.debug("Generating HMAC signature")
68
+ payload_str = json.dumps(payload)
69
+ computed = hmac.new(
70
+ WEBHOOK_SECRET.encode('utf-8'),
71
+ payload_str.encode('utf-8'),
72
+ hashlib.sha256
73
+ ).hexdigest()
74
+ return computed
75
+
76
+ def test_server_availability():
77
+ """Test that the server is running and accessible."""
78
+ logger.info("Starting test_server_availability")
79
+ try:
80
+ response = requests.get(BASE_URL, timeout=5)
81
+ assert response.status_code in [200, 404], f"Server not accessible: {response.status_code}"
82
+ logger.info(f"Server availability test passed: Status code {response.status_code}")
83
+ except requests.RequestException as e:
84
+ logger.error(f"Server not reachable: {str(e)}")
85
+ pytest.fail(f"Server not reachable: {str(e)}")
86
+
87
+ def test_webhook_dialin_connected(webhook_url, start_url, valid_dialin_payload):
88
+ """Test webhook handling of dialin.connected event."""
89
+ logger.info("Starting test_webhook_dialin_connected")
90
+ headers = {"X-Daily-Signature": generate_signature(valid_dialin_payload)}
91
+ with patch('requests.post') as mocked_post:
92
+ mocked_post.return_value.status_code = 200
93
+ mocked_post.return_value.text = '{"status": "Bot started"}'
94
+
95
  try:
96
  response = requests.post(
97
+ webhook_url,
98
+ json=valid_dialin_payload,
99
  headers=headers,
100
  timeout=5
101
  )
102
+ assert response.status_code == 200, f"Webhook failed: {response.text}"
103
+ assert response.json() == {"status": "Event received"}
104
+ mocked_post.assert_called_once_with(
105
+ start_url,
106
+ json=valid_dialin_payload,
 
 
 
 
 
 
 
 
107
  timeout=5
108
  )
109
+ logger.info("Webhook dialin.connected test passed")
 
 
 
 
110
  except Exception as e:
111
+ logger.error(f"Webhook dialin.connected test failed: {str(e)}")
112
  raise
113
 
114
+ def test_webhook_dialin_stopped(webhook_url, stopped_payload):
115
+ """Test webhook handling of dialin.stopped event."""
116
+ logger.info("Starting test_webhook_dialin_stopped")
117
+ headers = {"X-Daily-Signature": generate_signature(stopped_payload)}
118
+ try:
119
+ response = requests.post(
120
+ webhook_url,
121
+ json=stopped_payload,
122
+ headers=headers,
123
+ timeout=5
124
+ )
125
+ assert response.status_code == 200, f"Webhook failed: {response.text}"
126
+ assert response.json() == {"status": "Event received"}
127
+ logger.info("Webhook dialin.stopped test passed")
128
+ except Exception as e:
129
+ logger.error(f"Webhook dialin.stopped test failed: {str(e)}")
130
+ raise
131
 
132
+ def test_webhook_invalid_signature(webhook_url, valid_dialin_payload):
133
+ """Test webhook rejects requests with invalid signature."""
134
+ logger.info("Starting test_webhook_invalid_signature")
135
+ headers = {"X-Daily-Signature": "invalid-signature"}
136
+ try:
137
+ response = requests.post(
138
+ webhook_url,
139
+ json=valid_dialin_payload,
140
+ headers=headers,
141
+ timeout=5
142
+ )
143
+ assert response.status_code == 401, f"Expected 401 for invalid signature: {response.status_code}"
144
+ logger.info("Webhook invalid signature test passed")
145
+ except Exception as e:
146
+ logger.error(f"Webhook invalid signature test failed: {str(e)}")
147
+ raise
148
+
149
+ def test_start_endpoint_valid_payload(start_url, valid_dialin_payload):
150
+ """Test /start endpoint with valid dial-in payload."""
151
+ logger.info("Starting test_start_endpoint_valid_payload")
152
+ try:
153
+ response = requests.post(
154
+ start_url,
155
+ json=valid_dialin_payload,
156
+ timeout=5
157
+ )
158
+ assert response.status_code == 200, f"Start endpoint failed: {response.text}"
159
+ response_json = response.json()
160
+ assert response_json.get("status") == "Bot started", f"Unexpected status: {response_json}"
161
+ assert response_json.get("bot_type") == "call_transfer", f"Unexpected bot type: {response_json}"
162
+ logger.info("Start endpoint valid payload test passed")
163
+ except Exception as e:
164
+ logger.error(f"Start endpoint valid payload test failed: {str(e)}")
165
+ raise
166
+
167
+ def test_start_endpoint_invalid_payload(start_url, invalid_payload):
168
+ """Test /start endpoint with invalid payload."""
169
+ logger.info("Starting test_start_endpoint_invalid_payload")
170
+ try:
171
+ response = requests.post(
172
+ start_url,
173
+ json=invalid_payload,
174
+ timeout=5
175
+ )
176
+ assert response.status_code == 400, f"Expected 400 for invalid payload: {response.status_code}"
177
+ logger.info("Start endpoint invalid payload test passed")
178
+ except Exception as e:
179
+ logger.error(f"Start endpoint invalid payload test failed: {str(e)}")
180
+ raise
181
+
182
+ def test_404_on_root():
183
+ """Test that root endpoint returns 404 (as seen in logs)."""
184
+ logger.info("Starting test_404_on_root")
185
+ try:
186
+ response = requests.get(f"{BASE_URL}/?__theme=dark", timeout=5)
187
+ assert response.status_code == 404, f"Expected 404 for root endpoint: {response.status_code}"
188
+ logger.info("Root endpoint 404 test passed")
189
+ except Exception as e:
190
+ logger.error(f"Root endpoint 404 test failed: {str(e)}")
191
+ raise
192
+
193
+ def test_start_endpoint_test_mode(start_url):
194
+ """Test /start endpoint with test mode payload."""
195
+ logger.info("Starting test_start_endpoint_test_mode")
196
+ test_payload = {"test": True}
197
+ try:
198
+ response = requests.post(
199
+ start_url,
200
+ json=test_payload,
201
+ timeout=5
202
+ )
203
+ assert response.status_code == 200, f"Test mode failed: {response.text}"
204
+ assert response.json() == {"test": True}, f"Unexpected test mode response: {response.json()}"
205
+ logger.info("Start endpoint test mode test passed")
206
+ except Exception as e:
207
+ logger.error(f"Start endpoint test mode test failed: {str(e)}")
208
+ raise
209
 
210
  if __name__ == '__main__':
211
  logger.info("Starting test suite")
212
+ pytest.main(["-v", "--log-file=/app/test.log", "--log-file-level=INFO"])
213
  logger.info("Test suite completed")