import tempfile from collections.abc import AsyncIterator from pathlib import Path import pytest from watchfiles import Change as FileChange from beaver_gateway.vault import watch as watch_module from beaver_gateway.vault.watch import VaultFilter, VaultWatch, WatchRules VAULT = Path("/vault") FILTER = VaultFilter() def wakes(rel: str) -> bool: return FILTER(FileChange.modified, str(VAULT / rel)) def test_obsidian_never_wakes_the_watcher() -> None: assert not wakes(".obsidian/.sync.lock") assert not wakes(".obsidian/.sync.lock/data") assert not wakes(".obsidian") assert not wakes(".obsidian/workspace.json") assert not wakes(".obsidian/plugins/obsidian-git/data.json") def test_other_service_paths_never_wake_the_watcher() -> None: assert not wakes(".trash/📅 дни/2026-09-01.md") assert not wakes(".git/index") def test_notes_still_wake_the_watcher() -> None: assert wakes("📅 дни/2026-09-09.md") assert wakes("мета/бобер/состояние.md") assert wakes("заметка.md") assert wakes("💻 проекты/бобер/план.md") def test_lock_beside_a_note_is_quiet_but_the_note_is_not() -> None: assert not wakes("📅 дни/.2026-09-09.md.lock") assert not wakes("📅 дни/2026-09-09.md.tmp") assert not wakes("📅 дни/2026-09-09.md~") assert wakes("📅 дни/2026-09-09.md") async def test_the_filter_is_applied_by_awatch_itself( monkeypatch: pytest.MonkeyPatch, ) -> None: seen: dict[str, object] = {} async def fake_awatch( *paths: object, **kwargs: object ) -> AsyncIterator[set[object]]: seen.update(kwargs) seen["paths"] = paths for change in (): yield change monkeypatch.setattr(watch_module, "awatch", fake_awatch) root = Path(tempfile.mkdtemp(prefix="beaver-vault-")) watch = VaultWatch(root, WatchRules(names=("**",)), tz="UTC") await watch.run() assert isinstance(seen["watch_filter"], VaultFilter)