mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-06 03:30:25 -06:00
- 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.
343 lines
12 KiB
Python
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()
|