"""Tests for python-markdown-oembed extension."""
from __future__ import annotations
import json
import re
import warnings
from unittest.mock import MagicMock, patch
import markdown
import pytest
from mdx_oembed import endpoints
from mdx_oembed.inlinepatterns import OEMBED_LINK_RE, _is_image_url, _sanitize_html
from mdx_oembed.oembed import (
OEmbedConsumer,
OEmbedEndpoint,
OEmbedError,
OEmbedNoEndpoint,
)
# ---------------------------------------------------------------------------
# Regex tests
# ---------------------------------------------------------------------------
_OEMBED_RE = re.compile(OEMBED_LINK_RE)
def test_ignore_relative_image_link():
assert _OEMBED_RE.search("") is None
def test_match_absolute_url():
m = _OEMBED_RE.search("")
assert m is not None
def test_match_youtube_link():
m = _OEMBED_RE.search("")
assert m is not None
assert m.group(2) == "http://www.youtube.com/watch?v=ABC"
def test_match_youtube_short_link():
m = _OEMBED_RE.search("")
assert m is not None
def test_match_https():
m = _OEMBED_RE.search("")
assert m is not None
def test_match_protocol_relative():
m = _OEMBED_RE.search("")
assert m is not None
def test_alt_text_captured():
m = _OEMBED_RE.search("")
assert m is not None
assert m.group(1) == "my alt text"
# ---------------------------------------------------------------------------
# Image URL detection
# ---------------------------------------------------------------------------
@pytest.mark.parametrize(
"ext",
["png", "jpg", "jpeg", "gif", "webp", "avif", "svg", "bmp", "tiff", "ico"],
)
def test_common_image_extensions(ext: str):
assert _is_image_url(f"http://example.com/photo.{ext}") is True
def test_image_url_case_insensitive():
assert _is_image_url("http://example.com/Photo.PNG") is True
assert _is_image_url("http://example.com/photo.JpEg") is True
def test_image_url_query_string_ignored():
assert _is_image_url("http://example.com/photo.jpg?size=large") is True
def test_non_image_url():
assert _is_image_url("http://www.youtube.com/watch?v=ABC") is False
def test_no_extension_url():
assert _is_image_url("http://example.com/embed") is False
# ---------------------------------------------------------------------------
# HTML sanitization
# ---------------------------------------------------------------------------
def test_sanitize_allows_iframe():
html = (
''
)
result = _sanitize_html(html)
assert "", "type": "video"}).encode()
mock_resp = MagicMock()
mock_resp.status = 200
mock_resp.read.return_value = body
mock_resp.headers.get_content_charset.return_value = "utf-8"
mock_resp.__enter__ = MagicMock(return_value=mock_resp)
mock_resp.__exit__ = MagicMock(return_value=False)
with patch("mdx_oembed.oembed.urlopen", return_value=mock_resp):
data = consumer.embed("http://example.com/video/1")
assert data["html"] == ""
# ---------------------------------------------------------------------------
# Extension integration tests (mocked HTTP)
# ---------------------------------------------------------------------------
def _make_mock_consumer(
html_response: str = "",
) -> MagicMock:
"""Create a mock OEmbedConsumer that returns the given HTML."""
consumer = MagicMock()
data = {"html": html_response, "type": "video"}
response = MagicMock()
response.get = lambda key, default=None: data.get(key, default)
response.__getitem__ = lambda self_inner, key: data[key]
consumer.embed.return_value = response
return consumer
def _make_photo_consumer(
photo_url: str = "https://example.com/photo.jpg",
width: int = 640,
height: int = 480,
) -> MagicMock:
consumer = MagicMock()
data = {"type": "photo", "url": photo_url, "width": width, "height": height}
response = MagicMock()
response.get = lambda key, default=None: data.get(key, default)
response.__getitem__ = lambda self_inner, key: data[key]
consumer.embed.return_value = response
return consumer
def _make_failing_consumer(
exc_class: type[Exception] = Exception, msg: str = "fail"
) -> MagicMock:
consumer = MagicMock()
consumer.embed.side_effect = exc_class(msg)
return consumer
def _convert(
text: str,
consumer: MagicMock | None = None,
**ext_config: object,
) -> str:
"""Helper: convert markdown with a mocked consumer."""
if consumer is None:
consumer = _make_mock_consumer()
with patch("mdx_oembed.extension.OEmbedConsumer", return_value=consumer):
md = markdown.Markdown(
extensions=["oembed"],
extension_configs={"oembed": ext_config} if ext_config else {},
)
return md.convert(text)
# --- basic embedding ---
def test_youtube_embed():
output = _convert("")
assert "