The backend no longer mentions MinIO anywhere: MinioClient -> GarageClient (minio_client.py -> garage_client.py), MINIO_* env vars -> GARAGE_*, and the `minio` Python package is replaced with `boto3` (AWS's generic S3 client) since Garage is the only storage backend this project targets now. S3 API semantics are unchanged, so document_service.py's behavior is identical — this is a naming and dependency swap, not a logic change. Also updates test fixtures/names (FakeMinioClient -> FakeGarageClient, FakeMinioSDK -> FakeS3SDK) and storage/README.md, which no longer frames Garage as a MinIO replacement (that migration note has served its purpose now that no MinIO reference remains in the codebase). Backend: 54/54 tests passing. Frontend: 38/38 tests passing (unaffected, verified for regressions since it talks to the backend only through the unchanged REST API).
81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
from app.search_client import SearchClient
|
|
|
|
|
|
class FakeIndex:
|
|
def __init__(self):
|
|
self.documents = {}
|
|
self.deleted_ids = []
|
|
|
|
def add_documents(self, docs):
|
|
for doc in docs:
|
|
self.documents[doc["id"]] = doc
|
|
|
|
def delete_document(self, doc_id):
|
|
self.documents.pop(doc_id, None)
|
|
self.deleted_ids.append(doc_id)
|
|
|
|
def search(self, query, params=None):
|
|
hits = []
|
|
for doc in self.documents.values():
|
|
if query in doc["content"] or query in doc["title"]:
|
|
formatted = dict(doc)
|
|
if query in doc["content"]:
|
|
formatted["content"] = doc["content"].replace(query, f"<em>{query}</em>")
|
|
hits.append({**doc, "_formatted": formatted})
|
|
return {"hits": hits}
|
|
|
|
|
|
class FakeMeilisearchSDK:
|
|
def __init__(self):
|
|
self.indexes = {}
|
|
|
|
def index(self, name):
|
|
if name not in self.indexes:
|
|
self.indexes[name] = FakeIndex()
|
|
return self.indexes[name]
|
|
|
|
|
|
def test_index_document_adds_document_with_encoded_id():
|
|
sdk = FakeMeilisearchSDK()
|
|
client = SearchClient(sdk, index_name="documents")
|
|
|
|
client.index_document(
|
|
"产品文档/架构设计.md", "产品文档", "架构设计.md", "DocHub 使用 Garage 存储文档"
|
|
)
|
|
|
|
index = sdk.indexes["documents"]
|
|
assert len(index.documents) == 1
|
|
stored = list(index.documents.values())[0]
|
|
assert stored["key"] == "产品文档/架构设计.md"
|
|
assert stored["path"] == "产品文档"
|
|
assert stored["title"] == "架构设计.md"
|
|
assert stored["content"] == "DocHub 使用 Garage 存储文档"
|
|
|
|
|
|
def test_delete_document_removes_document():
|
|
sdk = FakeMeilisearchSDK()
|
|
client = SearchClient(sdk, index_name="documents")
|
|
client.index_document("产品文档/旧文档.md", "产品文档", "旧文档.md", "旧内容")
|
|
|
|
client.delete_document("产品文档/旧文档.md")
|
|
|
|
index = sdk.indexes["documents"]
|
|
assert index.documents == {}
|
|
assert len(index.deleted_ids) == 1
|
|
|
|
|
|
def test_search_returns_matching_documents_with_highlighted_snippet():
|
|
sdk = FakeMeilisearchSDK()
|
|
client = SearchClient(sdk, index_name="documents")
|
|
client.index_document(
|
|
"产品文档/架构设计.md", "产品文档", "架构设计.md", "DocHub 支持全文检索功能"
|
|
)
|
|
|
|
results = client.search("检索")
|
|
|
|
assert len(results) == 1
|
|
assert results[0]["key"] == "产品文档/架构设计.md"
|
|
assert results[0]["title"] == "架构设计.md"
|
|
assert results[0]["path"] == "产品文档"
|
|
assert "<em>检索</em>" in results[0]["snippet"]
|