from django import get_version as django_version
from django.forms import Media
from django.test import TestCase

from pipeline.forms import PipelineFormMedia

from ..utils import pipeline_settings


@pipeline_settings(
    PIPELINE_COLLECTOR_ENABLED=False,
    STYLESHEETS={
        "styles1": {
            "source_filenames": (
                "pipeline/css/first.css",
                "pipeline/css/second.css",
            ),
            "output_filename": "styles1.min.css",
        },
        "styles2": {
            "source_filenames": ("pipeline/css/unicode.css",),
            "output_filename": "styles2.min.css",
        },
        "print": {
            "source_filenames": ("pipeline/css/urls.css",),
            "output_filename": "print.min.css",
        },
    },
    JAVASCRIPT={
        "scripts1": {
            "source_filenames": (
                "pipeline/js/first.js",
                "pipeline/js/second.js",
            ),
            "output_filename": "scripts1.min.js",
        },
        "scripts2": {
            "source_filenames": ("pipeline/js/application.js",),
            "output_filename": "scripts2.min.js",
        },
    },
)
class PipelineFormMediaTests(TestCase):
    """Unit tests for pipeline.forms.PipelineFormMedia."""

    @pipeline_settings(PIPELINE_ENABLED=True)
    def test_css_packages_with_pipeline_enabled(self):
        """Testing PipelineFormMedia.css_packages with PIPELINE_ENABLED=True"""

        class MyMedia(PipelineFormMedia):
            css_packages = {
                "all": ("styles1", "styles2"),
                "print": ("print",),
            }

            css = {"all": ("extra1.css", "extra2.css")}

        media = Media(MyMedia)

        self.assertEqual(
            MyMedia.css,
            {
                "all": [
                    "extra1.css",
                    "extra2.css",
                    "/static/styles1.min.css",
                    "/static/styles2.min.css",
                ],
                "print": ["/static/print.min.css"],
            },
        )
        self.assertEqual(MyMedia.css, media._css)
        expected_regex = [
            r'<link href="{}"( type="text/css")? media="all" '
            'rel="stylesheet"( /)?>'.format(path)
            for path in (
                "/static/extra1.css",
                "/static/extra2.css",
                "/static/styles1.min.css",
                "/static/styles2.min.css",
            )
        ] + [
            r'<link href="/static/print.min.css" (type="text/css" )?'
            'media="print" rel="stylesheet"( /)?>'
        ]
        for rendered_node, expected_node in zip(media.render_css(), expected_regex):
            self.assertRegex(rendered_node, expected_node)

    @pipeline_settings(PIPELINE_ENABLED=False)
    def test_css_packages_with_pipeline_disabled(self):
        """Testing PipelineFormMedia.css_packages with PIPELINE_ENABLED=False"""

        class MyMedia(PipelineFormMedia):
            css_packages = {
                "all": ("styles1", "styles2"),
                "print": ("print",),
            }

            css = {"all": ("extra1.css", "extra2.css")}

        media = Media(MyMedia)

        self.assertEqual(
            MyMedia.css,
            {
                "all": [
                    "extra1.css",
                    "extra2.css",
                    "pipeline/css/first.css",
                    "pipeline/css/second.css",
                    "pipeline/css/unicode.css",
                ],
                "print": ["pipeline/css/urls.css"],
            },
        )
        self.assertEqual(MyMedia.css, media._css)

        expected_regex = [
            '<link href="{}"( type="text/css")? media="all" '
            'rel="stylesheet"( /)?>'.format(path)
            for path in (
                "/static/extra1.css",
                "/static/extra2.css",
                "/static/pipeline/css/first.css",
                "/static/pipeline/css/second.css",
                "/static/pipeline/css/unicode.css",
            )
        ] + [
            '<link href="/static/pipeline/css/urls.css" (type="text/css" )?'
            'media="print" rel="stylesheet"( /)?>'
        ]
        for rendered_node, expected_node in zip(media.render_css(), expected_regex):
            self.assertRegex(rendered_node, expected_node)

    @pipeline_settings(PIPELINE_ENABLED=True)
    def test_js_packages_with_pipeline_enabled(self):
        """Testing PipelineFormMedia.js_packages with PIPELINE_ENABLED=True"""

        class MyMedia(PipelineFormMedia):
            js_packages = ("scripts1", "scripts2")
            js = ("extra1.js", "extra2.js")

        media = Media(MyMedia)

        if django_version() < "3.1":
            script_tag = '<script type="text/javascript" src="%s"></script>'
        else:
            script_tag = '<script src="%s"></script>'

        self.assertEqual(
            MyMedia.js,
            [
                "extra1.js",
                "extra2.js",
                "/static/scripts1.min.js",
                "/static/scripts2.min.js",
            ],
        )
        self.assertEqual(MyMedia.js, media._js)
        self.assertEqual(
            media.render_js(),
            [
                script_tag % path
                for path in (
                    "/static/extra1.js",
                    "/static/extra2.js",
                    "/static/scripts1.min.js",
                    "/static/scripts2.min.js",
                )
            ],
        )

    @pipeline_settings(PIPELINE_ENABLED=False)
    def test_js_packages_with_pipeline_disabled(self):
        """Testing PipelineFormMedia.js_packages with PIPELINE_ENABLED=False"""

        class MyMedia(PipelineFormMedia):
            js_packages = ("scripts1", "scripts2")
            js = ("extra1.js", "extra2.js")

        media = Media(MyMedia)

        if django_version() < "3.1":
            script_tag = '<script type="text/javascript" src="%s"></script>'
        else:
            script_tag = '<script src="%s"></script>'

        self.assertEqual(
            MyMedia.js,
            [
                "extra1.js",
                "extra2.js",
                "pipeline/js/first.js",
                "pipeline/js/second.js",
                "pipeline/js/application.js",
            ],
        )
        self.assertEqual(MyMedia.js, media._js)
        self.assertEqual(
            media.render_js(),
            [
                script_tag % path
                for path in (
                    "/static/extra1.js",
                    "/static/extra2.js",
                    "/static/pipeline/js/first.js",
                    "/static/pipeline/js/second.js",
                    "/static/pipeline/js/application.js",
                )
            ],
        )
