We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/shameerampcome/servicenow-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""
Tests for the ServiceNow MCP catalog tools.
"""
import unittest
from unittest.mock import MagicMock, patch
import requests
from servicenow_mcp.auth.auth_manager import AuthManager
from servicenow_mcp.tools.catalog_tools import (
GetCatalogItemParams,
ListCatalogCategoriesParams,
ListCatalogItemsParams,
CreateCatalogCategoryParams,
UpdateCatalogCategoryParams,
MoveCatalogItemsParams,
get_catalog_item,
get_catalog_item_variables,
list_catalog_categories,
list_catalog_items,
create_catalog_category,
update_catalog_category,
move_catalog_items,
)
from servicenow_mcp.utils.config import AuthConfig, AuthType, BasicAuthConfig, ServerConfig
class TestCatalogTools(unittest.TestCase):
"""Test cases for the catalog tools."""
def setUp(self):
"""Set up test fixtures."""
# Create a mock server config
self.config = ServerConfig(
instance_url="https://example.service-now.com",
auth=AuthConfig(
type=AuthType.BASIC,
basic=BasicAuthConfig(username="admin", password="password"),
),
)
# Create a mock auth manager
self.auth_manager = MagicMock(spec=AuthManager)
self.auth_manager.get_headers.return_value = {"Authorization": "Basic YWRtaW46cGFzc3dvcmQ="}
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_list_catalog_items(self, mock_get):
"""Test listing catalog items."""
# Mock the response from ServiceNow
mock_response = MagicMock()
mock_response.json.return_value = {
"result": [
{
"sys_id": "item1",
"name": "Laptop",
"short_description": "Request a new laptop",
"category": "Hardware",
"price": "1000",
"picture": "laptop.jpg",
"active": "true",
"order": "100",
}
]
}
mock_response.raise_for_status = MagicMock()
mock_get.return_value = mock_response
# Call the function
params = ListCatalogItemsParams(
limit=10,
offset=0,
category="Hardware",
query="laptop",
active=True,
)
result = list_catalog_items(self.config, self.auth_manager, params)
# Check the result
self.assertTrue(result["success"])
self.assertEqual(len(result["items"]), 1)
self.assertEqual(result["items"][0]["name"], "Laptop")
self.assertEqual(result["items"][0]["category"], "Hardware")
# Check that the correct URL and parameters were used
mock_get.assert_called_once()
args, kwargs = mock_get.call_args
self.assertEqual(args[0], "https://example.service-now.com/api/now/table/sc_cat_item")
self.assertEqual(kwargs["params"]["sysparm_limit"], 10)
self.assertEqual(kwargs["params"]["sysparm_offset"], 0)
self.assertIn("sysparm_query", kwargs["params"])
self.assertIn("active=true", kwargs["params"]["sysparm_query"])
self.assertIn("category=Hardware", kwargs["params"]["sysparm_query"])
self.assertIn("short_descriptionLIKElaptop^ORnameLIKElaptop", kwargs["params"]["sysparm_query"])
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_list_catalog_items_error(self, mock_get):
"""Test listing catalog items with an error."""
# Mock the response from ServiceNow
mock_get.side_effect = requests.exceptions.RequestException("Error")
# Call the function
params = ListCatalogItemsParams(
limit=10,
offset=0,
)
result = list_catalog_items(self.config, self.auth_manager, params)
# Check the result
self.assertFalse(result["success"])
self.assertEqual(len(result["items"]), 0)
self.assertIn("Error", result["message"])
@patch("servicenow_mcp.tools.catalog_tools.get_catalog_item_variables")
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_get_catalog_item(self, mock_get, mock_get_variables):
"""Test getting a specific catalog item."""
# Mock the response from ServiceNow
mock_response = MagicMock()
mock_response.json.return_value = {
"result": {
"sys_id": "item1",
"name": "Laptop",
"short_description": "Request a new laptop",
"description": "Request a new laptop for work",
"category": "Hardware",
"price": "1000",
"picture": "laptop.jpg",
"active": "true",
"order": "100",
"delivery_time": "3 days",
"availability": "In Stock",
}
}
mock_response.raise_for_status = MagicMock()
mock_get.return_value = mock_response
# Mock the variables
mock_get_variables.return_value = [
{
"sys_id": "var1",
"name": "model",
"label": "Laptop Model",
"type": "string",
"mandatory": "true",
"default_value": "MacBook Pro",
"help_text": "Select the laptop model",
"order": "100",
}
]
# Call the function
params = GetCatalogItemParams(item_id="item1")
result = get_catalog_item(self.config, self.auth_manager, params)
# Check the result
self.assertTrue(result.success)
self.assertEqual(result.data["name"], "Laptop")
self.assertEqual(result.data["category"], "Hardware")
self.assertEqual(len(result.data["variables"]), 1)
self.assertEqual(result.data["variables"][0]["name"], "model")
# Check that the correct URL and parameters were used
mock_get.assert_called_once()
args, kwargs = mock_get.call_args
self.assertEqual(args[0], "https://example.service-now.com/api/now/table/sc_cat_item/item1")
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_get_catalog_item_not_found(self, mock_get):
"""Test getting a catalog item that doesn't exist."""
# Mock the response from ServiceNow
mock_response = MagicMock()
mock_response.json.return_value = {"result": {}}
mock_response.raise_for_status = MagicMock()
mock_get.return_value = mock_response
# Call the function
params = GetCatalogItemParams(item_id="nonexistent")
result = get_catalog_item(self.config, self.auth_manager, params)
# Check the result
self.assertFalse(result.success)
self.assertIn("not found", result.message)
self.assertIsNone(result.data)
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_get_catalog_item_error(self, mock_get):
"""Test getting a catalog item with an error."""
# Mock the response from ServiceNow
mock_get.side_effect = requests.exceptions.RequestException("Error")
# Call the function
params = GetCatalogItemParams(item_id="item1")
result = get_catalog_item(self.config, self.auth_manager, params)
# Check the result
self.assertFalse(result.success)
self.assertIn("Error", result.message)
self.assertIsNone(result.data)
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_get_catalog_item_variables(self, mock_get):
"""Test getting variables for a catalog item."""
# Mock the response from ServiceNow
mock_response = MagicMock()
mock_response.json.return_value = {
"result": [
{
"sys_id": "var1",
"name": "model",
"question_text": "Laptop Model",
"type": "string",
"mandatory": "true",
"default_value": "MacBook Pro",
"help_text": "Select the laptop model",
"order": "100",
}
]
}
mock_response.raise_for_status = MagicMock()
mock_get.return_value = mock_response
# Call the function
result = get_catalog_item_variables(self.config, self.auth_manager, "item1")
# Check the result
self.assertEqual(len(result), 1)
self.assertEqual(result[0]["name"], "model")
self.assertEqual(result[0]["label"], "Laptop Model")
self.assertEqual(result[0]["type"], "string")
# Check that the correct URL and parameters were used
mock_get.assert_called_once()
args, kwargs = mock_get.call_args
self.assertEqual(args[0], "https://example.service-now.com/api/now/table/item_option_new")
self.assertEqual(kwargs["params"]["sysparm_query"], "cat_item=item1^ORDERBYorder")
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_get_catalog_item_variables_error(self, mock_get):
"""Test getting variables for a catalog item with an error."""
# Mock the response from ServiceNow
mock_get.side_effect = requests.exceptions.RequestException("Error")
# Call the function
result = get_catalog_item_variables(self.config, self.auth_manager, "item1")
# Check the result
self.assertEqual(len(result), 0)
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_list_catalog_categories(self, mock_get):
"""Test listing catalog categories."""
# Mock the response from ServiceNow
mock_response = MagicMock()
mock_response.json.return_value = {
"result": [
{
"sys_id": "cat1",
"title": "Hardware",
"description": "Hardware requests",
"parent": "",
"icon": "hardware.png",
"active": "true",
"order": "100",
}
]
}
mock_response.raise_for_status = MagicMock()
mock_get.return_value = mock_response
# Call the function
params = ListCatalogCategoriesParams(
limit=10,
offset=0,
query="hardware",
active=True,
)
result = list_catalog_categories(self.config, self.auth_manager, params)
# Check the result
self.assertTrue(result["success"])
self.assertEqual(len(result["categories"]), 1)
self.assertEqual(result["categories"][0]["title"], "Hardware")
self.assertEqual(result["categories"][0]["description"], "Hardware requests")
# Check that the correct URL and parameters were used
mock_get.assert_called_once()
args, kwargs = mock_get.call_args
self.assertEqual(args[0], "https://example.service-now.com/api/now/table/sc_category")
self.assertEqual(kwargs["params"]["sysparm_limit"], 10)
self.assertEqual(kwargs["params"]["sysparm_offset"], 0)
self.assertIn("sysparm_query", kwargs["params"])
self.assertIn("active=true", kwargs["params"]["sysparm_query"])
self.assertIn("titleLIKEhardware^ORdescriptionLIKEhardware", kwargs["params"]["sysparm_query"])
@patch("servicenow_mcp.tools.catalog_tools.requests.get")
def test_list_catalog_categories_error(self, mock_get):
"""Test listing catalog categories with an error."""
# Mock the response from ServiceNow
mock_get.side_effect = requests.exceptions.RequestException("Error")
# Call the function
params = ListCatalogCategoriesParams(
limit=10,
offset=0,
)
result = list_catalog_categories(self.config, self.auth_manager, params)
# Check the result
self.assertFalse(result["success"])
self.assertEqual(len(result["categories"]), 0)
self.assertIn("Error", result["message"])
@patch("requests.post")
def test_create_catalog_category(self, mock_post):
"""Test creating a catalog category."""
# Mock response
mock_response = MagicMock()
mock_response.json.return_value = {
"result": {
"sys_id": "test_sys_id",
"title": "Test Category",
"description": "Test Description",
"parent": "",
"icon": "icon-test",
"active": "true",
"order": "100",
}
}
mock_post.return_value = mock_response
# Create params
params = CreateCatalogCategoryParams(
title="Test Category",
description="Test Description",
icon="icon-test",
active=True,
order=100,
)
# Call function
result = create_catalog_category(self.config, self.auth_manager, params)
# Verify result
self.assertTrue(result.success)
self.assertEqual(result.data["title"], "Test Category")
self.assertEqual(result.data["sys_id"], "test_sys_id")
# Verify request
mock_post.assert_called_once()
args, kwargs = mock_post.call_args
self.assertEqual(args[0], "https://example.service-now.com/api/now/table/sc_category")
self.assertEqual(kwargs["json"]["title"], "Test Category")
self.assertEqual(kwargs["json"]["description"], "Test Description")
@patch("requests.patch")
def test_update_catalog_category(self, mock_patch):
"""Test updating a catalog category."""
# Mock response
mock_response = MagicMock()
mock_response.json.return_value = {
"result": {
"sys_id": "test_sys_id",
"title": "Updated Category",
"description": "Updated Description",
"parent": "",
"icon": "icon-test",
"active": "true",
"order": "200",
}
}
mock_patch.return_value = mock_response
# Create params
params = UpdateCatalogCategoryParams(
category_id="test_sys_id",
title="Updated Category",
description="Updated Description",
order=200,
)
# Call function
result = update_catalog_category(self.config, self.auth_manager, params)
# Verify result
self.assertTrue(result.success)
self.assertEqual(result.data["title"], "Updated Category")
self.assertEqual(result.data["description"], "Updated Description")
self.assertEqual(result.data["order"], "200")
# Verify request
mock_patch.assert_called_once()
args, kwargs = mock_patch.call_args
self.assertEqual(args[0], "https://example.service-now.com/api/now/table/sc_category/test_sys_id")
self.assertEqual(kwargs["json"]["title"], "Updated Category")
self.assertEqual(kwargs["json"]["description"], "Updated Description")
self.assertEqual(kwargs["json"]["order"], "200")
@patch("requests.patch")
def test_move_catalog_items(self, mock_patch):
"""Test moving catalog items."""
# Mock response
mock_response = MagicMock()
mock_response.json.return_value = {"result": {"sys_id": "item_id", "category": "target_category_id"}}
mock_patch.return_value = mock_response
# Create params
params = MoveCatalogItemsParams(
item_ids=["item1", "item2", "item3"],
target_category_id="target_category_id",
)
# Call function
result = move_catalog_items(self.config, self.auth_manager, params)
# Verify result
self.assertTrue(result.success)
self.assertEqual(result.data["moved_items_count"], 3)
# Verify request
self.assertEqual(mock_patch.call_count, 3)
for i, call in enumerate(mock_patch.call_args_list):
args, kwargs = call
self.assertEqual(
args[0],
f"https://example.service-now.com/api/now/table/sc_cat_item/{params.item_ids[i]}"
)
self.assertEqual(kwargs["json"]["category"], "target_category_id")
if __name__ == "__main__":
unittest.main()