import datetime
import json
import unittest
import urllib.request
from unittest.mock import patch
from urllib.error import HTTPError, URLError
from django import template
from django.core.exceptions import ValidationError
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils.timezone import make_aware, now
from wagtail import blocks
from wagtail.embeds import oembed_providers
from wagtail.embeds.blocks import EmbedBlock, EmbedValue
from wagtail.embeds.embeds import get_embed, get_embed_hash
from wagtail.embeds.exceptions import (
EmbedNotFoundException,
EmbedUnsupportedProviderException,
)
from wagtail.embeds.finders import get_finders
from wagtail.embeds.finders.embedly import (
AccessDeniedEmbedlyException,
EmbedlyException,
)
from wagtail.embeds.finders.embedly import EmbedlyFinder as EmbedlyFinder
from wagtail.embeds.finders.facebook import AccessDeniedFacebookOEmbedException
from wagtail.embeds.finders.facebook import FacebookOEmbedFinder as FacebookOEmbedFinder
from wagtail.embeds.finders.instagram import AccessDeniedInstagramOEmbedException
from wagtail.embeds.finders.instagram import (
InstagramOEmbedFinder as InstagramOEmbedFinder,
)
from wagtail.embeds.finders.oembed import OEmbedFinder as OEmbedFinder
from wagtail.embeds.models import Embed
from wagtail.embeds.templatetags.wagtailembeds_tags import embed_tag
from wagtail.test.utils import WagtailTestUtils
try:
import embedly # noqa: F401
no_embedly = False
except ImportError:
no_embedly = True
class TestGetFinders(TestCase):
def test_defaults_to_oembed(self):
finders = get_finders()
self.assertEqual(len(finders), 1)
self.assertIsInstance(finders[0], OEmbedFinder)
# New WAGTAILEMBEDS_FINDERS setting
@override_settings(
WAGTAILEMBEDS_FINDERS=[{"class": "wagtail.embeds.finders.oembed"}]
)
def test_new_find_oembed(self):
finders = get_finders()
self.assertEqual(len(finders), 1)
self.assertIsInstance(finders[0], OEmbedFinder)
@override_settings(
WAGTAILEMBEDS_FINDERS=[
{
"class": "wagtail.embeds.finders.embedly",
"key": "foo",
}
]
)
def test_new_find_embedly(self):
finders = get_finders()
self.assertEqual(len(finders), 1)
self.assertIsInstance(finders[0], EmbedlyFinder)
self.assertEqual(finders[0].get_key(), "foo")
@override_settings(
WAGTAILEMBEDS_FINDERS=[
{"class": "wagtail.embeds.finders.oembed", "options": {"foo": "bar"}}
]
)
def test_new_find_oembed_with_options(self):
finders = get_finders()
self.assertEqual(len(finders), 1)
self.assertIsInstance(finders[0], OEmbedFinder)
self.assertEqual(finders[0].options, {"foo": "bar"})
@override_settings(
WAGTAILEMBEDS_FINDERS=[
{
"class": "wagtail.embeds.finders.instagram",
"app_id": "1234567890",
"app_secret": "abcdefghijklmnop",
},
]
)
def test_find_instagram_oembed_with_options(self):
finders = get_finders()
self.assertEqual(len(finders), 1)
self.assertIsInstance(finders[0], InstagramOEmbedFinder)
self.assertEqual(finders[0].app_id, "1234567890")
self.assertEqual(finders[0].app_secret, "abcdefghijklmnop")
# omitscript defaults to False
self.assertIs(finders[0].omitscript, False)
@override_settings(
WAGTAILEMBEDS_FINDERS=[
{
"class": "wagtail.embeds.finders.facebook",
"app_id": "1234567890",
"app_secret": "abcdefghijklmnop",
},
]
)
def test_find_facebook_oembed_with_options(self):
finders = get_finders()
self.assertEqual(len(finders), 1)
self.assertIsInstance(finders[0], FacebookOEmbedFinder)
self.assertEqual(finders[0].app_id, "1234567890")
self.assertEqual(finders[0].app_secret, "abcdefghijklmnop")
# omitscript defaults to False
self.assertIs(finders[0].omitscript, False)
class TestEmbeds(TestCase):
def setUp(self):
self.hit_count = 0
def dummy_finder(self, url, max_width=None, max_height=None):
# Up hit count
self.hit_count += 1
# Return a pretend record
return {
"title": "Test: " + url,
"type": "video",
"width": max_width if max_width else 640,
"height": 480,
"html": "
Blah blah blah
",
}
@override_settings(WAGTAILEMBEDS_RESPONSIVE_HTML=True)
def test_get_embed_responsive(self):
embed = get_embed("www.test.com/1234", max_width=400, finder=self.dummy_finder)
# Check that the embed is correct
self.assertEqual(embed.title, "Test: www.test.com/1234")
self.assertEqual(embed.type, "video")
self.assertEqual(embed.width, 400)
self.assertEqual(embed.thumbnail_url, "")
# Check ratio calculations
self.assertEqual(embed.ratio, 480 / 400)
self.assertEqual(embed.ratio_css, "120.0%")
self.assertTrue(embed.is_responsive)
# Check that there has only been one hit to the backend
self.assertEqual(self.hit_count, 1)
# Look for the same embed again and check the hit count hasn't increased
get_embed("www.test.com/1234", max_width=400, finder=self.dummy_finder)
self.assertEqual(self.hit_count, 1)
# Look for a different embed, hit count should increase
get_embed("www.test.com/4321", max_width=400, finder=self.dummy_finder)
self.assertEqual(self.hit_count, 2)
# Look for the same embed with a different width, this should also increase hit count
get_embed("www.test.com/4321", finder=self.dummy_finder)
self.assertEqual(self.hit_count, 3)
def test_get_embed_nonresponsive(self):
embed = get_embed("www.test.com/1234", max_width=400, finder=self.dummy_finder)
# Check that the embed is correct
self.assertEqual(embed.title, "Test: www.test.com/1234")
self.assertEqual(embed.type, "video")
self.assertEqual(embed.width, 400)
self.assertFalse(embed.is_responsive)
self.assertIsNone(embed.cache_until)
def dummy_cache_until_finder(self, url, max_width=None, max_height=None):
# Up hit count
self.hit_count += 1
# Return a pretend record
return {
"title": "Test: " + url,
"type": "video",
"width": max_width if max_width else 640,
"height": 480,
"html": "Blah blah blah
",
"cache_until": make_aware(datetime.datetime(2001, 2, 3)),
}
def test_get_embed_cache_until(self):
embed = get_embed(
"www.test.com/1234", max_width=400, finder=self.dummy_cache_until_finder
)
self.assertEqual(embed.cache_until, make_aware(datetime.datetime(2001, 2, 3)))
self.assertEqual(self.hit_count, 1)
# expired cache_until should be ignored
embed_2 = get_embed(
"www.test.com/1234", max_width=400, finder=self.dummy_cache_until_finder
)
self.assertEqual(self.hit_count, 2)
# future cache_until should not be ignored
future_dt = now() + datetime.timedelta(minutes=1)
embed.cache_until = future_dt
embed.save()
embed_3 = get_embed(
"www.test.com/1234", max_width=400, finder=self.dummy_cache_until_finder
)
self.assertEqual(self.hit_count, 2)
# ensure we've received the same embed
self.assertEqual(embed, embed_2)
self.assertEqual(embed, embed_3)
self.assertEqual(embed_3.cache_until, future_dt)
def dummy_finder_invalid_width(self, url, max_width=None, max_height=None):
# Return a record with an invalid width
return {
"title": "Test: " + url,
"type": "video",
"thumbnail_url": "",
"width": "100%",
"height": 480,
"html": "Blah blah blah
",
}
def test_invalid_width(self):
embed = get_embed(
"www.test.com/1234", max_width=400, finder=self.dummy_finder_invalid_width
)
# Width must be set to None
self.assertIsNone(embed.width)
def test_no_html(self):
def no_html_finder(url, max_width=None, max_height=None):
"""
A finder which returns everything but HTML
"""
embed = self.dummy_finder(url, max_width)
embed["html"] = None
return embed
embed = get_embed("www.test.com/1234", max_width=400, finder=no_html_finder)
self.assertEqual(embed.html, "")
@override_settings(WAGTAILEMBEDS_FINDERS=[])
def test_no_finders_available(self):
with self.assertRaises(EmbedUnsupportedProviderException):
get_embed("www.test.com/1234", max_width=400)
class TestEmbedHash(TestCase):
def test_get_embed_hash(self):
url = "www.test.com/1234"
self.assertEqual(get_embed_hash(url), "9a4cfc187266026cd68160b5db572629")
self.assertEqual(get_embed_hash(url, 0), "946fb9597a6c74ab3cef1699eff7fde7")
self.assertEqual(get_embed_hash(url, 1), "427830227a86093b50417e11dbd2f28e")
class TestChooser(WagtailTestUtils, TestCase):
def setUp(self):
# login
self.login()
def test_chooser(self):
r = self.client.get("/admin/embeds/chooser/")
self.assertEqual(r.status_code, 200)
def test_chooser_with_edit_params(self):
r = self.client.get("/admin/embeds/chooser/?url=http://example2.com")
self.assertEqual(r.status_code, 200)
response_json = json.loads(r.content.decode())
self.assertEqual(response_json["step"], "chooser")
self.assertIn('value="http://example2.com"', response_json["html"])
@patch("wagtail.embeds.embeds.get_embed")
def test_submit_valid_embed(self, get_embed):
get_embed.return_value = Embed(
html='
', title="An example embed"
)
response = self.client.post(
reverse("wagtailembeds:chooser_upload"),
{"embed-chooser-url": "http://www.example.com/"},
)
self.assertEqual(response.status_code, 200)
response_json = json.loads(response.content.decode())
self.assertEqual(response_json["step"], "embed_chosen")
self.assertEqual(response_json["embed_data"]["title"], "An example embed")
@patch("wagtail.embeds.embeds.get_embed")
def test_submit_unrecognised_embed(self, get_embed):
get_embed.side_effect = EmbedNotFoundException
response = self.client.post(
reverse("wagtailembeds:chooser_upload"),
{"embed-chooser-url": "http://www.example.com/"},
)
self.assertEqual(response.status_code, 200)
response_json = json.loads(response.content.decode())
self.assertEqual(response_json["step"], "chooser")
self.assertIn("Cannot find an embed for this URL.", response_json["html"])
class TestEmbedly(TestCase):
@unittest.skipIf(no_embedly, "Embedly is not installed")
def test_embedly_oembed_called_with_correct_arguments(self):
with patch("embedly.Embedly.oembed") as oembed:
oembed.return_value = {"type": "photo", "url": "http://www.example.com"}
EmbedlyFinder(key="foo").find_embed("http://www.example.com")
oembed.assert_called_with("http://www.example.com", better=False)
EmbedlyFinder(key="foo").find_embed("http://www.example.com", max_width=100)
oembed.assert_called_with(
"http://www.example.com", maxwidth=100, better=False
)
@unittest.skipIf(no_embedly, "Embedly is not installed")
def test_embedly_401(self):
with patch("embedly.Embedly.oembed") as oembed:
oembed.return_value = {
"type": "photo",
"url": "http://www.example.com",
"error": True,
"error_code": 401,
}
self.assertRaises(
AccessDeniedEmbedlyException,
EmbedlyFinder(key="foo").find_embed,
"http://www.example.com",
)
@unittest.skipIf(no_embedly, "Embedly is not installed")
def test_embedly_403(self):
with patch("embedly.Embedly.oembed") as oembed:
oembed.return_value = {
"type": "photo",
"url": "http://www.example.com",
"error": True,
"error_code": 403,
}
self.assertRaises(
AccessDeniedEmbedlyException,
EmbedlyFinder(key="foo").find_embed,
"http://www.example.com",
)
@unittest.skipIf(no_embedly, "Embedly is not installed")
def test_embedly_404(self):
with patch("embedly.Embedly.oembed") as oembed:
oembed.return_value = {
"type": "photo",
"url": "http://www.example.com",
"error": True,
"error_code": 404,
}
self.assertRaises(
EmbedNotFoundException,
EmbedlyFinder(key="foo").find_embed,
"http://www.example.com",
)
@unittest.skipIf(no_embedly, "Embedly is not installed")
def test_embedly_other_error(self):
with patch("embedly.Embedly.oembed") as oembed:
oembed.return_value = {
"type": "photo",
"url": "http://www.example.com",
"error": True,
"error_code": 999,
}
self.assertRaises(
EmbedlyException,
EmbedlyFinder(key="foo").find_embed,
"http://www.example.com",
)
@unittest.skipIf(no_embedly, "Embedly is not installed")
def test_embedly_html_conversion(self):
with patch("embedly.Embedly.oembed") as oembed:
oembed.return_value = {"type": "photo", "url": "http://www.example.com"}
result = EmbedlyFinder(key="foo").find_embed("http://www.example.com")
self.assertEqual(
result["html"], '
'
)
oembed.return_value = {"type": "something else", "html": "bar"}
result = EmbedlyFinder(key="foo").find_embed("http://www.example.com")
self.assertEqual(result["html"], "bar")
@unittest.skipIf(no_embedly, "Embedly is not installed")
def test_embedly_return_value(self):
with patch("embedly.Embedly.oembed") as oembed:
oembed.return_value = {"type": "something else", "html": "bar"}
result = EmbedlyFinder(key="foo").find_embed("http://www.example.com")
self.assertEqual(
result,
{
"title": "",
"author_name": "",
"provider_name": "",
"type": "something else",
"thumbnail_url": None,
"width": None,
"height": None,
"html": "bar",
},
)
oembed.return_value = {
"type": "something else",
"author_name": "Alice",
"provider_name": "Bob",
"title": "foo",
"thumbnail_url": "http://www.example.com",
"width": 100,
"height": 100,
"html": "bar",
}
result = EmbedlyFinder(key="foo").find_embed("http://www.example.com")
self.assertEqual(
result,
{
"type": "something else",
"author_name": "Alice",
"provider_name": "Bob",
"title": "foo",
"thumbnail_url": "http://www.example.com",
"width": 100,
"height": 100,
"html": "bar",
},
)
class TestOembed(TestCase):
def setUp(self):
class DummyResponse:
def read(self):
return b"foo"
self.dummy_response = DummyResponse()
def test_oembed_invalid_provider(self):
self.assertRaises(EmbedNotFoundException, OEmbedFinder().find_embed, "foo")
def test_oembed_invalid_request(self):
config = {"side_effect": URLError("foo")}
with patch.object(urllib.request, "urlopen", **config):
self.assertRaises(
EmbedNotFoundException,
OEmbedFinder().find_embed,
"http://www.youtube.com/watch/",
)
@patch("urllib.request.urlopen")
def test_oembed_non_json_response(self, urlopen):
urlopen.return_value = self.dummy_response
self.assertRaises(
EmbedNotFoundException,
OEmbedFinder().find_embed,
"https://www.youtube.com/watch?v=ReblZ7o7lu4",
)
@patch("urllib.request.urlopen")
@patch("json.loads")
def test_oembed_photo_request(self, loads, urlopen):
urlopen.return_value = self.dummy_response
loads.return_value = {"type": "photo", "url": "http://www.example.com"}
result = OEmbedFinder().find_embed("http://www.youtube.com/watch/")
self.assertEqual(result["type"], "photo")
self.assertEqual(result["html"], '
')
loads.assert_called_with("foo")
@patch("urllib.request.urlopen")
@patch("json.loads")
def test_oembed_return_values(self, loads, urlopen):
urlopen.return_value = self.dummy_response
loads.return_value = {
"type": "something",
"url": "http://www.example.com",
"title": "test_title",
"author_name": "test_author",
"provider_name": "test_provider_name",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": "test_html",
}
result = OEmbedFinder().find_embed("http://www.youtube.com/watch/")
self.assertEqual(
result,
{
"type": "something",
"title": "test_title",
"author_name": "test_author",
"provider_name": "test_provider_name",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": "test_html",
},
)
@patch("django.utils.timezone.now")
@patch("urllib.request.urlopen")
@patch("json.loads")
def test_oembed_cache_until(self, loads, urlopen, now):
urlopen.return_value = self.dummy_response
loads.return_value = {
"type": "something",
"url": "http://www.example.com",
"title": "test_title",
"author_name": "test_author",
"provider_name": "test_provider_name",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": "test_html",
"cache_age": 3600,
}
now.return_value = make_aware(datetime.datetime(2001, 2, 3))
result = OEmbedFinder().find_embed("http://www.youtube.com/watch/")
self.assertEqual(
result,
{
"type": "something",
"title": "test_title",
"author_name": "test_author",
"provider_name": "test_provider_name",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": "test_html",
"cache_until": make_aware(datetime.datetime(2001, 2, 3, hour=1)),
},
)
@patch("django.utils.timezone.now")
@patch("urllib.request.urlopen")
@patch("json.loads")
def test_oembed_cache_until_as_string(self, loads, urlopen, now):
urlopen.return_value = self.dummy_response
loads.return_value = {
"type": "something",
"url": "http://www.example.com",
"title": "test_title",
"author_name": "test_author",
"provider_name": "test_provider_name",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": "test_html",
"cache_age": "3600",
}
now.return_value = make_aware(datetime.datetime(2001, 2, 3))
result = OEmbedFinder().find_embed("http://www.youtube.com/watch/")
self.assertEqual(
result,
{
"type": "something",
"title": "test_title",
"author_name": "test_author",
"provider_name": "test_provider_name",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": "test_html",
"cache_until": make_aware(datetime.datetime(2001, 2, 3, hour=1)),
},
)
def test_oembed_accepts_known_provider(self):
finder = OEmbedFinder(providers=[oembed_providers.youtube])
self.assertTrue(finder.accept("http://www.youtube.com/watch/"))
def test_oembed_doesnt_accept_unknown_provider(self):
finder = OEmbedFinder(providers=[oembed_providers.twitter])
self.assertFalse(finder.accept("http://www.youtube.com/watch/"))
@patch("urllib.request.urlopen")
@patch("json.loads")
def test_endpoint_with_format_param(self, loads, urlopen):
urlopen.return_value = self.dummy_response
loads.return_value = {"type": "video", "url": "http://www.example.com"}
result = OEmbedFinder().find_embed("https://vimeo.com/217403396")
self.assertEqual(result["type"], "video")
request = urlopen.call_args[0][0]
self.assertEqual(
request.get_full_url().split("?")[0],
"https://www.vimeo.com/api/oembed.json",
)
class TestInstagramOEmbed(TestCase):
def setUp(self):
class DummyResponse:
def read(self):
return b"""{
"type": "something",
"url": "http://www.example.com",
"title": "test_title",
"author_name": "test_author",
"provider_name": "Instagram",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": "Content
"
}"""
self.dummy_response = DummyResponse()
def test_instagram_oembed_only_accepts_new_url_patterns(self):
finder = InstagramOEmbedFinder()
self.assertTrue(
finder.accept(
"https://www.instagram.com/p/CHeRxmnDSYe/?utm_source=ig_embed"
)
)
self.assertTrue(
finder.accept(
"https://www.instagram.com/tv/CZMkxGaIXk3/?utm_source=ig_embed"
)
)
self.assertTrue(
finder.accept(
"https://www.instagram.com/reel/CZMs3O_I22w/?utm_source=ig_embed"
)
)
self.assertFalse(
finder.accept("https://instagr.am/p/CHeRxmnDSYe/?utm_source=ig_embed")
)
@patch("urllib.request.urlopen")
def test_instagram_oembed_return_values(self, urlopen):
urlopen.return_value = self.dummy_response
result = InstagramOEmbedFinder(app_id="123", app_secret="abc").find_embed(
"https://instagram.com/p/CHeRxmnDSYe/"
)
self.assertEqual(
result,
{
"type": "something",
"title": "test_title",
"author_name": "test_author",
"provider_name": "Instagram",
"thumbnail_url": "test_thumbail_url",
"width": "test_width",
"height": "test_height",
"html": 'Content
',
},
)
# check that a request was made with the expected URL / authentication
request = urlopen.call_args[0][0]
self.assertEqual(
request.get_full_url(),
"https://graph.facebook.com/v11.0/instagram_oembed?url=https%3A%2F%2Finstagram.com%2Fp%2FCHeRxmnDSYe%2F&format=json",
)
self.assertEqual(request.get_header("Authorization"), "Bearer 123|abc")
def test_instagram_request_denied_401(self):
err = HTTPError(
"https://instagram.com/p/CHeRxmnDSYe/",
code=401,
msg="invalid credentials",
hdrs={},
fp=None,
)
config = {"side_effect": err}
with patch.object(urllib.request, "urlopen", **config):
self.assertRaises(
AccessDeniedInstagramOEmbedException,
InstagramOEmbedFinder().find_embed,
"https://instagram.com/p/CHeRxmnDSYe/",
)
def test_instagram_request_not_found(self):
err = HTTPError(
"https://instagram.com/p/badrequest/",
code=404,
msg="Not Found",
hdrs={},
fp=None,
)
config = {"side_effect": err}
with patch.object(urllib.request, "urlopen", **config):
self.assertRaises(
EmbedNotFoundException,
InstagramOEmbedFinder().find_embed,
"https://instagram.com/p/CHeRxmnDSYe/",
)
def test_instagram_failed_request(self):
config = {"side_effect": URLError(reason="Testing error handling")}
with patch.object(urllib.request, "urlopen", **config):
self.assertRaises(
EmbedNotFoundException,
InstagramOEmbedFinder().find_embed,
"https://instagram.com/p/CHeRxmnDSYe/",
)
class TestFacebookOEmbed(TestCase):
def setUp(self):
class DummyResponse:
def read(self):
return b"""{
"type": "something",
"url": "http://www.example.com",
"title": "test_title",
"author_name": "test_author",
"provider_name": "Facebook",
"width": "test_width",
"height": "test_height",
"html": "Content
"
}"""
self.dummy_response = DummyResponse()
def test_facebook_oembed_accepts_various_url_patterns(self):
finder = FacebookOEmbedFinder()
self.assertTrue(
finder.accept("https://www.facebook.com/testuser/posts/10157389310497085")
)
self.assertTrue(finder.accept("https://fb.watch/ABC123eew/"))
@patch("urllib.request.urlopen")
def test_facebook_oembed_return_values(self, urlopen):
urlopen.return_value = self.dummy_response
result = FacebookOEmbedFinder(app_id="123", app_secret="abc").find_embed(
"https://fb.watch/ABC123eew/"
)
self.assertEqual(
result,
{
"type": "something",
"title": "test_title",
"author_name": "test_author",
"provider_name": "Facebook",
"thumbnail_url": None,
"width": "test_width",
"height": "test_height",
"html": 'Content
',
},
)
# check that a request was made with the expected URL / authentication
request = urlopen.call_args[0][0]
self.assertEqual(
request.get_full_url(),
"https://graph.facebook.com/v11.0/oembed_video?url=https%3A%2F%2Ffb.watch%2FABC123eew%2F&format=json",
)
self.assertEqual(request.get_header("Authorization"), "Bearer 123|abc")
def test_facebook_request_denied_401(self):
err = HTTPError(
"https://fb.watch/ABC123eew/",
code=401,
msg="invalid credentials",
hdrs={},
fp=None,
)
config = {"side_effect": err}
with patch.object(urllib.request, "urlopen", **config):
self.assertRaises(
AccessDeniedFacebookOEmbedException,
FacebookOEmbedFinder().find_embed,
"https://fb.watch/ABC123eew/",
)
def test_facebook_request_not_found(self):
err = HTTPError(
"https://fb.watch/ABC123eew/", code=404, msg="Not Found", hdrs={}, fp=None
)
config = {"side_effect": err}
with patch.object(urllib.request, "urlopen", **config):
self.assertRaises(
EmbedNotFoundException,
FacebookOEmbedFinder().find_embed,
"https://fb.watch/ABC123eew/",
)
def test_facebook_failed_request(self):
config = {"side_effect": URLError(reason="Testing error handling")}
with patch.object(urllib.request, "urlopen", **config):
self.assertRaises(
EmbedNotFoundException,
FacebookOEmbedFinder().find_embed,
"https://fb.watch/ABC123eew/",
)
class TestEmbedTag(TestCase):
@patch("wagtail.embeds.embeds.get_embed")
def test_direct_call(self, get_embed):
get_embed.return_value = Embed(html='
')
result = embed_tag("http://www.youtube.com/watch/")
self.assertEqual(result, '
')
@patch("wagtail.embeds.embeds.get_embed")
def test_call_from_template(self, get_embed):
get_embed.return_value = Embed(html='
')
temp = template.Template(
'{% load wagtailembeds_tags %}{% embed "http://www.youtube.com/watch/" %}'
)
result = temp.render(template.Context())
self.assertEqual(result, '
')
@patch("wagtail.embeds.embeds.get_embed")
def test_catches_embed_not_found(self, get_embed):
get_embed.side_effect = EmbedNotFoundException
temp = template.Template(
'{% load wagtailembeds_tags %}{% embed "http://www.youtube.com/watch/" %}'
)
result = temp.render(template.Context())
self.assertEqual(result, "")
class TestEmbedBlock(TestCase):
def test_deserialize(self):
"""
Deserialising the JSONish value of an EmbedBlock (a URL) should give us an EmbedValue
for that URL
"""
block = EmbedBlock(required=False)
block_val = block.to_python("http://www.example.com/foo")
self.assertIsInstance(block_val, EmbedValue)
self.assertEqual(block_val.url, "http://www.example.com/foo")
# empty values should yield None
empty_block_val = block.to_python("")
self.assertIsNone(empty_block_val)
def test_serialize(self):
block = EmbedBlock(required=False)
block_val = EmbedValue("http://www.example.com/foo")
serialized_val = block.get_prep_value(block_val)
self.assertEqual(serialized_val, "http://www.example.com/foo")
serialized_empty_val = block.get_prep_value(None)
self.assertEqual(serialized_empty_val, "")
@patch("wagtail.embeds.embeds.get_embed")
def test_render(self, get_embed):
get_embed.return_value = Embed(html="Hello world!
")
block = EmbedBlock()
block_val = block.to_python("http://www.example.com/foo")
temp = template.Template("embed: {{ embed }}")
context = template.Context({"embed": block_val})
result = temp.render(context)
# Check that the embed was in the returned HTML
self.assertIn("Hello world!
", result)
# Check that get_embed was called correctly
get_embed.assert_any_call("http://www.example.com/foo", None, None)
@patch("wagtail.embeds.embeds.get_embed")
def test_render_within_structblock(self, get_embed):
"""
When rendering the value of an EmbedBlock directly in a template
(as happens when accessing it as a child of a StructBlock), the
proper embed output should be rendered, not the URL.
"""
get_embed.return_value = Embed(html="Hello world!
")
block = blocks.StructBlock(
[
("title", blocks.CharBlock()),
("embed", EmbedBlock()),
]
)
block_val = block.to_python(
{"title": "A test", "embed": "http://www.example.com/foo"}
)
temp = template.Template("embed: {{ self.embed }}")
context = template.Context({"self": block_val})
result = temp.render(context)
self.assertIn("Hello world!
", result)
# Check that get_embed was called correctly
get_embed.assert_any_call("http://www.example.com/foo", None, None)
def test_value_from_form(self):
"""
EmbedBlock should be able to turn a URL submitted as part of a form
back into an EmbedValue
"""
block = EmbedBlock(required=False)
block_val = block.value_from_datadict(
{"myembed": "http://www.example.com/foo"}, {}, prefix="myembed"
)
self.assertIsInstance(block_val, EmbedValue)
self.assertEqual(block_val.url, "http://www.example.com/foo")
# empty value should result in None
empty_val = block.value_from_datadict({"myembed": ""}, {}, prefix="myembed")
self.assertIsNone(empty_val)
def test_default(self):
block1 = EmbedBlock()
self.assertIsNone(block1.get_default())
block2 = EmbedBlock(default="")
self.assertIsNone(block2.get_default())
block3 = EmbedBlock(default=None)
self.assertIsNone(block3.get_default())
block4 = EmbedBlock(default="http://www.example.com/foo")
self.assertIsInstance(block4.get_default(), EmbedValue)
self.assertEqual(block4.get_default().url, "http://www.example.com/foo")
block5 = EmbedBlock(default=EmbedValue("http://www.example.com/foo"))
self.assertIsInstance(block5.get_default(), EmbedValue)
self.assertEqual(block5.get_default().url, "http://www.example.com/foo")
@patch("wagtail.embeds.embeds.get_embed")
def test_clean_required(self, get_embed):
get_embed.return_value = Embed(html="Hello world!
")
block = EmbedBlock()
cleaned_value = block.clean(
EmbedValue("https://www.youtube.com/watch?v=_U79Wc965vw")
)
self.assertIsInstance(cleaned_value, EmbedValue)
self.assertEqual(
cleaned_value.url, "https://www.youtube.com/watch?v=_U79Wc965vw"
)
with self.assertRaisesMessage(ValidationError, ""):
block.clean(None)
@patch("wagtail.embeds.embeds.get_embed")
def test_clean_non_required(self, get_embed):
get_embed.return_value = Embed(html="Hello world!
")
block = EmbedBlock(required=False)
cleaned_value = block.clean(
EmbedValue("https://www.youtube.com/watch?v=_U79Wc965vw")
)
self.assertIsInstance(cleaned_value, EmbedValue)
self.assertEqual(
cleaned_value.url, "https://www.youtube.com/watch?v=_U79Wc965vw"
)
cleaned_value = block.clean(None)
self.assertIsNone(cleaned_value)
@patch("wagtail.embeds.embeds.get_embed")
def test_clean_invalid_url(self, get_embed):
get_embed.side_effect = EmbedNotFoundException
non_required_block = EmbedBlock(required=False)
with self.assertRaises(ValidationError):
non_required_block.clean(EmbedValue("http://no-oembed-here.com/something"))
required_block = EmbedBlock()
with self.assertRaises(ValidationError):
required_block.clean(EmbedValue("http://no-oembed-here.com/something"))