def test_signup_restricitons(self): """Make sure users can't sign up for restricted activities or switch out of sticky activities.""" self.make_admin() get_user_model().objects.create(username="******", graduation_year=get_senior_graduation_year()) user2 = get_user_model().objects.create(username="******", graduation_year=get_senior_graduation_year()) block1 = self.add_block(date="2015-01-01", block_letter="A") room1 = self.add_room(name="room1", capacity=1) act1 = self.add_activity(name="Test Activity 1", sticky=True, restricted=True, users_allowed=[user2]) act1.rooms.add(room1) schact1 = EighthScheduledActivity.objects.create(block=block1, activity=act1, capacity=5) act2 = self.add_activity(name="Test Activity 2") act2.rooms.add(room1) EighthScheduledActivity.objects.create(block=block1, activity=act2, capacity=5) # Ensure that user1 can't sign up for act1 self.client.post(reverse("eighth_signup", args=[block1.id]), {"aid": act1.id}) self.assertEqual(len(EighthScheduledActivity.objects.get(block=block1.id, activity=act1.id).members.all()), 0) # Ensure that user2 can sign up for act1 self.verify_signup(user2, schact1) # Now that user2 is signed up for act1, make sure they can't switch themselves out self.client.post(reverse("eighth_signup", args=[block1.id]), {"aid": act2.id}) self.assertEqual(len(EighthScheduledActivity.objects.get(block=block1.id, activity=act1.id).members.all()), 1) self.assertEqual(len(EighthScheduledActivity.objects.get(block=block1.id, activity=act2.id).members.all()), 0)
def test_take_attendance_google_meet_csv(self): """Make sure taking attendence through an uploaded Google Meet file works.""" self.make_admin() user1 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1, student_id=12345, first_name="Test", last_name="User") user2 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1, student_id=12346, first_name="TestTwo", last_name="UserTwo") block1 = self.add_block(date="3000-11-11", block_letter="A") room1 = self.add_room(name="room1", capacity=5) act1 = self.add_activity(name="Test Activity 1") act1.rooms.add(room1) schact1 = self.schedule_activity(act1.id, block1.id, capacity=5) schact1.attendance_taken = False schact1.add_user(user1) schact1.add_user(user2) schact1.save() with tempfile.NamedTemporaryFile(mode="w+") as f: writer = csv.DictWriter(f, fieldnames=["Name", "Email"]) writer.writeheader() writer.writerow({ "Name": "Test User", "Email": "*****@*****.**" }) f.seek(0) self.client.post( reverse("eighth_take_attendance", args=[schact1.id]), {"attendance": f}) # Make sure attendance has been marked as taken. self.assertTrue( EighthScheduledActivity.objects.get( id=schact1.id).attendance_taken) # Make sure EighthSignup object hasn't been marked absent for user1. self.assertFalse( EighthSignup.objects.get(user=user1, scheduled_activity=schact1).was_absent) # Make sure EighthSignup object was marked absent for user2. self.assertTrue( EighthSignup.objects.get(user=user2, scheduled_activity=schact1).was_absent)
def test_stats_global_view(self): # I am unauthorized; this should 403 self.login("awilliam") response = self.client.get(reverse("eighth_statistics_global")) self.assertEqual(403, response.status_code) self.make_admin() response = self.client.get(reverse("eighth_statistics_global")) self.assertEqual(200, response.status_code) # Generate PDF response = self.client.post(reverse("eighth_statistics_global"), data={ "year": get_senior_graduation_year(), "generate": "pdf" }) self.assertEqual(200, response.status_code) # Generate CSV response = self.client.post(reverse("eighth_statistics_global"), data={ "year": get_senior_graduation_year(), "generate": "csv" }) self.assertEqual(200, response.status_code) # Add an activity then do it again act = self.add_activity(name="Test Activity 1") # Generate PDF response = self.client.post(reverse("eighth_statistics_global"), data={ "year": get_senior_graduation_year(), "generate": "pdf" }) self.assertEqual(200, response.status_code) # Generate CSV response = self.client.post(reverse("eighth_statistics_global"), data={ "year": get_senior_graduation_year(), "generate": "csv" }) self.assertEqual(200, response.status_code) # Attempt to parse the CSV reader = csv.DictReader( response.content.decode(encoding="UTF-8").split("\n")) # Loop over all of them, but there should only be one for row in reader: self.assertEqual(act.name, row["Activity"])
def test_signup_statistics(self): """Tests the signup_statistics command.""" # Add an activity but no signups today = timezone.localtime() block1 = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity1 = EighthActivity.objects.get_or_create(name="Test Activity")[0] scheduled1 = EighthScheduledActivity.objects.get_or_create(block=block1, activity=activity1, capacity=5)[0] # Run the command out = StringIO() call_command("signup_statistics", activity1.id, stdout=out) reader = csv.DictReader(out.getvalue().splitlines()) reader_contents = list(reader) self.assertEqual(0, len(reader_contents)) # Add a signup user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William", first_name="Angela", )[0] EighthSignup.objects.create(user=user, scheduled_activity=scheduled1) # Run the command out = StringIO() call_command("signup_statistics", activity1.id, stdout=out) reader = csv.DictReader(out.getvalue().splitlines()) reader_contents = list(reader) self.assertEqual(1, len(reader_contents)) self.assertEqual([{"TJ Username": "******", "First Name": "Angela", "Last Name": "William", "Number of Signups": "1"}], reader_contents)
def test_remove_withdrawn_students(self): """Tests the remove_withdrawn_students command.""" Group.objects.all().delete() # Call the command - it should error because the "Withdrawn from TJ" group doesn't exist out = StringIO() call_command("remove_withdrawn_students", stdout=out) self.assertIn("Withdrawn group could not be found", out.getvalue()) # Add a group with no students group = Group.objects.create(name="Withdrawn from TJ", id=9) out = StringIO() call_command("remove_withdrawn_students", stdout=out) self.assertIn("No users found in withdrawn group", out.getvalue()) # Add a user to that group user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William" )[0] user.groups.add(group) user.save() out = StringIO() call_command("remove_withdrawn_students", stdout=out) self.assertIn("Deleting 2021awilliam", out.getvalue()) self.assertEqual(0, get_user_model().objects.filter(username="******").count())
def test_clear_absence_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.attendance.clear_absence_view`.""" self.make_admin() # Add a user with an absence today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create( block=block, activity=activity, attendance_taken=True)[0] user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William")[0] signup = EighthSignup.objects.create(user=user, scheduled_activity=scheduled, was_absent=True) response = self.client.post( reverse("eighth_admin_clear_absence", kwargs={"signup_id": signup.id})) self.assertEqual(302, response.status_code) # to dashboard self.assertFalse(EighthSignup.objects.get(id=signup.id).was_absent)
def test_no_signups_roster(self): """Tests :func:`~intranet.apps.eighth.views.admin.attendance.no_signups_roster`.""" admin_user = self.make_admin() admin_user.user_type = "teacher" admin_user.save() # Add a block today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] EighthScheduledActivity.objects.get_or_create(block=block, activity=activity, attendance_taken=True) # Load the page response = self.client.get( reverse("eighth_admin_no_signups_roster", kwargs={"block_id": block.id})) self.assertEqual(200, response.status_code) self.assertEqual([], response.context["users"]) # Test CSV output response = self.client.get( reverse("eighth_admin_no_signups_csv", kwargs={"block_id": block.id})) self.assertEqual(200, response.status_code) reader = csv.DictReader(response.content.decode("UTF-8").split("\n")) reader_contents = list(reader) self.assertEqual(0, len(reader_contents)) # Add a user user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student")[0] # Load the page response = self.client.get( reverse("eighth_admin_no_signups_roster", kwargs={"block_id": block.id})) self.assertEqual(200, response.status_code) self.assertEqual([user], response.context["users"]) # Test CSV output response = self.client.get( reverse("eighth_admin_no_signups_csv", kwargs={"block_id": block.id})) self.assertEqual(200, response.status_code) reader = csv.DictReader(response.content.decode("UTF-8").split("\n")) reader_contents = list(reader) self.assertEqual(1, len(reader_contents)) self.assertEqual(reader_contents[0]["TJ Email"], "*****@*****.**")
def test_out_of_building_schedules_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.attendance.out_of_building_schedules_view`.""" self.make_admin() # First just load the page response = self.client.get( reverse("eighth_admin_export_out_of_building_schedules")) self.assertEqual(200, response.status_code) # Add a block and the "out of building" room, and an activity set to that room today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] room = EighthRoom.objects.get_or_create(name="Out of Building", capacity=5000)[0] activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] activity.rooms.add(room) activity.save() scheduled = EighthScheduledActivity.objects.get_or_create( block=block, activity=activity, attendance_taken=True)[0] # Load the page with that block response = self.client.get( reverse("eighth_admin_export_out_of_building_schedules"), data={"block": block.id}) self.assertEqual(200, response.status_code) self.assertEqual([], list(response.context["signups"])) # Add a user with a signup user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William")[0] signup = EighthSignup.objects.create(user=user, scheduled_activity=scheduled) # Load the page with that block response = self.client.get( reverse("eighth_admin_export_out_of_building_schedules"), data={"block": block.id}) self.assertEqual(200, response.status_code) self.assertEqual([signup], list(response.context["signups"])) # Test CSV response = self.client.get( reverse("eighth_admin_export_out_of_building_schedules_csv", kwargs={"block_id": block.id})) self.assertEqual(200, response.status_code) reader = csv.DictReader(response.content.decode("UTF-8").split("\n")) reader_contents = list(reader) self.assertEqual(1, len(reader_contents)) self.assertEqual("William", reader_contents[0]["Last Name"]) self.assertEqual(str(activity.id), reader_contents[0]["Activity ID"])
def test_open_passes_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.attendance.open_passes_view`.""" self.make_admin() # Load the page response = self.client.get(reverse("eighth_admin_view_open_passes")) self.assertEqual(200, response.status_code) # Make a student with a pass today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create( block=block, activity=activity, attendance_taken=True)[0] user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William")[0] signup = EighthSignup.objects.create(user=user, scheduled_activity=scheduled, after_deadline=True) # Accept the pass response = self.client.post(reverse("eighth_admin_view_open_passes"), data={signup.id: "accept"}) self.assertEqual(200, response.status_code) self.assertTrue(EighthSignup.objects.get(id=signup.id).pass_accepted) self.assertFalse(EighthSignup.objects.get(id=signup.id).was_absent) # Now, reject the pass response = self.client.post(reverse("eighth_admin_view_open_passes"), data={signup.id: "reject"}) self.assertEqual(200, response.status_code) self.assertTrue(EighthSignup.objects.get(id=signup.id).pass_accepted) self.assertTrue(EighthSignup.objects.get(id=signup.id).was_absent) # Test the CSV view # but first, reset the pass signup = EighthSignup.objects.get(id=signup.id) signup.pass_accepted = False signup.was_absent = False signup.save() response = self.client.get( reverse("eighth_admin_view_open_passes_csv")) self.assertEqual(200, response.status_code) reader = csv.DictReader(response.content.decode("UTF-8").split("\n")) reader_contents = list(reader) self.assertEqual(1, len(reader_contents)) self.assertEqual("0", reader_contents[0]["Absences"])
def add_arguments(self, parser): parser.add_argument("--run", action="store_true", dest="run", default=False, help="Actually run.") parser.add_argument("--confirm", action="store_true", dest="confirm", default=False, help="Skip confirmation.") parser.add_argument( "--senior-graduation-year", dest="senior_grad_year", type=int, default=get_senior_graduation_year(), help="The senior graduation year", )
def test_signup_status_email(self): """Tests the signup_status_email command.""" EighthBlock.objects.all().delete() get_user_model().objects.all().delete() # Running the command should error with "No upcoming blocks" out = StringIO() call_command("signup_status_email", stdout=out) self.assertIn("No upcoming blocks", out.getvalue()) # Make an EighthBlock today = timezone.localtime() block1 = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] with patch("intranet.apps.eighth.management.commands.signup_status_email.signup_status_email") as m: call_command("signup_status_email") m.assert_not_called() # Make a user but don't sign that user up user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William", first_name="Angela", )[0] with patch("intranet.apps.eighth.management.commands.signup_status_email.signup_status_email") as m: call_command("signup_status_email", "--everyone") m.assert_called_once() # Sign this user up for an activity activity1 = EighthActivity.objects.get_or_create(name="Test Activity")[0] scheduled1 = EighthScheduledActivity.objects.get_or_create(block=block1, activity=activity1, capacity=5)[0] EighthSignup.objects.create(scheduled_activity=scheduled1, user=user) with patch("intranet.apps.eighth.management.commands.signup_status_email.signup_status_email") as m: call_command("signup_status_email", "--everyone") m.assert_not_called() # Cancel that activity scheduled1.cancel() with patch("intranet.apps.eighth.management.commands.signup_status_email.signup_status_email") as m: call_command("signup_status_email", "--everyone") m.assert_called_once()
def test_activity_stats(self): self.make_admin() user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year())[0] block_a = self.add_block(date="2013-4-20", block_letter="A") block_b = self.add_block(date="2013-4-20", block_letter="B") act1 = self.add_activity(name="Test1") act2 = self.add_activity(name="Test2") schact_a = EighthScheduledActivity.objects.create(block=block_a, activity=act1) schact_b = EighthScheduledActivity.objects.create(block=block_b, activity=act1) EighthSignup.objects.create(scheduled_activity=schact_a, user=user) EighthSignup.objects.create(scheduled_activity=schact_b, user=user) response = self.client.get(reverse("eighth_statistics_multiple")) self.assertEqual(200, response.status_code) response = self.client.post( reverse("eighth_statistics_multiple"), { "activities": [act1.id, act2.id], "lower": "", "upper": "", "start": "2020-10-01", "end": "2020-10-24", "freshmen": "on", "sophmores": "on", "juniors": "on", "seniors": "on", }, ) self.assertEqual(len(response.context["signed_up"]), 0) response = self.client.post( reverse("eighth_statistics_multiple"), { "activities": [act1.id, act2.id], "lower": "", "upper": "", "start": "2013-01-01", "end": "2020-10-24", "freshmen": "on", "sophmores": "on", "juniors": "on", "seniors": "on", }, ) self.assertEqual(len(response.context["signed_up"]), 1) self.assertEqual(response.context["signed_up"][0]["signups"], 2)
def test_assign_withdrawn_students(self): """Tests :func:`~intranet.apps.eighth.views.admin.blocks.add_block_view`.""" self.make_admin() # Create a Z - Withdrawn from TJ activity activity = EighthActivity.objects.create(name="Z - Withdrawn from TJ") # Create a Withdrawn from TJ group and add a student grp = Group.objects.create(name="Withdrawn from TJ") user = get_user_model().objects.get_or_create( username="******", first_name="T", last_name="Test", graduation_year=get_senior_graduation_year())[0] user.groups.add(grp) user.save() # Make a block with the Withdrawn option enabled response = self.client.post( reverse("eighth_admin_add_block"), data={ "date": timezone.localtime().date().isoformat(), "modify_blocks": True, "blocks": ["A"], "assign_withdrawn": "on" }, ) self.assertEqual(200, response.status_code) block = EighthBlock.objects.get( date=timezone.localtime().date().isoformat(), block_letter="A") # Check that scheduled Z - Withdrawn from TJ activity exists in block sch_act = EighthScheduledActivity.objects.filter(block=block, activity=activity) self.assertEqual(len(sch_act), 1) self.assertTrue( EighthSignup.objects.filter( user=user, scheduled_activity=sch_act[0]).exists()) # Remove the block response = self.client.post( reverse("eighth_admin_add_block"), data={ "date": timezone.localtime().date().isoformat(), "modify_blocks": True, "blocks": [] })
def test_add_member_to_group_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.groups.add_member_to_group_view`""" self.make_admin() # Add a group and a user not in that group group = Group.objects.get_or_create(name="test group 8")[0] user1 = get_user_model().objects.get_or_create( username="******", first_name="Tommy", last_name="Test", student_id=1234568, user_type="student", graduation_year=get_senior_graduation_year(), )[0] # POST to that page by student ID response = self.client.post(reverse("eighth_admin_add_member_to_group", kwargs={"group_id": group.id}), data={"query": 1234568}) self.assertEqual(302, response.status_code) self.assertIn(group, get_user_model().objects.get(id=user1.id).groups.all()) # POST to that page by username response = self.client.post(reverse("eighth_admin_add_member_to_group", kwargs={"group_id": group.id}), data={"query": "2021ttest"}) self.assertEqual(200, response.status_code) self.assertIn(user1, response.context["users"]) # Remove the user from the group and try with Ion user IDs user1 = get_user_model().objects.get(id=user1.id) user1.groups.remove(group) user1.save() response = self.client.post(reverse("eighth_admin_add_member_to_group", kwargs={"group_id": group.id}), data={"user_id": [user1.id]}) self.assertEqual(302, response.status_code) self.assertIn(group, get_user_model().objects.get(id=user1.id).groups.all()) # GET should not work response = self.client.get(reverse("eighth_admin_add_member_to_group", kwargs={"group_id": group.id}), data={"query": "2021ttest"}) self.assertEqual(405, response.status_code)
def test_after_deadline_signup_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.attendance.after_deadline_signup_view`.""" admin_user = self.make_admin() admin_user.user_type = "teacher" admin_user.save() # Add a block today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create( block=block, activity=activity, attendance_taken=True)[0] # Load the page response = self.client.get( reverse("eighth_admin_view_after_deadline_signups")) self.assertEqual(200, response.status_code) self.assertEqual([], list(response.context["signups"])) # Make a user and a late signup user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William")[0] signup = EighthSignup.objects.create(user=user, scheduled_activity=scheduled, after_deadline=True) # Load the page response = self.client.get( reverse("eighth_admin_view_after_deadline_signups")) self.assertEqual(200, response.status_code) self.assertEqual([signup], list(response.context["signups"])) # Test CSV output response = self.client.get( reverse("eighth_admin_download_after_deadline_signups_csv")) self.assertEqual(200, response.status_code) reader = csv.DictReader(response.content.decode("UTF-8").split("\n")) reader_contents = list(reader) self.assertEqual(1, len(reader_contents)) self.assertEqual("William", reader_contents[0]["Last Name"]) self.assertEqual(str(block), reader_contents[0]["Block"])
def test_delete_duplicate_signups(self): """Tests the delete duplicate signups command.""" # I can't really create a duplicate signup, but I can test to make sure that # this command doesn't remove singular signups today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create(name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create(block=block, activity=activity)[0] user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William" )[0] signup = EighthSignup.objects.create(user=user, scheduled_activity=scheduled) call_command("delete_duplicate_signups") self.assertEqual(1, EighthSignup.objects.filter(id=signup.id).count())
def test_metrics_view(self): """Tests :func:`~intranet.apps.eighth.views.monitoring.metrics_view`.""" get_user_model().objects.all().delete() self.make_admin() response = self.client.get(reverse("metrics")) self.assertEqual(200, response.status_code) self.assertEqual( "intranet_eighth_next_block_signups 0\nintranet_eighth_next_block_signups_remaining 0\n\n", response.content.decode("UTF-8")) # Add a block and a student EighthBlock.objects.all().delete() today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] student = get_user_model().objects.get_or_create( username="******", user_type="student", graduation_year=get_senior_graduation_year() + 1)[0] response = self.client.get(reverse("metrics")) self.assertEqual(200, response.status_code) self.assertEqual( "intranet_eighth_next_block_signups 0\nintranet_eighth_next_block_signups_remaining 1\n\n", response.content.decode("UTF-8")) # Add an activity and a signup activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create( block=block, activity=activity)[0] EighthSignup.objects.get_or_create(user=student, scheduled_activity=scheduled) response = self.client.get(reverse("metrics")) self.assertEqual(200, response.status_code) self.assertEqual( "intranet_eighth_next_block_signups 1\nintranet_eighth_next_block_signups_remaining 0\n\n", response.content.decode("UTF-8"))
def test_eighth_signup_view(self): """Tests :func:`~intranet.apps.eighth.views.signup.eighth_signup_view`.""" # First, log in as a student get_user_model().objects.all().delete() user = self.login("2021awilliam") user.user_type = "student" user.graduation_year = get_senior_graduation_year() user.save() # Load the page. # response = self.client.get(reverse("eighth_signup")) # self.assertEqual(200, response.status_code) # Create an activity, schedule it, and attempt to sign up. today = timezone.localtime().date() block1 = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] EighthBlock.objects.get_or_create(date=today, block_letter="B") activity = EighthActivity.objects.get_or_create(name="Test Activity", default_capacity=5)[0] scheduled1 = EighthScheduledActivity.objects.get_or_create(block=block1, activity=activity, capacity=5)[0] response = self.client.post(reverse("eighth_signup"), data={"uid": user.id, "bid": block1.id, "aid": activity.id}) self.assertEqual(200, response.status_code) self.assertEqual(1, EighthSignup.objects.filter(user=user, scheduled_activity=scheduled1).count()) # Test unsignup self.make_admin() response = self.client.post(reverse("eighth_signup"), data={"uid": user.id, "bid": block1.id, "unsignup": "unsignup"}) self.assertEqual(200, response.status_code) self.assertEqual(0, EighthSignup.objects.filter(user=user, scheduled_activity=scheduled1).count()) response = self.client.post(reverse("eighth_signup"), data={"uid": user.id, "bid": block1.id, "unsignup": "unsignup"}) self.assertEqual(200, response.status_code) self.assertEqual("The signup did not exist.", response.content.decode("UTF-8")) # Test the "block" GET parameter response = self.client.get(reverse("eighth_signup"), data={"block": block1.id}) self.assertEqual(302, response.status_code) self.assertEqual(reverse("eighth_signup", kwargs={"block_id": block1.id}), response.url) response = self.client.get(reverse("eighth_signup"), data={"block": block1.id, "user": user.id}) self.assertEqual(302, response.status_code) self.assertEqual(reverse("eighth_signup", kwargs={"block_id": block1.id}) + f"?user={user.id}", response.url)
def test_remove_member_from_group_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.groups.remove_member_from_group_view`""" self.make_admin() # Add a group and a user in that group group = Group.objects.get_or_create(name="test group 9")[0] user1 = get_user_model().objects.get_or_create( username="******", first_name="Tommy", last_name="Test", student_id=1234568, user_type="student", graduation_year=get_senior_graduation_year(), )[0] user1.groups.add(group) user1.save() # A GET should not do anything response = self.client.get( reverse("eighth_admin_remove_member_from_group", kwargs={ "group_id": group.id, "user_id": user1.id })) self.assertEqual(405, response.status_code) self.assertIn(group, get_user_model().objects.get(id=user1.id).groups.all()) # POST to remove the user from the group response = self.client.post( reverse("eighth_admin_remove_member_from_group", kwargs={ "group_id": group.id, "user_id": user1.id })) self.assertEqual(302, response.status_code) self.assertNotIn( group, get_user_model().objects.get(id=user1.id).groups.all())
def test_eighth_multi_signup_view(self): """Tests :func:`~intranet.apps.eighth.views.signup.eighth_multi_signup_view`.""" # First, log in as a student get_user_model().objects.all().delete() user = self.login("2021awilliam") user.user_type = "student" user.graduation_year = get_senior_graduation_year() user.save() # Load the page. response = self.client.get(reverse("eighth_multi_signup")) self.assertEqual(200, response.status_code) # Add some blocks and schedule activities today = timezone.localtime().date() block1 = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] block2 = EighthBlock.objects.get_or_create(date=today, block_letter="B")[0] activity = EighthActivity.objects.get_or_create(name="Test Activity", default_capacity=5)[0] scheduled1 = EighthScheduledActivity.objects.get_or_create(block=block1, activity=activity, capacity=5)[0] scheduled2 = EighthScheduledActivity.objects.get_or_create(block=block2, activity=activity, capacity=5)[0] # Load the page. response = self.client.get(reverse("eighth_multi_signup"), data={"block": [block1.id, block2.id]}) self.assertEqual(200, response.status_code) self.assertEqual([block1, block2], list(response.context["blocks"])) # Parse the JSON in `response.context["activities_list"]` act_list = json.loads(str(response.context["activities_list"]).encode().decode("unicode-escape")) self.assertEqual(1, len(act_list)) # There is one activity self.assertEqual(block1.id, act_list["1"]["blocks"][0]["id"]) self.assertEqual(block2.id, act_list["1"]["blocks"][1]["id"]) # Try signing this user up for that activity on both blocks self.make_admin() response = self.client.post(reverse("eighth_multi_signup"), data={"bid": f"{block1.id},{block2.id}", "uid": user.id, "aid": activity.id}) self.assertEqual(200, response.status_code) self.assertEqual(1, EighthSignup.objects.filter(user=user, scheduled_activity=scheduled2).count()) self.assertEqual(1, EighthSignup.objects.filter(user=user, scheduled_activity=scheduled1).count())
def test_take_attendance_cancelled(self): """Make sure students in a cancelled activity are marked as absent when the button is pressed.""" self.make_admin() user1 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1) block1 = self.add_block(date="3000-11-11", block_letter="A") room1 = self.add_room(name="room1", capacity=1) act1 = self.add_activity(name="Test Activity 1") act1.rooms.add(room1) schact1 = self.schedule_activity(act1.id, block1.id) schact1.attendance_taken = False schact1.add_user(user1) schact1.cancelled = True schact1.save() response = self.client.post( reverse("eighth_admin_view_activities_without_attendance") + "?" + urlencode({"block": block1.id}), {"take_attendance_cancelled": "1"}) self.assertEqual(response.status_code, 302) # Make sure attendance has been marked as taken. self.assertTrue( EighthScheduledActivity.objects.get( id=schact1.id).attendance_taken) # Make sure EighthSignup object has been marked as absent. self.assertTrue( EighthSignup.objects.get(user=user1, scheduled_activity=schact1).was_absent) # Make sure student has correct number of absences. self.assertEqual( get_user_model().objects.get(id=user1.id).absence_count(), 1)
def test_stats_view(self): self.make_admin() act = self.add_activity(name="Test Activity 2") response = self.client.get( reverse("eighth_statistics", kwargs={"activity_id": act.id})) self.assertEqual(200, response.status_code) # Add a block and scheduled activity today = timezone.localtime().date() block = self.add_block(date=today, block_letter="A") EighthScheduledActivity.objects.create(activity=act, block=block) response = self.client.get(reverse("eighth_statistics", kwargs={"activity_id": act.id}), data={"year": get_senior_graduation_year()}) self.assertEqual(200, response.status_code) response = self.client.get(reverse("eighth_statistics", kwargs={"activity_id": act.id}), data={"print": True}) self.assertEqual(200, response.status_code)
def test_find_duplicates(self): """Tests the find duplicates command.""" EighthSignup.objects.all().delete() # Just run the command. out = StringIO() call_command("find_duplicates", stdout=out) self.assertIn("No duplicate signups found", out.getvalue()) # Add a user with a signup today = timezone.localtime() block1 = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity1 = EighthActivity.objects.get_or_create(name="Test Activity")[0] scheduled1 = EighthScheduledActivity.objects.get_or_create(block=block1, activity=activity1, capacity=5)[0] user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William" )[0] EighthSignup.objects.create(user=user, scheduled_activity=scheduled1) out = StringIO() call_command("find_duplicates", stdout=out) self.assertIn("No duplicate signups found", out.getvalue())
def test_dev_generate_signups(self): """Tests the dev_generate_signups command.""" # First, call this command with nothing set up. get_user_model().objects.all().delete() EighthBlock.objects.all().delete() EighthActivity.objects.all().delete() today = timezone.localtime() with patch("intranet.apps.eighth.management.commands.dev_generate_signups.input", return_value="y") as m: with self.assertRaises(CommandError): call_command("dev_generate_signups", today.strftime("%m/%d/%Y")) m.assert_called_once() # Create some blocks and activities, and schedule them block1 = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity1 = EighthActivity.objects.get_or_create(name="Test Activity")[0] scheduled1 = EighthScheduledActivity.objects.get_or_create(block=block1, activity=activity1, capacity=5)[0] block2 = EighthBlock.objects.get_or_create(date=today, block_letter="B")[0] activity2 = EighthActivity.objects.get_or_create(name="Test Activity")[0] scheduled2 = EighthScheduledActivity.objects.get_or_create(block=block2, activity=activity2, capacity=5)[0] user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William" )[0] # Call the command with patch("intranet.apps.eighth.management.commands.dev_generate_signups.input", return_value="y") as m: call_command("dev_generate_signups", today.strftime("%m/%d/%Y")) m.assert_called_once() self.assertEqual(2, EighthSignup.objects.filter(user=user, scheduled_activity__in=[scheduled2, scheduled1]).count())
def test_absence_email(self): """Tests the absence_email command.""" # Make a user, block, activity, and an absent signup today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create(name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create(block=block, activity=activity, attendance_taken=True)[0] user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William" )[0] signup = EighthSignup.objects.create(user=user, scheduled_activity=scheduled, was_absent=True) # Run command with patch("intranet.apps.eighth.management.commands.absence_email.absence_email", return_value=None) as m: call_command("absence_email") m.assert_called_once_with(signup) self.assertTrue(EighthSignup.objects.get(id=signup.id).absence_emailed) signup = EighthSignup.objects.get(id=signup.id) signup.absence_emailed = False signup.save() with patch("intranet.apps.eighth.management.commands.absence_email.absence_email", return_value=None) as m: call_command("absence_email", "--pretend") m.assert_not_called() self.assertFalse(EighthSignup.objects.get(id=signup.id).absence_emailed) with patch("intranet.apps.eighth.management.commands.absence_email.absence_email", return_value=None) as m: call_command("absence_email", "--silent") m.assert_called_once_with(signup) self.assertTrue(EighthSignup.objects.get(id=signup.id).absence_emailed)
def test_take_attendance(self): """Makes sure that taking attendance for activites with multiple students signed up works.""" self.make_admin() user1 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1, student_id=12345, first_name="Test", last_name="User") user2 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1, student_id=12346, first_name="TestTwo", last_name="UserTwo") user3 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1, student_id=12347, first_name="TestThree", last_name="UserThree") block1 = self.add_block(date="3000-11-11", block_letter="A") room1 = self.add_room(name="room1", capacity=5) act1 = self.add_activity(name="Test Activity 1") act1.rooms.add(room1) schact1 = self.schedule_activity(act1.id, block1.id, capacity=5) schact1.attendance_taken = False schact1.add_user(user1) schact1.add_user(user2) schact1.add_user(user3) schact1.save() # Simulate taking attendance with user1 and user3 present, but user2 absent. response = self.client.post(reverse("eighth_take_attendance", args=[schact1.id]), data={ user1.id: "on", user3.id: "on" }) self.assertEqual(response.status_code, 302) # Make sure activity is marked as attendance taken. self.assertTrue( EighthScheduledActivity.objects.get( id=schact1.id).attendance_taken) # Make sure EighthSignup object hasn't been marked absent for user1. self.assertFalse( EighthSignup.objects.get(user=user1, scheduled_activity=schact1).was_absent) # Make sure EighthSignup object was marked absent for user2. self.assertTrue( EighthSignup.objects.get(user=user2, scheduled_activity=schact1).was_absent) # Make sure EighthSignup object hasn't been marked absent for user3. self.assertFalse( EighthSignup.objects.get(user=user3, scheduled_activity=schact1).was_absent)
def test_take_attendance_google_meet_csv(self): """Make sure taking attendence through an uploaded Google Meet file works.""" self.make_admin() user1 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1, student_id=12345, first_name="Test", last_name="User") user2 = get_user_model().objects.create( username="******", graduation_year=get_senior_graduation_year() + 1, student_id=12346, first_name="TestTwo", last_name="UserTwo") block1 = self.add_block(date="3000-11-11", block_letter="A") room1 = self.add_room(name="room1", capacity=5) act1 = self.add_activity(name="Test Activity 1") act1.rooms.add(room1) schact1 = self.schedule_activity(act1.id, block1.id, capacity=5) schact1.attendance_taken = False schact1.add_user(user1) schact1.add_user(user2) schact1.save() with tempfile.NamedTemporaryFile(mode="w+") as f: writer = csv.DictWriter(f, fieldnames=["Name", "Email"]) writer.writeheader() writer.writerow({ "Name": "Test User", "Email": "*****@*****.**" }) f.seek(0) self.client.post( reverse("eighth_take_attendance", args=[schact1.id]), {"attendance": f}) # Make sure attendance has been marked as taken. self.assertTrue( EighthScheduledActivity.objects.get( id=schact1.id).attendance_taken) # Make sure EighthSignup object hasn't been marked absent for user1. self.assertFalse( EighthSignup.objects.get(user=user1, scheduled_activity=schact1).was_absent) # Make sure EighthSignup object was marked absent for user2. self.assertTrue( EighthSignup.objects.get(user=user2, scheduled_activity=schact1).was_absent) # Make sure bad file fails nicely with KeyError with tempfile.NamedTemporaryFile(mode="w+") as f: writer = csv.DictWriter(f, fieldnames=["NotName", "NotEmail"]) writer.writeheader() writer.writerow({ "NotName": "Test User", "NotEmail": "*****@*****.**" }) f.seek(0) response = self.client.post(reverse("eighth_take_attendance", args=[schact1.id]), {"attendance": f}, follow=True) self.assertIn( "Could not interpret file. Did you upload a Google Meet attendance report without modification?", list(map(str, list(response.context["messages"]))), ) self.assertEqual(response.status_code, 200) # Make sure bad file fails nicely with IndexError with tempfile.NamedTemporaryFile(mode="w+") as f: writer = csv.DictWriter(f, fieldnames=["Name", "Email"]) writer.writeheader() writer.writerow({"Name": "User", "Email": "@fcpsschools.net"}) f.seek(0) response = self.client.post(reverse("eighth_take_attendance", args=[schact1.id]), {"attendance": f}, follow=True) self.assertIn( "Could not interpret file. Did you upload a Google Meet attendance report without modification?", list(map(str, list(response.context["messages"]))), ) self.assertEqual(response.status_code, 200) # Make sure bad file fails nicely with ValueError with tempfile.NamedTemporaryFile(mode="w+") as f: writer = csv.DictWriter(f, fieldnames=["Name", "Email"]) writer.writeheader() writer.writerow({"Name": 1, "Email": 5}) f.seek(0) self.assertIn( "Could not interpret file. Did you upload a Google Meet attendance report without modification?", list(map(str, list(response.context["messages"]))), ) self.assertEqual(response.status_code, 200)
def test_schedule_activity_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.scheduling.schedule_activity_view`.""" self.make_admin() # Add a block and an activity today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] EighthBlock.objects.get_or_create(date=today, block_letter="B") activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] # Load the page response = self.client.get(reverse("eighth_admin_schedule_activity")) self.assertEqual(200, response.status_code) # Load the page and select the activity response = self.client.get(reverse("eighth_admin_schedule_activity"), data={"activity": activity.id}) self.assertEqual(200, response.status_code) self.assertEqual(activity, response.context["activity"]) self.assertEqual(block, response.context["rows"][0][0]) # Schedule this activity response = self.client.post( reverse("eighth_admin_schedule_activity"), data={ "form-TOTAL_FORMS": "1", "form-INITIAL_FORMS": "0", "form-MAX_NUM_FORMS": "", "form-0-block": block.id, "form-0-activity": activity.id, "form-0-scheduled": True, "form-0-capacity": 5, }, ) self.assertEqual(302, response.status_code) self.assertEqual( 1, EighthScheduledActivity.objects.filter(block=block, activity=activity, capacity=5).count()) # Cancel this activity response = self.client.post( reverse("eighth_admin_schedule_activity"), data={ "form-TOTAL_FORMS": "1", "form-INITIAL_FORMS": "0", "form-MAX_NUM_FORMS": "", "form-0-block": block.id, "form-0-activity": activity.id, "form-0-scheduled": False, "form-0-capacity": 5, }, ) self.assertEqual(302, response.status_code) self.assertEqual( 1, EighthScheduledActivity.objects.filter(block=block, activity=activity, capacity=5, cancelled=True).count()) # Unschedule this activity (i.e. delete it) response = self.client.post( reverse("eighth_admin_schedule_activity"), data={ "form-TOTAL_FORMS": "1", "form-INITIAL_FORMS": "0", "form-MAX_NUM_FORMS": "", "form-0-block": block.id, "form-0-activity": activity.id, "form-0-scheduled": False, "form-0-unschedule": True, "form-0-capacity": 5, }, ) self.assertEqual(302, response.status_code) self.assertEqual( 0, EighthScheduledActivity.objects.filter(block=block, activity=activity, capacity=5).count()) # Test both blocks scheduling activity.both_blocks = True activity.save() response = self.client.post( reverse("eighth_admin_schedule_activity"), data={ "form-TOTAL_FORMS": "1", "form-INITIAL_FORMS": "0", "form-MAX_NUM_FORMS": "", "form-0-block": block.id, "form-0-activity": activity.id, "form-0-scheduled": True, "form-0-capacity": 5, "form-0-both_blocks": True, }, ) self.assertEqual(302, response.status_code) self.assertEqual( 1, EighthScheduledActivity.objects.filter(block=block, activity=activity, capacity=5, both_blocks=True).count()) # Sign someone up for this activity user1 = get_user_model().objects.get_or_create( username="******", first_name="Tommy", last_name="Test", student_id=1234568, user_type="student", graduation_year=get_senior_graduation_year(), )[0] signup = EighthSignup.objects.get_or_create( user=user1, scheduled_activity=EighthScheduledActivity.objects.get( block=block, activity=activity, capacity=5, both_blocks=True))[0] # Cancelling should still work response = self.client.post( reverse("eighth_admin_schedule_activity"), data={ "form-TOTAL_FORMS": "1", "form-INITIAL_FORMS": "0", "form-MAX_NUM_FORMS": "", "form-0-block": block.id, "form-0-activity": activity.id, "form-0-scheduled": False, "form-0-capacity": 5, "form-0-both_blocks": True, }, ) self.assertEqual(302, response.status_code) self.assertEqual( 1, EighthScheduledActivity.objects.filter(block=block, activity=activity, capacity=5, cancelled=True, both_blocks=True).count()) # but deleting should not response = self.client.post( reverse("eighth_admin_schedule_activity"), data={ "form-TOTAL_FORMS": "1", "form-INITIAL_FORMS": "0", "form-MAX_NUM_FORMS": "", "form-0-block": block.id, "form-0-activity": activity.id, "form-0-scheduled": False, "form-0-unschedule": True, "form-0-capacity": 5, "form-0-both_blocks": True, }, ) self.assertEqual(302, response.status_code) self.assertEqual( 1, EighthScheduledActivity.objects.filter(block=block, activity=activity, capacity=5, cancelled=True, both_blocks=True).count()) # Remove the signup signup.delete() # Try again, the scheduled activity should be deleted response = self.client.post( reverse("eighth_admin_schedule_activity"), data={ "form-TOTAL_FORMS": "1", "form-INITIAL_FORMS": "0", "form-MAX_NUM_FORMS": "", "form-0-block": block.id, "form-0-activity": activity.id, "form-0-scheduled": False, "form-0-unschedule": True, "form-0-capacity": 5, "form-0-both_blocks": True, }, ) self.assertEqual(302, response.status_code) self.assertEqual( 0, EighthScheduledActivity.objects.filter(block=block, activity=activity, capacity=5, cancelled=True, both_blocks=True).count())
def test_delinquent_students_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.attendance.delinquent_students_view`.""" self.make_admin() # First, load the page response = self.client.get( reverse("eighth_admin_view_delinquent_students")) self.assertEqual(200, response.status_code) # Test with empty set of students (absences) EighthSignup.objects.all().delete() response = self.client.get( reverse("eighth_admin_view_delinquent_students"), data={ "lower": 1, "upper": 100, "freshmen": "on", "sophomores": "on", "juniors": "on", "seniors": "on" }, ) self.assertEqual(200, response.status_code) self.assertEqual([], response.context["delinquents"]) # Add an absence user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student")[0] today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create( block=block, activity=activity, attendance_taken=True)[0] EighthSignup.objects.create(user=user, scheduled_activity=scheduled, was_absent=True) response = self.client.get( reverse("eighth_admin_view_delinquent_students"), data={ "lower": 1, "upper": 100, "freshmen": "on", "sophomores": "on", "juniors": "on", "seniors": "on" }, ) self.assertEqual(200, response.status_code) self.assertEqual([{ "user": user, "absences": 1 }], response.context["delinquents"]) # Exclude seniors response = self.client.get( reverse("eighth_admin_view_delinquent_students"), data={ "lower": 1, "upper": 100, "freshmen": "on", "sophomores": "on", "juniors": "on" }) self.assertEqual(200, response.status_code) self.assertEqual([], response.context["delinquents"]) # Test CSV output response = self.client.get( reverse("eighth_admin_download_delinquent_students_csv"), data={ "lower": 1, "upper": 100, "freshmen": "on", "sophomores": "on", "juniors": "on", "seniors": "on" }, ) self.assertEqual(200, response.status_code) reader = csv.DictReader(response.content.decode("UTF-8").split("\n")) reader_contents = list(reader) self.assertEqual(1, len(reader_contents)) self.assertEqual(reader_contents[0]["TJ Email"], "*****@*****.**") self.assertEqual(reader_contents[0]["Absences"], "1")
def test_migrate_outstanding_passes_view(self): """Tests :func:`~intranet.apps.eighth.views.admin.attendance.migrate_outstanding_passes_view`.""" self.make_admin() EighthSignup.objects.all().delete() EighthBlock.objects.all().delete() EighthActivity.objects.all().delete() # First, load the page response = self.client.get( reverse("eighth_admin_migrate_outstanding_passes")) self.assertEqual(200, response.status_code) self.assertEqual([], list(response.context["blocks"])) # Add a block, activity, and a late signup today = timezone.localtime().date() block = EighthBlock.objects.get_or_create(date=today, block_letter="A")[0] activity = EighthActivity.objects.get_or_create( name="Test Activity")[0] scheduled = EighthScheduledActivity.objects.get_or_create( block=block, activity=activity, attendance_taken=True)[0] user = get_user_model().objects.get_or_create( username="******", graduation_year=get_senior_graduation_year(), user_type="student", last_name="William")[0] signup = EighthSignup.objects.create(user=user, scheduled_activity=scheduled, after_deadline=True, pass_accepted=False) # Load the page response = self.client.get( reverse("eighth_admin_migrate_outstanding_passes")) self.assertEqual(200, response.status_code) self.assertEqual([block], list(response.context["blocks"])) # POST something invalid, it should 404 response = self.client.post( reverse("eighth_admin_migrate_outstanding_passes") ) # missing block number self.assertEqual(404, response.status_code) # Now POST the block ID with it and the signup should migrate response = self.client.post( reverse("eighth_admin_migrate_outstanding_passes"), data={"block": block.id}) self.assertEqual(302, response.status_code) self.assertEqual( 1, EighthActivity.objects.filter( name="Z - 8th Period Pass Not Received").count()) self.assertEqual( EighthScheduledActivity.objects.get( activity__name="Z - 8th Period Pass Not Received", block=block), EighthSignup.objects.get(id=signup.id).scheduled_activity, )