fix: webhook container tests

This commit is contained in:
hjlarry 2025-10-30 17:46:59 +08:00
parent 030da43ae3
commit cbebac1d45
1 changed files with 141 additions and 81 deletions

View File

@ -20,9 +20,9 @@ class TestWebhookService:
def mock_external_dependencies(self): def mock_external_dependencies(self):
"""Mock external service dependencies.""" """Mock external service dependencies."""
with ( with (
patch("services.webhook_service.AsyncWorkflowService") as mock_async_service, patch("services.trigger.webhook_service.AsyncWorkflowService") as mock_async_service,
patch("services.webhook_service.ToolFileManager") as mock_tool_file_manager, patch("services.trigger.webhook_service.ToolFileManager") as mock_tool_file_manager,
patch("services.webhook_service.file_factory") as mock_file_factory, patch("services.trigger.webhook_service.file_factory") as mock_file_factory,
patch("services.account_service.FeatureService") as mock_feature_service, patch("services.account_service.FeatureService") as mock_feature_service,
): ):
# Mock ToolFileManager # Mock ToolFileManager
@ -244,106 +244,166 @@ class TestWebhookService:
assert webhook_data["method"] == "POST" assert webhook_data["method"] == "POST"
assert webhook_data["body"]["raw"] == "raw text content" assert webhook_data["body"]["raw"] == "raw text content"
def test_validate_webhook_request_success(self): def test_extract_and_validate_webhook_request_success(self):
"""Test successful webhook request validation.""" """Test successful webhook request validation and type conversion."""
webhook_data = { app = Flask(__name__)
"method": "POST",
"headers": {"Authorization": "Bearer token", "Content-Type": "application/json"},
"query_params": {"version": "1"},
"body": {"message": "hello"},
"files": {},
}
node_config = { with app.test_request_context(
"data": { "/webhook",
"method": "post", method="POST",
"headers": [{"name": "Authorization", "required": True}, {"name": "Content-Type", "required": False}], headers={"Content-Type": "application/json", "Authorization": "Bearer token"},
"params": [{"name": "version", "required": True}], query_string="version=1",
"body": [{"name": "message", "type": "string", "required": True}], json={"message": "hello"},
):
webhook_trigger = MagicMock()
node_config = {
"data": {
"method": "post",
"content_type": "application/json",
"headers": [
{"name": "Authorization", "required": True},
{"name": "Content-Type", "required": False},
],
"params": [{"name": "version", "required": True}],
"body": [{"name": "message", "type": "string", "required": True}],
}
} }
}
result = WebhookService.validate_webhook_request(webhook_data, node_config) result = WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
assert result["valid"] is True assert result["headers"]["Authorization"] == "Bearer token"
assert result["query_params"]["version"] == "1"
assert result["body"]["message"] == "hello"
def test_validate_webhook_request_method_mismatch(self): def test_extract_and_validate_webhook_request_method_mismatch(self):
"""Test webhook validation with HTTP method mismatch.""" """Test webhook validation with HTTP method mismatch."""
webhook_data = {"method": "GET", "headers": {}, "query_params": {}, "body": {}, "files": {}} app = Flask(__name__)
node_config = {"data": {"method": "post"}} with app.test_request_context(
"/webhook",
method="GET",
headers={"Content-Type": "application/json"},
):
webhook_trigger = MagicMock()
node_config = {"data": {"method": "post", "content_type": "application/json"}}
result = WebhookService.validate_webhook_request(webhook_data, node_config) with pytest.raises(ValueError, match="HTTP method mismatch"):
WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
assert result["valid"] is False def test_extract_and_validate_webhook_request_missing_required_header(self):
assert "HTTP method mismatch" in result["error"]
def test_validate_webhook_request_missing_required_header(self):
"""Test webhook validation with missing required header.""" """Test webhook validation with missing required header."""
webhook_data = {"method": "POST", "headers": {}, "query_params": {}, "body": {}, "files": {}} app = Flask(__name__)
node_config = {"data": {"method": "post", "headers": [{"name": "Authorization", "required": True}]}} with app.test_request_context(
"/webhook",
result = WebhookService.validate_webhook_request(webhook_data, node_config) method="POST",
headers={"Content-Type": "application/json"},
assert result["valid"] is False ):
assert "Required header missing: Authorization" in result["error"] webhook_trigger = MagicMock()
node_config = {
def test_validate_webhook_request_case_insensitive_headers(self): "data": {
"""Test webhook validation with case-insensitive header matching.""" "method": "post",
webhook_data = { "content_type": "application/json",
"method": "POST", "headers": [{"name": "Authorization", "required": True}],
"headers": {"authorization": "Bearer token"}, # lowercase }
"query_params": {},
"body": {},
"files": {},
}
node_config = {
"data": {
"method": "post",
"headers": [
{"name": "Authorization", "required": True} # Pascal case
],
} }
}
result = WebhookService.validate_webhook_request(webhook_data, node_config) with pytest.raises(ValueError, match="Required header missing: Authorization"):
WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
assert result["valid"] is True def test_extract_and_validate_webhook_request_case_insensitive_headers(self):
"""Test webhook validation with case-insensitive header matching."""
app = Flask(__name__)
def test_validate_webhook_request_missing_required_param(self): with app.test_request_context(
"/webhook",
method="POST",
headers={"Content-Type": "application/json", "authorization": "Bearer token"},
json={"message": "hello"},
):
webhook_trigger = MagicMock()
node_config = {
"data": {
"method": "post",
"content_type": "application/json",
"headers": [{"name": "Authorization", "required": True}],
"body": [{"name": "message", "type": "string", "required": True}],
}
}
result = WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
assert result["headers"].get("Authorization") == "Bearer token"
def test_extract_and_validate_webhook_request_missing_required_param(self):
"""Test webhook validation with missing required query parameter.""" """Test webhook validation with missing required query parameter."""
webhook_data = {"method": "POST", "headers": {}, "query_params": {}, "body": {}, "files": {}} app = Flask(__name__)
node_config = {"data": {"method": "post", "params": [{"name": "version", "required": True}]}} with app.test_request_context(
"/webhook",
method="POST",
headers={"Content-Type": "application/json"},
json={"message": "hello"},
):
webhook_trigger = MagicMock()
node_config = {
"data": {
"method": "post",
"content_type": "application/json",
"params": [{"name": "version", "required": True}],
"body": [{"name": "message", "type": "string", "required": True}],
}
}
result = WebhookService.validate_webhook_request(webhook_data, node_config) with pytest.raises(ValueError, match="Required parameter missing: version"):
WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
assert result["valid"] is False def test_extract_and_validate_webhook_request_missing_required_body_param(self):
assert "Required query parameter missing: version" in result["error"]
def test_validate_webhook_request_missing_required_body_param(self):
"""Test webhook validation with missing required body parameter.""" """Test webhook validation with missing required body parameter."""
webhook_data = {"method": "POST", "headers": {}, "query_params": {}, "body": {}, "files": {}} app = Flask(__name__)
node_config = {"data": {"method": "post", "body": [{"name": "message", "type": "string", "required": True}]}} with app.test_request_context(
"/webhook",
method="POST",
headers={"Content-Type": "application/json"},
json={},
):
webhook_trigger = MagicMock()
node_config = {
"data": {
"method": "post",
"content_type": "application/json",
"body": [{"name": "message", "type": "string", "required": True}],
}
}
result = WebhookService.validate_webhook_request(webhook_data, node_config) with pytest.raises(ValueError, match="Required body parameter missing: message"):
WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
assert result["valid"] is False def test_extract_and_validate_webhook_request_missing_required_file(self):
assert "Required body parameter missing: message" in result["error"] """Test webhook validation when required file is missing from multipart request."""
app = Flask(__name__)
def test_validate_webhook_request_missing_required_file(self): with app.test_request_context(
"""Test webhook validation with missing required file parameter.""" "/webhook",
webhook_data = {"method": "POST", "headers": {}, "query_params": {}, "body": {}, "files": {}} method="POST",
data={"note": "test"},
content_type="multipart/form-data",
):
webhook_trigger = MagicMock()
webhook_trigger.tenant_id = "tenant"
webhook_trigger.created_by = "user"
node_config = {
"data": {
"method": "post",
"content_type": "multipart/form-data",
"body": [{"name": "upload", "type": "file", "required": True}],
}
}
node_config = {"data": {"method": "post", "body": [{"name": "upload", "type": "file", "required": True}]}} result = WebhookService.extract_and_validate_webhook_data(webhook_trigger, node_config)
result = WebhookService.validate_webhook_request(webhook_data, node_config) assert result["files"] == {}
assert result["valid"] is False
assert "Required file parameter missing: upload" in result["error"]
def test_trigger_workflow_execution_success(self, test_data, mock_external_dependencies, flask_app_with_containers): def test_trigger_workflow_execution_success(self, test_data, mock_external_dependencies, flask_app_with_containers):
"""Test successful workflow execution trigger.""" """Test successful workflow execution trigger."""
@ -357,12 +417,12 @@ class TestWebhookService:
with flask_app_with_containers.app_context(): with flask_app_with_containers.app_context():
# Mock tenant owner lookup to return the test account # Mock tenant owner lookup to return the test account
with patch("services.webhook_service.select") as mock_select: with patch("services.trigger.webhook_service.select") as mock_select:
mock_query = MagicMock() mock_query = MagicMock()
mock_select.return_value.join.return_value.where.return_value = mock_query mock_select.return_value.join.return_value.where.return_value = mock_query
# Mock the session to return our test account # Mock the session to return our test account
with patch("services.webhook_service.Session") as mock_session: with patch("services.trigger.webhook_service.Session") as mock_session:
mock_session_instance = MagicMock() mock_session_instance = MagicMock()
mock_session.return_value.__enter__.return_value = mock_session_instance mock_session.return_value.__enter__.return_value = mock_session_instance
mock_session_instance.scalar.return_value = test_data["account"] mock_session_instance.scalar.return_value = test_data["account"]
@ -384,8 +444,8 @@ class TestWebhookService:
with flask_app_with_containers.app_context(): with flask_app_with_containers.app_context():
# Mock tenant owner lookup to return None # Mock tenant owner lookup to return None
with ( with (
patch("services.webhook_service.select") as mock_select, patch("services.trigger.webhook_service.select") as mock_select,
patch("services.webhook_service.Session") as mock_session, patch("services.trigger.webhook_service.Session") as mock_session,
): ):
mock_session_instance = MagicMock() mock_session_instance = MagicMock()
mock_session.return_value.__enter__.return_value = mock_session_instance mock_session.return_value.__enter__.return_value = mock_session_instance