text: from django.core.exceptions import ValidationError
  from django.http.request import HttpRequest
  from django.test import TestCase, override_settings
  
  from wagtail.core.models import Page, Site
  
  
  class TestSiteNaturalKey(TestCase):
      def test_natural_key(self):
          site = Site(hostname='example.com', port=8080)
          self.assertEqual(site.natural_key(), ('example.com', 8080))
  
      def test_get_by_natural_key(self):
          site = Site.objects.create(hostname='example.com', port=8080, root_page=Page.objects.get(pk=2))
          self.assertEqual(Site.objects.get_by_natural_key('example.com', 8080),
                           site)
  
  
  class TestSiteUrl(TestCase):
      def test_root_url_http(self):
          site = Site(hostname='example.com', port=80)
          self.assertEqual(site.root_url, 'http://example.com')
  
      def test_root_url_https(self):
          site = Site(hostname='example.com', port=443)
          self.assertEqual(site.root_url, 'https://example.com')
  
      def test_root_url_custom_port(self):
          site = Site(hostname='example.com', port=8000)
          self.assertEqual(site.root_url, 'http://example.com:8000')
  
  
  class TestSiteNameDisplay(TestCase):
      def test_site_name_not_default(self):
          site = Site(hostname='example.com', port=80, site_name='example dot com', is_default_site=False)
          self.assertEqual(site.__str__(), 'example dot com')
  
      def test_site_name_default(self):
          site = Site(hostname='example.com', port=80, site_name='example dot com', is_default_site=True)
          self.assertEqual(site.__str__(), 'example dot com [default]')
  
      def test_no_site_name_not_default_port_80(self):
          site = Site(hostname='example.com', port=80, is_default_site=False)
          self.assertEqual(site.__str__(), 'example.com')
  
      def test_no_site_name_default_port_80(self):
          site = Site(hostname='example.com', port=80, is_default_site=True)
          self.assertEqual(site.__str__(), 'example.com [default]')
  
      def test_no_site_name_not_default_port_n(self):
          site = Site(hostname='example.com', port=8080, is_default_site=False)
          self.assertEqual(site.__str__(), 'example.com:8080')
  
      def test_no_site_name_default_port_n(self):
          site = Site(hostname='example.com', port=8080, is_default_site=True)
          self.assertEqual(site.__str__(), 'example.com:8080 [default]')
  
  
  class TestSiteOrdering(TestCase):
      def setUp(self):
          self.root_page = Page.objects.get(pk=2)
          Site.objects.all().delete()  # Drop the initial site.
  
      def test_site_order_by_hostname(self):
          site_1 = Site.objects.create(hostname='charly.com', root_page=self.root_page)
          site_2 = Site.objects.create(hostname='bravo.com', root_page=self.root_page)
          site_3 = Site.objects.create(hostname='alfa.com', root_page=self.root_page)
          self.assertEqual(list(Site.objects.all().values_list("id", flat=True)), [site_3.id, site_2.id, site_1.id])
  
      def test_site_order_by_hostname_upper(self):
          site_1 = Site.objects.create(hostname='charly.com', root_page=self.root_page)
          site_2 = Site.objects.create(hostname='Bravo.com', root_page=self.root_page)
          site_3 = Site.objects.create(hostname='alfa.com', root_page=self.root_page)
          self.assertEqual(list(Site.objects.all().values_list("id", flat=True)), [site_3.id, site_2.id, site_1.id])
  
      def test_site_order_by_hostname_site_name_irrelevant(self):
          site_1 = Site.objects.create(hostname='charly.com', site_name='X-ray', root_page=self.root_page)
          site_2 = Site.objects.create(hostname='bravo.com', site_name='Yankee', root_page=self.root_page)
          site_3 = Site.objects.create(hostname='alfa.com', site_name='Zulu', root_page=self.root_page)
          self.assertEqual(list(Site.objects.all().values_list("id", flat=True)), [site_3.id, site_2.id, site_1.id])
  
  
  @override_settings(ALLOWED_HOSTS=['example.com', 'unknown.com', '127.0.0.1', '[::1]'])
  class TestFindSiteForRequest(TestCase):
      def setUp(self):
          self.default_site = Site.objects.get()
          self.site = Site.objects.create(hostname='example.com', port=80, root_page=Page.objects.get(pk=2))
  
      def test_with_host(self):
          request = HttpRequest()
          request.META = {'HTTP_HOST': 'example.com', 'SERVER_PORT': 80}
          self.assertEqual(Site.find_for_request(request), self.site)
  
      def test_with_unknown_host(self):
          request = HttpRequest()
          request.META = {'HTTP_HOST': 'unknown.com', 'SERVER_PORT': 80}
          self.assertEqual(Site.find_for_request(request), self.default_site)
  
      def test_with_server_name(self):
          request = HttpRequest()
          request.META = {
              'SERVER_NAME': 'example.com',
              'SERVER_PORT': 80
          }
          self.assertEqual(Site.find_for_request(request), self.site)
  
      def test_with_x_forwarded_host(self):
          with self.settings(USE_X_FORWARDED_HOST=True):
              request = HttpRequest()
              request.META = {'HTTP_X_FORWARDED_HOST': 'example.com', 'SERVER_PORT': 80}
              self.assertEqual(Site.find_for_request(request), self.site)
  
      def test_ipv4_host(self):
          request = HttpRequest()
          request.META = {
              'SERVER_NAME': '127.0.0.1',
              'SERVER_PORT': 80
          }
          self.assertEqual(Site.find_for_request(request), self.default_site)
  
      def test_ipv6_host(self):
          request = HttpRequest()
          request.META = {
              'SERVER_NAME': '[::1]',
              'SERVER_PORT': 80
          }
          self.assertEqual(Site.find_for_request(request), self.default_site)
  
  
  class TestDefaultSite(TestCase):
      def test_create_default_site(self):
          Site.objects.all().delete()
          Site.objects.create(hostname='test.com', is_default_site=True,
                              root_page=Page.objects.get(pk=2))
          self.assertTrue(Site.objects.filter(is_default_site=True).exists())
  
      def test_change_default_site(self):
          default = Site.objects.get(is_default_site=True)
          default.is_default_site = False
          default.save()
  
          Site.objects.create(hostname='test.com', is_default_site=True,
                              root_page=Page.objects.get(pk=2))
          self.assertTrue(Site.objects.filter(is_default_site=True).exists())
  
      def test_there_can_only_be_one(self):
          site = Site(hostname='test.com', is_default_site=True,
                      root_page=Page.objects.get(pk=2))
          with self.assertRaises(ValidationError):
              site.clean_fields()
  
      def test_oops_there_is_more_than_one(self):
          Site.objects.create(hostname='example.com', is_default_site=True,
                              root_page=Page.objects.get(pk=2))
  
          site = Site(hostname='test.com', is_default_site=True,
                      root_page=Page.objects.get(pk=2))
          with self.assertRaises(Site.MultipleObjectsReturned):
              # If there already are multiple default sites, you're in trouble
              site.clean_fields()
  
  
  class TestGetSiteRootPaths(TestCase):
  
      def setUp(self):
          self.default_site = Site.objects.get()
          self.abc_site = Site.objects.create(
              hostname='abc.com', root_page=self.default_site.root_page
          )
          self.def_site = Site.objects.create(
              hostname='def.com', root_page=self.default_site.root_page
          )
  
          # Changing the hostname to show that being the default site takes
          # promotes a site over the alphabetical ordering of hostname
          self.default_site.hostname = 'xyz.com'
          self.default_site.save()
  
      def test_result_order_when_multiple_sites_share_the_same_root_page(self):
          result = Site.get_site_root_paths()
  
          # An entry for the default site should come first
          self.assertEqual(result[0][0], self.default_site.id)
  
          # Followed by entries for others in 'host' alphabetical order
          self.assertEqual(result[1][0], self.abc_site.id)
          self.assertEqual(result[2][0], self.def_site.id)
  