Hello community,

here is the log from the commit of package python-pytest-html for 
openSUSE:Factory checked in at 2020-03-19 19:48:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pytest-html (Old)
 and      /work/SRC/openSUSE:Factory/.python-pytest-html.new.3160 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pytest-html"

Thu Mar 19 19:48:15 2020 rev:9 rq:785474 version:2.1.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pytest-html/python-pytest-html.changes    
2020-03-04 09:41:25.489964443 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-pytest-html.new.3160/python-pytest-html.changes
  2020-03-19 19:51:20.932220461 +0100
@@ -1,0 +2,10 @@
+Mon Mar 16 08:28:48 UTC 2020 - Tomáš Chvátal <[email protected]>
+
+- Update to 2.1.0:
+  * Added support for MP4 video format. (#260)
+  * Added support for sorting metadata by key. (#245)
+  * Added support for rendering reports collapsed (#239)
+  * Added extra fixture (#269)
+  * Added ability to change report title using hook (#270)
+
+-------------------------------------------------------------------

Old:
----
  pytest-html-2.0.1.tar.gz

New:
----
  pytest-html-2.1.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pytest-html.spec ++++++
--- /var/tmp/diff_new_pack.AY1ZeH/_old  2020-03-19 19:51:23.808222122 +0100
+++ /var/tmp/diff_new_pack.AY1ZeH/_new  2020-03-19 19:51:23.812222124 +0100
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           python-pytest-html
-Version:        2.0.1
+Version:        2.1.0
 Release:        0
 Summary:        Pytest plugin for generating HTML reports
 License:        MPL-2.0

++++++ pytest-html-2.0.1.tar.gz -> pytest-html-2.1.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/CHANGES.rst 
new/pytest-html-2.1.0/CHANGES.rst
--- old/pytest-html-2.0.1/CHANGES.rst   2019-11-18 22:25:48.000000000 +0100
+++ new/pytest-html-2.1.0/CHANGES.rst   2020-03-11 13:38:36.000000000 +0100
@@ -1,19 +1,41 @@
 Release Notes
 -------------
 
+**2.1.0 (2020-03-09)**
+
+* Added support for MP4 video format. (`#260 
<https://github.com/pytest-dev/pytest-html/pull/260>`_)
+
+  * Thanks to `@ExaltedBagel <https://github.com/ExaltedBagel>`_ for the PR
+
+* Added support for sorting metadata by key. (`#245 
<https://github.com/pytest-dev/pytest-html/issues/245>`_)
+
+  * Thanks to `@ssbarnea <https://github.com/ssbarnea>`_ for reporting and 
`@ExaltedBagel <https://github.com/ExaltedBagel>`_ for the fix
+
+* Added support for rendering reports collapsed (`#239 
<https://github.com/pytest-dev/pytest-html/issues/239>`_)
+
+  * Thanks to `@Wramberg <https://github.com/Wramberg>`_ for suggesting this 
enhancement
+
+* Added `extra` fixture (`#269 
<https://github.com/pytest-dev/pytest-html/pull/269>`_)
+
+  * Thanks to `@christiansandberg <https://github.com/christiansandberg>`_ for 
the PR
+
+* Added ability to change report title using hook (`#270 
<https://github.com/pytest-dev/pytest-html/pull/270>`_)
+
+  * Thanks to `@werdeil <https://github.com/werdeil>`_ for the PR
+
 **2.0.1 (2019-10-05)**
 
 * Properly check for presence of CSS file. (`#246 
<https://github.com/pytest-dev/pytest-html/issues/246>`_)
 
-    * Thanks to `@wanam <https://github.com/wanam>`_ for reporting, and 
`@krzysztof-pawlik-gat <https://github.com/krzysztof-pawlik-gat>`_ for the fix
+  * Thanks to `@wanam <https://github.com/wanam>`_ for reporting, and 
`@krzysztof-pawlik-gat <https://github.com/krzysztof-pawlik-gat>`_ for the fix
 
 * Added support for UTF-8 display. (`#244 
<https://github.com/pytest-dev/pytest-html/pull/244>`_)
 
-    * Thanks to `@Izhu666 <https://github.com/lzhu666>`_ for the PR
+  * Thanks to `@Izhu666 <https://github.com/lzhu666>`_ for the PR
 
 * Fix initial sort on column. (`#247 
<https://github.com/pytest-dev/pytest-html/issues/247>`_)
 
-    * Thanks to `@wanam <https://github.com/wanam>`_ for reporting and fixing
+  * Thanks to `@wanam <https://github.com/wanam>`_ for reporting and fixing
 
 **2.0.0 (2019-09-09)**
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/PKG-INFO 
new/pytest-html-2.1.0/PKG-INFO
--- old/pytest-html-2.0.1/PKG-INFO      2019-11-18 22:26:15.000000000 +0100
+++ new/pytest-html-2.1.0/PKG-INFO      2020-03-11 13:38:57.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: pytest-html
-Version: 2.0.1
+Version: 2.1.0
 Summary: pytest plugin for generating HTML reports
 Home-page: https://github.com/pytest-dev/pytest-html
 Author: Dave Hunt
@@ -95,6 +95,19 @@
         
           $ pytest --html=report.html --css=highcontrast.css 
--css=accessible.css
         
+        Report Title
+        ~~~~~~~~~~~~
+        
+        By default report title will be the filename of the report, you can 
edit it by using the :code: `pytest_html_report_title` hook:
+        
+        .. code-block:: python
+        
+           import pytest
+           from py.xml import html
+        
+           def pytest_html_report_title(report)
+              report.title = "My very own title!"
+        
         Environment
         ~~~~~~~~~~~
         
@@ -187,6 +200,17 @@
         
             extra.append(pytest_html.extras.text('some string', 
name='Different title'))
         
+        It is also possible to use the fixture :code:`extra` to add content 
directly
+        in a test function without implementing hooks. These will generally 
end up
+        before any extras added by plugins.
+        
+        .. code-block:: python
+        
+           from pytest_html import extras
+        
+           def test_extra(extra):
+              extra.append(extras.text('some string'))
+        
         
         Modifying the results table
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -248,8 +272,15 @@
         
         By default, all rows in the **Results** table will be expanded except 
those that have :code:`Passed`.
         
-        This behavior can be customized with a query parameter: 
:code:`?collapsed=Passed,XFailed,Skipped`.
+        This behavior can be customized either with a query parameter: 
:code:`?collapsed=Passed,XFailed,Skipped`
+        or by setting the :code:`render_collapsed` in a configuration file 
(pytest.ini, setup.cfg, etc).
+        
+        .. code-block:: ini
+        
+          [pytest]
+          render_collapsed = True
         
+        **NOTE:** Setting :code:`render_collapsed` will, unlike the query 
parameter, affect all statuses.
         
         Screenshots
         -----------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/README.rst 
new/pytest-html-2.1.0/README.rst
--- old/pytest-html-2.0.1/README.rst    2019-11-18 22:25:48.000000000 +0100
+++ new/pytest-html-2.1.0/README.rst    2020-03-11 13:38:36.000000000 +0100
@@ -87,6 +87,19 @@
 
   $ pytest --html=report.html --css=highcontrast.css --css=accessible.css
 
+Report Title
+~~~~~~~~~~~~
+
+By default report title will be the filename of the report, you can edit it by 
using the :code: `pytest_html_report_title` hook:
+
+.. code-block:: python
+
+   import pytest
+   from py.xml import html
+
+   def pytest_html_report_title(report)
+      report.title = "My very own title!"
+
 Environment
 ~~~~~~~~~~~
 
@@ -179,6 +192,17 @@
 
     extra.append(pytest_html.extras.text('some string', name='Different 
title'))
 
+It is also possible to use the fixture :code:`extra` to add content directly
+in a test function without implementing hooks. These will generally end up
+before any extras added by plugins.
+
+.. code-block:: python
+
+   from pytest_html import extras
+
+   def test_extra(extra):
+      extra.append(extras.text('some string'))
+
 
 Modifying the results table
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -240,8 +264,15 @@
 
 By default, all rows in the **Results** table will be expanded except those 
that have :code:`Passed`.
 
-This behavior can be customized with a query parameter: 
:code:`?collapsed=Passed,XFailed,Skipped`.
+This behavior can be customized either with a query parameter: 
:code:`?collapsed=Passed,XFailed,Skipped`
+or by setting the :code:`render_collapsed` in a configuration file 
(pytest.ini, setup.cfg, etc).
+
+.. code-block:: ini
+
+  [pytest]
+  render_collapsed = True
 
+**NOTE:** Setting :code:`render_collapsed` will, unlike the query parameter, 
affect all statuses.
 
 Screenshots
 -----------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/pytest_html/extras.py 
new/pytest-html-2.1.0/pytest_html/extras.py
--- old/pytest-html-2.0.1/pytest_html/extras.py 2019-11-18 22:25:48.000000000 
+0100
+++ new/pytest-html-2.1.0/pytest_html/extras.py 2020-03-11 13:38:36.000000000 
+0100
@@ -7,6 +7,7 @@
 FORMAT_JSON = "json"
 FORMAT_TEXT = "text"
 FORMAT_URL = "url"
+FORMAT_VIDEO = "video"
 
 
 def extra(content, format, name=None, mime_type=None, extension=None):
@@ -49,3 +50,11 @@
 
 def url(content, name="URL"):
     return extra(content, FORMAT_URL, name)
+
+
+def video(content, name="Video", mime_type="video/mp4", extension="mp4"):
+    return extra(content, FORMAT_VIDEO, name, mime_type, extension)
+
+
+def mp4(content, name="Video"):
+    return video(content, name)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/pytest_html/hooks.py 
new/pytest-html-2.1.0/pytest_html/hooks.py
--- old/pytest-html-2.0.1/pytest_html/hooks.py  2019-11-18 22:25:48.000000000 
+0100
+++ new/pytest-html-2.1.0/pytest_html/hooks.py  2020-03-11 13:38:36.000000000 
+0100
@@ -3,6 +3,10 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
+def pytest_html_report_title(report):
+    """ Called before adding the title to the report """
+
+
 def pytest_html_results_summary(prefix, summary, postfix):
     """ Called before adding the summary section to the report """
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/pytest_html/plugin.py 
new/pytest-html-2.1.0/pytest_html/plugin.py
--- old/pytest-html-2.0.1/pytest_html/plugin.py 2019-11-18 22:25:48.000000000 
+0100
+++ new/pytest-html-2.1.0/pytest_html/plugin.py 2020-03-11 13:38:36.000000000 
+0100
@@ -15,6 +15,7 @@
 import re
 
 from html import escape
+import pytest
 
 try:
     from ansi2html import Ansi2HTMLConverter, style
@@ -62,6 +63,12 @@
         default=[],
         help="append given css file content to report style file.",
     )
+    parser.addini(
+        "render_collapsed",
+        type="bool",
+        default=False,
+        help="Open the report with all rows collapsed. Useful for very large 
reports",
+    )
 
 
 def pytest_configure(config):
@@ -83,6 +90,29 @@
         config.pluginmanager.unregister(html)
 
 
[email protected](tryfirst=True, hookwrapper=True)
+def pytest_runtest_makereport(item, call):
+    outcome = yield
+    report = outcome.get_result()
+    if report.when == "call":
+        fixture_extras = item.funcargs.get("extra", [])
+        plugin_extras = getattr(report, "extra", [])
+        report.extra = fixture_extras + plugin_extras
+
+
[email protected]
+def extra():
+    """Add details to the HTML reports.
+
+    .. code-block:: python
+
+        import pytest_html
+        def test_foo(extra):
+            extra.append(pytest_html.extras.url('http://www.example.com/'))
+    """
+    return []
+
+
 def data_uri(content, mime_type="text/plain", charset="utf-8"):
     data = b64encode(content.encode(charset)).decode("ascii")
     return f"data:{mime_type};charset={charset};base64,{data}"
@@ -93,6 +123,7 @@
         logfile = os.path.expanduser(os.path.expandvars(logfile))
         self.logfile = os.path.abspath(logfile)
         self.test_logs = []
+        self.title = os.path.basename(self.logfile)
         self.results = []
         self.errors = self.failed = 0
         self.passed = self.skipped = 0
@@ -137,9 +168,13 @@
             )
 
             if len(cells) > 0:
+                tr_class = None
+                if self.config.getini("render_collapsed"):
+                    tr_class = "collapsed"
                 self.row_table = html.tr(cells)
                 self.row_extra = html.tr(
-                    html.td(self.additional_html, class_="extra", 
colspan=len(cells))
+                    html.td(self.additional_html, class_="extra", 
colspan=len(cells)),
+                    class_=tr_class,
                 )
 
         def __lt__(self, other):
@@ -181,33 +216,7 @@
         def append_extra_html(self, extra, extra_index, test_index):
             href = None
             if extra.get("format") == extras.FORMAT_IMAGE:
-                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.a(html.img(src=content), href=content)
-                elif self.self_contained:
-                    src = "data:{};base64,{}".format(extra.get("mime_type"), 
content)
-                    html_div = html.img(src=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(html.img(src=src), href=href)
-                self.additional_html.append(html.div(html_div, class_="image"))
+                self._append_image(extra, extra_index, test_index)
 
             elif extra.get("format") == extras.FORMAT_HTML:
                 
self.additional_html.append(html.div(raw(extra.get("content"))))
@@ -235,6 +244,9 @@
             elif extra.get("format") == extras.FORMAT_URL:
                 href = extra.get("content")
 
+            elif extra.get("format") == extras.FORMAT_VIDEO:
+                self._append_video(extra, extra_index, test_index)
+
             if href is not None:
                 self.links_html.append(
                     html.a(
@@ -276,6 +288,52 @@
                 log.append("No log output captured.")
             additional_html.append(log)
 
+        def _make_media_html_div(
+            self, extra, extra_index, test_index, base_extra_string, 
base_extra_class
+        ):
+            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 "
+                        f"resource: {content}"
+                    )
+
+                html_div = html.a(
+                    raw(base_extra_string.format(extra.get("content"))), 
href=content
+                )
+            elif self.self_contained:
+                src = f"data:{extra.get('mime_type')};base64,{content}"
+                html_div = raw(base_extra_string.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(class_=base_extra_class, target="_blank", 
href=href)
+            return html_div
+
+        def _append_image(self, extra, extra_index, test_index):
+            image_base = '<img src="{}"/>'
+            html_div = self._make_media_html_div(
+                extra, extra_index, test_index, image_base, "image"
+            )
+            self.additional_html.append(html.div(html_div, class_="image"))
+
+        def _append_video(self, extra, extra_index, test_index):
+            video_base = '<video controls><source src="{}" 
type="video/mp4"></video>'
+            html_div = self._make_media_html_div(
+                extra, extra_index, test_index, video_base, "video"
+            )
+            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:
@@ -457,9 +515,11 @@
             __name__, os.path.join("resources", "main.js")
         ).decode("utf-8")
 
+        session.config.hook.pytest_html_report_title(report=self)
+
         body = html.body(
             html.script(raw(main_js)),
-            html.h1(os.path.basename(self.logfile)),
+            html.h1(self.title),
             html.p(
                 "Report generated on {} at {} by ".format(
                     generated.strftime("%d-%b-%Y"), 
generated.strftime("%H:%M:%S")
@@ -505,8 +565,12 @@
             if isinstance(value, str) and value.startswith("http"):
                 value = html.a(value, href=value, target="_blank")
             elif isinstance(value, (list, tuple, set)):
-                value = ", ".join(str(i) for i in value)
-            rows.append(html.tr(html.td(key), html.td(value)))
+                value = ", ".join(str(i) for i in sorted(map(str, value)))
+            elif isinstance(value, dict):
+                sorted_dict = {k: value[k] for k in sorted(value)}
+                value = json.dumps(sorted_dict)
+            raw_value_string = raw(str(value))
+            rows.append(html.tr(html.td(key), html.td(raw_value_string)))
 
         environment.append(html.table(rows, id="environment"))
         return environment
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/pytest_html/resources/main.js 
new/pytest-html-2.1.0/pytest_html/resources/main.js
--- old/pytest-html-2.0.1/pytest_html/resources/main.js 2019-11-18 
22:25:48.000000000 +0100
+++ new/pytest-html-2.1.0/pytest_html/resources/main.js 2020-03-11 
13:38:36.000000000 +0100
@@ -81,7 +81,9 @@
         var collapsed = get_query_parameter('collapsed') || 'Passed';
         var extras = elem.parentNode.nextElementSibling;
         var expandcollapse = document.createElement("span");
-        if (collapsed.includes(elem.innerHTML)) {
+        if (extras.classList.contains("collapsed")) {
+            expandcollapse.classList.add("expander")
+        } else if (collapsed.includes(elem.innerHTML)) {
             extras.classList.add("collapsed");
             expandcollapse.classList.add("expander");
         } else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/pytest_html/resources/style.css 
new/pytest-html-2.1.0/pytest_html/resources/style.css
--- old/pytest-html-2.0.1/pytest_html/resources/style.css       2019-11-18 
22:25:48.000000000 +0100
+++ new/pytest-html-2.1.0/pytest_html/resources/style.css       2020-03-11 
13:38:36.000000000 +0100
@@ -113,6 +113,19 @@
 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;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/pytest_html.egg-info/PKG-INFO 
new/pytest-html-2.1.0/pytest_html.egg-info/PKG-INFO
--- old/pytest-html-2.0.1/pytest_html.egg-info/PKG-INFO 2019-11-18 
22:26:14.000000000 +0100
+++ new/pytest-html-2.1.0/pytest_html.egg-info/PKG-INFO 2020-03-11 
13:38:57.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: pytest-html
-Version: 2.0.1
+Version: 2.1.0
 Summary: pytest plugin for generating HTML reports
 Home-page: https://github.com/pytest-dev/pytest-html
 Author: Dave Hunt
@@ -95,6 +95,19 @@
         
           $ pytest --html=report.html --css=highcontrast.css 
--css=accessible.css
         
+        Report Title
+        ~~~~~~~~~~~~
+        
+        By default report title will be the filename of the report, you can 
edit it by using the :code: `pytest_html_report_title` hook:
+        
+        .. code-block:: python
+        
+           import pytest
+           from py.xml import html
+        
+           def pytest_html_report_title(report)
+              report.title = "My very own title!"
+        
         Environment
         ~~~~~~~~~~~
         
@@ -187,6 +200,17 @@
         
             extra.append(pytest_html.extras.text('some string', 
name='Different title'))
         
+        It is also possible to use the fixture :code:`extra` to add content 
directly
+        in a test function without implementing hooks. These will generally 
end up
+        before any extras added by plugins.
+        
+        .. code-block:: python
+        
+           from pytest_html import extras
+        
+           def test_extra(extra):
+              extra.append(extras.text('some string'))
+        
         
         Modifying the results table
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -248,8 +272,15 @@
         
         By default, all rows in the **Results** table will be expanded except 
those that have :code:`Passed`.
         
-        This behavior can be customized with a query parameter: 
:code:`?collapsed=Passed,XFailed,Skipped`.
+        This behavior can be customized either with a query parameter: 
:code:`?collapsed=Passed,XFailed,Skipped`
+        or by setting the :code:`render_collapsed` in a configuration file 
(pytest.ini, setup.cfg, etc).
+        
+        .. code-block:: ini
+        
+          [pytest]
+          render_collapsed = True
         
+        **NOTE:** Setting :code:`render_collapsed` will, unlike the query 
parameter, affect all statuses.
         
         Screenshots
         -----------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-html-2.0.1/testing/test_pytest_html.py 
new/pytest-html-2.1.0/testing/test_pytest_html.py
--- old/pytest-html-2.0.1/testing/test_pytest_html.py   2019-11-18 
22:25:48.000000000 +0100
+++ new/pytest-html-2.1.0/testing/test_pytest_html.py   2020-03-11 
13:38:36.000000000 +0100
@@ -418,6 +418,35 @@
         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'")]
     )
@@ -554,6 +583,20 @@
         assert link in html
         assert os.path.exists(src)
 
+    def test_extra_fixture(self, testdir):
+        content = b64encode(b"foo").decode("ascii")
+        testdir.makepyfile(
+            f"""
+            def test_pass(extra):
+                from pytest_html import extras
+                extra.append(extras.png('{content}'))
+        """
+        )
+        result, html = run(testdir, "report.html", "--self-contained-html")
+        assert result.ret == 0
+        src = f"data:image/png;base64,{content}"
+        assert f'<img src="{src}"/>' in html
+
     def test_no_invalid_characters_in_filename(self, testdir):
         testdir.makeconftest(
             """
@@ -633,10 +676,22 @@
         assert "Environment" in html
         assert len(re.findall(content, html)) == 1
 
-    def test_environment_list_value(self, testdir):
-        content = tuple(str(random.random()) for i in range(10))
-        content += tuple(random.random() for i in range(10))
-        expected_content = ", ".join(str(i) for i in content)
+    _unsorted_tuples = [
+        ("Hello", "fzWZP6vKRv", "hello", "garAge", "123Go"),
+        (2, 4, 2, 1, 54),
+        ("Yes", 400, "5.4"),
+    ]
+    _sorted_tuples = [
+        "123Go, Hello, fzWZP6vKRv, garAge, hello",
+        "1, 2, 2, 4, 54",
+        "400, 5.4, Yes",
+    ]
+    _test_environment_list_value_data_set = zip(_unsorted_tuples, 
_sorted_tuples)
+
+    @pytest.mark.parametrize(
+        "content,expected_content", _test_environment_list_value_data_set
+    )
+    def test_environment_list_value(self, testdir, content, expected_content):
         expected_html_re = fr"<td>content</td>\n\s+<td>{expected_content}</td>"
         testdir.makeconftest(
             f"""
@@ -651,6 +706,46 @@
         assert "Environment" in html
         assert len(re.findall(expected_html_re, html)) == 1
 
+    _unordered_dict = {k: len(k) for k in _unsorted_tuples[0]}
+    _unordered_dict_expected = (
+        r'<td>content</td>\n\s+<td>{"123Go": 5, "Hello": 5, '
+        r'"fzWZP6vKRv": 10, "garAge": 6, "hello": 5}</td>'
+    )
+    _unordered_dict_with_html = {
+        "First Link": r'<a href="https://www.w3schools.com";>W3Schools</a>',
+        "Second Link": r'<a href="https://www.w3schools.com";>W2Schools</a>',
+        "Third Link": r'<a href="https://www.w3schools.com";>W4Schools</a>',
+    }
+    _unordered_dict_with_html_expected = (
+        r"<td>content</td>\n\s+<td>{"
+        r'"First Link": "<a 
href=\\"https://www.w3schools.com\\";>W3Schools</a>", '
+        r'"Second Link": "<a 
href=\\"https://www.w3schools.com\\";>W2Schools</a>", '
+        r'"Third Link": "<a 
href=\\"https://www.w3schools.com\\";>W4Schools</a>"}</td>'
+    )
+
+    @pytest.mark.parametrize(
+        "unordered_dict,expected_output",
+        [
+            (_unordered_dict, _unordered_dict_expected),
+            (_unordered_dict_with_html, _unordered_dict_with_html_expected),
+        ],
+    )
+    def test_environment_unordered_dict_value(
+        self, testdir, unordered_dict, expected_output
+    ):
+        testdir.makeconftest(
+            f"""
+            def pytest_configure(config):
+                values = dict({json.dumps(unordered_dict)})
+                config._metadata['content'] = values
+        """
+        )
+        testdir.makepyfile("def test_pass(): pass")
+        result, html = run(testdir)
+        assert result.ret == 0
+        assert "Environment" in html
+        assert len(re.findall(expected_output, html)) == 1
+
     def test_environment_ordered(self, testdir):
         testdir.makeconftest(
             """
@@ -799,3 +894,43 @@
         result, html = run(testdir)
         assert result.ret == 0
         assert r"\u6d4b\u8bd5\u7528\u4f8b\u540d\u79f0" not in html
+
+    @pytest.mark.parametrize("is_collapsed", [True, False])
+    def test_collapsed(self, testdir, is_collapsed):
+        collapsed_html = '<tr class="collapsed">'
+        expected_count = 2 if is_collapsed else 0
+        testdir.makeini(
+            f"""
+            [pytest]
+            render_collapsed = {is_collapsed}
+        """
+        )
+        testdir.makepyfile(
+            """
+            def test_fail():
+                assert False
+
+            def test_pass():
+                assert True
+        """
+        )
+        result, html = run(testdir)
+        assert result.ret == 1
+        assert len(re.findall(collapsed_html, html)) == expected_count
+        assert_results(html, tests=2, passed=1, failed=1)
+
+    def test_custom_content_report_title(self, testdir):
+        content_report_title = str(random.random())
+        testdir.makeconftest(
+            f"""
+            import pytest
+            from py.xml import html
+
+            def pytest_html_report_title(report):
+                report.title = "title is {content_report_title}"
+        """
+        )
+        testdir.makepyfile("def test_pass(): pass")
+        result, html = run(testdir)
+        assert result.ret == 0
+        assert len(re.findall(content_report_title, html)) == 1


Reply via email to