# Copyright © The Debusine Developers
# See the AUTHORS file at the top-level directory of this distribution
#
# This file is part of Debusine. It is subject to the license terms
# in the LICENSE file found in the top-level directory of this
# distribution. No part of Debusine, including this file, may be copied,
# modified, propagated, or distributed except according to the terms
# contained in the LICENSE file.

"""Tests for the view tests utilities."""
import lxml
import lxml.objectify
from django.urls import reverse
from rest_framework import status

from debusine.test.django import TestCase
from debusine.web.views.tests.utils import ViewTestMixin


class TestWebUtils(ViewTestMixin, TestCase):
    """Tests for view test utility code."""

    def test_invalid_html(self) -> None:
        """Test warnings on invalid HTML."""
        response = self.client.get(reverse("homepage:homepage"))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        response.content = b"<!DOCTYPE html><html><does-not-exist></html>"
        with self.assertRaisesRegex(
            AssertionError, r"1:HTML_UNKNOWN_TAG:Tag does-not-exist invalid"
        ):
            self.assertHTMLValid(response)

        response.content = b"<!DOCTYPE html><html"
        with self.assertRaisesRegex(
            AssertionError,
            r"1:ERR_GT_REQUIRED:Couldn't find end of Start Tag html",
        ):
            self.assertHTMLValid(response)

    def test_workspace_list_not_found(self) -> None:
        """Test that workspace_list_table_rows errors when not found."""
        default_workspace = self.playground.get_default_workspace()
        default_workspace.public = False
        default_workspace.save()

        response = self.client.get(reverse("homepage:homepage"))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        tree = self.assertHTMLValid(response)
        with self.assertRaisesRegex(
            AssertionError, r"page has no workspace list table"
        ):
            self.workspace_list_table_rows(tree)

    def test_collection_list_not_found(self) -> None:
        """Test that collection_list_table_rows errors when not found."""
        response = self.client.get(reverse("homepage:homepage"))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        tree = self.assertHTMLValid(response)
        with self.assertRaisesRegex(
            AssertionError, r"page has no collection list table"
        ):
            self.collection_list_table_rows(tree)

    def test_assert_html_contents_equivalent(self) -> None:
        """Test that assertHTMLContentsEquivalent works as expected."""
        node = lxml.objectify.fromstring(
            '<span> some  na\n\n (<abbr title="Ext">E</abbr>)\n\n</span>\n     '
        )

        self.assertHTMLContentsEquivalent(
            node, '<span>some    na (<abbr title="Ext">E</abbr>)</span>'
        )

        with self.assertRaises(AssertionError):
            self.assertHTMLContentsEquivalent(node, "<span>Sample</span>")

        with self.assertRaises(AssertionError):
            self.assertHTMLContentsEquivalent(
                node, '<span>so me    na (<abbr title="Ext">E</abbr>)</span>'
            )

    def test_assert_has_element(self) -> None:
        """Test that assertHasElement works as expected."""
        tree = lxml.objectify.fromstring("<p><b>this</b> is a <b>test</b></p>")

        p = self.assertHasElement(tree, "//p")
        self.assertTextContentEqual(p, "this is a test")

        with self.assertRaisesRegex(AssertionError, "'//i' not found in tree"):
            self.assertHasElement(tree, "//i")
        with self.assertRaisesRegex(
            AssertionError, "'//b' matched 2 elements instead of one"
        ):
            self.assertHasElement(tree, "//b")

    def test_assert_enforces_permission_target_name(self) -> None:
        """Test assertEnforcesPermission target_name resolution."""
        artifact, _ = self.playground.create_artifact()

        self.assertEnforcesPermission(
            artifact.can_display,
            artifact.get_absolute_url(),
            "get_context_data",
        )
        self.assertEnforcesPermission(
            artifact.can_display,
            artifact.get_absolute_url(),
            "debusine.web.views.artifacts.ArtifactDetailView.get_context_data",
        )
