793 lines
28 KiB
Python
793 lines
28 KiB
Python
"""Tests for main CLI global options stored in context."""
|
|
|
|
from unittest.mock import MagicMock, Mock, patch
|
|
|
|
import pytest
|
|
from typer.testing import CliRunner
|
|
|
|
from openwebui_cli.main import app
|
|
|
|
runner = CliRunner()
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_config(tmp_path, monkeypatch):
|
|
"""Mock configuration for testing."""
|
|
config_dir = tmp_path / "openwebui"
|
|
config_path = config_dir / "config.yaml"
|
|
|
|
monkeypatch.setattr("openwebui_cli.config.get_config_dir", lambda: config_dir)
|
|
monkeypatch.setattr("openwebui_cli.config.get_config_path", lambda: config_path)
|
|
|
|
# Create default config
|
|
from openwebui_cli.config import Config, save_config
|
|
config = Config()
|
|
save_config(config)
|
|
|
|
return config_path
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_keyring(monkeypatch):
|
|
"""Mock keyring for testing."""
|
|
token_store = {}
|
|
|
|
def get_password(service, key):
|
|
return token_store.get(f"{service}:{key}")
|
|
|
|
def set_password(service, key, password):
|
|
token_store[f"{service}:{key}"] = password
|
|
|
|
monkeypatch.setattr("keyring.get_password", get_password)
|
|
monkeypatch.setattr("keyring.set_password", set_password)
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_client():
|
|
"""Mock HTTP client for testing."""
|
|
response_data = {
|
|
"choices": [
|
|
{
|
|
"message": {
|
|
"content": "Test response"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
mock_http_client = MagicMock()
|
|
mock_http_client.__enter__.return_value = mock_http_client
|
|
mock_http_client.__exit__.return_value = None
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = response_data
|
|
mock_http_client.post.return_value = mock_response
|
|
|
|
return mock_http_client
|
|
|
|
|
|
class TestGlobalOptionsStorage:
|
|
"""Test that global options are properly stored in context."""
|
|
|
|
def test_profile_option_stored_in_context(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --profile option is stored in context."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--profile", "test-profile",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# Verify profile was passed to create_client
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "test-profile"
|
|
|
|
def test_uri_option_stored_in_context(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --uri option is stored in context."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--uri", "http://test.local:9000",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# Verify URI was passed to create_client
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("uri") == "http://test.local:9000"
|
|
|
|
def test_token_option_stored_in_context(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --token option is stored in context."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--token", "secret-token-123",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# Verify token was passed to create_client
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("token") == "secret-token-123"
|
|
|
|
def test_timeout_option_stored_in_context(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --timeout option is stored in context."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--timeout", "60",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# Verify timeout was passed to create_client as integer
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("timeout") == 60
|
|
assert isinstance(call_kwargs.get("timeout"), int)
|
|
|
|
def test_format_option_stored_in_context(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --format option is stored in context."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--format", "json",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# Verify format was used for output
|
|
assert "choices" in result.stdout # JSON output has 'choices' key
|
|
|
|
|
|
class TestFormatOptionDefault:
|
|
"""Test format option defaults to 'text'."""
|
|
|
|
def test_format_defaults_to_text(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --format defaults to 'text' when not specified."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# Text format should show plain content without JSON structure
|
|
assert "Test response" in result.stdout
|
|
|
|
def test_format_text_explicit(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --format text explicitly."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--format", "text",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
assert "Test response" in result.stdout
|
|
|
|
def test_format_json_explicit(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --format json explicitly."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--format", "json",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# JSON format should have structured output
|
|
assert "choices" in result.stdout
|
|
|
|
|
|
class TestQuietFlag:
|
|
"""Test --quiet flag."""
|
|
|
|
def test_quiet_flag_recognized(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --quiet flag is recognized."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--quiet",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_quiet_flag_short_form(self, mock_config, mock_keyring, mock_client):
|
|
"""Test -q short form of --quiet."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"-q",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_quiet_flag_default_false(self, mock_config, mock_keyring, mock_client):
|
|
"""Test quiet flag defaults to False."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
# Without quiet flag, output should be normal
|
|
assert len(result.stdout) > 0
|
|
|
|
|
|
class TestVerboseFlag:
|
|
"""Test --verbose flag."""
|
|
|
|
def test_verbose_flag_recognized(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --verbose flag is recognized."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--verbose",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_verbose_flag_debug_alias(self, mock_config, mock_keyring, mock_client):
|
|
"""Test --debug is alias for --verbose."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--debug",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
|
|
def test_verbose_flag_default_false(self, mock_config, mock_keyring, mock_client):
|
|
"""Test verbose flag defaults to False."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
|
|
|
|
class TestShortFormOptions:
|
|
"""Test short form global options."""
|
|
|
|
def test_profile_short_form_p_upper(self, mock_config, mock_keyring, mock_client):
|
|
"""Test -P short form for --profile."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"-P", "prod-profile",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "prod-profile"
|
|
|
|
def test_uri_short_form_u_upper(self, mock_config, mock_keyring, mock_client):
|
|
"""Test -U short form for --uri."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"-U", "http://prod.example.com",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("uri") == "http://prod.example.com"
|
|
|
|
def test_format_short_form_f(self, mock_config, mock_keyring, mock_client):
|
|
"""Test -f short form for --format."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"-f", "json",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
assert "choices" in result.stdout
|
|
|
|
def test_timeout_short_form_t(self, mock_config, mock_keyring, mock_client):
|
|
"""Test -t short form for --timeout."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"-t", "30",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("timeout") == 30
|
|
|
|
|
|
class TestMultipleGlobalOptions:
|
|
"""Test multiple global options together."""
|
|
|
|
def test_all_options_together(self, mock_config, mock_keyring, mock_client):
|
|
"""Test all global options together."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--profile", "test-profile",
|
|
"--uri", "http://test.local:9000",
|
|
"--token", "secret-token",
|
|
"--format", "json",
|
|
"--timeout", "45",
|
|
"--verbose",
|
|
"--quiet",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "test-profile"
|
|
assert call_kwargs.get("uri") == "http://test.local:9000"
|
|
assert call_kwargs.get("token") == "secret-token"
|
|
assert call_kwargs.get("timeout") == 45
|
|
|
|
def test_short_form_options_combined(self, mock_config, mock_keyring, mock_client):
|
|
"""Test short form options can be combined."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"-P", "profile1",
|
|
"-U", "http://server1.com",
|
|
"-f", "json",
|
|
"-t", "50",
|
|
"-q",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "profile1"
|
|
assert call_kwargs.get("uri") == "http://server1.com"
|
|
assert call_kwargs.get("timeout") == 50
|
|
|
|
def test_mixed_short_and_long_options(self, mock_config, mock_keyring, mock_client):
|
|
"""Test mixing short and long form options."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"-P", "profile2",
|
|
"--uri", "http://mixed.com",
|
|
"-f", "text",
|
|
"--token", "mixed-token",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "profile2"
|
|
assert call_kwargs.get("uri") == "http://mixed.com"
|
|
assert call_kwargs.get("token") == "mixed-token"
|
|
|
|
|
|
class TestGlobalOptionsWithDifferentCommands:
|
|
"""Test global options work with different subcommands."""
|
|
|
|
def test_global_options_with_models_command(self, mock_config, mock_keyring):
|
|
"""Test global options are available for models command."""
|
|
with patch("openwebui_cli.commands.models.create_client") as mock_create_client:
|
|
mock_http_client = MagicMock()
|
|
mock_http_client.__enter__.return_value = mock_http_client
|
|
mock_http_client.__exit__.return_value = None
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = {"data": []}
|
|
mock_http_client.get.return_value = mock_response
|
|
mock_create_client.return_value = mock_http_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--profile", "test-profile",
|
|
"--uri", "http://test.local",
|
|
"--token", "test-token",
|
|
"models", "list"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "test-profile"
|
|
assert call_kwargs.get("uri") == "http://test.local"
|
|
assert call_kwargs.get("token") == "test-token"
|
|
|
|
def test_global_options_with_auth_command(self, mock_config, mock_keyring):
|
|
"""Test global options are available for auth command."""
|
|
with patch("openwebui_cli.commands.auth.create_client") as mock_create_client:
|
|
mock_http_client = MagicMock()
|
|
mock_http_client.__enter__.return_value = mock_http_client
|
|
mock_http_client.__exit__.return_value = None
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = {"name": "test", "email": "test@example.com", "role": "user"}
|
|
mock_http_client.get.return_value = mock_response
|
|
mock_create_client.return_value = mock_http_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--profile", "auth-profile",
|
|
"--uri", "http://auth.local",
|
|
"auth", "whoami"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "auth-profile"
|
|
assert call_kwargs.get("uri") == "http://auth.local"
|
|
|
|
|
|
class TestGlobalOptionsEdgeCases:
|
|
"""Test edge cases for global options."""
|
|
|
|
def test_timeout_zero_value(self, mock_config, mock_keyring, mock_client):
|
|
"""Test timeout with zero value."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--timeout", "0",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("timeout") == 0
|
|
|
|
def test_timeout_large_value(self, mock_config, mock_keyring, mock_client):
|
|
"""Test timeout with large value."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--timeout", "3600",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("timeout") == 3600
|
|
|
|
def test_profile_with_special_characters(self, mock_config, mock_keyring, mock_client):
|
|
"""Test profile with special characters."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--profile", "test-profile_v2",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("profile") == "test-profile_v2"
|
|
|
|
def test_uri_with_special_characters(self, mock_config, mock_keyring, mock_client):
|
|
"""Test URI with special characters and ports."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--uri", "http://test.example.com:9000/api",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("uri") == "http://test.example.com:9000/api"
|
|
|
|
def test_token_with_special_characters(self, mock_config, mock_keyring, mock_client):
|
|
"""Test token with special characters."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
special_token = "sk-test_1234-5678$%&!@#"
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--token", special_token,
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
assert call_kwargs.get("token") == special_token
|
|
|
|
def test_none_values_handled_correctly(self, mock_config, mock_keyring, mock_client):
|
|
"""Test that None values are handled correctly."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_create_client.call_args[1]
|
|
# When not provided, these should be None
|
|
assert call_kwargs.get("profile") is None
|
|
assert call_kwargs.get("uri") is None
|
|
assert call_kwargs.get("token") is None
|
|
|
|
def test_format_with_unrecognized_value(self, mock_config, mock_keyring, mock_client):
|
|
"""Test format with unrecognized value (still stored, usage depends on command)."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--format", "yaml",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
# Command succeeds; format validation is command-specific
|
|
assert result.exit_code == 0
|
|
|
|
|
|
class TestGlobalOptionsContextIsolation:
|
|
"""Test that context is properly isolated between commands."""
|
|
|
|
def test_context_not_shared_between_invocations(self, mock_config, mock_keyring, mock_client):
|
|
"""Test that context from one invocation doesn't leak to next."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_create_client:
|
|
mock_create_client.return_value = mock_client
|
|
|
|
# First invocation with profile1
|
|
result1 = runner.invoke(
|
|
app,
|
|
[
|
|
"--profile", "profile1",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
assert result1.exit_code == 0
|
|
|
|
# Second invocation with profile2
|
|
result2 = runner.invoke(
|
|
app,
|
|
[
|
|
"--profile", "profile2",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
assert result2.exit_code == 0
|
|
|
|
# Verify each invocation got the right profile
|
|
calls = mock_create_client.call_args_list
|
|
assert calls[0][1].get("profile") == "profile1"
|
|
assert calls[1][1].get("profile") == "profile2"
|
|
|
|
def test_context_persists_across_subcommand_calls(self, mock_config, mock_keyring):
|
|
"""Test that context persists when calling subcommands."""
|
|
with patch("openwebui_cli.commands.chat.create_client") as mock_chat_client:
|
|
mock_http_client = MagicMock()
|
|
mock_http_client.__enter__.return_value = mock_http_client
|
|
mock_http_client.__exit__.return_value = None
|
|
mock_response = Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = {
|
|
"choices": [{"message": {"content": "Response"}}]
|
|
}
|
|
mock_http_client.post.return_value = mock_response
|
|
mock_chat_client.return_value = mock_http_client
|
|
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"--token", "persistent-token",
|
|
"chat", "send",
|
|
"-m", "test-model",
|
|
"-p", "Hello",
|
|
"--no-stream"
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
call_kwargs = mock_chat_client.call_args[1]
|
|
assert call_kwargs.get("token") == "persistent-token"
|