def get_data_three_hours_before(self): """Data to simulate the reminder sent 3 hours before the live starts.""" video = VideoFactory( live_state=IDLE, live_type=RAW, starting_at=timezone.now() + timedelta(hours=2), ) # registration has been created 26 hours ago (>1day) LiveRegistrationFactory( anonymous_id=uuid.uuid4(), created_on=timezone.now() - timedelta(hours=26), email="*****@*****.**", is_registered=True, should_send_reminders=True, video=video, ) # LTI registration with reminder 3 sent LiveRegistrationFactory( consumer_site=video.playlist.consumer_site, created_on=timezone.now() - timedelta(hours=26), email="*****@*****.**", is_registered=True, should_send_reminders=True, lti_id="Maths", lti_user_id="56255f3807599c377bf0e5bf072359fd", reminders=[settings.REMINDER_3], username="******", video=video, )
def get_data_three_days_before(self): """Data to simulate the reminder sent 3 days before the live starts""" video = VideoFactory( live_state=IDLE, live_type=RAW, starting_at=timezone.now() + timedelta(days=2), ) # registration has been created 32 days agp (>30 days) LiveRegistrationFactory( anonymous_id=uuid.uuid4(), created_on=timezone.now() - timedelta(days=32), email="*****@*****.**", is_registered=True, should_send_reminders=True, video=video, ) # LTI registration LiveRegistrationFactory( consumer_site=video.playlist.consumer_site, created_on=timezone.now() - timedelta(days=32), email="*****@*****.**", is_registered=True, should_send_reminders=True, lti_id="Maths", lti_user_id="56255f3807599c377bf0e5bf072359fd", username="******", video=video, )
def get_data_already_started(self): """Data to simulate reminder sent when live is already started.""" video = VideoFactory( live_state=RUNNING, live_type=RAW, starting_at=timezone.now() + timedelta(days=10), ) LiveRegistrationFactory( anonymous_id=uuid.uuid4(), email="*****@*****.**", is_registered=True, should_send_reminders=True, video=video, ) # LTI registration with other reminders sent LiveRegistrationFactory( consumer_site=video.playlist.consumer_site, email="*****@*****.**", is_registered=True, should_send_reminders=True, lti_id="Maths", lti_user_id="56255f3807599c377bf0e5bf072359fd", reminders=[ settings.REMINDER_1, settings.REMINDER_2, settings.REMINDER_3 ], username="******", video=video, )
def get_data_video_date_updated(self): """ Data to simulate the reminder sent when video had its starting date updated """ video = VideoFactory( live_state=IDLE, live_type=RAW, starting_at=timezone.now() + timedelta(days=2), ) LiveSessionFactory( anonymous_id=uuid.uuid4(), created_on=timezone.now() - timedelta(hours=1), email="*****@*****.**", must_notify=[settings.REMINDER_DATE_UPDATED], is_registered=True, should_send_reminders=True, video=video, ) # LTI registration LiveSessionFactory( consumer_site=video.playlist.consumer_site, created_on=timezone.now() - timedelta(hours=1), email="*****@*****.**", is_registered=True, must_notify=[settings.REMINDER_DATE_UPDATED], lti_id="Maths", lti_user_id="56255f3807599c377bf0e5bf072359fu", should_send_reminders=True, username="******", video=video, ) # french LiveSessionFactory( consumer_site=video.playlist.consumer_site, created_on=timezone.now() - timedelta(hours=1), email="*****@*****.**", is_registered=True, language="fr", lti_id="Maths", lti_user_id="36255f3807599c377bf0e5bf072359fu", must_notify=[settings.REMINDER_DATE_UPDATED], should_send_reminders=True, username="******", video=video, )
def test_send_video_to_simple_user(self): """A message containing serialized video is dispatched to the regular group.""" video = VideoFactory() channel_layer = get_channel_layer() async_to_sync(channel_layer.group_add)( VIDEO_ROOM_NAME.format(video_id=str(video.id)), "test_channel") channel_layers_utils.dispatch_video(video, to_admin=False) message = async_to_sync(channel_layer.receive)("test_channel") self.assertEqual(message["type"], "video_updated") self.assertEqual( message["video"], VideoSerializer(video, context={ "is_admin": False }).data)
def get_data_five_minutes_before(self): """Data to simulate the reminder sent 5 minutes before the live starts.""" video = VideoFactory( live_state=IDLE, live_type=RAW, starting_at=timezone.now() + timedelta(minutes=4), ) # registration has been created 4 hours ago LiveSessionFactory( anonymous_id=uuid.uuid4(), created_on=timezone.now() - timedelta(hours=4), email="*****@*****.**", is_registered=True, should_send_reminders=True, video=video, ) # LTI registration with other reminders sent LiveSessionFactory( consumer_site=video.playlist.consumer_site, created_on=timezone.now() - timedelta(hours=10), email="*****@*****.**", is_registered=True, should_send_reminders=True, lti_id="Maths", lti_user_id="56255f3807599c377bf0e5bf07235955", reminders=[settings.REMINDER_2, settings.REMINDER_3], username="******", video=video, ) # french LiveSessionFactory( consumer_site=video.playlist.consumer_site, created_on=timezone.now() - timedelta(hours=10), email="*****@*****.**", is_registered=True, language="fr", lti_id="Maths", lti_user_id="26255f3807599c377bf0e5bf07235555", reminders=[settings.REMINDER_2, settings.REMINDER_3], should_send_reminders=True, username="******", video=video, )
def _get_video(self, **kwargs): """Create a video using VideoFactory""" return VideoFactory(**kwargs)
def test_lti_select(page: Page, live_server: LiveServer): """Test LTI select.""" lti_consumer_parameters = { "roles": random.choice(["instructor", "administrator"]), "content_item_return_url": f"{live_server.url}/development/", "context_id": "sent_lti_context_id", "lti_message_type": "ContentItemSelectionRequest", "lti_version": "LTI-1p0", } lti_parameters, passport = generate_passport_and_signed_lti_parameters( url=f"{live_server.url}/lti/select/", lti_parameters=lti_consumer_parameters, ) resolutions = [144] playlist = PlaylistFactory( lti_id=lti_parameters.get("context_id"), consumer_site=passport.consumer_site, ) video = VideoFactory( playlist=playlist, uploaded_on=timezone.now(), resolutions=resolutions, ) document = DocumentFactory( playlist=playlist, uploaded_on=timezone.now(), ) page.goto(f"{live_server.url}/development/") lti_select_form = page.query_selector("#lti_select") for key, value in lti_parameters.items(): if key in ("roles", ): lti_select_form.query_selector( f'select[name="{key}"]').select_option(value) else: lti_select_form.query_selector(f'input[name="{key}"]').fill(value) page.click('#lti_select input[type="submit"]') lti_select_iframe = page.frame("lti_select") # Select a document lti_select_iframe.click('button[role="tab"]:has-text("Documents")') document_content_items = (json.dumps({ "@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem", "@graph": [{ "@type": "ContentItem", "url": f"{live_server.url}/lti/documents/{document.id}", "title": f"{document.title}", "frame": [], }], }).replace(", ", ",").replace(": ", ":")) assert document_content_items not in lti_select_iframe.content() with page.expect_request("**/lti/respond/"): lti_select_iframe.click(f'[title="Select {document.title}"]') lti_select_iframe.wait_for_selector("dd") assert document_content_items in lti_select_iframe.content() # Select a video page.click('#lti_select input[type="submit"]') lti_select_iframe.click('button[role="tab"]:has-text("Videos")') video_content_items = (json.dumps({ "@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem", "@graph": [{ "@type": "ContentItem", "url": f"{live_server}/lti/videos/{video.id}", "title": f"{video.title}", "frame": [], }], }).replace(", ", ",").replace(": ", ":")) assert video_content_items not in lti_select_iframe.content() with page.expect_request("**/lti/respond/"): lti_select_iframe.click(f'[title="Select {video.title}"]') lti_select_iframe.wait_for_selector("dd") assert video_content_items in lti_select_iframe.content() assert Video.objects.count() == 1
def _preview_video(live_server, page, video_uploaded=False): """Fill form to open video in a new page.""" # uncomment to log requests # page.on( # "request", # lambda request: print(">>", request.method, request.url, request.post_data), # ) # page.on("response", lambda response: print("<<", response.status, response.url)) # uncomment to print console logs # page.on("console", lambda msg: print(msg.text)) page.set_viewport_size({"width": 1200, "height": 1200}) resource_id = uuid.uuid4() context_id = "sent_lti_context_id" passport_attributes = {} video = None if video_uploaded: video = VideoFactory( uploaded_on=timezone.now(), resolutions=settings.VIDEO_RESOLUTIONS, upload_state=READY, ) resource_id = video.id context_id = video.playlist.lti_id passport_attributes = {"consumer_site": video.playlist.consumer_site} lti_consumer_parameters = { "uuid": str(resource_id), "resource_link_id": "example.com-df7", "context_id": context_id, "roles": random.choice(["instructor", "administrator"]), "resource": "videos", "user_id": "56255f3807599c377bf0e5bf072359fd", "lis_person_contact_email_primary": "*****@*****.**", "custom_component_display_name": "LTI Consumer", "lti_version": "LTI-1p0", "lis_person_sourcedid": "John", "lis_person_name_full": "John Doe", "lti_message_type": "basic-lti-launch-request", "launch_presentation_return_url": "", "lis_result_sourcedid": "course-v1%3Aufr%2Bmathematics%2B0001:" "example.com-df7b0f2886f04b279854585735a402c4:" "56255f3807599c377bf0e5bf072359fd", "launch_presentation_locale": "en", } lti_parameters, _passport = generate_passport_and_signed_lti_parameters( url=f"{live_server.url}/lti/videos/{resource_id}", lti_parameters=lti_consumer_parameters, passport_attributes=passport_attributes, ) page.goto(f"{live_server.url}/development/") lti_resource_page_form = page.query_selector("#lti_resource_page") for key, value in lti_parameters.items(): if key in ( "custom_component_display_name", "lti_version", "lis_person_name_full", "lti_message_type", "launch_presentation_return_url", "lis_result_sourcedid", "launch_presentation_locale", ): continue if key in ( "resource", "roles", ): lti_resource_page_form.query_selector( f'select[name="{key}"]').select_option(value, timeout=100) else: lti_resource_page_form.query_selector(f'input[name="{key}"]').fill( value, timeout=100) page.click('#lti_resource_page input[type="submit"]') if not video_uploaded: page.wait_for_selector("text=There is currently no video to display.") return page, video
def test_lti_select_default_title_no_text(page: Page, live_server: LiveServer): """When the request has a default title don't use it in the created resource, and send the ressource title in the LTI response.""" lti_consumer_parameters = { "roles": random.choice(["instructor", "administrator"]), "content_item_return_url": f"{live_server.url}/development/", "context_id": "sent_lti_context_id", "lti_message_type": "ContentItemSelectionRequest", "lti_version": "LTI-1p0", "title": settings.LTI_CONFIG_TITLE, "text": "", } lti_parameters, passport = generate_passport_and_signed_lti_parameters( url=f"{live_server.url}/lti/select/", lti_parameters=lti_consumer_parameters, ) resolutions = [144] playlist = PlaylistFactory( lti_id=lti_parameters.get("context_id"), consumer_site=passport.consumer_site, ) video = VideoFactory( playlist=playlist, uploaded_on=timezone.now(), resolutions=resolutions, ) document = DocumentFactory( description="Document description", playlist=playlist, uploaded_on=timezone.now(), ) page.goto(f"{live_server.url}/development/") lti_select_form = page.query_selector("#lti_select") for key, value in lti_parameters.items(): if key in ("roles", ): lti_select_form.query_selector( f'select[name="{key}"]').select_option(value) else: lti_select_form.query_selector(f'input[name="{key}"]').fill(value) page.click('#lti_select input[type="submit"]') lti_select_iframe = page.frame("lti_select") # Select a document lti_select_iframe.click('button[role="tab"]:has-text("Documents")') # Use the document title and description in the response to fill the activity title and text document_content_items = (json.dumps({ "@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem", "@graph": [{ "@type": "ContentItem", "url": f"{live_server.url}/lti/documents/{document.id}", "frame": [], "title": document.title, "text": document.description, }], }).replace(", ", ",").replace(": ", ":")) assert document_content_items not in lti_select_iframe.content() with page.expect_request("**/lti/respond/"): lti_select_iframe.click(f'[title="Select {document.title}"]') lti_select_iframe.wait_for_selector("dd") assert document_content_items in lti_select_iframe.content() # Select a video page.click('#lti_select input[type="submit"]') lti_select_iframe.click('button[role="tab"]:has-text("Videos")') # Use the video title and description in the response to fill the activity title and text video_content_items = (json.dumps({ "@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem", "@graph": [{ "@type": "ContentItem", "url": f"{live_server}/lti/videos/{video.id}", "frame": [], "title": video.title, "text": video.description, }], }).replace(", ", ",").replace(": ", ":")) assert video_content_items not in lti_select_iframe.content() with page.expect_request("**/lti/respond/"): lti_select_iframe.click(f'[title="Select {video.title}"]') lti_select_iframe.wait_for_selector("dd") assert video_content_items in lti_select_iframe.content() assert Video.objects.count() == 1 # Select a new video page.click('#lti_select input[type="submit"]') lti_select_iframe.click('button[role="tab"]:has-text("Videos")') sent_title = f'"title":"{lti_consumer_parameters.get("title")}"' assert sent_title not in lti_select_iframe.content() with page.expect_request("**/lti/respond/"): lti_select_iframe.click("text=Add a video") lti_select_iframe.wait_for_selector("dd") # added video is created assert Video.objects.count() == 2 added_video = Video.objects.exclude(id=video.id).first() assert added_video.title != lti_consumer_parameters.get("title") assert added_video.description == lti_consumer_parameters.get("text") # Don't send title nor text in the response video_content_items = (json.dumps({ "@context": "http://purl.imsglobal.org/ctx/lti/v1/ContentItem", "@graph": [{ "@type": "ContentItem", "url": f"{live_server}/lti/videos/{added_video.id}", "frame": [], }], }).replace(", ", ",").replace(": ", ":")) assert video_content_items in lti_select_iframe.content()