Added the CSS specification for the video class. It is pretty much a duplicate of the image css.

Code for the video extra has been extracted to a function to clean up a bit the if/elif/elif that is starting to
get pretty big. Maybe the other conditions could be extracted to their own method to clean up a bit. Once again,
there seems to be a lot of code duplication with image, so we may want to refactor images, videos, and audio as
a media type and have some kind of template method.

Basic unit tests were added to make sure that the extra was correctly added to the report when the extra was
requested.
This commit is contained in:
Maxime Jacob 2020-02-01 21:01:19 -05:00
parent 8de28f6d1f
commit f03b9d9a4b
3 changed files with 75 additions and 32 deletions

View File

@ -236,38 +236,7 @@ class HTMLReport:
href = extra.get("content")
elif extra.get("format") == extras.FORMAT_VIDEO:
video_base = (
'<video controls>\n<source src={} type="video/mp4">\n</video>'
)
content = extra.get("content")
try:
is_uri_or_path = content.startswith(("file", "http")) or isfile(
content
)
except ValueError:
# On Windows, os.path.isfile throws this exception when
# passed a b64 encoded image.
is_uri_or_path = False
if is_uri_or_path:
if self.self_contained:
warnings.warn(
"Self-contained HTML report "
"includes link to external "
"resource: {}".format(content)
)
html_div = html.div(raw(video_base.format(extra.get("content"))))
elif self.self_contained:
src = "data:{};base64,{}".format(extra.get("mime_type"), content)
html_div = html.div(raw(video_base.format(src)))
else:
content = b64decode(content.encode("utf-8"))
href = src = self.create_asset(
content, extra_index, test_index, extra.get("extension"), "wb"
)
html_div = html.a(video_base.format(src), href=href)
self.additional_html.append(html.div(html_div, class_="video"))
self._append_video(extra, extra_index, test_index)
if href is not None:
self.links_html.append(
@ -310,6 +279,36 @@ class HTMLReport:
log.append("No log output captured.")
additional_html.append(log)
def _append_video(self, extra, extra_index, test_index):
video_base = '<video controls><source src="{}" type="video/mp4"></video>'
content = extra.get("content")
try:
is_uri_or_path = content.startswith(("file", "http")) or isfile(content)
except ValueError:
# On Windows, os.path.isfile throws this exception when
# passed a b64 encoded image.
is_uri_or_path = False
if is_uri_or_path:
if self.self_contained:
warnings.warn(
"Self-contained HTML report "
"includes link to external "
"resource: {}".format(content)
)
html_div = html.div(raw(video_base.format(extra.get("content"))))
elif self.self_contained:
src = "data:{};base64,{}".format(extra.get("mime_type"), content)
html_div = html.div(raw(video_base.format(src)))
else:
content = b64decode(content.encode("utf-8"))
href = src = self.create_asset(
content, extra_index, test_index, extra.get("extension"), "wb"
)
html_div = html.a(video_base.format(src), href=href)
self.additional_html.append(html.div(html_div, class_="video"))
def _appendrow(self, outcome, report):
result = self.TestResult(outcome, report, self.logfile, self.config)
if result.row_table is not None:

View File

@ -113,6 +113,19 @@ div.image {
div.image img {
width: 320px
}
div.video {
border: 1px solid #e6e6e6;
float: right;
height: 240px;
margin-left: 5px;
overflow: hidden;
width: 320px
}
div.video video {
overflow: hidden;
width: 320px;
height: 240px;
}
.collapsed {
display: none;
}

View File

@ -418,6 +418,37 @@ class TestHTML:
self.test_extra_image(testdir, "image/png", "png")
assert mock_isfile.call_count == 1
@pytest.mark.parametrize(
"mime_type, extension", [("video/mp4", "mp4")],
)
def test_extra_video(self, testdir, mime_type, extension):
content = str(random.random())
testdir.makeconftest(
f"""
import pytest
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
if report.when == 'call':
from pytest_html import extras
report.extra = [extras.{extension}('{content}')]
"""
)
testdir.makepyfile("def test_pass(): pass")
result, html = run(testdir, "report.html", "--self-contained-html")
assert result.ret == 0
src = f"data:{mime_type};base64,{content}"
assert (
f'<video controls><source src="{src}" type="{mime_type}"></video>' in html
)
def test_extra_video_windows(self, mocker, testdir):
mock_isfile = mocker.patch("pytest_html.plugin.isfile")
mock_isfile.side_effect = ValueError("stat: path too long for Windows")
self.test_extra_video(testdir, "video/mp4", "mp4")
assert mock_isfile.call_count == 1
@pytest.mark.parametrize(
"content", [("u'\u0081'"), ("'foo'"), ("b'\\xe2\\x80\\x93'")]
)