diff --git a/src/open_inwoner/accounts/tests/test_action_views.py b/src/open_inwoner/accounts/tests/test_action_views.py index 9d3a9d1704..363e7882eb 100644 --- a/src/open_inwoner/accounts/tests/test_action_views.py +++ b/src/open_inwoner/accounts/tests/test_action_views.py @@ -1,14 +1,17 @@ +import time from datetime import date -from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.contrib.messages import get_messages +from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.core.files.uploadedfile import SimpleUploadedFile from django.urls import reverse from django.utils.translation import gettext as _ from django_webtest import WebTest from privates.test import temp_private_root +from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By +from selenium.webdriver.remote.webdriver import WebDriver from open_inwoner.utils.tests.selenium import ChromeSeleniumMixin, FirefoxSeleniumMixin @@ -299,20 +302,18 @@ def test_action_status_not_your_action(self): class ActionStatusSeleniumBaseTests: - options = None - driver = None - selenium = None + selenium: WebDriver def setUp(self) -> None: super().setUp() self.user = UserFactory.create() - self.action = ActionFactory( name="my_action", created_by=self.user, status=StatusChoices.open, ) + self.action_list_url = reverse("accounts:action_list") @classmethod def setUpClass(cls): @@ -322,7 +323,13 @@ def setUpClass(cls): def test_action_status(self): self.force_login(self.user) - self.selenium.get(self.live_server_url + reverse("accounts:action_list")) + # wait for user and session to be visible from the server thread + time.sleep(1) + + self.selenium.set_window_size(1200, 1200) + self.selenium.get(self.live_server_url + self.action_list_url) + + self.assertEqual(self.action.status, StatusChoices.open) wrapper = self.selenium.find_element( By.CSS_SELECTOR, f"#actions_{self.action.id}__status" @@ -330,8 +337,6 @@ def test_action_status(self): dropdown = wrapper.find_element(By.CSS_SELECTOR, ".dropdown") dropdown_content = dropdown.find_element(By.CSS_SELECTOR, ".dropdown__content") - self.selenium.execute_script("arguments[0].scrollIntoView(true);", wrapper) - # grab and check our button is Open button = wrapper.find_element( By.CSS_SELECTOR, @@ -345,8 +350,14 @@ def test_action_status(self): button.get_attribute("class"), ) - # open the dropdown - button.click() + # scroll the dropdown into view and open it + ActionChains(self.selenium).scroll_to_element(wrapper).scroll_by_amount( + 0, 200 + ).click(button).perform() + + # wait for htmx to return (neither implicit or explicit wait/until nor ActionChains.pause will help) + time.sleep(1) + self.assertIn( f"dropdown--{StatusChoices.open}", dropdown.get_attribute("class") ) @@ -359,9 +370,12 @@ def test_action_status(self): self.assertTrue(status_closed_button.is_displayed()) # click button and htmx should run - status_closed_button.click() + ActionChains(self.selenium).click(status_closed_button).perform() + + # wait for htmx to return (neither implicit or explicit wait/until nor ActionChains.pause will help) + time.sleep(1) - # grab and check our button is now Closed + # regrab and check our button is now Closed button = self.selenium.find_element( By.CSS_SELECTOR, f"#actions_{self.action.id}__status .actions__status-selector", diff --git a/src/open_inwoner/plans/tests/test_views.py b/src/open_inwoner/plans/tests/test_views.py index ba1e5930aa..1147b75ae0 100644 --- a/src/open_inwoner/plans/tests/test_views.py +++ b/src/open_inwoner/plans/tests/test_views.py @@ -1,9 +1,11 @@ from django.contrib.messages import get_messages +from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.core import mail from django.urls import reverse from django.utils.translation import ugettext as _ from django_webtest import WebTest +from privates.test import temp_private_root from webtest import Upload from open_inwoner.accounts.choices import StatusChoices @@ -13,6 +15,8 @@ ContactFactory, UserFactory, ) +from open_inwoner.accounts.tests.test_action_views import ActionStatusSeleniumBaseTests +from open_inwoner.utils.tests.selenium import ChromeSeleniumMixin, FirefoxSeleniumMixin from ..models import Plan from .factories import ActionTemplateFactory, PlanFactory, PlanTemplateFactory @@ -502,3 +506,38 @@ def test_plan_action_status_not_your_action(self): HTTP_HX_REQUEST="true", ) self.assertEqual(response.status_code, 404) + + +class _PlanActionStatusSeleniumMixin: + def setUp(self) -> None: + super().setUp() + + # update the action to belong to our plan + self.plan = PlanFactory(created_by=self.user) + self.action.plan = self.plan + self.action.save() + + # override the url to show plan detail page + self.action_list_url = reverse( + "plans:plan_detail", kwargs={"uuid": self.plan.uuid} + ) + + +@temp_private_root() +class PlanActionStatusFirefoxSeleniumTests( + FirefoxSeleniumMixin, + _PlanActionStatusSeleniumMixin, + ActionStatusSeleniumBaseTests, + StaticLiveServerTestCase, +): + pass + + +@temp_private_root() +class PlanActionStatusChromeSeleniumTests( + ChromeSeleniumMixin, + _PlanActionStatusSeleniumMixin, + ActionStatusSeleniumBaseTests, + StaticLiveServerTestCase, +): + pass diff --git a/src/open_inwoner/plans/urls.py b/src/open_inwoner/plans/urls.py index 2db95e9680..2669fe2a5a 100644 --- a/src/open_inwoner/plans/urls.py +++ b/src/open_inwoner/plans/urls.py @@ -2,8 +2,8 @@ from .views import ( PlanActionCreateView, - PlanActionEditStatusTagView, PlanActionDeleteView, + PlanActionEditStatusTagView, PlanActionEditView, PlanCreateView, PlanDetailView, diff --git a/src/open_inwoner/plans/views.py b/src/open_inwoner/plans/views.py index 09edc2dd2c..294a6853b0 100644 --- a/src/open_inwoner/plans/views.py +++ b/src/open_inwoner/plans/views.py @@ -11,8 +11,8 @@ from open_inwoner.accounts.forms import ActionListForm, DocumentForm from open_inwoner.accounts.views.actions import ( ActionCreateView, - ActionUpdateStatusTagView, ActionDeleteView, + ActionUpdateStatusTagView, ActionUpdateView, BaseActionFilter, ) diff --git a/src/open_inwoner/utils/tests/selenium.py b/src/open_inwoner/utils/tests/selenium.py index fab0041b84..6cbbc1e8b1 100644 --- a/src/open_inwoner/utils/tests/selenium.py +++ b/src/open_inwoner/utils/tests/selenium.py @@ -4,6 +4,7 @@ from selenium.webdriver.chrome.webdriver import WebDriver as ChromeDriver from selenium.webdriver.firefox.options import Options as FirefoxOptions from selenium.webdriver.firefox.webdriver import WebDriver as FirefoxDriver +from selenium.webdriver.remote.webdriver import WebDriver from seleniumlogin import force_login as selenium_force_login @@ -14,9 +15,7 @@ class SeleniumBrowserMixinBase: expected to be mixed in with StaticLiveServerTestCase """ - options = None - driver = None - selenium = None + selenium: WebDriver = None def force_login(self, user): selenium_force_login(user, self.selenium, self.live_server_url)