style: formater le depot avec ruff format
QUA-002, premiere moitie. **Ce commit ne fait que reformater** : aucun changement de comportement, aucune ligne de logique touchee. 72 fichiers, 4 restaient deja conformes. Il est isole exprès, pour que `git log -p` sur les commits voisins reste lisible. `quote-style = "preserve"` etait deja pose dans pyproject.toml, ce qui evite le brassage guillemets simples / doubles : le diff porte sur les retours a la ligne, l indentation des appels longs et les virgules finales, pas sur le style de chaine. Verification : 263 tests passent avant et apres, ruff check propre. L activation en CI arrive dans le commit suivant, separement, pour que ce diff-ci ne contienne rien d autre. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+66
-44
@@ -28,28 +28,27 @@ class TestDefaults:
|
||||
assert 'Se connecter' in body
|
||||
|
||||
def test_the_html_lang_attribute_follows_the_locale(self, client):
|
||||
english = client.get('/auth/login',
|
||||
headers={'Accept-Language': 'en-CA,en;q=0.9'})
|
||||
english = client.get('/auth/login', headers={'Accept-Language': 'en-CA,en;q=0.9'})
|
||||
assert 'lang="en"' in english.get_data(as_text=True)
|
||||
|
||||
|
||||
class TestBrowserNegotiation:
|
||||
def test_an_english_browser_is_served_english(self, client):
|
||||
body = client.get('/auth/login',
|
||||
headers={'Accept-Language': 'en-CA,en;q=0.9'}
|
||||
).get_data(as_text=True)
|
||||
body = client.get('/auth/login', headers={'Accept-Language': 'en-CA,en;q=0.9'}).get_data(
|
||||
as_text=True
|
||||
)
|
||||
assert 'Sign In' in body
|
||||
|
||||
def test_an_unsupported_language_falls_back_to_french(self, client):
|
||||
body = client.get('/auth/login',
|
||||
headers={'Accept-Language': 'de-DE,de;q=0.9'}
|
||||
).get_data(as_text=True)
|
||||
body = client.get('/auth/login', headers={'Accept-Language': 'de-DE,de;q=0.9'}).get_data(
|
||||
as_text=True
|
||||
)
|
||||
assert 'Se connecter' in body
|
||||
|
||||
def test_a_french_browser_is_served_french(self, client):
|
||||
body = client.get('/auth/login',
|
||||
headers={'Accept-Language': 'fr-CA,fr;q=0.9'}
|
||||
).get_data(as_text=True)
|
||||
body = client.get('/auth/login', headers={'Accept-Language': 'fr-CA,fr;q=0.9'}).get_data(
|
||||
as_text=True
|
||||
)
|
||||
assert 'Se connecter' in body
|
||||
|
||||
|
||||
@@ -65,9 +64,9 @@ class TestExplicitSwitch:
|
||||
"""Someone on an English machine who picks French must keep French."""
|
||||
client.get('/lang/fr')
|
||||
|
||||
body = client.get('/auth/login',
|
||||
headers={'Accept-Language': 'en-CA,en;q=0.9'}
|
||||
).get_data(as_text=True)
|
||||
body = client.get('/auth/login', headers={'Accept-Language': 'en-CA,en;q=0.9'}).get_data(
|
||||
as_text=True
|
||||
)
|
||||
|
||||
assert 'Se connecter' in body
|
||||
assert 'lang="fr"' in body
|
||||
@@ -85,16 +84,18 @@ class TestExplicitSwitch:
|
||||
assert 'Sign In' in body, 'an unsupported code must not change the locale'
|
||||
|
||||
def test_the_switcher_redirects_back_to_the_referring_page(self, client):
|
||||
response = client.get('/lang/en',
|
||||
headers={'Referer': 'http://localhost/auth/register'},
|
||||
follow_redirects=False)
|
||||
response = client.get(
|
||||
'/lang/en',
|
||||
headers={'Referer': 'http://localhost/auth/register'},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert response.headers['Location'].endswith('/auth/register')
|
||||
|
||||
def test_an_external_referer_is_not_followed(self, client):
|
||||
"""An unchecked Referer would make this an open redirect."""
|
||||
response = client.get('/lang/en',
|
||||
headers={'Referer': 'https://evil.test/phishing'},
|
||||
follow_redirects=False)
|
||||
response = client.get(
|
||||
'/lang/en', headers={'Referer': 'https://evil.test/phishing'}, follow_redirects=False
|
||||
)
|
||||
assert 'evil.test' not in response.headers['Location']
|
||||
|
||||
|
||||
@@ -135,13 +136,14 @@ class TestTranslatedContent:
|
||||
body = client.get('/no-such-page').get_data(as_text=True)
|
||||
assert 'Page introuvable' in body
|
||||
|
||||
@pytest.mark.parametrize('locale,expected', [
|
||||
('fr', 'Ce compte a été désactivé.'),
|
||||
('en', 'This account has been deactivated.'),
|
||||
])
|
||||
def test_flash_messages_are_translated(
|
||||
self, app, client, make_user, login, locale, expected
|
||||
):
|
||||
@pytest.mark.parametrize(
|
||||
'locale,expected',
|
||||
[
|
||||
('fr', 'Ce compte a été désactivé.'),
|
||||
('en', 'This account has been deactivated.'),
|
||||
],
|
||||
)
|
||||
def test_flash_messages_are_translated(self, app, client, make_user, login, locale, expected):
|
||||
from app.extensions import db
|
||||
from app.models import User
|
||||
|
||||
@@ -168,11 +170,14 @@ class TestCatalogueIntegrity:
|
||||
|
||||
path = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||
'app', 'translations', locale, 'LC_MESSAGES', 'messages.mo',
|
||||
'app',
|
||||
'translations',
|
||||
locale,
|
||||
'LC_MESSAGES',
|
||||
'messages.mo',
|
||||
)
|
||||
assert os.path.exists(path), (
|
||||
f'{locale} catalogue is not compiled: run '
|
||||
'`pybabel compile -d app/translations`'
|
||||
f'{locale} catalogue is not compiled: run `pybabel compile -d app/translations`'
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize('locale', SUPPORTED_LOCALES)
|
||||
@@ -184,15 +189,18 @@ class TestCatalogueIntegrity:
|
||||
|
||||
path = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||
'app', 'translations', locale, 'LC_MESSAGES', 'messages.po',
|
||||
'app',
|
||||
'translations',
|
||||
locale,
|
||||
'LC_MESSAGES',
|
||||
'messages.po',
|
||||
)
|
||||
with io.open(path, encoding='utf-8') as handle:
|
||||
catalog = read_po(handle, locale=locale)
|
||||
|
||||
untranslated = [m.id for m in catalog if m.id and not m.string]
|
||||
assert not untranslated, (
|
||||
f'{len(untranslated)} untranslated string(s) in {locale}: '
|
||||
f'{untranslated[:5]}'
|
||||
f'{len(untranslated)} untranslated string(s) in {locale}: {untranslated[:5]}'
|
||||
)
|
||||
|
||||
|
||||
@@ -233,9 +241,9 @@ class TestLocaleSurvivesSessionRotation:
|
||||
client.get('/lang/fr')
|
||||
as_role('player')
|
||||
|
||||
body = client.get('/users/profile',
|
||||
headers={'Accept-Language': 'en-CA,en;q=0.9'}
|
||||
).get_data(as_text=True)
|
||||
body = client.get('/users/profile', headers={'Accept-Language': 'en-CA,en;q=0.9'}).get_data(
|
||||
as_text=True
|
||||
)
|
||||
assert 'lang="fr"' in body
|
||||
|
||||
def test_the_csrf_token_is_still_preserved(self, app, client, make_user, login):
|
||||
@@ -273,20 +281,34 @@ class TestFlashMessagesAreTranslated:
|
||||
built at import time, before any request exists."""
|
||||
as_role('admin')
|
||||
|
||||
body = client.post('/users/create', data={
|
||||
'username': 'x', 'email': 'not-an-email',
|
||||
'password': 'a', 'full_name': 'X', 'role': 'coach',
|
||||
}, follow_redirects=True).get_data(as_text=True)
|
||||
body = client.post(
|
||||
'/users/create',
|
||||
data={
|
||||
'username': 'x',
|
||||
'email': 'not-an-email',
|
||||
'password': 'a',
|
||||
'full_name': 'X',
|
||||
'role': 'coach',
|
||||
},
|
||||
follow_redirects=True,
|
||||
).get_data(as_text=True)
|
||||
|
||||
assert 'Le nom d' in body and 'utilisateur doit compter' in body
|
||||
|
||||
def test_a_message_with_a_value_keeps_it(self, client, as_role):
|
||||
as_role('admin')
|
||||
|
||||
body = client.post('/users/create', data={
|
||||
'username': 'recrue', 'email': '[email protected]',
|
||||
'password': 'Password123', 'full_name': 'Nouvelle Recrue', 'role': 'coach',
|
||||
}, follow_redirects=True).get_data(as_text=True)
|
||||
body = client.post(
|
||||
'/users/create',
|
||||
data={
|
||||
'username': 'recrue',
|
||||
'email': '[email protected]',
|
||||
'password': 'Password123',
|
||||
'full_name': 'Nouvelle Recrue',
|
||||
'role': 'coach',
|
||||
},
|
||||
follow_redirects=True,
|
||||
).get_data(as_text=True)
|
||||
|
||||
assert 'Nouvelle Recrue' in body
|
||||
assert 'créé avec le rôle coach' in body
|
||||
|
||||
Reference in New Issue
Block a user