import zipfile from pathlib import Path def test_source_backup_uses_project_root_and_excludes_runtime_secrets(tmp_path, monkeypatch): from scripts.tools import backup_system project_root = tmp_path / "momo-pro-system" project_root.mkdir() (project_root / "config.py").write_text('SYSTEM_VERSION = "V10.TEST"\n', encoding="utf-8") (project_root / "app.py").write_text("print('app')\n", encoding="utf-8") (project_root / ".env").write_text("SECRET=1\n", encoding="utf-8") (project_root / "config").mkdir() (project_root / "config" / "google_token.json").write_text("{}", encoding="utf-8") (project_root / "config" / "source_contract.json").write_text("{}", encoding="utf-8") (project_root / "services").mkdir() (project_root / "services" / "growth.py").write_text("# ok\n", encoding="utf-8") (project_root / "docs" / "design").mkdir(parents=True) (project_root / "docs" / "design" / "handoff.jsx").write_text("// generated\n", encoding="utf-8") (project_root / "docs" / "guide.md").write_text("guide\n", encoding="utf-8") (project_root / "export_assets").mkdir() (project_root / "export_assets" / "logo.ai").write_text("asset\n", encoding="utf-8") (project_root / "frontend" / ".next").mkdir(parents=True) (project_root / "frontend" / ".next" / "trace").write_text("build\n", encoding="utf-8") (project_root / "frontend" / "app").mkdir() (project_root / "frontend" / "app" / "page.tsx").write_text("// source\n", encoding="utf-8") (project_root / "logs").mkdir() (project_root / "logs" / "system.log").write_text("runtime log\n", encoding="utf-8") (project_root / "MOMO Pro" / "uploads").mkdir(parents=True) (project_root / "MOMO Pro" / "uploads" / "pasted.png").write_text("asset\n", encoding="utf-8") (project_root / "production_v3 3" / "static").mkdir(parents=True) (project_root / "production_v3 3" / "static" / "old.css").write_text("old\n", encoding="utf-8") (project_root / "components").symlink_to("web/templates/components") (project_root / ".claude" / "worktrees").mkdir(parents=True) (project_root / ".claude" / "worktrees" / "old.md").write_text("old", encoding="utf-8") (project_root / "backups").mkdir() (project_root / "backups" / "old.zip").write_text("old", encoding="utf-8") monkeypatch.setenv("MOMO_BACKUP_ROOT", str(project_root)) backup_path = Path(backup_system.create_backup()) assert backup_path.parent == project_root / "backups" assert "V10.TEST" in backup_path.name assert backup_path.exists() with zipfile.ZipFile(backup_path) as archive: names = set(archive.namelist()) assert "app.py" in names assert "config.py" in names assert "services/growth.py" in names assert "docs/guide.md" in names assert "frontend/app/page.tsx" in names assert "config/source_contract.json" in names assert "docs/design/handoff.jsx" not in names assert "export_assets/logo.ai" not in names assert "frontend/.next/trace" not in names assert "logs/system.log" not in names assert "MOMO Pro/uploads/pasted.png" not in names assert "production_v3 3/static/old.css" not in names assert ".env" not in names assert ".claude/worktrees/old.md" not in names assert "components" not in names assert "config/google_token.json" not in names assert "backups/old.zip" not in names assert backup_path.name not in names def test_root_backup_entrypoint_exists(): assert (Path(__file__).resolve().parents[1] / "backup_system.py").exists()