from unittest.mock import Mock, patch

from django.test import SimpleTestCase

from corehq.apps.domain.exceptions import DomainDoesNotExist
from corehq.apps.linked_domain.exceptions import (
    DomainLinkAlreadyExists,
    DomainLinkError,
    DomainLinkNotAllowed,
)
from corehq.apps.linked_domain.views import link_domains


class LinkDomainsTests(SimpleTestCase):

    @classmethod
    def setUpClass(cls):
        super(LinkDomainsTests, cls).setUpClass()
        cls.upstream_domain = 'upstream'
        cls.downstream_domain = 'downstream'

    def test_exception_raised_if_domain_does_not_exist(self):
        def mock_handler(domain):
            return domain != self.downstream_domain

        with patch('corehq.apps.linked_domain.views.domain_exists') as mock_domainexists,\
             self.assertRaises(DomainDoesNotExist):
            mock_domainexists.side_effect = mock_handler
            link_domains(Mock(), self.upstream_domain, self.downstream_domain)

    def test_exception_raised_if_domain_link_already_exists(self):
        with patch('corehq.apps.linked_domain.views.domain_exists', return_value=True),\
             patch('corehq.apps.linked_domain.views.get_active_domain_link', return_value=Mock()),\
             self.assertRaises(DomainLinkAlreadyExists):
            link_domains(Mock(), self.upstream_domain, self.downstream_domain)

    def test_exception_raised_if_domain_link_error_raised(self):
        def mock_handler(downstream, upstream):
            raise DomainLinkError

        with patch('corehq.apps.linked_domain.views.domain_exists', return_value=True),\
             patch('corehq.apps.linked_domain.views.get_active_domain_link', return_value=None),\
             patch('corehq.apps.linked_domain.views.DomainLink.link_domains') as mock_linkdomains,\
             self.assertRaises(DomainLinkError):
            mock_linkdomains.side_effect = mock_handler
            link_domains(Mock(), self.upstream_domain, self.downstream_domain)

    def test_exception_raised_if_user_is_not_admin_in_both_domains(self):
        with patch('corehq.apps.linked_domain.views.domain_exists', return_value=True),\
             patch('corehq.apps.linked_domain.views.get_active_domain_link', return_value=None),\
             patch('corehq.apps.linked_domain.views.user_has_admin_access_in_all_domains', return_value=False),\
             self.assertRaises(DomainLinkNotAllowed):
            link_domains(Mock(), self.upstream_domain, self.downstream_domain)

    def test_successful(self):
        with patch('corehq.apps.linked_domain.views.domain_exists', return_value=True),\
             patch('corehq.apps.linked_domain.views.get_active_domain_link', return_value=None),\
             patch('corehq.apps.linked_domain.views.DomainLink.link_domains', return_value=True),\
             patch('corehq.apps.linked_domain.views.user_has_admin_access_in_all_domains', return_value=True):
            domain_link = link_domains(Mock(), self.upstream_domain, self.downstream_domain)

        self.assertIsNotNone(domain_link)

[((26, 13, 26, 67), 'unittest.mock.patch', 'patch', ({(26, 19, 26, 66): '"""corehq.apps.linked_domain.views.domain_exists"""'}, {}), "('corehq.apps.linked_domain.views.domain_exists')", False, 'from unittest.mock import Mock, patch\n'), ((32, 13, 32, 86), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((41, 13, 41, 86), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((42, 13, 42, 95), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((43, 13, 43, 77), 'unittest.mock.patch', 'patch', ({(43, 19, 43, 76): '"""corehq.apps.linked_domain.views.DomainLink.link_domains"""'}, {}), "('corehq.apps.linked_domain.views.DomainLink.link_domains')", False, 'from unittest.mock import Mock, patch\n'), ((49, 13, 49, 86), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((50, 13, 50, 95), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((51, 13, 51, 110), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((56, 13, 56, 86), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((57, 13, 57, 95), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((58, 13, 58, 96), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((59, 13, 59, 109), 'unittest.mock.patch', 'patch', (), '', False, 'from unittest.mock import Mock, patch\n'), ((29, 25, 29, 31), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock, patch\n'), ((35, 25, 35, 31), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock, patch\n'), ((46, 25, 46, 31), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock, patch\n'), ((53, 25, 53, 31), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock, patch\n'), ((60, 39, 60, 45), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock, patch\n'), ((33, 90, 33, 96), 'unittest.mock.Mock', 'Mock', ({}, {}), '()', False, 'from unittest.mock import Mock, patch\n')]