Initial commit
This commit is contained in:
commit
9c7df76fbd
91 files changed
+36572
No files matched your search
@@ -0,0 +1,147 @@
|
||||
"""
|
||||
test_checkpoint.py — Tests for checkpoint.py.
|
||||
|
||||
Covers:
|
||||
- _checkpoint_key: stable hashing of scan options
|
||||
- _save_checkpoint / _load_checkpoint / _clear_checkpoint
|
||||
- _load_delta_tokens / _save_delta_tokens
|
||||
"""
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
import checkpoint
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Fixtures
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _isolate(tmp_path, monkeypatch):
|
||||
"""Redirect all disk writes to a temp dir for each test."""
|
||||
monkeypatch.setattr(checkpoint, "_CHECKPOINT_PATH", tmp_path / "checkpoint.json")
|
||||
monkeypatch.setattr(checkpoint, "_DELTA_PATH", tmp_path / "delta.json")
|
||||
|
||||
|
||||
_OPTS = {
|
||||
"sources": ["email", "onedrive"],
|
||||
"user_ids": [{"id": "user-1"}, {"id": "user-2"}],
|
||||
"options": {"older_than_days": 365},
|
||||
}
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 1. _checkpoint_key
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
class TestCheckpointKey:
|
||||
|
||||
def test_returns_string(self):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
assert isinstance(key, str)
|
||||
|
||||
def test_key_is_hex(self):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
int(key, 16) # raises ValueError if not hex
|
||||
|
||||
def test_same_options_same_key(self):
|
||||
assert checkpoint._checkpoint_key(_OPTS) == checkpoint._checkpoint_key(_OPTS)
|
||||
|
||||
def test_different_sources_different_key(self):
|
||||
opts2 = {**_OPTS, "sources": ["sharepoint"]}
|
||||
assert checkpoint._checkpoint_key(_OPTS) != checkpoint._checkpoint_key(opts2)
|
||||
|
||||
def test_different_users_different_key(self):
|
||||
opts2 = {**_OPTS, "user_ids": [{"id": "user-99"}]}
|
||||
assert checkpoint._checkpoint_key(_OPTS) != checkpoint._checkpoint_key(opts2)
|
||||
|
||||
def test_source_order_irrelevant(self):
|
||||
opts_a = {**_OPTS, "sources": ["email", "onedrive"]}
|
||||
opts_b = {**_OPTS, "sources": ["onedrive", "email"]}
|
||||
assert checkpoint._checkpoint_key(opts_a) == checkpoint._checkpoint_key(opts_b)
|
||||
|
||||
def test_empty_options(self):
|
||||
key = checkpoint._checkpoint_key({})
|
||||
assert isinstance(key, str) and len(key) > 0
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 2. Save / load / clear
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
class TestSaveLoadCheckpoint:
|
||||
|
||||
def test_load_returns_none_when_no_file(self):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
assert checkpoint._load_checkpoint(key) is None
|
||||
|
||||
def test_save_then_load(self):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
checkpoint._save_checkpoint(
|
||||
key,
|
||||
scanned_ids={"id1", "id2", "id3"},
|
||||
flagged=[{"id": "c1", "name": "file.docx"}],
|
||||
meta={"started_at": 1700000000},
|
||||
)
|
||||
loaded = checkpoint._load_checkpoint(key)
|
||||
assert loaded is not None
|
||||
|
||||
def test_scanned_ids_preserved(self):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
checkpoint._save_checkpoint(key, {"id1", "id2"}, [], {})
|
||||
loaded = checkpoint._load_checkpoint(key)
|
||||
assert set(loaded["scanned_ids"]) == {"id1", "id2"}
|
||||
|
||||
def test_flagged_items_preserved(self):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
cards = [{"id": "c1"}, {"id": "c2"}]
|
||||
checkpoint._save_checkpoint(key, set(), cards, {})
|
||||
loaded = checkpoint._load_checkpoint(key)
|
||||
assert len(loaded["flagged"]) == 2
|
||||
|
||||
def test_wrong_key_returns_none(self):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
checkpoint._save_checkpoint(key, {"id1"}, [], {})
|
||||
other_opts = {**_OPTS, "sources": ["sharepoint"]}
|
||||
other_key = checkpoint._checkpoint_key(other_opts)
|
||||
assert checkpoint._load_checkpoint(other_key) is None
|
||||
|
||||
def test_clear_removes_file(self, tmp_path):
|
||||
key = checkpoint._checkpoint_key(_OPTS)
|
||||
checkpoint._save_checkpoint(key, {"id1"}, [], {})
|
||||
checkpoint._clear_checkpoint()
|
||||
assert checkpoint._load_checkpoint(key) is None
|
||||
|
||||
def test_clear_on_missing_file_does_not_raise(self):
|
||||
checkpoint._clear_checkpoint() # no file exists — must not raise
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# 3. Delta tokens
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
class TestDeltaTokens:
|
||||
|
||||
def test_load_returns_empty_when_no_file(self):
|
||||
assert checkpoint._load_delta_tokens() == {}
|
||||
|
||||
def test_save_then_load(self):
|
||||
tokens = {
|
||||
"email:user1": "https://graph.microsoft.com/v1.0/me/mailFolders/delta?$deltaToken=abc",
|
||||
"onedrive:user1": "https://graph.microsoft.com/v1.0/me/drive/delta?token=xyz",
|
||||
}
|
||||
checkpoint._save_delta_tokens(tokens)
|
||||
loaded = checkpoint._load_delta_tokens()
|
||||
assert loaded == tokens
|
||||
|
||||
def test_overwrite_preserves_new_value(self):
|
||||
checkpoint._save_delta_tokens({"key": "old_url"})
|
||||
checkpoint._save_delta_tokens({"key": "new_url"})
|
||||
assert checkpoint._load_delta_tokens()["key"] == "new_url"
|
||||
|
||||
def test_save_empty_dict(self):
|
||||
checkpoint._save_delta_tokens({})
|
||||
assert checkpoint._load_delta_tokens() == {}
|
||||
Reference in new issue
Block a user