File size: 9,763 Bytes
0828c2c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
"""Tests for main document exclusion in document processing."""

import copy

import pytest

from src.config_loader import get_config
from src.document_processor import DocumentProcessor


@pytest.fixture(autouse=True)
def cleanup_config():
    """Ensure config is properly restored after each test in this module."""
    config = get_config()
    # Save original get method
    original_get = config.get
    # Save original config
    original_config = copy.deepcopy(config._config)

    yield

    # Restore original get method and config
    config.get = original_get
    config._config = original_config


class TestMainDocumentExclusion:
    """Test that main document is excluded from vector store processing."""

    def test_main_document_excluded_from_processing(self, tmp_path):
        """Test that main document file is skipped during directory processing."""
        # Create test documents directory
        docs_dir = tmp_path / "documents"
        docs_dir.mkdir()

        # Create main document
        main_doc = docs_dir / "main_profile.md"
        main_doc.write_text("# Main Profile\n\nThis should be excluded.")

        # Create other documents
        other_doc1 = docs_dir / "resume.md"
        other_doc1.write_text("# Resume\n\nThis should be included.")

        other_doc2 = docs_dir / "projects.md"
        other_doc2.write_text("# Projects\n\nThis should also be included.")

        # Create processor and mock config
        processor = DocumentProcessor()
        original_get = processor.config.get

        def mock_get(key, default=None):
            if key == "main_document.path":
                return str(main_doc)
            if key == "main_document.exclude_from_index":
                return True
            return original_get(key, default)

        processor.config.get = mock_get

        # Process directory
        documents = processor.process_directory(docs_dir)

        # Get all source files from processed documents
        processed_files = {doc.metadata.get("source", "") for doc in documents}

        # Main document should NOT be in processed files
        assert str(main_doc) not in processed_files

        # Other documents SHOULD be processed
        assert any("resume.md" in source for source in processed_files)
        assert any("projects.md" in source for source in processed_files)

    def test_main_document_included_when_exclude_from_index_false(self, tmp_path):
        """Test main document is indexed when exclude_from_index is false."""
        docs_dir = tmp_path / "documents"
        docs_dir.mkdir()

        main_doc = docs_dir / "main_profile.md"
        main_doc.write_text("# Main Profile\n\nShould be indexed.")

        processor = DocumentProcessor()
        original_get = processor.config.get

        def mock_get(key, default=None):
            if key == "main_document.path":
                return str(main_doc)
            if key == "main_document.exclude_from_index":
                return False
            return original_get(key, default)

        processor.config.get = mock_get

        documents = processor.process_directory(docs_dir)
        processed_files = {doc.metadata.get("source", "") for doc in documents}

        assert any("main_profile.md" in source for source in processed_files)

    def test_all_documents_processed_when_main_doc_disabled(self, tmp_path):
        """Test that all documents are processed when main doc feature is disabled."""
        # Create test documents directory
        docs_dir = tmp_path / "documents"
        docs_dir.mkdir()

        # Create documents including what would be the main document
        main_doc = docs_dir / "main_profile.md"
        main_doc.write_text("# Main Profile\n\nContent here.")

        other_doc = docs_dir / "resume.md"
        other_doc.write_text("# Resume\n\nContent here.")

        # Create processor with main doc disabled
        processor = DocumentProcessor()
        original_get = processor.config.get

        def mock_get(key, default=None):
            if key == "main_document.path":
                return ""  # Empty path = disabled
            return original_get(key, default)

        processor.config.get = mock_get

        # Process directory
        documents = processor.process_directory(docs_dir)

        # Get all source files
        processed_files = {doc.metadata.get("source", "") for doc in documents}

        # ALL documents should be processed (including main_profile.md)
        assert any("main_profile.md" in source for source in processed_files)
        assert any("resume.md" in source for source in processed_files)

    def test_main_document_exclusion_case_insensitive_paths(self, tmp_path):
        """Test that path comparison works regardless of path format."""
        docs_dir = tmp_path / "documents"
        docs_dir.mkdir()

        # Create main document
        main_doc = docs_dir / "main_profile.md"
        main_doc.write_text("# Main Profile\n\nExclude me.")

        other_doc = docs_dir / "other.md"
        other_doc.write_text("# Other\n\nInclude me.")

        processor = DocumentProcessor()
        original_get = processor.config.get

        def mock_get(key, default=None):
            if key == "main_document.path":
                # Return path with different format but same file
                return str(main_doc.resolve())
            if key == "main_document.exclude_from_index":
                return True
            return original_get(key, default)

        processor.config.get = mock_get

        # Process directory
        documents = processor.process_directory(docs_dir)

        # Get all source files
        processed_files = {doc.metadata.get("source", "") for doc in documents}

        # Main document should be excluded
        assert str(main_doc) not in processed_files
        assert str(main_doc.resolve()) not in processed_files

        # Other document should be included
        assert len(documents) > 0
        assert any("other.md" in source for source in processed_files)

    def test_subdirectory_main_document_excluded(self, tmp_path):
        """Test that main document in subdirectory is excluded."""
        docs_dir = tmp_path / "documents"
        docs_dir.mkdir()

        # Create subdirectory
        subdir = docs_dir / "profiles"
        subdir.mkdir()

        # Create main document in subdirectory
        main_doc = subdir / "main_profile.md"
        main_doc.write_text("# Main Profile\n\nExclude me.")

        # Create other document
        other_doc = docs_dir / "resume.md"
        other_doc.write_text("# Resume\n\nInclude me.")

        processor = DocumentProcessor()
        original_get = processor.config.get

        def mock_get(key, default=None):
            if key == "main_document.path":
                return str(main_doc)
            if key == "main_document.exclude_from_index":
                return True
            return original_get(key, default)

        processor.config.get = mock_get

        # Process directory (recursively)
        documents = processor.process_directory(docs_dir)

        # Get all source files
        processed_files = {doc.metadata.get("source", "") for doc in documents}

        # Main document should be excluded
        assert str(main_doc) not in processed_files

        # Other document should be included
        assert any("resume.md" in source for source in processed_files)

    def test_no_documents_after_main_doc_exclusion(self, tmp_path):
        """Test behavior when only main document exists."""
        docs_dir = tmp_path / "documents"
        docs_dir.mkdir()

        # Create only the main document
        main_doc = docs_dir / "main_profile.md"
        main_doc.write_text("# Main Profile\n\nOnly document.")

        processor = DocumentProcessor()
        original_get = processor.config.get

        def mock_get(key, default=None):
            if key == "main_document.path":
                return str(main_doc)
            if key == "main_document.exclude_from_index":
                return True
            return original_get(key, default)

        processor.config.get = mock_get

        # Process directory
        documents = processor.process_directory(docs_dir)

        # Should have no documents (only main doc was excluded)
        assert len(documents) == 0

    def test_main_document_with_different_extension_not_confused(self, tmp_path):
        """Test that only exact main document file is excluded."""
        docs_dir = tmp_path / "documents"
        docs_dir.mkdir()

        # Create main document (PDF)
        main_doc = docs_dir / "main_profile.pdf"
        main_doc.write_text("PDF content")

        # Create similar named file (MD) - should NOT be excluded
        similar_doc = docs_dir / "main_profile.md"
        similar_doc.write_text("# Main Profile\n\nInclude me.")

        processor = DocumentProcessor()
        original_get = processor.config.get

        def mock_get(key, default=None):
            if key == "main_document.path":
                return str(main_doc)  # Only PDF is main doc
            if key == "main_document.exclude_from_index":
                return True
            return original_get(key, default)

        processor.config.get = mock_get

        # Process directory
        documents = processor.process_directory(docs_dir)

        # Get all source files
        processed_files = {doc.metadata.get("source", "") for doc in documents}

        # MD file should be included (different extension)
        assert any("main_profile.md" in source for source in processed_files)

        # PDF should be excluded
        # Note: PDF loading might fail with text content, but it should be skipped anyway