Merge pull request #36 from yetty/I34-force-ssl

Closes #34. Options in embed tag.
This commit is contained in:
Juda Kaleta 2014-07-26 16:54:15 +02:00
commit 45203418ff
19 changed files with 566 additions and 665 deletions

View file

@ -1,6 +1,11 @@
Release 1.0.0 (dev)
-------------------
**Backward incompatible changes:**
- filter `embed_video_tags.embed` has been removed
Backward compatible changes:
*No changes yet.*

View file

@ -48,34 +48,16 @@ Default sizes are ``tiny`` (420x315), ``small`` (480x360), ``medium`` (640x480),
{% video my_video '100% x 50%' %}
Some backends (e.g. YouTube) allow configuration of the embedding via passing
query parameters. To specify the parameters:
It is possible to set backend options via parameters in template tag. It is
useful for example to enforce HTTPS protocol or set different query appended
to url.
::
{% video item.video 'small' rel=0 %}
{% video item.video 'small' start=2 stop=5 repeat=1 %}
{% video item.video rel=0 as my_video %}
URL: {{ my_video.url }}
Thumbnail: {{ my_video.thumbnail }}
Backend: {{ my_video.backend }}
{% video my_video 'small' %}
{% video my_video query="rel=0&wmode=transparent" is_secure=True %}
{{ video.url }} {# always with https #}
{% endvideo %}
Parameters may also be template variables:
::
{% video item.video 'small' start=item.start stop=item.stop repeat=item.repeat %}
.. tip::
You can provide default values for the query string that's included in the
embedded URL by updating your Django settings file.
.. tip::
@ -96,7 +78,7 @@ Parameters may also be template variables:
backend (:py:data:`~embed_video.backends.VideoBackend.template_name`).
.. versionadded:: 0.9
``template_name`` has been added in version 0.9.

View file

@ -1,24 +1,21 @@
import re
import requests
import sys
import json
import requests
try:
# Python <= 2.7
import urlparse
from urllib import urlencode
except ImportError:
# support for py3
if sys.version_info.major == 3:
import urllib.parse as urlparse
from urllib.parse import urlencode
else:
import urlparse
from django.conf import settings
from django.http import QueryDict
from django.template.loader import render_to_string
from django.utils.functional import cached_property
from django.utils.safestring import mark_safe
from django.utils.datastructures import SortedDict
from .utils import import_by_path
from .settings import EMBED_VIDEO_BACKENDS, EMBED_VIDEO_TIMEOUT
from .settings import EMBED_VIDEO_BACKENDS, EMBED_VIDEO_TIMEOUT, \
EMBED_VIDEO_YOUTUBE_DEFAULT_QUERY
class EmbedVideoException(Exception):
@ -112,7 +109,12 @@ class VideoBackend(object):
``{{ width }}``, ``{{ height }}``
"""
def __init__(self, url, is_secure=False, query=None):
default_query = ''
"""
Default query string or `QueryDict` appended to url
"""
def __init__(self, url, is_secure=False):
"""
First it tries to load data from cache and if it don't succeed, run
:py:meth:`init` and then save it to cache.
@ -120,22 +122,17 @@ class VideoBackend(object):
self.is_secure = is_secure
self.backend = self.__class__.__name__
self._url = url
self.update_query(query)
def update_query(self, query=None):
self._query = SortedDict(self.get_default_query())
if query is not None:
self._query.update(query)
self.query = QueryDict(self.default_query, mutable=True)
@cached_property
def code(self):
return self.get_code()
@cached_property
@property
def url(self):
return self.get_url()
@cached_property
@property
def protocol(self):
return 'https' if self.allow_https and self.is_secure else 'http'
@ -147,6 +144,16 @@ class VideoBackend(object):
def info(self):
return self.get_info()
@property
def query(self):
return self._query
@query.setter
def query(self, value):
self._query = value \
if isinstance(value, QueryDict) \
else QueryDict(value, mutable=True)
@classmethod
def is_valid(cls, url):
"""
@ -168,8 +175,7 @@ class VideoBackend(object):
Returns URL folded from :py:data:`pattern_url` and parsed code.
"""
url = self.pattern_url.format(code=self.code, protocol=self.protocol)
if self._query:
url += '?' + urlencode(self._query, doseq=True)
url += '?' + self.query.urlencode() if self.query else ''
return mark_safe(url)
def get_thumbnail_url(self):
@ -193,12 +199,9 @@ class VideoBackend(object):
def get_info(self):
raise NotImplementedError
def get_default_query(self):
# Derive backend name from class name
backend_name = self.__class__.__name__[:-7].upper()
default = getattr(self, 'default_query', {})
settings_key = 'EMBED_VIDEO_{0}_QUERY'.format(backend_name)
return getattr(settings, settings_key, default).copy()
def set_options(self, options):
for key in options:
setattr(self, key, options[key])
class YoutubeBackend(VideoBackend):
@ -225,7 +228,7 @@ class YoutubeBackend(VideoBackend):
pattern_url = '{protocol}://www.youtube.com/embed/{code}'
pattern_thumbnail_url = '{protocol}://img.youtube.com/vi/{code}/hqdefault.jpg'
default_query = {'wmode': 'opaque'}
default_query = EMBED_VIDEO_YOUTUBE_DEFAULT_QUERY
def get_code(self):
code = super(YoutubeBackend, self).get_code()

View file

@ -8,3 +8,6 @@ EMBED_VIDEO_BACKENDS = getattr(settings, 'EMBED_VIDEO_BACKENDS', (
))
EMBED_VIDEO_TIMEOUT = getattr(settings, 'EMBED_VIDEO_TIMEOUT', 10)
EMBED_VIDEO_YOUTUBE_DEFAULT_QUERY = \
getattr(settings, 'EMBED_VIDEO_YOUTUBE_DEFAULT_QUERY', 'wmode=opaque')

View file

@ -1,2 +1 @@
<iframe width="{{ width }}" height="{{ height }}" src="{{ backend.url }}"
frameborder="0" allowfullscreen></iframe>
<iframe width="{{ width }}" height="{{ height }}" src="{{ backend.url }}" frameborder="0" allowfullscreen></iframe>

View file

@ -1,9 +1,8 @@
import re
import logging
import requests
from collections import defaultdict
from django.template import Library, Node, TemplateSyntaxError, Variable
from django.template import Library, Node, TemplateSyntaxError
from django.utils.safestring import mark_safe
from django.utils.encoding import smart_str
@ -14,8 +13,6 @@ register = Library()
logger = logging.getLogger(__name__)
# Used for parsing keyword arguments passed in as key-value pairs
kw_pat = re.compile(r'^(?P<key>[\w]+)=(?P<value>.+)$')
@register.tag('video')
@ -28,25 +25,26 @@ class VideoNode(Node):
.. code-block:: html+django
{% video URL [SIZE] %}
{% video URL [SIZE] [key1=value1, key2=value2...] %}
Or as a block:
.. code-block:: html+django
{% video URL as VAR %}
{% video URL [SIZE] [key1=value1, key2=value2...] as VAR %}
...
{% endvideo %}
Example:
Examples:
.. code-block:: html+django
{% video item.video %}
{% video item.video "large" %}
{% video item.video "340x200" %}
{% video item.video "100% x 300" %}
{% video item.video "100% x 300" query="rel=0&wmode=opaque" %}
{% video item.video as my_video %}
{% video item.video is_secure=True as my_video %}
URL: {{ my_video.url }}
Thumbnail: {{ my_video.thumbnail }}
Backend: {{ my_video.backend }}
@ -57,62 +55,48 @@ class VideoNode(Node):
'[size] [key1=val1 key2=val2 ...] [as var] %}``'
default_size = 'small'
re_size = re.compile('(?P<width>\d+%?) *x *(?P<height>\d+%?)')
re_size = re.compile('[\'"]?(?P<width>\d+%?) *x *(?P<height>\d+%?)[\'"]?')
re_option = re.compile(r'^(?P<key>[\w]+)=(?P<value>.+)$')
def __init__(self, parser, token):
self.size = None
self.bits = token.split_contents()
self.query = None
self.parser = parser
self.bits = list(token.split_contents())
self.tag_name = str(self.pop_bit())
self.url = self.pop_bit()
try:
self.url = parser.compile_filter(self.bits[1])
except IndexError:
raise TemplateSyntaxError(self.error_msg)
# Determine if the tag is being used as a context variable
if self.bits[-2] == 'as':
option_bits = self.bits[2:-2]
self.nodelist_file = parser.parse(('endvideo',))
if len(self.bits) > 1 and self.bits[-2] == 'as':
del self.bits[-2]
self.variable_name = str(self.pop_bit(-1))
self.nodelist_file = parser.parse(('end' + self.tag_name, ))
parser.delete_first_token()
else:
option_bits = self.bits[2:]
self.variable_name = None
# Size must be the first argument and is only accepted when this is
# used as a template tag (but not when used as a block tag)
if len(option_bits) != 0 and '=' not in option_bits[0]:
self.size = parser.compile_filter(option_bits[0])
option_bits = option_bits[1:]
else:
self.size = self.default_size
self.size = self.pop_bit() if self.bits and '=' not in self.bits[0] else None
self.options = self.parse_options(self.bits)
# Parse arguments passed in as KEY=VALUE pairs that will be added to
# the URL as a GET query string
if len(option_bits) != 0:
self.query = defaultdict(list)
def pop_bit(self, index=0):
return self.parser.compile_filter(self.bits.pop(index))
for bit in option_bits:
match = kw_pat.match(bit)
key = smart_str(match.group('key'))
value = Variable(smart_str(match.group('value')))
self.query[key].append(value)
def parse_options(self, bits):
options = {}
for bit in bits:
parsed_bit = self.re_option.match(bit)
key = smart_str(parsed_bit.group('key'))
value = self.parser.compile_filter(parsed_bit.group('value'))
options[key] = value
return options
def render(self, context):
# Attempt to resolve any parameters passed in.
if self.query is not None:
resolved_query = defaultdict(list)
for key, values in self.query.items():
for value in values:
resolved_value = value.resolve(context)
resolved_query[key].append(resolved_value)
else:
resolved_query = None
url = self.url.resolve(context)
size = self.size.resolve(context) if self.size else None
options = self.resolve_options(context)
try:
if self.size:
return self.__render_embed(url, context, resolved_query)
else:
return self.__render_block(url, context, resolved_query)
if not self.variable_name:
return self.embed(url, size, context=context, **options)
backend = self.get_backend(url, context=context, **options)
return self.render_block(context, backend)
except requests.Timeout:
logger.exception('Timeout reached during rendering embed video (`{0}`)'.format(url))
except UnknownBackendException:
@ -122,23 +106,22 @@ class VideoNode(Node):
return ''
def __render_embed(self, url, context, query):
size = self.size.resolve(context) \
if hasattr(self.size, 'resolve') else self.size
return self.embed(url, size, context=context, query=query)
def __render_block(self, url, context, query):
as_var = self.bits[-1]
def resolve_options(self, context):
options = {}
for key in self.options:
value = self.options[key]
options[key] = value.resolve(context)
return options
def render_block(self, context, backend):
context.push()
context[as_var] = self.get_backend(url, context=context, query=query)
context[self.variable_name] = backend
output = self.nodelist_file.render(context)
context.pop()
return output
@staticmethod
def get_backend(backend_or_url, context=None, query=None):
def get_backend(backend_or_url, context=None, **options):
"""
Returns instance of VideoBackend. If context is passed to the method
and request is secure, than the is_secure mark is set to backend.
@ -151,22 +134,22 @@ class VideoNode(Node):
if context and 'request' in context:
backend.is_secure = context['request'].is_secure()
backend.update_query(query)
if options:
backend.set_options(options)
return backend
@staticmethod
def embed(url, size, GET=None, context=None, query=None):
@classmethod
def embed(cls, url, size, context=None, **options):
"""
Direct render of embed video.
"""
backend = VideoNode.get_backend(url, context=context, query=query)
width, height = VideoNode.get_size(size)
backend = cls.get_backend(url, context=context, **options)
width, height = cls.get_size(size)
return mark_safe(backend.get_embed_code(width=width, height=height))
@staticmethod
def get_size(value):
@classmethod
def get_size(cls, value):
"""
Predefined sizes:
@ -191,11 +174,12 @@ class VideoNode(Node):
'huge': (1280, 960),
}
value = value or cls.default_size
if value in sizes:
return sizes[value]
try:
size = VideoNode.re_size.match(value)
size = cls.re_size.match(value)
return [size.group('width'), size.group('height')]
except AttributeError:
raise TemplateSyntaxError(
@ -209,28 +193,3 @@ class VideoNode(Node):
def __repr__(self):
return '<VideoNode "%s">' % self.url
@register.filter(is_safe=True)
def embed(backend, size='small'):
"""
.. warning::
.. deprecated:: 0.7
Use :py:func:`VideoNode.embed` instead.
Same like :py:func:`VideoNode.embed` tag but **always uses insecure
HTTP protocol**.
Usage:
.. code-block:: html+django
{{ URL|embed:SIZE }}
Example:
.. code-block:: html+django
{{ 'http://www.youtube.com/watch?v=guXyvo2FfLs'|embed:'large' }}
"""
return VideoNode.embed(backend, size)

View file

@ -0,0 +1,17 @@
from embed_video.backends import detect_backend
class BackendTestMixin(object):
urls = []
instance = None
def test_detect(self):
for url in self.urls:
backend = detect_backend(url[0])
self.assertIsInstance(backend, self.instance)
def test_code(self):
for url in self.urls:
backend = self.instance(url[0])
self.assertEqual(backend.code, url[1])

View file

@ -1,8 +1,15 @@
import re
from unittest import TestCase
from embed_video.backends import detect_backend
from embed_video.backends import VideoBackend, detect_backend
from .custom_backend import CustomBackend
class CustomBackend(VideoBackend):
re_detect = re.compile(r'http://myvideo\.com/[0-9]+')
re_code = re.compile(r'http://myvideo\.com/(?P<code>[0-9]+)')
pattern_url = '{protocol}://play.myvideo.com/c/{code}/'
pattern_thumbnail_url = '{protocol}://thumb.myvideo.com/c/{code}/'
class CustomBackendTestCase(TestCase):
@ -27,4 +34,3 @@ class CustomBackendTestCase(TestCase):
def test_thumbnail(self):
self.assertEqual(self.backend.get_thumbnail_url(),
'http://thumb.myvideo.com/c/1530/')

View file

@ -0,0 +1,55 @@
import requests
from mock import patch
from unittest import TestCase
from . import BackendTestMixin
from embed_video.backends import SoundCloudBackend, VideoDoesntExistException
class SoundCloudBackendTestCase(BackendTestMixin, TestCase):
urls = (
('https://soundcloud.com/community/soundcloud-case-study-wildlife', '82244706'),
('https://soundcloud.com/matej-roman/jaromir-nohavica-karel-plihal-mikymauz', '7834701'),
('https://soundcloud.com/beny97/sets/jaromir-nohavica-prazska', '960591'),
('https://soundcloud.com/corbel-keep/norah-jones-come-away-with', '22485933'),
)
instance = SoundCloudBackend
def setUp(self):
class FooBackend(SoundCloudBackend):
url = 'foobar'
def get_info(self):
return {
'width': 123,
'height': 321,
'thumbnail_url': 'xyz',
'html': u'\u003Ciframe width=\"100%\" height=\"400\" '
u'scrolling=\"no\" frameborder=\"no\" '
u'src=\"{0}\"\u003E\u003C/iframe\u003E'.format(self.url)
}
self.foo = FooBackend('abcd')
def test_width(self):
self.assertEqual(self.foo.width, 123)
def test_height(self):
self.assertEqual(self.foo.height, 321)
def test_get_thumbnail_url(self):
self.assertEqual(self.foo.get_thumbnail_url(), 'xyz')
def test_get_url(self):
self.assertEqual(self.foo.get_url(), self.foo.url)
@patch('embed_video.backends.EMBED_VIDEO_TIMEOUT', 0.000001)
def test_timeout_in_get_info(self):
backend = SoundCloudBackend('https://soundcloud.com/community/soundcloud-case-study-wildlife')
self.assertRaises(requests.Timeout, backend.get_info)
def test_invalid_url(self):
""" Check if bug #21 is fixed. """
backend = SoundCloudBackend('https://soundcloud.com/xyz/foo')
self.assertRaises(VideoDoesntExistException, backend.get_info)

View file

@ -0,0 +1,20 @@
from unittest import TestCase
from embed_video.backends import UnknownBackendException, detect_backend, \
VideoBackend
class VideoBackendTestCase(TestCase):
unknown_backend_urls = (
'http://myurl.com/?video=http://www.youtube.com/watch?v=jsrRJyHBvzw',
'http://myurl.com/?video=www.youtube.com/watch?v=jsrRJyHBvzw',
'http://youtube.com.myurl.com/watch?v=jsrRJyHBvzw',
'http://vimeo.com.myurl.com/72304002',
)
def test_detect_bad_urls(self):
for url in self.unknown_backend_urls:
self.assertRaises(UnknownBackendException, detect_backend, url)
def test_not_implemented_get_info(self):
backend = VideoBackend('http://www.example.com')
self.assertRaises(NotImplementedError, backend.get_info)

View file

@ -0,0 +1,34 @@
import requests
from mock import patch
from unittest import TestCase
from . import BackendTestMixin
from embed_video.backends import VimeoBackend, VideoDoesntExistException
class VimeoBackendTestCase(BackendTestMixin, TestCase):
urls = (
('http://vimeo.com/72304002', '72304002'),
('https://vimeo.com/72304002', '72304002'),
('http://www.vimeo.com/72304002', '72304002'),
('https://www.vimeo.com/72304002', '72304002'),
('http://player.vimeo.com/video/72304002', '72304002'),
('https://player.vimeo.com/video/72304002', '72304002'),
)
instance = VimeoBackend
def test_vimeo_get_info_exception(self):
with self.assertRaises(VideoDoesntExistException):
backend = VimeoBackend('http://vimeo.com/123')
backend.get_info()
def test_get_thumbnail_url(self):
backend = VimeoBackend('http://vimeo.com/72304002')
self.assertEqual(backend.get_thumbnail_url(),
'http://i.vimeocdn.com/video/446150690_640.jpg')
@patch('embed_video.backends.EMBED_VIDEO_TIMEOUT', 0.000001)
def test_timeout_in_get_info(self):
backend = VimeoBackend('http://vimeo.com/72304002')
self.assertRaises(requests.Timeout, backend.get_info)

View file

@ -0,0 +1,42 @@
from unittest import TestCase
from . import BackendTestMixin
from embed_video.backends import YoutubeBackend, UnknownIdException
class YoutubeBackendTestCase(BackendTestMixin, TestCase):
urls = (
('http://youtu.be/jsrRJyHBvzw', 'jsrRJyHBvzw'),
('http://youtu.be/n17B_uFF4cA', 'n17B_uFF4cA'),
('http://youtu.be/t-ZRX8984sc', 't-ZRX8984sc'),
('https://youtu.be/t-ZRX8984sc', 't-ZRX8984sc'),
('http://youtube.com/watch?v=jsrRJyHBvzw', 'jsrRJyHBvzw'),
('https://youtube.com/watch?v=jsrRJyHBvzw', 'jsrRJyHBvzw'),
('http://www.youtube.com/v/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('https://www.youtube.com/v/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('http://www.youtube.com/embed/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('https://www.youtube.com/embed/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('http://www.youtube.com/watch?v=jsrRJyHBvzw', 'jsrRJyHBvzw'),
('https://www.youtube.com/watch?v=t-ZRX8984sc', 't-ZRX8984sc'),
('http://www.youtube.com/watch?v=iwGFalTRHDA&feature=related', 'iwGFalTRHDA'),
('https://www.youtube.com/watch?v=iwGFalTRHDA&feature=related', 'iwGFalTRHDA'),
('http://www.youtube.com/watch?feature=player_embedded&v=2NpZbaAIXag', '2NpZbaAIXag'),
('https://www.youtube.com/watch?feature=player_embedded&v=2NpZbaAIXag', '2NpZbaAIXag'),
('https://www.youtube.com/watch?v=XPk521voaOE&feature=youtube_gdata_player', 'XPk521voaOE'),
('http://www.youtube.com/watch?v=6xu00J3-g2s&list=PLb5n6wzDlPakFKvJ69rJ9AJW24Aaaki2z', '6xu00J3-g2s'),
('https://m.youtube.com/#/watch?v=IAooXLAPoBQ', 'IAooXLAPoBQ'),
('https://m.youtube.com/watch?v=IAooXLAPoBQ', 'IAooXLAPoBQ'),
('http://www.youtube.com/edit?video_id=eBea01qmnOE', 'eBea01qmnOE')
)
instance = YoutubeBackend
def test_youtube_keyerror(self):
""" Test for issue #7 """
backend = self.instance('http://youtube.com/watch?id=5')
self.assertRaises(UnknownIdException, backend.get_code)
def test_thumbnail(self):
for url in self.urls:
backend = self.instance(url[0])
self.assertIn(url[1], backend.thumbnail)

View file

@ -1,11 +0,0 @@
import re
from embed_video.backends import VideoBackend
class CustomBackend(VideoBackend):
re_detect = re.compile(r'http://myvideo\.com/[0-9]+')
re_code = re.compile(r'http://myvideo\.com/(?P<code>[0-9]+)')
pattern_url = '{protocol}://play.myvideo.com/c/{code}/'
pattern_thumbnail_url = '{protocol}://thumb.myvideo.com/c/{code}/'

View file

@ -17,7 +17,7 @@ EMBED_VIDEO_BACKENDS = (
'embed_video.backends.YoutubeBackend',
'embed_video.backends.VimeoBackend',
'embed_video.backends.SoundCloudBackend',
'embed_video.tests.custom_backend.CustomBackend',
'embed_video.tests.backends.tests_custom_backend.CustomBackend',
)

View file

@ -0,0 +1,285 @@
from unittest import TestCase, skip
from mock import Mock, patch
import re
from django.template import TemplateSyntaxError
from django.http import HttpRequest
from django.template.base import Template
from django.template.context import RequestContext
from django.test.client import RequestFactory
from testfixtures import log_capture
from embed_video.templatetags.embed_video_tags import VideoNode
URL_PATTERN = re.compile(r'src="?\'?([^"\'>]*)"')
class EmbedTestCase(TestCase):
def assertRenderedTemplate(self, template_string, output, context=None):
response = RequestContext(HttpRequest(), context)
rendered_output = Template(template_string).render(response)
self.assertEqual(rendered_output.strip(), output.strip())
def test_embed(self):
template = """
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %}
{% video ytb 'large' %}
{% endvideo %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="960" height="720" '
'src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque" '
'frameborder="0" allowfullscreen></iframe>'
)
def test_embed_invalid_url(self):
template = """
{% load embed_video_tags %}
{% video 'http://www.youtube.com/edit?abcd=efgh' as ytb %}
{{ ytb.url }}
{% endvideo %}
"""
self.assertRenderedTemplate(template, '')
def test_embed_with_none_instance(self):
template = """
{% with None as my_video %}
{% load embed_video_tags %}
{% video my_video %}{% endwith %}
"""
self.assertRenderedTemplate(template, '')
def test_embed_empty_string(self):
template = """
{% load embed_video_tags %}
{% video '' 'large' %}
"""
self.assertRenderedTemplate(template, '')
def test_direct_embed_tag(self):
template = """
{% load embed_video_tags %}
{% video "http://www.youtube.com/watch?v=jsrRJyHBvzw" "large" %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="960" height="720" '
'src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque" '
'frameborder="0" allowfullscreen></iframe>'
)
def test_direct_embed_tag_with_default_size(self):
template = """
{% load embed_video_tags %}
{% video "http://www.youtube.com/watch?v=jsrRJyHBvzw" %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="480" height="360" '
'src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque" '
'frameborder="0" allowfullscreen></iframe>'
)
def test_direct_embed_invalid_url(self):
template = """
{% load embed_video_tags %}
{% video "https://soundcloud.com/xyz/foo" %}
"""
self.assertRenderedTemplate(template, '')
def test_user_size(self):
template = """
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %}
{% video ytb '800x800' %}
{% endvideo %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="800" height="800" '
'src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque" '
'frameborder="0" allowfullscreen></iframe>'
)
@skip
def test_wrong_size(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' 'so x huge' %}
""")
request = RequestContext(HttpRequest())
self.assertRaises(TemplateSyntaxError, template.render, request)
def test_tag_youtube(self):
template = """
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %}
{{ ytb.url }} {{ ytb.backend }}
{% endvideo %}
"""
self.assertRenderedTemplate(
template,
'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque '
'YoutubeBackend'
)
def test_tag_vimeo(self):
template = """
{% load embed_video_tags %}
{% video 'https://vimeo.com/72304002' as vimeo %}
{{ vimeo.url }} {{ vimeo.backend }} {{ vimeo.info.duration }}
{% endvideo %}
"""
self.assertRenderedTemplate(
template, 'http://player.vimeo.com/video/72304002 VimeoBackend 176'
)
def test_tag_soundcloud(self):
template = """
{% load embed_video_tags %}
{% video 'https://soundcloud.com/community/soundcloud-case-study-wildlife' as soundcloud %}
{{ soundcloud.url }} {{ soundcloud.backend }}
{% endvideo %}
"""
self.assertRenderedTemplate(
template,
'https://w.soundcloud.com/player/?visual=true&amp;url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F82244706&amp;show_artwork=true '
'SoundCloudBackend'
)
@patch('embed_video.backends.EMBED_VIDEO_TIMEOUT', 0.000001)
@log_capture()
def test_empty_if_timeout(self, logs):
template = """
{% load embed_video_tags %}
{% video "http://vimeo.com/72304002" as my_video %}
{{ my_video.thumbnail }}
{% endvideo %}
"""
self.assertRenderedTemplate(template, '')
logs.check(
('requests.packages.urllib3.connectionpool', 'INFO', 'Starting new HTTP connection (1): vimeo.com'),
('embed_video.templatetags.embed_video_tags', 'ERROR', 'Timeout reached during rendering embed video (`http://vimeo.com/72304002`)')
)
def test_relative_size(self):
template = """
{% load embed_video_tags %}
{% video "http://vimeo.com/72304002" "80%x30%" %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="80%" height="30%" '
'src="http://player.vimeo.com/video/72304002" '
'frameborder="0" allowfullscreen></iframe>'
)
def test_allow_spaces_in_size(self):
template = """
{% load embed_video_tags %}
{% video "http://vimeo.com/72304002" "80% x 300" %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="80%" height="300" '
'src="http://player.vimeo.com/video/72304002" '
'frameborder="0" allowfullscreen></iframe>'
)
def test_embed_with_query(self):
template = """
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' query="rel=1&wmode=transparent" as ytb %}
{{ ytb.url }}
{% endvideo %}
"""
self.assertRenderedTemplate(
template,
'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=transparent&rel=1'
)
def test_direct_embed_with_query(self):
template = """
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' query="rel=1&wmode=transparent" %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="480" height="360" '
'src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=transparent&rel=1" '
'frameborder="0" allowfullscreen></iframe>'
)
def test_set_options(self):
template = """
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' "300x200" is_secure=True query="rel=1" %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="300" height="200" '
'src="https://www.youtube.com/embed/jsrRJyHBvzw?rel=1" '
'frameborder="0" allowfullscreen></iframe>'
)
def test_size_as_variable(self):
template = """
{% load embed_video_tags %}
{% with size="500x200" %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' size %}
{% endwith %}
"""
self.assertRenderedTemplate(
template,
'<iframe width="500" height="200" '
'src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque" '
'frameborder="0" allowfullscreen></iframe>'
)
class EmbedVideoNodeTestCase(TestCase):
def setUp(self):
self.parser = Mock()
self.token = Mock(methods=['split_contents'])
def test_repr(self):
self.token.split_contents.return_value = (
'video', 'http://youtu.be/v/1234', 'as', 'myvideo'
)
self.parser.compile_filter.return_value = u'some_url'
node = VideoNode(self.parser, self.token)
self.assertEqual(str(node), '<VideoNode "some_url">')
def test_videonode_iter(self):
out = ['a', 'b', 'c', 'd']
class FooNode(VideoNode):
nodelist_file = out
def __init__(self):
pass
node = FooNode()
self.assertEqual(out, [x for x in node])
def test_get_backend_secure(self):
class SecureRequest(RequestFactory):
is_secure = lambda x: True
context = {'request': SecureRequest()}
backend = VideoNode.get_backend('http://www.youtube.com/watch?v=jsrRJyHBvzw', context)
self.assertTrue(backend.is_secure)
def test_get_backend_insecure(self):
class InsecureRequest(RequestFactory):
is_secure = lambda x: False
context = {'request': InsecureRequest()}
backend = VideoNode.get_backend('http://www.youtube.com/watch?v=jsrRJyHBvzw', context)
self.assertFalse(backend.is_secure)

View file

@ -1,157 +0,0 @@
from unittest import TestCase
from mock import patch
import requests
from ..backends import detect_backend, YoutubeBackend, VimeoBackend, \
SoundCloudBackend, UnknownBackendException, VideoDoesntExistException, \
UnknownIdException, VideoBackend
class BackendTestMixin(object):
def test_detect(self):
for url in self.urls:
backend = detect_backend(url[0])
self.assertIsInstance(backend, self.instance)
def test_code(self):
for url in self.urls:
backend = self.instance(url[0])
self.assertEqual(backend.code, url[1])
class VideoBackendTestCase(TestCase):
unknown_backend_urls = (
'http://myurl.com/?video=http://www.youtube.com/watch?v=jsrRJyHBvzw',
'http://myurl.com/?video=www.youtube.com/watch?v=jsrRJyHBvzw',
'http://youtube.com.myurl.com/watch?v=jsrRJyHBvzw',
'http://vimeo.com.myurl.com/72304002',
)
def test_detect_bad_urls(self):
for url in self.unknown_backend_urls:
self.assertRaises(UnknownBackendException, detect_backend, url)
def test_not_implemented_get_info(self):
backend = VideoBackend('http://www.example.com')
self.assertRaises(NotImplementedError, backend.get_info)
class YoutubeBackendTestCase(BackendTestMixin, TestCase):
urls = (
('http://youtu.be/jsrRJyHBvzw', 'jsrRJyHBvzw'),
('http://youtu.be/n17B_uFF4cA', 'n17B_uFF4cA'),
('http://youtu.be/t-ZRX8984sc', 't-ZRX8984sc'),
('https://youtu.be/t-ZRX8984sc', 't-ZRX8984sc'),
('http://youtube.com/watch?v=jsrRJyHBvzw', 'jsrRJyHBvzw'),
('https://youtube.com/watch?v=jsrRJyHBvzw', 'jsrRJyHBvzw'),
('http://www.youtube.com/v/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('https://www.youtube.com/v/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('http://www.youtube.com/embed/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('https://www.youtube.com/embed/0zM3nApSvMg?rel=0', '0zM3nApSvMg'),
('http://www.youtube.com/watch?v=jsrRJyHBvzw', 'jsrRJyHBvzw'),
('https://www.youtube.com/watch?v=t-ZRX8984sc', 't-ZRX8984sc'),
('http://www.youtube.com/watch?v=iwGFalTRHDA&feature=related', 'iwGFalTRHDA'),
('https://www.youtube.com/watch?v=iwGFalTRHDA&feature=related', 'iwGFalTRHDA'),
('http://www.youtube.com/watch?feature=player_embedded&v=2NpZbaAIXag', '2NpZbaAIXag'),
('https://www.youtube.com/watch?feature=player_embedded&v=2NpZbaAIXag', '2NpZbaAIXag'),
('https://www.youtube.com/watch?v=XPk521voaOE&feature=youtube_gdata_player', 'XPk521voaOE'),
('http://www.youtube.com/watch?v=6xu00J3-g2s&list=PLb5n6wzDlPakFKvJ69rJ9AJW24Aaaki2z', '6xu00J3-g2s'),
('https://m.youtube.com/#/watch?v=IAooXLAPoBQ', 'IAooXLAPoBQ'),
('https://m.youtube.com/watch?v=IAooXLAPoBQ', 'IAooXLAPoBQ'),
('http://www.youtube.com/edit?video_id=eBea01qmnOE', 'eBea01qmnOE')
)
instance = YoutubeBackend
def test_youtube_keyerror(self):
""" Test for issue #7 """
backend = self.instance('http://youtube.com/watch?id=5')
self.assertRaises(UnknownIdException, backend.get_code)
def test_thumbnail(self):
for url in self.urls:
backend = self.instance(url[0])
self.assertIn(url[1], backend.thumbnail)
class VimeoBackendTestCase(BackendTestMixin, TestCase):
urls = (
('http://vimeo.com/72304002', '72304002'),
('https://vimeo.com/72304002', '72304002'),
('http://www.vimeo.com/72304002', '72304002'),
('https://www.vimeo.com/72304002', '72304002'),
('http://player.vimeo.com/video/72304002', '72304002'),
('https://player.vimeo.com/video/72304002', '72304002'),
)
instance = VimeoBackend
def test_vimeo_get_info_exception(self):
with self.assertRaises(VideoDoesntExistException):
backend = VimeoBackend('http://vimeo.com/123')
backend.get_info()
def test_get_thumbnail_url(self):
backend = VimeoBackend('http://vimeo.com/72304002')
self.assertEqual(backend.get_thumbnail_url(),
'http://i.vimeocdn.com/video/446150690_640.jpg')
@patch('embed_video.backends.EMBED_VIDEO_TIMEOUT', 0.000001)
def test_timeout_in_get_info(self):
backend = VimeoBackend('http://vimeo.com/72304002')
self.assertRaises(requests.Timeout, backend.get_info)
class SoundCloudBackendTestCase(BackendTestMixin, TestCase):
urls = (
('https://soundcloud.com/community/soundcloud-case-study-wildlife', '82244706'),
('https://soundcloud.com/matej-roman/jaromir-nohavica-karel-plihal-mikymauz', '7834701'),
('https://soundcloud.com/beny97/sets/jaromir-nohavica-prazska', '960591'),
('https://soundcloud.com/corbel-keep/norah-jones-come-away-with', '22485933'),
)
instance = SoundCloudBackend
def setUp(self):
class FooBackend(SoundCloudBackend):
url = 'foobar'
def get_info(self):
return {
'width': 123,
'height': 321,
'thumbnail_url': 'xyz',
'html': u'\u003Ciframe width=\"100%\" height=\"400\" '
u'scrolling=\"no\" frameborder=\"no\" '
u'src=\"{0}\"\u003E\u003C/iframe\u003E'.format(self.url)
}
self.foo = FooBackend('abcd')
def test_width(self):
self.assertEqual(self.foo.width, 123)
def test_height(self):
self.assertEqual(self.foo.height, 321)
def test_get_thumbnail_url(self):
self.assertEqual(self.foo.get_thumbnail_url(), 'xyz')
def test_get_url(self):
self.assertEqual(self.foo.get_url(), self.foo.url)
def test_get_embed_code(self):
self.assertEqual(self.foo.get_embed_code(100, 200),
u'<iframe width="100" height="321" src="foobar"'
u'\n frameborder="0" allowfullscreen>'
u'</iframe>\n')
@patch('embed_video.backends.EMBED_VIDEO_TIMEOUT', 0.000001)
def test_timeout_in_get_info(self):
backend = SoundCloudBackend('https://soundcloud.com/community/soundcloud-case-study-wildlife')
self.assertRaises(requests.Timeout, backend.get_info)
def test_invalid_url(self):
""" Check if bug #21 is fixed. """
backend = SoundCloudBackend('https://soundcloud.com/xyz/foo')
self.assertRaises(VideoDoesntExistException, backend.get_info)

View file

@ -1,341 +0,0 @@
from unittest import TestCase
from mock import Mock, patch
import re
try:
# Python <= 2.7
import urlparse
except ImportError:
# Python 3
import urllib.parse as urlparse
from django.template import TemplateSyntaxError
from django.http import HttpRequest
from django.template.base import Template
from django.template.context import RequestContext
from django.test.utils import override_settings
from django.test.client import RequestFactory
from testfixtures import LogCapture
from embed_video.templatetags.embed_video_tags import VideoNode
URL_PATTERN = re.compile(r'src="?\'?([^"\'>]*)"')
class EmbedVideoNodeTestCase(TestCase):
def setUp(self):
self.parser = Mock()
self.token = Mock(methods=['split_contents'])
@staticmethod
def _grc(context=None):
return RequestContext(HttpRequest(), context)
def test_embed(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %}
{% video ytb 'large' %}
{% endvideo %}
""")
rendered = u'''<iframe width="960" height="720" src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque"
frameborder="0" allowfullscreen></iframe>'''
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_direct_embed(self):
template = Template("""
{% load embed_video_tags %}
{{ 'http://www.youtube.com/watch?v=jsrRJyHBvzw'|embed:'large' }}
""")
rendered = u'''<iframe width="960" height="720" src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque"
frameborder="0" allowfullscreen></iframe>'''
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_direct_embed_tag(self):
template = Template("""
{% load embed_video_tags %}
{% video "http://www.youtube.com/watch?v=jsrRJyHBvzw" "large" %}
""")
rendered = u'''<iframe width="960" height="720" src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque"
frameborder="0" allowfullscreen></iframe>'''
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_direct_embed_tag_with_default_size(self):
template = Template("""
{% load embed_video_tags %}
{% video "http://www.youtube.com/watch?v=jsrRJyHBvzw" %}
""")
rendered = u'''<iframe width="480" height="360" src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque"
frameborder="0" allowfullscreen></iframe>'''
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_user_size(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %}
{% video ytb '800x800' %}
{% endvideo %}
""")
rendered = u'''<iframe width="800" height="800" src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque"
frameborder="0" allowfullscreen></iframe>'''
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_wrong_size(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' 'so x huge' %}
""")
self.assertRaises(TemplateSyntaxError, template.render, self._grc())
def test_tag_youtube(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' as ytb %}
{{ ytb.url }}
{% endvideo %}
""")
rendered = 'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_tag_youtube_invalid_url(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/edit?abcd=efgh' as ytb %}
{{ ytb.url }}
{% endvideo %}
""")
self.assertEqual(template.render(self._grc()).strip(), '')
def test_tag_vimeo(self):
template = Template("""
{% load embed_video_tags %}
{% video 'https://vimeo.com/72304002' as vimeo %}
{{ vimeo.url }}
{% endvideo %}
""")
rendered = 'http://player.vimeo.com/video/72304002'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_tag_backend_variable_vimeo(self):
template = Template("""
{% load embed_video_tags %}
{% video 'https://vimeo.com/72304002' as vimeo %}
{{ vimeo.backend }}
{% endvideo %}
""")
rendered = 'VimeoBackend'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_tag_backend_variable_youtube(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvz' as youtube %}
{{ youtube.backend }}
{% endvideo %}
""")
rendered = 'YoutubeBackend'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_tag_backend_variable_soundcloud(self):
template = Template("""
{% load embed_video_tags %}
{% video 'https://soundcloud.com/community/soundcloud-case-study-wildlife' as soundcloud %}
{{ soundcloud.backend }}
{% endvideo %}
""")
rendered = 'SoundCloudBackend'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_syntax_error(self):
self.token.split_contents.return_value = []
self.assertRaises(TemplateSyntaxError, VideoNode, self.parser, self.token)
def test_repr(self):
self.token.split_contents.return_value = (
'video', 'http://youtu.be/v/1234', 'as', 'myvideo'
)
self.parser.compile_filter.return_value = u'some_url'
node = VideoNode(self.parser, self.token)
self.assertEqual(str(node), '<VideoNode "some_url">')
def test_videonode_iter(self):
out = ['a', 'b', 'c', 'd']
class FooNode(VideoNode):
nodelist_file = out
def __init__(self):
pass
node = FooNode()
self.assertEqual(out, [x for x in node])
def test_get_backend_secure(self):
class SecureRequest(RequestFactory):
is_secure = lambda x: True
context = {'request': SecureRequest()}
backend = VideoNode.get_backend('http://www.youtube.com/watch?v=jsrRJyHBvzw', context)
self.assertTrue(backend.is_secure)
def test_get_backend_insecure(self):
class InsecureRequest(RequestFactory):
is_secure = lambda x: False
context = {'request': InsecureRequest()}
backend = VideoNode.get_backend('http://www.youtube.com/watch?v=jsrRJyHBvzw', context)
self.assertFalse(backend.is_secure)
def test_no_video_provided(self):
template = Template("""
{% load embed_video_tags %}
{% video '' 'large' %}
""")
self.assertEqual(template.render(self._grc()).strip(), '')
@patch('embed_video.backends.EMBED_VIDEO_TIMEOUT', 0.000001)
def test_empty_if_timeout(self):
template = Template("""
{% load embed_video_tags %}
{% video "http://vimeo.com/72304002" as my_video %}
{{ my_video.thumbnail }}
{% endvideo %}
""")
with LogCapture() as logs:
self.assertEqual(template.render(self._grc()).strip(), '')
log = logs.records[-1]
self.assertEqual(log.name, 'embed_video.templatetags.embed_video_tags')
self.assertEqual(log.msg, 'Timeout reached during rendering embed video (`http://vimeo.com/72304002`)')
def test_relative_size(self):
template = Template("""
{% load embed_video_tags %}
{% video "http://vimeo.com/72304002" "80%x30%" %}
""")
rendered = '<iframe width="80%" height="30%" src="http://player.vimeo.com/video/72304002"' \
'\n frameborder="0" allowfullscreen></iframe>'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_allow_spaces_in_size(self):
template = Template("""
{% load embed_video_tags %}
{% video "http://vimeo.com/72304002" "80% x 300" %}
""")
rendered = '<iframe width="80%" height="300" src="http://player.vimeo.com/video/72304002"' \
'\n frameborder="0" allowfullscreen></iframe>'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_soundcloud_invalid_url(self):
template = Template("""
{% load embed_video_tags %}
{% video "https://soundcloud.com/xyz/foo" %}
""")
self.assertEqual(template.render(self._grc()).strip(), '')
##########################################################################
# Tests for adding GET query via KEY=VALUE pairs
##########################################################################
def _validate_GET_query(self, rendered, expected):
# Use this functioon to test the KEY=VALUE optional arguments to the
# templatetag because there's no guarantee that they will be appended
# to the URL query string in a particular order. By default the
# YouTube backend adds wmode=opaque to the query string, so be sure to
# include that in the expected querystring dict.
url = URL_PATTERN.search(rendered).group(1)
result = urlparse.urlparse(url)
qs = urlparse.parse_qs(result[4])
self.assertEqual(qs, expected)
@override_settings(EMBED_VIDEO_YOUTUBE_QUERY={'rel': 0, 'stop': 5})
def test_embed_with_query_settings_override(self):
# Test KEY=VALUE argument with default values provided by settings
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' %}
""")
expected = {
'rel': ['0'],
'stop': ['5'],
}
rendered = template.render(self._grc())
self._validate_GET_query(rendered, expected)
def test_embed_with_query_var(self):
# Test KEY=VALUE argument with the value resolving to a context
# variable.
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' rel=show_related loop=5 %}
""")
expected = {
'rel': ['0'],
'loop': ['5'],
'wmode': ['opaque']
}
context = {'show_related': 0}
rendered = template.render(self._grc(context))
self._validate_GET_query(rendered, expected)
def test_embed_with_query_multiple(self):
# Test multiple KEY=VALUE arguments
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' rel=0 loop=1 end=5 %}
""")
expected = {
'rel': ['0'],
'loop': ['1'],
'end': ['5'],
'wmode': ['opaque']
}
self._validate_GET_query(template.render(self._grc()), expected)
def test_embed_with_query_multiple_list(self):
# Test multiple KEY=VALUE arguments where the key is repeated multiple
# times (this is valid in a URL query).
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' rel=0 loop=1 end=5 end=6 %}
""")
expected = {
'rel': ['0'],
'loop': ['1'],
'end': ['5', '6'],
'wmode': ['opaque']
}
self._validate_GET_query(template.render(self._grc()), expected)
def test_tag_youtube_with_query(self):
# Test KEY=VALUE arguments when used as a tag block.
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' rel=0 as ytb %}
{{ ytb.url }}
{% endvideo %}
""")
rendered = 'http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque&rel=0'
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_embed_with_query_rel(self):
template = Template("""
{% load embed_video_tags %}
{% video 'http://www.youtube.com/watch?v=jsrRJyHBvzw' rel=0 %}
""")
rendered = u'''<iframe width="480" height="360" src="http://www.youtube.com/embed/jsrRJyHBvzw?wmode=opaque&rel=0"
frameborder="0" allowfullscreen></iframe>'''
self.assertEqual(template.render(self._grc()).strip(), rendered)
def test_none_variable_passed_to_tag(self):
"""
Checks issue #24.
"""
template = Template("""
{% with None as my_video %}
{% load embed_video_tags %}
{% video my_video %}
{% endwith %}
""")
self.assertEqual(template.render(self._grc()).strip(), '')