235
tests/test_sync.py
Normal file
235
tests/test_sync.py
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
"""Tests for sync module."""
|
||||||
|
import json
|
||||||
|
|
||||||
|
from i18n_key_sync.sync import SyncChange, Syncer, SyncResult
|
||||||
|
|
||||||
|
|
||||||
|
class TestSyncChange:
|
||||||
|
"""Tests for SyncChange class."""
|
||||||
|
|
||||||
|
def test_sync_change_creation(self):
|
||||||
|
"""Test creating a SyncChange."""
|
||||||
|
change = SyncChange(
|
||||||
|
locale="en",
|
||||||
|
key="new_key",
|
||||||
|
old_value=None,
|
||||||
|
new_value="New Value",
|
||||||
|
action="add",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert change.locale == "en"
|
||||||
|
assert change.key == "new_key"
|
||||||
|
assert change.old_value is None
|
||||||
|
assert change.new_value == "New Value"
|
||||||
|
assert change.action == "add"
|
||||||
|
|
||||||
|
|
||||||
|
class TestSyncResult:
|
||||||
|
"""Tests for SyncResult class."""
|
||||||
|
|
||||||
|
def test_sync_result_total_changes(self):
|
||||||
|
"""Test SyncResult total_changes property."""
|
||||||
|
result = SyncResult(
|
||||||
|
changes=[
|
||||||
|
SyncChange("en", "key1", None, "value1", "add"),
|
||||||
|
SyncChange("es", "key2", None, "value2", "add"),
|
||||||
|
],
|
||||||
|
locales_updated=["en", "es"],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.total_changes == 2
|
||||||
|
|
||||||
|
|
||||||
|
class TestSyncer:
|
||||||
|
"""Tests for Syncer class."""
|
||||||
|
|
||||||
|
def test_sync_keys_adds_missing(self, locale_parser, tmp_path):
|
||||||
|
"""Test syncing adds missing keys to locale files."""
|
||||||
|
locale_dir = tmp_path / "locales"
|
||||||
|
locale_dir.mkdir()
|
||||||
|
|
||||||
|
locale_file = locale_dir / "en.json"
|
||||||
|
locale_file.write_text(json.dumps({"existing": "value"}))
|
||||||
|
|
||||||
|
syncer = Syncer(locale_parser)
|
||||||
|
keys = {"existing", "new_key1", "new_key2"}
|
||||||
|
|
||||||
|
changes = syncer.sync_keys(
|
||||||
|
keys=keys,
|
||||||
|
locale_dir=str(locale_dir),
|
||||||
|
placeholder_value="TODO",
|
||||||
|
dry_run=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(changes) == 2
|
||||||
|
assert changes[0].action == "add"
|
||||||
|
assert changes[0].key in ["new_key1", "new_key2"]
|
||||||
|
|
||||||
|
data = json.loads(locale_file.read_text())
|
||||||
|
assert "new_key1" in data
|
||||||
|
assert "new_key2" in data
|
||||||
|
|
||||||
|
def test_sync_keys_dry_run(self, locale_parser, tmp_path):
|
||||||
|
"""Test dry run doesn't modify files."""
|
||||||
|
locale_dir = tmp_path / "locales"
|
||||||
|
locale_dir.mkdir()
|
||||||
|
|
||||||
|
locale_file = locale_dir / "en.json"
|
||||||
|
locale_file.write_text(json.dumps({"existing": "value"}))
|
||||||
|
|
||||||
|
syncer = Syncer(locale_parser)
|
||||||
|
keys = {"existing", "new_key"}
|
||||||
|
|
||||||
|
changes = syncer.sync_keys(
|
||||||
|
keys=keys,
|
||||||
|
locale_dir=str(locale_dir),
|
||||||
|
placeholder_value="TODO",
|
||||||
|
dry_run=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(changes) == 1
|
||||||
|
|
||||||
|
data = json.loads(locale_file.read_text())
|
||||||
|
assert "new_key" not in data
|
||||||
|
assert data == {"existing": "value"}
|
||||||
|
|
||||||
|
def test_sync_keys_specific_locales(self, locale_parser, tmp_path):
|
||||||
|
"""Test syncing only specific locales."""
|
||||||
|
locale_dir = tmp_path / "locales"
|
||||||
|
locale_dir.mkdir()
|
||||||
|
|
||||||
|
en_file = locale_dir / "en.json"
|
||||||
|
en_file.write_text(json.dumps({}))
|
||||||
|
|
||||||
|
es_file = locale_dir / "es.json"
|
||||||
|
es_file.write_text(json.dumps({}))
|
||||||
|
|
||||||
|
syncer = Syncer(locale_parser)
|
||||||
|
keys = {"key1", "key2"}
|
||||||
|
|
||||||
|
changes = syncer.sync_keys(
|
||||||
|
keys=keys,
|
||||||
|
locale_dir=str(locale_dir),
|
||||||
|
target_locales=["en"],
|
||||||
|
placeholder_value="TODO",
|
||||||
|
dry_run=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(changes) == 2
|
||||||
|
|
||||||
|
en_data = json.loads(en_file.read_text())
|
||||||
|
assert "key1" in en_data
|
||||||
|
assert "key2" in en_data
|
||||||
|
|
||||||
|
es_data = json.loads(es_file.read_text())
|
||||||
|
assert "key1" not in es_data
|
||||||
|
|
||||||
|
def test_sync_keys_fill_from_locale(self, locale_parser, tmp_path):
|
||||||
|
"""Test syncing with fill from source locale."""
|
||||||
|
locale_dir = tmp_path / "locales"
|
||||||
|
locale_dir.mkdir()
|
||||||
|
|
||||||
|
en_file = locale_dir / "en.json"
|
||||||
|
en_file.write_text(json.dumps({"key1": "Hello", "key2": "World"}))
|
||||||
|
|
||||||
|
es_file = locale_dir / "es.json"
|
||||||
|
es_file.write_text(json.dumps({"key1": "Hola"}))
|
||||||
|
|
||||||
|
syncer = Syncer(locale_parser)
|
||||||
|
keys = {"key1", "key2", "key3"}
|
||||||
|
|
||||||
|
changes = syncer.sync_keys(
|
||||||
|
keys=keys,
|
||||||
|
locale_dir=str(locale_dir),
|
||||||
|
target_locales=["es"],
|
||||||
|
placeholder_value="TODO",
|
||||||
|
fill_from_locale="en",
|
||||||
|
dry_run=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(changes) == 2
|
||||||
|
|
||||||
|
es_data = json.loads(es_file.read_text())
|
||||||
|
assert es_data["key1"] == "Hola"
|
||||||
|
assert es_data["key2"] == "World"
|
||||||
|
assert es_data["key3"] == "TODO"
|
||||||
|
|
||||||
|
def test_sync_to_new_locale(self, locale_parser, tmp_path):
|
||||||
|
"""Test creating a new locale file."""
|
||||||
|
locale_dir = tmp_path / "locales"
|
||||||
|
locale_dir.mkdir()
|
||||||
|
|
||||||
|
en_file = locale_dir / "en.json"
|
||||||
|
en_file.write_text(json.dumps({"key1": "Hello", "key2": "World"}))
|
||||||
|
|
||||||
|
syncer = Syncer(locale_parser)
|
||||||
|
keys = {"key1", "key2", "key3"}
|
||||||
|
|
||||||
|
changes = syncer.sync_to_new_locale(
|
||||||
|
keys=keys,
|
||||||
|
locale_dir=str(locale_dir),
|
||||||
|
new_locale="fr",
|
||||||
|
source_locale="en",
|
||||||
|
placeholder_value="TODO",
|
||||||
|
dry_run=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(changes) == 3
|
||||||
|
|
||||||
|
fr_file = locale_dir / "fr.json"
|
||||||
|
assert fr_file.exists()
|
||||||
|
|
||||||
|
fr_data = json.loads(fr_file.read_text())
|
||||||
|
assert fr_data["key1"] == "Hello"
|
||||||
|
assert fr_data["key2"] == "World"
|
||||||
|
assert fr_data["key3"] == "TODO"
|
||||||
|
|
||||||
|
def test_sync_to_new_locale_dry_run(self, locale_parser, tmp_path):
|
||||||
|
"""Test creating new locale with dry run."""
|
||||||
|
locale_dir = tmp_path / "locales"
|
||||||
|
locale_dir.mkdir()
|
||||||
|
|
||||||
|
en_file = locale_dir / "en.json"
|
||||||
|
en_file.write_text(json.dumps({"key1": "Hello"}))
|
||||||
|
|
||||||
|
syncer = Syncer(locale_parser)
|
||||||
|
keys = {"key1", "key2"}
|
||||||
|
|
||||||
|
changes = syncer.sync_to_new_locale(
|
||||||
|
keys=keys,
|
||||||
|
locale_dir=str(locale_dir),
|
||||||
|
new_locale="fr",
|
||||||
|
source_locale="en",
|
||||||
|
placeholder_value="TODO",
|
||||||
|
dry_run=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(changes) == 2
|
||||||
|
|
||||||
|
fr_file = locale_dir / "fr.json"
|
||||||
|
assert not fr_file.exists()
|
||||||
|
|
||||||
|
def test_sync_keys_nested(self, locale_parser, tmp_path):
|
||||||
|
"""Test syncing nested keys."""
|
||||||
|
locale_dir = tmp_path / "locales"
|
||||||
|
locale_dir.mkdir()
|
||||||
|
|
||||||
|
locale_file = locale_dir / "en.json"
|
||||||
|
locale_file.write_text(json.dumps({}))
|
||||||
|
|
||||||
|
syncer = Syncer(locale_parser)
|
||||||
|
keys = {"user.profile.name", "user.profile.email", "common.save"}
|
||||||
|
|
||||||
|
changes = syncer.sync_keys(
|
||||||
|
keys=keys,
|
||||||
|
locale_dir=str(locale_dir),
|
||||||
|
placeholder_value="TODO",
|
||||||
|
dry_run=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(changes) == 3
|
||||||
|
|
||||||
|
data = json.loads(locale_file.read_text())
|
||||||
|
assert data["user"]["profile"]["name"] == "TODO"
|
||||||
|
assert data["user"]["profile"]["email"] == "TODO"
|
||||||
|
assert data["common"]["save"] == "TODO"
|
||||||
Reference in New Issue
Block a user