From b052dacda168cde0d3f527e67d9daf35df811785 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Fri, 13 Mar 2026 16:46:33 -0400 Subject: [PATCH] test: Add comprehensive integrity suite for locales, export/import, and bundling --- tests/test_integrity.py | 140 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 tests/test_integrity.py diff --git a/tests/test_integrity.py b/tests/test_integrity.py new file mode 100644 index 0000000..f412228 --- /dev/null +++ b/tests/test_integrity.py @@ -0,0 +1,140 @@ +import json +import os +import shutil +import zipfile +from pathlib import Path +import pytest +from voxvera import cli + +# Helper to find project root +REPO_ROOT = Path(__file__).resolve().parent.parent + +def test_locale_completeness(): + """Verify that all non-English locales have the same keys as English.""" + locales_dir = REPO_ROOT / "voxvera" / "locales" + en_path = locales_dir / "en.json" + + with open(en_path, "r", encoding="utf-8") as f: + en_data = json.load(f) + + # Flatten keys for easier comparison + def get_keys(d, prefix=""): + keys = set() + for k, v in d.items(): + if isinstance(v, dict): + keys.update(get_keys(v, f"{prefix}{k}.")) + else: + keys.add(f"{prefix}{k}") + return keys + + en_keys = get_keys(en_data) + + locale_files = list(locales_dir.glob("*.json")) + assert len(locale_files) >= 10, "Should have at least 10 languages supported" + + missing_info = [] + for lp in locale_files: + if lp.name == "en.json": + continue + with open(lp, "r", encoding="utf-8") as f: + data = json.load(f) + keys = get_keys(data) + missing = en_keys - keys + if missing: + missing_info.append(f"{lp.name} is missing: {missing}") + + assert not missing_info, "\n".join(missing_info) + + +def test_export_import_roundtrip(tmp_path, monkeypatch): + """Verify that export -> import preserves the Tor identity key perfectly.""" + # Setup tmp environment + shutil.copytree(REPO_ROOT / "voxvera" / "src", tmp_path / "src") + shutil.copytree(REPO_ROOT / "voxvera" / "locales", tmp_path / "locales") + monkeypatch.setattr(cli, "ROOT", tmp_path) + monkeypatch.setattr(cli, "_src_res", lambda *p: tmp_path / "src" / Path(*p)) + monkeypatch.setattr(cli, "_locale_res", lambda *p: tmp_path / "locales" / Path(*p)) + + # Create a site with a "secret" Tor key + folder_name = "secret-site" + site_dir = tmp_path / "host" / folder_name + site_dir.mkdir(parents=True) + + config = {"folder_name": folder_name, "name": "Secret", "lang": "en"} + with open(site_dir / "config.json", "w") as f: + json.dump(config, f) + + secret_key = "THIS-IS-A-VERY-SECRET-TOR-KEY-12345" + session_file = site_dir / ".onionshare-session" + session_file.write_text(secret_key) + + # Export it + export_zip = tmp_path / "export.zip" + cli.export_site(folder_name, output_path=str(export_zip)) + assert export_zip.exists() + + # Delete the original site + shutil.rmtree(site_dir) + assert not site_dir.exists() + + # Import it + cli.import_site(str(export_zip)) + + # Verify the key is exactly the same + restored_key = (tmp_path / "host" / folder_name / ".onionshare-session").read_text() + assert restored_key == secret_key + assert (tmp_path / "host" / folder_name / "config.json").exists() + + +def test_visual_width_logic(): + """Verify that visual width calculation handles CJK and Hindi correctly.""" + # Test cases: (string, expected_width) + cases = [ + ("Hello", 5), + ("日本語", 6), # Each char is 2 units wide + ("हिन्दी", 5), # Hindi chars vary, but should be handled by wcwidth + ("~~REDACTED~~", 13), + ("W" * 10, 10), + ] + + for text, expected in cases: + width = cli._get_visual_width(text) + assert width >= expected - 1, f"Width for '{text}' too low: {width}" + + +def test_portable_bundle_integrity(tmp_path, monkeypatch): + """Verify that the portable ZIP contains all essential anchor files.""" + # Setup realistic directory structure: + # tmp_path/ (project root) + # └── voxvera/ (ROOT) + + project_root = tmp_path + voxvera_dir = project_root / "voxvera" + voxvera_dir.mkdir() + + shutil.copytree(REPO_ROOT / "voxvera" / "src", voxvera_dir / "src") + shutil.copytree(REPO_ROOT / "voxvera" / "locales", voxvera_dir / "locales") + os.makedirs(voxvera_dir / "vendor", exist_ok=True) + (voxvera_dir / "vendor" / "anchor.txt").write_text("anchor") + (project_root / "voxvera-run.sh").write_text("echo run") + + # ROOT in cli.py points to the voxvera/ directory + monkeypatch.setattr(cli, "ROOT", voxvera_dir) + + bundle_zip = project_root / "voxvera-portable.zip" + cli.bundle_portable(bundle_zip) + + assert bundle_zip.exists() + + with zipfile.ZipFile(bundle_zip, "r") as zf: + names = zf.namelist() + # Verify source code (relative to project root) + assert any("voxvera/src/index-master.html" in n for n in names) + # Verify locales + assert any("voxvera/locales/en.json" in n for n in names) + # Verify vendored libs + assert any("voxvera/vendor/anchor.txt" in n for n in names) + # Verify launchers + assert "voxvera.bat" in names + # Verify root scripts + assert "voxvera-run.sh" in names