fix(search): handle engine-specific SerpApi result keys

Expands SerpApi result parsing to dynamically check for 'shopping_results', 'news_results', 'local_results', and 'jobs_results' when 'organic_results' is absent, matching official SerpApi engine behavior.
This commit is contained in:
Gowtham 2026-10-09 16:39:10 +05:30
parent 5a7ef2cca2
commit 89712b2dcb
2 changed files with 37 additions and 5 deletions

View file

@ -157,15 +157,24 @@ class SerpApiSearchConfig(BaseSearchConfig):
"""
response_json: Final = raw_response.json()
results_list: Final = ( # pyright: ignore[reportUnknownVariableType] # standard response shape
response_json.get("organic_results")
or response_json.get("news_results")
or response_json.get("shopping_results")
or response_json.get("local_results")
or response_json.get("jobs_results")
or []
)
results: Final = [
SearchResult(
title=result.get("title", ""),
url=result.get("link", ""),
snippet=result.get("snippet", ""),
date=result.get("date"),
title=result.get("title", ""), # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType] # parsing generic json dict
url=result.get("link", ""), # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType] # parsing generic json dict
snippet=result.get("snippet", ""), # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType] # parsing generic json dict
date=result.get("date"), # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType] # parsing generic json dict
last_updated=None,
)
for result in response_json.get("organic_results", [])
for result in results_list # pyright: ignore[reportUnknownVariableType] # iterating generic json array
]
return SearchResponse(

View file

@ -236,6 +236,29 @@ class TestSerpApiSearchConfig:
assert result.results[1].url == "https://example.com/2"
assert result.results[1].date is None
def test_transform_search_response_shopping_results(self):
config = SerpApiSearchConfig()
mock_response = Mock(spec=httpx.Response)
mock_response.json.return_value = {
"shopping_results": [
{
"title": "Shopping Result 1",
"link": "https://example.com/shop",
"snippet": "Buy this thing",
}
]
}
result = config.transform_search_response(
raw_response=mock_response,
logging_obj=MagicMock(),
)
assert isinstance(result, SearchResponse)
assert len(result.results) == 1
assert result.results[0].title == "Shopping Result 1"
def test_transform_search_response_empty_results(self):
config = SerpApiSearchConfig()