1697 lines
85 KiB
Python
1697 lines
85 KiB
Python
import json
|
|
import os
|
|
import shutil
|
|
import datetime
|
|
import urlparse
|
|
import random
|
|
|
|
import debug # pyflakes:ignore
|
|
|
|
from django.urls import reverse as urlreverse
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import User
|
|
|
|
from mock import patch
|
|
from pyquery import PyQuery
|
|
from StringIO import StringIO
|
|
|
|
from ietf.doc.models import Document
|
|
from ietf.group.models import Group, Role
|
|
from ietf.meeting.helpers import can_approve_interim_request, can_view_interim_request
|
|
from ietf.meeting.helpers import send_interim_approval_request
|
|
from ietf.meeting.helpers import send_interim_cancellation_notice
|
|
from ietf.meeting.helpers import send_interim_minutes_reminder
|
|
from ietf.meeting.models import Session, TimeSlot, Meeting
|
|
from ietf.meeting.test_data import make_meeting_test_data, make_interim_meeting
|
|
from ietf.meeting.utils import finalize
|
|
from ietf.name.models import SessionStatusName
|
|
from ietf.utils.test_utils import TestCase, login_testing_unauthorized, unicontent
|
|
from ietf.utils.mail import outbox
|
|
from ietf.utils.text import xslugify
|
|
|
|
from ietf.person.factories import PersonFactory
|
|
from ietf.group.factories import GroupFactory, GroupEventFactory
|
|
from ietf.meeting.factories import ( SessionFactory, SessionPresentationFactory, ScheduleFactory,
|
|
MeetingFactory, FloorPlanFactory )
|
|
from ietf.doc.factories import DocumentFactory
|
|
|
|
|
|
class MeetingTests(TestCase):
|
|
def setUp(self):
|
|
self.materials_dir = self.tempdir('materials')
|
|
self.saved_agenda_path = settings.AGENDA_PATH
|
|
settings.AGENDA_PATH = self.materials_dir
|
|
|
|
def tearDown(self):
|
|
settings.AGENDA_PATH = self.saved_agenda_path
|
|
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(sessionassignments__session=session,sessionassignments__schedule=meeting.agenda)
|
|
|
|
self.write_materials_files(meeting, session)
|
|
|
|
# utc
|
|
time_interval = "%s-%s" % (slot.utc_start_time().strftime("%H:%M").lstrip("0"), (slot.utc_start_time() + slot.duration).strftime("%H:%M").lstrip("0"))
|
|
|
|
r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number,utc='-utc')))
|
|
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)
|
|
|
|
# plain
|
|
time_interval = "%s-%s" % (slot.time.strftime("%H:%M").lstrip("0"), (slot.time + slot.duration).strftime("%H:%M").lstrip("0"))
|
|
|
|
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)
|
|
|
|
r = self.client.get(urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email())))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue('not the official schedule' in unicontent(r))
|
|
|
|
# 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 unicontent(r))
|
|
self.assertTrue(session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().external_url in unicontent(r))
|
|
self.assertFalse(session.materials.filter(type='slides',states__type__slug='slides',states__slug='deleted').first().external_url in unicontent(r))
|
|
|
|
# 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 unicontent(r))
|
|
self.assertTrue(session.materials.filter(type='slides').exclude(states__type__slug='slides',states__slug='deleted').first().get_absolute_url() in unicontent(r))
|
|
# 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 unicontent(r))
|
|
|
|
# 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_current_audio(self):
|
|
date = datetime.date.today()
|
|
meeting = MeetingFactory(type_id='ietf', date=date )
|
|
make_meeting_test_data(meeting=meeting)
|
|
url = urlreverse("ietf.meeting.views.agenda", kwargs=dict(num=meeting.number))
|
|
r = self.client.get(url)
|
|
self.assertTrue("Audio stream" in unicontent(r))
|
|
|
|
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 unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
|
|
|
|
url = urlreverse("ietf.meeting.views.agenda_by_room",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
|
|
r = self.client.get(url)
|
|
self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room',]]))
|
|
self.assertFalse('IESG Breakfast' in unicontent(r))
|
|
|
|
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 unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
|
|
|
|
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
|
|
r = self.client.get(url)
|
|
self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room',]]))
|
|
self.assertFalse('IESG Breakfast' in unicontent(r))
|
|
|
|
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 unicontent(r) for x in ['mars','Test Room']]))
|
|
self.assertFalse(any([x in unicontent(r) 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 unicontent(r) for x in ['mars','Test Room']]))
|
|
self.assertTrue(all([x in unicontent(r) for x in ['IESG Breakfast','Breakfast Room']]))
|
|
|
|
url = urlreverse("ietf.meeting.views.agenda_by_type",kwargs=dict(num=meeting.number,type='lead',name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
|
|
r = self.client.get(url)
|
|
self.assertFalse(any([x in unicontent(r) for x in ['IESG Breakfast','Breakfast Room']]))
|
|
|
|
def test_agenda_room_view(self):
|
|
meeting = make_meeting_test_data()
|
|
url = urlreverse("ietf.meeting.views.room_view",kwargs=dict(num=meeting.number))
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code,200)
|
|
self.assertTrue(all([x in unicontent(r) for x in ['mars','IESG Breakfast','Test Room','Breakfast Room']]))
|
|
url = urlreverse("ietf.meeting.views.room_view",kwargs=dict(num=meeting.number,name=meeting.unofficial_schedule.name,owner=meeting.unofficial_schedule.owner.email()))
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code,200)
|
|
self.assertTrue(all([x in unicontent(r) for x in ['mars','Test Room','Breakfast Room']]))
|
|
self.assertFalse('IESG Breakfast' in unicontent(r))
|
|
|
|
|
|
def test_agenda_week_view(self):
|
|
meeting = make_meeting_test_data()
|
|
url = urlreverse("ietf.meeting.views.week_view",kwargs=dict(num=meeting.number)) + "#farfut"
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code,200)
|
|
self.assertTrue(all([x in unicontent(r) for x in ['var all_items', 'maximize', 'draw_calendar', ]]))
|
|
|
|
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 unicontent(r))
|
|
|
|
# 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"])
|
|
|
|
# session minutes
|
|
r = self.client.get(urlreverse("ietf.meeting.views.session_minutes",
|
|
kwargs=dict(num=meeting.number, session=session.group.acronym)))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue("1. More work items underway" in unicontent(r))
|
|
|
|
# test with explicit meeting number in url
|
|
r = self.client.get(urlreverse("ietf.meeting.views.materials", kwargs=dict(num=meeting.number)))
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
row = q('#content #%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\")"))
|
|
|
|
# test with no meeting number in url
|
|
r = self.client.get(urlreverse("ietf.meeting.views.materials", kwargs=dict()))
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
row = q('#content #%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\")"))
|
|
|
|
# test with a loggged-in wg chair
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
r = self.client.get(urlreverse("ietf.meeting.views.materials", kwargs=dict(num=meeting.number)))
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
row = q('#content td div: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\")"))
|
|
self.assertTrue(row.find('a:contains("Edit materials")'))
|
|
# FIXME: missing tests of .pdf/.tar generation (some code can
|
|
# probably be lifted from similar tests in iesg/tests.py)
|
|
|
|
def test_materials_editable_groups(self):
|
|
meeting = make_meeting_test_data()
|
|
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
r = self.client.get(urlreverse("ietf.meeting.views.materials_editable_groups", kwargs={'num':meeting.number}))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue(meeting.number in unicontent(r))
|
|
self.assertTrue("mars" in unicontent(r))
|
|
self.assertFalse("No session requested" in unicontent(r))
|
|
|
|
self.client.login(username="ad", password="ad+password")
|
|
r = self.client.get(urlreverse("ietf.meeting.views.materials_editable_groups", kwargs={'num':meeting.number}))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue(meeting.number in unicontent(r))
|
|
self.assertTrue("frfarea" in unicontent(r))
|
|
self.assertTrue("No session requested" in unicontent(r))
|
|
|
|
self.client.login(username="plain",password="plain+password")
|
|
r = self.client.get(urlreverse("ietf.meeting.views.materials_editable_groups", kwargs={'num':meeting.number}))
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue(meeting.number in unicontent(r))
|
|
self.assertTrue("You cannot manage the meeting materials for any groups" in unicontent(r))
|
|
|
|
def test_proceedings(self):
|
|
meeting = make_meeting_test_data()
|
|
session = Session.objects.filter(meeting=meeting, group__acronym="mars").first()
|
|
GroupEventFactory(group=session.group,type='status_update')
|
|
SessionPresentationFactory(document__type_id='recording',session=session)
|
|
SessionPresentationFactory(document__type_id='recording',session=session,document__title="Audio recording for tests")
|
|
|
|
self.write_materials_files(meeting, session)
|
|
|
|
url = urlreverse("ietf.meeting.views.proceedings", kwargs=dict(num=meeting.number))
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
def test_proceedings_acknowledgements(self):
|
|
make_meeting_test_data()
|
|
meeting = MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
|
meeting.acknowledgements = 'test acknowledgements'
|
|
meeting.save()
|
|
url = urlreverse('ietf.meeting.views.proceedings_acknowledgements',kwargs={'num':meeting.number})
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue('test acknowledgements' in response.content)
|
|
|
|
@patch('urllib2.urlopen')
|
|
def test_proceedings_attendees(self, mock_urlopen):
|
|
mock_urlopen.return_value = StringIO('[{"LastName":"Smith","FirstName":"John","Company":"ABC","Country":"US"}]')
|
|
make_meeting_test_data()
|
|
meeting = MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
|
finalize(meeting)
|
|
url = urlreverse('ietf.meeting.views.proceedings_attendees',kwargs={'num':96})
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue('Attendee List' in response.content)
|
|
q = PyQuery(response.content)
|
|
self.assertEqual(1,len(q("#id_attendees tbody tr")))
|
|
|
|
def test_proceedings_overview(self):
|
|
'''Test proceedings IETF Overview page.
|
|
Note: old meetings aren't supported so need to add a new meeting then test.
|
|
'''
|
|
make_meeting_test_data()
|
|
meeting = MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
|
finalize(meeting)
|
|
url = urlreverse('ietf.meeting.views.proceedings_overview',kwargs={'num':96})
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue('The Internet Engineering Task Force' in response.content)
|
|
|
|
def test_proceedings_progress_report(self):
|
|
make_meeting_test_data()
|
|
MeetingFactory(type_id='ietf', date=datetime.date(2016,4,3), number="95")
|
|
MeetingFactory(type_id='ietf', date=datetime.date(2016,7,14), number="96")
|
|
|
|
url = urlreverse('ietf.meeting.views.proceedings_progress_report',kwargs={'num':96})
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertTrue('Progress Report' in response.content)
|
|
|
|
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 unicontent(r))
|
|
self.assertTrue(session.group.acronym in unicontent(r))
|
|
|
|
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_assignments" in unicontent(r))
|
|
|
|
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 unicontent(r))
|
|
|
|
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.timeslotassignments.get(schedule__name='test-agenda')
|
|
mars_slot = TimeSlot.objects.get(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda')
|
|
mars_ends = mars_slot.time + mars_slot.duration
|
|
|
|
session = Session.objects.filter(meeting=meeting, group__acronym="ames").first()
|
|
ames_slot_qs = TimeSlot.objects.filter(sessionassignments__session=session,sessionassignments__schedule__name='test-agenda')
|
|
|
|
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)
|
|
|
|
class SessionDetailsTests(TestCase):
|
|
|
|
def test_session_details(self):
|
|
|
|
group = GroupFactory.create(type_id='wg',state_id='active')
|
|
session = SessionFactory.create(meeting__type_id='ietf',group=group, meeting__date=datetime.date.today()+datetime.timedelta(days=90))
|
|
SessionPresentationFactory.create(session=session,document__type_id='draft',rev=None)
|
|
SessionPresentationFactory.create(session=session,document__type_id='minutes')
|
|
SessionPresentationFactory.create(session=session,document__type_id='slides')
|
|
SessionPresentationFactory.create(session=session,document__type_id='agenda')
|
|
|
|
url = urlreverse('ietf.meeting.views.session_details', kwargs=dict(num=session.meeting.number, acronym=group.acronym))
|
|
r = self.client.get(url)
|
|
self.assertTrue(all([x in unicontent(r) for x in ('slides','agenda','minutes','draft')]))
|
|
self.assertFalse('deleted' in unicontent(r))
|
|
|
|
def test_add_session_drafts(self):
|
|
group = GroupFactory.create(type_id='wg',state_id='active')
|
|
group_chair = PersonFactory.create()
|
|
group.role_set.create(name_id='chair',person = group_chair, email = group_chair.email())
|
|
session = SessionFactory.create(meeting__type_id='ietf',group=group, meeting__date=datetime.date.today()+datetime.timedelta(days=90))
|
|
SessionPresentationFactory.create(session=session,document__type_id='draft',rev=None)
|
|
old_draft = session.sessionpresentation_set.filter(document__type='draft').first().document
|
|
new_draft = DocumentFactory(type_id='draft')
|
|
|
|
url = urlreverse('ietf.meeting.views.add_session_drafts', kwargs=dict(num=session.meeting.number, session_id=session.pk))
|
|
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 404)
|
|
|
|
self.client.login(username="plain",password="plain+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 404)
|
|
|
|
self.client.login(username=group_chair.user.username, password='%s+password'%group_chair.user.username)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue(old_draft.name in unicontent(r))
|
|
|
|
r = self.client.post(url,dict(drafts=[new_draft.name,old_draft.name]))
|
|
self.assertTrue(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue("Already linked:" in q('form .alert-danger').text())
|
|
|
|
self.assertEqual(1,session.sessionpresentation_set.count())
|
|
r = self.client.post(url,dict(drafts=[new_draft.name,]))
|
|
self.assertTrue(r.status_code, 302)
|
|
self.assertEqual(2,session.sessionpresentation_set.count())
|
|
|
|
session.meeting.date -= datetime.timedelta(days=180)
|
|
session.meeting.save()
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code,404)
|
|
self.client.login(username='secretary',password='secretary+password')
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code,200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(1,len(q(".alert-warning:contains('may affect published proceedings')")))
|
|
|
|
class EditScheduleListTests(TestCase):
|
|
def setUp(self):
|
|
self.mtg = MeetingFactory(type_id='ietf')
|
|
ScheduleFactory(meeting=self.mtg,name='Empty-Schedule')
|
|
|
|
def test_list_agendas(self):
|
|
url = urlreverse('ietf.meeting.views.list_agendas',kwargs={'num':self.mtg.number})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertTrue(r.status_code, 200)
|
|
|
|
def test_delete_schedule(self):
|
|
url = urlreverse('ietf.meeting.views.delete_schedule',
|
|
kwargs={'num':self.mtg.number,
|
|
'owner':self.mtg.agenda.owner.email_address(),
|
|
'name':self.mtg.agenda.name,
|
|
})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertTrue(r.status_code, 403)
|
|
r = self.client.post(url,{'save':1})
|
|
self.assertTrue(r.status_code, 403)
|
|
self.assertEqual(self.mtg.schedule_set.count(),2)
|
|
self.mtg.agenda=None
|
|
self.mtg.save()
|
|
r = self.client.get(url)
|
|
self.assertTrue(r.status_code, 200)
|
|
r = self.client.post(url,{'save':1})
|
|
self.assertTrue(r.status_code, 302)
|
|
self.assertEqual(self.mtg.schedule_set.count(),1)
|
|
|
|
def test_make_schedule_official(self):
|
|
schedule = self.mtg.schedule_set.exclude(id=self.mtg.agenda.id).first()
|
|
url = urlreverse('ietf.meeting.views.make_schedule_official',
|
|
kwargs={'num':self.mtg.number,
|
|
'owner':schedule.owner.email_address(),
|
|
'name':schedule.name,
|
|
})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertTrue(r.status_code, 200)
|
|
r = self.client.post(url,{'save':1})
|
|
self.assertTrue(r.status_code, 302)
|
|
mtg = Meeting.objects.get(number=self.mtg.number)
|
|
self.assertEqual(mtg.agenda,schedule)
|
|
|
|
# -------------------------------------------------
|
|
# Interim Meeting Tests
|
|
# -------------------------------------------------
|
|
|
|
class InterimTests(TestCase):
|
|
def setUp(self):
|
|
self.materials_dir = self.tempdir('materials')
|
|
self.saved_agenda_path = settings.AGENDA_PATH
|
|
settings.AGENDA_PATH = self.materials_dir
|
|
|
|
def tearDown(self):
|
|
settings.AGENDA_PATH = self.saved_agenda_path
|
|
shutil.rmtree(self.materials_dir)
|
|
|
|
def check_interim_tabs(self, url):
|
|
'''Helper function to check interim meeting list tabs'''
|
|
# no logged in - no tabs
|
|
r = self.client.get(url)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("ul.nav-tabs")), 0)
|
|
# plain user - no tabs
|
|
username = "plain"
|
|
self.client.login(username=username, password=username + "+password")
|
|
r = self.client.get(url)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("ul.nav-tabs")), 0)
|
|
self.client.logout()
|
|
# privileged user
|
|
username = "ad"
|
|
self.client.login(username=username, password=username + "+password")
|
|
r = self.client.get(url)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("a:contains('Pending')")), 1)
|
|
self.assertEqual(len(q("a:contains('Announce')")), 0)
|
|
self.client.logout()
|
|
# secretariat
|
|
username = "secretary"
|
|
self.client.login(username=username, password=username + "+password")
|
|
r = self.client.get(url)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("a:contains('Pending')")), 1)
|
|
self.assertEqual(len(q("a:contains('Announce')")), 1)
|
|
self.client.logout()
|
|
|
|
def test_interim_announce(self):
|
|
make_meeting_test_data()
|
|
url = urlreverse("ietf.meeting.views.interim_announce")
|
|
meeting = Meeting.objects.filter(type='interim', session__group__acronym='mars').first()
|
|
session = meeting.session_set.first()
|
|
session.status = SessionStatusName.objects.get(slug='scheda')
|
|
session.save()
|
|
login_testing_unauthorized(self, "secretary", url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue(meeting.number in r.content)
|
|
|
|
def test_interim_skip_announcement(self):
|
|
make_meeting_test_data()
|
|
group = Group.objects.get(acronym='irg')
|
|
date = datetime.date.today() + datetime.timedelta(days=30)
|
|
meeting = make_interim_meeting(group=group, date=date, status='scheda')
|
|
url = urlreverse("ietf.meeting.views.interim_skip_announcement", kwargs={'number': meeting.number})
|
|
login_testing_unauthorized(self, "secretary", url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
# check post
|
|
len_before = len(outbox)
|
|
r = self.client.post(url)
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.interim_announce'))
|
|
self.assertEqual(meeting.session_set.first().status.slug,'sched')
|
|
self.assertEqual(len(outbox), len_before)
|
|
|
|
def test_interim_send_announcement(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim', session__status='apprw', session__group__acronym='mars').first()
|
|
url = urlreverse("ietf.meeting.views.interim_send_announcement", kwargs={'number': meeting.number})
|
|
login_testing_unauthorized(self, "secretary", url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
initial = r.context['form'].initial
|
|
# send announcement
|
|
len_before = len(outbox)
|
|
r = self.client.post(url, initial)
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.interim_announce'))
|
|
self.assertEqual(len(outbox), len_before + 1)
|
|
self.assertTrue('WG Virtual Meeting' in outbox[-1]['Subject'])
|
|
|
|
def test_interim_approve_by_ad(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim', session__status='apprw', session__group__acronym='mars').first()
|
|
url = urlreverse('ietf.meeting.views.interim_request_details', kwargs={'number': meeting.number})
|
|
length_before = len(outbox)
|
|
login_testing_unauthorized(self, "ad", url)
|
|
r = self.client.post(url, {'approve': 'approve'})
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.interim_pending'))
|
|
for session in meeting.session_set.all():
|
|
self.assertEqual(session.status.slug, 'scheda')
|
|
self.assertEqual(len(outbox), length_before + 1)
|
|
self.assertTrue('ready for announcement' in outbox[-1]['Subject'])
|
|
|
|
def test_interim_approve_by_secretariat(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim', session__status='apprw', session__group__acronym='mars').first()
|
|
url = urlreverse('ietf.meeting.views.interim_request_details', kwargs={'number': meeting.number})
|
|
login_testing_unauthorized(self, "secretary", url)
|
|
r = self.client.post(url, {'approve': 'approve'})
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.interim_send_announcement', kwargs={'number': meeting.number}))
|
|
for session in meeting.session_set.all():
|
|
self.assertEqual(session.status.slug, 'scheda')
|
|
|
|
def test_past(self):
|
|
today = datetime.date.today()
|
|
last_week = today - datetime.timedelta(days=7)
|
|
ietf = SessionFactory(meeting__type_id='ietf',meeting__date=last_week,group__state_id='active',group__parent=GroupFactory(state_id='active'))
|
|
interim = SessionFactory(meeting__type_id='interim',meeting__date=last_week,status_id='canceled',group__state_id='active',group__parent=GroupFactory(state_id='active'))
|
|
url = urlreverse('ietf.meeting.views.past')
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue('IETF - %02d'%int(ietf.meeting.number) in unicontent(r))
|
|
q = PyQuery(r.content)
|
|
id="-%s" % interim.group.acronym
|
|
self.assertTrue('CANCELLED' in q('[id*="'+id+'"]').text())
|
|
|
|
def test_upcoming(self):
|
|
make_meeting_test_data()
|
|
url = urlreverse("ietf.meeting.views.upcoming")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
today = datetime.date.today()
|
|
mars_interim = Meeting.objects.filter(date__gt=today, type='interim', session__group__acronym='mars', session__status='sched').first()
|
|
ames_interim = Meeting.objects.filter(date__gt=today, type='interim', session__group__acronym='ames', session__status='canceled').first()
|
|
self.assertTrue(mars_interim.number in r.content)
|
|
self.assertTrue(ames_interim.number in r.content)
|
|
self.assertTrue('IETF - 42' in r.content)
|
|
# cancelled session
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('CANCELLED' in q('[id*="-ames"]').text())
|
|
self.check_interim_tabs(url)
|
|
|
|
def test_upcoming_ical(self):
|
|
make_meeting_test_data()
|
|
url = urlreverse("ietf.meeting.views.upcoming_ical")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(r.get('Content-Type'), "text/calendar")
|
|
self.assertEqual(r.content.count('UID'), 5)
|
|
# check filtered output
|
|
url = url + '?filters=mars'
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertEqual(r.get('Content-Type'), "text/calendar")
|
|
# print r.content
|
|
self.assertEqual(r.content.count('UID'), 2)
|
|
|
|
|
|
def test_interim_request_permissions(self):
|
|
'''Ensure only authorized users see link to request interim meeting'''
|
|
make_meeting_test_data()
|
|
|
|
# test unauthorized not logged in
|
|
upcoming_url = urlreverse("ietf.meeting.views.upcoming")
|
|
request_url = urlreverse("ietf.meeting.views.interim_request")
|
|
r = self.client.get(upcoming_url)
|
|
self.assertNotContains(r,'Request new interim meeting')
|
|
|
|
# test unauthorized user
|
|
login_testing_unauthorized(self,"plain",request_url)
|
|
r = self.client.get(upcoming_url)
|
|
self.assertNotContains(r,'Request new interim meeting')
|
|
r = self.client.get(request_url)
|
|
self.assertEqual(r.status_code, 403)
|
|
self.client.logout()
|
|
|
|
# test authorized
|
|
for username in ('secretary','ad','marschairman','irtf-chair','irgchairman'):
|
|
self.client.login(username=username, password= username + "+password")
|
|
r = self.client.get(upcoming_url)
|
|
self.assertContains(r,'Request new interim meeting')
|
|
r = self.client.get(request_url)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.client.logout()
|
|
|
|
def test_interim_request_options(self):
|
|
make_meeting_test_data()
|
|
|
|
# secretariat can request for any group
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
r = self.client.get("/meeting/interim/request/")
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(Group.objects.filter(type__in=('wg', 'rg'), state__in=('active', 'proposed')).count(),
|
|
len(q("#id_group option")) - 1) # -1 for options placeholder
|
|
self.client.logout()
|
|
|
|
# wg chair
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
r = self.client.get("/meeting/interim/request/")
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
user = User.objects.get(username='marschairman')
|
|
person = user.person
|
|
count = person.role_set.filter(name='chair',group__type__in=('wg', 'rg'), group__state__in=('active', 'proposed')).count()
|
|
self.assertEqual(count, len(q("#id_group option")) - 1) # -1 for options placeholder
|
|
|
|
# wg AND rg chair
|
|
group = Group.objects.get(acronym='irg')
|
|
Role.objects.create(name_id='chair',group=group,person=person,email=person.email())
|
|
r = self.client.get("/meeting/interim/request/")
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
count = person.role_set.filter(name='chair',group__type__in=('wg', 'rg'), group__state__in=('active', 'proposed')).count()
|
|
self.assertEqual(count, len(q("#id_group option")) - 1) # -1 for options placeholder
|
|
|
|
def test_interim_request_single_virtual(self):
|
|
make_meeting_test_data()
|
|
group = Group.objects.get(acronym='mars')
|
|
date = datetime.date.today() + datetime.timedelta(days=30)
|
|
time = datetime.datetime.now().time().replace(microsecond=0,second=0)
|
|
dt = datetime.datetime.combine(date, time)
|
|
duration = datetime.timedelta(hours=3)
|
|
remote_instructions = 'Use webex'
|
|
agenda = 'Intro. Slides. Discuss.'
|
|
agenda_note = 'On second level'
|
|
length_before = len(outbox)
|
|
meeting_count = Meeting.objects.filter(number__contains='-%s-'%group.acronym, date__year=date.year).count()
|
|
next_num = "%02d" % (meeting_count+1)
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
data = {'group':group.pk,
|
|
'meeting_type':'single',
|
|
'city':'',
|
|
'country':'',
|
|
'time_zone':'UTC',
|
|
'session_set-0-date':date.strftime("%Y-%m-%d"),
|
|
'session_set-0-time':time.strftime('%H:%M'),
|
|
'session_set-0-requested_duration':'03:00:00',
|
|
'session_set-0-remote_instructions':remote_instructions,
|
|
'session_set-0-agenda':agenda,
|
|
'session_set-0-agenda_note':agenda_note,
|
|
'session_set-TOTAL_FORMS':1,
|
|
'session_set-INITIAL_FORMS':0,
|
|
'session_set-MIN_NUM_FORMS':0,
|
|
'session_set-MAX_NUM_FORMS':1000}
|
|
|
|
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
|
|
self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming'))
|
|
meeting = Meeting.objects.order_by('id').last()
|
|
self.assertEqual(meeting.type_id,'interim')
|
|
self.assertEqual(meeting.date,date)
|
|
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year, group.acronym, next_num))
|
|
self.assertEqual(meeting.city,'')
|
|
self.assertEqual(meeting.country,'')
|
|
self.assertEqual(meeting.time_zone,'UTC')
|
|
session = meeting.session_set.first()
|
|
self.assertEqual(session.remote_instructions,remote_instructions)
|
|
self.assertEqual(session.agenda_note,agenda_note)
|
|
self.assertEqual(session.status.slug,'scheda')
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,dt)
|
|
self.assertEqual(timeslot.duration,duration)
|
|
# ensure agenda document was created
|
|
self.assertEqual(session.materials.count(),1)
|
|
doc = session.materials.first()
|
|
path = os.path.join(doc.get_file_path(),doc.filename_with_rev())
|
|
self.assertTrue(os.path.exists(path))
|
|
# check notice to secretariat
|
|
self.assertEqual(len(outbox), length_before + 1)
|
|
self.assertTrue('interim meeting ready for announcement' in outbox[-1]['Subject'])
|
|
self.assertTrue('iesg-secretary@ietf.org' in outbox[-1]['To'])
|
|
|
|
def test_interim_request_single_in_person(self):
|
|
make_meeting_test_data()
|
|
group = Group.objects.get(acronym='mars')
|
|
date = datetime.date.today() + datetime.timedelta(days=30)
|
|
time = datetime.datetime.now().time().replace(microsecond=0,second=0)
|
|
dt = datetime.datetime.combine(date, time)
|
|
duration = datetime.timedelta(hours=3)
|
|
city = 'San Francisco'
|
|
country = 'US'
|
|
time_zone = 'US/Pacific'
|
|
remote_instructions = 'Use webex'
|
|
agenda = 'Intro. Slides. Discuss.'
|
|
agenda_note = 'On second level'
|
|
meeting_count = Meeting.objects.filter(number__contains='-%s-'%group.acronym, date__year=date.year).count()
|
|
next_num = "%02d" % (meeting_count+1)
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
data = {'group':group.pk,
|
|
'meeting_type':'single',
|
|
'city':city,
|
|
'country':country,
|
|
'time_zone':time_zone,
|
|
'session_set-0-date':date.strftime("%Y-%m-%d"),
|
|
'session_set-0-time':time.strftime('%H:%M'),
|
|
'session_set-0-requested_duration':'03:00:00',
|
|
'session_set-0-remote_instructions':remote_instructions,
|
|
'session_set-0-agenda':agenda,
|
|
'session_set-0-agenda_note':agenda_note,
|
|
'session_set-TOTAL_FORMS':1,
|
|
'session_set-INITIAL_FORMS':0}
|
|
|
|
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
|
|
|
|
self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming'))
|
|
meeting = Meeting.objects.order_by('id').last()
|
|
self.assertEqual(meeting.type_id,'interim')
|
|
self.assertEqual(meeting.date,date)
|
|
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year, group.acronym, next_num))
|
|
self.assertEqual(meeting.city,city)
|
|
self.assertEqual(meeting.country,country)
|
|
self.assertEqual(meeting.time_zone,time_zone)
|
|
session = meeting.session_set.first()
|
|
self.assertEqual(session.remote_instructions,remote_instructions)
|
|
self.assertEqual(session.agenda_note,agenda_note)
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,dt)
|
|
self.assertEqual(timeslot.duration,duration)
|
|
|
|
def test_interim_request_multi_day(self):
|
|
make_meeting_test_data()
|
|
date = datetime.date.today() + datetime.timedelta(days=30)
|
|
date2 = date + datetime.timedelta(days=1)
|
|
time = datetime.datetime.now().time().replace(microsecond=0,second=0)
|
|
dt = datetime.datetime.combine(date, time)
|
|
dt2 = datetime.datetime.combine(date2, time)
|
|
duration = datetime.timedelta(hours=3)
|
|
group = Group.objects.get(acronym='mars')
|
|
city = 'San Francisco'
|
|
country = 'US'
|
|
time_zone = 'US/Pacific'
|
|
remote_instructions = 'Use webex'
|
|
agenda = 'Intro. Slides. Discuss.'
|
|
agenda_note = 'On second level'
|
|
meeting_count = Meeting.objects.filter(number__contains='-%s-'%group.acronym, date__year=date.year).count()
|
|
next_num = "%02d" % (meeting_count+1)
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
data = {'group':group.pk,
|
|
'meeting_type':'multi-day',
|
|
'city':city,
|
|
'country':country,
|
|
'time_zone':time_zone,
|
|
'session_set-0-date':date.strftime("%Y-%m-%d"),
|
|
'session_set-0-time':time.strftime('%H:%M'),
|
|
'session_set-0-requested_duration':'03:00:00',
|
|
'session_set-0-remote_instructions':remote_instructions,
|
|
'session_set-0-agenda':agenda,
|
|
'session_set-0-agenda_note':agenda_note,
|
|
'session_set-1-date':date2.strftime("%Y-%m-%d"),
|
|
'session_set-1-time':time.strftime('%H:%M'),
|
|
'session_set-1-requested_duration':'03:00:00',
|
|
'session_set-1-remote_instructions':remote_instructions,
|
|
'session_set-1-agenda':agenda,
|
|
'session_set-1-agenda_note':agenda_note,
|
|
'session_set-TOTAL_FORMS':2,
|
|
'session_set-INITIAL_FORMS':0}
|
|
|
|
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
|
|
self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming'))
|
|
meeting = Meeting.objects.order_by('id').last()
|
|
self.assertEqual(meeting.type_id,'interim')
|
|
self.assertEqual(meeting.date,date)
|
|
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year, group.acronym, next_num))
|
|
self.assertEqual(meeting.city,city)
|
|
self.assertEqual(meeting.country,country)
|
|
self.assertEqual(meeting.time_zone,time_zone)
|
|
self.assertEqual(meeting.session_set.count(),2)
|
|
# first sesstion
|
|
session = meeting.session_set.all()[0]
|
|
self.assertEqual(session.remote_instructions,remote_instructions)
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,dt)
|
|
self.assertEqual(timeslot.duration,duration)
|
|
self.assertEqual(session.agenda_note,agenda_note)
|
|
# second sesstion
|
|
session = meeting.session_set.all()[1]
|
|
self.assertEqual(session.remote_instructions,remote_instructions)
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,dt2)
|
|
self.assertEqual(timeslot.duration,duration)
|
|
self.assertEqual(session.agenda_note,agenda_note)
|
|
|
|
def test_interim_request_multi_day_non_consecutive(self):
|
|
make_meeting_test_data()
|
|
date = datetime.date.today() + datetime.timedelta(days=30)
|
|
date2 = date + datetime.timedelta(days=2)
|
|
time = datetime.datetime.now().time().replace(microsecond=0,second=0)
|
|
group = Group.objects.get(acronym='mars')
|
|
city = 'San Francisco'
|
|
country = 'US'
|
|
time_zone = 'US/Pacific'
|
|
remote_instructions = 'Use webex'
|
|
agenda = 'Intro. Slides. Discuss.'
|
|
agenda_note = 'On second level'
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
data = {'group':group.pk,
|
|
'meeting_type':'multi-day',
|
|
'city':city,
|
|
'country':country,
|
|
'time_zone':time_zone,
|
|
'session_set-0-date':date.strftime("%Y-%m-%d"),
|
|
'session_set-0-time':time.strftime('%H:%M'),
|
|
'session_set-0-requested_duration':'03:00:00',
|
|
'session_set-0-remote_instructions':remote_instructions,
|
|
'session_set-0-agenda':agenda,
|
|
'session_set-0-agenda_note':agenda_note,
|
|
'session_set-1-date':date2.strftime("%Y-%m-%d"),
|
|
'session_set-1-time':time.strftime('%H:%M'),
|
|
'session_set-1-requested_duration':'03:00:00',
|
|
'session_set-1-remote_instructions':remote_instructions,
|
|
'session_set-1-agenda':agenda,
|
|
'session_set-1-agenda_note':agenda_note,
|
|
'session_set-TOTAL_FORMS':2,
|
|
'session_set-INITIAL_FORMS':0}
|
|
|
|
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
|
|
self.assertEqual(r.status_code, 200)
|
|
self.assertTrue('days must be consecutive' in r.content)
|
|
|
|
def test_interim_request_series(self):
|
|
make_meeting_test_data()
|
|
meeting_count_before = Meeting.objects.filter(type='interim').count()
|
|
date = datetime.date.today() + datetime.timedelta(days=30)
|
|
date2 = date + datetime.timedelta(days=1)
|
|
time = datetime.datetime.now().time().replace(microsecond=0,second=0)
|
|
dt = datetime.datetime.combine(date, time)
|
|
dt2 = datetime.datetime.combine(date2, time)
|
|
duration = datetime.timedelta(hours=3)
|
|
group = Group.objects.get(acronym='mars')
|
|
city = ''
|
|
country = ''
|
|
time_zone = 'US/Pacific'
|
|
remote_instructions = 'Use webex'
|
|
agenda = 'Intro. Slides. Discuss.'
|
|
agenda_note = 'On second level'
|
|
meeting_count = Meeting.objects.filter(number__contains='-%s-'%group.acronym, date__year=date.year).count()
|
|
next_num = "%02d" % (meeting_count+1)
|
|
next_num2 = "%02d" % (meeting_count+2)
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
r = self.client.get(urlreverse("ietf.meeting.views.interim_request"))
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
data = {'group':group.pk,
|
|
'meeting_type':'series',
|
|
'city':city,
|
|
'country':country,
|
|
'time_zone':time_zone,
|
|
'session_set-0-date':date.strftime("%Y-%m-%d"),
|
|
'session_set-0-time':time.strftime('%H:%M'),
|
|
'session_set-0-requested_duration':'03:00:00',
|
|
'session_set-0-remote_instructions':remote_instructions,
|
|
'session_set-0-agenda':agenda,
|
|
'session_set-0-agenda_note':agenda_note,
|
|
'session_set-1-date':date2.strftime("%Y-%m-%d"),
|
|
'session_set-1-time':time.strftime('%H:%M'),
|
|
'session_set-1-requested_duration':'03:00:00',
|
|
'session_set-1-remote_instructions':remote_instructions,
|
|
'session_set-1-agenda':agenda,
|
|
'session_set-1-agenda_note':agenda_note,
|
|
'session_set-TOTAL_FORMS':2,
|
|
'session_set-INITIAL_FORMS':0}
|
|
|
|
r = self.client.post(urlreverse("ietf.meeting.views.interim_request"),data)
|
|
|
|
self.assertRedirects(r,urlreverse('ietf.meeting.views.upcoming'))
|
|
meeting_count_after = Meeting.objects.filter(type='interim').count()
|
|
self.assertEqual(meeting_count_after,meeting_count_before + 2)
|
|
meetings = Meeting.objects.order_by('-id')[:2]
|
|
# first meeting
|
|
meeting = meetings[1]
|
|
self.assertEqual(meeting.type_id,'interim')
|
|
self.assertEqual(meeting.date,date)
|
|
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date.year, group.acronym, next_num))
|
|
self.assertEqual(meeting.city,city)
|
|
self.assertEqual(meeting.country,country)
|
|
self.assertEqual(meeting.time_zone,time_zone)
|
|
self.assertEqual(meeting.session_set.count(),1)
|
|
session = meeting.session_set.first()
|
|
self.assertEqual(session.remote_instructions,remote_instructions)
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,dt)
|
|
self.assertEqual(timeslot.duration,duration)
|
|
self.assertEqual(session.agenda_note,agenda_note)
|
|
# second meeting
|
|
meeting = meetings[0]
|
|
self.assertEqual(meeting.type_id,'interim')
|
|
self.assertEqual(meeting.date,date2)
|
|
self.assertEqual(meeting.number,'interim-%s-%s-%s' % (date2.year, group.acronym, next_num2))
|
|
self.assertEqual(meeting.city,city)
|
|
self.assertEqual(meeting.country,country)
|
|
self.assertEqual(meeting.time_zone,time_zone)
|
|
self.assertEqual(meeting.session_set.count(),1)
|
|
session = meeting.session_set.first()
|
|
self.assertEqual(session.remote_instructions,remote_instructions)
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,dt2)
|
|
self.assertEqual(timeslot.duration,duration)
|
|
self.assertEqual(session.agenda_note,agenda_note)
|
|
|
|
|
|
def test_interim_pending(self):
|
|
make_meeting_test_data()
|
|
url = urlreverse('ietf.meeting.views.interim_pending')
|
|
count = Meeting.objects.filter(type='interim',session__status='apprw').distinct().count()
|
|
|
|
# unpriviledged user
|
|
login_testing_unauthorized(self,"plain",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 403)
|
|
|
|
# secretariat
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("#pending-interim-meetings-table tr"))-1, count)
|
|
self.client.logout()
|
|
|
|
|
|
def test_can_approve_interim_request(self):
|
|
make_meeting_test_data()
|
|
# unprivileged user
|
|
user = User.objects.get(username='plain')
|
|
group = Group.objects.get(acronym='mars')
|
|
meeting = Meeting.objects.filter(type='interim',session__status='apprw',session__group=group).first()
|
|
self.assertFalse(can_approve_interim_request(meeting=meeting,user=user))
|
|
# Secretariat
|
|
user = User.objects.get(username='secretary')
|
|
self.assertTrue(can_approve_interim_request(meeting=meeting,user=user))
|
|
# related AD
|
|
user = User.objects.get(username='ad')
|
|
self.assertTrue(can_approve_interim_request(meeting=meeting,user=user))
|
|
# other AD
|
|
user = User.objects.get(username='ops-ad')
|
|
self.assertFalse(can_approve_interim_request(meeting=meeting,user=user))
|
|
# WG Chair
|
|
user = User.objects.get(username='marschairman')
|
|
self.assertFalse(can_approve_interim_request(meeting=meeting,user=user))
|
|
|
|
def test_can_view_interim_request(self):
|
|
make_meeting_test_data()
|
|
# unprivileged user
|
|
user = User.objects.get(username='plain')
|
|
group = Group.objects.get(acronym='mars')
|
|
meeting = Meeting.objects.filter(type='interim',session__status='apprw',session__group=group).first()
|
|
self.assertFalse(can_view_interim_request(meeting=meeting,user=user))
|
|
# Secretariat
|
|
user = User.objects.get(username='secretary')
|
|
self.assertTrue(can_view_interim_request(meeting=meeting,user=user))
|
|
# related AD
|
|
user = User.objects.get(username='ad')
|
|
self.assertTrue(can_view_interim_request(meeting=meeting,user=user))
|
|
# other AD
|
|
user = User.objects.get(username='ops-ad')
|
|
self.assertTrue(can_view_interim_request(meeting=meeting,user=user))
|
|
# WG Chair
|
|
user = User.objects.get(username='marschairman')
|
|
self.assertTrue(can_view_interim_request(meeting=meeting,user=user))
|
|
# Other WG Chair
|
|
user = User.objects.get(username='ameschairman')
|
|
self.assertFalse(can_view_interim_request(meeting=meeting,user=user))
|
|
|
|
def test_interim_request_details(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim',session__status='apprw',session__group__acronym='mars').first()
|
|
url = urlreverse('ietf.meeting.views.interim_request_details',kwargs={'number':meeting.number})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
def test_interim_request_details_announcement(self):
|
|
'''Test access to Announce / Skip Announce features'''
|
|
make_meeting_test_data()
|
|
date = datetime.date.today() + datetime.timedelta(days=30)
|
|
group = Group.objects.get(acronym='mars')
|
|
meeting = make_interim_meeting(group=group, date=date, status='scheda')
|
|
url = urlreverse('ietf.meeting.views.interim_request_details',kwargs={'number':meeting.number})
|
|
|
|
# Chair, no access
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("a.btn:contains('Announce')")),0)
|
|
|
|
# Secretariat has access
|
|
self.client.login(username="secretary", password="secretary+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("a.btn:contains('Announce')")),2)
|
|
|
|
def test_interim_request_disapprove(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim',session__status='apprw',session__group__acronym='mars').first()
|
|
url = urlreverse('ietf.meeting.views.interim_request_details',kwargs={'number':meeting.number})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.post(url,{'disapprove':'Disapprove'})
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.interim_pending'))
|
|
for session in meeting.session_set.all():
|
|
self.assertEqual(session.status_id,'disappr')
|
|
|
|
def test_interim_request_cancel(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim', session__status='apprw', session__group__acronym='mars').first()
|
|
url = urlreverse('ietf.meeting.views.interim_request_details', kwargs={'number': meeting.number})
|
|
# ensure no cancel button for unauthorized user
|
|
self.client.login(username="ameschairman", password="ameschairman+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("a.btn:contains('Cancel')")), 0)
|
|
# ensure cancel button for authorized user
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertEqual(len(q("a.btn:contains('Cancel')")), 1)
|
|
# ensure fail unauthorized
|
|
url = urlreverse('ietf.meeting.views.interim_request_cancel', kwargs={'number': meeting.number})
|
|
comments = 'Bob cannot make it'
|
|
self.client.login(username="ameschairman", password="ameschairman+password")
|
|
r = self.client.post(url, {'comments': comments})
|
|
self.assertEqual(r.status_code, 403)
|
|
# test cancelling before announcement
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
length_before = len(outbox)
|
|
r = self.client.post(url, {'comments': comments})
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.upcoming'))
|
|
for session in meeting.session_set.all():
|
|
self.assertEqual(session.status_id, 'canceledpa')
|
|
self.assertEqual(session.agenda_note, comments)
|
|
self.assertEqual(len(outbox), length_before) # no email notice
|
|
# test cancelling after announcement
|
|
meeting = Meeting.objects.filter(type='interim', session__status='sched', session__group__acronym='mars').first()
|
|
url = urlreverse('ietf.meeting.views.interim_request_cancel', kwargs={'number': meeting.number})
|
|
r = self.client.post(url, {'comments': comments})
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.upcoming'))
|
|
for session in meeting.session_set.all():
|
|
self.assertEqual(session.status_id, 'canceled')
|
|
self.assertEqual(session.agenda_note, comments)
|
|
self.assertEqual(len(outbox), length_before + 1)
|
|
self.assertTrue('Interim Meeting Cancelled' in outbox[-1]['Subject'])
|
|
|
|
def test_interim_request_edit_no_notice(self):
|
|
'''Edit a request. No notice should go out if it hasn't been announced yet'''
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim', session__status='apprw', session__group__acronym='mars').first()
|
|
group = meeting.session_set.first().group
|
|
url = urlreverse('ietf.meeting.views.interim_request_edit', kwargs={'number': meeting.number})
|
|
# test unauthorized access
|
|
self.client.login(username="ameschairman", password="ameschairman+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 403)
|
|
# test authorized use
|
|
login_testing_unauthorized(self, "secretary", url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
# post changes
|
|
length_before = len(outbox)
|
|
form_initial = r.context['form'].initial
|
|
formset_initial = r.context['formset'].forms[0].initial
|
|
new_time = formset_initial['time'] + datetime.timedelta(hours=1)
|
|
data = {'group':group.pk,
|
|
'meeting_type':'single',
|
|
'session_set-0-id':meeting.session_set.first().id,
|
|
'session_set-0-date':formset_initial['date'].strftime('%Y-%m-%d'),
|
|
'session_set-0-time':new_time.strftime('%H:%M'),
|
|
'session_set-0-requested_duration':formset_initial['requested_duration'],
|
|
'session_set-0-remote_instructions':formset_initial['remote_instructions'],
|
|
#'session_set-0-agenda':formset_initial['agenda'],
|
|
'session_set-0-agenda_note':formset_initial['agenda_note'],
|
|
'session_set-TOTAL_FORMS':1,
|
|
'session_set-INITIAL_FORMS':1}
|
|
data.update(form_initial)
|
|
r = self.client.post(url, data)
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.interim_request_details', kwargs={'number': meeting.number}))
|
|
self.assertEqual(len(outbox),length_before)
|
|
session = meeting.session_set.first()
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,new_time)
|
|
|
|
def test_interim_request_edit(self):
|
|
'''Edit request. Send notice of change'''
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim', session__status='sched', session__group__acronym='mars').first()
|
|
group = meeting.session_set.first().group
|
|
url = urlreverse('ietf.meeting.views.interim_request_edit', kwargs={'number': meeting.number})
|
|
# test unauthorized access
|
|
self.client.login(username="ameschairman", password="ameschairman+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 403)
|
|
# test authorized use
|
|
login_testing_unauthorized(self, "secretary", url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
# post changes
|
|
length_before = len(outbox)
|
|
form_initial = r.context['form'].initial
|
|
formset_initial = r.context['formset'].forms[0].initial
|
|
new_time = formset_initial['time'] + datetime.timedelta(hours=1)
|
|
new_duration = formset_initial['requested_duration'] + datetime.timedelta(hours=1)
|
|
data = {'group':group.pk,
|
|
'meeting_type':'single',
|
|
'session_set-0-id':meeting.session_set.first().id,
|
|
'session_set-0-date':formset_initial['date'].strftime('%Y-%m-%d'),
|
|
'session_set-0-time':new_time.strftime('%H:%M'),
|
|
'session_set-0-requested_duration':self.strfdelta(new_duration, '{hours}:{minutes}'),
|
|
'session_set-0-remote_instructions':formset_initial['remote_instructions'],
|
|
#'session_set-0-agenda':formset_initial['agenda'],
|
|
'session_set-0-agenda_note':formset_initial['agenda_note'],
|
|
'session_set-TOTAL_FORMS':1,
|
|
'session_set-INITIAL_FORMS':1}
|
|
data.update(form_initial)
|
|
r = self.client.post(url, data)
|
|
self.assertRedirects(r, urlreverse('ietf.meeting.views.interim_request_details', kwargs={'number': meeting.number}))
|
|
self.assertEqual(len(outbox),length_before+1)
|
|
self.assertTrue('CHANGED' in outbox[-1]['Subject'])
|
|
session = meeting.session_set.first()
|
|
timeslot = session.official_timeslotassignment().timeslot
|
|
self.assertEqual(timeslot.time,new_time)
|
|
self.assertEqual(timeslot.duration,new_duration)
|
|
|
|
def strfdelta(self, tdelta, fmt):
|
|
d = {"days": tdelta.days}
|
|
d["hours"], rem = divmod(tdelta.seconds, 3600)
|
|
d["minutes"], d["seconds"] = divmod(rem, 60)
|
|
return fmt.format(**d)
|
|
|
|
def test_interim_request_details_permissions(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim',session__status='apprw',session__group__acronym='mars').first()
|
|
url = urlreverse('ietf.meeting.views.interim_request_details',kwargs={'number':meeting.number})
|
|
|
|
# unprivileged user
|
|
login_testing_unauthorized(self,"plain",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 403)
|
|
|
|
def test_send_interim_approval_request(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim',session__status='apprw',session__group__acronym='mars').first()
|
|
length_before = len(outbox)
|
|
send_interim_approval_request(meetings=[meeting])
|
|
self.assertEqual(len(outbox),length_before+1)
|
|
self.assertTrue('New Interim Meeting Request' in outbox[-1]['Subject'])
|
|
|
|
def test_send_interim_cancellation_notice(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type='interim',session__status='sched',session__group__acronym='mars').first()
|
|
length_before = len(outbox)
|
|
send_interim_cancellation_notice(meeting=meeting)
|
|
self.assertEqual(len(outbox),length_before+1)
|
|
self.assertTrue('Interim Meeting Cancelled' in outbox[-1]['Subject'])
|
|
|
|
def test_send_interim_minutes_reminder(self):
|
|
make_meeting_test_data()
|
|
group = Group.objects.get(acronym='mars')
|
|
date = datetime.datetime.today() - datetime.timedelta(days=10)
|
|
meeting = make_interim_meeting(group=group, date=date, status='sched')
|
|
length_before = len(outbox)
|
|
send_interim_minutes_reminder(meeting=meeting)
|
|
self.assertEqual(len(outbox),length_before+1)
|
|
self.assertTrue('Action Required: Minutes' in outbox[-1]['Subject'])
|
|
|
|
|
|
class AjaxTests(TestCase):
|
|
def test_ajax_get_utc(self):
|
|
# test bad queries
|
|
url = urlreverse('ietf.meeting.views.ajax_get_utc') + "?date=2016-1-1&time=badtime&timezone=UTC"
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
data = json.loads(r.content)
|
|
self.assertEqual(data["error"], True)
|
|
url = urlreverse('ietf.meeting.views.ajax_get_utc') + "?date=2016-1-1&time=25:99&timezone=UTC"
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
data = json.loads(r.content)
|
|
self.assertEqual(data["error"], True)
|
|
url = urlreverse('ietf.meeting.views.ajax_get_utc') + "?date=2016-1-1&time=10:00am&timezone=UTC"
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
data = json.loads(r.content)
|
|
self.assertEqual(data["error"], True)
|
|
# test good query
|
|
url = urlreverse('ietf.meeting.views.ajax_get_utc') + "?date=2016-1-1&time=12:00&timezone=US/Pacific"
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
data = json.loads(r.content)
|
|
self.assertTrue('timezone' in data)
|
|
self.assertTrue('time' in data)
|
|
self.assertTrue('utc' in data)
|
|
self.assertTrue('error' not in data)
|
|
self.assertEqual(data['utc'], '20:00')
|
|
|
|
class FloorPlanTests(TestCase):
|
|
def setUp(self):
|
|
pass
|
|
|
|
def tearDown(self):
|
|
pass
|
|
|
|
def test_floor_plan_page(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type_id='ietf').order_by('id').last()
|
|
floorplan = FloorPlanFactory.create(meeting=meeting)
|
|
|
|
url = urlreverse('ietf.meeting.views.floor_plan')
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
url = urlreverse('ietf.meeting.views.floor_plan', kwargs={'floor': xslugify(floorplan.name)} )
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
class IphoneAppJsonTests(TestCase):
|
|
def setUp(self):
|
|
pass
|
|
|
|
def tearDown(self):
|
|
pass
|
|
|
|
def test_iphone_app_json(self):
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type_id='ietf').order_by('id').last()
|
|
floorplan = FloorPlanFactory.create(meeting=meeting)
|
|
for room in meeting.room_set.all():
|
|
room.floorplan = floorplan
|
|
room.x1 = random.randint(0,100)
|
|
room.y1 = random.randint(0,100)
|
|
room.x2 = random.randint(0,100)
|
|
room.y2 = random.randint(0,100)
|
|
room.save()
|
|
url = urlreverse('ietf.meeting.views.json_agenda',kwargs={'num':meeting.number})
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code,200)
|
|
|
|
class FinalizeProceedingsTests(TestCase):
|
|
@patch('urllib2.urlopen')
|
|
def test_finalize_proceedings(self, mock_urlopen):
|
|
mock_urlopen.return_value = StringIO('[{"LastName":"Smith","FirstName":"John","Company":"ABC","Country":"US"}]')
|
|
make_meeting_test_data()
|
|
meeting = Meeting.objects.filter(type_id='ietf').order_by('id').last()
|
|
meeting.session_set.filter(group__acronym='mars').first().sessionpresentation_set.create(document=Document.objects.filter(type='draft').first(),rev=None)
|
|
|
|
url = urlreverse('ietf.meeting.views.finalize_proceedings',kwargs={'num':meeting.number})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
self.assertEqual(meeting.proceedings_final,False)
|
|
self.assertEqual(meeting.session_set.filter(group__acronym="mars").first().sessionpresentation_set.filter(document__type="draft").first().rev,None)
|
|
r = self.client.post(url,{'finalize':1})
|
|
self.assertEqual(r.status_code, 302)
|
|
meeting = Meeting.objects.get(pk=meeting.pk)
|
|
self.assertEqual(meeting.proceedings_final,True)
|
|
self.assertEqual(meeting.session_set.filter(group__acronym="mars").first().sessionpresentation_set.filter(document__type="draft").first().rev,'00')
|
|
|
|
class MaterialsTests(TestCase):
|
|
|
|
def setUp(self):
|
|
self.materials_dir = self.tempdir('materials')
|
|
if not os.path.exists(self.materials_dir):
|
|
os.mkdir(self.materials_dir)
|
|
self.saved_agenda_path = settings.AGENDA_PATH
|
|
settings.AGENDA_PATH = self.materials_dir
|
|
|
|
def tearDown(self):
|
|
settings.AGENDA_PATH = self.saved_agenda_path
|
|
shutil.rmtree(self.materials_dir)
|
|
|
|
def test_upload_bluesheets(self):
|
|
session = SessionFactory(meeting__type_id='ietf')
|
|
url = urlreverse('ietf.meeting.views.upload_session_bluesheets',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Upload' in unicode(q("title")))
|
|
self.assertFalse(session.sessionpresentation_set.exists())
|
|
test_file = StringIO('this is some text for a test')
|
|
test_file.name = "not_really.pdf"
|
|
r = self.client.post(url,dict(file=test_file))
|
|
self.assertEqual(r.status_code, 302)
|
|
bs_doc = session.sessionpresentation_set.filter(document__type_id='bluesheets').first().document
|
|
self.assertEqual(bs_doc.rev,'00')
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Revise' in unicode(q("title")))
|
|
test_file = StringIO('this is some different text for a test')
|
|
test_file.name = "also_not_really.pdf"
|
|
r = self.client.post(url,dict(file=test_file))
|
|
self.assertEqual(r.status_code, 302)
|
|
bs_doc = Document.objects.get(pk=bs_doc.pk)
|
|
self.assertEqual(bs_doc.rev,'01')
|
|
|
|
def test_upload_bluesheets_chair_access(self):
|
|
make_meeting_test_data()
|
|
mars = Group.objects.get(acronym='mars')
|
|
session=SessionFactory(meeting__type_id='ietf',group=mars)
|
|
url = urlreverse('ietf.meeting.views.upload_session_bluesheets',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 403)
|
|
|
|
def test_upload_bluesheets_interim(self):
|
|
session=SessionFactory(meeting__type_id='interim')
|
|
url = urlreverse('ietf.meeting.views.upload_session_bluesheets',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Upload' in unicode(q("title")))
|
|
self.assertFalse(session.sessionpresentation_set.exists())
|
|
test_file = StringIO('this is some text for a test')
|
|
test_file.name = "not_really.pdf"
|
|
r = self.client.post(url,dict(file=test_file))
|
|
self.assertEqual(r.status_code, 302)
|
|
bs_doc = session.sessionpresentation_set.filter(document__type_id='bluesheets').first().document
|
|
self.assertEqual(bs_doc.rev,'00')
|
|
|
|
def test_upload_bluesheets_interim_chair_access(self):
|
|
make_meeting_test_data()
|
|
mars = Group.objects.get(acronym='mars')
|
|
session=SessionFactory(meeting__type_id='interim',group=mars)
|
|
url = urlreverse('ietf.meeting.views.upload_session_bluesheets',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
self.client.login(username="marschairman", password="marschairman+password")
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Upload' in unicode(q("title")))
|
|
|
|
|
|
def test_upload_minutes_agenda(self):
|
|
for doctype in ('minutes','agenda'):
|
|
session = SessionFactory(meeting__type_id='ietf')
|
|
if doctype == 'minutes':
|
|
url = urlreverse('ietf.meeting.views.upload_session_minutes',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
else:
|
|
url = urlreverse('ietf.meeting.views.upload_session_agenda',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
self.client.logout()
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Upload' in unicode(q("Title")))
|
|
self.assertFalse(session.sessionpresentation_set.exists())
|
|
self.assertFalse(q('form input[type="checkbox"]'))
|
|
|
|
session2 = SessionFactory(meeting=session.meeting,group=session.group)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue(q('form input[type="checkbox"]'))
|
|
|
|
test_file = StringIO('this is some text for a test')
|
|
test_file.name = "not_really.json"
|
|
r = self.client.post(url,dict(file=test_file))
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue(q('form .has-error'))
|
|
|
|
test_file = StringIO('this is some text for a test'*1510000)
|
|
test_file.name = "not_really.pdf"
|
|
r = self.client.post(url,dict(file=test_file))
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue(q('form .has-error'))
|
|
|
|
test_file = StringIO('this is some text for a test')
|
|
test_file.name = "not_really.txt"
|
|
r = self.client.post(url,dict(file=test_file,apply_to_all=False))
|
|
self.assertEqual(r.status_code, 302)
|
|
doc = session.sessionpresentation_set.filter(document__type_id=doctype).first().document
|
|
self.assertEqual(doc.rev,'00')
|
|
self.assertFalse(session2.sessionpresentation_set.filter(document__type_id=doctype))
|
|
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Revise' in unicode(q("Title")))
|
|
test_file = StringIO('this is some different text for a test')
|
|
test_file.name = "also_not_really.txt"
|
|
r = self.client.post(url,dict(file=test_file,apply_to_all=True))
|
|
self.assertEqual(r.status_code, 302)
|
|
doc = Document.objects.get(pk=doc.pk)
|
|
self.assertEqual(doc.rev,'01')
|
|
self.assertTrue(session2.sessionpresentation_set.filter(document__type_id=doctype))
|
|
|
|
def test_upload_minutes_agenda_interim(self):
|
|
session=SessionFactory(meeting__type_id='interim')
|
|
for doctype in ('minutes','agenda'):
|
|
if doctype=='minutes':
|
|
url = urlreverse('ietf.meeting.views.upload_session_minutes',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
else:
|
|
url = urlreverse('ietf.meeting.views.upload_session_agenda',kwargs={'num':session.meeting.number,'session_id':session.id})
|
|
self.client.logout()
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Upload' in unicode(q("title")))
|
|
self.assertFalse(session.sessionpresentation_set.filter(document__type_id=doctype))
|
|
test_file = StringIO('this is some text for a test')
|
|
test_file.name = "not_really.txt"
|
|
r = self.client.post(url,dict(file=test_file))
|
|
self.assertEqual(r.status_code, 302)
|
|
doc = session.sessionpresentation_set.filter(document__type_id=doctype).first().document
|
|
self.assertEqual(doc.rev,'00')
|
|
|
|
def test_upload_slides(self):
|
|
|
|
session1 = SessionFactory(meeting__type_id='ietf')
|
|
session2 = SessionFactory(meeting=session1.meeting,group=session1.group)
|
|
url = urlreverse('ietf.meeting.views.upload_session_slides',kwargs={'num':session1.meeting.number,'session_id':session1.id})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
r = self.client.get(url)
|
|
self.assertEqual(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Upload' in unicode(q("title")))
|
|
self.assertFalse(session1.sessionpresentation_set.filter(document__type_id='slides'))
|
|
test_file = StringIO('this is not really a slide')
|
|
test_file.name = 'not_really.txt'
|
|
r = self.client.post(url,dict(file=test_file,title='a test slide file',apply_to_all=True))
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(session1.sessionpresentation_set.count(),1)
|
|
self.assertEqual(session2.sessionpresentation_set.count(),1)
|
|
sp = session2.sessionpresentation_set.first()
|
|
self.assertEqual(sp.document.name, 'slides-%s-%s-a-test-slide-file' % (session1.meeting.number,session1.group.acronym ) )
|
|
self.assertEqual(sp.order,1)
|
|
|
|
url = urlreverse('ietf.meeting.views.upload_session_slides',kwargs={'num':session2.meeting.number,'session_id':session2.id})
|
|
test_file = StringIO('some other thing still not slidelike')
|
|
test_file.name = 'also_not_really.txt'
|
|
r = self.client.post(url,dict(file=test_file,title='a different slide file',apply_to_all=False))
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(session1.sessionpresentation_set.count(),1)
|
|
self.assertEqual(session2.sessionpresentation_set.count(),2)
|
|
sp = session2.sessionpresentation_set.get(document__name__endswith='-a-different-slide-file')
|
|
self.assertEqual(sp.order,2)
|
|
self.assertEqual(sp.rev,u'00')
|
|
self.assertEqual(sp.document.rev,u'00')
|
|
|
|
url = urlreverse('ietf.meeting.views.upload_session_slides',kwargs={'num':session2.meeting.number,'session_id':session2.id,'name':session2.sessionpresentation_set.get(order=2).document.name})
|
|
r = self.client.get(url)
|
|
self.assertTrue(r.status_code, 200)
|
|
q = PyQuery(r.content)
|
|
self.assertTrue('Revise' in unicode(q("title")))
|
|
test_file = StringIO('new content for the second slide deck')
|
|
test_file.name = 'doesnotmatter.txt'
|
|
r = self.client.post(url,dict(file=test_file,title='rename the presentation',apply_to_all=False))
|
|
self.assertEqual(r.status_code, 302)
|
|
self.assertEqual(session1.sessionpresentation_set.count(),1)
|
|
self.assertEqual(session2.sessionpresentation_set.count(),2)
|
|
sp = session2.sessionpresentation_set.get(order=2)
|
|
self.assertEqual(sp.rev,u'01')
|
|
self.assertEqual(sp.document.rev,u'01')
|
|
|
|
def test_remove_sessionpresentation(self):
|
|
session = SessionFactory(meeting__type_id='ietf')
|
|
doc = DocumentFactory(type_id='slides')
|
|
session.sessionpresentation_set.create(document=doc)
|
|
|
|
url = urlreverse('ietf.meeting.views.remove_sessionpresentation',kwargs={'num':session.meeting.number,'session_id':session.id,'name':'no-such-doc'})
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
url = urlreverse('ietf.meeting.views.remove_sessionpresentation',kwargs={'num':session.meeting.number,'session_id':0,'name':doc.name})
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 404)
|
|
|
|
url = urlreverse('ietf.meeting.views.remove_sessionpresentation',kwargs={'num':session.meeting.number,'session_id':session.id,'name':doc.name})
|
|
login_testing_unauthorized(self,"secretary",url)
|
|
response = self.client.get(url)
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
self.assertEqual(1,session.sessionpresentation_set.count())
|
|
response = self.client.post(url,{'remove_session':''})
|
|
self.assertEqual(response.status_code, 302)
|
|
self.assertEqual(0,session.sessionpresentation_set.count())
|
|
self.assertEqual(2,doc.docevent_set.count())
|