# (c) cavaliba.com - tests / dataview "query" vs the user's own query

"""
A dataview's "query" is loaded into the search box on an explicit ?dv= switch
only, and never beats a query the request itself carries. The tricky one:
cv-search-form has action="", so submitting it from ".../list/?dv=NAME" POSTs
back to that same URL with "dv" still in request.GET - the query the user just
typed must win there.

Also: a view with an empty query doesn't clear the current filter, and a query
with characters the search box itself would reject is ignored.
"""

from django.test import TestCase, override_settings
from django.urls import reverse

import app_home.cache as cache
from tests import helper

CLASSNAME = "dvqprec"
COLUMNS = "columns:\n  - keyname\n  - status\n"


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class TestDataViewQueryPrecedence(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_admin_user(login="unittest")
        helper.add_schema(
            classname=CLASSNAME,
            field_definition={"status": {"dataformat": "string", "displayname": "Status"}},
        )
        helper.add_instance(classname=CLASSNAME, keyname="obj-ok", fields={"status": "ok"})
        helper.add_instance(classname=CLASSNAME, keyname="obj-old", fields={"status": "obsolete"})
        helper.add_instance(
            classname="_dataview",
            keyname="dvqprec_obsolete",
            fields={
                "target_class": CLASSNAME,
                "query": "status:obsolete",
                "content": COLUMNS,
            },
        )
        # no query at all: must leave whatever filter is in place alone
        helper.add_instance(
            classname="_dataview",
            keyname="dvqprec_all",
            fields={"target_class": CLASSNAME, "content": COLUMNS},
        )
        # a comma is outside the search box's own allowed characters
        helper.add_instance(
            classname="_dataview",
            keyname="dvqprec_bad",
            fields={
                "target_class": CLASSNAME,
                "query": "status:ok,obsolete",
                "content": COLUMNS,
            },
        )
        self.url = reverse("app_data:instance_list", kwargs={"classname": CLASSNAME})

    def test_typed_query_wins_over_dv_still_in_the_url(self):
        response = self.client.post(
            f"{self.url}?dv=dvqprec_obsolete", {"query": "status:ok"}, follow=True
        )
        self.assertContains(response, 'value="status:ok"')
        self.assertNotContains(response, 'value="status:obsolete"')

    def test_typed_query_filters_the_rows_not_the_view_query(self):
        response = self.client.post(
            f"{self.url}?dv=dvqprec_obsolete", {"query": "status:ok"}, follow=True
        )
        content = response.content.decode()
        self.assertIn("obj-ok", content)
        self.assertNotIn("obj-old", content)

    def test_pagination_does_not_re_apply_the_view_query(self):
        self.client.get(self.url, {"dv": "dvqprec_obsolete"})
        self.client.post(self.url, {"query": "status:ok"})

        response = self.client.get(self.url, {"page": 1, "size": 10})

        self.assertContains(response, 'value="status:ok"')
        self.assertNotContains(response, 'value="status:obsolete"')

    def test_view_without_a_query_leaves_the_current_filter_alone(self):
        self.client.post(self.url, {"query": "status:ok"})

        response = self.client.get(self.url, {"dv": "dvqprec_all"})

        self.assertContains(response, 'value="status:ok"')

    def test_invalid_view_query_is_ignored(self):
        response = self.client.get(self.url, {"dv": "dvqprec_bad"})

        self.assertNotContains(response, "status:ok,obsolete")
        content = response.content.decode()
        self.assertIn("obj-ok", content)
        self.assertIn("obj-old", content)
