Files
TimeTracker/tests/test_i18n.py
Dries Peeters 90dde470da style: standardize code formatting and normalize line endings
- Normalize line endings from CRLF to LF across all files to match .editorconfig
- Standardize quote style from single quotes to double quotes
- Normalize whitespace and formatting throughout codebase
- Apply consistent code style across 372 files including:
  * Application code (models, routes, services, utils)
  * Test files
  * Configuration files
  * CI/CD workflows

This ensures consistency with the project's .editorconfig settings and
improves code maintainability.
2025-11-28 20:05:37 +01:00

343 lines
12 KiB
Python

"""Tests for internationalization (i18n) functionality"""
import pytest
from flask import session
from app import create_app, db
from app.models import User
from flask_babel import get_locale
class TestI18nConfiguration:
"""Test internationalization configuration"""
def test_supported_languages_configured(self, client):
"""Test that all supported languages are configured"""
with client.application.app_context():
languages = client.application.config.get("LANGUAGES", {})
# Check that all required languages are present
assert "en" in languages
assert "de" in languages
assert "fr" in languages
assert "es" in languages
assert "ar" in languages
assert "he" in languages
assert "nl" in languages
assert "it" in languages
assert "fi" in languages
# Check that language labels are set
assert languages["en"] == "English"
assert languages["es"] == "Español"
assert languages["ar"] == "العربية"
assert languages["he"] == "עברית"
def test_rtl_languages_configured(self, client):
"""Test that RTL languages are configured"""
with client.application.app_context():
rtl_languages = client.application.config.get("RTL_LANGUAGES", set())
# Check that RTL languages are present
assert "ar" in rtl_languages
assert "he" in rtl_languages
# Check that LTR languages are not in RTL set
assert "en" not in rtl_languages
assert "de" not in rtl_languages
assert "es" not in rtl_languages
def test_default_locale_is_english(self, client):
"""Test that default locale is English"""
with client.application.app_context():
default_locale = client.application.config.get("BABEL_DEFAULT_LOCALE")
assert default_locale == "en"
class TestLocaleSelection:
"""Test locale selection logic"""
def test_locale_from_user_preference(self, client, test_user):
"""Test that locale is selected from user's preference"""
# Set user's preferred language
test_user.preferred_language = "de"
db.session.commit()
# Login as user
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Check that locale is set to user's preference
with client.application.test_request_context():
with client.session_transaction() as sess:
# Simulate request context
from flask import g
from app import babel
# The locale selector should return user's preference
assert test_user.preferred_language == "de"
def test_locale_from_session(self, client):
"""Test that locale is selected from session when not logged in"""
with client:
# Set language in session
with client.session_transaction() as sess:
sess["preferred_language"] = "fr"
# Make a request
response = client.get("/")
# Check that session language is used
with client.session_transaction() as sess:
assert sess.get("preferred_language") == "fr"
def test_locale_fallback_to_default(self, client):
"""Test that locale falls back to default when not set"""
with client:
# Don't set any language preference
response = client.get("/")
# Should use default locale (English)
assert response.status_code in [200, 302] # May redirect to login
class TestLanguageSwitching:
"""Test language switching functionality"""
def test_set_language_direct_route(self, client, test_user):
"""Test direct language switching route"""
# Login first
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Switch to Spanish
response = client.get("/set-language/es", follow_redirects=False)
# Should redirect
assert response.status_code == 302
# Check that user's preference is updated
db.session.refresh(test_user)
assert test_user.preferred_language == "es"
# Check that session is updated
with client.session_transaction() as sess:
assert sess.get("preferred_language") == "es"
def test_set_language_api_endpoint(self, client, test_user):
"""Test API endpoint for language switching"""
# Login first
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Switch to Arabic via API
response = client.post("/api/language", json={"language": "ar"}, content_type="application/json")
assert response.status_code == 200
data = response.get_json()
assert data["success"] is True
assert data["language"] == "ar"
# Check that user's preference is updated
db.session.refresh(test_user)
assert test_user.preferred_language == "ar"
def test_set_invalid_language(self, client, test_user):
"""Test that invalid languages are rejected"""
# Login first
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Try to set invalid language
response = client.post("/api/language", json={"language": "invalid"}, content_type="application/json")
assert response.status_code == 400
data = response.get_json()
assert "error" in data
def test_language_persists_across_sessions(self, client, test_user):
"""Test that language preference persists across sessions"""
# Login and set language
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
client.get("/set-language/de", follow_redirects=True)
# Logout
client.get("/auth/logout", follow_redirects=True)
# Login again
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Check that language preference is still set
db.session.refresh(test_user)
assert test_user.preferred_language == "de"
class TestRTLSupport:
"""Test Right-to-Left language support"""
def test_rtl_detection_for_arabic(self, client, test_user):
"""Test that Arabic is detected as RTL"""
# Set language to Arabic
test_user.preferred_language = "ar"
db.session.commit()
# Login
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Get dashboard
response = client.get("/dashboard")
# Check that page includes RTL directive
assert response.status_code == 200
assert b'dir="rtl"' in response.data or b"dir='rtl'" in response.data
def test_rtl_detection_for_hebrew(self, client, test_user):
"""Test that Hebrew is detected as RTL"""
# Set language to Hebrew
test_user.preferred_language = "he"
db.session.commit()
# Login
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Get dashboard
response = client.get("/dashboard")
# Check that page includes RTL directive
assert response.status_code == 200
assert b'dir="rtl"' in response.data or b"dir='rtl'" in response.data
def test_ltr_for_english(self, client, test_user):
"""Test that English is LTR"""
# Set language to English
test_user.preferred_language = "en"
db.session.commit()
# Login
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Get dashboard
response = client.get("/dashboard")
# Check that page includes LTR directive
assert response.status_code == 200
assert b'dir="ltr"' in response.data or b"dir='ltr'" in response.data
class TestTranslations:
"""Test that translations are working"""
def test_english_translations(self, client):
"""Test English translations"""
with client.application.test_request_context():
from flask_babel import _
# Test common translations
assert _("Dashboard") == "Dashboard"
assert _("Projects") == "Projects"
assert _("Login") == "Login"
def test_translation_files_exist(self, client):
"""Test that translation files exist for all languages"""
import os
languages = ["en", "de", "fr", "es", "ar", "he", "nl", "it", "fi"]
for lang in languages:
po_file = os.path.join("translations", lang, "LC_MESSAGES", "messages.po")
assert os.path.exists(po_file), f"Translation file missing for {lang}"
class TestLanguageSelectorUI:
"""Test language selector UI"""
def test_language_selector_in_header(self, client, test_user):
"""Test that language selector appears in header"""
# Login
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Get dashboard
response = client.get("/dashboard")
# Check that language selector is present
assert response.status_code == 200
assert b"langDropdown" in response.data or b"lang-dropdown" in response.data.lower()
assert b"fa-globe" in response.data or b"globe" in response.data.lower()
def test_language_list_contains_all_languages(self, client, test_user):
"""Test that language selector contains all available languages"""
# Login
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Get dashboard
response = client.get("/dashboard")
assert response.status_code == 200
response_text = response.data.decode("utf-8")
# Check for language names in the page
languages_to_check = ["English", "Español", "Français", "Deutsch"]
for lang in languages_to_check:
assert lang in response_text, f"Language '{lang}' not found in language selector"
class TestUserSettingsLanguage:
"""Test language settings in user settings page"""
def test_language_setting_in_user_settings(self, client, test_user):
"""Test that language setting is available in user settings"""
# Login
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Get settings page
response = client.get("/settings")
# Check that language setting is present
assert response.status_code == 200
assert b"preferred_language" in response.data or b"language" in response.data.lower()
def test_save_language_in_user_settings(self, client, test_user):
"""Test saving language preference in user settings"""
# Login
with client.session_transaction() as sess:
sess["_user_id"] = str(test_user.id)
# Update settings with language
response = client.post(
"/settings",
data={
"preferred_language": "fr",
"full_name": test_user.full_name or "Test User",
"email": test_user.email or "test@example.com",
},
follow_redirects=True,
)
# Check that setting was saved
assert response.status_code == 200
db.session.refresh(test_user)
assert test_user.preferred_language == "fr"
@pytest.fixture
def test_user(client):
"""Create a test user"""
with client.application.app_context():
user = User(username="testuser", role="user")
user.is_active = True
db.session.add(user)
db.session.commit()
yield user
# Cleanup - delete related activities first to avoid constraint violations
from app.models import Activity
Activity.query.filter_by(user_id=user.id).delete()
db.session.delete(user)
db.session.commit()