diff options
| author | Jake Howard <git@theorangeone.net> | 2024-06-11 19:27:49 +0100 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2024-07-04 11:38:58 +0200 |
| commit | 53e674d5744faad61e52d8459c9198b2aa6f63dd (patch) | |
| tree | 0b2de1867fbec42098705ae834ff9fa2af33f78f /tests/admin_views/test_multidb.py | |
| parent | 31837dbcb36f1ab57fb1b16cb0b126c55a1bdf01 (diff) | |
Fixed #35520 -- Avoided opening transaction for read-only ModelAdmin requests.
Diffstat (limited to 'tests/admin_views/test_multidb.py')
| -rw-r--r-- | tests/admin_views/test_multidb.py | 75 |
1 files changed, 72 insertions, 3 deletions
diff --git a/tests/admin_views/test_multidb.py b/tests/admin_views/test_multidb.py index 654161e11d..0f18aeb315 100644 --- a/tests/admin_views/test_multidb.py +++ b/tests/admin_views/test_multidb.py @@ -40,6 +40,7 @@ urlpatterns = [ @override_settings(ROOT_URLCONF=__name__, DATABASE_ROUTERS=["%s.Router" % __name__]) class MultiDatabaseTests(TestCase): databases = {"default", "other"} + READ_ONLY_METHODS = {"get", "options", "head", "trace"} @classmethod def setUpTestData(cls): @@ -56,48 +57,116 @@ class MultiDatabaseTests(TestCase): b.save(using=db) cls.test_book_ids[db] = b.id + def tearDown(self): + # Reset the routers' state between each test. + Router.target_db = None + @mock.patch("django.contrib.admin.options.transaction") def test_add_view(self, mock): for db in self.databases: with self.subTest(db=db): + mock.mock_reset() Router.target_db = db self.client.force_login(self.superusers[db]) - self.client.post( + response = self.client.post( reverse("test_adminsite:admin_views_book_add"), {"name": "Foobar: 5th edition"}, ) + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.url, reverse("test_adminsite:admin_views_book_changelist") + ) mock.atomic.assert_called_with(using=db) @mock.patch("django.contrib.admin.options.transaction") + def test_read_only_methods_add_view(self, mock): + for db in self.databases: + for method in self.READ_ONLY_METHODS: + with self.subTest(db=db, method=method): + mock.mock_reset() + Router.target_db = db + self.client.force_login(self.superusers[db]) + response = getattr(self.client, method)( + reverse("test_adminsite:admin_views_book_add"), + ) + self.assertEqual(response.status_code, 200) + mock.atomic.assert_not_called() + + @mock.patch("django.contrib.admin.options.transaction") def test_change_view(self, mock): for db in self.databases: with self.subTest(db=db): + mock.mock_reset() Router.target_db = db self.client.force_login(self.superusers[db]) - self.client.post( + response = self.client.post( reverse( "test_adminsite:admin_views_book_change", args=[self.test_book_ids[db]], ), {"name": "Test Book 2: Test more"}, ) + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.url, reverse("test_adminsite:admin_views_book_changelist") + ) mock.atomic.assert_called_with(using=db) @mock.patch("django.contrib.admin.options.transaction") + def test_read_only_methods_change_view(self, mock): + for db in self.databases: + for method in self.READ_ONLY_METHODS: + with self.subTest(db=db, method=method): + mock.mock_reset() + Router.target_db = db + self.client.force_login(self.superusers[db]) + response = getattr(self.client, method)( + reverse( + "test_adminsite:admin_views_book_change", + args=[self.test_book_ids[db]], + ), + data={"name": "Test Book 2: Test more"}, + ) + self.assertEqual(response.status_code, 200) + mock.atomic.assert_not_called() + + @mock.patch("django.contrib.admin.options.transaction") def test_delete_view(self, mock): for db in self.databases: with self.subTest(db=db): + mock.mock_reset() Router.target_db = db self.client.force_login(self.superusers[db]) - self.client.post( + response = self.client.post( reverse( "test_adminsite:admin_views_book_delete", args=[self.test_book_ids[db]], ), {"post": "yes"}, ) + self.assertEqual(response.status_code, 302) + self.assertEqual( + response.url, reverse("test_adminsite:admin_views_book_changelist") + ) mock.atomic.assert_called_with(using=db) + @mock.patch("django.contrib.admin.options.transaction") + def test_read_only_methods_delete_view(self, mock): + for db in self.databases: + for method in self.READ_ONLY_METHODS: + with self.subTest(db=db, method=method): + mock.mock_reset() + Router.target_db = db + self.client.force_login(self.superusers[db]) + response = getattr(self.client, method)( + reverse( + "test_adminsite:admin_views_book_delete", + args=[self.test_book_ids[db]], + ) + ) + self.assertEqual(response.status_code, 200) + mock.atomic.assert_not_called() + class ViewOnSiteRouter: def db_for_read(self, model, instance=None, **hints): |
