class SelectLTIViewTestCase(TestCase):
    """Test the select LTI view in the ``core`` app of the Marsha project."""

    maxDiff = None

    @override_settings({{cookiecutter.setting_name}}=True)
    def test_views_lti_select_{{cookiecutter.app_name}}_enabled(self):
        """Frontend context flag should be enabled when flag is enabled."""
        lti_consumer_parameters = {
            "roles": random.choice(["instructor", "administrator"]),
            "content_item_return_url": "https://lti-consumer.site/lti",
            "context_id": "sent_lti_context_id",
        }
        lti_parameters, _ = generate_passport_and_signed_lti_parameters(
            url="http://testserver/lti/select/",
            lti_parameters=lti_consumer_parameters,
        )

        response = self.client.post(
            "/lti/select/",
            lti_parameters,
            HTTP_REFERER="http://testserver",
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "<html>")

        match = re.search(
            '<div id="marsha-frontend-data" data-context="(.*)">',
            response.content.decode("utf-8"),
        )
        context = json.loads(unescape(match.group(1)))

        self.assertTrue(context.get("flags").get("{{ cookiecutter.app_name }}"))
    def test_views_lti_select_bbb_disabled(self):
        """Frontend context flag should be disabled when flag is disabled."""
        lti_consumer_parameters = {
            "roles": random.choice(["instructor", "administrator"]),
            "content_item_return_url": "https://lti-consumer.site/lti",
            "context_id": "sent_lti_context_id",
        }
        lti_parameters, _ = generate_passport_and_signed_lti_parameters(
            url="http://testserver/lti/select/",
            lti_parameters=lti_consumer_parameters,
        )

        response = self.client.post(
            "/lti/select/",
            lti_parameters,
            HTTP_REFERER="http://testserver",
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "<html>")

        match = re.search(
            '<div id="marsha-frontend-data" data-context="(.*)">',
            response.content.decode("utf-8"),
        )
        context = json.loads(unescape(match.group(1)))

        self.assertFalse(context.get("flags").get("BBB"))
Exemple #3
0
def test_lti_select_bbb_disabled(page: Page, live_server: LiveServer,
                                 settings):
    """When BBB flag is disabled, classrooms are not selectable."""
    settings.BBB_ENABLED = False
    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,
    )

    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")

    lti_select_iframe.wait_for_selector(
        "button[role='tab']:has-text('Classrooms')", state="hidden")
Exemple #4
0
def test_lti_playlist_portability_video(page: Page, live_server: LiveServer):
    """Test LTI playlist portability."""
    page, video = _preview_video(live_server, page, video_uploaded=True)

    new_playlist = PlaylistFactory(consumer_site=video.consumer_site, )

    page.click("text=Playlist")

    content = page.text_content("[role=heading]")
    assert (
        content ==
        f"Belongs to playlist {video.playlist.title} ({video.playlist.id})")
    page.fill('[placeholder="Paste playlist id"]', str(new_playlist.id))

    page.click('[aria-label="add share"]')

    # wait for request done
    with page.expect_response(f"**/api/playlists/{video.playlist.id}/"):
        print("put done")

    assert video.playlist.portable_to.get(id=new_playlist.id)
    page.text_content(f"[aria-label='Shared with {new_playlist.title}']")
    page.text_content('[role="status"]:has-text("Playlist updated")')

    # go to new_playlist LTI select view
    lti_consumer_parameters = {
        "roles": random.choice(["instructor", "administrator"]),
        "content_item_return_url": f"{live_server.url}/development/",
        "context_id": new_playlist.lti_id,
        "lti_message_type": "ContentItemSelectionRequest",
        "lti_version": "LTI-1p0",
        "title": "",
        "text": "",
    }
    lti_parameters, passport = generate_passport_and_signed_lti_parameters(
        url=f"{live_server.url}/lti/select/",
        lti_parameters=lti_consumer_parameters,
        passport_attributes={"consumer_site": video.playlist.consumer_site},
    )

    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"]')

    # ensure video is available in new_playlist
    lti_select_iframe = page.frame("lti_select")
    lti_select_iframe.click('button[role="tab"]:has-text("Videos")')
    lti_select_iframe.text_content(f'[title="Select {video.title}"]')
Exemple #5
0
def test_lti_select_bbb_enabled(page: Page, live_server: LiveServer, settings):
    """Test LTI select."""
    settings.BBB_ENABLED = True
    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,
    )

    playlist = PlaylistFactory(
        lti_id=lti_parameters.get("context_id"),
        consumer_site=passport.consumer_site,
    )
    meeting = MeetingFactory(playlist=playlist, )

    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 meeting
    lti_select_iframe.click('button[role="tab"]:has-text("Meetings")')
    meeting_content_items = (json.dumps({
        "@context":
        "http://purl.imsglobal.org/ctx/lti/v1/ContentItem",
        "@graph": [{
            "@type": "ContentItem",
            "url": f"{live_server.url}/lti/meetings/{meeting.id}",
            "title": f"{meeting.title}",
            "frame": [],
        }],
    }).replace(", ", ",").replace(": ", ":"))
    assert meeting_content_items not in lti_select_iframe.content()
    with page.expect_request("**/lti/respond/"):
        lti_select_iframe.click(f'[title="Select {meeting.title}"]')
    lti_select_iframe.wait_for_selector("dd")
    assert meeting_content_items in lti_select_iframe.content()
            response.content.decode("utf-8"),
        )
        context = json.loads(unescape(match.group(1)))

        self.assertTrue(context.get("flags").get("{{ cookiecutter.app_name }}"))

    @override_settings({{cookiecutter.setting_name}}=False)
    def test_views_lti_select_{{cookiecutter.app_name}}_disabled(self):
        """Frontend context flag should be disabled when flag is disabled."""
        lti_consumer_parameters = {
            "roles": random.choice(["instructor", "administrator"]),
            "content_item_return_url": "https://lti-consumer.site/lti",
            "context_id": "sent_lti_context_id",
        }
        lti_parameters, _ = generate_passport_and_signed_lti_parameters(
            url="http://testserver/lti/select/",
            lti_parameters=lti_consumer_parameters,
        )

        response = self.client.post(
            "/lti/select/",
            lti_parameters,
            HTTP_REFERER="http://testserver",
        )
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "<html>")

        match = re.search(
            '<div id="marsha-frontend-data" data-context="(.*)">',
            response.content.decode("utf-8"),
        )
        context = json.loads(unescape(match.group(1)))
Exemple #7
0
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
Exemple #8
0
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
Exemple #9
0
def _preview_classroom(page: Page, live_server: LiveServer):
    """Fill form to open resource 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))

    page.set_viewport_size({"width": 1200, "height": 1200})

    classroom_id = uuid.uuid4()
    context_id = "sent_lti_context_id"
    passport_attributes = {}

    lti_consumer_parameters = {
        "uuid":
        str(classroom_id),
        "resource_link_id":
        "example.com-df7",
        "context_id":
        context_id,
        "roles":
        random.choice(["instructor", "administrator"]),
        "resource":
        "classrooms",
        "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/classrooms/{classroom_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"]')

    return page, classroom_id
Exemple #10
0
def test_lti_select_bbb_enabled(page: Page, live_server: LiveServer, settings):
    """Test LTI select."""
    settings.BBB_ENABLED = True

    responses.add(
        responses.GET,
        "https://10.7.7.1/bigbluebutton/api/getMeetingInfo",
        body="""<response>
            <returncode>FAILED</returncode>
            <messageKey>notFound</messageKey>
            <message>We could not find a meeting with that meeting ID</message>
        </response>
        """,
        status=200,
    )

    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": "Sent LMS activity title",
        "text": "Sent LMS activity text",
    }
    lti_parameters, passport = generate_passport_and_signed_lti_parameters(
        url=f"{live_server.url}/lti/select/",
        lti_parameters=lti_consumer_parameters,
    )

    playlist = PlaylistFactory(
        lti_id=lti_parameters.get("context_id"),
        consumer_site=passport.consumer_site,
    )
    classroom = ClassroomFactory(playlist=playlist, )

    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 classroom
    lti_select_iframe.click('button[role="tab"]:has-text("Classrooms")')
    classroom_content_items = (json.dumps({
        "@context":
        "http://purl.imsglobal.org/ctx/lti/v1/ContentItem",
        "@graph": [{
            "@type": "ContentItem",
            "url": f"{live_server.url}/lti/classrooms/{classroom.id}",
            "frame": [],
            "title": lti_consumer_parameters.get("title"),
            "text": lti_consumer_parameters.get("text"),
        }],
    }).replace(", ", ",").replace(": ", ":"))
    assert classroom_content_items not in lti_select_iframe.content()
    with page.expect_request("**/lti/respond/"):
        lti_select_iframe.click(f'[title="Select {classroom.title}"]')
    lti_select_iframe.wait_for_selector("dd")
    assert classroom_content_items in lti_select_iframe.content()

    # Select a new classroom
    page.click('#lti_select input[type="submit"]')

    lti_select_iframe.click('button[role="tab"]:has-text("Classrooms")')
    sent_title_and_text = (f'"title":"{lti_consumer_parameters.get("title")}",'
                           f'"text":"{lti_consumer_parameters.get("text")}"')
    assert sent_title_and_text not in lti_select_iframe.content()
    with page.expect_request("**/lti/respond/"):
        lti_select_iframe.click("text=Add a classroom")
    lti_select_iframe.wait_for_selector("dd")

    # assert sent_title_and_text in lti_select_iframe.content()
    # assert Classroom.objects.count() == 1

    # added classroom is created
    assert Classroom.objects.count() == 2
    added_classroom = Classroom.objects.exclude(id=classroom.id).first()
    assert added_classroom.title == lti_consumer_parameters.get("title")
    assert added_classroom.description == lti_consumer_parameters.get("text")
    classroom_content_items = (json.dumps({
        "@context":
        "http://purl.imsglobal.org/ctx/lti/v1/ContentItem",
        "@graph": [{
            "@type": "ContentItem",
            "url": f"{live_server}/lti/classrooms/{added_classroom.id}",
            "frame": [],
            "title": lti_consumer_parameters.get("title"),
            "text": lti_consumer_parameters.get("text"),
        }],
    }).replace(", ", ",").replace(": ", ":"))
    assert classroom_content_items in lti_select_iframe.content()
Exemple #11
0
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()