mirror of https://github.com/ae-utbm/sith3.git
Compare commits
7 Commits
38f6c27983
...
5ccb499665
Author | SHA1 | Date |
---|---|---|
Antoine Bartuccio | 5ccb499665 | |
Antoine Bartuccio | c467165bf3 | |
Antoine Bartuccio | 8512f3c5d0 | |
Antoine Bartuccio | 5003e57338 | |
Antoine Bartuccio | b7c2da53fe | |
Antoine Bartuccio | 598cdc0284 | |
Antoine Bartuccio | 692d9a25e3 |
|
@ -77,4 +77,25 @@ class UVCommentForm(forms.ModelForm):
|
|||
|
||||
class Meta:
|
||||
model = UVComment
|
||||
fields = ()
|
||||
fields = (
|
||||
"author",
|
||||
"uv",
|
||||
"grade_global",
|
||||
"grade_utility",
|
||||
"grade_interest",
|
||||
"grade_teaching",
|
||||
"grade_work_load",
|
||||
"comment",
|
||||
)
|
||||
widgets = {
|
||||
"comment": MarkdownInput,
|
||||
"author": forms.HiddenInput,
|
||||
"uv": forms.HiddenInput,
|
||||
}
|
||||
|
||||
def __init__(self, author_id, uv_id, *args, **kwargs):
|
||||
super(UVCommentForm, self).__init__(*args, **kwargs)
|
||||
self.fields["author"].queryset = User.objects.filter(id=author_id).all()
|
||||
self.fields["author"].initial = author_id
|
||||
self.fields["uv"].queryset = UV.objects.filter(id=uv_id).all()
|
||||
self.fields["uv"].initial = uv_id
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.20 on 2019-06-15 15:00
|
||||
# Generated by Django 1.11.20 on 2019-06-16 14:22
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -176,7 +176,7 @@ class Migration(migrations.Migration):
|
|||
"author",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="created_UVs",
|
||||
related_name="uv_created",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="author",
|
||||
),
|
||||
|
@ -194,7 +194,85 @@ class Migration(migrations.Migration):
|
|||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
)
|
||||
),
|
||||
("comment", models.TextField(verbose_name="comment")),
|
||||
(
|
||||
"grade_global",
|
||||
models.IntegerField(
|
||||
default=-1,
|
||||
validators=[
|
||||
django.core.validators.MinValueValidator(-1),
|
||||
django.core.validators.MaxValueValidator(5),
|
||||
],
|
||||
verbose_name="global grade",
|
||||
),
|
||||
),
|
||||
(
|
||||
"grade_utility",
|
||||
models.IntegerField(
|
||||
default=-1,
|
||||
validators=[
|
||||
django.core.validators.MinValueValidator(-1),
|
||||
django.core.validators.MaxValueValidator(5),
|
||||
],
|
||||
verbose_name="utility grade",
|
||||
),
|
||||
),
|
||||
(
|
||||
"grade_interest",
|
||||
models.IntegerField(
|
||||
default=-1,
|
||||
validators=[
|
||||
django.core.validators.MinValueValidator(-1),
|
||||
django.core.validators.MaxValueValidator(5),
|
||||
],
|
||||
verbose_name="interest grade",
|
||||
),
|
||||
),
|
||||
(
|
||||
"grade_teaching",
|
||||
models.IntegerField(
|
||||
default=-1,
|
||||
validators=[
|
||||
django.core.validators.MinValueValidator(-1),
|
||||
django.core.validators.MaxValueValidator(5),
|
||||
],
|
||||
verbose_name="teaching grade",
|
||||
),
|
||||
),
|
||||
(
|
||||
"grade_work_load",
|
||||
models.IntegerField(
|
||||
default=-1,
|
||||
validators=[
|
||||
django.core.validators.MinValueValidator(-1),
|
||||
django.core.validators.MaxValueValidator(5),
|
||||
],
|
||||
verbose_name="work load grade",
|
||||
),
|
||||
),
|
||||
(
|
||||
"publish_date",
|
||||
models.DateField(auto_now=True, verbose_name="publish date"),
|
||||
),
|
||||
(
|
||||
"author",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="uv_comments",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="author",
|
||||
),
|
||||
),
|
||||
(
|
||||
"uv",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="comments",
|
||||
to="pedagogy.UV",
|
||||
verbose_name="uv",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
|
@ -211,4 +289,64 @@ class Migration(migrations.Migration):
|
|||
)
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="UVResult",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"grade",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("A", "A"),
|
||||
("B", "B"),
|
||||
("C", "C"),
|
||||
("D", "D"),
|
||||
("E", "E"),
|
||||
("FX", "FX"),
|
||||
("F", "F"),
|
||||
("ABS", "Abs"),
|
||||
],
|
||||
default="A",
|
||||
max_length=10,
|
||||
verbose_name="grade",
|
||||
),
|
||||
),
|
||||
(
|
||||
"semester",
|
||||
models.CharField(
|
||||
max_length=5,
|
||||
validators=[
|
||||
django.core.validators.RegexValidator("[AP][0-9]{3}")
|
||||
],
|
||||
verbose_name="semester",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="uv_results",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="user",
|
||||
),
|
||||
),
|
||||
(
|
||||
"uv",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="results",
|
||||
to="pedagogy.UV",
|
||||
verbose_name="uv",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -67,7 +67,7 @@ class UV(models.Model):
|
|||
)
|
||||
author = models.ForeignKey(
|
||||
User,
|
||||
related_name="created_UVs",
|
||||
related_name="uv_created",
|
||||
verbose_name=_("author"),
|
||||
null=False,
|
||||
blank=False,
|
||||
|
@ -152,7 +152,86 @@ class UVComment(models.Model):
|
|||
A comment about an UV
|
||||
"""
|
||||
|
||||
pass
|
||||
def is_owned_by(self, user):
|
||||
"""
|
||||
Is owned by a pedagogy admin, a superuser or the author himself
|
||||
"""
|
||||
return self.author == user or user.is_owner(self.uv)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s" % (self.uv, self.author)
|
||||
|
||||
author = models.ForeignKey(
|
||||
User,
|
||||
related_name="uv_comments",
|
||||
verbose_name=_("author"),
|
||||
null=False,
|
||||
blank=False,
|
||||
)
|
||||
uv = models.ForeignKey(UV, related_name="comments", verbose_name=_("uv"))
|
||||
comment = models.TextField(_("comment"))
|
||||
grade_global = models.IntegerField(
|
||||
_("global grade"),
|
||||
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
|
||||
blank=False,
|
||||
null=False,
|
||||
default=-1,
|
||||
)
|
||||
grade_utility = models.IntegerField(
|
||||
_("utility grade"),
|
||||
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
|
||||
blank=False,
|
||||
null=False,
|
||||
default=-1,
|
||||
)
|
||||
grade_interest = models.IntegerField(
|
||||
_("interest grade"),
|
||||
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
|
||||
blank=False,
|
||||
null=False,
|
||||
default=-1,
|
||||
)
|
||||
grade_teaching = models.IntegerField(
|
||||
_("teaching grade"),
|
||||
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
|
||||
blank=False,
|
||||
null=False,
|
||||
default=-1,
|
||||
)
|
||||
grade_work_load = models.IntegerField(
|
||||
_("work load grade"),
|
||||
validators=[validators.MinValueValidator(-1), validators.MaxValueValidator(5)],
|
||||
blank=False,
|
||||
null=False,
|
||||
default=-1,
|
||||
)
|
||||
publish_date = models.DateField(_("publish date"), auto_now=True)
|
||||
|
||||
|
||||
class UVResult(models.Model):
|
||||
"""
|
||||
Results got to an UV
|
||||
Views will be implemented after the first release
|
||||
Will list every UV done by an user
|
||||
Linked to user
|
||||
uv
|
||||
Contains a grade settings.SITH_PEDAGOGY_UV_RESULT_GRADE
|
||||
a semester (P/A)20xx
|
||||
"""
|
||||
|
||||
uv = models.ForeignKey(UV, related_name="results", verbose_name=_("uv"))
|
||||
user = models.ForeignKey(User, related_name="uv_results", verbose_name=("user"))
|
||||
grade = models.CharField(
|
||||
_("grade"),
|
||||
max_length=10,
|
||||
choices=settings.SITH_PEDAGOGY_UV_RESULT_GRADE,
|
||||
default=settings.SITH_PEDAGOGY_UV_RESULT_GRADE[0][0],
|
||||
)
|
||||
semester = models.CharField(
|
||||
_("semester"),
|
||||
max_length=5,
|
||||
validators=[validators.RegexValidator("[AP][0-9]{3}")],
|
||||
)
|
||||
|
||||
|
||||
class UVCommentReport(models.Model):
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{% endif %}
|
||||
{% for uv in object_list %}
|
||||
<p>
|
||||
{{ uv.code }}
|
||||
<a href="{{ url('pedagogy:uv_detail', uv_id=uv.id) }}">{{ uv.code }}</a>
|
||||
{% if user.is_owner(uv) -%}
|
||||
<a href="{{ url('pedagogy:uv_update', uv_id=uv.id) }}">{% trans %}Edit{% endtrans %}</a>
|
||||
<a href="{{ url('pedagogy:uv_delete', uv_id=uv.id) }}">{% trans %}Delete{% endtrans %}</a>
|
||||
|
|
|
@ -5,9 +5,35 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<p><a href="{{ url('pedagogy:guide') }}">{% trans %}Back{% endtrans %}</a></p>
|
||||
<h1>{{ object.code }} - {{ object.title }}</h1>
|
||||
<p>{{ object.objectives|markdown }}</p>
|
||||
<p>{{ object.program|markdown }}</p>
|
||||
<p>{{ object.skills|markdown }}</p>
|
||||
<p>{{ object.key_concepts|markdown }}</p>
|
||||
|
||||
{% if object.comments.exists() %}
|
||||
<h2>{% trans %}Comments{% endtrans %}</h2>
|
||||
{% for comment in object.comments.all() %}
|
||||
<p>{{ comment.grade_global }}</p>
|
||||
<p>{{ comment.grade_utility }}</p>
|
||||
<p>{{ comment.grade_interest }}</p>
|
||||
<p>{{ comment.grade_teaching }}</p>
|
||||
<p>{{ comment.grade_work_load }}</p>
|
||||
<p>{{ comment.comment }}</p>
|
||||
<p>{% trans %}Published: {% endtrans %}{{ comment.publish_date }}</p>
|
||||
<p>{% trans %}Author: {% endtrans %}{{ comment.author }}</p>
|
||||
{% if user.is_owner(comment) %}
|
||||
<p><a href="{{ url('pedagogy:comment_update', comment_id=comment.id) }}">{% trans %}Edit{% endtrans %}</a></p>
|
||||
<p><a href="{{ url('pedagogy:comment_delete', comment_id=comment.id) }}">{% trans %}Delete{% endtrans %}</a></p>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<h2>{% trans %}Leave comment{% endtrans %}</h2>
|
||||
<form action="{{ url('pedagogy:uv_detail', uv_id=object.id) }}" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p() }}
|
||||
<p><input type="submit" value="{% trans %}Comment{% endtrans %}" /></p>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -28,7 +28,51 @@ from django.core.management import call_command
|
|||
|
||||
from core.models import User
|
||||
|
||||
from pedagogy.models import UV
|
||||
from pedagogy.models import UV, UVComment
|
||||
|
||||
|
||||
def create_uv_template(user_id, code="IFC1", exclude_list=[]):
|
||||
"""
|
||||
Factory to help UV creation/update in post requests
|
||||
"""
|
||||
uv = {
|
||||
"code": code,
|
||||
"author": user_id,
|
||||
"credit_type": "TM",
|
||||
"semester": "SPRING",
|
||||
"language": "FR",
|
||||
"credits": 3,
|
||||
"hours_CM": 10,
|
||||
"hours_TD": 28,
|
||||
"hours_TP": 0,
|
||||
"hours_THE": 37,
|
||||
"hours_TE": 0,
|
||||
"manager": "Gilles BERTRAND",
|
||||
"title": "Algorithmique et programmation : niveau I, initiés - partie I",
|
||||
"objectives": """* Introduction à l'algorithmique et à la programmation pour initiés.
|
||||
* Pratiques et développement en langage C.""",
|
||||
"program": """* Découverte des outils élémentaires utilisés pour écrire, compiler et exécuter un programme écrit en langage C
|
||||
* Règles de programmation : normes en cours, règles de présentation du code, commentaires
|
||||
* Initiation à l'algorithmique et découverte des bases du langage C :
|
||||
* les conditions
|
||||
* les boucles
|
||||
* les types de données
|
||||
* les tableaux à une dimension
|
||||
* manipulations des chaînes de caractères
|
||||
* les fonctions et procédures""",
|
||||
"skills": "* D'écrire un algorithme et de l'implémenter en C",
|
||||
"key_concepts": """* Algorithme
|
||||
* Variables scalaires et vectorielles
|
||||
* Structures alternatives, répétitives
|
||||
* Fonctions, procédures
|
||||
* Chaînes de caractères""",
|
||||
}
|
||||
for excluded in exclude_list:
|
||||
uv.pop(excluded)
|
||||
return uv
|
||||
|
||||
|
||||
# UV class tests
|
||||
|
||||
|
||||
class UVCreation(TestCase):
|
||||
|
@ -43,48 +87,10 @@ class UVCreation(TestCase):
|
|||
self.sli = User.objects.filter(username="sli").first()
|
||||
self.guy = User.objects.filter(username="guy").first()
|
||||
|
||||
@staticmethod
|
||||
def create_uv_template(user_id, code="IFC1", exclude_list=[]):
|
||||
uv = {
|
||||
"code": code,
|
||||
"author": user_id,
|
||||
"credit_type": "TM",
|
||||
"semester": "SPRING",
|
||||
"language": "FR",
|
||||
"credits": 3,
|
||||
"hours_CM": 10,
|
||||
"hours_TD": 28,
|
||||
"hours_TP": 0,
|
||||
"hours_THE": 37,
|
||||
"hours_TE": 0,
|
||||
"manager": "Gilles BERTRAND",
|
||||
"title": "Algorithmique et programmation : niveau I, initiés - partie I",
|
||||
"objectives": """* Introduction à l'algorithmique et à la programmation pour initiés.
|
||||
* Pratiques et développement en langage C.""",
|
||||
"program": """* Découverte des outils élémentaires utilisés pour écrire, compiler et exécuter un programme écrit en langage C
|
||||
* Règles de programmation : normes en cours, règles de présentation du code, commentaires
|
||||
* Initiation à l'algorithmique et découverte des bases du langage C :
|
||||
* les conditions
|
||||
* les boucles
|
||||
* les types de données
|
||||
* les tableaux à une dimension
|
||||
* manipulations des chaînes de caractères
|
||||
* les fonctions et procédures""",
|
||||
"skills": "* D'écrire un algorithme et de l'implémenter en C",
|
||||
"key_concepts": """* Algorithme
|
||||
* Variables scalaires et vectorielles
|
||||
* Structures alternatives, répétitives
|
||||
* Fonctions, procédures
|
||||
* Chaînes de caractères""",
|
||||
}
|
||||
for excluded in exclude_list:
|
||||
uv.pop(excluded)
|
||||
return uv
|
||||
|
||||
def test_create_uv_admin_success(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_create"), self.create_uv_template(self.bibou.id)
|
||||
reverse("pedagogy:uv_create"), create_uv_template(self.bibou.id)
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
self.assertTrue(UV.objects.filter(code="IFC1").exists())
|
||||
|
@ -92,7 +98,7 @@ class UVCreation(TestCase):
|
|||
def test_create_uv_pedagogy_admin_success(self):
|
||||
self.client.login(username="tutu", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_create"), self.create_uv_template(self.tutu.id)
|
||||
reverse("pedagogy:uv_create"), create_uv_template(self.tutu.id)
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
self.assertTrue(UV.objects.filter(code="IFC1").exists())
|
||||
|
@ -100,21 +106,21 @@ class UVCreation(TestCase):
|
|||
def test_create_uv_unauthorized_fail(self):
|
||||
# Test with anonymous user
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_create"), self.create_uv_template(0)
|
||||
reverse("pedagogy:uv_create"), create_uv_template(0)
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Test with subscribed user
|
||||
self.client.login(username="sli", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_create"), self.create_uv_template(self.sli.id)
|
||||
reverse("pedagogy:uv_create"), create_uv_template(self.sli.id)
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Test with non subscribed user
|
||||
self.client.login(username="guy", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_create"), self.create_uv_template(self.guy.id)
|
||||
reverse("pedagogy:uv_create"), create_uv_template(self.guy.id)
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
|
@ -126,7 +132,7 @@ class UVCreation(TestCase):
|
|||
|
||||
# Test with wrong user id (if someone cheats on the hidden input)
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_create"), self.create_uv_template(self.bibou.id)
|
||||
reverse("pedagogy:uv_create"), create_uv_template(self.bibou.id)
|
||||
)
|
||||
self.assertNotEquals(response.status_code, 302)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
@ -134,10 +140,428 @@ class UVCreation(TestCase):
|
|||
# Remove a required field
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_create"),
|
||||
self.create_uv_template(self.tutu.id, exclude_list=["title"]),
|
||||
create_uv_template(self.tutu.id, exclude_list=["title"]),
|
||||
)
|
||||
self.assertNotEquals(response.status_code, 302)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
# Check that the UV hase never been created
|
||||
self.assertFalse(UV.objects.filter(code="IFC1").exists())
|
||||
|
||||
|
||||
class UVListTest(TestCase):
|
||||
"""
|
||||
Test guide display rights
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command("populate")
|
||||
|
||||
def test_uv_list_display_success(self):
|
||||
# Display for root
|
||||
self.client.login(username="root", password="plop")
|
||||
response = self.client.get(reverse("pedagogy:guide"))
|
||||
self.assertContains(response, text="PA00")
|
||||
|
||||
# Display for pedagogy admin
|
||||
self.client.login(username="tutu", password="plop")
|
||||
response = self.client.get(reverse("pedagogy:guide"))
|
||||
self.assertContains(response, text="PA00")
|
||||
|
||||
# Display for simple subscriber
|
||||
self.client.login(username="sli", password="plop")
|
||||
response = self.client.get(reverse("pedagogy:guide"))
|
||||
self.assertContains(response, text="PA00")
|
||||
|
||||
def test_uv_list_display_fail(self):
|
||||
# Don't display for anonymous user
|
||||
response = self.client.get(reverse("pedagogy:guide"))
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Don't display for none subscribed users
|
||||
self.client.login(username="guy", password="plop")
|
||||
response = self.client.get(reverse("pedagogy:guide"))
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
|
||||
class UVDeleteTest(TestCase):
|
||||
"""
|
||||
Test UV deletion rights
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command("populate")
|
||||
|
||||
def test_uv_delete_root_success(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
)
|
||||
)
|
||||
self.assertFalse(UV.objects.filter(code="PA00").exists())
|
||||
|
||||
def test_uv_delete_pedagogy_admin_success(self):
|
||||
self.client.login(username="tutu", password="plop")
|
||||
self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
)
|
||||
)
|
||||
self.assertFalse(UV.objects.filter(code="PA00").exists())
|
||||
|
||||
def test_uv_delete_pedagogy_unauthorized_fail(self):
|
||||
# Anonymous user
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
)
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Not subscribed user
|
||||
self.client.login(username="guy", password="plop")
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
)
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Simply subscribed user
|
||||
self.client.login(username="sli", password="plop")
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_delete", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
)
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Check that the UV still exists
|
||||
self.assertTrue(UV.objects.filter(code="PA00").exists())
|
||||
|
||||
|
||||
class UVUpdateTest(TestCase):
|
||||
"""
|
||||
Test UV update rights
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command("populate")
|
||||
self.bibou = User.objects.filter(username="root").first()
|
||||
self.tutu = User.objects.filter(username="tutu").first()
|
||||
self.sli = User.objects.filter(username="sli").first()
|
||||
self.guy = User.objects.filter(username="guy").first()
|
||||
|
||||
def test_uv_update_root_success(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
),
|
||||
create_uv_template(self.bibou.id, code="PA00"),
|
||||
)
|
||||
self.assertEquals(UV.objects.get(code="PA00").credit_type, "TM")
|
||||
|
||||
def test_uv_update_pedagogy_admin_success(self):
|
||||
self.client.login(username="tutu", password="plop")
|
||||
self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
),
|
||||
create_uv_template(self.tutu.id, code="PA00"),
|
||||
)
|
||||
self.assertEquals(UV.objects.get(code="PA00").credit_type, "TM")
|
||||
|
||||
def test_uv_update_pedagogy_unauthorized_fail(self):
|
||||
# Anonymous user
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
),
|
||||
create_uv_template(0, code="PA00"),
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Not subscribed user
|
||||
self.client.login(username="guy", password="plop")
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
),
|
||||
create_uv_template(self.guy.id, code="PA00"),
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Simply subscribed user
|
||||
self.client.login(username="sli", password="plop")
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"pedagogy:uv_update", kwargs={"uv_id": UV.objects.get(code="PA00").id}
|
||||
),
|
||||
create_uv_template(self.sli.id, code="PA00"),
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Check that the UV has not changed
|
||||
self.assertEquals(UV.objects.get(code="PA00").credit_type, "OM")
|
||||
|
||||
|
||||
# UVComment class tests
|
||||
|
||||
|
||||
def create_uv_comment_template(user_id, uv_code="PA00", exclude_list=[]):
|
||||
"""
|
||||
Factory to help UVComment creation/update in post requests
|
||||
"""
|
||||
comment = {
|
||||
"author": user_id,
|
||||
"uv": UV.objects.get(code=uv_code).id,
|
||||
"grade_global": 5,
|
||||
"grade_utility": 5,
|
||||
"grade_interest": 5,
|
||||
"grade_teaching": -1,
|
||||
"grade_work_load": 3,
|
||||
"comment": "Superbe UV qui fait vivre la vie associative de l'école",
|
||||
}
|
||||
for excluded in exclude_list:
|
||||
comment.pop(excluded)
|
||||
return comment
|
||||
|
||||
|
||||
class UVCommentCreationAndDisplay(TestCase):
|
||||
"""
|
||||
Test UVComment creation and it's display
|
||||
Display and creation are the same view
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command("populate")
|
||||
self.bibou = User.objects.filter(username="root").first()
|
||||
self.tutu = User.objects.filter(username="tutu").first()
|
||||
self.sli = User.objects.filter(username="sli").first()
|
||||
self.guy = User.objects.filter(username="guy").first()
|
||||
self.uv = UV.objects.get(code="PA00")
|
||||
|
||||
def test_create_uv_comment_admin_success(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
|
||||
create_uv_comment_template(self.bibou.id),
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
response = self.client.get(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
|
||||
)
|
||||
self.assertContains(response, text="Superbe UV")
|
||||
|
||||
def test_create_uv_comment_pedagogy_admin_success(self):
|
||||
self.client.login(username="tutu", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
|
||||
create_uv_comment_template(self.tutu.id),
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
response = self.client.get(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
|
||||
)
|
||||
self.assertContains(response, text="Superbe UV")
|
||||
|
||||
def test_create_uv_comment_subscriber_success(self):
|
||||
self.client.login(username="sli", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
|
||||
create_uv_comment_template(self.sli.id),
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
response = self.client.get(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
|
||||
)
|
||||
self.assertContains(response, text="Superbe UV")
|
||||
|
||||
def test_create_uv_comment_unauthorized_fail(self):
|
||||
# Test with anonymous user
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
|
||||
create_uv_comment_template(0),
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Test with non subscribed user
|
||||
self.client.login(username="guy", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
|
||||
create_uv_comment_template(self.guy.id),
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Check that the comment has never been created
|
||||
self.client.login(username="root", password="plop")
|
||||
response = self.client.get(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
|
||||
)
|
||||
self.assertNotContains(response, text="Superbe UV")
|
||||
|
||||
def test_create_uv_comment_bad_form_fail(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id}),
|
||||
create_uv_comment_template(self.bibou.id, exclude_list=["grade_global"]),
|
||||
)
|
||||
|
||||
self.assertEquals(response.status_code, 200)
|
||||
|
||||
response = self.client.get(
|
||||
reverse("pedagogy:uv_detail", kwargs={"uv_id": self.uv.id})
|
||||
)
|
||||
self.assertNotContains(response, text="Superbe UV")
|
||||
|
||||
|
||||
class UVCommentDeleteTest(TestCase):
|
||||
"""
|
||||
Test UVComment deletion rights
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command("populate")
|
||||
comment_kwargs = create_uv_comment_template(
|
||||
User.objects.get(username="krophil").id
|
||||
)
|
||||
comment_kwargs["author"] = User.objects.get(id=comment_kwargs["author"])
|
||||
comment_kwargs["uv"] = UV.objects.get(id=comment_kwargs["uv"])
|
||||
self.comment = UVComment(**comment_kwargs)
|
||||
self.comment.save()
|
||||
|
||||
def test_uv_comment_delete_root_success(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
self.client.post(
|
||||
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
|
||||
)
|
||||
self.assertFalse(UVComment.objects.filter(id=self.comment.id).exists())
|
||||
|
||||
def test_uv_comment_delete_pedagogy_admin_success(self):
|
||||
self.client.login(username="tutu", password="plop")
|
||||
self.client.post(
|
||||
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
|
||||
)
|
||||
self.assertFalse(UVComment.objects.filter(id=self.comment.id).exists())
|
||||
|
||||
def test_uv_comment_delete_author_success(self):
|
||||
self.client.login(username="krophil", password="plop")
|
||||
self.client.post(
|
||||
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
|
||||
)
|
||||
self.assertFalse(UVComment.objects.filter(id=self.comment.id).exists())
|
||||
|
||||
def test_uv_comment_delete_unauthorized_fail(self):
|
||||
# Anonymous user
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Unsbscribed user
|
||||
self.client.login(username="guy", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Subscribed user (not author of the comment)
|
||||
self.client.login(username="sli", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_delete", kwargs={"comment_id": self.comment.id})
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Check that the comment still exists
|
||||
self.assertTrue(UVComment.objects.filter(id=self.comment.id).exists())
|
||||
|
||||
|
||||
class UVCommentUpdateTest(TestCase):
|
||||
"""
|
||||
Test UVComment update rights
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
call_command("populate")
|
||||
|
||||
self.krophil = User.objects.get(username="krophil")
|
||||
|
||||
# Prepare a comment
|
||||
comment_kwargs = create_uv_comment_template(self.krophil.id)
|
||||
comment_kwargs["author"] = self.krophil
|
||||
comment_kwargs["uv"] = UV.objects.get(id=comment_kwargs["uv"])
|
||||
self.comment = UVComment(**comment_kwargs)
|
||||
self.comment.save()
|
||||
|
||||
# Prepare edit of this comment for post requests
|
||||
self.comment_edit = create_uv_comment_template(self.krophil.id)
|
||||
self.comment_edit["comment"] = "Edited"
|
||||
|
||||
def test_uv_comment_update_root_success(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
|
||||
self.comment_edit,
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
self.comment.refresh_from_db()
|
||||
self.assertEquals(self.comment.comment, self.comment_edit["comment"])
|
||||
|
||||
def test_uv_comment_update_pedagogy_admin_success(self):
|
||||
self.client.login(username="tutu", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
|
||||
self.comment_edit,
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
self.comment.refresh_from_db()
|
||||
self.assertEquals(self.comment.comment, self.comment_edit["comment"])
|
||||
|
||||
def test_uv_comment_update_author_success(self):
|
||||
self.client.login(username="krophil", password="plop")
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
|
||||
self.comment_edit,
|
||||
)
|
||||
self.assertEquals(response.status_code, 302)
|
||||
self.comment.refresh_from_db()
|
||||
self.assertEquals(self.comment.comment, self.comment_edit["comment"])
|
||||
|
||||
def test_uv_comment_update_unauthorized_fail(self):
|
||||
# Anonymous user
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
|
||||
self.comment_edit,
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Unsbscribed user
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
|
||||
self.comment_edit,
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Subscribed user (not author of the comment)
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
|
||||
self.comment_edit,
|
||||
)
|
||||
self.assertEquals(response.status_code, 403)
|
||||
|
||||
# Check that the comment hasn't change
|
||||
self.comment.refresh_from_db()
|
||||
self.assertNotEquals(self.comment.comment, self.comment_edit["comment"])
|
||||
|
||||
def test_uv_comment_update_original_author_does_not_change(self):
|
||||
self.client.login(username="root", password="plop")
|
||||
self.comment_edit["author"] = User.objects.get(username="root").id
|
||||
|
||||
response = self.client.post(
|
||||
reverse("pedagogy:comment_update", kwargs={"comment_id": self.comment.id}),
|
||||
self.comment_edit,
|
||||
)
|
||||
self.assertEquals(response.status_code, 200)
|
||||
self.assertEquals(self.comment.author, self.krophil)
|
||||
|
|
|
@ -31,9 +31,14 @@ urlpatterns = [
|
|||
url(r"^$", UVListView.as_view(), name="guide"),
|
||||
url(r"^uv/(?P<uv_id>[0-9]+)$", UVDetailFormView.as_view(), name="uv_detail"),
|
||||
url(
|
||||
r"^comment/(?P<comment_id>[0-9]+)$",
|
||||
UVCommentDetailView.as_view(),
|
||||
name="comment_detail",
|
||||
r"^comment/(?P<comment_id>[0-9]+)/edit$",
|
||||
UVCommentUpdateView.as_view(),
|
||||
name="comment_update",
|
||||
),
|
||||
url(
|
||||
r"^comment/(?P<comment_id>[0-9]+)/delete$",
|
||||
UVCommentDeleteView.as_view(),
|
||||
name="comment_delete",
|
||||
),
|
||||
url(
|
||||
r"^comment/(?P<comment_id>[0-9]+)/report$",
|
||||
|
|
|
@ -42,7 +42,7 @@ from core.views import (
|
|||
)
|
||||
|
||||
from pedagogy.forms import UVForm, UVCommentForm
|
||||
from pedagogy.models import UV
|
||||
from pedagogy.models import UV, UVComment
|
||||
|
||||
# Some mixins
|
||||
|
||||
|
@ -82,13 +82,55 @@ class UVDetailFormView(CanViewMixin, CanCreateUVFunctionMixin, DetailFormView):
|
|||
template_name = "pedagogy/uv_detail.jinja"
|
||||
form_class = UVCommentForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(UVDetailFormView, self).get_form_kwargs()
|
||||
kwargs["author_id"] = self.request.user.id
|
||||
kwargs["uv_id"] = self.get_object().id
|
||||
return kwargs
|
||||
|
||||
class UVCommentDetailView(DetailView):
|
||||
def form_valid(self, form):
|
||||
form.save()
|
||||
return super(UVDetailFormView, self).form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy(
|
||||
"pedagogy:uv_detail", kwargs={"uv_id": self.get_object().id}
|
||||
)
|
||||
|
||||
|
||||
class UVCommentUpdateView(CanEditPropMixin, UpdateView):
|
||||
"""
|
||||
Display a specified UVComment (for easy sharing of the comment)
|
||||
Allow edit of a given comment
|
||||
"""
|
||||
|
||||
pass
|
||||
model = UVComment
|
||||
form_class = UVCommentForm
|
||||
pk_url_kwarg = "comment_id"
|
||||
template_name = "core/edit.jinja"
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(UVCommentUpdateView, self).get_form_kwargs()
|
||||
obj = self.get_object()
|
||||
kwargs["author_id"] = obj.author.id
|
||||
kwargs["uv_id"] = obj.uv.id
|
||||
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})
|
||||
|
||||
|
||||
class UVCommentDeleteView(CanEditPropMixin, DeleteView):
|
||||
"""
|
||||
Allow delete of a given comment
|
||||
"""
|
||||
|
||||
model = UVComment
|
||||
pk_url_kwarg = "comment_id"
|
||||
template_name = "core/delete_confirm.jinja"
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("pedagogy:uv_detail", kwargs={"uv_id": self.object.uv.id})
|
||||
|
||||
|
||||
class UVListView(CanViewMixin, CanCreateUVFunctionMixin, ListView):
|
||||
|
|
|
@ -431,6 +431,17 @@ SITH_PEDAGOGY_UV_LANGUAGE = [
|
|||
("SP", _("Spanich")),
|
||||
]
|
||||
|
||||
SITH_PEDAGOGY_UV_RESULT_GRADE = [
|
||||
("A", _("A")),
|
||||
("B", _("B")),
|
||||
("C", _("C")),
|
||||
("D", _("D")),
|
||||
("E", _("E")),
|
||||
("FX", _("FX")),
|
||||
("F", _("F")),
|
||||
("ABS", _("Abs")),
|
||||
]
|
||||
|
||||
SITH_ECOCUP_CONS = 1152
|
||||
|
||||
SITH_ECOCUP_DECO = 1151
|
||||
|
|
Loading…
Reference in New Issue