PlanOpticon

planopticon / tests / test_cloud_sources.py
Blame History Raw 214 lines
1
"""Tests for cloud source integrations."""
2
3
import json
4
from pathlib import Path
5
from unittest.mock import MagicMock, patch
6
7
import pytest
8
9
from video_processor.sources.base import BaseSource, SourceFile
10
11
12
class TestSourceFile:
13
def test_basic(self):
14
f = SourceFile(name="video.mp4", id="abc123")
15
assert f.name == "video.mp4"
16
assert f.id == "abc123"
17
18
def test_full(self):
19
f = SourceFile(
20
name="meeting.mp4",
21
id="xyz",
22
size_bytes=1024000,
23
mime_type="video/mp4",
24
modified_at="2025-01-01T00:00:00Z",
25
path="/recordings/meeting.mp4",
26
)
27
assert f.size_bytes == 1024000
28
assert f.path == "/recordings/meeting.mp4"
29
30
def test_round_trip(self):
31
f = SourceFile(name="test.mp4", id="1")
32
data = f.model_dump_json()
33
restored = SourceFile.model_validate_json(data)
34
assert restored.name == f.name
35
36
37
class TestBaseSource:
38
def test_download_all(self, tmp_path):
39
class FakeSource(BaseSource):
40
def authenticate(self):
41
return True
42
43
def list_videos(self, **kwargs):
44
return []
45
46
def download(self, file, destination):
47
destination.write_text("fake video data")
48
return destination
49
50
source = FakeSource()
51
files = [
52
SourceFile(name="a.mp4", id="1"),
53
SourceFile(name="b.mp4", id="2"),
54
]
55
paths = source.download_all(files, tmp_path / "downloads")
56
assert len(paths) == 2
57
assert (tmp_path / "downloads" / "a.mp4").exists()
58
assert (tmp_path / "downloads" / "b.mp4").exists()
59
60
def test_download_all_handles_errors(self, tmp_path):
61
class FailingSource(BaseSource):
62
def authenticate(self):
63
return True
64
65
def list_videos(self, **kwargs):
66
return []
67
68
def download(self, file, destination):
69
raise RuntimeError("Download failed")
70
71
source = FailingSource()
72
files = [SourceFile(name="fail.mp4", id="1")]
73
paths = source.download_all(files, tmp_path / "downloads")
74
assert len(paths) == 0
75
76
77
class TestGoogleDriveSource:
78
def test_init_defaults(self):
79
from video_processor.sources.google_drive import GoogleDriveSource
80
81
source = GoogleDriveSource()
82
assert source.service is None
83
assert source.use_service_account is None
84
85
def test_init_with_credentials(self):
86
from video_processor.sources.google_drive import GoogleDriveSource
87
88
source = GoogleDriveSource(
89
credentials_path="/path/to/creds.json",
90
use_service_account=True,
91
)
92
assert source.credentials_path == "/path/to/creds.json"
93
assert source.use_service_account is True
94
95
def test_is_service_account_true(self, tmp_path):
96
from video_processor.sources.google_drive import GoogleDriveSource
97
98
creds_file = tmp_path / "sa.json"
99
creds_file.write_text(json.dumps({"type": "service_account"}))
100
source = GoogleDriveSource(credentials_path=str(creds_file))
101
assert source._is_service_account() is True
102
103
def test_is_service_account_false(self, tmp_path):
104
from video_processor.sources.google_drive import GoogleDriveSource
105
106
creds_file = tmp_path / "oauth.json"
107
creds_file.write_text(json.dumps({"installed": {}}))
108
source = GoogleDriveSource(credentials_path=str(creds_file))
109
assert source._is_service_account() is False
110
111
@patch.dict("os.environ", {}, clear=True)
112
def test_is_service_account_no_path(self):
113
from video_processor.sources.google_drive import GoogleDriveSource
114
115
source = GoogleDriveSource(credentials_path=None)
116
source.credentials_path = None # Override any env var fallback
117
assert source._is_service_account() is False
118
119
def test_list_videos_not_authenticated(self):
120
from video_processor.sources.google_drive import GoogleDriveSource
121
122
source = GoogleDriveSource()
123
with pytest.raises(RuntimeError, match="Not authenticated"):
124
source.list_videos(folder_id="abc")
125
126
def test_download_not_authenticated(self):
127
from video_processor.sources.google_drive import GoogleDriveSource
128
129
source = GoogleDriveSource()
130
f = SourceFile(name="test.mp4", id="1")
131
with pytest.raises(RuntimeError, match="Not authenticated"):
132
source.download(f, Path("/tmp/test.mp4"))
133
134
@patch("video_processor.sources.google_drive.GoogleDriveSource._auth_service_account")
135
def test_authenticate_import_error(self, mock_auth):
136
from video_processor.sources.google_drive import GoogleDriveSource
137
138
source = GoogleDriveSource()
139
with patch.dict(
140
"sys.modules", {"google.oauth2": None, "google.oauth2.service_account": None}
141
):
142
# The import will fail inside authenticate
143
result = source.authenticate()
144
assert result is False
145
146
147
class TestDropboxSource:
148
def test_init_defaults(self):
149
from video_processor.sources.dropbox_source import DropboxSource
150
151
source = DropboxSource()
152
assert source.dbx is None
153
154
def test_init_with_token(self):
155
from video_processor.sources.dropbox_source import DropboxSource
156
157
source = DropboxSource(access_token="test_token")
158
assert source.access_token == "test_token"
159
160
def test_init_with_app_key(self):
161
from video_processor.sources.dropbox_source import DropboxSource
162
163
source = DropboxSource(app_key="key", app_secret="secret")
164
assert source.app_key == "key"
165
assert source.app_secret == "secret"
166
167
def test_list_videos_not_authenticated(self):
168
from video_processor.sources.dropbox_source import DropboxSource
169
170
source = DropboxSource()
171
with pytest.raises(RuntimeError, match="Not authenticated"):
172
source.list_videos(folder_path="/recordings")
173
174
def test_download_not_authenticated(self):
175
from video_processor.sources.dropbox_source import DropboxSource
176
177
source = DropboxSource()
178
f = SourceFile(name="test.mp4", id="1", path="/test.mp4")
179
with pytest.raises(RuntimeError, match="Not authenticated"):
180
source.download(f, Path("/tmp/test.mp4"))
181
182
def test_authenticate_no_sdk(self):
183
from video_processor.sources.dropbox_source import DropboxSource
184
185
source = DropboxSource()
186
with patch.dict("sys.modules", {"dropbox": None}):
187
result = source.authenticate()
188
assert result is False
189
190
def test_auth_saved_token(self, tmp_path):
191
pytest.importorskip("dropbox")
192
from video_processor.sources.dropbox_source import DropboxSource
193
194
token_file = tmp_path / "token.json"
195
token_file.write_text(
196
json.dumps(
197
{
198
"refresh_token": "rt_test",
199
"app_key": "key",
200
"app_secret": "secret",
201
}
202
)
203
)
204
205
source = DropboxSource(token_path=token_file, app_key="key", app_secret="secret")
206
207
mock_dbx = MagicMock()
208
with patch("dropbox.Dropbox", return_value=mock_dbx):
209
import dropbox
210
211
result = source._auth_saved_token(dropbox)
212
assert result is True
213
assert source.dbx is mock_dbx
214

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button