Skip to content

Commit fb90f53

Browse files
committed
tests(cli): Improve test coverage for ls subcommand and handle CollectionNotFoundError
1 parent 9a5da91 commit fb90f53

File tree

2 files changed

+42
-66
lines changed

2 files changed

+42
-66
lines changed

src/vectorcode/subcommands/files/ls.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,28 @@
33

44
from vectorcode.cli_utils import Config
55
from vectorcode.database import get_database_connector
6+
from vectorcode.database.errors import CollectionNotFoundError
67
from vectorcode.database.types import ResultType
78

89
logger = logging.getLogger(name=__name__)
910

1011

1112
async def ls(configs: Config) -> int:
1213
database = get_database_connector(configs)
13-
files = list(
14-
i.path
15-
for i in (
16-
await database.list_collection_content(what=ResultType.document)
17-
).files
18-
)
19-
if configs.pipe:
20-
print(json.dumps(files))
21-
else:
22-
print("\n".join(files))
23-
return 0
14+
try:
15+
files = list(
16+
i.path
17+
for i in (
18+
await database.list_collection_content(what=ResultType.document)
19+
).files
20+
)
21+
if configs.pipe:
22+
print(json.dumps(files))
23+
else:
24+
print("\n".join(files))
25+
return 0
26+
except CollectionNotFoundError:
27+
logger.error(f"There's no existing collection for `{configs.project_root}`.")
28+
return 1
29+
except Exception: # pragma: nocover
30+
raise

tests/subcommands/files/test_files_ls.py

Lines changed: 24 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,47 +2,29 @@
22
from unittest.mock import AsyncMock, patch
33

44
import pytest
5-
from chromadb.api.models.AsyncCollection import AsyncCollection
65

76
from vectorcode.cli_utils import CliAction, Config, FilesAction
7+
from vectorcode.database.errors import CollectionNotFoundError
8+
from vectorcode.database.types import FileInCollection
89
from vectorcode.subcommands.files.ls import ls
910

1011

1112
@pytest.fixture
12-
def client():
13-
return AsyncMock()
14-
15-
16-
@pytest.fixture
17-
def collection():
18-
col = AsyncMock(spec=AsyncCollection)
19-
col.get.return_value = {
20-
"ids": ["id1", "id2", "id3"],
21-
"distances": [0.1, 0.2, 0.3],
22-
"metadatas": [
23-
{"path": "file1.py", "start": 1, "end": 1},
24-
{"path": "file2.py", "start": 1, "end": 1},
25-
{"path": "file3.py", "start": 1, "end": 1},
26-
],
27-
"documents": [
28-
"content1",
29-
"content2",
30-
"content3",
31-
],
32-
}
33-
return col
13+
def mock_db():
14+
db = AsyncMock()
15+
db.list_collection_content.return_value.files = [
16+
FileInCollection(path="file1.py", sha256="hash1"),
17+
FileInCollection(path="file2.py", sha256="hash2"),
18+
FileInCollection(path="file3.py", sha256="hash3"),
19+
]
20+
return db
3421

3522

3623
@pytest.mark.asyncio
37-
async def test_ls(client, collection, capsys):
38-
with (
39-
patch("vectorcode.subcommands.files.ls.ClientManager") as MockClientManager,
40-
patch(
41-
"vectorcode.subcommands.files.ls.get_collection", return_value=collection
42-
),
43-
patch("vectorcode.common.try_server", return_value=True),
24+
async def test_ls(mock_db, capsys):
25+
with patch(
26+
"vectorcode.subcommands.files.ls.get_database_connector", return_value=mock_db
4427
):
45-
MockClientManager.return_value._create_client.return_value = client
4628
await ls(Config(action=CliAction.files, files_action=FilesAction.ls))
4729
out = capsys.readouterr().out
4830
assert "file1.py" in out
@@ -51,27 +33,21 @@ async def test_ls(client, collection, capsys):
5133

5234

5335
@pytest.mark.asyncio
54-
async def test_ls_piped(client, collection, capsys):
55-
with (
56-
patch("vectorcode.subcommands.files.ls.ClientManager") as MockClientManager,
57-
patch(
58-
"vectorcode.subcommands.files.ls.get_collection", return_value=collection
59-
),
60-
patch("vectorcode.common.try_server", return_value=True),
36+
async def test_ls_piped(mock_db, capsys):
37+
with patch(
38+
"vectorcode.subcommands.files.ls.get_database_connector", return_value=mock_db
6139
):
62-
MockClientManager.return_value._create_client.return_value = client
6340
await ls(Config(action=CliAction.files, files_action=FilesAction.ls, pipe=True))
6441
out = capsys.readouterr().out
6542
assert json.dumps(["file1.py", "file2.py", "file3.py"]).strip() == out.strip()
6643

6744

6845
@pytest.mark.asyncio
69-
async def test_ls_no_collection(client, collection, capsys):
70-
with (
71-
patch("vectorcode.subcommands.files.ls.ClientManager") as MockClientManager,
72-
patch("vectorcode.subcommands.files.ls.get_collection", side_effect=ValueError),
46+
async def test_ls_no_collection(mock_db):
47+
mock_db.list_collection_content.side_effect = CollectionNotFoundError
48+
with patch(
49+
"vectorcode.subcommands.files.ls.get_database_connector", return_value=mock_db
7350
):
74-
MockClientManager.return_value._create_client.return_value = client
7551
assert (
7652
await ls(
7753
Config(action=CliAction.files, files_action=FilesAction.ls, pipe=True)
@@ -81,18 +57,11 @@ async def test_ls_no_collection(client, collection, capsys):
8157

8258

8359
@pytest.mark.asyncio
84-
async def test_ls_empty_collection(client, capsys):
85-
mock_collection = AsyncMock(spec=AsyncCollection)
86-
mock_collection.get.return_value = {}
87-
with (
88-
patch("vectorcode.subcommands.files.ls.ClientManager") as MockClientManager,
89-
patch(
90-
"vectorcode.subcommands.files.ls.get_collection",
91-
return_value=mock_collection,
92-
),
93-
patch("vectorcode.common.try_server", return_value=True),
60+
async def test_ls_empty_collection(mock_db):
61+
mock_db.list_collection_content.return_value.files = []
62+
with patch(
63+
"vectorcode.subcommands.files.ls.get_database_connector", return_value=mock_db
9464
):
95-
MockClientManager.return_value._create_client.return_value = client
9665
assert (
9766
await ls(Config(action=CliAction.files, files_action=FilesAction.ls)) == 0
9867
)

0 commit comments

Comments
 (0)