Skip to main content
Glama

MCP Atlassian

by ArconixForge
test_environment.py9.76 kB
"""Tests for the environment utilities module.""" import logging import pytest from mcp_atlassian.utils.environment import get_available_services from tests.utils.assertions import assert_log_contains from tests.utils.mocks import MockEnvironment @pytest.fixture(autouse=True) def setup_logger(): """Ensure logger is set to INFO level for capturing log messages.""" logger = logging.getLogger("mcp-atlassian.utils.environment") original_level = logger.level logger.setLevel(logging.INFO) yield logger.setLevel(original_level) @pytest.fixture def env_scenarios(): """Environment configuration scenarios for testing.""" return { "oauth_cloud": { "CONFLUENCE_URL": "https://company.atlassian.net", "JIRA_URL": "https://company.atlassian.net", "ATLASSIAN_OAUTH_CLIENT_ID": "client_id", "ATLASSIAN_OAUTH_CLIENT_SECRET": "client_secret", "ATLASSIAN_OAUTH_REDIRECT_URI": "http://localhost:8080/callback", "ATLASSIAN_OAUTH_SCOPE": "read:jira-user", "ATLASSIAN_OAUTH_CLOUD_ID": "cloud_id", }, "basic_auth_cloud": { "CONFLUENCE_URL": "https://company.atlassian.net", "CONFLUENCE_USERNAME": "user@company.com", "CONFLUENCE_API_TOKEN": "api_token", "JIRA_URL": "https://company.atlassian.net", "JIRA_USERNAME": "user@company.com", "JIRA_API_TOKEN": "api_token", }, "pat_server": { "CONFLUENCE_URL": "https://confluence.company.com", "CONFLUENCE_PERSONAL_TOKEN": "pat_token", "JIRA_URL": "https://jira.company.com", "JIRA_PERSONAL_TOKEN": "pat_token", }, "basic_auth_server": { "CONFLUENCE_URL": "https://confluence.company.com", "CONFLUENCE_USERNAME": "admin", "CONFLUENCE_API_TOKEN": "password", "JIRA_URL": "https://jira.company.com", "JIRA_USERNAME": "admin", "JIRA_API_TOKEN": "password", }, } def _assert_service_availability(result, confluence_expected, jira_expected): """Helper to assert service availability.""" assert result == {"confluence": confluence_expected, "jira": jira_expected} def _assert_authentication_logs(caplog, auth_type, services): """Helper to assert authentication log messages.""" log_patterns = { "oauth": "OAuth 2.0 (3LO) authentication (Cloud-only features)", "cloud_basic": "Cloud Basic Authentication (API Token)", "server": "Server/Data Center authentication (PAT or Basic Auth)", "not_configured": "is not configured or required environment variables are missing", } for service in services: service_name = service.title() if auth_type == "not_configured": assert_log_contains( caplog, "INFO", f"{service_name} {log_patterns[auth_type]}" ) else: assert_log_contains( caplog, "INFO", f"Using {service_name} {log_patterns[auth_type]}" ) class TestGetAvailableServices: """Test cases for get_available_services function.""" def test_no_services_configured(self, caplog): """Test that no services are available when no environment variables are set.""" with MockEnvironment.clean_env(): result = get_available_services() _assert_service_availability( result, confluence_expected=False, jira_expected=False ) _assert_authentication_logs( caplog, "not_configured", ["confluence", "jira"] ) @pytest.mark.parametrize( "scenario,expected_confluence,expected_jira", [ ("oauth_cloud", True, True), ("basic_auth_cloud", True, True), ("pat_server", True, True), ("basic_auth_server", True, True), ], ) def test_valid_authentication_scenarios( self, env_scenarios, scenario, expected_confluence, expected_jira, caplog ): """Test various valid authentication scenarios.""" with MockEnvironment.clean_env(): for key, value in env_scenarios[scenario].items(): import os os.environ[key] = value result = get_available_services() _assert_service_availability( result, confluence_expected=expected_confluence, jira_expected=expected_jira, ) # Verify appropriate log messages based on scenario if scenario == "oauth_cloud": _assert_authentication_logs(caplog, "oauth", ["confluence", "jira"]) elif scenario == "basic_auth_cloud": _assert_authentication_logs( caplog, "cloud_basic", ["confluence", "jira"] ) elif scenario in ["pat_server", "basic_auth_server"]: _assert_authentication_logs(caplog, "server", ["confluence", "jira"]) @pytest.mark.parametrize( "missing_oauth_var", [ "ATLASSIAN_OAUTH_CLIENT_ID", "ATLASSIAN_OAUTH_CLIENT_SECRET", "ATLASSIAN_OAUTH_REDIRECT_URI", "ATLASSIAN_OAUTH_SCOPE", "ATLASSIAN_OAUTH_CLOUD_ID", ], ) def test_oauth_missing_required_vars( self, env_scenarios, missing_oauth_var, caplog ): """Test that OAuth fails when any required variable is missing.""" with MockEnvironment.clean_env(): oauth_config = env_scenarios["oauth_cloud"] # Remove one required OAuth variable del oauth_config[missing_oauth_var] for key, value in oauth_config.items(): import os os.environ[key] = value result = get_available_services() _assert_service_availability( result, confluence_expected=False, jira_expected=False ) @pytest.mark.parametrize( "missing_basic_vars,service", [ (["CONFLUENCE_USERNAME", "JIRA_USERNAME"], "username"), (["CONFLUENCE_API_TOKEN", "JIRA_API_TOKEN"], "token"), ], ) def test_basic_auth_missing_credentials( self, env_scenarios, missing_basic_vars, service ): """Test that basic auth fails when credentials are missing.""" with MockEnvironment.clean_env(): basic_config = env_scenarios["basic_auth_cloud"].copy() # Remove required variables for var in missing_basic_vars: del basic_config[var] for key, value in basic_config.items(): import os os.environ[key] = value result = get_available_services() _assert_service_availability( result, confluence_expected=False, jira_expected=False ) def test_oauth_precedence_over_basic_auth(self, env_scenarios, caplog): """Test that OAuth takes precedence over Basic Auth.""" with MockEnvironment.clean_env(): # Set both OAuth and Basic Auth variables combined_config = { **env_scenarios["oauth_cloud"], **env_scenarios["basic_auth_cloud"], } for key, value in combined_config.items(): import os os.environ[key] = value result = get_available_services() _assert_service_availability( result, confluence_expected=True, jira_expected=True ) # Should use OAuth, not Basic Auth _assert_authentication_logs(caplog, "oauth", ["confluence", "jira"]) assert "Basic Authentication" not in caplog.text def test_mixed_service_configuration(self, caplog): """Test mixed configurations where only one service is configured.""" with MockEnvironment.clean_env(): import os os.environ["CONFLUENCE_URL"] = "https://company.atlassian.net" os.environ["CONFLUENCE_USERNAME"] = "user@company.com" os.environ["CONFLUENCE_API_TOKEN"] = "api_token" result = get_available_services() _assert_service_availability( result, confluence_expected=True, jira_expected=False ) _assert_authentication_logs(caplog, "cloud_basic", ["confluence"]) _assert_authentication_logs(caplog, "not_configured", ["jira"]) def test_return_value_structure(self): """Test that the return value has the correct structure.""" with MockEnvironment.clean_env(): result = get_available_services() assert isinstance(result, dict) assert set(result.keys()) == {"confluence", "jira"} assert all(isinstance(v, bool) for v in result.values()) @pytest.mark.parametrize( "invalid_vars", [ {"CONFLUENCE_URL": "", "JIRA_URL": ""}, # Empty strings {"confluence_url": "https://test.com"}, # Wrong case ], ) def test_invalid_environment_variables(self, invalid_vars, caplog): """Test behavior with invalid environment variables.""" with MockEnvironment.clean_env(): for key, value in invalid_vars.items(): import os os.environ[key] = value result = get_available_services() _assert_service_availability( result, confluence_expected=False, jira_expected=False ) _assert_authentication_logs( caplog, "not_configured", ["confluence", "jira"] )

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ArconixForge/mcp-atlassian'

If you have feedback or need assistance with the MCP directory API, please join our Discord server