Deadmon commited on
Commit
bda4f40
·
verified ·
1 Parent(s): 3cbf9f8

Update test_webhook_and_start.py

Browse files
Files changed (1) hide show
  1. test_webhook_and_start.py +141 -174
test_webhook_and_start.py CHANGED
@@ -1,4 +1,4 @@
1
- import pytest
2
  import json
3
  import hmac
4
  import hashlib
@@ -6,10 +6,9 @@ import requests
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 = "/pipecat/test.log"
13
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
14
  logging.basicConfig(
15
  level=logging.INFO,
@@ -21,193 +20,161 @@ logging.basicConfig(
21
  )
22
  logger = logging.getLogger(__name__)
23
 
24
- # Base URL of your Hugging Face Space or local server
25
  BASE_URL="https://deadmon-pipecat.hf.space/webhook" # Replace with your endpoint
26
  WEBHOOK_SECRET="eW91ci1zZWNyZXQtc3RyaW5n" # Base64-encoded 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")
 
1
+ import unittest
2
  import json
3
  import hmac
4
  import hashlib
 
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 = "/app/test.log"
12
  os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)
13
  logging.basicConfig(
14
  level=logging.INFO,
 
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")