def test_venues(self): """Test that we detect venues violating the day constraints correctly.""" day1 = Day.objects.create(date=D.date(2013, 9, 22)) day2 = Day.objects.create(date=D.date(2013, 9, 23)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue2 = Venue.objects.create(order=2, name='Venue 2') venue1.days.add(day1) venue2.days.add(day2) start1 = D.time(10, 0, 0) start2 = D.time(11, 0, 0) slot1 = Slot.objects.create(start_time=start1, end_time=start2, day=day1) page = Page.objects.create(name="test page", slug="test") item1 = ScheduleItem.objects.create(venue=venue1, page_id=page.pk) item1.slots.add(slot1) item2 = ScheduleItem.objects.create(venue=venue2, page_id=page.pk) item2.slots.add(slot1) all_items = prefetch_schedule_items() # Needs to be an explicit list, as in the find_clashes test venues = list(find_invalid_venues(all_items)) assert venues[0][0] == venue2 assert set(venues[0][1]) == set([item2]) slot2 = Slot.objects.create(start_time=start1, end_time=start2, day=day2) item3 = ScheduleItem.objects.create(venue=venue2, page_id=page.pk) item3.slots.add(slot2) all_items = prefetch_schedule_items() venues = list(find_invalid_venues(all_items)) assert venues[0][0] == venue2 assert set(venues[0][1]) == set([item2]) item4 = ScheduleItem.objects.create(venue=venue1, page_id=page.pk) item5 = ScheduleItem.objects.create(venue=venue2, page_id=page.pk) item4.slots.add(slot2) item5.slots.add(slot1) all_items = prefetch_schedule_items() venues = list(find_invalid_venues(all_items)) assert set([x[0] for x in venues]) == set([venue1, venue2]) venue_1_items = [] venue_2_items = [] for sublist in venues: if sublist[0] == venue1: venue_1_items.extend(sublist[1]) elif sublist[0] == venue2: venue_2_items.extend(sublist[1]) assert set(venue_1_items) == set([item4]) assert set(venue_2_items) == set([item2, item5])
def test_duplicates(self): """Test that we can detect duplicates talks and pages""" # Final chedule is # Venue 1 Venue 2 # 10-11 Talk 1 Page 1 # 11-12 Talk 1 Page 1 day1 = Day.objects.create(date=D.date(2013, 9, 22)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue2 = Venue.objects.create(order=2, name='Venue 2') venue1.days.add(day1) venue2.days.add(day1) start1 = D.time(10, 0, 0) start2 = D.time(11, 0, 0) end = D.time(12, 0, 0) slot1 = Slot.objects.create(start_time=start1, end_time=start2, day=day1) slot2 = Slot.objects.create(start_time=start1, end_time=end, day=day1) user = get_user_model().objects.create_user('john', '*****@*****.**', 'johnpassword') talk = Talk.objects.create(title="Test talk", status=ACCEPTED, corresponding_author_id=user.id) page1 = Page.objects.create(name="test page", slug="test") page2 = Page.objects.create(name="test page 2", slug="test2") item1 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk) item1.slots.add(slot1) item2 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk) item2.slots.add(slot2) all_items = prefetch_schedule_items() duplicates = find_duplicate_schedule_items(all_items) assert set(duplicates) == set([item1, item2]) item3 = ScheduleItem.objects.create(venue=venue2, page_id=page1.pk) item3.slots.add(slot1) item4 = ScheduleItem.objects.create(venue=venue2, talk_id=talk.pk) item4.slots.add(slot2) all_items = prefetch_schedule_items() duplicates = find_duplicate_schedule_items(all_items) assert set(duplicates) == set([item1, item2, item4]) item4.page_id = page2.pk item4.talk_id = None item4.save() all_items = prefetch_schedule_items() duplicates = find_duplicate_schedule_items(all_items) assert set(duplicates) == set([item1, item2])
def test_non_contiguous(self): """Test that we detect items with non contiguous slots""" # Create a item with a gap in the slots assigned to it day1 = ScheduleBlock.objects.create( start_time=D.datetime(2013, 9, 22, 9, 0, 0, tzinfo=timezone.utc), end_time=D.datetime(2013, 9, 22, 19, 0, 0, tzinfo=timezone.utc)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue1.blocks.add(day1) start1 = D.datetime(2013, 9, 22, 10, 0, 0, tzinfo=timezone.utc) start2 = D.datetime(2013, 9, 22, 11, 0, 0, tzinfo=timezone.utc) start3 = D.datetime(2013, 9, 22, 12, 0, 0, tzinfo=timezone.utc) end = D.datetime(2013, 9, 22, 13, 0, 0, tzinfo=timezone.utc) slot1 = Slot.objects.create(start_time=start1, end_time=start2) slot2 = Slot.objects.create(start_time=start2, end_time=start3) slot3 = Slot.objects.create(start_time=start3, end_time=end) user = get_user_model().objects.create_user('john', '*****@*****.**', 'johnpassword') talk = Talk.objects.create(title="Test talk", status=ACCEPTED, corresponding_author_id=user.id) page = Page.objects.create(name="test page", slug="test") item1 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk) item1.slots.add(slot1) item1.slots.add(slot3) item2 = ScheduleItem.objects.create(venue=venue1, page_id=page.pk) item2.slots.add(slot2) all_items = prefetch_schedule_items() invalid = find_non_contiguous(all_items) # Only item1 is invalid assert set(invalid) == set([item1]) item1.slots.add(slot2) item1.slots.remove(slot1) item2.slots.add(slot1) item2.slots.remove(slot2) all_items = prefetch_schedule_items() invalid = validate_items(all_items) # Everything is valid now assert set(invalid) == set([])
def test_non_contiguous(self): """Test that we detect items with non contiguous slots""" # Create a item with a gap in the slots assigned to it day1 = Day.objects.create(date=D.date(2013, 9, 22)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue1.days.add(day1) start1 = D.time(10, 0, 0) start2 = D.time(11, 0, 0) start3 = D.time(12, 0, 0) end = D.time(13, 0, 0) slot1 = Slot.objects.create(start_time=start1, end_time=start2, day=day1) slot2 = Slot.objects.create(start_time=start2, end_time=start3, day=day1) slot3 = Slot.objects.create(start_time=start3, end_time=end, day=day1) user = get_user_model().objects.create_user('john', '*****@*****.**', 'johnpassword') talk = Talk.objects.create(title="Test talk", status=ACCEPTED, corresponding_author_id=user.id) page = Page.objects.create(name="test page", slug="test") item1 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk) item1.slots.add(slot1) item1.slots.add(slot3) item2 = ScheduleItem.objects.create(venue=venue1, page_id=page.pk) item2.slots.add(slot2) all_items = prefetch_schedule_items() invalid = find_non_contiguous(all_items) # Only item1 is invalid assert set(invalid) == set([item1]) item1.slots.add(slot2) item1.slots.remove(slot1) item2.slots.add(slot1) item2.slots.remove(slot2) all_items = prefetch_schedule_items() invalid = validate_items(all_items) # Everything is valid now assert set(invalid) == set([])
def test_validation(self): """Test that we detect validation errors correctly""" # Create a item with both a talk and a page assigned day1 = Day.objects.create(date=D.date(2013, 9, 22)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue1.days.add(day1) start1 = D.time(10, 0, 0) start2 = D.time(11, 0, 0) end = D.time(12, 0, 0) slot1 = Slot.objects.create(start_time=start1, end_time=start2, day=day1) slot2 = Slot.objects.create(start_time=start1, end_time=end, day=day1) user = get_user_model().objects.create_user('john', '*****@*****.**', 'johnpassword') talk = Talk.objects.create(title="Test talk", status=ACCEPTED, corresponding_author_id=user.id) page = Page.objects.create(name="test page", slug="test") item1 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk, page_id=page.pk) item1.slots.add(slot1) all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1]) item2 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk) item2.slots.add(slot2) # Test talk status talk.status = REJECTED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item2]) talk.status = SUBMITTED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item2]) talk.status = CANCELLED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1]) talk.status = UNDER_CONSIDERATION talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item2]) talk.status = ACCEPTED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1]) item3 = ScheduleItem.objects.create(venue=venue1, talk_id=None, page_id=None) item3.slots.add(slot2) all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item3])
def test_clashes(self): """Test that we can detect clashes correctly""" day1 = Day.objects.create(date=D.date(2013, 9, 22)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue2 = Venue.objects.create(order=2, name='Venue 2') venue1.days.add(day1) venue2.days.add(day1) start1 = D.time(10, 0, 0) start2 = D.time(11, 0, 0) end = D.time(12, 0, 0) slot1 = Slot.objects.create(start_time=start1, end_time=start2, day=day1) slot2 = Slot.objects.create(start_time=start2, end_time=end, day=day1) item1 = ScheduleItem.objects.create(venue=venue1, details="Item 1") item2 = ScheduleItem.objects.create(venue=venue1, details="Item 2") # Create a simple venue/slot clash item1.slots.add(slot1) item2.slots.add(slot1) all_items = prefetch_schedule_items() # Needs to be an explicit list, not a generator on python 3 here clashes = list(find_clashes(all_items)) assert len(clashes) == 1 pos = (venue1, slot1) assert pos == clashes[0][0] assert item1 in clashes[0][1] assert item2 in clashes[0][1] # Create a overlapping clashes item2.slots.remove(slot1) item1.slots.add(slot2) item2.slots.add(slot2) all_items = prefetch_schedule_items() clashes = list(find_clashes(all_items)) assert len(clashes) == 1 pos = (venue1, slot2) assert pos == clashes[0][0] assert item1 in clashes[0][1] assert item2 in clashes[0][1] # Add a clash in a second venue item3 = ScheduleItem.objects.create(venue=venue2, details="Item 3") item4 = ScheduleItem.objects.create(venue=venue2, details="Item 4") item3.slots.add(slot2) item4.slots.add(slot2) all_items = prefetch_schedule_items() clashes = list(find_clashes(all_items)) assert len(clashes) == 2 pos = (venue2, slot2) assert pos in [x[0] for x in clashes] clash_items = [] for sublist in clashes: if sublist[0] == pos: clash_items.extend(sublist[1]) assert item3 in clash_items assert item4 in clash_items # Fix clashes item1.slots.remove(slot2) item3.slots.remove(slot2) item3.slots.add(slot1) all_items = prefetch_schedule_items() clashes = find_clashes(all_items) assert len(clashes) == 0
def test_venues(self): """Test that we detect venues violating the day constraints correctly.""" day1 = ScheduleBlock.objects.create( start_time=D.datetime(2013, 9, 22, 9, 0, 0, tzinfo=timezone.utc), end_time=D.datetime(2013, 9, 22, 19, 0, 0, tzinfo=timezone.utc)) day2 = ScheduleBlock.objects.create( start_time=D.datetime(2013, 9, 23, 9, 0, 0, tzinfo=timezone.utc), end_time=D.datetime(2013, 9, 23, 19, 0, 0, tzinfo=timezone.utc)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue2 = Venue.objects.create(order=2, name='Venue 2') venue1.blocks.add(day1) venue2.blocks.add(day2) start1 = D.datetime(2013, 9, 22, 10, 0, 0, tzinfo=timezone.utc) start2 = D.datetime(2013, 9, 22, 11, 0, 0, tzinfo=timezone.utc) slot1 = Slot.objects.create(start_time=start1, end_time=start2) page = Page.objects.create(name="test page", slug="test") item1 = ScheduleItem.objects.create(venue=venue1, page_id=page.pk) item1.slots.add(slot1) item2 = ScheduleItem.objects.create(venue=venue2, page_id=page.pk) item2.slots.add(slot1) all_items = prefetch_schedule_items() # Needs to be an explicit list, as in the find_clashes test venues = list(find_invalid_venues(all_items)) assert venues[0][0] == venue2 assert set(venues[0][1]) == set([item2]) start1d2 = D.datetime(2013, 9, 23, 10, 0, 0, tzinfo=timezone.utc) start2d2 = D.datetime(2013, 9, 23, 11, 0, 0, tzinfo=timezone.utc) slot2 = Slot.objects.create(start_time=start1d2, end_time=start2d2) item3 = ScheduleItem.objects.create(venue=venue2, page_id=page.pk) item3.slots.add(slot2) all_items = prefetch_schedule_items() venues = list(find_invalid_venues(all_items)) assert venues[0][0] == venue2 assert set(venues[0][1]) == set([item2]) item4 = ScheduleItem.objects.create(venue=venue1, page_id=page.pk) item5 = ScheduleItem.objects.create(venue=venue2, page_id=page.pk) item4.slots.add(slot2) item5.slots.add(slot1) all_items = prefetch_schedule_items() venues = list(find_invalid_venues(all_items)) assert set([x[0] for x in venues]) == set([venue1, venue2]) venue_1_items = [] venue_2_items = [] for sublist in venues: if sublist[0] == venue1: venue_1_items.extend(sublist[1]) elif sublist[0] == venue2: venue_2_items.extend(sublist[1]) assert set(venue_1_items) == set([item4]) assert set(venue_2_items) == set([item2, item5])
def test_validation(self): """Test that we detect validation errors correctly""" # Create a item with both a talk and a page assigned day1 = Day.objects.create(date=D.date(2013, 9, 22)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue1.days.add(day1) start1 = D.time(10, 0, 0) start2 = D.time(11, 0, 0) end = D.time(12, 0, 0) slot1 = Slot.objects.create(start_time=start1, end_time=start2, day=day1) slot2 = Slot.objects.create(start_time=start1, end_time=end, day=day1) user = get_user_model().objects.create_user('john', '*****@*****.**', 'johnpassword') talk = Talk.objects.create(title="Test talk", status=ACCEPTED, corresponding_author_id=user.id) page = Page.objects.create(name="test page", slug="test") item1 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk, page_id=page.pk) item1.slots.add(slot1) all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1]) item2 = ScheduleItem.objects.create(venue=venue1, talk_id=talk.pk) item2.slots.add(slot2) # Test talk status talk.status = REJECTED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item2]) talk.status = SUBMITTED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item2]) talk.status = CANCELLED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1]) talk.status = UNDER_CONSIDERATION talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item2]) talk.status = ACCEPTED talk.save() all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1]) item3 = ScheduleItem.objects.create(venue=venue1, talk_id=None, page_id=None) item3.slots.add(slot2) all_items = prefetch_schedule_items() invalid = validate_items(all_items) assert set(invalid) == set([item1, item3])
def test_clashes(self): """Test that we can detect clashes correctly""" day1 = Day.objects.create(date=D.date(2013, 9, 22)) venue1 = Venue.objects.create(order=1, name='Venue 1') venue2 = Venue.objects.create(order=2, name='Venue 2') venue1.days.add(day1) venue2.days.add(day1) start1 = D.time(10, 0, 0) start2 = D.time(11, 0, 0) end = D.time(12, 0, 0) slot1 = Slot.objects.create(start_time=start1, end_time=start2, day=day1) slot2 = Slot.objects.create(start_time=start2, end_time=end, day=day1) item1 = ScheduleItem.objects.create(venue=venue1, details="Item 1") item2 = ScheduleItem.objects.create(venue=venue1, details="Item 2") # Create a simple venue/slot clash item1.slots.add(slot1) item2.slots.add(slot1) all_items = prefetch_schedule_items() # Needs to be an explicit list, not a generator on python 3 here clashes = list(find_clashes(all_items)) assert len(clashes) == 1 pos = (venue1, slot1) assert pos == clashes[0][0] assert item1 in clashes[0][1] assert item2 in clashes[0][1] # Create a overlapping clashes item2.slots.remove(slot1) item1.slots.add(slot2) item2.slots.add(slot2) all_items = prefetch_schedule_items() clashes = list(find_clashes(all_items)) assert len(clashes) == 1 pos = (venue1, slot2) assert pos == clashes[0][0] assert item1 in clashes[0][1] assert item2 in clashes[0][1] # Add a clash in a second venue item3 = ScheduleItem.objects.create(venue=venue2, details="Item 3") item4 = ScheduleItem.objects.create(venue=venue2, details="Item 4") item3.slots.add(slot2) item4.slots.add(slot2) all_items = prefetch_schedule_items() clashes = list(find_clashes(all_items)) assert len(clashes) == 2 pos = (venue2, slot2) assert pos in [x[0] for x in clashes] clash_items = [] for sublist in clashes: if sublist[0] == pos: clash_items.extend(sublist[1]) assert item3 in clash_items assert item4 in clash_items # Fix clashes item1.slots.remove(slot2) item3.slots.remove(slot2) item3.slots.add(slot1) all_items = prefetch_schedule_items() clashes = find_clashes(all_items) assert len(clashes) == 0