|
| 1 | +from selenium.common.exceptions import NoSuchElementException |
| 2 | + |
1 | 3 | from django.contrib.admin import ModelAdmin, TabularInline
|
2 | 4 | from django.contrib.admin.helpers import InlineAdminForm
|
3 | 5 | from django.contrib.admin.tests import AdminSeleniumTestCase
|
@@ -862,6 +864,98 @@ def test_inline_change_fk_all_perms(self):
|
862 | 864 | )
|
863 | 865 |
|
864 | 866 |
|
| 867 | +@override_settings(ROOT_URLCONF='admin_inlines.urls') |
| 868 | +class TestReadOnlyChangeViewInlinePermissions(TestCase): |
| 869 | + |
| 870 | + @classmethod |
| 871 | + def setUpTestData(cls): |
| 872 | + cls.user = User.objects.create_user('testing', password='password', is_staff=True) |
| 873 | + cls.user.user_permissions.add( |
| 874 | + Permission.objects.get(codename='view_poll', content_type=ContentType.objects.get_for_model(Poll)) |
| 875 | + ) |
| 876 | + cls.user.user_permissions.add( |
| 877 | + *Permission.objects.filter( |
| 878 | + codename__endswith="question", content_type=ContentType.objects.get_for_model(Question) |
| 879 | + ).values_list('pk', flat=True) |
| 880 | + ) |
| 881 | + |
| 882 | + cls.poll = Poll.objects.create(name="Survey") |
| 883 | + cls.add_url = reverse('admin:admin_inlines_poll_add') |
| 884 | + cls.change_url = reverse('admin:admin_inlines_poll_change', args=(cls.poll.id,)) |
| 885 | + |
| 886 | + def setUp(self): |
| 887 | + self.client.force_login(self.user) |
| 888 | + |
| 889 | + def test_add_url_not_allowed(self): |
| 890 | + response = self.client.get(self.add_url) |
| 891 | + self.assertEqual(response.status_code, 403) |
| 892 | + |
| 893 | + response = self.client.post(self.add_url, {}) |
| 894 | + self.assertEqual(response.status_code, 403) |
| 895 | + |
| 896 | + def test_post_to_change_url_not_allowed(self): |
| 897 | + response = self.client.post(self.change_url, {}) |
| 898 | + self.assertEqual(response.status_code, 403) |
| 899 | + |
| 900 | + def test_get_to_change_url_is_allowed(self): |
| 901 | + response = self.client.get(self.change_url) |
| 902 | + self.assertEqual(response.status_code, 200) |
| 903 | + |
| 904 | + def test_main_model_is_rendered_as_read_only(self): |
| 905 | + response = self.client.get(self.change_url) |
| 906 | + self.assertContains( |
| 907 | + response, |
| 908 | + '<div class="readonly">%s</div>' % self.poll.name, |
| 909 | + html=True |
| 910 | + ) |
| 911 | + input = '<input type="text" name="name" value="%s" class="vTextField" maxlength="40" required id="id_name">' |
| 912 | + self.assertNotContains( |
| 913 | + response, |
| 914 | + input % self.poll.name, |
| 915 | + html=True |
| 916 | + ) |
| 917 | + |
| 918 | + def test_inlines_are_rendered_as_read_only(self): |
| 919 | + question = Question.objects.create(text="How will this be rendered?", poll=self.poll) |
| 920 | + response = self.client.get(self.change_url) |
| 921 | + self.assertContains( |
| 922 | + response, |
| 923 | + '<td class="field-text"><p>%s</p></td>' % question.text, |
| 924 | + html=True |
| 925 | + ) |
| 926 | + self.assertNotContains(response, 'id="id_question_set-0-text"') |
| 927 | + self.assertNotContains(response, 'id="id_related_objs-0-DELETE"') |
| 928 | + |
| 929 | + def test_submit_line_shows_only_close_button(self): |
| 930 | + response = self.client.get(self.change_url) |
| 931 | + self.assertContains( |
| 932 | + response, |
| 933 | + '<a href="/admin/admin_inlines/poll/" class="closelink">Close</a>', |
| 934 | + html=True |
| 935 | + ) |
| 936 | + delete_link = '<p class="deletelink-box"><a href="/admin/admin_inlines/poll/%s/delete/" class="deletelink">Delete</a></p>' # noqa |
| 937 | + self.assertNotContains( |
| 938 | + response, |
| 939 | + delete_link % self.poll.id, |
| 940 | + html=True |
| 941 | + ) |
| 942 | + self.assertNotContains(response, '<input type="submit" value="Save and add another" name="_addanother">') |
| 943 | + self.assertNotContains(response, '<input type="submit" value="Save and continue editing" name="_continue">') |
| 944 | + |
| 945 | + def test_inline_delete_buttons_are_not_shown(self): |
| 946 | + Question.objects.create(text="How will this be rendered?", poll=self.poll) |
| 947 | + response = self.client.get(self.change_url) |
| 948 | + self.assertNotContains( |
| 949 | + response, |
| 950 | + '<input type="checkbox" name="question_set-0-DELETE" id="id_question_set-0-DELETE">', |
| 951 | + html=True |
| 952 | + ) |
| 953 | + |
| 954 | + def test_extra_inlines_are_not_shown(self): |
| 955 | + response = self.client.get(self.change_url) |
| 956 | + self.assertNotContains(response, 'id="id_question_set-0-text"') |
| 957 | + |
| 958 | + |
865 | 959 | @override_settings(ROOT_URLCONF='admin_inlines.urls')
|
866 | 960 | class SeleniumTests(AdminSeleniumTestCase):
|
867 | 961 |
|
@@ -965,6 +1059,24 @@ def test_add_inlines(self):
|
965 | 1059 | self.assertEqual(ProfileCollection.objects.all().count(), 1)
|
966 | 1060 | self.assertEqual(Profile.objects.all().count(), 3)
|
967 | 1061 |
|
| 1062 | + def test_add_inline_link_absent_for_view_only_parent_model(self): |
| 1063 | + user = User.objects.create_user('testing', password='password', is_staff=True) |
| 1064 | + user.user_permissions.add( |
| 1065 | + Permission.objects.get(codename='view_poll', content_type=ContentType.objects.get_for_model(Poll)) |
| 1066 | + ) |
| 1067 | + user.user_permissions.add( |
| 1068 | + *Permission.objects.filter( |
| 1069 | + codename__endswith="question", content_type=ContentType.objects.get_for_model(Question) |
| 1070 | + ).values_list('pk', flat=True) |
| 1071 | + ) |
| 1072 | + self.admin_login(username='testing', password='password') |
| 1073 | + poll = Poll.objects.create(name="Survey") |
| 1074 | + change_url = reverse('admin:admin_inlines_poll_change', args=(poll.id,)) |
| 1075 | + self.selenium.get(self.live_server_url + change_url) |
| 1076 | + with self.disable_implicit_wait(): |
| 1077 | + with self.assertRaises(NoSuchElementException): |
| 1078 | + self.selenium.find_element_by_link_text('Add another Question') |
| 1079 | + |
968 | 1080 | def test_delete_inlines(self):
|
969 | 1081 | self.admin_login(username='super', password='secret')
|
970 | 1082 | self.selenium.get(self.live_server_url + reverse('admin:admin_inlines_profilecollection_add'))
|
|
0 commit comments