|
48 | 48 | from ietf.meeting.test_data import make_meeting_test_data, make_interim_meeting, make_interim_test_data |
49 | 49 | from ietf.meeting.utils import condition_slide_order |
50 | 50 | from ietf.meeting.utils import add_event_info_to_session_qs, participants_for_meeting |
51 | | -from ietf.meeting.utils import create_recording, get_next_sequence, bluesheet_data |
| 51 | +from ietf.meeting.utils import create_recording, delete_recording, get_next_sequence, bluesheet_data |
52 | 52 | from ietf.meeting.views import session_draft_list, parse_agenda_filter_params, sessions_post_save, agenda_extract_schedule |
53 | 53 | from ietf.meeting.views import get_summary_by_area, get_summary_by_type, get_summary_by_purpose, generate_agenda_data |
54 | 54 | from ietf.name.models import SessionStatusName, ImportantDateName, RoleName, ProceedingsMaterialTypeName |
@@ -441,6 +441,48 @@ def test_session_recordings_via_factories(self): |
441 | 441 | self.assertIn(new_recording_title, links[0].text_content()) |
442 | 442 | #debug.show("q(f'#notes_and_recordings_{session_pk}')") |
443 | 443 |
|
| 444 | + def test_delete_recordings(self): |
| 445 | + # No user specified, active recording state |
| 446 | + sp = SessionPresentationFactory( |
| 447 | + document__type_id="recording", |
| 448 | + document__external_url="https://example.com/some-recording", |
| 449 | + document__states=[("recording", "active")], |
| 450 | + ) |
| 451 | + doc = sp.document |
| 452 | + doc.docevent_set.all().delete() # clear this out |
| 453 | + delete_recording(sp) |
| 454 | + self.assertFalse(SessionPresentation.objects.filter(pk=sp.pk).exists()) |
| 455 | + self.assertEqual(doc.get_state("recording").slug, "deleted", "recording state updated") |
| 456 | + self.assertEqual(doc.docevent_set.count(), 1, "one event added") |
| 457 | + event = doc.docevent_set.first() |
| 458 | + self.assertEqual(event.type, "changed_state", "event is a changed_state event") |
| 459 | + self.assertEqual(event.by.name, "(System)", "system user is responsible") |
| 460 | + |
| 461 | + # Specified user, no recording state |
| 462 | + sp = SessionPresentationFactory( |
| 463 | + document__type_id="recording", |
| 464 | + document__external_url="https://example.com/some-recording", |
| 465 | + document__states=[], |
| 466 | + ) |
| 467 | + doc = sp.document |
| 468 | + doc.docevent_set.all().delete() # clear this out |
| 469 | + user = PersonFactory() # naming matches the methods - user is a Person, not a User |
| 470 | + delete_recording(sp, user=user) |
| 471 | + self.assertFalse(SessionPresentation.objects.filter(pk=sp.pk).exists()) |
| 472 | + self.assertEqual(doc.get_state("recording").slug, "deleted", "recording state updated") |
| 473 | + self.assertEqual(doc.docevent_set.count(), 1, "one event added") |
| 474 | + event = doc.docevent_set.first() |
| 475 | + self.assertEqual(event.type, "changed_state", "event is a changed_state event") |
| 476 | + self.assertEqual(event.by, user, "user is responsible") |
| 477 | + |
| 478 | + # Document is not a recording |
| 479 | + sp = SessionPresentationFactory( |
| 480 | + document__type_id="draft", |
| 481 | + document__external_url="https://example.com/some-recording", |
| 482 | + ) |
| 483 | + with self.assertRaises(ValueError): |
| 484 | + delete_recording(sp) |
| 485 | + |
444 | 486 | def test_agenda_ical_next_meeting_type(self): |
445 | 487 | # start with no upcoming IETF meetings, just an interim |
446 | 488 | MeetingFactory( |
@@ -7363,6 +7405,118 @@ def test_request_minutes(self): |
7363 | 7405 | self.assertEqual(r.status_code,302) |
7364 | 7406 | self.assertEqual(len(outbox),1) |
7365 | 7407 |
|
| 7408 | + @override_settings(YOUTUBE_DOMAINS=["youtube.com"]) |
| 7409 | + def test_add_session_recordings(self): |
| 7410 | + session = SessionFactory(meeting__type_id="ietf") |
| 7411 | + url = urlreverse( |
| 7412 | + "ietf.meeting.views.add_session_recordings", |
| 7413 | + kwargs={"session_id": session.pk, "num": session.meeting.number}, |
| 7414 | + ) |
| 7415 | + # does not fully validate authorization for non-secretariat users :-( |
| 7416 | + login_testing_unauthorized(self, "secretary", url) |
| 7417 | + r = self.client.get(url) |
| 7418 | + pq = PyQuery(r.content) |
| 7419 | + title_input = pq("input#id_title") |
| 7420 | + self.assertIsNotNone(title_input) |
| 7421 | + self.assertEqual( |
| 7422 | + title_input.attr.value, |
| 7423 | + "Video recording of {acro} for {timestamp}".format( |
| 7424 | + acro=session.group.acronym, |
| 7425 | + timestamp=session.official_timeslotassignment().timeslot.utc_start_time().strftime( |
| 7426 | + "%Y-%m-%d %H:%M" |
| 7427 | + ), |
| 7428 | + ), |
| 7429 | + ) |
| 7430 | + |
| 7431 | + with patch("ietf.meeting.views.create_recording") as mock_create: |
| 7432 | + r = self.client.post( |
| 7433 | + url, |
| 7434 | + data={ |
| 7435 | + "title": "This is my video title", |
| 7436 | + "url": "", |
| 7437 | + } |
| 7438 | + ) |
| 7439 | + self.assertFalse(mock_create.called) |
| 7440 | + |
| 7441 | + with patch("ietf.meeting.views.create_recording") as mock_create: |
| 7442 | + r = self.client.post( |
| 7443 | + url, |
| 7444 | + data={ |
| 7445 | + "title": "This is my video title", |
| 7446 | + "url": "https://yubtub.com/this-is-not-a-youtube-video", |
| 7447 | + } |
| 7448 | + ) |
| 7449 | + self.assertFalse(mock_create.called) |
| 7450 | + |
| 7451 | + with patch("ietf.meeting.views.create_recording") as mock_create: |
| 7452 | + r = self.client.post( |
| 7453 | + url, |
| 7454 | + data={ |
| 7455 | + "title": "This is my video title", |
| 7456 | + "url": "https://youtube.com/finally-a-video", |
| 7457 | + } |
| 7458 | + ) |
| 7459 | + self.assertTrue(mock_create.called) |
| 7460 | + self.assertEqual( |
| 7461 | + mock_create.call_args, |
| 7462 | + call( |
| 7463 | + session, |
| 7464 | + "https://youtube.com/finally-a-video", |
| 7465 | + title="This is my video title", |
| 7466 | + user=Person.objects.get(user__username="secretary"), |
| 7467 | + ), |
| 7468 | + ) |
| 7469 | + |
| 7470 | + # CAN delete session presentation for this session |
| 7471 | + sp = SessionPresentationFactory( |
| 7472 | + session=session, |
| 7473 | + document__type_id="recording", |
| 7474 | + document__external_url="https://example.com/some-video", |
| 7475 | + ) |
| 7476 | + with patch("ietf.meeting.views.delete_recording") as mock_delete: |
| 7477 | + r = self.client.post( |
| 7478 | + url, |
| 7479 | + data={ |
| 7480 | + "delete": str(sp.pk), |
| 7481 | + } |
| 7482 | + ) |
| 7483 | + self.assertEqual(r.status_code, 200) |
| 7484 | + self.assertTrue(mock_delete.called) |
| 7485 | + self.assertEqual(mock_delete.call_args, call(sp)) |
| 7486 | + |
| 7487 | + # ValueError message from delete_recording does not reach the user |
| 7488 | + sp = SessionPresentationFactory( |
| 7489 | + session=session, |
| 7490 | + document__type_id="recording", |
| 7491 | + document__external_url="https://example.com/some-video", |
| 7492 | + ) |
| 7493 | + with patch("ietf.meeting.views.delete_recording", side_effect=ValueError("oh joy!")) as mock_delete: |
| 7494 | + r = self.client.post( |
| 7495 | + url, |
| 7496 | + data={ |
| 7497 | + "delete": str(sp.pk), |
| 7498 | + } |
| 7499 | + ) |
| 7500 | + self.assertTrue(mock_delete.called) |
| 7501 | + self.assertNotContains(r, "oh joy!", status_code=200) |
| 7502 | + |
| 7503 | + # CANNOT delete session presentation for a different session |
| 7504 | + sp_for_other_session = SessionPresentationFactory( |
| 7505 | + document__type_id="recording", |
| 7506 | + document__external_url="https://example.com/some-other-video", |
| 7507 | + ) |
| 7508 | + with patch("ietf.meeting.views.delete_recording") as mock_delete: |
| 7509 | + r = self.client.post( |
| 7510 | + url, |
| 7511 | + data={ |
| 7512 | + "delete": str(sp_for_other_session.pk), |
| 7513 | + } |
| 7514 | + ) |
| 7515 | + self.assertEqual(r.status_code, 404) |
| 7516 | + self.assertFalse(mock_delete.called) |
| 7517 | + |
| 7518 | + |
| 7519 | + |
7366 | 7520 | class HasMeetingsTests(TestCase): |
7367 | 7521 | settings_temp_path_overrides = TestCase.settings_temp_path_overrides + ['AGENDA_PATH'] |
7368 | 7522 |
|
|
0 commit comments