File size: 7,156 Bytes
e41e94d
e3c68ad
72917ff
e41e94d
31d6c52
9cae871
 
e41e94d
 
2652f92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31d6c52
2652f92
 
 
 
 
 
 
 
 
e41e94d
 
2652f92
 
 
 
 
31d6c52
2652f92
 
 
 
 
 
 
 
 
 
e41e94d
fd63faf
2652f92
 
fd63faf
2652f92
 
31d6c52
2652f92
25ee338
72917ff
 
2652f92
25ee338
2652f92
 
25ee338
2652f92
 
5e96c67
6a48ef2
dd82ad4
 
5e96c67
 
 
72917ff
2652f92
dd82ad4
31d6c52
 
fd63faf
31d6c52
6a48ef2
dd82ad4
 
31d6c52
 
 
72917ff
2652f92
 
 
 
 
fd63faf
2652f92
c3b6480
72917ff
2652f92
 
 
dd82ad4
f3e28db
fd63faf
31d6c52
dd82ad4
e41e94d
31d6c52
 
fd63faf
2652f92
 
 
 
6a48ef2
dd82ad4
 
6a48ef2
2652f92
31d6c52
f3e28db
2652f92
 
 
 
 
 
 
 
6a48ef2
dd82ad4
 
6a48ef2
2652f92
31d6c52
f3e28db
2652f92
 
 
 
 
 
 
 
f3e28db
fd63faf
2652f92
 
 
fd63faf
2652f92
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
"""Unit tests for TextProcessor class."""

from unittest.mock import MagicMock, patch

from yomitalk.common import APIType
from yomitalk.components.text_processor import TextProcessor
from yomitalk.prompt_manager import DocumentType, PodcastMode


class TestTextProcessor:
    """Test class for TextProcessor."""

    def setup_method(self):
        """Set up test fixtures before each test method is run."""
        self.text_processor = TextProcessor()

    def test_initialization(self):
        """Test that TextProcessor initializes correctly."""
        # Check that the basic attributes are initialized
        assert hasattr(self.text_processor, "prompt_manager")
        assert hasattr(self.text_processor, "openai_model")
        assert hasattr(self.text_processor, "gemini_model")
        assert hasattr(self.text_processor, "current_api_type")

        # Check default values
        assert self.text_processor.current_api_type is None

    @patch("yomitalk.components.text_processor.OpenAIModel")
    def test_set_openai_api_key(self, mock_openai_model):
        """Test setting OpenAI API key."""
        # Mock the OpenAI model
        mock_instance = MagicMock()
        mock_instance.set_api_key.return_value = True
        mock_openai_model.return_value = mock_instance
        self.text_processor.openai_model = mock_instance

        # Test with valid API key
        api_key = "sk-valid-api-key"
        result = self.text_processor.set_openai_api_key(api_key)

        # Verify results
        assert result is True
        assert self.text_processor.current_api_type == APIType.OPENAI
        mock_instance.set_api_key.assert_called_once_with(api_key)

    @patch("yomitalk.components.text_processor.GeminiModel")
    def test_set_gemini_api_key(self, mock_gemini_model):
        """Test setting Gemini API key."""
        # Mock the Gemini model
        mock_instance = MagicMock()
        mock_instance.set_api_key.return_value = True
        mock_gemini_model.return_value = mock_instance
        self.text_processor.gemini_model = mock_instance

        # Test with valid API key
        api_key = "valid-gemini-api-key"
        result = self.text_processor.set_gemini_api_key(api_key)

        # Verify results
        assert result is True
        assert self.text_processor.current_api_type == APIType.GEMINI
        mock_instance.set_api_key.assert_called_once_with(api_key)

    def test_get_podcast_mode(self):
        """Test getting podcast mode."""
        # 現在のPodcastモードを取得
        result = self.text_processor.get_podcast_mode()
        # モードがPodcastModeのインスタンスであることを確認
        assert isinstance(result, PodcastMode)

    def test_set_api_type(self):
        """Test setting API type."""
        # Clear environment API keys and APIが設定されていない場合
        with (
            patch.object(self.text_processor.openai_model, "has_api_key", return_value=False),
            patch.object(self.text_processor.gemini_model, "has_api_key", return_value=False),
        ):
            assert self.text_processor.set_api_type(APIType.OPENAI) is False
            assert self.text_processor.set_api_type(APIType.GEMINI) is False

        # APIが設定されている場合をシミュレート
        with patch.object(self.text_processor.openai_model, "has_api_key", return_value=True):
            assert self.text_processor.set_api_type(APIType.OPENAI) is True
            assert self.text_processor.get_current_api_type() == APIType.OPENAI

        # OpenAI APIキーが設定されていないがGemini APIキーがある場合
        with (
            patch.object(self.text_processor.openai_model, "has_api_key", return_value=False),
            patch.object(self.text_processor.gemini_model, "has_api_key", return_value=True),
        ):
            assert self.text_processor.set_api_type(APIType.GEMINI) is True
            assert self.text_processor.get_current_api_type() == APIType.GEMINI

    def test_set_document_type(self):
        """Test setting document type."""
        # DocumentTypeを設定するテスト
        result = self.text_processor.set_document_type(DocumentType.PAPER)
        assert result is True

        # 設定されたドキュメントタイプを確認
        assert self.text_processor.prompt_manager.current_document_type is DocumentType.PAPER

    def test_generate_conversation(self):
        """Test generate podcast conversation."""
        # アップストリームを設定
        with patch.object(self.text_processor.openai_model, "has_api_key", return_value=True):
            self.text_processor.set_api_type(APIType.OPENAI)

            # 簡単なテキストでテスト実行
            result = self.text_processor.generate_podcast_conversation("Test input text")

            # 出力の基本検証
            assert isinstance(result, str)

    def test_api_generation(self):
        """Test API generation methods."""
        # OpenAIとGeminiのAPIがあると仮定したテスト
        # 実際のAPIを呼び出さないでモックする
        with (
            patch.object(self.text_processor.openai_model, "generate_text") as mock_openai,
            patch.object(self.text_processor.openai_model, "has_api_key") as mock_has_api_key,
        ):
            mock_openai.return_value = "OpenAI generated text"
            mock_has_api_key.return_value = True
            self.text_processor.set_api_type(APIType.OPENAI)

            # OpenAIによる生成をテスト
            result = self.text_processor.generate_podcast_conversation("Test")
            assert "OpenAI generated text" in result

    def test_gemini_generation(self):
        """Test Gemini generation."""
        # Geminiのモックをセットアップ
        with (
            patch.object(self.text_processor.gemini_model, "generate_text") as mock_gemini,
            patch.object(self.text_processor.gemini_model, "has_api_key") as mock_has_api_key,
        ):
            mock_gemini.return_value = "Gemini generated text"
            mock_has_api_key.return_value = True
            self.text_processor.set_api_type(APIType.GEMINI)

            # GeminiによるPodcast会話生成をテスト
            result = self.text_processor.generate_podcast_conversation("Test")
            assert "Gemini generated text" in result

    def test_api_configuration_validation(self):
        """Test API configuration validation."""
        # APIキーが設定されていない場合のエラー処理テスト
        # 直接current_api_typeにアクセスする代わりにAPIキーなしの状態をテスト

        # エラーメッセージが返ることを確認
        result = self.text_processor.generate_podcast_conversation("Test")
        assert "Error:" in result  # RuntimeError の代わりにエラーメッセージが返る

    def test_get_template_content(self):
        """Test getting template content."""
        # テンプレート内容を取得するテスト
        result = self.text_processor.get_template_content()
        assert isinstance(result, str)