Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
saxix committed Oct 9, 2024
1 parent 7ebe069 commit 4bb68db
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 61 deletions.
32 changes: 32 additions & 0 deletions docs/src/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,36 @@ Install [uv](https://docs.astral.sh/uv/)


## Run tests

pytests tests

## Run Selenium tests (ONLY)

pytests tests -m selenium


## Run Selenium any tests

pytests tests --selenium


!!! note

You can disable selenium headless mode (show the browser activity on the screen) using `--show-browser` flag




## Run local server


./manage.py runserver


!!! note

To facililate developing you can use:

export AUTHENTICATION_BACKENDS="country_workspace.security.backends.AnyUserAuthBackend"

It works only if `DEBUG=True`
6 changes: 0 additions & 6 deletions src/country_workspace/config/urls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from django.conf import settings
from django.conf.urls import include
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path

Expand All @@ -10,7 +8,6 @@

urlpatterns = [
path(r"admin/", admin.site.urls),
# path(r"", admin.site.urls),
path(r"security/", include("unicef_security.urls", namespace="security")),
path(r"social/", include("social_django.urls", namespace="social")),
path(r"accounts/", include("django.contrib.auth.urls")),
Expand All @@ -19,6 +16,3 @@
path(r"__debug__/", include(debug_toolbar.urls)),
path(r"", workspace.urls),
]

if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
8 changes: 8 additions & 0 deletions src/country_workspace/models/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any

from django.db import models
from django.urls import reverse


class BaseQuerySet(models.QuerySet["models.Model"]):
Expand All @@ -24,3 +25,10 @@ class BaseModel(models.Model):

class Meta:
abstract = True

def get_change_url(self, namespace="workspace"):
return reverse(
"%s:%s_%s_change"
% (namespace, self._meta.app_label, self._meta.model_name),
args=[self.pk],
)
4 changes: 3 additions & 1 deletion src/country_workspace/models/household.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@


class Household(BaseModel):
country_office = models.ForeignKey(Office, on_delete=models.CASCADE)
country_office = models.ForeignKey(
Office, on_delete=models.CASCADE, related_name="households"
)
program = models.ForeignKey(Program, on_delete=models.CASCADE)
name = models.CharField(_("Name"), max_length=255)
flex_fields = models.JSONField(default=dict, blank=True)
Expand Down
2 changes: 0 additions & 2 deletions src/country_workspace/models/locations.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Any, Optional

from django.db import models
from django.db.models import JSONField, Q, UniqueConstraint
from django.utils.translation import gettext as _
Expand Down
Binary file added src/country_workspace/web/static/favicon.ico
Binary file not shown.
21 changes: 12 additions & 9 deletions src/country_workspace/workspaces/changelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ class WorkspaceChangeList(DjangoChangeList):

def url_for_result(self, result):
pk = getattr(result, self.pk_attname)
return reverse(
"%s:%s_%s_change"
% (
self.model_admin.admin_site.namespace,
self.opts.app_label,
self.opts.model_name,
),
args=(quote(pk),),
current_app=self.model_admin.admin_site.name,
return (
reverse(
"%s:%s_%s_change"
% (
self.model_admin.admin_site.namespace,
self.opts.app_label,
self.opts.model_name,
),
args=(quote(pk),),
current_app=self.model_admin.admin_site.name,
)
+ self.preserved_filters
)
4 changes: 2 additions & 2 deletions src/country_workspace/workspaces/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
class CountryHousehold(global_models.Household):
class Meta:
proxy = True
# verbose_name = "Household"
# verbose_name_plural = "Households"
verbose_name = "Country Household"
verbose_name_plural = "Country Households"
# app_label = "country_workspace"


Expand Down
31 changes: 28 additions & 3 deletions src/country_workspace/workspaces/options.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from urllib.parse import urlencode

from django.contrib import admin
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.http import HttpResponseRedirect
Expand All @@ -20,11 +22,29 @@ class WorkspaceModelAdmin(ExtraButtonsMixin, AdminFiltersMixin, admin.ModelAdmin
"workspace/delete_selected_confirmation.html"
)
delete_confirmation_template = "workspace/delete_confirmation.html"
preserve_filters = True

def __init__(self, model, admin_site):
self._selected_program = None
super().__init__(model, admin_site)

def get_preserved_filters(self, request):
"""
Return the preserved filters querystring.
"""
match = request.resolver_match
if self.preserve_filters and match:
current_url = "%s:%s" % (match.app_name, match.url_name)
changelist_url = self.get_changelist_url(request)
if current_url == changelist_url:
preserved_filters = request.GET.urlencode()
else:
preserved_filters = request.GET.get("_changelist_filters")

if preserved_filters:
return urlencode({"_changelist_filters": preserved_filters})
return ""

def add_preserved_filters(self, request, base_url):
preserved_filters = self.get_preserved_filters(request)
preserved_qsl = self._get_preserved_qsl(request, preserved_filters)
Expand All @@ -44,7 +64,7 @@ def get_changelist_url(self, request):
% (self.admin_site.namespace, opts.app_label, opts.model_name),
current_app=self.admin_site.name,
)
return self.add_preserved_filters(request, obj_url)
return obj_url

def get_change_url(self, request, obj):
opts = self.model._meta
Expand All @@ -54,7 +74,7 @@ def get_change_url(self, request, obj):
args=[obj.pk],
current_app=self.admin_site.name,
)
return self.add_preserved_filters(request, obj_url)
return obj_url

def get_changelist(self, request, **kwargs):
from .changelist import WorkspaceChangeList
Expand All @@ -68,6 +88,9 @@ def changeform_view(self, request, object_id=None, form_url="", extra_context=No
extra_context["show_save_and_add_another"] = False
extra_context["show_save_and_continue"] = True
extra_context["show_save"] = False
extra_context["changelist_url2"] = self.add_preserved_filters(
request, self.get_changelist_url(request)
)
# extra_context = self.get_common_context(
# request, object_id, **(extra_context or {})
# )
Expand All @@ -76,7 +99,9 @@ def changeform_view(self, request, object_id=None, form_url="", extra_context=No
)

def _response_post_save(self, request, obj):
return HttpResponseRedirect(self.get_changelist_url(request))
return HttpResponseRedirect(
self.add_preserved_filters(request, self.get_changelist_url(request))
)

def response_add(self, request, obj, post_url_continue=None):
return HttpResponseRedirect(self.get_change_url(request, obj))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
{% if show_save_and_continue %}<input type="submit" value="{% if can_change %}{% translate 'Save and continue editing' %}{% else %}{% translate 'Save and view' %}{% endif %}" name="_continue">{% endif %}
{% if show_close %}
{% url opts|admin_urlname:'changelist' as changelist_url %}
<a href="{% add_preserved_filters changelist_url %}" class="closelink">{% translate 'Close' %}</a>
<a href="{% add_preserved_filters changelist_url2 %}" class="closelink">{% translate 'Close' %}</a>
{% endif %}
{% if show_delete_link and original %}
{% url opts|workspace_urlname:'delete' original.pk|admin_urlquote as delete_url %}
Expand Down
20 changes: 1 addition & 19 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,42 +34,24 @@ def pytest_addoption(parser):

def pytest_configure(config):
os.environ.update(DJANGO_SETTINGS_MODULE="country_workspace.config.settings")
os.environ.setdefault("STATIC_URL", "/static/")
os.environ.setdefault("MEDIA_ROOT", "/tmp/static/")
os.environ.setdefault("STATIC_ROOT", "/tmp/media/")
os.environ.setdefault("TEST_EMAIL_SENDER", "[email protected]")
os.environ.setdefault("TEST_EMAIL_RECIPIENT", "[email protected]")

os.environ["MAILJET_API_KEY"] = "11"
os.environ["MAILJET_SECRET_KEY"] = "11"
os.environ["FILE_STORAGE_DEFAULT"] = (
"django.core.files.storage.FileSystemStorage?location=/tmp/hde/storage/"
)
os.environ["FILE_STORAGE_STATIC"] = (
"django.core.files.storage.FileSystemStorage?location=/tmp/hde/static/"
)
os.environ["FILE_STORAGE_MEDIA"] = (
"django.core.files.storage.FileSystemStorage?location=/tmp/hde/storage/"
)
os.environ["FILE_STORAGE_HOPE"] = (
"django.core.files.storage.FileSystemStorage?location=/tmp/hde/hope/"
)
os.environ["SOCIAL_AUTH_REDIRECT_IS_HTTPS"] = "0"
os.environ["CELERY_TASK_ALWAYS_EAGER"] = "0"
os.environ["SECURE_HSTS_PRELOAD"] = "0"
os.environ["SECRET_KEY"] = "kugiugiuygiuygiuygiuhgiuhgiuhgiugiu"

os.environ["LOGGING_LEVEL"] = "CRITICAL"
os.environ["GMAIL_USER"] = "11"
os.environ["GMAIL_PASSWORD"] = "11"
from django.conf import settings

settings.ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
settings.SIGNING_BACKEND = "testutils.signers.PlainSigner"
settings.MEDIA_ROOT = "/tmp/media"
settings.STATIC_ROOT = "/tmp/static"
os.makedirs(settings.MEDIA_ROOT, exist_ok=True)
os.makedirs(settings.STATIC_ROOT, exist_ok=True)

django.setup()


Expand Down
2 changes: 2 additions & 0 deletions tests/extras/testutils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def wait_for_url(driver, url):
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

if "://" not in url:
url = f"{driver.live_server.url}{url}"
wait = WebDriverWait(driver, 10)
wait.until(EC.url_contains(url))

Expand Down
39 changes: 25 additions & 14 deletions tests/functional/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest
from selenium.webdriver.common.by import By
from testutils.utils import wait_for
from testutils.utils import wait_for, wait_for_url

Proxy = namedtuple("Proxy", "host,port")

Expand All @@ -13,11 +13,6 @@ def pytest_configure(config):
setattr(config.option, "driver", "chrome")


SELENIUM_DEFAULT_PAGE_LOAD_TIMEOUT = 3
SELENIUM_DEFAULT_IMPLICITLY_WAIT = 1
SELENIUM_DEFAULT_SCRIPT_TIMEOUT = 1


@contextlib.contextmanager
def timeouts(driver, wait=None, page=None, script=None):
from selenium.webdriver.common.timeouts import Timeouts
Expand Down Expand Up @@ -45,24 +40,40 @@ def find_by_css(selenium, *args):


@pytest.fixture
def chrome_options(request):
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
def chrome_options(request, chrome_options):
if not request.config.getvalue("show_browser"):
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--allow-insecure-localhost")
chrome_options.add_argument("--disable-browser-side-navigation")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--disable-translate")
chrome_options.add_argument("--ignore-certificate-errors")
chrome_options.add_argument("--lang=en-GB")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--proxy-bypass-list=*")
chrome_options.add_argument("--proxy-server='direct://'")
chrome_options.add_argument("--start-maximized")

prefs = {
"profile.default_content_setting_values.notifications": 1
} # explicitly allow notifications
chrome_options.add_experimental_option("prefs", prefs)

return chrome_options


@pytest.fixture
def selenium(monkeypatch, settings, driver):
def selenium(monkeypatch, live_server, settings, driver):

driver.with_timeouts = timeouts.__get__(driver)
driver.set_input_value = set_input_value.__get__(driver)

driver.live_server = live_server
driver.wait_for = wait_for.__get__(driver)
driver.wait_for_url = wait_for_url.__get__(driver)
driver.find_by_css = find_by_css.__get__(driver)

# driver.maximize_window()
# driver.fullscreen_window()

yield driver
Loading

0 comments on commit 4bb68db

Please sign in to comment.