-
-
Notifications
You must be signed in to change notification settings - Fork 300
[docs] Fixed various spelling mistakes and typos #1399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4318a3f
04c2b46
75245ea
6b77f61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,7 +4,22 @@ | |
| from django.test import tag | ||
| from django.urls.base import reverse | ||
| from django_loci.tests import TestAdminMixin | ||
| from unittest.mock import MagicMock | ||
| from django_loci.base import geocoding_views | ||
| from django_loci.tests.base.test_selenium import BaseTestDeviceAdminSelenium | ||
| from time import sleep | ||
| from selenium.webdriver import ActionChains | ||
| from selenium.webdriver.support import expected_conditions as EC | ||
| from selenium.webdriver.support.ui import WebDriverWait | ||
|
|
||
| class MockLocation: | ||
| def __init__(self, address="Lazio 00185, ITA", latitude=41.898903, longitude=12.512124): | ||
| self.address = address | ||
| self.latitude = latitude | ||
| self.longitude = longitude | ||
|
|
||
| geocoding_views.geocode = MagicMock(return_value=MockLocation()) | ||
| geocoding_views.reverse_geocode = MagicMock(return_value=MockLocation()) | ||
| from selenium.webdriver.common.by import By | ||
| from swapper import load_model | ||
|
|
||
|
|
@@ -63,6 +78,39 @@ def _fill_device_form(self): | |
| self.find_element(by=By.CLASS_NAME, value="select2-results__option").click() | ||
| super()._fill_device_form() | ||
|
|
||
| def test_real_time_update_address_field(self): | ||
| # Changing the address in tab 1 should update it in tab 0 in real time without a page reload. | ||
| # We increase the alert check timeout to 10s to prevent TimeoutException on slow CI runs. | ||
| location = self._create_location() | ||
| self.login() | ||
| url = reverse(f"admin:{self.app_label}_location_change", args=[location.id]) | ||
| self.open(url) | ||
| self.web_driver.switch_to.new_window("tab") | ||
| tabs = self.web_driver.window_handles | ||
| self.web_driver.switch_to.window(tabs[-1]) | ||
| self.open(url) | ||
| address_input = self.find_element(by=By.ID, value="id_address") | ||
| self.assertEqual(address_input.get_attribute("value"), location.address) | ||
| self.find_element( | ||
| by=By.XPATH, value='//a[@class="leaflet-draw-draw-marker"]' | ||
| ).click() | ||
| elem = self.find_element(by=By.ID, value="id_geometry-map") | ||
| ActionChains(self.web_driver).move_to_element(elem).move_by_offset( | ||
| 30, 15 | ||
| ).click().perform() | ||
|
Comment on lines
+98
to
+100
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win Document the map-click offset rationale or replace magic numbers with named constants. At Line 98-Line 100, As per coding guidelines, cryptic code must include a concise explanation of why the complexity is needed and acceptable. 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| alert = WebDriverWait(self.web_driver, 10).until(EC.alert_is_present()) | ||
| alert.accept() | ||
| sleep(0.05) | ||
| new_address = "Lazio 00185, ITA" | ||
| address_input = self.find_element(by=By.ID, value="id_address") | ||
| self.assertIn(new_address, address_input.get_attribute("value")) | ||
|
Comment on lines
+103
to
+106
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace fixed At Line 103, Proposed deterministic wait- sleep(0.05)
new_address = "Lazio 00185, ITA"
- address_input = self.find_element(by=By.ID, value="id_address")
- self.assertIn(new_address, address_input.get_attribute("value"))
+ WebDriverWait(self.web_driver, 10).until(
+ lambda d: new_address in d.find_element(By.ID, "id_address").get_attribute("value")
+ )
+ address_input = self.find_element(by=By.ID, value="id_address")
+ self.assertIn(new_address, address_input.get_attribute("value"))🤖 Prompt for AI Agents |
||
| self.wait_for("element_to_be_clickable", by=By.NAME, value="_continue").click() | ||
| self.web_driver.close() | ||
| initial_tab = tabs.index(tabs[-1]) - 1 | ||
| self.web_driver.switch_to.window(tabs[initial_tab]) | ||
| address_input = self.find_element(by=By.ID, value="id_address") | ||
| self.assertIn(new_address, address_input.get_attribute("value")) | ||
|
|
||
|
|
||
| @tag("selenium_tests") | ||
| class TestDeviceAdminReadonly( | ||
|
|
@@ -108,10 +156,19 @@ def test_unsaved_changes_readonly(self): | |
| # so we just need to ensure it's set as expected | ||
| self.web_driver.execute_script( | ||
| 'django.jQuery(window).on("beforeunload", function(e) {' | ||
| " sessionStorage.setItem('unsaved_changes_alert', e.returnValue);" | ||
| " console.warn(e.returnValue); });" | ||
| ) | ||
| self.web_driver.refresh() | ||
| for entry in self.get_browser_logs(): | ||
| alert = self.web_driver.execute_script( | ||
| "var alert = sessionStorage.getItem('unsaved_changes_alert');" | ||
| "sessionStorage.removeItem('unsaved_changes_alert');" | ||
| "return alert;" | ||
| ) | ||
| if alert and "You haven't saved your changes yet!" in alert: | ||
| self.fail("Unsaved changes alert displayed without any change") | ||
|
|
||
| for entry in self.get_browser_logs() or []: | ||
| if ( | ||
| entry["level"] == "WARNING" | ||
| and "You haven't saved your changes yet!" in entry["message"] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,7 +9,24 @@ | |
| from ..utils import UnqiueCommonNameMixin | ||
|
|
||
|
|
||
| # Avoids "DateTimeField received a naive datetime while time zone support is active" | ||
| # warning by returning an aware datetime when USE_TZ is True. | ||
| def default_validity_start(): | ||
| from datetime import datetime, timedelta | ||
| from django.conf import settings | ||
| from django.utils import timezone | ||
| start = datetime.now() - timedelta(days=1) | ||
| start = start.replace(hour=0, minute=0, second=0, microsecond=0) | ||
| if settings.USE_TZ: | ||
| return timezone.make_aware(start) | ||
| return start | ||
|
Comment on lines
+18
to
+22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Build Current logic can shift the date when server timezone and Django configured timezone differ, because Proposed fix def default_validity_start():
- from datetime import datetime, timedelta
+ from datetime import timedelta
from django.conf import settings
from django.utils import timezone
- start = datetime.now() - timedelta(days=1)
- start = start.replace(hour=0, minute=0, second=0, microsecond=0)
+ if settings.USE_TZ:
+ start = timezone.localtime(timezone.now()) - timedelta(days=1)
+ else:
+ start = timezone.now() - timedelta(days=1)
+ start = start.replace(hour=0, minute=0, second=0, microsecond=0)
if settings.USE_TZ:
- return timezone.make_aware(start)
+ return timezone.make_aware(start) if timezone.is_naive(start) else start
return start🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| class AbstractCa(ShareableOrgMixin, UnqiueCommonNameMixin, BaseCa): | ||
| validity_start = models.DateTimeField( | ||
| blank=True, null=True, default=default_validity_start | ||
| ) | ||
|
|
||
| class Meta(BaseCa.Meta): | ||
| abstract = True | ||
| constraints = [ | ||
|
|
@@ -21,6 +38,9 @@ class Meta(BaseCa.Meta): | |
|
|
||
|
|
||
| class AbstractCert(ShareableOrgMixin, UnqiueCommonNameMixin, BaseCert): | ||
| validity_start = models.DateTimeField( | ||
| blank=True, null=True, default=default_validity_start | ||
| ) | ||
| ca = models.ForeignKey( | ||
| get_model_name("django_x509", "Ca"), | ||
| verbose_name=_("CA"), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import openwisp_controller.pki.base.models | ||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ("pki", "0012_alter_ca_extensions_alter_ca_key_length_and_more"), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.AlterField( | ||
| model_name="ca", | ||
| name="validity_start", | ||
| field=models.DateTimeField( | ||
| blank=True, | ||
| default=openwisp_controller.pki.base.models.default_validity_start, | ||
| null=True, | ||
| ), | ||
| ), | ||
| migrations.AlterField( | ||
| model_name="cert", | ||
| name="validity_start", | ||
| field=models.DateTimeField( | ||
| blank=True, | ||
| default=openwisp_controller.pki.base.models.default_validity_start, | ||
| null=True, | ||
| ), | ||
| ), | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid module-level global monkeypatching of
geocoding_viewsin tests.At Line 21 and Line 22, patching
geocoding_views.geocode/reverse_geocodeat import time can leak mocked behavior into other tests in the same process and create order-dependent failures. Scope these mocks to the test/class lifecycle and restore originals.Proposed scoped patching approach
🤖 Prompt for AI Agents