1. from django.contrib.admin.utils import quote
    
  2. from django.contrib.admin.views.main import IS_POPUP_VAR
    
  3. from django.contrib.auth.models import User
    
  4. from django.template.response import TemplateResponse
    
  5. from django.test import TestCase, override_settings
    
  6. from django.urls import reverse
    
  7. 
    
  8. from .models import Action, Car, Person
    
  9. 
    
  10. 
    
  11. @override_settings(
    
  12.     ROOT_URLCONF="admin_custom_urls.urls",
    
  13. )
    
  14. class AdminCustomUrlsTest(TestCase):
    
  15.     """
    
  16.     Remember that:
    
  17.     * The Action model has a CharField PK.
    
  18.     * The ModelAdmin for Action customizes the add_view URL, it's
    
  19.       '<app name>/<model name>/!add/'
    
  20.     """
    
  21. 
    
  22.     @classmethod
    
  23.     def setUpTestData(cls):
    
  24.         cls.superuser = User.objects.create_superuser(
    
  25.             username="super", password="secret", email="[email protected]"
    
  26.         )
    
  27.         Action.objects.create(name="delete", description="Remove things.")
    
  28.         Action.objects.create(name="rename", description="Gives things other names.")
    
  29.         Action.objects.create(name="add", description="Add things.")
    
  30.         Action.objects.create(
    
  31.             name="path/to/file/", description="An action with '/' in its name."
    
  32.         )
    
  33.         Action.objects.create(
    
  34.             name="path/to/html/document.html",
    
  35.             description="An action with a name similar to a HTML doc path.",
    
  36.         )
    
  37.         Action.objects.create(
    
  38.             name="javascript:alert('Hello world');\">Click here</a>",
    
  39.             description="An action with a name suspected of being a XSS attempt",
    
  40.         )
    
  41. 
    
  42.     def setUp(self):
    
  43.         self.client.force_login(self.superuser)
    
  44. 
    
  45.     def test_basic_add_GET(self):
    
  46.         """
    
  47.         Ensure GET on the add_view works.
    
  48.         """
    
  49.         add_url = reverse("admin_custom_urls:admin_custom_urls_action_add")
    
  50.         self.assertTrue(add_url.endswith("/!add/"))
    
  51.         response = self.client.get(add_url)
    
  52.         self.assertIsInstance(response, TemplateResponse)
    
  53.         self.assertEqual(response.status_code, 200)
    
  54. 
    
  55.     def test_add_with_GET_args(self):
    
  56.         """
    
  57.         Ensure GET on the add_view plus specifying a field value in the query
    
  58.         string works.
    
  59.         """
    
  60.         response = self.client.get(
    
  61.             reverse("admin_custom_urls:admin_custom_urls_action_add"),
    
  62.             {"name": "My Action"},
    
  63.         )
    
  64.         self.assertContains(response, 'value="My Action"')
    
  65. 
    
  66.     def test_basic_add_POST(self):
    
  67.         """
    
  68.         Ensure POST on add_view works.
    
  69.         """
    
  70.         post_data = {
    
  71.             IS_POPUP_VAR: "1",
    
  72.             "name": "Action added through a popup",
    
  73.             "description": "Description of added action",
    
  74.         }
    
  75.         response = self.client.post(
    
  76.             reverse("admin_custom_urls:admin_custom_urls_action_add"), post_data
    
  77.         )
    
  78.         self.assertContains(response, "Action added through a popup")
    
  79. 
    
  80.     def test_admin_URLs_no_clash(self):
    
  81.         # Should get the change_view for model instance with PK 'add', not show
    
  82.         # the add_view
    
  83.         url = reverse(
    
  84.             "admin_custom_urls:%s_action_change" % Action._meta.app_label,
    
  85.             args=(quote("add"),),
    
  86.         )
    
  87.         response = self.client.get(url)
    
  88.         self.assertContains(response, "Change action")
    
  89. 
    
  90.         # Should correctly get the change_view for the model instance with the
    
  91.         # funny-looking PK (the one with a 'path/to/html/document.html' value)
    
  92.         url = reverse(
    
  93.             "admin_custom_urls:%s_action_change" % Action._meta.app_label,
    
  94.             args=(quote("path/to/html/document.html"),),
    
  95.         )
    
  96.         response = self.client.get(url)
    
  97.         self.assertContains(response, "Change action")
    
  98.         self.assertContains(response, 'value="path/to/html/document.html"')
    
  99. 
    
  100.     def test_post_save_add_redirect(self):
    
  101.         """
    
  102.         ModelAdmin.response_post_save_add() controls the redirection after
    
  103.         the 'Save' button has been pressed when adding a new object.
    
  104.         """
    
  105.         post_data = {"name": "John Doe"}
    
  106.         self.assertEqual(Person.objects.count(), 0)
    
  107.         response = self.client.post(
    
  108.             reverse("admin_custom_urls:admin_custom_urls_person_add"), post_data
    
  109.         )
    
  110.         persons = Person.objects.all()
    
  111.         self.assertEqual(len(persons), 1)
    
  112.         redirect_url = reverse(
    
  113.             "admin_custom_urls:admin_custom_urls_person_history", args=[persons[0].pk]
    
  114.         )
    
  115.         self.assertRedirects(response, redirect_url)
    
  116. 
    
  117.     def test_post_save_change_redirect(self):
    
  118.         """
    
  119.         ModelAdmin.response_post_save_change() controls the redirection after
    
  120.         the 'Save' button has been pressed when editing an existing object.
    
  121.         """
    
  122.         Person.objects.create(name="John Doe")
    
  123.         self.assertEqual(Person.objects.count(), 1)
    
  124.         person = Person.objects.all()[0]
    
  125.         post_url = reverse(
    
  126.             "admin_custom_urls:admin_custom_urls_person_change", args=[person.pk]
    
  127.         )
    
  128.         response = self.client.post(post_url, {"name": "Jack Doe"})
    
  129.         self.assertRedirects(
    
  130.             response,
    
  131.             reverse(
    
  132.                 "admin_custom_urls:admin_custom_urls_person_delete", args=[person.pk]
    
  133.             ),
    
  134.         )
    
  135. 
    
  136.     def test_post_url_continue(self):
    
  137.         """
    
  138.         The ModelAdmin.response_add()'s parameter `post_url_continue` controls
    
  139.         the redirection after an object has been created.
    
  140.         """
    
  141.         post_data = {"name": "SuperFast", "_continue": "1"}
    
  142.         self.assertEqual(Car.objects.count(), 0)
    
  143.         response = self.client.post(
    
  144.             reverse("admin_custom_urls:admin_custom_urls_car_add"), post_data
    
  145.         )
    
  146.         cars = Car.objects.all()
    
  147.         self.assertEqual(len(cars), 1)
    
  148.         self.assertRedirects(
    
  149.             response,
    
  150.             reverse(
    
  151.                 "admin_custom_urls:admin_custom_urls_car_history", args=[cars[0].pk]
    
  152.             ),
    
  153.         )