feat: Update Gmail component (#7530)

* chore: action params naming

* chore: remove comments

* chore: replaced MessageTextInput field with StrInput

* feat: add google calendar component

* feat: replaced loops with hardcoded display-name action-enum mapping to improve performance

* chore: format

* fix: add type ignore for action_key in getattr call

* feat: add google sheets component

* fix: format google calendar utils

* feat: add google meet Component

* chore: minor improvement

* chore: format & lint

* fix: google meet component

* feat: add GitHub component

* fix: format

* fix: lint

* fix: typo

* feat: add Slack Component

* fix: format

* fix: rest bool value to None

* chore: disabled slack tools temporarily

* fix: add condition to set list variables to None in when action is changed

* chore: capitalise display names

* fix: update list issues field to MessateTextInput

* fix: format/lint in slack component

* fix: google calendar logo

* fix: revert setting bool field to None

* feat: composio-core & composio-core version bump to 0.7.10

* fix: minor bugs

* feat: add accepted values to AccessType field in google meet component

* feat: add accepted values for entry point access field in Google meet component

* fix: Google Calendar display names

* feat: replace list with nested list for batch update field in Google sheets

* fix: display name in Google sheets

* fix: format

* fix: titlecase display name in google meet component

* feat: set advaced to true for advanced fields

* feat: add condition to skip empty list fields in execute_action

* chore: improve display names GitHub Component

* fix: slack component display names & minor enhancements

* feat: update condition to skip empty fields while executing action

* feat: fix google calendar field description

* feat: update googlemeet component to use new inputs & composio base class

* chore: update googlemeet component filename

* feat: update github component to use new inputs & composio base class

* feat: update google calendar to use new inputs & composio base class

* feat: update google sheets component to use new inputs & Composio base class

* feat: update slack component to use new inputs & Composio base class

* fix: format

* chore: cleanup un-used code

* chore: format

* feat: add missing fields & actions

* chore: fix typo

* feat: rm other components

* feat: improve error message format & revert composio libs bump

* chore: revert uv.lock file

* update tests

* fix: remove duplicate action field in GMAIL_FETCH_EMAILS

* fix: remove unused code

* fix: add ignore statement

---------

Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
This commit is contained in:
Abhishek Patil 2025-04-15 23:46:36 +05:30 committed by GitHub
commit dc35b4ec9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 113 additions and 61 deletions

View file

@ -15,7 +15,7 @@ class MockComposioToolSet:
return []
def execute_action(self, *_, **__):
return {"data": {"response": "mocked response"}}
return {"successful": True, "data": {"result": "mocked response"}}
class TestComposioBase(ComponentTestBaseWithoutClient):

View file

@ -72,9 +72,18 @@ class TestGmailComponent(ComponentTestBaseWithoutClient):
component.body = "Test Body"
component.is_html = False
# For this specific test, customize the _actions_data to not use get_result_field
component._actions_data = {
"GMAIL_SEND_EMAIL": {
"display_name": "Send Email",
"action_fields": ["recipient_email", "subject", "body", "is_html"],
"get_result_field": False,
}
}
# Execute action
result = component.execute_action()
assert result == "mocked response"
assert result == {"result": "mocked response"}
def test_execute_action_fetch_emails(self, component_class, default_kwargs, monkeypatch):
# Mock Action enum
@ -87,27 +96,24 @@ class TestGmailComponent(ComponentTestBaseWithoutClient):
component.max_results = 10
component.query = "from:test@example.com"
# Create a mock for the toolset
mock_toolset = MagicMock()
# The execute_action method needs to return a structure that works with the component's logic
# Based on the error, we need to make sure the 'data' key contains a dictionary with at least one key
mock_toolset.execute_action.return_value = {"data": {"response": "mocked response"}}
# Patch the _build_wrapper method to return our mock
with patch.object(component, "_build_wrapper", return_value=mock_toolset):
# Also patch the _actions_data to ensure it has the correct structure for GMAIL_FETCH_EMAILS
# This ensures the result_field is set correctly
component._actions_data = {
"GMAIL_FETCH_EMAILS": {
"action_fields": ["max_results", "query"],
"result_field": "response",
"get_result_field": True,
}
# For this specific test, we need to customize the action_data to handle results field
component._actions_data = {
"GMAIL_FETCH_EMAILS": {
"action_fields": ["max_results", "query"],
"result_field": "messages",
"get_result_field": True,
}
}
# Execute action
# Create a mock for the toolset with specific structure for this test
mock_toolset = MagicMock()
mock_toolset.execute_action.return_value = {"successful": True, "data": {"messages": "mocked response"}}
# Patch the _build_wrapper method
with patch.object(component, "_build_wrapper", return_value=mock_toolset):
result = component.execute_action()
assert result == "mocked response"
# Based on the component's actual behavior, it returns the entire data dict
assert result == {"messages": "mocked response"}
def test_execute_action_get_profile(self, component_class, default_kwargs, monkeypatch):
# Mock Action enum
@ -118,9 +124,18 @@ class TestGmailComponent(ComponentTestBaseWithoutClient):
component.api_key = "test_key"
component.action = [{"name": "Get User Profile"}]
# For this specific test, customize the _actions_data to not use get_result_field
component._actions_data = {
"GMAIL_GET_PROFILE": {
"display_name": "Get User Profile",
"action_fields": ["gmail_user_id"],
"get_result_field": False,
}
}
# Execute action
result = component.execute_action()
assert result == "mocked response"
assert result == {"result": "mocked response"}
def test_execute_action_invalid_action(self, component_class, default_kwargs):
# Setup component
@ -173,24 +188,9 @@ class TestGmailComponent(ComponentTestBaseWithoutClient):
# Verify the DataFrame is not empty
assert not result.empty
# Verify the DataFrame contains our mock data
# This will depend on how the component processes the data
# We can check for specific column names or values
if hasattr(result, "columns"):
# If the DataFrame has columns, check for expected ones
expected_columns = ["id", "threadId", "subject", "from", "date", "snippet"]
for col in expected_columns:
if col in result.columns:
assert True
break
else:
# If none of the expected columns are found, check if data is in the DataFrame
assert any(
"Test Email" in str(cell) for cell in result.values.flat if hasattr(cell, "__contains__")
)
else:
# If the DataFrame structure is different, just check for some expected content
assert "Test Email" in str(result)
# Check for expected content in the DataFrame string representation
data_str = str(result)
assert "test email" in data_str
def test_update_build_config(self, component_class, default_kwargs):
# Test that the Gmail component properly inherits and uses the base component's