# (c) cavaliba.com - tests / views_task - task detail Stop button vs task state

"""
The detail page polls itself while the task is live, swapping only
#datatask-detail-card. Anything rendered outside that element keeps the state it
had on first load - so the Stop button has to be inside it, or a task finishing
while the page is open leaves an enabled Stop button behind (abort_task() then
refuses it as not_running).
"""

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

import app_home.cache as cache
from app_data.tasks import create_datatask, finish_task
from tests import helper

STOP_MARKER = "fa-stop"


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class TaskDetailStopButtonTest(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_user_with_perm(login="unittest", perms=[])

    def _detail(self, handle):
        return self.client.get(reverse("app_data:task_detail", kwargs={"handle": handle}))

    @staticmethod
    def _card_fragment(content):
        """The polled region only - what a refresh actually replaces."""

        marker = b'id="datatask-detail-card"'
        return content[content.index(marker) :]

    def test_running_task_offers_stop(self):
        dt = create_datatask("t", owner_id="unittest")
        dt.state = "RUNNING"
        dt.save()

        response = self._detail(dt.handle)

        self.assertContains(response, STOP_MARKER)

    def test_queued_task_offers_stop(self):
        dt = create_datatask("t", owner_id="unittest")

        response = self._detail(dt.handle)

        self.assertEqual(dt.state, "QUEUED")
        self.assertContains(response, STOP_MARKER)

    def test_done_task_has_no_stop(self):
        dt = create_datatask("t", owner_id="unittest")
        finish_task(dt.handle, state="DONE")

        response = self._detail(dt.handle)

        self.assertNotContains(response, STOP_MARKER)

    def test_aborted_task_has_no_stop(self):
        dt = create_datatask("t", owner_id="unittest")
        finish_task(dt.handle, state="ABORTED")

        response = self._detail(dt.handle)

        self.assertNotContains(response, STOP_MARKER)

    def test_stop_button_sits_inside_the_polled_region(self):
        """A refresh of a finished task must be able to take the button away."""

        dt = create_datatask("t", owner_id="unittest")
        dt.state = "RUNNING"
        dt.save()

        response = self._detail(dt.handle)

        self.assertIn(STOP_MARKER.encode(), self._card_fragment(response.content))

    def test_polling_stops_once_terminal(self):
        # scoped to the card: the navbar Tasks dropdown has an hx-trigger of
        # its own, which has nothing to do with this page's self-refresh
        dt = create_datatask("t", owner_id="unittest")
        finish_task(dt.handle, state="DONE")

        response = self._detail(dt.handle)

        self.assertNotIn(b"every 2s", self._card_fragment(response.content))

    def test_polling_runs_while_live(self):
        dt = create_datatask("t", owner_id="unittest")
        dt.state = "RUNNING"
        dt.save()

        response = self._detail(dt.handle)

        self.assertIn(b"every 2s", self._card_fragment(response.content))


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class StopButtonPermissionTest(TestCase):
    """The button is only rendered when it would actually work: own task always,
    somebody else's only with p_task_manage. Before 5.4.0 it was rendered on task
    state alone and the view then bounced the click to the home page."""

    def setUp(self):
        cache.clear()

    def _detail(self, handle):
        return self.client.get(reverse("app_data:task_detail", kwargs={"handle": handle}))

    def _list(self):
        return self.client.get(reverse("app_data:task_list"))

    def test_detail_offers_stop_on_own_task_with_no_permission(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        dt = create_datatask("t", owner_id="unittest")

        self.assertContains(self._detail(dt.handle), STOP_MARKER)

    def test_detail_hides_stop_on_another_users_task(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_all"])
        dt = create_datatask("t", owner_id="someone_else")

        self.assertNotContains(self._detail(dt.handle), STOP_MARKER)

    def test_detail_offers_stop_on_another_users_task_with_p_task_manage(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_all", "p_task_manage"])
        dt = create_datatask("t", owner_id="someone_else")

        self.assertContains(self._detail(dt.handle), STOP_MARKER)

    def test_list_offers_stop_on_own_task_with_no_permission(self):
        helper.add_user_with_perm(login="unittest", perms=[])
        create_datatask("t", owner_id="unittest")

        self.assertContains(self._list(), ">Stop<")

    def test_list_hides_stop_on_another_users_task(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_all"])
        create_datatask("t", owner_id="someone_else")

        response = self._list()

        self.assertContains(response, "someone_else")
        self.assertNotContains(response, ">Stop<")

    def test_list_offers_stop_on_another_users_task_with_p_task_manage(self):
        helper.add_user_with_perm(login="unittest", perms=["p_task_all", "p_task_manage"])
        create_datatask("t", owner_id="someone_else")

        self.assertContains(self._list(), ">Stop<")
