Skip to content

Commit 01dd422

Browse files
committed
tests: add filesystem tests
1 parent 57fada3 commit 01dd422

File tree

4 files changed

+121
-7
lines changed

4 files changed

+121
-7
lines changed

src/mega/data_structures.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ class Node(_DictDumper):
212212
type: NodeType
213213
attributes: Attributes
214214
created_at: TimeStamp
215-
keys: MappingProxyType[UserID, str]
215+
keys: MappingProxyType[UserID, str] = dataclasses.field(compare=False)
216216
share_owner: UserID | None
217217
share_key: str | None
218218

@@ -250,7 +250,7 @@ def from_dump(cls, dump: dict[str, Any], /) -> Self:
250250
dump = dump | dict( # noqa: C408
251251
type=NodeType[str(dump["type"]).upper()],
252252
attributes=Attributes(**dump["attributes"]) if dump["attributes"] else None,
253-
_crypto=Crypto.from_dump(dump["_crypto"]),
253+
_crypto=Crypto.from_dump(dump["_crypto"]) if dump["_crypto"] else None,
254254
)
255255

256256
return cls(**dump)

src/mega/filesystem.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1+
from __future__ import annotations
2+
13
import dataclasses
24
import errno
3-
from collections.abc import Generator, Iterable, Iterator, Sequence
4-
from os import PathLike
55
from pathlib import PurePosixPath
66
from types import MappingProxyType
7-
from typing import Any, Self
7+
from typing import TYPE_CHECKING, Any, Self
88

99
from mega.data_structures import Node, NodeID, NodeType, _DictDumper
1010
from mega.errors import MultipleNodesFoundError
1111

12+
if TYPE_CHECKING:
13+
from collections.abc import Generator, Iterable, Iterator, Sequence
14+
from os import PathLike
15+
1216
_POSIX_ROOT = PurePosixPath("/")
1317

1418

tests/fake_fs.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@
421421
"owner": "me",
422422
"type": "file",
423423
"attributes": {
424-
"name": "main.py",
424+
"name": "logo.png",
425425
"label": "blue",
426426
"favorited": false
427427
},
@@ -868,7 +868,7 @@
868868
"MBlNlb2P": "/styles.css",
869869
"7N9QiWZ9": "/tests",
870870
"RDJJI2lv": "/tests/logo.png",
871-
"pHWVIQLd": "/tests/main.py",
871+
"pHWVIQLd": "/tests/logo.png",
872872
"oImwb6nN": "/tests/script.js",
873873
"FIXitv4F": "/tests/scripts",
874874
"0fPFklV3": "/tests/scripts/notes.txt",

tests/test_filesystem.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
from __future__ import annotations
2+
3+
import json
4+
from pathlib import Path, PurePosixPath
5+
6+
import pytest
7+
8+
from mega.data_structures import Node
9+
from mega.errors import MultipleNodesFoundError
10+
from mega.filesystem import UserFileSystem
11+
12+
NODE_ID = "0fPFklV3"
13+
FIND_NODE_ID = "0fPFklV3"
14+
DELETED_NODE_IDS = "t8HkzBH2", "8EwHVJna"
15+
16+
17+
@pytest.fixture(name="fs")
18+
async def filesystem() -> UserFileSystem:
19+
return UserFileSystem.from_dump(json.loads(Path("fake_fs.json").read_text()))
20+
21+
22+
def test_filesystem_has_root(fs: UserFileSystem) -> None:
23+
assert isinstance(fs, UserFileSystem)
24+
assert fs.root
25+
assert fs.inbox
26+
assert fs.trash_bin
27+
28+
29+
def test_magic_methods(fs: UserFileSystem) -> None:
30+
assert len(fs) == 20
31+
assert len(fs) == fs.file_count + fs.folder_count + 3
32+
assert isinstance(next(iter(fs)), Node)
33+
node = fs[NODE_ID]
34+
assert isinstance(node, Node)
35+
assert node.id == NODE_ID
36+
assert node.id in fs
37+
assert node not in fs
38+
39+
40+
def test_deleted(fs: UserFileSystem) -> None:
41+
deleted = set(fs.deleted)
42+
assert deleted == {fs[DELETED_NODE_IDS[0]]}
43+
all_deleted = set(fs.iterdir(fs.trash_bin.id, recursive=True))
44+
assert all_deleted == {
45+
fs[DELETED_NODE_IDS[0]],
46+
fs[DELETED_NODE_IDS[1]],
47+
}
48+
49+
50+
def test_path_resolve(fs: UserFileSystem) -> None:
51+
path = "tests/scripts/script.js"
52+
rel_path = PurePosixPath(path)
53+
node = fs.find(path)
54+
assert node is fs.find(rel_path)
55+
assert fs.relative_path(node.id) == rel_path
56+
assert fs.resolve(node.id) == PurePosixPath("/") / rel_path
57+
58+
59+
def test_search(fs: UserFileSystem) -> None:
60+
query = "tests/script"
61+
results = dict(fs.search(query))
62+
expected = (
63+
"/tests/script.js",
64+
"/tests/scripts",
65+
"/tests/scripts/notes.txt",
66+
"/tests/scripts/script.js",
67+
"/tests/scripts/styles.css",
68+
)
69+
70+
assert sorted(results.values()) == sorted(PurePosixPath(v) for v in expected)
71+
72+
73+
def test_find(fs: UserFileSystem) -> None:
74+
node = fs.find("/tests/scripts/notes.txt")
75+
assert node is fs[FIND_NODE_ID]
76+
77+
with pytest.raises(FileNotFoundError):
78+
fs.find("/this/path/does/not/exists")
79+
80+
with pytest.raises(FileNotFoundError):
81+
fs.find("/tests/script")
82+
83+
with pytest.raises(MultipleNodesFoundError):
84+
fs.find("/tests/logo.png")
85+
86+
87+
def test_iter_dir(fs: UserFileSystem) -> None:
88+
children = (
89+
"/tests/logo.png",
90+
"/tests/logo.png",
91+
"/tests/script.js",
92+
"/tests/scripts",
93+
"/tests/setup.sh",
94+
"/tests/utils.py",
95+
)
96+
97+
recursive_children = (
98+
*children,
99+
"/tests/scripts/notes.txt",
100+
"/tests/scripts/script.js",
101+
"/tests/scripts/styles.css",
102+
)
103+
104+
node = fs.find("/tests")
105+
106+
def get_path(recursive: bool) -> list[str]:
107+
return sorted(str(fs.resolve(n.id)) for n in fs.iterdir(node.id, recursive=recursive))
108+
109+
assert get_path(recursive=False) == sorted(children)
110+
assert get_path(recursive=True) == sorted(recursive_children)

0 commit comments

Comments
 (0)