-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_client.py
More file actions
111 lines (87 loc) · 4.86 KB
/
test_client.py
File metadata and controls
111 lines (87 loc) · 4.86 KB
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
"""Tests for the Capture client."""
import pytest
from numbersprotocol_capture import Capture, ValidationError
class TestCaptureClient:
"""Tests for Capture client initialization."""
def test_init_with_token(self) -> None:
"""Test client initialization with token."""
capture = Capture(token="test-token")
assert capture._token == "test-token"
assert capture._testnet is False
capture.close()
def test_init_without_token_raises_error(self) -> None:
"""Test that missing token raises ValidationError."""
with pytest.raises(ValidationError, match="token is required"):
Capture(token="")
def test_init_with_testnet(self) -> None:
"""Test client initialization with testnet flag."""
capture = Capture(token="test-token", testnet=True)
assert capture._testnet is True
capture.close()
def test_init_with_custom_base_url(self) -> None:
"""Test client initialization with custom base URL."""
capture = Capture(token="test-token", base_url="https://custom.api.com")
assert capture._base_url == "https://custom.api.com"
capture.close()
def test_context_manager(self) -> None:
"""Test client as context manager."""
with Capture(token="test-token") as capture:
assert capture._token == "test-token"
class TestValidation:
"""Tests for input validation."""
def test_register_empty_file_raises_error(self, tmp_path) -> None:
"""Test that empty file raises ValidationError."""
empty_file = tmp_path / "empty.txt"
empty_file.write_bytes(b"")
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="file cannot be empty"):
capture.register(str(empty_file))
def test_register_headline_too_long_raises_error(self, tmp_path) -> None:
"""Test that headline over 25 chars raises ValidationError."""
test_file = tmp_path / "test.txt"
test_file.write_bytes(b"test content")
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="headline must be 25 characters or less"):
capture.register(str(test_file), headline="a" * 30)
def test_register_binary_without_filename_raises_error(self) -> None:
"""Test that binary input without filename raises ValidationError."""
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="filename is required"):
capture.register(b"test content")
def test_get_empty_nid_raises_error(self) -> None:
"""Test that empty NID raises ValidationError."""
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="nid is required"):
capture.get("")
def test_update_empty_nid_raises_error(self) -> None:
"""Test that empty NID raises ValidationError."""
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="nid is required"):
capture.update("", caption="test")
class TestNidFormatValidation:
"""Tests for NID format validation (path traversal prevention)."""
def test_get_rejects_path_traversal_nid(self) -> None:
"""Test that nid with path traversal characters is rejected."""
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="nid contains invalid characters"):
capture.get("../../admin/users")
def test_update_rejects_path_traversal_nid(self) -> None:
"""Test that nid with path traversal characters is rejected in update."""
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="nid contains invalid characters"):
capture.update("../../admin/users", caption="x")
def test_get_rejects_nid_with_url_special_chars(self) -> None:
"""Test that nid with URL-special characters is rejected."""
with Capture(token="test-token") as capture:
with pytest.raises(ValidationError, match="nid contains invalid characters"):
capture.get("bafybei?inject=1")
with pytest.raises(ValidationError, match="nid contains invalid characters"):
capture.get("bafybei#fragment")
def test_get_accepts_valid_alphanumeric_nid(self) -> None:
"""Test that a valid alphanumeric NID passes format validation."""
valid_nid = "bafybeif3mhxhkhfwuszl2lybtai3hz3q6naqpfisd4q55mcc7opkmiv5ei"
with Capture(token="test-token") as capture:
# Should not raise ValidationError for format; will fail at network level
with pytest.raises(Exception) as exc_info:
capture.get(valid_nid)
assert "nid contains invalid characters" not in str(exc_info.value)