diff --git a/.env b/.env index 5802fdc..0268899 100644 --- a/.env +++ b/.env @@ -1,2 +1,3 @@ PYTHON_VERSION=3.8 DJANGO_VERSION=3.1.7 +SELENIUM_VERSION=4.0.0a7 diff --git a/admin_confirm/tests/README.md b/admin_confirm/tests/README.md index 7304bf5..5d99fc5 100644 --- a/admin_confirm/tests/README.md +++ b/admin_confirm/tests/README.md @@ -46,8 +46,8 @@ These are some areas which might/probably have issues that are not currently tes - [x] ModelAdmin.fieldsets - [ ] ModelAdmin.form -- [ ] ModelAdmin.raw_id_fields -- [ ] ModelAdmin.radio_fields +- [x] ModelAdmin.raw_id_fields +- [x] ModelAdmin.radio_fields - [ ] ModelAdmin.autocomplete_fields - [ ] ModelAdmin.prepopulated_fields diff --git a/admin_confirm/tests/helpers.py b/admin_confirm/tests/helpers.py index ded48d3..666a1b3 100644 --- a/admin_confirm/tests/helpers.py +++ b/admin_confirm/tests/helpers.py @@ -71,7 +71,6 @@ class AdminConfirmTestCase(TestCase): class AdminConfirmIntegrationTestCase(LiveServerTestCase): @classmethod def setUpClass(cls): - cls.host = socket.gethostbyname(socket.gethostname()) cls.selenium = webdriver.Remote( command_executor="http://selenium:4444/wd/hub", @@ -96,6 +95,7 @@ class AdminConfirmIntegrationTestCase(LiveServerTestCase): def tearDown(self): cache.clear() + self.selenium.get(self.live_server_url) return super().tearDown() @classmethod diff --git a/admin_confirm/tests/integration/test_with_cache.py b/admin_confirm/tests/integration/test_with_cache.py index 0567310..246a5d9 100644 --- a/admin_confirm/tests/integration/test_with_cache.py +++ b/admin_confirm/tests/integration/test_with_cache.py @@ -7,18 +7,16 @@ import pytest import pkg_resources from importlib import reload -from tests.factories import ShopFactory -from tests.market.models import GeneralManager, Item, ShoppingMall, Town +from tests.market.models import Item, ShoppingMall from admin_confirm.tests.helpers import AdminConfirmIntegrationTestCase from tests.market.admin import shoppingmall_admin from admin_confirm.constants import CONFIRM_CHANGE -from selenium.webdriver.support.ui import Select from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.remote.file_detector import LocalFileDetector +from selenium.webdriver.common.by import By from django.core.files.uploadedfile import SimpleUploadedFile -from tempfile import NamedTemporaryFile class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): @@ -39,21 +37,21 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Change name - name = self.selenium.find_element_by_name("name") + name = self.selenium.find_element(By.NAME, "name") name.send_keys("New Name") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should have hidden form containing the updated name self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - name = hidden_form.find_element_by_name("name") + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + name = hidden_form.find_element(By.NAME, "name") self.assertIn("New Name", name.get_attribute("value")) with self.assertRaises(NoSuchElementException): - self.selenium.find_element_by_name("_confirmation_received") + self.selenium.find_element(By.NAME, "_confirmation_received") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should persist change mall.refresh_from_db() @@ -68,19 +66,19 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Change price - price = self.selenium.find_element_by_name("price") + price = self.selenium.find_element(By.NAME, "price") price.send_keys(2) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should have hidden form containing the updated price self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - price = hidden_form.find_element_by_name("price") + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + price = hidden_form.find_element(By.NAME, "price") self.assertEqual("21.00", price.get_attribute("value")) - self.selenium.find_element_by_name("_confirmation_received") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_confirmation_received") + self.selenium.find_element(By.NAME, "_continue").click() item.refresh_from_db() @@ -101,24 +99,24 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Make a change to trigger confirmation page - price = self.selenium.find_element_by_name("price") + price = self.selenium.find_element(By.NAME, "price") price.send_keys(2) # Upload a new file - self.selenium.find_element_by_id("id_file").send_keys( + self.selenium.find_element(By.ID, "id_file").send_keys( os.getcwd() + "/screenshot.png" ) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should have hidden form containing the updated price self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - price = hidden_form.find_element_by_name("price") + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + price = hidden_form.find_element(By.NAME, "price") self.assertEqual("21.00", price.get_attribute("value")) - self.selenium.find_element_by_name("_confirmation_received") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_confirmation_received") + self.selenium.find_element(By.NAME, "_continue").click() item.refresh_from_db() self.assertEqual(21, int(item.price)) @@ -146,24 +144,24 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Make a change to trigger confirmation page - price = self.selenium.find_element_by_name("price") + price = self.selenium.find_element(By.NAME, "price") price.send_keys(2) # Upload a new file - self.selenium.find_element_by_id("id_file").send_keys( + self.selenium.find_element(By.ID, "id_file").send_keys( os.getcwd() + "/screenshot.png" ) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should have hidden form containing the updated price self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - price = hidden_form.find_element_by_name("price") + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + price = hidden_form.find_element(By.NAME, "price") self.assertEqual("21.00", price.get_attribute("value")) - self.selenium.find_element_by_name("_confirmation_received") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_confirmation_received") + self.selenium.find_element(By.NAME, "_continue").click() item.refresh_from_db() self.assertEqual(21, int(item.price)) @@ -185,27 +183,27 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Make a change to trigger confirmation page - price = self.selenium.find_element_by_name("price") + price = self.selenium.find_element(By.NAME, "price") price.send_keys(2) # Choose to clear the existing file - self.selenium.find_element_by_id("file-clear_id").click() + self.selenium.find_element(By.ID, "file-clear_id").click() self.assertTrue( - self.selenium.find_element_by_xpath( - ".//*[@id='file-clear_id']" + self.selenium.find_element( + By.XPATH, ".//*[@id='file-clear_id']" ).get_attribute("checked") ) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should have hidden form containing the updated price self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - price = hidden_form.find_element_by_name("price") + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + price = hidden_form.find_element(By.NAME, "price") self.assertEqual("21.00", price.get_attribute("value")) - self.selenium.find_element_by_name("_confirmation_received") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_confirmation_received") + self.selenium.find_element(By.NAME, "_continue").click() item.refresh_from_db() self.assertEqual(21, int(item.price)) diff --git a/admin_confirm/tests/integration/test_with_form_input_types.py b/admin_confirm/tests/integration/test_with_form_input_types.py new file mode 100644 index 0000000..39b9cf0 --- /dev/null +++ b/admin_confirm/tests/integration/test_with_form_input_types.py @@ -0,0 +1,100 @@ +""" +Tests with different form input types +""" +from importlib import reload +from tests.factories import ShopFactory +from tests.market.models import GeneralManager, Item, ShoppingMall, Town + +from admin_confirm.tests.helpers import AdminConfirmIntegrationTestCase +from tests.market.admin import item_admin, shoppingmall_admin + +from django.contrib.admin import VERTICAL +from admin_confirm.constants import CONFIRM_ADD, CONFIRM_CHANGE +from selenium.webdriver.support.ui import Select +from selenium.webdriver.common.by import By + + +class ConfirmWithFormInputTypes(AdminConfirmIntegrationTestCase): + @classmethod + def setUpClass(cls): + i_admin = item_admin.ItemAdmin + i_admin.confirm_add = True + i_admin.confirm_change = True + i_admin.confirmation_fields = ["currency", "price", "name"] + i_admin.radio_fields = {"currency": VERTICAL} + + mall_admin = shoppingmall_admin.ShoppingMallAdmin + mall_admin.raw_id_fields = ["general_manager"] + mall_admin.inlines = [] + return super().setUpClass() + + @classmethod + def tearDownClass(cls): + reload(shoppingmall_admin) + reload(item_admin) + return super().tearDownClass() + + def test_radio_input_should_work(self): + self.selenium.get(self.live_server_url + f"/admin/market/item/add/") + self.assertIn("radio", self.selenium.page_source) + + # Should ask for confirmation of add + self.assertIn(CONFIRM_ADD, self.selenium.page_source) + + name = self.selenium.find_element(By.NAME, "name") + name.send_keys("New Name") + price = self.selenium.find_element(By.NAME, "price") + price.send_keys("24.00") + + # Select a radio option for currency + currency = self.selenium.find_element(By.ID, "id_currency_0") + currency.click() + expected_value = currency.get_attribute("value") + + self.selenium.find_element(By.NAME, "_continue").click() + + # Should have hidden form containing the updated name + self.assertIn("Confirm", self.selenium.page_source) + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + name = hidden_form.find_element(By.NAME, "name") + self.assertEqual("New Name", name.get_attribute("value")) + + self.selenium.find_element(By.NAME, "_continue").click() + + # Should persist addition + self.assertEqual(Item.objects.count(), 1) + item = Item.objects.all().first() + self.assertEqual("New Name", item.name) + self.assertEqual(expected_value, item.currency) + self.assertEqual(24, int(item.price)) + + def test_raw_id_fields_should_work(self): + gm1 = GeneralManager.objects.create(name="gm1") + shops = [ShopFactory(name=i) for i in range(3)] + town = Town.objects.create(name="town") + mall = ShoppingMall.objects.create(name="mall", general_manager=gm1, town=town) + mall.shops.set(shops) + + self.selenium.get( + self.live_server_url + f"/admin/market/shoppingmall/{mall.id}/change/" + ) + self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) + + # Make a change to trigger confirmation page + name = self.selenium.find_element(By.NAME, "name") + name.send_keys("New Name") + + # Set general_manager via raw_id_fields + gm2 = GeneralManager.objects.create(name="gm2") + general_manager = self.selenium.find_element(By.NAME, "general_manager") + general_manager.clear() + general_manager.send_keys(str(gm2.id)) + + self.selenium.find_element(By.NAME, "_continue").click() + + self.assertIn("Confirm", self.selenium.page_source) + self.selenium.find_element(By.NAME, "_continue").click() + + mall.refresh_from_db() + self.assertIn("New Name", mall.name) + self.assertEqual(gm2, mall.general_manager) diff --git a/admin_confirm/tests/integration/test_with_inlines.py b/admin_confirm/tests/integration/test_with_inlines.py index ae24a2a..04744a8 100644 --- a/admin_confirm/tests/integration/test_with_inlines.py +++ b/admin_confirm/tests/integration/test_with_inlines.py @@ -15,6 +15,7 @@ from tests.market.admin import shoppingmall_admin from admin_confirm.constants import CONFIRM_CHANGE from selenium.webdriver.support.ui import Select +from selenium.webdriver.common.by import By class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): @@ -36,18 +37,18 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Change name - name = self.selenium.find_element_by_name("name") + name = self.selenium.find_element(By.NAME, "name") name.send_keys("New Name") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should have hidden form containing the updated name self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - name = hidden_form.find_element_by_name("name") + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + name = hidden_form.find_element(By.NAME, "name") self.assertIn("New Name", name.get_attribute("value")) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() # Should persist change mall.refresh_from_db() @@ -67,16 +68,16 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Make a change to trigger confirmation page - name = self.selenium.find_element_by_name("name") + name = self.selenium.find_element(By.NAME, "name") name.send_keys("New Name") - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - hidden_form.find_element_by_name("ShoppingMall_shops-TOTAL_FORMS") - self.selenium.find_element_by_name("_continue").click() + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + hidden_form.find_element(By.NAME, "ShoppingMall_shops-TOTAL_FORMS") + self.selenium.find_element(By.NAME, "_continue").click() mall.refresh_from_db() self.assertIn("New Name", mall.name) @@ -94,22 +95,22 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Make a change to trigger confirmation page - name = self.selenium.find_element_by_name("name") + name = self.selenium.find_element(By.NAME, "name") name.send_keys("New Name") # Change shops via inline form select_shop = Select( - self.selenium.find_element_by_name("ShoppingMall_shops-0-shop") + self.selenium.find_element(By.NAME, "ShoppingMall_shops-0-shop") ) select_shop.select_by_value(str(shops[2].id)) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - hidden_form.find_element_by_name("ShoppingMall_shops-TOTAL_FORMS") - self.selenium.find_element_by_name("_continue").click() + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + hidden_form.find_element(By.NAME, "ShoppingMall_shops-TOTAL_FORMS") + self.selenium.find_element(By.NAME, "_continue").click() mall.refresh_from_db() self.assertIn("New Name", mall.name) @@ -140,22 +141,22 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Make a change to trigger confirmation page - name = self.selenium.find_element_by_name("name") + name = self.selenium.find_element(By.NAME, "name") name.send_keys("New Name") # Change shops via inline form select_shop = Select( - self.selenium.find_element_by_name("ShoppingMall_shops-0-shop") + self.selenium.find_element(By.NAME, "ShoppingMall_shops-0-shop") ) select_shop.select_by_value(str(shops[2].id)) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - hidden_form.find_element_by_name("ShoppingMall_shops-TOTAL_FORMS") - self.selenium.find_element_by_name("_continue").click() + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + hidden_form.find_element(By.NAME, "ShoppingMall_shops-TOTAL_FORMS") + self.selenium.find_element(By.NAME, "_continue").click() mall.refresh_from_db() self.assertIn("New Name", mall.name) @@ -180,22 +181,22 @@ class ConfirmWithInlinesTests(AdminConfirmIntegrationTestCase): self.assertIn(CONFIRM_CHANGE, self.selenium.page_source) # Make a change to trigger confirmation page - name = self.selenium.find_element_by_name("name") + name = self.selenium.find_element(By.NAME, "name") name.send_keys("New Name") # Change shops via inline form select_shop = Select( - self.selenium.find_element_by_name("ShoppingMall_shops-0-shop") + self.selenium.find_element(By.NAME, "ShoppingMall_shops-0-shop") ) select_shop.select_by_value(str(shops[2].id)) - self.selenium.find_element_by_name("_continue").click() + self.selenium.find_element(By.NAME, "_continue").click() self.assertIn("Confirm", self.selenium.page_source) - hidden_form = self.selenium.find_element_by_id("hidden-form") - hidden_form.find_element_by_name("ShoppingMall_shops-TOTAL_FORMS") - self.selenium.find_element_by_name("_continue").click() + hidden_form = self.selenium.find_element(By.ID, "hidden-form") + hidden_form.find_element(By.NAME, "ShoppingMall_shops-TOTAL_FORMS") + self.selenium.find_element(By.NAME, "_continue").click() mall.refresh_from_db() self.assertIn("New Name", mall.name) diff --git a/setup.py b/setup.py index 3bfc8c1..6b7a31e 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ README = open(os.path.join(here, "README.md")).read() setup( name="django-admin-confirm", - version="0.2.3.dev9", + version="0.2.3a0", packages=["admin_confirm"], description=("Adds confirmation to Django Admin changes, additions and actions"), long_description_content_type="text/markdown", diff --git a/tests/market/admin/generalmanager_admin.py b/tests/market/admin/generalmanager_admin.py index 4c5073e..e346f82 100644 --- a/tests/market/admin/generalmanager_admin.py +++ b/tests/market/admin/generalmanager_admin.py @@ -3,3 +3,4 @@ from django.contrib.admin import ModelAdmin class GeneralManagerAdmin(ModelAdmin): save_as = True + search_fields = ["name"] diff --git a/tests/market/admin/item_admin.py b/tests/market/admin/item_admin.py index ca120fc..0ecc0d0 100644 --- a/tests/market/admin/item_admin.py +++ b/tests/market/admin/item_admin.py @@ -1,4 +1,4 @@ -from django.contrib.admin import ModelAdmin +from django.contrib.admin import ModelAdmin, VERTICAL from django.utils.safestring import mark_safe from admin_confirm.admin import AdminConfirmMixin @@ -7,6 +7,7 @@ class ItemAdmin(AdminConfirmMixin, ModelAdmin): confirm_change = True confirm_add = True confirmation_fields = ["price"] + radio_fields = {"currency": VERTICAL} list_display = ("name", "price", "currency") readonly_fields = ["image_preview"] diff --git a/tests/market/admin/shoppingmall_admin.py b/tests/market/admin/shoppingmall_admin.py index cabc13a..66e0808 100644 --- a/tests/market/admin/shoppingmall_admin.py +++ b/tests/market/admin/shoppingmall_admin.py @@ -14,3 +14,4 @@ class ShoppingMallAdmin(AdminConfirmMixin, ModelAdmin): confirmation_fields = ["name"] inlines = [ShopInline] + raw_id_fields = ["general_manager"]