# (c) cavaliba.com - tests / migrator drop_permission_from_roles()

"""
Deleting a SirenePermission row leaves its keyname behind in every role that
held it, where it resolves to None at read time. drop_permission_from_roles()
is the sweep that follows such a deletion (used by the 5.4.0 block for
p_task_view). It must touch every role, not a known list, and be replayable:
the version block it sits in re-runs on every start while the version is -RC.
"""

from django.test import TestCase

import app_home.cache as cache
from app_data.data import Instance
from app_home.migrator import drop_permission_from_roles
from app_user.models import SirenePermission
from tests import helper

STALE = "p_unittest_stale"
KEPT = "p_unittest_kept"


class TestMigratorDropPermissionFromRoles(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_admin_user(login="unittest")
        for keyname in (STALE, KEPT):
            SirenePermission.objects.get_or_create(keyname=keyname)

    @staticmethod
    def _add_role(keyname, perms):
        helper.add_user_with_perm(login=keyname, perms=perms)
        return f"role_{keyname}"

    @staticmethod
    def _perms(role_keyname):
        cache.clear()
        role = Instance.from_keyname(classname="role", keyname=role_keyname)
        return role.fields["permissions"].get_value()

    def test_removes_the_keyname_and_keeps_the_others(self):
        role_keyname = self._add_role("holder", [STALE, KEPT])

        count = drop_permission_from_roles(STALE)

        self.assertEqual(count, 1)
        self.assertEqual(self._perms(role_keyname), [KEPT])

    def test_leaves_roles_without_the_keyname_untouched(self):
        role_keyname = self._add_role("other", [KEPT])

        count = drop_permission_from_roles(STALE)

        self.assertEqual(count, 0)
        self.assertEqual(self._perms(role_keyname), [KEPT])

    def test_sweeps_every_role_holding_it(self):
        first = self._add_role("holder1", [STALE])
        second = self._add_role("holder2", [STALE, KEPT])
        self._add_role("holder3", [KEPT])

        count = drop_permission_from_roles(STALE)

        self.assertEqual(count, 2)
        self.assertEqual(self._perms(first), [])
        self.assertEqual(self._perms(second), [KEPT])

    def test_is_replayable(self):
        role_keyname = self._add_role("holder", [STALE, KEPT])

        drop_permission_from_roles(STALE)
        count = drop_permission_from_roles(STALE)

        self.assertEqual(count, 0)
        self.assertEqual(self._perms(role_keyname), [KEPT])
