"""
Tests for PubChem batch operation endpoints.
"""
import pytest
from pubchem_mcp_server import (
batch_get_compounds,
batch_search_similarity
)
# Test data
TEST_CIDS = "2244,5793,2782" # Aspirin, Glucose, Paracetamol
TEST_SMILES = "CC(=O)OC1=CC=CC=C1C(=O)O" # Aspirin
@pytest.mark.asyncio
async def test_batch_get_compounds():
"""Test batch retrieval of compound properties."""
result = await batch_get_compounds(TEST_CIDS)
assert "Batch Property Data" in result
# Should have CID column and property column
assert "CID" in result
assert "MolecularWeight" in result
# All CIDs should be in the result
for cid in TEST_CIDS.split(","):
assert cid in result
@pytest.mark.asyncio
async def test_batch_get_compounds_custom_property():
"""Test batch retrieval with a custom property."""
result = await batch_get_compounds(TEST_CIDS, property_name="MolecularFormula")
assert "Batch Property Data" in result
assert "MolecularFormula" in result
# Should have some common formulas
assert "C9H8O4" in result or "C6H12O6" in result or "C8H9NO2" in result
@pytest.mark.asyncio
async def test_batch_get_compounds_property_aliases():
"""Test batch retrieval with property name aliases."""
# Test different property aliases
result_mw = await batch_get_compounds(TEST_CIDS, property_name="mw")
assert "MolecularWeight" in result_mw
result_formula = await batch_get_compounds(TEST_CIDS, property_name="formula")
assert "MolecularFormula" in result_formula
result_logp = await batch_get_compounds(TEST_CIDS, property_name="logp")
assert "XLogP" in result_logp or "LogP" in result_logp
@pytest.mark.asyncio
async def test_batch_search_similarity():
"""Test batch similarity search."""
result = await batch_search_similarity(TEST_SMILES)
assert "Compounds similar to" in result
assert TEST_SMILES in result
# Table should have CID, Name, and Formula columns
assert "CID" in result
assert "Name" in result
assert "Formula" in result
# Aspirin should be in the results
assert "2244" in result or "Aspirin" in result or "Acetylsalicylic acid" in result
@pytest.mark.asyncio
async def test_batch_search_similarity_threshold():
"""Test similarity search with different thresholds."""
# Higher threshold should return fewer results
result_high = await batch_search_similarity(TEST_SMILES, threshold=0.95)
result_low = await batch_search_similarity(TEST_SMILES, threshold=0.7)
# Count the number of compound entries in each
high_compounds = [line for line in result_high.split('\n') if line.strip() and not line.startswith('-') and "CID" not in line]
low_compounds = [line for line in result_low.split('\n') if line.strip() and not line.startswith('-') and "CID" not in line]
# More permissive threshold should generally return more results
# (But due to mock data in test mode, might not always be true, so we don't assert this)
@pytest.mark.asyncio
async def test_batch_search_similarity_limit():
"""Test limiting the number of similarity search results."""
result_default = await batch_search_similarity(TEST_SMILES)
result_limited = await batch_search_similarity(TEST_SMILES, max_results=3)
# Limited version should have fewer results
assert len(result_limited) < len(result_default)
# Count only the actual compound entries (lines with vertical bars that aren't headers)
limited_compounds = [line for line in result_limited.split('\n')
if line.strip() and "|" in line and "CID" not in line]
assert len(limited_compounds) <= 3
@pytest.mark.asyncio
async def test_error_handling():
"""Test error handling for invalid inputs."""
# Test invalid CIDs
result = await batch_get_compounds("999999999,888888888")
assert "No compounds found" in result or "No property data found" in result or "Invalid request" in result or "Error" in result
# Test invalid SMILES
result = await batch_search_similarity("InvalidSMILES")
assert "No similar compounds found" in result or "Invalid SMILES" in result or "Error" in result