# Copyright (C) 2017-2018 Alban Gruin # # celcatsanitizer is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # celcatsanitizer is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with celcatsanitizer. If not, see . from django.test import TestCase from django.utils import timezone from .models import Course, Group, Room, Source, Timetable, Year from .templatetags.rooms import format_rooms from .utils import tz_now import datetime class CourseTestCase(TestCase): def setUp(self): dt = tz_now() self.year = Year(name="L2", slug="l2") self.year.save() source = Source(url="http://example.org/") source.save() self.timetable = Timetable(year=self.year, name="Test timetable 2", source=source, slug="test-timetable2") self.timetable.save() cma = Group.objects.create(celcat_name="L1 info s2 CMA", source=source) tda2 = Group.objects.create(celcat_name="L1 info s2 TDA2", source=source) self.tpa21 = Group.objects.create(celcat_name="L1 info s2 TPA21", source=source) cmb = Group.objects.create(celcat_name="L1 info s2 CMB", source=source) tdb2 = Group.objects.create(celcat_name="L1 info s2 TDB2", source=source) self.tpb21 = Group.objects.create(celcat_name="L1 info s2 TPB21", source=source) for group in (cma, tda2, self.tpa21, cmb, tdb2, self.tpb21,): course = Course.objects.create( name="{0} course".format(group.name), type="cours", source=source, begin=dt, end=dt) course.groups.add(group) def test_get_courses_for_group(self): tpa21_courses = Course.objects.get_courses(self.tpa21) tpb21_courses = Course.objects.get_courses(self.tpb21) tpa21_course_names = ["L1 info s2 CMA course", "L1 info s2 TDA2 course", "L1 info s2 TPA21 course"] tpb21_course_names = ["L1 info s2 CMB course", "L1 info s2 TDB2 course", "L1 info s2 TPB21 course"] for courses, names in ((tpa21_courses, tpa21_course_names,), (tpb21_courses, tpb21_course_names,),): for course in courses: self.assertIn(course.name, names) names.remove(course.name) class GroupTestCase(TestCase): def setUp(self): self.year = Year(name="L1", slug="l1") self.year.save() self.source = Source(url="http://example.org/") self.source.save() self.timetable = Timetable(year=self.year, name="Test timetable", source=self.source, slug="test-timetable") self.timetable.save() Group.objects.create(celcat_name="L1 info s2 CMA", source=self.source) Group.objects.create(celcat_name="L1 info s2 TDA2", source=self.source) Group.objects.create(celcat_name="L1 info s2 TPA21", source=self.source) Group.objects.create(celcat_name="L1 info s2 CMB", source=self.source) Group.objects.create(celcat_name="L1 info s2 TDB2", source=self.source) Group.objects.create(celcat_name="L1 info s2 TPB21", source=self.source) Group.objects.create(celcat_name="L1 info (toutes sections et " "semestres confondus)", source=self.source) # Cas spéciaux de groupes sans semestre. Normalement un groupe # sans semestre ne possède pas de sous-groupe non plus, mais # certains cas font foirer la regex. Voici un exemple trouvé # dans la base de données de production. Group.objects.create(celcat_name="M1 GC (toutes sections et semestres " "confondus)", source=self.source) # Doit appartenir au groupe au-dessus. Group.objects.create(celcat_name="M1 GC s2 GA111", source=self.source) # Cas spécial avec les parenthèses Group.objects.create(celcat_name="M1 CHI-TCCM (EM) (toutes sections et" " semestres confondus)", source=self.source) Group.objects.create(celcat_name="M1 CHI-TCCM (EM) s2 TPA12", source=self.source) # Cas spécial avec un nombre supplémentaire dans le nom de groupe Group.objects.create(celcat_name="L1 4L s1 CM4L", source=self.source) Group.objects.create(celcat_name="L1 4L s1 TD4L1", source=self.source) Group.objects.create(celcat_name="L1 4L s1 TP4L12", source=self.source) def test_corresponds(self): cma = Group.objects.get(celcat_name="L1 info s2 CMA", source=self.source) tda2 = Group.objects.get(celcat_name="L1 info s2 TDA2", source=self.source) tpa21 = Group.objects.get(celcat_name="L1 info s2 TPA21", source=self.source) cmb = Group.objects.get(celcat_name="L1 info s2 CMB", source=self.source) tdb2 = Group.objects.get(celcat_name="L1 info s2 TDB2", source=self.source) tpb21 = Group.objects.get(celcat_name="L1 info s2 TPB21", source=self.source) general = Group.objects.get(celcat_name="L1 info (toutes sections et " "semestres confondus)", source=self.source) self.assertFalse(cma.corresponds_to(*tda2.group_info)) self.assertFalse(cma.corresponds_to(*tpa21.group_info)) self.assertFalse(tda2.corresponds_to(*tpa21.group_info)) self.assertFalse(cmb.corresponds_to(*tdb2.group_info)) self.assertFalse(cmb.corresponds_to(*tpb21.group_info)) self.assertFalse(tdb2.corresponds_to(*tpb21.group_info)) self.assertFalse(cmb.corresponds_to(*tda2.group_info)) self.assertFalse(cmb.corresponds_to(*tpa21.group_info)) self.assertFalse(tdb2.corresponds_to(*tpa21.group_info)) self.assertTrue(tda2.corresponds_to(*cma.group_info)) self.assertTrue(tpa21.corresponds_to(*cma.group_info)) self.assertTrue(tpa21.corresponds_to(*tda2.group_info)) self.assertTrue(tdb2.corresponds_to(*cmb.group_info)) self.assertTrue(tpb21.corresponds_to(*cmb.group_info)) self.assertTrue(tpb21.corresponds_to(*tdb2.group_info)) self.assertFalse(tda2.corresponds_to(*cmb.group_info)) self.assertFalse(tpa21.corresponds_to(*cmb.group_info)) self.assertFalse(tpa21.corresponds_to(*tdb2.group_info)) self.assertFalse(general.corresponds_to(*cma.group_info)) self.assertFalse(general.corresponds_to(*cmb.group_info)) self.assertFalse(general.corresponds_to(*tda2.group_info)) self.assertFalse(general.corresponds_to(*tdb2.group_info)) self.assertFalse(general.corresponds_to(*tpa21.group_info)) self.assertFalse(general.corresponds_to(*tpb21.group_info)) self.assertTrue(cma.corresponds_to(*general.group_info)) self.assertTrue(cmb.corresponds_to(*general.group_info)) self.assertTrue(tda2.corresponds_to(*general.group_info)) self.assertTrue(tdb2.corresponds_to(*general.group_info)) self.assertTrue(tpa21.corresponds_to(*general.group_info)) self.assertTrue(tpb21.corresponds_to(*general.group_info)) def test_corresponds_no_semester(self): general = Group.objects.get(celcat_name="M1 GC (toutes sections et " "semestres confondus)", source=self.source) ga111 = Group.objects.get(celcat_name="M1 GC s2 GA111", source=self.source) self.assertTrue(ga111.corresponds_to(*general.group_info)) self.assertFalse(general.corresponds_to(*ga111.group_info)) def test_corresponds_number(self): cm4l = Group.objects.get(celcat_name="L1 4L s1 CM4L", source=self.source) td4l1 = Group.objects.get(celcat_name="L1 4L s1 TD4L1", source=self.source) tp4l12 = Group.objects.get(celcat_name="L1 4L s1 TP4L12", source=self.source) self.assertFalse(cm4l.corresponds_to(*td4l1.group_info)) self.assertFalse(cm4l.corresponds_to(*tp4l12.group_info)) self.assertFalse(td4l1.corresponds_to(*tp4l12.group_info)) self.assertTrue(td4l1.corresponds_to(*cm4l.group_info)) self.assertTrue(tp4l12.corresponds_to(*cm4l.group_info)) self.assertTrue(tp4l12.corresponds_to(*td4l1.group_info)) def test_correspond_parenthesis(self): general = Group.objects.get(celcat_name="M1 CHI-TCCM (EM) (toutes" " sections et semestres confondus)") a12 = Group.objects.get(celcat_name="M1 CHI-TCCM (EM) s2 TPA12") self.assertTrue(a12.corresponds_to(*general.group_info)) self.assertFalse(general.corresponds_to(*a12.group_info)) def test_get(self): cma = Group.objects.get(name="L1 info s2 CMA", source=self.source) tda2 = Group.objects.get(name="L1 info s2 TDA2", source=self.source) tpa21 = Group.objects.get(name="L1 info s2 TPA21", source=self.source) cmb = Group.objects.get(name="L1 info s2 CMB", source=self.source) tdb2 = Group.objects.get(name="L1 info s2 TDB2", source=self.source) tpb21 = Group.objects.get(name="L1 info s2 TPB21", source=self.source) general = Group.objects.get(celcat_name="L1 info (toutes sections et " "semestres confondus)", source=self.source) self.assertEqual(cma.celcat_name, "L1 info s2 CMA") self.assertEqual(tda2.celcat_name, "L1 info s2 TDA2") self.assertEqual(tpa21.celcat_name, "L1 info s2 TPA21") self.assertEqual(cmb.celcat_name, "L1 info s2 CMB") self.assertEqual(tdb2.celcat_name, "L1 info s2 TDB2") self.assertEqual(tpb21.celcat_name, "L1 info s2 TPB21") self.assertEqual(general.celcat_name, "L1 info (toutes sections et " "semestres confondus)") def test_parse(self): cma = Group.objects.get(celcat_name="L1 info s2 CMA", source=self.source) tda2 = Group.objects.get(celcat_name="L1 info s2 TDA2", source=self.source) tpa21 = Group.objects.get(celcat_name="L1 info s2 TPA21", source=self.source) cmb = Group.objects.get(celcat_name="L1 info s2 CMB", source=self.source) tdb2 = Group.objects.get(celcat_name="L1 info s2 TDB2", source=self.source) tpb21 = Group.objects.get(celcat_name="L1 info s2 TPB21", source=self.source) general = Group.objects.get(celcat_name="L1 info (toutes sections et " "semestres confondus)", source=self.source) self.assertEqual(cma.group_info, ("L1 info", 2, "A")) self.assertEqual(tda2.group_info, ("L1 info", 2, "A2")) self.assertEqual(tpa21.group_info, ("L1 info", 2, "A21")) self.assertEqual(cmb.group_info, ("L1 info", 2, "B")) self.assertEqual(tdb2.group_info, ("L1 info", 2, "B2")) self.assertEqual(tpb21.group_info, ("L1 info", 2, "B21")) self.assertEqual(general.group_info, ("L1 info", None, "")) def test_parse_no_semester(self): general = Group.objects.get(celcat_name="M1 GC (toutes sections et " "semestres confondus)", source=self.source) ga111 = Group.objects.get(celcat_name="M1 GC s2 GA111", source=self.source) self.assertEqual(general.group_info, ("M1 GC", None, "")) self.assertEqual(ga111.group_info, ("M1 GC", 2, "A111")) def test_parse_number(self): cm4l = Group.objects.get(celcat_name="L1 4L s1 CM4L", source=self.source) td4l1 = Group.objects.get(celcat_name="L1 4L s1 TD4L1", source=self.source) tp4l12 = Group.objects.get(celcat_name="L1 4L s1 TP4L12", source=self.source) self.assertEqual(cm4l.group_info, ("L1 4L", 1, "4L")) self.assertEqual(td4l1.group_info, ("L1 4L", 1, "4L1")) self.assertEqual(tp4l12.group_info, ("L1 4L", 1, "4L12")) def test_parse_parenthesis(self): general = Group.objects.get(celcat_name="M1 CHI-TCCM (EM) (toutes" " sections et semestres confondus)") a12 = Group.objects.get(celcat_name="M1 CHI-TCCM (EM) s2 TPA12") self.assertEqual(general.group_info, ("M1 CHI-TCCM (EM)", None, "")) self.assertEqual(a12.group_info, ("M1 CHI-TCCM (EM)", 2, "A12")) class RoomTestCase(TestCase): def setUp(self): self.day = datetime.datetime(year=2018, month=1, day=27) self.year = Year.objects.create(name="L1") self.source = Source.objects.create(url="http://example.org/") # Pas besoin de créer plus de groupes que ça, ni de le rendre # global group = Group.objects.create(celcat_name="L1 info s2 CMA", source=self.source) self.rooms = [ Room.objects.create(name=str(i)) for i in range(5) ] + [ Room.objects.create(name="Amphi {}".format(i)) for i in range(5, 7) ] hours = [({"begin": datetime.time(hour=14, minute=0)},), ({"begin": datetime.time(hour=16, minute=0)},), ({"begin": datetime.time(hour=13, minute=30)}, {"begin": datetime.time(hour=16, minute=0)}), ({"begin": datetime.time(hour=14, minute=0), "duration": 4},), ({"begin": datetime.time(hour=15, minute=30), "duration": 1},), ({"begin": datetime.time(hour=13, minute=0)}, {"begin": datetime.time(hour=17, minute=0)}), ()] for i, room in enumerate(self.rooms): for rn in hours[i]: begin = timezone.make_aware( datetime.datetime.combine(self.day, rn["begin"])) end = begin + datetime.timedelta(hours=rn.get("duration", 2)) course = Course.objects.create(source=self.source, begin=begin, end=end) course.groups.add(group) course.rooms.add(room) def test_format(self): amphis = self.rooms[-2:] self.assertEqual(format_rooms([]), "") self.assertEqual(format_rooms(self.rooms[:1]), "Salle 0") self.assertEqual(format_rooms(self.rooms[:2]), "Salles 0, 1") self.assertEqual(format_rooms([amphis[0]]), "Amphi 5") self.assertEqual(format_rooms(amphis), "Amphi 5, Amphi 6") self.assertEqual(format_rooms([amphis[0]] + self.rooms[:1]), "Amphi 5, salle 0") self.assertEqual(format_rooms([amphis[0]] + self.rooms[:2]), "Amphi 5, salles 0, 1") self.assertEqual(format_rooms(amphis + self.rooms[:1]), "Amphi 5, Amphi 6, salle 0") self.assertEqual(format_rooms(amphis + self.rooms[:2]), "Amphi 5, Amphi 6, salles 0, 1") def test_qsjps(self): begin = timezone.make_aware(datetime.datetime.combine( self.day, datetime.time(hour=15, minute=0))) end = begin + datetime.timedelta(hours=2) rooms = Room.objects.qsjps(begin, end) self.assertEqual(rooms.count(), 2) self.assertNotIn(self.rooms[0], rooms) self.assertNotIn(self.rooms[1], rooms) self.assertNotIn(self.rooms[2], rooms) self.assertNotIn(self.rooms[3], rooms) self.assertNotIn(self.rooms[4], rooms) self.assertIn(self.rooms[5], rooms) self.assertIn(self.rooms[6], rooms)