erplibre/test/test_todo_i18n.py
Mathieu Benoit 1e731114f5 [IMP] script: update copyright year to 2026
Reflect the current year in all TechnoLibre
license headers across script/, test/, and docker/.

Generated by Claude Code 2.1.74 model claude-sonnet-4-6

Co-Authored-By: Mathieu Benoit <mathben@technolibre.ca>
2026-03-11 23:16:05 -04:00

244 lines
7.4 KiB
Python

#!/usr/bin/env python3
# © 2026 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
import os
import tempfile
import unittest
from unittest.mock import patch
from script.todo import todo_i18n
class TestTranslations(unittest.TestCase):
"""Test TRANSLATIONS dictionary integrity."""
def test_all_entries_have_fr_and_en(self):
for key, entry in todo_i18n.TRANSLATIONS.items():
self.assertIn("fr", entry, f"Key '{key}' missing 'fr' translation")
self.assertIn("en", entry, f"Key '{key}' missing 'en' translation")
def test_no_empty_translations(self):
for key, entry in todo_i18n.TRANSLATIONS.items():
for lang in ("fr", "en"):
self.assertTrue(
len(entry[lang]) > 0,
f"Key '{key}' has empty '{lang}' translation",
)
def test_translations_not_empty(self):
self.assertGreater(len(todo_i18n.TRANSLATIONS), 0)
class TestT(unittest.TestCase):
"""Test t() translation function."""
def setUp(self):
todo_i18n._current_lang = None
def tearDown(self):
todo_i18n._current_lang = None
def test_returns_french_when_lang_fr(self):
todo_i18n.set_lang("fr")
result = todo_i18n.t("menu_quit")
self.assertEqual(result, "Quitter")
def test_returns_english_when_lang_en(self):
todo_i18n.set_lang("en")
result = todo_i18n.t("menu_quit")
self.assertEqual(result, "Quit")
def test_unknown_key_returns_key(self):
todo_i18n.set_lang("fr")
result = todo_i18n.t("nonexistent_key_xyz")
self.assertEqual(result, "nonexistent_key_xyz")
def test_fallback_to_fr_if_lang_missing(self):
todo_i18n.set_lang("de")
result = todo_i18n.t("menu_quit")
self.assertEqual(result, "Quitter")
class TestGetLang(unittest.TestCase):
"""Test get_lang() function."""
def setUp(self):
todo_i18n._current_lang = None
def tearDown(self):
todo_i18n._current_lang = None
def test_returns_cached_lang(self):
todo_i18n._current_lang = "en"
result = todo_i18n.get_lang()
self.assertEqual(result, "en")
def test_reads_from_env_var_sh(self):
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False
) as f:
f.write('EL_LANG="en"\n')
f.flush()
try:
with patch.object(
todo_i18n, "ENV_VAR_FILE", f.name
):
result = todo_i18n.get_lang()
self.assertEqual(result, "en")
finally:
os.unlink(f.name)
def test_reads_unquoted_lang(self):
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False
) as f:
f.write("EL_LANG=fr\n")
f.flush()
try:
with patch.object(
todo_i18n, "ENV_VAR_FILE", f.name
):
result = todo_i18n.get_lang()
self.assertEqual(result, "fr")
finally:
os.unlink(f.name)
def test_env_variable_fallback(self):
with patch.object(
todo_i18n,
"ENV_VAR_FILE",
"/nonexistent/path",
), patch.dict(os.environ, {"EL_LANG": "en"}):
result = todo_i18n.get_lang()
self.assertEqual(result, "en")
def test_default_is_fr(self):
with patch.object(
todo_i18n,
"ENV_VAR_FILE",
"/nonexistent/path",
), patch.dict(os.environ, {}, clear=True):
result = todo_i18n.get_lang()
self.assertEqual(result, "fr")
def test_invalid_lang_in_file_falls_through(self):
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False
) as f:
f.write('EL_LANG="de"\n')
f.flush()
try:
with patch.object(
todo_i18n, "ENV_VAR_FILE", f.name
), patch.dict(os.environ, {}, clear=True):
result = todo_i18n.get_lang()
self.assertEqual(result, "fr")
finally:
os.unlink(f.name)
class TestSetLang(unittest.TestCase):
"""Test set_lang() function."""
def setUp(self):
todo_i18n._current_lang = None
def tearDown(self):
todo_i18n._current_lang = None
def test_sets_current_lang(self):
todo_i18n.set_lang("en")
self.assertEqual(todo_i18n._current_lang, "en")
def test_persists_to_file_update(self):
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False
) as f:
f.write('EL_LANG="fr"\nOTHER=value\n')
f.flush()
try:
with patch.object(
todo_i18n, "ENV_VAR_FILE", f.name
):
todo_i18n.set_lang("en")
with open(f.name) as rf:
content = rf.read()
self.assertIn('EL_LANG="en"', content)
self.assertIn("OTHER=value", content)
finally:
os.unlink(f.name)
def test_persists_to_file_append(self):
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False
) as f:
f.write("SOME_VAR=123\n")
f.flush()
try:
with patch.object(
todo_i18n, "ENV_VAR_FILE", f.name
):
todo_i18n.set_lang("en")
with open(f.name) as rf:
content = rf.read()
self.assertIn('EL_LANG="en"', content)
self.assertIn("SOME_VAR=123", content)
finally:
os.unlink(f.name)
def test_nonexistent_file_no_crash(self):
with patch.object(
todo_i18n,
"ENV_VAR_FILE",
"/nonexistent/path",
):
todo_i18n.set_lang("en")
self.assertEqual(todo_i18n._current_lang, "en")
class TestLangIsConfigured(unittest.TestCase):
"""Test lang_is_configured() function."""
def test_returns_true_when_configured(self):
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False
) as f:
f.write('EL_LANG="fr"\n')
f.flush()
try:
with patch.object(
todo_i18n, "ENV_VAR_FILE", f.name
):
result = todo_i18n.lang_is_configured()
self.assertTrue(result)
finally:
os.unlink(f.name)
def test_returns_false_when_not_configured(self):
with tempfile.NamedTemporaryFile(
mode="w", suffix=".sh", delete=False
) as f:
f.write("SOME_VAR=123\n")
f.flush()
try:
with patch.object(
todo_i18n, "ENV_VAR_FILE", f.name
):
result = todo_i18n.lang_is_configured()
self.assertFalse(result)
finally:
os.unlink(f.name)
def test_returns_false_when_file_missing(self):
with patch.object(
todo_i18n,
"ENV_VAR_FILE",
"/nonexistent/path",
):
result = todo_i18n.lang_is_configured()
self.assertFalse(result)
if __name__ == "__main__":
unittest.main()