datatracker/ietf/meeting/tests_api.py
Henrik Levkowetz f2b883d2bb Merged in ^/trunk@17617.
- Legacy-Id: 17618
2020-04-14 17:11:51 +00:00

503 lines
21 KiB
Python

# Copyright The IETF Trust 2013-2020, All Rights Reserved
# -*- coding: utf-8 -*-
import datetime
from urllib.parse import urlsplit
from django.urls import reverse as urlreverse
import debug # pyflakes:ignore
from ietf.name.models import TimerangeName
from ietf.group.models import Group
from ietf.meeting.models import Schedule, TimeSlot, Session, SchedTimeSessAssignment, Meeting, Constraint
from ietf.meeting.test_data import make_meeting_test_data
from ietf.person.models import Person
from ietf.utils.test_utils import TestCase
from ietf.utils.mail import outbox
class ApiTests(TestCase):
def test_update_schedule(self):
meeting = make_meeting_test_data()
schedule = Schedule.objects.get(meeting__number=72,name="test-schedule")
mars_session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
ames_session = Session.objects.filter(meeting=meeting, group__acronym="ames").first()
mars_scheduled = SchedTimeSessAssignment.objects.get(session=mars_session,schedule__name='test-schedule')
mars_slot = mars_scheduled.timeslot
ames_scheduled = SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-schedule')
ames_slot = ames_scheduled.timeslot
def do_unschedule(assignment):
url = urlreverse("ietf.meeting.ajax.assignment_json",
kwargs=dict(num=assignment.session.meeting.number,
owner=assignment.schedule.owner_email(),
name=assignment.schedule.name,
assignment_id=assignment.pk,))
return self.client.delete(url)
def do_schedule(schedule,session,timeslot):
url = urlreverse("ietf.meeting.ajax.assignments_json",
kwargs=dict(num=session.meeting.number,
owner=schedule.owner_email(),
name=schedule.name,))
post_data = '{ "session_id": "%s", "timeslot_id": "%s" }'%(session.pk,timeslot.pk)
return self.client.post(url,post_data,content_type='application/x-www-form-urlencoded')
def do_extend(schedule, assignment):
session = assignment.session
url = urlreverse("ietf.meeting.ajax.assignments_json",
kwargs=dict(num=session.meeting.number,
owner=schedule.owner_email(),
name=schedule.name,))
post_data = '{ "session_id": "%s", "timeslot_id": "%s", "extendedfrom_id": "%s" }'%(session.pk,assignment.timeslot.slot_to_the_right.pk,assignment.pk)
return self.client.post(url,post_data,content_type='application/x-www-form-urlencoded')
# not logged in
# faulty delete
r = do_unschedule(mars_scheduled)
self.assertEqual(r.status_code, 403)
self.assertEqual(SchedTimeSessAssignment.objects.get(pk=mars_scheduled.pk).session, mars_session)
# faulty post
r = do_schedule(schedule,ames_session,mars_slot)
self.assertEqual(r.status_code, 403)
# logged in as non-owner
# faulty delete
self.client.login(username="ad", password="ad+password")
r = do_unschedule(mars_scheduled)
self.assertEqual(r.status_code, 403)
self.assertTrue("error" in r.json())
# faulty post
r = do_schedule(schedule,ames_session,mars_slot)
self.assertEqual(r.status_code, 403)
# Put ames in the same timeslot as mars
self.client.login(username="plain", password='plain+password')
r = do_unschedule(ames_scheduled)
self.assertEqual(r.status_code, 200)
self.assertNotIn("error", r.json())
r = do_schedule(schedule,ames_session,mars_slot)
self.assertEqual(r.status_code, 201)
# Move the two timeslots close enough together for extension to work
ames_slot_qs=TimeSlot.objects.filter(id=ames_slot.id)
ames_slot_qs.update(time=mars_slot.time+mars_slot.duration+datetime.timedelta(minutes=10))
# Extend the mars session
r = do_extend(schedule,mars_scheduled)
self.assertEqual(r.status_code, 201)
self.assertTrue("error" not in r.json())
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-schedule').count(),2)
# Unschedule mars
r = do_unschedule(mars_scheduled)
self.assertEqual(r.status_code, 200)
self.assertNotIn("error", r.json())
# Make sure it got both the original and extended session
self.assertEqual(mars_session.timeslotassignments.filter(schedule__name='test-schedule').count(),0)
self.assertEqual(SchedTimeSessAssignment.objects.get(session=ames_session,schedule__name='test-schedule').timeslot, mars_slot)
def test_constraints_json(self):
meeting = make_meeting_test_data()
session = Session.objects.filter(meeting=meeting, group__acronym="mars").select_related("group").first()
c_ames = Constraint.objects.create(meeting=meeting, source=session.group,
target=Group.objects.get(acronym="ames"),
name_id="conflict")
c_person = Constraint.objects.create(meeting=meeting, source=session.group,
person=Person.objects.get(user__username="ad"),
name_id="bethere")
c_adjacent = Constraint.objects.create(meeting=meeting, source=session.group,
target=Group.objects.get(acronym="irg"),
name_id="wg_adjacent")
c_time_relation = Constraint.objects.create(meeting=meeting, source=session.group,
time_relation='subsequent-days',
name_id="time_relation")
c_timerange = Constraint.objects.create(meeting=meeting, source=session.group,
name_id="timerange")
c_timerange.timeranges.set(TimerangeName.objects.filter(slug__startswith='monday'))
r = self.client.get(urlreverse("ietf.meeting.ajax.session_constraints", kwargs=dict(num=meeting.number, sessionid=session.pk)))
self.assertEqual(r.status_code, 200)
constraints = r.json()
expected_keys = set([c_ames.pk, c_person.pk, c_adjacent.pk, c_time_relation.pk, c_timerange.pk])
self.assertEqual(expected_keys, set(c["constraint_id"] for c in constraints))
def test_meeting_json(self):
meeting = make_meeting_test_data()
r = self.client.get(urlreverse("ietf.meeting.ajax.meeting_json", kwargs=dict(num=meeting.number)))
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info["name"], meeting.number)
def test_get_room_json(self):
meeting = make_meeting_test_data()
room = meeting.room_set.first()
r = self.client.get(urlreverse("ietf.meeting.ajax.timeslot_roomurl", kwargs=dict(num=meeting.number, roomid=room.pk)))
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info["name"], room.name)
def test_create_new_room(self):
meeting = make_meeting_test_data()
timeslots_before = meeting.timeslot_set.filter(type='regular').count()
url = urlreverse("ietf.meeting.ajax.timeslot_roomsurl", kwargs=dict(num=meeting.number))
post_data = { "name": "new room", "capacity": "50" , "resources": [], "session_types":['regular']}
# unauthorized post
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 302)
self.assertTrue(not meeting.room_set.filter(name="new room"))
# create room
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 302)
self.assertTrue(meeting.room_set.filter(name="new room"))
timeslots_after = meeting.timeslot_set.filter(type='regular').count()
# It's not clear that what that ajax function is doing is the right thing to do,
# but it currently makes a new timeslot for any existing timeslot.
# The condition tested below relies on the timeslots before this test all having different start and end times
self.assertEqual( timeslots_after, 2 * timeslots_before)
def test_delete_room(self):
meeting = make_meeting_test_data()
room = meeting.room_set.first()
timeslots_before = list(room.timeslot_set.values_list("pk", flat=True))
url = urlreverse("ietf.meeting.ajax.timeslot_roomurl", kwargs=dict(num=meeting.number, roomid=room.pk))
# unauthorized delete
r = self.client.delete(url)
self.assertEqual(r.status_code, 302)
self.assertTrue(meeting.room_set.filter(pk=room.pk))
# delete
self.client.login(username="secretary", password="secretary+password")
r = self.client.delete(url)
self.assertTrue(not meeting.room_set.filter(pk=room.pk))
self.assertTrue(not TimeSlot.objects.filter(pk__in=timeslots_before))
# This really belongs in group tests
def test_group_json(self):
make_meeting_test_data()
group = Group.objects.get(acronym="mars")
url = urlreverse("ietf.group.views.group_json", kwargs=dict(acronym=group.acronym))
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info["name"], group.name)
# This really belongs in person tests
def test_person_json(self):
make_meeting_test_data()
person = Person.objects.get(user__username="ad")
url = urlreverse("ietf.person.ajax.person_json", kwargs=dict(personid=person.pk))
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info["name"], person.name)
def test_sessions_json(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.ajax.sessions_json",kwargs=dict(num=meeting.number))
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(set([x['short_name'] for x in info]),set([s.session.short_name for s in meeting.schedule.assignments.filter(session__type_id='regular')]))
schedule = meeting.schedule
url = urlreverse("ietf.meeting.ajax.assignments_json",
kwargs=dict(num=meeting.number,owner=schedule.owner_email(),name=schedule.name))
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(len(info),schedule.assignments.count())
def test_slot_json(self):
meeting = make_meeting_test_data()
slot = meeting.timeslot_set.all()[0]
url = urlreverse("ietf.meeting.ajax.timeslot_sloturl",
kwargs=dict(num=meeting.number, slotid=slot.pk))
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info["timeslot_id"], slot.pk)
def test_create_new_slot(self):
meeting = make_meeting_test_data()
slot_time = datetime.date.today()
url = urlreverse("ietf.meeting.ajax.timeslot_slotsurl",
kwargs=dict(num=meeting.number))
post_data = {
'type' : 'plenary',
'time' : slot_time.strftime("%Y-%m-%d"),
'duration': '08:00:00',
}
# unauthorized post
prior_slotcount = meeting.timeslot_set.count()
self.client.login(username="ad", password="ad+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 403)
self.assertEqual(meeting.timeslot_set.count(),prior_slotcount)
# create slot
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 201)
self.assertTrue(meeting.timeslot_set.filter(time=slot_time))
self.assertEqual(meeting.timeslot_set.count(),prior_slotcount+1)
def test_delete_slot(self):
meeting = make_meeting_test_data()
slot = meeting.timeslot_set.all()[0]
url = urlreverse("ietf.meeting.ajax.timeslot_sloturl",
kwargs=dict(num=meeting.number, slotid=slot.pk))
# unauthorized delete
self.client.login(username="ad", password="ad+password")
r = self.client.delete(url)
self.assertEqual(r.status_code, 403)
# delete
self.client.login(username="secretary", password="secretary+password")
self.client.delete(url)
self.assertTrue(not meeting.timeslot_set.filter(pk=slot.pk))
def test_schedule_json(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.ajax.schedule_infourl",
kwargs=dict(num=meeting.number,
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
r = self.client.get(url)
info = r.json()
self.assertEqual(info["schedule_id"], meeting.schedule.pk)
def test_create_new_schedule(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.ajax.schedule_infosurl",
kwargs=dict(num=meeting.number))
post_data = {
'name': 'new-schedule',
}
# unauthorized post
self.client.login(username="plain", password="plain+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 403)
self.assertTrue(not meeting.schedule_set.filter(name='new-schedule'))
# create new schedule
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 302)
self.assertTrue(meeting.schedule_set.filter(name='new-schedule'))
def test_update_meeting_schedule(self):
meeting = make_meeting_test_data()
self.assertTrue(meeting.schedule.visible)
url = urlreverse("ietf.meeting.ajax.schedule_infourl",
kwargs=dict(num=meeting.number,
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
post_data = {
'visible': 'false',
'name': 'new-test-name',
}
# unauthorized posts
self.client.logout()
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 403)
self.client.login(username="ad", password="ad+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 403)
# change schedule
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 302)
changed_schedule = Schedule.objects.get(pk=meeting.schedule.pk)
self.assertTrue(not changed_schedule.visible)
self.assertEqual(changed_schedule.name, "new-test-name")
def test_delete_schedule(self):
meeting = make_meeting_test_data()
url = urlreverse("ietf.meeting.ajax.schedule_infourl",
kwargs=dict(num=meeting.number,
owner=meeting.schedule.owner_email(),
name=meeting.schedule.name))
# unauthorized delete
self.client.login(username="plain", password="plain+password")
r = self.client.delete(url)
self.assertEqual(r.status_code, 403)
# delete
self.client.login(username="secretary", password="secretary+password")
r = self.client.delete(url)
self.assertEqual(r.status_code, 200)
self.assertTrue(not Schedule.objects.filter(pk=meeting.schedule.pk))
def test_set_meeting_schedule(self):
meeting = make_meeting_test_data()
schedule = meeting.schedule
url = urlreverse("ietf.meeting.ajax.meeting_json",
kwargs=dict(num=meeting.number))
post_data = {
"schedule": "",
}
# unauthorized post
self.client.login(username="ad", password="ad+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 403)
# clear
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 200)
self.assertTrue(not Meeting.objects.get(pk=meeting.pk).schedule)
# set schedule - first fail with non-public
post_data = {
"schedule": schedule.name,
}
schedule.public = False
schedule.save()
r = self.client.post(url, post_data)
self.assertTrue(r.status_code != 200)
self.assertTrue(not Meeting.objects.get(pk=meeting.pk).schedule)
# then go through with public
schedule.public = True
schedule.save()
# Setting a meeting as official no longer sends mail immediately
prior_length= len(outbox)
r = self.client.post(url, post_data)
self.assertEqual(r.status_code, 200)
self.assertEqual(Meeting.objects.get(pk=meeting.pk).schedule, schedule)
self.assertEqual(len(outbox),prior_length)
def test_read_only(self):
meeting = make_meeting_test_data()
# Secretariat
self.client.login(username="secretary", password="secretary+password")
url = '/meeting/%s/agenda/%s/%s/permissions' % (meeting.number, meeting.schedule.owner.email_address(), meeting.schedule.name);
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info['secretariat'], True)
self.assertEqual(urlsplit(info['owner_href'])[2], "/person/%s.json" % meeting.schedule.owner_id)
self.assertEqual(info['read_only'], True)
self.assertEqual(info['save_perm'], True)
# owner
self.client.login(username=meeting.schedule.owner.user.username,
password=meeting.schedule.owner.user.username+"+password")
url = '/meeting/%s/agenda/%s/%s/permissions' % (meeting.number, meeting.schedule.owner.email_address(), meeting.schedule.name);
r = self.client.get(url)
self.assertEqual(r.status_code, 200)
info = r.json()
self.assertEqual(info['secretariat'], False)
self.assertEqual(info['read_only'], False)
self.assertEqual(info['save_perm'], False)
def test_update_timeslot_pinned(self):
meeting = make_meeting_test_data()
scheduled = SchedTimeSessAssignment.objects.filter(
session__meeting=meeting, session__group__acronym="mars").first()
url = '/meeting/%s/agenda/%s/%s/session/%u.json' % (meeting.number, meeting.schedule.owner_email(), meeting.schedule.name, scheduled.pk)
post_data = {
"pinned": True
}
# unauthorized post gets failure (no redirect)
r = self.client.put(url, post_data)
self.assertEqual(r.status_code, 403,
"post to %s should have failed, no permission, got: %u/%s" %
(url, r.status_code, r.content))
self.assertTrue(not SchedTimeSessAssignment.objects.get(pk=scheduled.pk).pinned)
# set pinned
meeting.schedule.owner = Person.objects.get(user__username="secretary")
meeting.schedule.save()
# need to rebuild URL, since the schedule owner has changed.
url = '/meeting/%s/agenda/%s/%s/session/%u.json' % (meeting.number, meeting.schedule.owner_email(), meeting.schedule.name, scheduled.pk)
self.client.login(username="secretary", password="secretary+password")
r = self.client.put(url, post_data)
self.assertEqual(r.status_code, 200,
"post to %s should have worked, but got: %u/%s" %
(url, r.status_code, r.content))
self.assertTrue(SchedTimeSessAssignment.objects.get(pk=scheduled.pk).pinned)
class TimeSlotEditingApiTests(TestCase):
def test_manipulate_timeslot(self):
meeting = make_meeting_test_data()
slot = meeting.timeslot_set.all()[0]
self.assertEqual(TimeSlot.objects.get(pk=slot.pk).type_id,'regular')
url = urlreverse("ietf.meeting.ajax.timeslot_sloturl",
kwargs=dict(num=meeting.number, slotid=slot.pk))
modify_post_data = {
"purpose" : "plenary"
}
# Fail as non-secretariat
self.client.login(username="plain", password="plain+password")
r = self.client.post(url, modify_post_data)
self.assertEqual(r.status_code, 403)
slot.refresh_from_db()
self.assertEqual(slot.type_id, 'regular')
# Successful change of purpose
self.client.login(username="secretary", password="secretary+password")
r = self.client.post(url, modify_post_data)
self.assertEqual(r.status_code, 200)
slot.refresh_from_db()
self.assertEqual(slot.type_id, 'plenary')