refactor(google_serper_api): migrate to new tool mode implementation (#5446)

* # refactor(google_serper_api): migrate to new tool mode implementation

BREAKING CHANGE: Replace legacy LCToolComponent implementation with new Component base class

- Migrate from LCToolComponent to Component base class
- Add tool_mode flag to MultilineInput
- Update output configuration to use DataFrame type
- Implement structured error handling with DataFrame responses
- Remove legacy tool mode implementation

* test(google-serper): add unit tests for GoogleSerperAPIComponent

- Add comprehensive test suite for GoogleSerperAPIComponent
- Mock HTTP requests to test search functionality
- Test component initialization and configuration
- Add error handling test cases
- Test text search and wrapper building methods
- Ensure proper DataFrame output structure

This change improves test coverage for the Google Serper API integration,
following existing test patterns in the project.

* [autofix.ci] apply automated fixes

* style(tests): remove unused fixture argument in google-serper test

- Remove unused mock_search_results fixture from test_text_search_serper
- Fix linting error ARG001 (unused function argument)

* revert(tools): restore Google Search API component to original implementation

Due to backward compatibility concerns, reverting the Google Search API component
to its initial implementation state to maintain stability and prevent breaking changes.

* refactor(components): mark GoogleSerperAPI component as deprecated & Legacy

* feat(components): add GoogleSerperAPICore component

* refactor(google-serper): fix filename typo from 'gloogle' to 'google'

* test(google-serper): add unit tests following component test guide

* feat(icons): improve Serper icon quality and add to icon list

* [autofix.ci] apply automated fixes

* Update test_google_serper_api_core.py

test update

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
This commit is contained in:
VICTOR CORREA GOMES 2025-01-17 22:25:34 -03:00 • committed by GitHub
commit d650b21f17
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 213 additions and 44 deletions

View file

@ -0,0 +1,114 @@
from unittest.mock import MagicMock, patch
import pytest
from langflow.components.tools import GoogleSerperAPICore
from langflow.schema import DataFrame
@pytest.fixture
def google_serper_component():
return GoogleSerperAPICore()
@pytest.fixture
def mock_search_results():
return {
"organic": [
{
"title": "Test Title 1",
"link": "https://test1.com",
"snippet": "Test snippet 1",
},
{
"title": "Test Title 2",
"link": "https://test2.com",
"snippet": "Test snippet 2",
},
]
}
def test_component_initialization(google_serper_component):
assert google_serper_component.display_name == "Google Serper API"
assert google_serper_component.icon == "Serper"
input_names = [input_.name for input_ in google_serper_component.inputs]
assert "serper_api_key" in input_names
assert "input_value" in input_names
assert "k" in input_names
@patch("langchain_community.utilities.google_serper.requests.get")
@patch("langchain_community.utilities.google_serper.requests.post")
def test_search_serper_success(mock_post, mock_get, google_serper_component, mock_search_results):
# Configure mocks
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.json.return_value = mock_search_results
mock_post.return_value = mock_response
mock_get.return_value = mock_response
# Configure component
google_serper_component.serper_api_key = "test_api_key"
google_serper_component.input_value = "test query"
google_serper_component.k = 2
# Execute search
result = google_serper_component.search_serper()
# Verify results
assert isinstance(result, DataFrame)
assert len(result) == 2
assert list(result.columns) == ["title", "link", "snippet"]
assert result.iloc[0]["title"] == "Test Title 1"
assert result.iloc[1]["link"] == "https://test2.com"
@patch("langchain_community.utilities.google_serper.requests.get")
@patch("langchain_community.utilities.google_serper.requests.post")
def test_search_serper_error_handling(mock_post, mock_get, google_serper_component):
# Configure mocks to simulate error
mock_response = MagicMock()
mock_response.status_code = 403
mock_response.raise_for_status.side_effect = ConnectionError("API connection failed")
mock_post.return_value = mock_response
mock_get.return_value = mock_response
# Configure component
google_serper_component.serper_api_key = "test_api_key"
google_serper_component.input_value = "test query"
google_serper_component.k = 2
# Execute search
result = google_serper_component.search_serper()
# Verify error handling
assert isinstance(result, DataFrame)
assert "error" in result.columns
assert "API connection failed" in result.iloc[0]["error"]
def test_text_search_serper(google_serper_component):
with patch.object(google_serper_component, "search_serper") as mock_search:
mock_search.return_value = DataFrame(
[{"title": "Test Title", "link": "https://test.com", "snippet": "Test snippet"}]
)
result = google_serper_component.text_search_serper()
assert result.text is not None
assert "Test Title" in result.text
assert "https://test.com" in result.text
def test_build_wrapper(google_serper_component):
google_serper_component.serper_api_key = "test_api_key"
google_serper_component.k = 2
wrapper = google_serper_component._build_wrapper()
assert wrapper.serper_api_key == "test_api_key"
assert wrapper.k == 2
def test_build_method(google_serper_component):
build_result = google_serper_component.build()
assert build_result == google_serper_component.search_serper