Testing update
This commit is contained in:
@@ -0,0 +1 @@
|
||||
"""End-to-end tests for MCP tools."""
|
||||
@@ -0,0 +1,72 @@
|
||||
"""
|
||||
Fast E2E smoke tests for MCP tools (<30 seconds).
|
||||
|
||||
These tests make MINIMAL real API calls to verify the service is working.
|
||||
For comprehensive E2E testing, see test_mcp_tools_comprehensive.py
|
||||
|
||||
Target: Complete in <30 seconds
|
||||
"""
|
||||
import json
|
||||
import pytest
|
||||
from nadlan_mcp.fastmcp_server import (
|
||||
autocomplete_address,
|
||||
find_recent_deals_for_address,
|
||||
get_street_deals,
|
||||
get_deals_by_radius,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
class TestMCPToolsSmokeTests:
|
||||
"""Minimal E2E smoke tests to verify API connectivity."""
|
||||
|
||||
# Known working data
|
||||
TEST_ADDRESS = "סוקולוב 38 חולון"
|
||||
TEST_POLYGON_ID = "52385050"
|
||||
TEST_LAT = 3766290.19
|
||||
TEST_LON = 3870928.84
|
||||
|
||||
def test_autocomplete_works(self):
|
||||
"""Smoke test: Autocomplete returns results."""
|
||||
result = autocomplete_address("חולון")
|
||||
data = json.loads(result)
|
||||
|
||||
assert isinstance(data, list)
|
||||
assert len(data) > 0
|
||||
assert "text" in data[0]
|
||||
|
||||
def test_get_street_deals_works(self):
|
||||
"""Smoke test: Can fetch street deals."""
|
||||
# Use small limit for speed
|
||||
result = get_street_deals(self.TEST_POLYGON_ID, limit=5, deal_type=2)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_deals" in data
|
||||
assert data["total_deals"] > 0
|
||||
assert "deals" in data
|
||||
|
||||
def test_get_deals_by_radius_works(self):
|
||||
"""Smoke test: Can fetch polygon metadata by radius."""
|
||||
# Use small radius for speed
|
||||
result = get_deals_by_radius(self.TEST_LAT, self.TEST_LON, radius_meters=100)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_polygons" in data
|
||||
assert data["total_polygons"] > 0
|
||||
|
||||
def test_find_recent_deals_minimal(self):
|
||||
"""Smoke test: Main tool works with minimal data."""
|
||||
# Use very small limits to speed up
|
||||
result = find_recent_deals_for_address(
|
||||
self.TEST_ADDRESS,
|
||||
years_back=1,
|
||||
radius_meters=30,
|
||||
max_deals=10
|
||||
)
|
||||
data = json.loads(result)
|
||||
|
||||
# Just verify structure, don't check counts
|
||||
assert "search_parameters" in data
|
||||
assert "market_statistics" in data
|
||||
assert "deals" in data
|
||||
assert isinstance(data["deals"], list)
|
||||
@@ -0,0 +1,185 @@
|
||||
"""
|
||||
End-to-end tests for all MCP tools.
|
||||
|
||||
These tests make real API calls to verify the complete functionality
|
||||
of each MCP tool from end to end.
|
||||
|
||||
Mark as integration tests since they hit real APIs.
|
||||
"""
|
||||
import json
|
||||
import pytest
|
||||
from nadlan_mcp.fastmcp_server import (
|
||||
autocomplete_address,
|
||||
find_recent_deals_for_address,
|
||||
analyze_market_trends,
|
||||
get_valuation_comparables,
|
||||
get_deal_statistics,
|
||||
get_market_activity_metrics,
|
||||
compare_addresses,
|
||||
get_street_deals,
|
||||
get_neighborhood_deals,
|
||||
get_deals_by_radius,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
class TestMCPToolsE2E:
|
||||
"""End-to-end tests for all 10 MCP tools."""
|
||||
|
||||
# Test addresses
|
||||
TEST_ADDRESS_1 = "סוקולוב 38 חולון"
|
||||
TEST_ADDRESS_2 = "דיזנגוף 50 תל אביב"
|
||||
TEST_POLYGON_ID = "52385050" # Known polygon with data
|
||||
# ITM coordinates for Holon (lat, lon format for MCP tool)
|
||||
TEST_LAT = 3766290.19
|
||||
TEST_LON = 3870928.84
|
||||
|
||||
def test_autocomplete_address(self):
|
||||
"""Test address autocomplete returns results."""
|
||||
result = autocomplete_address("חולון סוקולוב")
|
||||
data = json.loads(result)
|
||||
|
||||
assert isinstance(data, list)
|
||||
assert len(data) > 0
|
||||
|
||||
# Check first result has expected structure
|
||||
first = data[0]
|
||||
assert "text" in first
|
||||
assert "coordinates" in first or "id" in first
|
||||
|
||||
def test_find_recent_deals_for_address(self):
|
||||
"""Test finding recent deals for an address."""
|
||||
result = find_recent_deals_for_address(self.TEST_ADDRESS_1, max_deals=100)
|
||||
data = json.loads(result)
|
||||
|
||||
# Check response structure
|
||||
assert "search_parameters" in data
|
||||
assert "market_statistics" in data
|
||||
assert "deals" in data
|
||||
|
||||
# Verify some deals were found
|
||||
assert isinstance(data["deals"], list)
|
||||
assert len(data["deals"]) > 0
|
||||
|
||||
# Check deal structure
|
||||
deal = data["deals"][0]
|
||||
assert "deal_amount" in deal
|
||||
assert "deal_date" in deal
|
||||
assert "settlement_name_heb" in deal
|
||||
|
||||
def test_analyze_market_trends(self):
|
||||
"""Test market trend analysis."""
|
||||
result = analyze_market_trends(
|
||||
self.TEST_ADDRESS_1, years_back=3, radius_meters=100
|
||||
)
|
||||
data = json.loads(result)
|
||||
|
||||
# Check response structure
|
||||
assert "market_summary" in data
|
||||
assert "total_deals" in data["market_summary"]
|
||||
assert isinstance(data["market_summary"]["total_deals"], int)
|
||||
assert data["market_summary"]["total_deals"] >= 0
|
||||
|
||||
def test_get_valuation_comparables(self):
|
||||
"""Test getting valuation comparables."""
|
||||
result = get_valuation_comparables(
|
||||
self.TEST_ADDRESS_1,
|
||||
years_back=3,
|
||||
min_rooms=3.0,
|
||||
max_rooms=5.0
|
||||
)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_comparables" in data
|
||||
assert isinstance(data["total_comparables"], int)
|
||||
assert data["total_comparables"] >= 0
|
||||
|
||||
if data["total_comparables"] > 0:
|
||||
assert "comparables" in data
|
||||
comp = data["comparables"][0]
|
||||
assert "deal_amount" in comp
|
||||
assert "asset_room_num" in comp
|
||||
|
||||
def test_get_deal_statistics(self):
|
||||
"""Test deal statistics calculation."""
|
||||
result = get_deal_statistics(self.TEST_ADDRESS_1, years_back=3)
|
||||
data = json.loads(result)
|
||||
|
||||
# Check response structure
|
||||
assert "statistics" in data
|
||||
if "sample_size" in data["statistics"]:
|
||||
assert isinstance(data["statistics"]["sample_size"], int)
|
||||
assert data["statistics"]["sample_size"] >= 0
|
||||
|
||||
def test_get_market_activity_metrics(self):
|
||||
"""Test market activity metrics."""
|
||||
result = get_market_activity_metrics(self.TEST_ADDRESS_1, years_back=3)
|
||||
data = json.loads(result)
|
||||
|
||||
# Check response structure
|
||||
assert "market_activity" in data
|
||||
if data["market_activity"] is not None:
|
||||
assert "activity_score" in data["market_activity"]
|
||||
|
||||
def test_compare_addresses(self):
|
||||
"""Test comparing multiple addresses."""
|
||||
result = compare_addresses([self.TEST_ADDRESS_1, self.TEST_ADDRESS_2])
|
||||
data = json.loads(result)
|
||||
|
||||
assert isinstance(data, dict)
|
||||
assert "addresses_compared" in data
|
||||
assert "all_results" in data
|
||||
|
||||
def test_get_street_deals(self):
|
||||
"""Test getting street-level deals."""
|
||||
result = get_street_deals(self.TEST_POLYGON_ID, limit=100, deal_type=2)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_deals" in data
|
||||
assert isinstance(data["total_deals"], int)
|
||||
assert data["total_deals"] > 0 # Known polygon should have deals
|
||||
|
||||
assert "deals" in data
|
||||
assert len(data["deals"]) > 0
|
||||
|
||||
# Check deal structure
|
||||
deal = data["deals"][0]
|
||||
assert "deal_amount" in deal
|
||||
assert "deal_date" in deal
|
||||
|
||||
def test_get_neighborhood_deals(self):
|
||||
"""Test getting neighborhood-level deals."""
|
||||
result = get_neighborhood_deals(self.TEST_POLYGON_ID, limit=100, deal_type=2)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_deals" in data
|
||||
assert isinstance(data["total_deals"], int)
|
||||
assert data["total_deals"] > 0 # Known polygon should have deals
|
||||
|
||||
assert "deals" in data
|
||||
assert len(data["deals"]) > 0
|
||||
|
||||
def test_get_deals_by_radius(self):
|
||||
"""Test getting polygon metadata by radius."""
|
||||
result = get_deals_by_radius(self.TEST_LAT, self.TEST_LON, radius_meters=500)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_polygons" in data
|
||||
assert isinstance(data["total_polygons"], int)
|
||||
assert data["total_polygons"] > 0 # Known coords should have polygons
|
||||
|
||||
assert "polygons" in data
|
||||
assert len(data["polygons"]) > 0
|
||||
|
||||
# Check polygon metadata structure
|
||||
polygon = data["polygons"][0]
|
||||
assert "polygon_id" in polygon or "objectid" in polygon
|
||||
|
||||
def test_get_deals_by_radius_no_results(self):
|
||||
"""Test get_deals_by_radius with coords that have no data."""
|
||||
# Use coordinates unlikely to have data
|
||||
result = get_deals_by_radius(37.66, 38.71, radius_meters=10)
|
||||
|
||||
# Should return a message string, not JSON
|
||||
assert isinstance(result, str)
|
||||
assert "No polygons found" in result or "total_polygons" in result
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
[
|
||||
{
|
||||
"text": "סוקולוב חולון",
|
||||
"id": "street|STREET_MID_POINT|40087",
|
||||
"type": "street",
|
||||
"score": 1658.0989,
|
||||
"coordinates": {
|
||||
"longitude": 3871467.9873431968,
|
||||
"latitude": 3766276.9742487124
|
||||
},
|
||||
"shape": "POINT(3871467.9873431968 3766276.9742487124)"
|
||||
},
|
||||
{
|
||||
"text": "קופת חולים - לאומית סוקולוב חולון",
|
||||
"id": "institutes|POI_BLDG|71871",
|
||||
"type": "institutes",
|
||||
"score": 1095.5675,
|
||||
"coordinates": {
|
||||
"longitude": 3871143.6159368134,
|
||||
"latitude": 3766329.3192062005
|
||||
},
|
||||
"shape": "POINT(3871143.6159368134 3766329.3192062005)"
|
||||
},
|
||||
{
|
||||
"text": "קופת חולים - לאומית סוקולוב חולון",
|
||||
"id": "poi|POI_MID_POINT|102233",
|
||||
"type": "poi",
|
||||
"score": 1099.5448,
|
||||
"coordinates": {
|
||||
"longitude": 3871143.6159681133,
|
||||
"latitude": 3766329.319199102
|
||||
},
|
||||
"shape": "POINT(3871143.6159681133 3766329.319199102)"
|
||||
}
|
||||
]
|
||||
+332
@@ -0,0 +1,332 @@
|
||||
[
|
||||
{
|
||||
"objectid": 1969420,
|
||||
"deal_amount": 1600000.0,
|
||||
"deal_date": "2025-09-11",
|
||||
"asset_area": 61.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870720.4640780594 3766261.471274853,3870704.822454856 3766280.494942658,3870715.8743646624 3766289.5618421077,3870731.3745853226 3766270.5375762666,3870720.4640780594 3766261.471274853)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000721,
|
||||
"streetNameHeb": "בילינסון",
|
||||
"streetNameEng": "Belinson",
|
||||
"houseNum": 6,
|
||||
"floorNo": "רביעית",
|
||||
"dealId": 3633677206,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 3,
|
||||
"gushNum": 7172,
|
||||
"parcelNum": 235,
|
||||
"subParcelNum": 11,
|
||||
"polygonId": "52995209",
|
||||
"price_per_sqm": 26229.51
|
||||
},
|
||||
{
|
||||
"objectid": 1968034,
|
||||
"deal_amount": 1800000.0,
|
||||
"deal_date": "2025-08-21",
|
||||
"asset_area": 51.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3871546.267254118 3766046.2332329005,3871519.7450213963 3766048.8632871644,3871520.755660357 3766058.564386736,3871529.006896269 3766057.780093892,3871529.5742626246 3766063.3353820755,3871547.727459817 3766061.4891484776,3871546.267254118 3766046.2332329005)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000415,
|
||||
"streetNameHeb": "חנקין",
|
||||
"streetNameEng": "Hankin",
|
||||
"houseNum": 62,
|
||||
"floorNo": "שניה",
|
||||
"dealId": 3632991008,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 3,
|
||||
"gushNum": 7170,
|
||||
"parcelNum": 91,
|
||||
"subParcelNum": 8,
|
||||
"polygonId": "52487416",
|
||||
"price_per_sqm": 35294.12
|
||||
},
|
||||
{
|
||||
"objectid": 1972678,
|
||||
"deal_amount": 2170000.0,
|
||||
"deal_date": "2025-08-20",
|
||||
"asset_area": 90.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870461.085939886 3765412.661079392,3870461.8556948095 3765419.4469509623,3870454.5119660264 3765416.0582189877,3870449.8311605644 3765416.7315218183,3870448.8832249534 3765412.6281236825,3870444.1110105794 3765413.266600847,3870448.3403304657 3765432.7404882894,3870508.9368100218 3765424.106078474,3870506.5193002103 3765406.631910944,3870482.4682015995 3765409.8236224824,3870476.137660146 3765410.663707863,3870461.085939886 3765412.661079392)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000720,
|
||||
"streetNameHeb": "לאון בלום",
|
||||
"streetNameEng": "L?on Blum",
|
||||
"houseNum": 64,
|
||||
"floorNo": "שניה",
|
||||
"dealId": 3633156134,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 4,
|
||||
"gushNum": 7176,
|
||||
"parcelNum": 9,
|
||||
"subParcelNum": 59,
|
||||
"polygonId": "52202717",
|
||||
"price_per_sqm": 24111.11
|
||||
},
|
||||
{
|
||||
"objectid": 1967412,
|
||||
"deal_amount": 2050000.0,
|
||||
"deal_date": "2025-08-14",
|
||||
"asset_area": 95.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3871347.8555616946 3766162.0722470563,3871334.99564493 3766163.205144352,3871336.9037298146 3766187.3432294633,3871349.869159977 3766186.35283101,3871347.8555616946 3766162.0722470563)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000443,
|
||||
"streetNameHeb": "שפרינצק",
|
||||
"streetNameEng": "Sprinzak",
|
||||
"houseNum": 29,
|
||||
"floorNo": "שניה",
|
||||
"dealId": 3632926686,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 4,
|
||||
"gushNum": 7170,
|
||||
"parcelNum": 28,
|
||||
"subParcelNum": 6,
|
||||
"polygonId": "53339618",
|
||||
"price_per_sqm": 21578.95
|
||||
},
|
||||
{
|
||||
"objectid": 1972438,
|
||||
"deal_amount": 2057000.0,
|
||||
"deal_date": "2025-08-13",
|
||||
"asset_area": 70.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870628.707375865 3765928.3916899217,3870616.197248105 3765933.4442600156,3870624.479632951 3765954.33986368,3870628.9524073373 3765952.58190368,3870629.4304386983 3765953.8507194677,3870634.044605639 3765952.0933281765,3870632.98273369 3765949.4960702136,3870635.237077585 3765948.5461212373,3870632.1913898066 3765941.121957529,3870633.501643529 3765940.5352417007,3870628.707375865 3765928.3916899217)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000720,
|
||||
"streetNameHeb": "לאון בלום",
|
||||
"streetNameEng": "L?on Blum",
|
||||
"houseNum": 23,
|
||||
"floorNo": null,
|
||||
"dealId": 3633759218,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 3,
|
||||
"gushNum": 7176,
|
||||
"parcelNum": 23,
|
||||
"subParcelNum": 2,
|
||||
"polygonId": "52475840",
|
||||
"price_per_sqm": 29385.71
|
||||
},
|
||||
{
|
||||
"objectid": 1972437,
|
||||
"deal_amount": 2207000.0,
|
||||
"deal_date": "2025-08-13",
|
||||
"asset_area": 78.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870628.707375865 3765928.3916899217,3870616.197248105 3765933.4442600156,3870624.479632951 3765954.33986368,3870628.9524073373 3765952.58190368,3870629.4304386983 3765953.8507194677,3870634.044605639 3765952.0933281765,3870632.98273369 3765949.4960702136,3870635.237077585 3765948.5461212373,3870632.1913898066 3765941.121957529,3870633.501643529 3765940.5352417007,3870628.707375865 3765928.3916899217)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000720,
|
||||
"streetNameHeb": "לאון בלום",
|
||||
"streetNameEng": "L?on Blum",
|
||||
"houseNum": 23,
|
||||
"floorNo": null,
|
||||
"dealId": 3633751330,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 4,
|
||||
"gushNum": 7176,
|
||||
"parcelNum": 23,
|
||||
"subParcelNum": 2,
|
||||
"polygonId": "52475840",
|
||||
"price_per_sqm": 28294.87
|
||||
},
|
||||
{
|
||||
"objectid": 1967707,
|
||||
"deal_amount": 1400000.0,
|
||||
"deal_date": "2025-08-12",
|
||||
"asset_area": 74.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3871406.5046315272 3766032.4932356784,3871393.876109203 3766033.069669732,3871395.3254547855 3766060.893880203,3871408.6494925357 3766060.5448129214,3871406.5046315272 3766032.4932356784)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000503,
|
||||
"streetNameHeb": "ביאליק",
|
||||
"streetNameEng": "Bialik",
|
||||
"houseNum": 8,
|
||||
"floorNo": "שניה",
|
||||
"dealId": 3633004406,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 3,
|
||||
"gushNum": 7170,
|
||||
"parcelNum": 57,
|
||||
"subParcelNum": 6,
|
||||
"polygonId": "64907781",
|
||||
"price_per_sqm": 18918.92
|
||||
},
|
||||
{
|
||||
"objectid": 1971495,
|
||||
"deal_amount": 1000000.0,
|
||||
"deal_date": "2025-08-07",
|
||||
"asset_area": 82.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3871176.244711883 3765574.7175676874,3871108.214092787 3765583.100809277,3871109.35308285 3765593.027038448,3871177.5128026525 3765584.7863754295,3871176.244711883 3765574.7175676874)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "HOLON",
|
||||
"streetCode": 66000304,
|
||||
"streetNameHeb": "ההסתדרות",
|
||||
"streetNameEng": "HaHistadrut",
|
||||
"houseNum": 60,
|
||||
"floorNo": "ראשונה",
|
||||
"dealId": 3632654898,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 4,
|
||||
"gushNum": 7174,
|
||||
"parcelNum": 199,
|
||||
"subParcelNum": 27,
|
||||
"polygonId": "52506738",
|
||||
"price_per_sqm": 12195.12
|
||||
},
|
||||
{
|
||||
"objectid": 1969515,
|
||||
"deal_amount": 3000000.0,
|
||||
"deal_date": "2025-08-06",
|
||||
"asset_area": 117.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870582.7778358534 3766007.818947901,3870555.75388674 3766020.9588606944,3870560.5454790723 3766030.81737579,3870587.5814648867 3766017.6182896625,3870582.7778358534 3766007.818947901)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000721,
|
||||
"streetNameHeb": "בילינסון",
|
||||
"streetNameEng": "Belinson",
|
||||
"houseNum": 35,
|
||||
"floorNo": "מרתף+",
|
||||
"dealId": 3632769506,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 5,
|
||||
"gushNum": 7172,
|
||||
"parcelNum": 55,
|
||||
"subParcelNum": 2,
|
||||
"polygonId": "52469890",
|
||||
"price_per_sqm": 25641.03
|
||||
},
|
||||
{
|
||||
"objectid": 1967553,
|
||||
"deal_amount": 3540000.0,
|
||||
"deal_date": "2025-08-04",
|
||||
"asset_area": 130.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3871283.98382443 3766041.272967665,3871272.3244377715 3766042.777610746,3871274.3714343957 3766058.5450168313,3871278.7452240535 3766057.970421447,3871282.8507001335 3766089.5882179793,3871278.6182943583 3766090.1633791463,3871280.9063065085 3766107.565754848,3871297.410878644 3766105.4883675845,3871296.839837455 3766100.8920923057,3871290.697705125 3766101.684622215,3871289.325197258 3766091.1650558305,3871293.4512298624 3766090.672348892,3871291.964111744 3766079.3353630104,3871299.8747903355 3766078.2657070043,3871298.260388772 3766066.3362180092,3871291.1870977194 3766067.2079217676,3871289.8131462242 3766057.05542465,3871286.0290623982 3766057.490289319,3871283.98382443 3766041.272967665)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": null,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000708,
|
||||
"streetNameHeb": "שנקר",
|
||||
"streetNameEng": "Shenkar",
|
||||
"houseNum": 55,
|
||||
"floorNo": "שניה",
|
||||
"dealId": 3632695759,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 5,
|
||||
"gushNum": 7170,
|
||||
"parcelNum": 44,
|
||||
"subParcelNum": 19,
|
||||
"polygonId": "52507812",
|
||||
"price_per_sqm": 27230.77
|
||||
}
|
||||
]
|
||||
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
[
|
||||
{
|
||||
"dealscount": "10",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7170-31",
|
||||
"objectid": 14248
|
||||
},
|
||||
{
|
||||
"dealscount": "6",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-19",
|
||||
"objectid": 14249
|
||||
},
|
||||
{
|
||||
"dealscount": "1",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-3",
|
||||
"objectid": 14301
|
||||
},
|
||||
{
|
||||
"dealscount": "14",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-212",
|
||||
"objectid": 14302
|
||||
},
|
||||
{
|
||||
"dealscount": "14",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-213",
|
||||
"objectid": 14303
|
||||
},
|
||||
{
|
||||
"dealscount": "57",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-128",
|
||||
"objectid": 14304
|
||||
},
|
||||
{
|
||||
"dealscount": "1",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-5",
|
||||
"objectid": 14305
|
||||
},
|
||||
{
|
||||
"dealscount": "3",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-216",
|
||||
"objectid": 14306
|
||||
},
|
||||
{
|
||||
"dealscount": "11",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-218",
|
||||
"objectid": 14314
|
||||
},
|
||||
{
|
||||
"dealscount": "1",
|
||||
"settlementNameHeb": "חולון",
|
||||
"streetNameHeb": null,
|
||||
"houseNum": null,
|
||||
"polygon_id": "7172-7",
|
||||
"objectid": 14315
|
||||
}
|
||||
]
|
||||
Vendored
+332
@@ -0,0 +1,332 @@
|
||||
[
|
||||
{
|
||||
"objectid": 1960644,
|
||||
"deal_amount": 200000.0,
|
||||
"deal_date": "2024-10-13",
|
||||
"asset_area": 20.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "בנין",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 32,
|
||||
"floorNo": "קרקע",
|
||||
"dealId": 3605441588,
|
||||
"dealNatureDescription": "חנות",
|
||||
"assetRoomNum": null,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 141,
|
||||
"subParcelNum": 5,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 10000.0
|
||||
},
|
||||
{
|
||||
"objectid": 1960654,
|
||||
"deal_amount": 892000.0,
|
||||
"deal_date": "2024-08-08",
|
||||
"asset_area": 69.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 34,
|
||||
"floorNo": "שניה",
|
||||
"dealId": 3603340277,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 3,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 142,
|
||||
"subParcelNum": 8,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 12927.54
|
||||
},
|
||||
{
|
||||
"objectid": 1960646,
|
||||
"deal_amount": 1650000.0,
|
||||
"deal_date": "2022-08-17",
|
||||
"asset_area": 59.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 32,
|
||||
"floorNo": "ראשונה",
|
||||
"dealId": 3547500052,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 2,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 141,
|
||||
"subParcelNum": 7,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 27966.1
|
||||
},
|
||||
{
|
||||
"objectid": 1960650,
|
||||
"deal_amount": 500000.0,
|
||||
"deal_date": "2019-03-03",
|
||||
"asset_area": 29.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "בנין",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 34,
|
||||
"floorNo": "קרקע",
|
||||
"dealId": 3453745430,
|
||||
"dealNatureDescription": "חנות",
|
||||
"assetRoomNum": null,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 142,
|
||||
"subParcelNum": 4,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 17241.38
|
||||
},
|
||||
{
|
||||
"objectid": 1960640,
|
||||
"deal_amount": 510000.0,
|
||||
"deal_date": "2016-12-06",
|
||||
"asset_area": 98.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "בנין",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 32,
|
||||
"floorNo": "מרתף",
|
||||
"dealId": 3375045810,
|
||||
"dealNatureDescription": "מחסנים",
|
||||
"assetRoomNum": null,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 141,
|
||||
"subParcelNum": 1,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 5204.08
|
||||
},
|
||||
{
|
||||
"objectid": 1960642,
|
||||
"deal_amount": 899000.0,
|
||||
"deal_date": "2013-12-30",
|
||||
"asset_area": 42.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 32,
|
||||
"floorNo": "שלישית",
|
||||
"dealId": 3306035061,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 2,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 141,
|
||||
"subParcelNum": 11,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 21404.76
|
||||
},
|
||||
{
|
||||
"objectid": 1960638,
|
||||
"deal_amount": 580000.0,
|
||||
"deal_date": "2013-03-11",
|
||||
"asset_area": 47.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "בנין",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 32,
|
||||
"floorNo": "מרתף",
|
||||
"dealId": 3280438878,
|
||||
"dealNatureDescription": "תעשיה",
|
||||
"assetRoomNum": null,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 141,
|
||||
"subParcelNum": 1,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 12340.43
|
||||
},
|
||||
{
|
||||
"objectid": 1960649,
|
||||
"deal_amount": 720000.0,
|
||||
"deal_date": "2008-11-20",
|
||||
"asset_area": 20.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "בנין",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 34,
|
||||
"floorNo": "קרקע",
|
||||
"dealId": 3140497058,
|
||||
"dealNatureDescription": "חנות",
|
||||
"assetRoomNum": null,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 142,
|
||||
"subParcelNum": 3,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 36000.0
|
||||
},
|
||||
{
|
||||
"objectid": 1960643,
|
||||
"deal_amount": 100000.0,
|
||||
"deal_date": "2008-11-09",
|
||||
"asset_area": 58.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 32,
|
||||
"floorNo": "שלישית",
|
||||
"dealId": 3139951568,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 3,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 141,
|
||||
"subParcelNum": 12,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 1724.14
|
||||
},
|
||||
{
|
||||
"objectid": 1960647,
|
||||
"deal_amount": 430000.0,
|
||||
"deal_date": "2008-06-17",
|
||||
"asset_area": 42.0,
|
||||
"settlement_name_heb": "חולון",
|
||||
"property_type_description": "דירה",
|
||||
"neighborhood": "קרית עבודה",
|
||||
"street_name": null,
|
||||
"house_number": null,
|
||||
"floor": null,
|
||||
"floor_number": null,
|
||||
"rooms": null,
|
||||
"priority": null,
|
||||
"shape": "MULTIPOLYGON(((3870903.639498367 3766273.3642689525,3870887.6103521264 3766277.301987773,3870893.7433254845 3766302.5584789426,3870909.784521754 3766298.561590301,3870903.639498367 3766273.3642689525)))",
|
||||
"source_polygon_id": null,
|
||||
"sourceorder": 1,
|
||||
"settlementId": 6600,
|
||||
"settlementNameEng": "Holon",
|
||||
"streetCode": 66000401,
|
||||
"streetNameHeb": "סוקולוב",
|
||||
"streetNameEng": "Sokolov",
|
||||
"houseNum": 32,
|
||||
"floorNo": "שניה",
|
||||
"dealId": 3137311234,
|
||||
"dealNatureDescription": "דירה בבית קומות",
|
||||
"assetRoomNum": 2,
|
||||
"gushNum": 7166,
|
||||
"parcelNum": 141,
|
||||
"subParcelNum": 9,
|
||||
"polygonId": "52385050",
|
||||
"price_per_sqm": 10238.1
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,155 @@
|
||||
"""
|
||||
Fast unit tests for MCP tools using cached fixtures.
|
||||
|
||||
These tests use pre-recorded API responses to run quickly (~1s)
|
||||
without hitting the real Govmap API.
|
||||
|
||||
For full E2E tests with real API calls, see tests/e2e/test_mcp_tools.py
|
||||
"""
|
||||
import json
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, Mock
|
||||
from nadlan_mcp.govmap.models import Deal, AutocompleteResult, AutocompleteResponse, CoordinatePoint
|
||||
from nadlan_mcp.fastmcp_server import (
|
||||
autocomplete_address,
|
||||
find_recent_deals_for_address,
|
||||
get_street_deals,
|
||||
get_neighborhood_deals,
|
||||
get_deals_by_radius,
|
||||
)
|
||||
|
||||
|
||||
# Load fixtures
|
||||
FIXTURES_DIR = Path(__file__).parent / "fixtures"
|
||||
|
||||
|
||||
def load_fixture(filename):
|
||||
"""Load a JSON fixture file."""
|
||||
with open(FIXTURES_DIR / filename, encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_autocomplete_data():
|
||||
"""Cached autocomplete response."""
|
||||
data = load_fixture("autocomplete_response.json")
|
||||
results = [AutocompleteResult.model_validate(r) for r in data]
|
||||
return AutocompleteResponse(results=results, resultsCount=len(results))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_street_deals_data():
|
||||
"""Cached street deals response."""
|
||||
data = load_fixture("street_deals.json")
|
||||
return [Deal.model_validate(d) for d in data]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_neighborhood_deals_data():
|
||||
"""Cached neighborhood deals response."""
|
||||
data = load_fixture("neighborhood_deals.json")
|
||||
return [Deal.model_validate(d) for d in data]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_polygon_metadata_data():
|
||||
"""Cached polygon metadata response."""
|
||||
return load_fixture("polygon_metadata.json")
|
||||
|
||||
|
||||
class TestMCPToolsFast:
|
||||
"""Fast unit tests for MCP tools using mocked data."""
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
def test_autocomplete_address_fast(self, mock_client, mock_autocomplete_data):
|
||||
"""Test autocomplete with cached data."""
|
||||
mock_client.autocomplete_address.return_value = mock_autocomplete_data
|
||||
|
||||
result = autocomplete_address("חולון סוקולוב")
|
||||
data = json.loads(result)
|
||||
|
||||
assert isinstance(data, list)
|
||||
assert len(data) > 0
|
||||
assert "text" in data[0]
|
||||
assert "coordinates" in data[0]
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
def test_get_street_deals_fast(self, mock_client, mock_street_deals_data):
|
||||
"""Test street deals with cached data."""
|
||||
mock_client.get_street_deals.return_value = mock_street_deals_data
|
||||
|
||||
result = get_street_deals("52385050", limit=100, deal_type=2)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_deals" in data
|
||||
assert data["total_deals"] == len(mock_street_deals_data)
|
||||
assert "deals" in data
|
||||
assert len(data["deals"]) > 0
|
||||
|
||||
# Verify deal structure
|
||||
deal = data["deals"][0]
|
||||
assert "deal_amount" in deal
|
||||
assert "deal_date" in deal
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
def test_get_neighborhood_deals_fast(self, mock_client, mock_neighborhood_deals_data):
|
||||
"""Test neighborhood deals with cached data."""
|
||||
mock_client.get_neighborhood_deals.return_value = mock_neighborhood_deals_data
|
||||
|
||||
result = get_neighborhood_deals("52385050", limit=100, deal_type=2)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_deals" in data
|
||||
assert data["total_deals"] == len(mock_neighborhood_deals_data)
|
||||
assert "deals" in data
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
def test_get_deals_by_radius_fast(self, mock_client, mock_polygon_metadata_data):
|
||||
"""Test deals by radius with cached data."""
|
||||
mock_client.get_deals_by_radius.return_value = mock_polygon_metadata_data
|
||||
|
||||
result = get_deals_by_radius(37.6629, 38.7093, radius_meters=500)
|
||||
data = json.loads(result)
|
||||
|
||||
assert "total_polygons" in data
|
||||
assert data["total_polygons"] == len(mock_polygon_metadata_data)
|
||||
assert "polygons" in data
|
||||
|
||||
@pytest.mark.skip(reason="Complex workflow with statistics - tested in E2E suite")
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
def test_find_recent_deals_fast(self, mock_client, mock_street_deals_data,
|
||||
mock_neighborhood_deals_data, mock_polygon_metadata_data,
|
||||
mock_autocomplete_data):
|
||||
"""Test find_recent_deals with fully mocked workflow.
|
||||
|
||||
NOTE: This test is skipped because find_recent_deals_for_address has complex
|
||||
statistics calculations that require specific data structure. Use E2E tests
|
||||
in tests/e2e/test_mcp_tools.py for full integration testing.
|
||||
"""
|
||||
pass
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
def test_no_deals_found(self, mock_client):
|
||||
"""Test handling when no deals are found."""
|
||||
mock_client.get_street_deals.return_value = []
|
||||
|
||||
result = get_street_deals("999999", limit=100, deal_type=2)
|
||||
|
||||
# Should return a message string when no deals found
|
||||
assert isinstance(result, str)
|
||||
assert "No" in result or "found" in result.lower()
|
||||
|
||||
@patch('nadlan_mcp.fastmcp_server.client')
|
||||
def test_deal_type_filtering(self, mock_client, mock_street_deals_data):
|
||||
"""Test that deal_type parameter is passed correctly."""
|
||||
mock_client.get_street_deals.return_value = mock_street_deals_data
|
||||
|
||||
# Test with deal_type=1 (first hand)
|
||||
result = get_street_deals("52385050", limit=100, deal_type=1)
|
||||
data = json.loads(result)
|
||||
|
||||
# Verify client was called with correct deal_type
|
||||
mock_client.get_street_deals.assert_called_once_with("52385050", 100, deal_type=1)
|
||||
assert "deal_type" in data
|
||||
assert data["deal_type"] == 1
|
||||
Reference in New Issue
Block a user