Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix restrictions logic bugs #298

Closed
wants to merge 56 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
9c2ed02
update model testen + start update serializer testen
ArnoutAllaert May 17, 2024
b7b7fee
fix indiening save functie + update serializer testen
ArnoutAllaert May 18, 2024
1a7cc49
update views testen
ArnoutAllaert May 18, 2024
e2e2a01
overal waar mogelijk PositiveSmallIntegerField gebruikt
ArnoutAllaert May 18, 2024
acb4b6c
template view testen
ArnoutAllaert May 18, 2024
cdbb811
coverage + linter
ArnoutAllaert May 18, 2024
772106c
linter
ArnoutAllaert May 18, 2024
8ef5e5e
confirmation mail test
ArnoutAllaert May 18, 2024
143257c
linter
ArnoutAllaert May 18, 2024
a61dfcf
coverage verslag + TODO verwijderd
ArnoutAllaert May 18, 2024
8001c05
update testen + Merge branch 'develop' into backend_testen
ArnoutAllaert May 19, 2024
6c4a6c2
coverage
ArnoutAllaert May 19, 2024
cf7d490
Merge pull request #286 from SELab-2/frontend
sPAICEcake May 20, 2024
6ac02e8
Update RestrictionTemplateUI.tsx
mathis2003 May 20, 2024
9849628
Merge pull request #288 from SELab-2/mathis2003-patch-1
mathis2003 May 20, 2024
7c1276f
unused import
sPAICEcake May 20, 2024
91b2f43
Merge pull request #265 from SELab-2/backend_testen
sPAICEcake May 20, 2024
f3f6387
logo login terug gezet
Bendemeurichy May 20, 2024
414d4c3
assignmentpage zou in orde moeten zijn terug, lijn per lijn nagekeken…
Bendemeurichy May 20, 2024
57d4511
index laten beginnen van 1 ipv 0
Bendemeurichy May 20, 2024
20101c0
tijdsformaat van dayjs gefixt op assignmentpage
gusvanpoucke May 20, 2024
d5aa7ec
kleine taalfix GroepsNummer -> Groepnummer
gusvanpoucke May 20, 2024
441bc87
Kleine patch die er gewoon voor zorgt dat je PATCH requests kan doen …
LGDTimtou May 20, 2024
e8e439e
Merge branch 'develop' into backend_extras
LGDTimtou May 20, 2024
a8326cb
Merge pull request #290 from SELab-2/backend_extras
LGDTimtou May 20, 2024
e98c1a7
'geen score' op subjectPage ipv 0/20
gusvanpoucke May 20, 2024
b31e8f1
cancel + alert add change subject
Bendemeurichy May 20, 2024
2a9f0d2
kotjes deadlines terug opgeschoond
Bendemeurichy May 20, 2024
a88b7fa
groepsleden knop geeft nu geen error meer, maar laat weten aan de stu…
gusvanpoucke May 20, 2024
2550f05
Merge branch 'merge_problems_fix' of https://github.com/SELab-2/UGent…
gusvanpoucke May 20, 2024
6c9d245
headers for restrictions list
mathis2003 May 20, 2024
7ba0357
opdracht icons worden nu wel geupdate op verandering van jaar in kale…
gusvanpoucke May 20, 2024
22e6eb2
status op mainpage in orde gebracht
Bendemeurichy May 20, 2024
87b2811
studentPopUp fixed
sPAICEcake May 20, 2024
bea5be1
pin icon verschijnt rechtsboven
gusvanpoucke May 20, 2024
afd8c57
'geen deadline' word nu overal correct getoond
gusvanpoucke May 20, 2024
423ba47
verwijderen restricties mogelijk + toevoegknop verplaatst
Bendemeurichy May 20, 2024
943f6e3
patch fix
Bendemeurichy May 20, 2024
80e9b75
Merge pull request #291 from SELab-2/restrictions_list_view
Bendemeurichy May 20, 2024
259e4ec
voeg jezelf toe bij nieuw vak, geen spookvakken meer
Bendemeurichy May 20, 2024
3e9aae3
Merge remote-tracking branch 'origin/merge_problems_fix' into merge_p…
Bendemeurichy May 20, 2024
f5727c6
cleanup restrictions box in addchangeAssigmentPage
friedrecursion May 20, 2024
68dc6dd
vakken renderen op jaartal
sPAICEcake May 20, 2024
feb5ff3
Merge branch 'merge_problems_fix' of https://github.com/SELab-2/UGent…
sPAICEcake May 20, 2024
ea950d4
Merge pull request #293 from SELab-2/restrictions_list_view
mathis2003 May 20, 2024
9cb42df
er verschijnen nu alerts als je op de addchangesubjectpage ongeldige …
gusvanpoucke May 20, 2024
13760ea
Merge branch 'merge_problems_fix' of https://github.com/SELab-2/UGent…
gusvanpoucke May 20, 2024
2b7145e
popup weggewerkt en jaarkeuze andere kleur
Bendemeurichy May 20, 2024
6b0f8cb
remove unused import
Bendemeurichy May 20, 2024
8999d02
Merge pull request #289 from SELab-2/merge_problems_fix
sPAICEcake May 20, 2024
b46d41c
positie jaarkiezer verandert
Bendemeurichy May 20, 2024
c95e8e2
Merge pull request #294 from SELab-2/merge_problems_fix
Bendemeurichy May 20, 2024
97c8a76
fixed missing properties
Bendemeurichy May 20, 2024
56374be
Merge pull request #295 from SELab-2/merge_problems_fix
Bendemeurichy May 20, 2024
28ced6f
fix opened template code
mathis2003 May 21, 2024
2387756
fix template names in editors
mathis2003 May 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .coverage
Binary file not shown.
1 change: 0 additions & 1 deletion api/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ def __call__(self, request):


class DisableCSRFMiddleware(object):

def __init__(self, get_response):
self.get_response = get_response

Expand Down
4 changes: 0 additions & 4 deletions api/models/indiening.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ def __str__(self):
return str(self.indiening_id)

def save(self, *args, **kwargs):
# First save to generate the indiening_id if it doesn't exist
if not self.indiening_id:
super(Indiening, self).save(*args, **kwargs)

# Update the bestand path if it's still using the temporary path
if "temp" in self.bestand.name:
old_file = self.bestand
Expand Down
6 changes: 3 additions & 3 deletions api/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Project(models.Model):
Standaard ingesteld op 20.
max_groep_grootte (IntegerField): Een veld voor het instellen van de max grootte van de groep voor het project.
Standaard ingesteld op 1.
student_groep (BooleanField): Een veld om aan te geven of het een individueel project is of niet.
student_groep (BooleanField): Een veld om aan te geven of de studenten hun eigen groep mogen kiezen.
Standaard ingesteld of False.
zichtbaar (BooleanField): Een veld om aan te geven of het project zichtbaar is of niet.
Standaard ingesteld op True.
Expand All @@ -57,8 +57,8 @@ class Project(models.Model):
vak = models.ForeignKey(Vak, on_delete=models.CASCADE)
deadline = models.DateTimeField(null=True, blank=True)
extra_deadline = models.DateTimeField(null=True, blank=True)
max_score = models.IntegerField(default=20)
max_groep_grootte = models.IntegerField(default=1)
max_score = models.PositiveSmallIntegerField(default=20)
max_groep_grootte = models.PositiveSmallIntegerField(default=1)
student_groep = models.BooleanField(default=False, blank=True)
zichtbaar = models.BooleanField(default=True, blank=True)
gearchiveerd = models.BooleanField(default=False, blank=True)
Expand Down
2 changes: 1 addition & 1 deletion api/models/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Score(models.Model):
"""

score_id = models.AutoField(primary_key=True)
score = models.SmallIntegerField()
score = models.PositiveSmallIntegerField()
indiening = models.ForeignKey("Indiening", on_delete=models.CASCADE)

def __str__(self):
Expand Down
2 changes: 1 addition & 1 deletion api/models/vak.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Vak(models.Model):

vak_id = models.AutoField(primary_key=True)
naam = models.CharField(max_length=100)
jaartal = models.IntegerField(default=date.today().year)
jaartal = models.PositiveSmallIntegerField(default=date.today().year)
gearchiveerd = models.BooleanField(default=False, blank=True)
studenten = models.ManyToManyField(
"Gebruiker", related_name="vak_gebruikers", blank=True
Expand Down
8 changes: 5 additions & 3 deletions api/serializers/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ def update(self, instance, validated_data):
Returns:
Project: Het bijgewerkte project.
"""
validated_data.pop("max_groep_grootte")
validated_data.pop("project_groep")
validated_data.pop("max_groep_grootte", None)
validated_data.pop("project_groep", None)

deadline = validated_data.pop("deadline", instance.deadline)
extra_deadline = validated_data.pop("extra_deadline", instance.extra_deadline)
Expand Down Expand Up @@ -103,7 +103,9 @@ def create_groepen(instance):
except Exception:
pass
else:
for _ in range(len(instance.vak.studenten.all())//instance.max_groep_grootte + 1):
for _ in range(
len(instance.vak.studenten.all()) // instance.max_groep_grootte + 1
):
try:
serializer = GroepSerializer(
data={"studenten": [], "project": instance.project_id}
Expand Down
6 changes: 5 additions & 1 deletion api/serializers/vak.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ def add_students_to_group(instance):

else:
groepen = Groep.objects.filter(project=project.project_id)
nieuwe_groepen = len(instance.studenten.all())//project.max_groep_grootte + 1 - len(groepen)
nieuwe_groepen = (
len(instance.studenten.all()) // project.max_groep_grootte
+ 1
- len(groepen)
)
for _ in range(nieuwe_groepen):
try:
serializer = GroepSerializer(
Expand Down
15 changes: 2 additions & 13 deletions api/tests/factories/indiening.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import factory
from api.models.indiening import Indiening, IndieningBestand
from api.models.indiening import Indiening
from factory.django import DjangoModelFactory
from factory import SubFactory
from .groep import GroepFactory
Expand All @@ -23,16 +23,5 @@ class Meta:
)
status = factory.Faker("boolean")
result = factory.Faker("paragraph")
artefacten = None

indiening_bestanden = factory.RelatedFactory(
"api.tests.factories.indiening.IndieningBestandFactory", "indiening"
)


class IndieningBestandFactory(DjangoModelFactory):
class Meta:
model = IndieningBestand

indiening = SubFactory(IndieningFactory)
bestand = FileField(filename="test.txt", data=b"file content")
artefacten = None
1 change: 1 addition & 0 deletions api/tests/factories/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ class Meta:
)
max_score = factory.Faker("random_int", min=10, max=100)
max_groep_grootte = factory.Faker("random_int", min=1, max=5)
student_groep = factory.Faker("boolean")
zichtbaar = factory.Faker("boolean")
gearchiveerd = factory.Faker("boolean")
3 changes: 1 addition & 2 deletions api/tests/factories/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ class Meta:
@classmethod
def _create(cls, model_class, *args, **kwargs):
indiening = kwargs.pop("indiening")
max_score = indiening.groep.project.max_score
kwargs["score"] = random.randint(0, max_score)
kwargs["score"] = random.randint(0, indiening.groep.project.max_score)
return super()._create(model_class, indiening=indiening, *args, **kwargs)
12 changes: 12 additions & 0 deletions api/tests/factories/template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import factory
from factory.django import FileField
from api.models.template import Template
from api.tests.factories.gebruiker import UserFactory


class TemplateFactory(factory.django.DjangoModelFactory):
class Meta:
model = Template

user = factory.SubFactory(UserFactory)
bestand = FileField(filename="template.txt", data=b"file content")
132 changes: 115 additions & 17 deletions api/tests/models/test_indiening.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
from django.test import TestCase
from django.core.files.uploadedfile import SimpleUploadedFile
from api.tests.factories.indiening import IndieningFactory, IndieningBestandFactory
from api.tests.factories.indiening import IndieningFactory
from api.models.indiening import upload_to
from unittest.mock import patch, MagicMock, call
from api.models.indiening import send_indiening_confirmation_mail
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import os


class IndieningModelTest(TestCase):
def setUp(self):
@patch("api.models.indiening.send_indiening_confirmation_mail")
def setUp(self, mock_send_mail):
self.indiening = IndieningFactory.create()

def test_str_method(self):
Expand All @@ -20,30 +25,123 @@ def test_tijdstip(self):
def test_status(self):
self.assertIsNotNone(self.indiening.status)

def test_indiening_bestanden(self):
self.assertEqual(self.indiening.indiening_bestanden.count(), 1)

def test_upload_to(self):
filename = "test_indiening.txt"
expected_path = (
f"data/indieningen/indiening_{self.indiening.indiening_id}/{filename}"
)
self.assertEqual(upload_to(self.indiening, filename), expected_path)

def test_artefacten(self):
self.assertIsNotNone(self.indiening.artefacten)

def test_result(self):
self.assertIsNotNone(self.indiening.result)

def test_bestand(self):
self.assertIsNotNone(self.indiening.bestand)

@patch("smtplib.SMTP_SSL")
@patch("ssl.create_default_context")
def test_send_indiening_confirmation_mail(
self, mock_create_default_context, mock_smtp
):
indiening = self.indiening
project = indiening.groep.project

smtp_server_address = "smtp.gmail.com"
smtp_port = 465
mail_username = os.environ.get("MAIL_USERNAME")
mail_app_password = os.environ.get("MAIL_APP_PASSWORD")
indiening_status = {
-1: "heeft niet alle testen geslaagd.",
0: "wordt nog getest...",
1: "heeft alle testen geslaagd!",
}
project_url = f"https://sel2-4.ugent.be/course/{project.vak.vak_id}/assignment/{project.project_id}"
indiening_url = f"https://sel2-4.ugent.be/course/{project.vak.vak_id}/assignment/ \
{project.project_id}/submission/{indiening.indiening_id}"

# Setup the mock SMTP_SSL object
mock_smtp_instance = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_smtp_instance

# Call the function
send_indiening_confirmation_mail(indiening)

# Check that create_default_context was called once
assert mock_create_default_context.call_count == 1

class IndieningBestandModelTest(TestCase):
def setUp(self):
self.indiening_bestand = IndieningBestandFactory.create(
bestand=SimpleUploadedFile("file.txt", b"file_content")
# Check that SMTP_SSL was called with the correct arguments
assert mock_smtp.call_count == indiening.groep.studenten.count()
mock_smtp.assert_has_calls(
[
call(
smtp_server_address,
smtp_port,
context=mock_create_default_context.return_value,
)
]
* indiening.groep.studenten.count()
)

def test_str_method(self):
self.assertEqual(
str(self.indiening_bestand), str(self.indiening_bestand.bestand.name)
# Check that login was called with the correct arguments
mock_smtp_instance.login.assert_called_with(mail_username, mail_app_password)

# Check that sendmail was called once for each student
assert (
mock_smtp_instance.sendmail.call_count == indiening.groep.studenten.count()
)

def test_indiening(self):
self.assertIsNotNone(self.indiening_bestand.indiening)
# Check that sendmail was called with the correct arguments
for student in indiening.groep.studenten.all():
subject = "Indieningsontvangst"

def test_bestand(self):
self.assertIsNotNone(self.indiening_bestand.bestand)
email = MIMEMultipart("alternative")
email["Subject"] = subject
email["From"] = mail_username
email["To"] = student.user.email

plain_text = f"""
Beste {student.user.first_name} {student.user.last_name},

Dit is een bevestiging dat uw indiening voor het project {project.titel} is ontvangen.
De indiening {indiening_status[indiening.status]}.
"""

html_text = f"""
<html>
<body>
<p>Beste {student.user.first_name} {student.user.last_name}</p>
<p>Dit is een bevestiging dat uw indiening voor het project \
<a href="{project_url}">{project.titel}</a> is ontvangen.</p>
<p>De <a href="{indiening_url}">indiening</a> {indiening_status[indiening.status]}</p>
</body>
</html>
"""

email.attach(MIMEText(plain_text, "plain"))
email.attach(MIMEText(html_text, "html"))

call_args_list = mock_smtp_instance.sendmail.call_args_list
for mock_call in call_args_list:
(
sent_mail_username,
sent_student_email,
sent_email_content,
) = mock_call.args
assert sent_mail_username == mail_username
assert sent_student_email == student.user.email
assert subject in sent_email_content
assert (
f"Beste {student.user.first_name} {student.user.last_name}"
in sent_email_content
)
assert (
f"Dit is een bevestiging dat uw indiening voor het project {project.titel} is ontvangen."
in sent_email_content
)
assert (
f"De indiening {indiening_status[indiening.status]}"
in sent_email_content
)
4 changes: 3 additions & 1 deletion api/tests/models/test_score.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from django.test import TestCase
from api.tests.factories.score import ScoreFactory
from api.tests.factories.indiening import IndieningFactory
from unittest.mock import patch


class ScoreModelTest(TestCase):
def setUp(self):
@patch("api.models.indiening.send_indiening_confirmation_mail")
def setUp(self, mock_send_mail):
self.indiening = IndieningFactory.create()
self.score = ScoreFactory.create(indiening=self.indiening)

Expand Down
21 changes: 21 additions & 0 deletions api/tests/models/test_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from django.test import TestCase
from api.tests.factories.template import TemplateFactory
from api.models.template import Template
from api.models.template import upload_to


class TemplateModelTest(TestCase):
def setUp(self):
self.template = TemplateFactory.create()

def test_template_creation(self):
self.assertIsInstance(self.template, Template)
self.assertEqual(Template.objects.count(), 1)

def test_template_str(self):
self.assertEqual(str(self.template), self.template.bestand.name)

def test_upload_to(self):
filename = "test_template.txt"
expected_path = f"data/templates/gebruiker_{self.template.user.id}/{filename}"
self.assertEqual(upload_to(self.template, filename), expected_path)
Loading
Loading