From f2f6747b7438e974d09a57d1aaac11e9290152e2 Mon Sep 17 00:00:00 2001 From: Vinicius Brasil Date: Fri, 2 May 2025 10:55:26 -0300 Subject: [PATCH] Ensure `ToolCommand` is authenticated --- src/crewai/cli/command.py | 2 +- tests/cli/tools/test_main.py | 78 +++++++++++++++--------------------- 2 files changed, 34 insertions(+), 46 deletions(-) diff --git a/src/crewai/cli/command.py b/src/crewai/cli/command.py index 2bef8985d..ba705c42f 100644 --- a/src/crewai/cli/command.py +++ b/src/crewai/cli/command.py @@ -20,7 +20,7 @@ class PlusAPIMixin: try: telemetry.set_tracer() self.plus_api_client = PlusAPI(api_key=get_auth_token()) - except Exception: + except Exception as e: self._deploy_signup_error_span = telemetry.deploy_signup_error_span() console.print( "Please sign up/login to CrewAI+ before using the CLI.", diff --git a/tests/cli/tools/test_main.py b/tests/cli/tools/test_main.py index 788bd277a..28659a80a 100644 --- a/tests/cli/tools/test_main.py +++ b/tests/cli/tools/test_main.py @@ -6,8 +6,10 @@ from contextlib import contextmanager from unittest import mock from unittest.mock import MagicMock, patch +import pytest from pytest import raises +from crewai.cli.authentication.utils import TokenManager from crewai.cli.tools.main import ToolCommand @@ -22,14 +24,20 @@ def in_temp_dir(): os.chdir(original_dir) -@patch("crewai.cli.tools.main.subprocess.run") -def test_create_success(mock_subprocess, capsys): - with in_temp_dir(): - tool_command = ToolCommand() +@pytest.fixture +def tool_command(): + TokenManager().save_tokens("test-token", 36000) + tool_command = ToolCommand() + with patch.object(tool_command, "login"): + yield tool_command - with patch.object(tool_command, "login") as mock_login: - tool_command.create("test-tool") - output = capsys.readouterr().out + +@patch("crewai.cli.tools.main.subprocess.run") +def test_create_success(mock_subprocess, capsys, tool_command): + with in_temp_dir(): + tool_command.create("test-tool") + output = capsys.readouterr().out + assert "Creating custom tool test_tool..." in output assert os.path.isdir("test_tool") assert os.path.isfile(os.path.join("test_tool", "README.md")) @@ -43,15 +51,12 @@ def test_create_success(mock_subprocess, capsys): content = f.read() assert "class TestTool" in content - mock_login.assert_called_once() mock_subprocess.assert_called_once_with(["git", "init"], check=True) - assert "Creating custom tool test_tool..." in output - @patch("crewai.cli.tools.main.subprocess.run") @patch("crewai.cli.plus_api.PlusAPI.get_tool") -def test_install_success(mock_get, mock_subprocess_run, capsys): +def test_install_success(mock_get, mock_subprocess_run, capsys, tool_command): mock_get_response = MagicMock() mock_get_response.status_code = 200 mock_get_response.json.return_value = { @@ -61,9 +66,9 @@ def test_install_success(mock_get, mock_subprocess_run, capsys): mock_get.return_value = mock_get_response mock_subprocess_run.return_value = MagicMock(stderr=None) - tool_command = ToolCommand() tool_command.install("sample-tool") output = capsys.readouterr().out + assert "Successfully installed sample-tool" in output mock_get.assert_has_calls([mock.call("sample-tool"), mock.call().json()]) mock_subprocess_run.assert_any_call( @@ -80,49 +85,38 @@ def test_install_success(mock_get, mock_subprocess_run, capsys): env=unittest.mock.ANY, ) - assert "Successfully installed sample-tool" in output - @patch("crewai.cli.plus_api.PlusAPI.get_tool") -def test_install_tool_not_found(mock_get, capsys): +def test_install_tool_not_found(mock_get, capsys, tool_command): mock_get_response = MagicMock() mock_get_response.status_code = 404 mock_get.return_value = mock_get_response - tool_command = ToolCommand() - - try: + with raises(SystemExit): tool_command.install("non-existent-tool") - except SystemExit: - pass output = capsys.readouterr().out + assert "No tool found with this name" in output mock_get.assert_called_once_with("non-existent-tool") - assert "No tool found with this name" in output @patch("crewai.cli.plus_api.PlusAPI.get_tool") -def test_install_api_error(mock_get, capsys): +def test_install_api_error(mock_get, capsys, tool_command): mock_get_response = MagicMock() mock_get_response.status_code = 500 mock_get.return_value = mock_get_response - tool_command = ToolCommand() - - try: + with raises(SystemExit): tool_command.install("error-tool") - except SystemExit: - pass output = capsys.readouterr().out + assert "Failed to get tool details" in output mock_get.assert_called_once_with("error-tool") - assert "Failed to get tool details" in output @patch("crewai.cli.tools.main.git.Repository.is_synced", return_value=False) -def test_publish_when_not_in_sync(mock_is_synced, capsys): +def test_publish_when_not_in_sync(mock_is_synced, capsys, tool_command): with raises(SystemExit): - tool_command = ToolCommand() tool_command.publish(is_public=True) output = capsys.readouterr().out @@ -150,13 +144,13 @@ def test_publish_when_not_in_sync_and_force( mock_get_project_description, mock_get_project_version, mock_get_project_name, + tool_command, ): mock_publish_response = MagicMock() mock_publish_response.status_code = 200 mock_publish_response.json.return_value = {"handle": "sample-tool"} mock_publish.return_value = mock_publish_response - tool_command = ToolCommand() tool_command.publish(is_public=True, force=True) mock_get_project_name.assert_called_with(require=True) @@ -198,13 +192,13 @@ def test_publish_success( mock_get_project_description, mock_get_project_version, mock_get_project_name, + tool_command, ): mock_publish_response = MagicMock() mock_publish_response.status_code = 200 mock_publish_response.json.return_value = {"handle": "sample-tool"} mock_publish.return_value = mock_publish_response - tool_command = ToolCommand() tool_command.publish(is_public=True) mock_get_project_name.assert_called_with(require=True) @@ -245,24 +239,21 @@ def test_publish_failure( mock_get_project_version, mock_get_project_name, capsys, + tool_command, ): mock_publish_response = MagicMock() mock_publish_response.status_code = 422 mock_publish_response.json.return_value = {"name": ["is already taken"]} mock_publish.return_value = mock_publish_response - tool_command = ToolCommand() - - try: + with raises(SystemExit): tool_command.publish(is_public=True) - except SystemExit: - pass output = capsys.readouterr().out - - mock_publish.assert_called_once() assert "Failed to complete operation" in output assert "Name is already taken" in output + mock_publish.assert_called_once() + @patch("crewai.cli.tools.main.get_project_name", return_value="sample-tool") @patch("crewai.cli.tools.main.get_project_version", return_value="1.0.0") @@ -284,6 +275,7 @@ def test_publish_api_error( mock_get_project_version, mock_get_project_name, capsys, + tool_command, ): mock_response = MagicMock() mock_response.status_code = 500 @@ -291,13 +283,9 @@ def test_publish_api_error( mock_response.ok = False mock_publish.return_value = mock_response - tool_command = ToolCommand() - - try: + with raises(SystemExit): tool_command.publish(is_public=True) - except SystemExit: - pass output = capsys.readouterr().out + assert "Request to Enterprise API failed" in output mock_publish.assert_called_once() - assert "Request to Enterprise API failed" in output