9
9
10
10
import json
11
11
import os
12
+ from copy import deepcopy
13
+ from datetime import datetime
12
14
from unittest .mock import ANY , MagicMock , patch
13
15
14
16
import pytest
15
17
from fastapi .testclient import TestClient
16
18
17
- from mcpgateway .schemas import ResourceRead , ServerRead
19
+ from mcpgateway .schemas import (
20
+ PromptRead ,
21
+ ResourceRead ,
22
+ ServerRead ,
23
+ ToolMetrics ,
24
+ ToolRead ,
25
+ )
18
26
from mcpgateway .types import InitializeResult , ResourceContent , ServerCapabilities
19
27
20
28
# --------------------------------------------------------------------------- #
21
- # Constants #
29
+ # Constants #
22
30
# --------------------------------------------------------------------------- #
23
31
PROTOCOL_VERSION = os .getenv ("PROTOCOL_VERSION" , "2025-03-26" )
24
32
71
79
"originalNameSlug" : "test-tool" ,
72
80
}
73
81
82
+ # camelCase → snake_case key map for the fields that differ
83
+ _TOOL_KEY_MAP = {
84
+ "originalName" : "original_name" ,
85
+ "requestType" : "request_type" ,
86
+ "integrationType" : "integration_type" ,
87
+ "inputSchema" : "input_schema" ,
88
+ "jsonpathFilter" : "jsonpath_filter" ,
89
+ "createdAt" : "created_at" ,
90
+ "updatedAt" : "updated_at" ,
91
+ "isActive" : "is_active" ,
92
+ "gatewayId" : "gateway_id" ,
93
+ "gatewaySlug" : "gateway_slug" ,
94
+ "originalNameSlug" : "original_name_slug" ,
95
+ }
96
+
97
+
98
+ def camel_to_snake_tool (d : dict ) -> dict :
99
+ out = deepcopy (d )
100
+ # id must be str
101
+ out ["id" ] = str (out ["id" ])
102
+ for camel , snake in _TOOL_KEY_MAP .items ():
103
+ if camel in out :
104
+ out [snake ] = out .pop (camel )
105
+ return out
106
+
107
+
108
+ MOCK_TOOL_READ_SNAKE = camel_to_snake_tool (MOCK_TOOL_READ )
109
+
110
+
74
111
MOCK_RESOURCE_READ = {
75
112
"id" : 1 ,
76
113
"uri" : "test/resource" ,
@@ -183,7 +220,7 @@ def test_static_files(self, test_client):
183
220
184
221
185
222
# ----------------------------------------------------- #
186
- # Protocol & MCP Core Tests #
223
+ # Protocol & MCP Core Tests #
187
224
# ----------------------------------------------------- #
188
225
class TestProtocolEndpoints :
189
226
"""Tests for MCP protocol operations: initialize, ping, notifications, etc."""
@@ -402,36 +439,29 @@ def test_list_tools_endpoint(self, mock_list_tools, test_client, auth_headers):
402
439
assert len (data ) == 1 and data [0 ]["name" ] == "test_tool"
403
440
mock_list_tools .assert_called_once ()
404
441
405
- # @patch("mcpgateway.main.tool_service.register_tool")
406
- # def test_create_tool_endpoint(self, mock_create, test_client, auth_headers):
407
- # """Test registering a new tool."""
408
- # mock_create.return_value = MagicMock()
409
- # mock_create.return_value.model_dump.return_value = MOCK_TOOL_READ
410
- # req = {"name": "test_tool", "url": "http://example.com", "description": "A test tool"}
411
- # response = test_client.post("/tools/", json=req, headers=auth_headers)
412
- # assert response.status_code == 200
413
- # mock_create.assert_called_once()
442
+ @patch ("mcpgateway.main.tool_service.register_tool" )
443
+ def test_create_tool_endpoint (self , mock_create , test_client , auth_headers ):
444
+ mock_create .return_value = MOCK_TOOL_READ_SNAKE
445
+ req = {"name" : "test_tool" , "url" : "http://example.com" , "description" : "A test tool" }
446
+ response = test_client .post ("/tools/" , json = req , headers = auth_headers )
447
+ assert response .status_code == 200
448
+ mock_create .assert_called_once ()
414
449
415
- # @patch("mcpgateway.main.tool_service.get_tool")
416
- # def test_get_tool_endpoint(self, mock_get, test_client, auth_headers):
417
- # """Test retrieving a specific tool."""
418
- # mock_tool = MagicMock( )
419
- # mock_tool.to_dict.return_value = MOCK_TOOL_READ
420
- # mock_get.return_value = mock_tool
450
+ @patch ("mcpgateway.main.tool_service.get_tool" )
451
+ def test_get_tool_endpoint (self , mock_get , test_client , auth_headers ):
452
+ mock_get . return_value = MOCK_TOOL_READ_SNAKE
453
+ response = test_client . get ( "/tools/1" , headers = auth_headers )
454
+ assert response . status_code == 200
455
+ mock_get .assert_called_once ()
421
456
422
- # response = test_client.get("/tools/1", headers=auth_headers)
423
- # assert response.status_code == 200
424
- # mock_get.assert_called_once()
425
-
426
- # @patch("mcpgateway.main.tool_service.update_tool")
427
- # def test_update_tool_endpoint(self, mock_update, test_client, auth_headers):
428
- # """Test updating an existing tool."""
429
- # mock_update.return_value = MagicMock()
430
- # mock_update.return_value.model_dump.return_value = MOCK_TOOL_READ
431
- # req = {"description": "Updated description"}
432
- # response = test_client.put("/tools/1", json=req, headers=auth_headers)
433
- # assert response.status_code == 200
434
- # mock_update.assert_called_once()
457
+ @patch ("mcpgateway.main.tool_service.update_tool" )
458
+ def test_update_tool_endpoint (self , mock_update , test_client , auth_headers ):
459
+ updated = {** MOCK_TOOL_READ_SNAKE , "description" : "Updated description" }
460
+ mock_update .return_value = updated
461
+ req = {"description" : "Updated description" }
462
+ response = test_client .put ("/tools/1" , json = req , headers = auth_headers )
463
+ assert response .status_code == 200
464
+ mock_update .assert_called_once ()
435
465
436
466
@patch ("mcpgateway.main.tool_service.toggle_tool_status" )
437
467
def test_toggle_tool_status (self , mock_toggle , test_client , auth_headers ):
@@ -554,15 +584,17 @@ def test_list_prompts_endpoint(self, mock_list_prompts, test_client, auth_header
554
584
assert len (data ) == 1
555
585
mock_list_prompts .assert_called_once ()
556
586
557
- # @patch("mcpgateway.main.prompt_service.register_prompt")
558
- # def test_create_prompt_endpoint(self, mock_create, test_client, auth_headers):
559
- # """Test creating a new prompt template."""
560
- # mock_create.return_value = MagicMock()
561
- # mock_create.return_value.model_dump.return_value = MOCK_PROMPT_READ
562
- # req = {"name": "test_prompt", "template": "Hello {name}", "description": "A test prompt"}
563
- # response = test_client.post("/prompts/", json=req, headers=auth_headers)
564
- # assert response.status_code == 200
565
- # mock_create.assert_called_once()
587
+ @patch ("mcpgateway.main.prompt_service.register_prompt" )
588
+ def test_create_prompt_endpoint (self , mock_create , test_client , auth_headers ):
589
+ """Test creating a new prompt template."""
590
+ # Return an actual model instance
591
+ mock_create .return_value = PromptRead (** MOCK_PROMPT_READ )
592
+
593
+ req = {"name" : "test_prompt" , "template" : "Hello {name}" , "description" : "A test prompt" }
594
+ response = test_client .post ("/prompts/" , json = req , headers = auth_headers )
595
+
596
+ assert response .status_code == 200
597
+ mock_create .assert_called_once ()
566
598
567
599
@patch ("mcpgateway.main.prompt_service.get_prompt" )
568
600
def test_get_prompt_with_args (self , mock_get , test_client , auth_headers ):
@@ -586,15 +618,17 @@ def test_get_prompt_no_args(self, mock_get, test_client, auth_headers):
586
618
assert response .status_code == 200
587
619
mock_get .assert_called_once_with (ANY , "test" , {})
588
620
589
- # @patch("mcpgateway.main.prompt_service.update_prompt")
590
- # def test_update_prompt_endpoint(self, mock_update, test_client, auth_headers):
591
- # """Test updating an existing prompt."""
592
- # mock_update.return_value = MagicMock()
593
- # mock_update.return_value.model_dump.return_value = MOCK_PROMPT_READ
594
- # req = {"description": "Updated description"}
595
- # response = test_client.put("/prompts/test_prompt", json=req, headers=auth_headers)
596
- # assert response.status_code == 200
597
- # mock_update.assert_called_once()
621
+ @patch ("mcpgateway.main.prompt_service.update_prompt" )
622
+ def test_update_prompt_endpoint (self , mock_update , test_client , auth_headers ):
623
+ """Test updating an existing prompt."""
624
+ updated = {** MOCK_PROMPT_READ , "description" : "Updated description" }
625
+ mock_update .return_value = PromptRead (** updated ) # <- real model
626
+
627
+ req = {"description" : "Updated description" }
628
+ response = test_client .put ("/prompts/test_prompt" , json = req , headers = auth_headers )
629
+
630
+ assert response .status_code == 200
631
+ mock_update .assert_called_once ()
598
632
599
633
@patch ("mcpgateway.main.prompt_service.delete_prompt" )
600
634
def test_delete_prompt_endpoint (self , mock_delete , test_client , auth_headers ):
0 commit comments