mirror of
https://gitlab.com/animath/si/plateforme-corres2math.git
synced 2024-12-05 02:06:52 +00:00
Cover also settings files, keep 100% coverage by ignoring production files
This commit is contained in:
parent
fa368a399a
commit
1ddf39f296
@ -11,7 +11,7 @@ class Command(BaseCommand):
|
|||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
Matrix.set_display_name("Bot des Correspondances")
|
Matrix.set_display_name("Bot des Correspondances")
|
||||||
|
|
||||||
if not os.path.isfile(".matrix_avatar"):
|
if not os.path.isfile(".matrix_avatar"): # pragma: no cover
|
||||||
stat_file = os.stat("corres2math/static/logo.png")
|
stat_file = os.stat("corres2math/static/logo.png")
|
||||||
with open("corres2math/static/logo.png", "rb") as f:
|
with open("corres2math/static/logo.png", "rb") as f:
|
||||||
resp, _ = Matrix.upload(f, filename="logo.png", content_type="image/png", filesize=stat_file.st_size)
|
resp, _ = Matrix.upload(f, filename="logo.png", content_type="image/png", filesize=stat_file.st_size)
|
||||||
@ -21,9 +21,9 @@ class Command(BaseCommand):
|
|||||||
with open(".matrix_avatar", "w") as f:
|
with open(".matrix_avatar", "w") as f:
|
||||||
f.write(avatar_uri)
|
f.write(avatar_uri)
|
||||||
Matrix.set_avatar(avatar_uri)
|
Matrix.set_avatar(avatar_uri)
|
||||||
else:
|
|
||||||
with open(".matrix_avatar", "r") as f:
|
with open(".matrix_avatar", "r") as f:
|
||||||
avatar_uri = f.read().rstrip(" \t\r\n")
|
avatar_uri = f.read().rstrip(" \t\r\n")
|
||||||
|
|
||||||
if not async_to_sync(Matrix.resolve_room_alias)("#faq:correspondances-maths.fr"):
|
if not async_to_sync(Matrix.resolve_room_alias)("#faq:correspondances-maths.fr"):
|
||||||
Matrix.create_room(
|
Matrix.create_room(
|
||||||
|
@ -27,7 +27,7 @@ def register_phases(apps, schema_editor):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def reverse_phase_registering(apps, schema_editor):
|
def reverse_phase_registering(apps, _): # pragma: no cover
|
||||||
"""
|
"""
|
||||||
Drop all phases in order to unapply this migration.
|
Drop all phases in order to unapply this migration.
|
||||||
"""
|
"""
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -652,6 +653,14 @@ class TestStudentParticipation(TestCase):
|
|||||||
))
|
))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
# Unauthenticated user can't update the calendar
|
||||||
|
self.client.logout()
|
||||||
|
response = self.client.get(reverse("participation:calendar"))
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
response = self.client.get(reverse("participation:update_phase", args=(2,)))
|
||||||
|
self.assertRedirects(response, reverse("login") + "?next=" +
|
||||||
|
reverse("participation:update_phase", args=(2,)), 302, 200)
|
||||||
|
|
||||||
def test_forbidden_access(self):
|
def test_forbidden_access(self):
|
||||||
"""
|
"""
|
||||||
Load personnal pages and ensure that these are protected.
|
Load personnal pages and ensure that these are protected.
|
||||||
@ -682,6 +691,22 @@ class TestStudentParticipation(TestCase):
|
|||||||
resp = self.client.get(reverse("participation:delete_question", args=(question.pk,)))
|
resp = self.client.get(reverse("participation:delete_question", args=(question.pk,)))
|
||||||
self.assertEqual(resp.status_code, 403)
|
self.assertEqual(resp.status_code, 403)
|
||||||
|
|
||||||
|
def test_cover_matrix(self):
|
||||||
|
"""
|
||||||
|
Load matrix scripts, to cover them and ensure that they can run.
|
||||||
|
"""
|
||||||
|
self.user.registration.team = self.team
|
||||||
|
self.user.registration.save()
|
||||||
|
self.second_user.registration.team = self.second_team
|
||||||
|
self.second_user.registration.save()
|
||||||
|
self.team.participation.valid = True
|
||||||
|
self.team.participation.received_participation = self.second_team.participation
|
||||||
|
self.team.participation.save()
|
||||||
|
|
||||||
|
call_command('fix_matrix_channels')
|
||||||
|
call_command('setup_third_phase')
|
||||||
|
os.remove(".matrix_avatar")
|
||||||
|
|
||||||
|
|
||||||
class TestAdmin(TestCase):
|
class TestAdmin(TestCase):
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
|
@ -58,11 +58,11 @@ class Registration(PolymorphicModel):
|
|||||||
self.user.email_user(subject, message, html_message=html)
|
self.user.email_user(subject, message, html_message=html)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def type(self):
|
def type(self): # pragma: no cover
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def form_class(self):
|
def form_class(self): # pragma: no cover
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -335,8 +335,3 @@ class TestRegistration(TestCase):
|
|||||||
attr = CustomAuthUser(self.user.username).attributs()
|
attr = CustomAuthUser(self.user.username).attributs()
|
||||||
self.assertEqual(attr["matrix_username"], self.user.registration.matrix_username)
|
self.assertEqual(attr["matrix_username"], self.user.registration.matrix_username)
|
||||||
self.assertEqual(attr["display_name"], str(self.user.registration))
|
self.assertEqual(attr["display_name"], str(self.user.registration))
|
||||||
|
|
||||||
def test_not_implemented_error(self):
|
|
||||||
# Only for coverage
|
|
||||||
self.assertRaises(NotImplementedError, lambda: Registration().type)
|
|
||||||
self.assertRaises(NotImplementedError, lambda: Registration().form_class)
|
|
||||||
|
@ -6,7 +6,7 @@ _client = None
|
|||||||
def get_sympa_client():
|
def get_sympa_client():
|
||||||
global _client
|
global _client
|
||||||
if _client is None:
|
if _client is None:
|
||||||
if os.getenv("SYMPA_PASSWORD", None) is not None:
|
if os.getenv("SYMPA_PASSWORD", None) is not None: # pragma: no cover
|
||||||
from sympasoap import Client
|
from sympasoap import Client
|
||||||
_client = Client("https://" + os.getenv("SYMPA_URL"))
|
_client = Client("https://" + os.getenv("SYMPA_URL"))
|
||||||
_client.login(os.getenv("SYMPA_EMAIL"), os.getenv("SYMPA_PASSWORD"))
|
_client.login(os.getenv("SYMPA_EMAIL"), os.getenv("SYMPA_PASSWORD"))
|
||||||
|
@ -22,7 +22,7 @@ class Matrix:
|
|||||||
_device_id: str = None
|
_device_id: str = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def _get_client(cls) -> Union[AsyncClient, "FakeMatrixClient"]:
|
async def _get_client(cls) -> Union[AsyncClient, "FakeMatrixClient"]: # pragma: no cover
|
||||||
"""
|
"""
|
||||||
Retrieve the bot account.
|
Retrieve the bot account.
|
||||||
If not logged, log in and store access token.
|
If not logged, log in and store access token.
|
||||||
@ -133,7 +133,8 @@ class Matrix:
|
|||||||
If left as ``None``, some servers might refuse the upload.
|
If left as ``None``, some servers might refuse the upload.
|
||||||
"""
|
"""
|
||||||
client = await cls._get_client()
|
client = await cls._get_client()
|
||||||
return await client.upload(data_provider, content_type, filename, encrypt, monitor, filesize)
|
return await client.upload(data_provider, content_type, filename, encrypt, monitor, filesize) \
|
||||||
|
if isinstance(client, AsyncClient) else UploadResponse("debug mode"), None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@async_to_sync
|
@async_to_sync
|
||||||
@ -219,9 +220,7 @@ class Matrix:
|
|||||||
"""
|
"""
|
||||||
client = await cls._get_client()
|
client = await cls._get_client()
|
||||||
resp: RoomResolveAliasResponse = await client.room_resolve_alias(room_alias)
|
resp: RoomResolveAliasResponse = await client.room_resolve_alias(room_alias)
|
||||||
if isinstance(resp, RoomResolveAliasResponse):
|
return resp.room_id if isinstance(resp, RoomResolveAliasResponse) else None
|
||||||
return resp.room_id
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@async_to_sync
|
@async_to_sync
|
||||||
@ -291,7 +290,7 @@ class Matrix:
|
|||||||
@classmethod
|
@classmethod
|
||||||
@async_to_sync
|
@async_to_sync
|
||||||
async def set_room_power_level(cls, room_id: str, user_id: str, power_level: int)\
|
async def set_room_power_level(cls, room_id: str, user_id: str, power_level: int)\
|
||||||
-> Union[RoomPutStateResponse, RoomPutStateError]:
|
-> Union[RoomPutStateResponse, RoomPutStateError]: # pragma: no cover
|
||||||
"""
|
"""
|
||||||
Put a given power level to a user in a certain room.
|
Put a given power level to a user in a certain room.
|
||||||
|
|
||||||
@ -306,6 +305,9 @@ class Matrix:
|
|||||||
power_level (int): The target power level to give.
|
power_level (int): The target power level to give.
|
||||||
"""
|
"""
|
||||||
client = await cls._get_client()
|
client = await cls._get_client()
|
||||||
|
if isinstance(client, FakeMatrixClient):
|
||||||
|
return RoomPutStateError("debug mode")
|
||||||
|
|
||||||
if room_id.startswith("#"):
|
if room_id.startswith("#"):
|
||||||
room_id = await cls.resolve_room_alias(room_id)
|
room_id = await cls.resolve_room_alias(room_id)
|
||||||
resp = await client.room_get_state_event(room_id, "m.room.power_levels")
|
resp = await client.room_get_state_event(room_id, "m.room.power_levels")
|
||||||
@ -316,7 +318,7 @@ class Matrix:
|
|||||||
@classmethod
|
@classmethod
|
||||||
@async_to_sync
|
@async_to_sync
|
||||||
async def set_room_power_level_event(cls, room_id: str, event: str, power_level: int)\
|
async def set_room_power_level_event(cls, room_id: str, event: str, power_level: int)\
|
||||||
-> Union[RoomPutStateResponse, RoomPutStateError]:
|
-> Union[RoomPutStateResponse, RoomPutStateError]: # pragma: no cover
|
||||||
"""
|
"""
|
||||||
Define the minimal power level to have to send a certain event type
|
Define the minimal power level to have to send a certain event type
|
||||||
in a given room.
|
in a given room.
|
||||||
@ -332,6 +334,9 @@ class Matrix:
|
|||||||
power_level (int): The target power level to give.
|
power_level (int): The target power level to give.
|
||||||
"""
|
"""
|
||||||
client = await cls._get_client()
|
client = await cls._get_client()
|
||||||
|
if isinstance(client, FakeMatrixClient):
|
||||||
|
return RoomPutStateError("debug mode")
|
||||||
|
|
||||||
if room_id.startswith("#"):
|
if room_id.startswith("#"):
|
||||||
room_id = await cls.resolve_room_alias(room_id)
|
room_id = await cls.resolve_room_alias(room_id)
|
||||||
resp = await client.room_get_state_event(room_id, "m.room.power_levels")
|
resp = await client.room_get_state_event(room_id, "m.room.power_levels")
|
||||||
|
@ -21,19 +21,13 @@ def get_current_user() -> User:
|
|||||||
return getattr(_thread_locals, USER_ATTR_NAME, None)
|
return getattr(_thread_locals, USER_ATTR_NAME, None)
|
||||||
|
|
||||||
|
|
||||||
def get_current_session() -> SessionStore:
|
|
||||||
return getattr(_thread_locals, SESSION_ATTR_NAME, None)
|
|
||||||
|
|
||||||
|
|
||||||
def get_current_ip() -> str:
|
def get_current_ip() -> str:
|
||||||
return getattr(_thread_locals, IP_ATTR_NAME, None)
|
return getattr(_thread_locals, IP_ATTR_NAME, None)
|
||||||
|
|
||||||
|
|
||||||
def get_current_authenticated_user():
|
def get_current_authenticated_user():
|
||||||
current_user = get_current_user()
|
current_user = get_current_user()
|
||||||
if isinstance(current_user, AnonymousUser):
|
return None if isinstance(current_user, AnonymousUser) else current_user
|
||||||
return None
|
|
||||||
return current_user
|
|
||||||
|
|
||||||
|
|
||||||
class SessionMiddleware(object):
|
class SessionMiddleware(object):
|
||||||
@ -49,10 +43,7 @@ class SessionMiddleware(object):
|
|||||||
request.user = User.objects.get(pk=request.session["_fake_user_id"])
|
request.user = User.objects.get(pk=request.session["_fake_user_id"])
|
||||||
|
|
||||||
user = request.user
|
user = request.user
|
||||||
if 'HTTP_X_REAL_IP' in request.META:
|
ip = request.META.get('HTTP_X_REAL_IP' if 'HTTP_X_REAL_IP' in request.META else 'REMOTE_ADDR')
|
||||||
ip = request.META.get('HTTP_X_REAL_IP')
|
|
||||||
else:
|
|
||||||
ip = request.META.get('REMOTE_ADDR')
|
|
||||||
|
|
||||||
_set_current_user_and_ip(user, request.session, ip)
|
_set_current_user_and_ip(user, request.session, ip)
|
||||||
response = self.get_response(request)
|
response = self.get_response(request)
|
||||||
@ -61,7 +52,7 @@ class SessionMiddleware(object):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class TurbolinksMiddleware(object):
|
class TurbolinksMiddleware(object): # pragma: no cover
|
||||||
"""
|
"""
|
||||||
Send the `Turbolinks-Location` header in response to a visit that was redirected,
|
Send the `Turbolinks-Location` header in response to a visit that was redirected,
|
||||||
and Turbolinks will replace the browser's topmost history entry.
|
and Turbolinks will replace the browser's topmost history entry.
|
||||||
|
@ -195,7 +195,7 @@ HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
|
|||||||
|
|
||||||
_db_type = os.getenv('DJANGO_DB_TYPE', 'sqlite').lower()
|
_db_type = os.getenv('DJANGO_DB_TYPE', 'sqlite').lower()
|
||||||
|
|
||||||
if _db_type == 'mysql' or _db_type.startswith('postgres') or _db_type == 'psql':
|
if _db_type == 'mysql' or _db_type.startswith('postgres') or _db_type == 'psql': # pragma: no cover
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.mysql' if _db_type == 'mysql' else 'django.db.backends.postgresql_psycopg2',
|
'ENGINE': 'django.db.backends.mysql' if _db_type == 'mysql' else 'django.db.backends.postgresql_psycopg2',
|
||||||
@ -214,7 +214,7 @@ else:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if os.getenv("CORRES2MATH_STAGE", "dev") == "prod":
|
if os.getenv("CORRES2MATH_STAGE", "dev") == "prod": # pragma: no cover
|
||||||
from .settings_prod import * # noqa: F401,F403
|
from .settings_prod import * # noqa: F401,F403
|
||||||
else:
|
else:
|
||||||
from .settings_dev import * # noqa: F401,F403
|
from .settings_dev import * # noqa: F401,F403
|
||||||
|
24
corres2math/tests.py
Normal file
24
corres2math/tests.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.handlers.asgi import ASGIHandler
|
||||||
|
from django.core.handlers.wsgi import WSGIHandler
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestLoadModules(TestCase):
|
||||||
|
"""
|
||||||
|
Load modules that are not used in development mode in order to increase coverage.
|
||||||
|
"""
|
||||||
|
def test_asgi(self):
|
||||||
|
from corres2math import asgi
|
||||||
|
self.assertTrue(isinstance(asgi.application, ASGIHandler))
|
||||||
|
|
||||||
|
def test_wsgi(self):
|
||||||
|
from corres2math import wsgi
|
||||||
|
self.assertTrue(isinstance(wsgi.application, WSGIHandler))
|
||||||
|
|
||||||
|
def test_load_production_settings(self):
|
||||||
|
os.putenv("CORRES2MATH_STAGE", "prod")
|
||||||
|
os.putenv("DJANGO_DB_TYPE", "postgres")
|
||||||
|
from corres2math import settings_prod
|
||||||
|
self.assertFalse(settings_prod.DEBUG)
|
2
tox.ini
2
tox.ini
@ -12,7 +12,7 @@ deps =
|
|||||||
-r{toxinidir}/requirements.txt
|
-r{toxinidir}/requirements.txt
|
||||||
coverage
|
coverage
|
||||||
commands =
|
commands =
|
||||||
coverage run --omit='apps/scripts*' --source=apps,corres2math ./manage.py test apps/
|
coverage run --source=apps,corres2math ./manage.py test apps/ corres2math/
|
||||||
coverage report -m
|
coverage report -m
|
||||||
|
|
||||||
[testenv:linters]
|
[testenv:linters]
|
||||||
|
Loading…
Reference in New Issue
Block a user