326 lines
15 KiB
Python
326 lines
15 KiB
Python
import os
|
|
import shutil
|
|
import datetime
|
|
import urlparse
|
|
|
|
from django.core.urlresolvers import reverse as urlreverse
|
|
from django.conf import settings
|
|
|
|
from pyquery import PyQuery
|
|
|
|
from ietf.doc.models import Document
|
|
from ietf.meeting.models import Session, TimeSlot
|
|
from ietf.meeting.test_data import make_meeting_test_data
|
|
from ietf.utils.test_utils import TestCase, login_testing_unauthorized
|
|
|
|
class MeetingTests(TestCase):
|
|
def setUp(self):
|
|
self.materials_dir = os.path.abspath(settings.TEST_MATERIALS_DIR)
|
|
if not os.path.exists(self.materials_dir):
|
|
os.mkdir(self.materials_dir)
|
|
settings.AGENDA_PATH = self.materials_dir
|
|
|
|
def tearDown(self):
|
|
shutil.rmtree(self.materials_dir)
|
|
|
|
def write_materials_file(self, meeting, doc, content):
|
|
path = os.path.join(self.materials_dir, "%s/%s/%s" % (meeting.number, doc.type_id, doc.external_url))
|
|
|
|
dirname = os.path.dirname(path)
|
|
if not os.path.exists(dirname):
|
|
os.makedirs(dirname)
|
|
|
|
with open(path, "w") as f:
|
|
f.write(content)
|
|
|
|
def write_materials_files(self, meeting, session):
|
|
|
|
draft = Document.objects.filter(type="draft", group=session.group).first()
|
|
|
|
self.write_materials_file(meeting, session.materials.get(type="agenda"),
|
|
"1. WG status (15 minutes)\n\n2. Status of %s\n\n" % draft.name)
|
|
|
|
self.write_materials_file(meeting, session.materials.get(type="minutes"),
|
|
"1. More work items underway\n\n2. The draft will be finished before next meeting\n\n")
|
|
|
|
self.write_materials_file(meeting, session.materials.filter(type="slides").exclude(states__type__slug='slides',states__slug='deleted').first(),
|
|
"This is a slideshow")
|
|
|
|
|
|
def test_agenda(self):
|
|
meeting = make_meeting_test_data()
|
|
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
|
|
slot = TimeSlot.objects.get(scheduledsession__session=session)
|
|
|
|
self.write_materials_files(meeting, session)
|
|
|
|
time_interval = "%s-%s" % (slot.time.strftime("%H:%M").lstrip("0"), (slot.time + slot.duration).strftime("%H:%M").lstrip("0"))
|
|
|
|
# plain
|
|
r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number)))
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
agenda_content = q("#content").html()
|
|
self.assertTrue(session.group.acronym in agenda_content)
|
|
self.assertTrue(session.group.name in agenda_content)
|
|
self.assertTrue(session.group.parent.acronym.upper() in agenda_content)
|
|
self.assertTrue(slot.location.name in agenda_content)
|
|
self.assertTrue(time_interval in agenda_content)
|
|
|
|
# Make sure there's a frame for the agenda and it points to the right place
|
|
self.assertTrue(any([session.materials.get(type='agenda').href() in x.attrib["data-src"] for x in q('tr div.modal-body div.frame')]))
|
|
|
|
# Make sure undeleted slides are present and deleted slides are not
|
|
self.assertTrue(any([session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().title in x.text for x in q('tr div.modal-body ul a')]))
|
|
self.assertFalse(any([session.materials.filter(type='slides',states__type__slug='slides',states__slug='deleted').first().title in x.text for x in q('tr div.modal-body ul a')]))
|
|
|
|
# text
|
|
# the rest of the results don't have as nicely formatted times
|
|
time_interval = time_interval.replace(":", "")
|
|
|
|
r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number, ext=".txt")))
|
|
self.assertEqual(r.status_code, 200)
|
|
agenda_content = r.content
|
|
self.assertTrue(session.group.acronym in agenda_content)
|
|
self.assertTrue(session.group.name in agenda_content)
|
|
self.assertTrue(session.group.parent.acronym.upper() in agenda_content)
|
|
self.assertTrue(slot.location.name in agenda_content)
|
|
|
|
self.assertTrue(time_interval in agenda_content)
|
|
|
|
# CSV
|
|
r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number, ext=".csv")))
|
|
self.assertEqual(r.status_code, 200)
|
|
agenda_content = r.content
|
|
self.assertTrue(session.group.acronym in agenda_content)
|
|
self.assertTrue(session.group.name in agenda_content)
|
|
self.assertTrue(session.group.parent.acronym.upper() in agenda_content)
|
|
self.assertTrue(slot.location.name in agenda_content)
|
|
|
|
self.assertTrue(session.materials.get(type='agenda').external_url in r.content)
|
|
self.assertTrue(session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().external_url in r.content)
|
|
self.assertFalse(session.materials.filter(type='slides',states__type__slug='slides',states__slug='deleted').first().external_url in r.content)
|
|
|
|
# iCal
|
|
r = self.client.get(urlreverse("ietf.meeting.views.ical_agenda", kwargs=dict(num=meeting.number))
|
|
+ "?" + session.group.parent.acronym.upper())
|
|
self.assertEqual(r.status_code, 200)
|
|
agenda_content = r.content
|
|
self.assertTrue(session.group.acronym in agenda_content)
|
|
self.assertTrue(session.group.name in agenda_content)
|
|
self.assertTrue(slot.location.name in agenda_content)
|
|
self.assertTrue("BEGIN:VTIMEZONE" in agenda_content)
|
|
self.assertTrue("END:VTIMEZONE" in agenda_content)
|
|
|
|
self.assertTrue(session.agenda().get_absolute_url() in r.content)
|
|
self.assertTrue(session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().get_absolute_url() in r.content)
|
|
# TODO - the ics view uses .all on a queryset in a view so it's showing the deleted slides.
|
|
#self.assertFalse(session.materials.filter(type='slides',states__type__slug='slides',states__slug='deleted').first().get_absolute_url() in r.content)
|
|
|
|
# week view
|
|
r = self.client.get(urlreverse("ietf.meeting.views.week_view", kwargs=dict(num=meeting.number)))
|
|
self.assertEqual(r.status_code, 200)
|
|
agenda_content = r.content
|
|
self.assertTrue(session.group.acronym in agenda_content)
|
|
self.assertTrue(slot.location.name in agenda_content)
|
|
|
|
def test_agenda_by_room(self):
|
|
meeting = make_meeting_test_data()
|
|
url = urlreverse("ietf.meeting.views.agenda_by_room",kwargs=dict(num=meeting.number))
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertTrue(all([x in r.content for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
|
|
|
|
def test_agenda_by_type(self):
|
|
meeting = make_meeting_test_data()
|
|
|
|
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number))
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertTrue(all([x in r.content for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
|
|
|
|
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='session'))
|
|
r = self.client.get(url)
|
|
self.assertTrue(all([x in r.content for x in ['mars','Test Room']]))
|
|
self.assertFalse(any([x in r.content for x in ['IESG Breakfast','Breakfast Room']]))
|
|
|
|
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='lead'))
|
|
r = self.client.get(url)
|
|
self.assertFalse(any([x in r.content for x in ['mars','Test Room']]))
|
|
self.assertTrue(all([x in r.content for x in ['IESG Breakfast','Breakfast Room']]))
|
|
|
|
def test_session_details(self):
|
|
meeting = make_meeting_test_data()
|
|
url = urlreverse("ietf.meeting.views.session_details", kwargs=dict(num=meeting.number, acronym="mars"))
|
|
r = self.client.get(url)
|
|
self.assertTrue(all([x in r.content for x in ('slides','agenda','minutes')]))
|
|
self.assertFalse('deleted' in r.content)
|
|
|
|
def test_materials(self):
|
|
meeting = make_meeting_test_data()
|
|
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
|
|
|
|
self.write_materials_files(meeting, session)
|
|
|
|
# session agenda
|
|
r = self.client.get(urlreverse("ietf.meeting.views.session_agenda",
|
|
kwargs=dict(num=meeting.number, session=session.group.acronym)))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue("1. WG status" in r.content)
|
|
|
|
# early materials page
|
|
r = self.client.get(urlreverse("ietf.meeting.views.current_materials"))
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertTrue(meeting.number in r["Location"])
|
|
|
|
r = self.client.get(urlreverse("ietf.meeting.views.materials", kwargs=dict(meeting_num=meeting.number)))
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
row = q('#content td:contains("%s")' % str(session.group.acronym)).closest("tr")
|
|
self.assertTrue(row.find('a:contains("Agenda")'))
|
|
self.assertTrue(row.find('a:contains("Minutes")'))
|
|
self.assertTrue(row.find('a:contains("Slideshow")'))
|
|
self.assertFalse(row.find("a:contains(\"Bad Slideshow\")"))
|
|
|
|
# FIXME: missing tests of .pdf/.tar generation (some code can
|
|
# probably be lifted from similar tests in iesg/tests.py)
|
|
|
|
def test_feed(self):
|
|
meeting = make_meeting_test_data()
|
|
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
|
|
|
|
r = self.client.get("/feed/wg-proceedings/")
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue("agenda" in r.content)
|
|
self.assertTrue(session.group.acronym in r.content)
|
|
|
|
class EditTests(TestCase):
|
|
def setUp(self):
|
|
# make sure we have the colors of the area
|
|
from ietf.group.colors import fg_group_colors, bg_group_colors
|
|
area_upper = "FARFUT"
|
|
fg_group_colors[area_upper] = "#333"
|
|
bg_group_colors[area_upper] = "#aaa"
|
|
|
|
def test_edit_agenda(self):
|
|
meeting = make_meeting_test_data()
|
|
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
r = self.client.get(urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number)))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue("load_scheduledsessions" in r.content)
|
|
|
|
def test_save_agenda_as_and_read_permissions(self):
|
|
meeting = make_meeting_test_data()
|
|
|
|
# try to get non-existing agenda
|
|
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
|
|
owner=meeting.agenda.owner_email(),
|
|
name="foo"))
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 404)
|
|
|
|
# save as new name (requires valid existing agenda)
|
|
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
|
|
owner=meeting.agenda.owner_email(),
|
|
name=meeting.agenda.name))
|
|
self.client.login(username="ad", password="ad+password")
|
|
r = self.client.post(url, {
|
|
'savename': "foo",
|
|
'saveas': "saveas",
|
|
})
|
|
self.assertEqual(r.status_code, 302)
|
|
# Verify that we actually got redirected to a new place.
|
|
self.assertNotEqual(urlparse.urlparse(r.url).path, url)
|
|
|
|
# get
|
|
schedule = meeting.get_schedule_by_name("foo")
|
|
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
|
|
owner=schedule.owner_email(),
|
|
name="foo"))
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
schedule.visible = True
|
|
schedule.public = False
|
|
schedule.save()
|
|
|
|
# get as anonymous doesn't work
|
|
self.client.logout()
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 403)
|
|
|
|
# public, now anonymous works
|
|
schedule.public = True
|
|
schedule.save()
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
# Secretariat can always see it
|
|
schedule.visible = False
|
|
schedule.public = False
|
|
schedule.save()
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
def test_save_agenda_broken_names(self):
|
|
meeting = make_meeting_test_data()
|
|
|
|
# save as new name (requires valid existing agenda)
|
|
url = urlreverse("ietf.meeting.views.edit_agenda", kwargs=dict(num=meeting.number,
|
|
owner=meeting.agenda.owner_email(),
|
|
name=meeting.agenda.name))
|
|
self.client.login(username="ad", password="ad+password")
|
|
r = self.client.post(url, {
|
|
'savename': "/no/this/should/not/work/it/is/too/long",
|
|
'saveas': "saveas",
|
|
})
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(urlparse.urlparse(r.url).path, url)
|
|
# TODO: Verify that an error message was in fact returned.
|
|
|
|
r = self.client.post(url, {
|
|
'savename': "/invalid/chars/",
|
|
'saveas': "saveas",
|
|
})
|
|
# TODO: Verify that an error message was in fact returned.
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(urlparse.urlparse(r.url).path, url)
|
|
|
|
# Non-ASCII alphanumeric characters
|
|
r = self.client.post(url, {
|
|
'savename': u"f\u00E9ling",
|
|
'saveas': "saveas",
|
|
})
|
|
# TODO: Verify that an error message was in fact returned.
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(urlparse.urlparse(r.url).path, url)
|
|
|
|
|
|
def test_edit_timeslots(self):
|
|
meeting = make_meeting_test_data()
|
|
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
r = self.client.get(urlreverse("ietf.meeting.views.edit_timeslots", kwargs=dict(num=meeting.number)))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue(meeting.room_set.all().first().name in r.content)
|
|
|
|
def test_slot_to_the_right(self):
|
|
meeting = make_meeting_test_data()
|
|
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
|
|
mars_scheduled = session.scheduledsession_set.get()
|
|
mars_slot = TimeSlot.objects.get(scheduledsession__session=session)
|
|
mars_ends = mars_slot.time + mars_slot.duration
|
|
|
|
session = Session.objects.filter(meeting=meeting, group__acronym="ames").first()
|
|
ames_slot_qs = TimeSlot.objects.filter(scheduledsession__session=session)
|
|
|
|
ames_slot_qs.update(time=mars_ends + datetime.timedelta(seconds=11 * 60))
|
|
self.assertTrue(not mars_slot.slot_to_the_right)
|
|
self.assertTrue(not mars_scheduled.slot_to_the_right)
|
|
|
|
ames_slot_qs.update(time=mars_ends + datetime.timedelta(seconds=10 * 60))
|
|
self.assertTrue(mars_slot.slot_to_the_right)
|
|
self.assertTrue(mars_scheduled.slot_to_the_right)
|