django-cms-qe 4.5.0__py3-none-any.whl → 4.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
-/__init__.py ADDED
File without changes
-/browser.py ADDED
@@ -0,0 +1,47 @@
1
+ from selenium.common.exceptions import NoSuchElementException
2
+ from webdriverwrapper import Chrome as _Chrome
3
+
4
+
5
+ class ChromeBrowser(_Chrome):
6
+ def get_error_page(self):
7
+ # Django error page.
8
+ try:
9
+ error_page = self.get_elm('summary')
10
+ except NoSuchElementException:
11
+ pass
12
+ else:
13
+ header = error_page.get_elm(tag_name='h1')
14
+ return header.text
15
+
16
+ # Generic error page.
17
+ try:
18
+ error_page = self.get_elm('error-page')
19
+ except NoSuchElementException:
20
+ pass
21
+ else:
22
+ header = error_page.get_elm(tag_name='h1')
23
+ return header.text
24
+
25
+ def get_error_traceback(self):
26
+ try:
27
+ traceback = self.get_elm('traceback_area')
28
+ except NoSuchElementException:
29
+ pass
30
+ else:
31
+ return traceback.text
32
+
33
+ def get_error_messages(self):
34
+ try:
35
+ error_elms = self.get_elms(xpath='//*[contains(@class, "alert-danger")]')
36
+ except NoSuchElementException:
37
+ return []
38
+ else:
39
+ return [error_elm.text for error_elm in error_elms]
40
+
41
+ def get_info_messages(self):
42
+ try:
43
+ info_elms = self.get_elms(xpath='//*[contains(@class, "alert-success")]')
44
+ except NoSuchElementException:
45
+ return []
46
+ else:
47
+ return [info_elm.get_attribute('info') for info_elm in info_elms]
-/cms_qe/__init__.py ADDED
File without changes
-/cms_qe/test_base.py ADDED
@@ -0,0 +1,2 @@
1
+ def test_homepage(driver):
2
+ pass
@@ -0,0 +1,14 @@
1
+ from webdriverwrapper.decorators import expected_error_page
2
+
3
+ from ..pages.cms import CreatePagePage
4
+
5
+
6
+ @expected_error_page(None)
7
+ def test_page_not_found(driver):
8
+ driver.go_to('/404')
9
+
10
+
11
+ # No error page should be detected.
12
+ def test_page_not_found_custom_by_cms(driver):
13
+ CreatePagePage(driver).open().create_page('Page not found', slug='error404')
14
+ driver.go_to('/404')
-/conftest.py ADDED
@@ -0,0 +1,6 @@
1
+ def pytest_addoption(parser):
2
+ parser.addoption('--no-display', action='store_true', help='do not use virtual display')
3
+
4
+
5
+ def pytest_configure(config):
6
+ config.webdriverwrapper_screenshot_path = '/tmp/testresults'
-/fixtures/__init__.py ADDED
File without changes
-/fixtures/base.py ADDED
@@ -0,0 +1,75 @@
1
+ import os
2
+
3
+ import pytest
4
+ from selenium import webdriver
5
+ from webdriverwrapper.pytest import * # noqa: F403,F401
6
+
7
+ from ..browser import ChromeBrowser
8
+ from ..pages.cms import LoginPage, WizardPage
9
+
10
+ __all__ = [
11
+ 'display',
12
+ 'session_driver',
13
+ '_driver',
14
+ 'homepage_url',
15
+ 'admin_username',
16
+ ]
17
+
18
+
19
+ @pytest.fixture(scope='session', autouse=True)
20
+ def display(request):
21
+ no_display = request.config.getoption('--no-display')
22
+
23
+ if no_display:
24
+ yield
25
+ else:
26
+ from pyvirtualdisplay import Display
27
+
28
+ display = Display(visible=0, size=(1200, 2000))
29
+ display.start()
30
+ yield
31
+ display.stop()
32
+
33
+
34
+ @pytest.yield_fixture(scope='session')
35
+ def session_driver(request, homepage_url, admin_username):
36
+ no_display = request.config.getoption('--no-display')
37
+
38
+ driver = open_browser(homepage_url)
39
+ try:
40
+ LoginPage(driver).open().login(admin_username)
41
+ WizardPage(driver).open().create_home_page()
42
+ yield driver
43
+ finally:
44
+ if not no_display:
45
+ driver.quit()
46
+
47
+
48
+ def open_browser(homepage_url):
49
+ """
50
+ Open browser a type URL `homepage_url`.
51
+ """
52
+ chrome_options = webdriver.ChromeOptions()
53
+ chrome_options.add_argument('--incognito')
54
+ chrome_options.add_argument('--no-sandbox') # So it will work in GitLab CI.
55
+
56
+ driver = ChromeBrowser(chrome_options=chrome_options)
57
+ driver.get(homepage_url)
58
+ return driver
59
+
60
+
61
+ @pytest.fixture
62
+ def _driver(session_driver, homepage_url):
63
+ session_driver.get(homepage_url)
64
+ return session_driver
65
+
66
+
67
+ @pytest.fixture(scope='session')
68
+ def homepage_url():
69
+ port = os.environ.get('WEB_PORT', '8000')
70
+ return f'http://localhost:{port}'
71
+
72
+
73
+ @pytest.fixture(scope='session')
74
+ def admin_username():
75
+ return os.environ.get('ADMIN_USER', 'admin')
-/pages/__init__.py ADDED
File without changes
@@ -0,0 +1,5 @@
1
+ from .login import LoginPage
2
+ from .page import CreatePagePage
3
+ from .wizard import WizardPage
4
+
5
+ __all__ = ['LoginPage', 'CreatePagePage', 'WizardPage']
-/pages/cms/login.py ADDED
@@ -0,0 +1,17 @@
1
+ class LoginPage:
2
+ def __init__(self, driver):
3
+ self._driver = driver
4
+
5
+ def open(self):
6
+ self._driver.go_to('/admin')
7
+ return self
8
+
9
+ def login(self, username, password=None):
10
+ """
11
+ Log in to Django CMS application as `username` with `password`.
12
+ If `password` is empty, then is used same as `username`.
13
+ """
14
+ self._driver.get_elm('login-form').fill_out_and_submit({
15
+ 'username': username,
16
+ 'password': password or username,
17
+ })
-/pages/cms/page.py ADDED
@@ -0,0 +1,16 @@
1
+ class CreatePagePage:
2
+ def __init__(self, driver):
3
+ self._driver = driver
4
+
5
+ def open(self):
6
+ self._driver.go_to('/admin/cms/page/add/')
7
+ return self
8
+
9
+ def create_page(self, title, slug=''):
10
+ # Title will automatically set slug which we want to force.
11
+ self._driver.get_elm(tag_name='form').fill_out({
12
+ 'title': title,
13
+ })
14
+ self._driver.get_elm(tag_name='form').fill_out_and_submit({
15
+ 'slug': slug,
16
+ })
-/pages/cms/wizard.py ADDED
@@ -0,0 +1,17 @@
1
+ class WizardPage:
2
+ def __init__(self, driver):
3
+ self._driver = driver
4
+
5
+ def open(self):
6
+ self._driver.go_to('/cms_wizard/create/?language=en')
7
+ return self
8
+
9
+ def create_home_page(self):
10
+ """
11
+ Creates empty homepage for Django CMS. Usuful to create some
12
+ at the beggining of tests so any test can start somewhere.
13
+ """
14
+ self._driver.get_elm(tag_name='form').submit()
15
+ self._driver.get_elm(tag_name='form').fill_out_and_submit({
16
+ '1-title': 'homepage',
17
+ })
cms_qe/hooks.py CHANGED
@@ -8,6 +8,7 @@ from django.db import InternalError, connection
8
8
  from django.http import HttpRequest, HttpResponseRedirect
9
9
  from django.template.response import TemplateResponse
10
10
  from django.urls import reverse
11
+ from django.utils.module_loading import import_string
11
12
  from django.utils.translation import gettext_lazy as _
12
13
  from djangocms_alias.models import AliasContent
13
14
  from menus.menu_pool import MenuRenderer, menu_pool
@@ -49,7 +50,8 @@ class PgIsInRecoveryLoginView(LoginView):
49
50
  class PgIsInRecoveryMenuRenderer(MenuRenderer):
50
51
 
51
52
  def __init__(self, pool, request):
52
- pool.menus['CMSMenu'] = CMSMenu
53
+ menu_path = getattr(settings, "CMS_QE_CMSMENU", None)
54
+ pool.menus['CMSMenu'] = CMSMenu if menu_path is None else import_string(menu_path)
53
55
  super().__init__(pool, request)
54
56
 
55
57
  def get_nodes(self, namespace=None, root_id=None, breadcrumb=False):
@@ -0,0 +1,8 @@
1
+ from django.urls.converters import StringConverter
2
+
3
+
4
+ class PackagesConverter(StringConverter):
5
+ """JavaScriptCatalog packages converter."""
6
+
7
+ # Same as SlugConverter, but with extra '+', that is used in JavaScriptCatalog as a sepearator in list of packages.
8
+ regex = "[-a-zA-Z0-9_+]+"
cms_qe/urls.py CHANGED
@@ -10,9 +10,10 @@ from django.conf.urls.i18n import i18n_patterns
10
10
  from django.conf.urls.static import static
11
11
  from django.contrib import admin
12
12
  from django.contrib.sitemaps.views import sitemap
13
- from django.urls import include, path
13
+ from django.urls import include, path, register_converter
14
14
  from django.views.i18n import JavaScriptCatalog
15
15
 
16
+ from cms_qe.url_converters import PackagesConverter
16
17
  from cms_qe.views.maintenance import HealthCheckView, ReloadSiteView
17
18
  from cms_qe.views.redirect_to_page import RedirectToPage
18
19
  from cms_qe.views.search_result import SiteSearchView
@@ -34,6 +35,8 @@ handler404 = 'cms_qe.views.handler404'
34
35
  handler500 = 'cms_qe.views.handler500'
35
36
  handler503 = 'cms_qe.views.handler503'
36
37
 
38
+ register_converter(PackagesConverter, "pkg")
39
+
37
40
  urlpatterns = [
38
41
  path('', include('filer.server.urls')),
39
42
  path('csp-report', views.csp_report),
@@ -72,6 +75,7 @@ if settings.DEBUG:
72
75
  if settings.CMS_QE_AUTH_ENABLED:
73
76
  urlpatterns += i18n_patterns(
74
77
  path('jsi18n/', JavaScriptCatalog.as_view(), name='javascript-catalog'),
78
+ path('jsi18n/<pkg:packages>/', JavaScriptCatalog.as_view(), name='jsi18n'),
75
79
  path('jsi18n-aldryn-forms/', JavaScriptCatalog.as_view(packages=['aldryn_forms']), name='js-aldryn-forms'),
76
80
  path('admin/', admin.site.urls),
77
81
  path('auth/', include('cms_qe_auth.urls')),
@@ -80,6 +84,7 @@ if settings.CMS_QE_AUTH_ENABLED:
80
84
  else:
81
85
  urlpatterns += i18n_patterns(
82
86
  path('jsi18n/', JavaScriptCatalog.as_view(), name='javascript-catalog'),
87
+ path('jsi18n/<pkg:packages>/', JavaScriptCatalog.as_view(), name='jsi18n'),
83
88
  path('jsi18n-aldryn-forms/', JavaScriptCatalog.as_view(packages=['aldryn_forms']), name='js-aldryn-forms'),
84
89
  path('admin/', admin.site.urls),
85
90
  path('', include('cms.urls')),
cms_qe_table/forms.py CHANGED
@@ -49,8 +49,8 @@ class FilterWidget(forms.JSONField.widget):
49
49
  :any:`cms_qe_table.forms.TableWidget`. Please use both in the same form.
50
50
  """
51
51
 
52
- def render(self, name: str, value: str, attrs: Optional[dict] = None): # pylint: disable=W0221
53
- textarea = super().render(name, value, attrs)
52
+ def render(self, name: str, value: str, attrs: Optional[dict] = None, renderer: Any = None):
53
+ textarea = super().render(name, value, attrs, renderer)
54
54
  context = {
55
55
  'id': attrs['id'] if attrs else 'filter-widget',
56
56
  'textarea': textarea,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cms-qe
3
- Version: 4.5.0
3
+ Version: 4.5.2
4
4
  Summary: Django CMS Quick & Easy provides all important modules to run new page withouta lot of coding. Aims to do it very easily and securely.
5
5
  Home-page: https://websites.pages.nic.cz/django-cms-qe
6
6
  Author: CZ.NIC, z.s.p.o.
@@ -1,3 +1,16 @@
1
+ -/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ -/browser.py,sha256=OcfqxDa9OtL7M5CSwfIxtzToMUEhqGLvditemPeEUNo,1437
3
+ -/conftest.py,sha256=mAptaAyj7a1hbUPDRWBBs1qL0TJ8Fma7Mch6PZwgtNo,220
4
+ -/cms_qe/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ -/cms_qe/test_base.py,sha256=RbJQLvSvrskOibwY7CmR2XrYCWHBk2UTVyvJwZuDXpE,36
6
+ -/cms_qe/test_errors.py,sha256=oGwegQ6hmS-VgnuYKRFOSaVpfNXX5tDdNemGSJoDNpw,378
7
+ -/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ -/fixtures/base.py,sha256=c5oqqqvtCRUmVQdvlu6kPBypGz8gdIPJP0Gcvl6fBGs,1788
9
+ -/pages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ -/pages/cms/__init__.py,sha256=_qe4YZYaQbrXp7Szmmeo4TUSkXlE5Rozu8E3tthA6-E,150
11
+ -/pages/cms/login.py,sha256=UPzJQcYff8NUAT4nvmfQoJQxzOJyPrJ_cKtH35NVfNg,521
12
+ -/pages/cms/page.py,sha256=YQnpZkopfVnhoyQKpRDGqjNeV6xUl-pEHjEcZ9HRiPk,489
13
+ -/pages/cms/wizard.py,sha256=yatbXH-rf1ap4O1hY0I13WikM3zkm_NrAiSK6bqENIU,545
1
14
  cms_qe/__init__.py,sha256=do1c4s8BgjukMZMMMhBHs_lG9j8ncnAjR3oTICWEq5w,684
2
15
  cms_qe/admin.py,sha256=eLqAF3UIDWWyA0xE0Ft5WP5_3HImSWk3EYL2cRfL_8A,171
3
16
  cms_qe/apps.py,sha256=AeRcBWwGs7rKLlzHhnV8M_2BEnkoO9959VwesxfHaio,338
@@ -8,12 +21,13 @@ cms_qe/cms_menus_mixin.py,sha256=1i0t2PQoabzffuOZKIhneiJJ9K8Nz70dDS6DqWlJMRg,245
8
21
  cms_qe/constants.py,sha256=YWUWCIabSwcamGZynvkJ9i8OWGtfHf-wFirm8GtqQpI,90
9
22
  cms_qe/export.py,sha256=3MflO_EmaCrlqqa-cTMOiRirsp3r4mxdQNt-Zh5FtzY,8242
10
23
  cms_qe/fixtures.py,sha256=cq_wnZnqBwPBOHpp_0bHk424iCXKvwmN6ZaKwDvguXk,755
11
- cms_qe/hooks.py,sha256=Bu8eV2E8wTeOAPET8C_YocwMV6h5XLItPO3ItCkV-yI,3482
24
+ cms_qe/hooks.py,sha256=8xDLsSDZ9iEtzheFpCQSjbc8HhCkB47L0_Rt3hnt-rw,3649
12
25
  cms_qe/ldap.py,sha256=2mpFdLoIdT_pAiGJ6ADnE74YXjaC55aNANv0L8DVwqU,188
13
26
  cms_qe/monitoring.py,sha256=5t_o7o0htmAAxVjkN2oz0O0v9XdzfePhSfPGcLNPmE8,769
14
27
  cms_qe/signals.py,sha256=MbuLSxPlJA147LEg-lDWDoUNTV1y0OKjwoI3HzgR97g,1253
15
28
  cms_qe/staticfiles.py,sha256=OHkfDfpIxN0B-eCRagZzHDHyBgaulcyYgKhp_3mPZuk,1363
16
- cms_qe/urls.py,sha256=npDzzW9SgLVMZECTyOUL5Cpw7RxeuuNssTKOXuXuxtM,3247
29
+ cms_qe/url_converters.py,sha256=o90Altx8IR39Cgr0t__2exiWzzltHePJzIkTxKuePFY,294
30
+ cms_qe/urls.py,sha256=sLi-vHEz96omZzq3znOfP6ujr6K4TBxJ7-ZjFXKtInQ,3533
17
31
  cms_qe/utils.py,sha256=52ETz4NKv8xyBrMJ4yDUTfUBaO6Owp-5_IHfxDftQEE,2913
18
32
  cms_qe/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
33
  cms_qe/api/constants.py,sha256=pdSziATRm6yUaaPBYoD07JXcULMvKD0h5RdNTPpG0rM,64
@@ -3927,7 +3941,7 @@ cms_qe_table/__init__.py,sha256=0eiVSkglZ6A-QLBnGXQdTlysM6dj2kfTc6scFcUGGVA,1084
3927
3941
  cms_qe_table/cms_plugins.py,sha256=dR8b7h_xOJnQ4CDetxrfOiv1tfekhdnpe4KbKqasLi0,1065
3928
3942
  cms_qe_table/exceptions.py,sha256=D9jeyKebnha1lObxS-eJhDeIYLobqlQCLieqg5jPkEU,349
3929
3943
  cms_qe_table/fixtures.py,sha256=8uTt28vboA3J25zwx2P9LwM1jYmHAd1pUjUhA2MaK-c,357
3930
- cms_qe_table/forms.py,sha256=xY31OeQREHf7oNdQnuNw6KaOGlQlVRNAQc0L9aH3Ybo,2837
3944
+ cms_qe_table/forms.py,sha256=ji7syhElVoT4NAhTwd_f3aKmdjnblMOo2DBND-FRxIM,2844
3931
3945
  cms_qe_table/models.py,sha256=VwpfIjdXSmNhYnikGMMYWMGmeXdGxltx0qiAjwNyqMk,4083
3932
3946
  cms_qe_table/urls.py,sha256=fuNw0jv3TysA8bp1lTuj_5b1e5vQUJURn9zZNzBiLfE,246
3933
3947
  cms_qe_table/utils.py,sha256=hpe6cOHFff2de67APMPkZ3JTLLKME1GXIJ4ZUU3uDhE,4451
@@ -3976,8 +3990,8 @@ cms_qe_video/templates/cms_qe/video/video_source_file.html,sha256=QJF5fs88s9Fznp
3976
3990
  cms_qe_video/templates/cms_qe/video/video_widget.html,sha256=Yumciq6bGlAYI1lYx5j9V6IF8QYrncNYygPTkXEz6Wk,925
3977
3991
  cms_qe_video/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3978
3992
  cms_qe_video/templatetags/cms_qe_video.py,sha256=NR_mGv91J0rEreZrQjCzaaXSrZsKvrSas12wMJ-Dg24,1168
3979
- django_cms_qe-4.5.0.dist-info/licenses/LICENSE,sha256=5wLaeUil0gfU9p8C4zn2Yu_PvZBNieUoYl0z9FcFWdA,1521
3980
- django_cms_qe-4.5.0.dist-info/METADATA,sha256=flJkfof2GTuJ5SgrXWgZ7iEr8sKfjDXMuOR9s-ezPzg,6399
3981
- django_cms_qe-4.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
3982
- django_cms_qe-4.5.0.dist-info/top_level.txt,sha256=u9pqfoJfXwh29tMO7lnphA5yn7ChYZquFe7_sNtEiW8,150
3983
- django_cms_qe-4.5.0.dist-info/RECORD,,
3993
+ django_cms_qe-4.5.2.dist-info/licenses/LICENSE,sha256=5wLaeUil0gfU9p8C4zn2Yu_PvZBNieUoYl0z9FcFWdA,1521
3994
+ django_cms_qe-4.5.2.dist-info/METADATA,sha256=gS35alR2Z2Ld0jd03FqC6vCiL1xPXHnkEWCe7UjIK8Q,6399
3995
+ django_cms_qe-4.5.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
3996
+ django_cms_qe-4.5.2.dist-info/top_level.txt,sha256=kTKoWq2LvtdlDtFHYsZB5eRkNW7m6Jf7IVA3nks0984,152
3997
+ django_cms_qe-4.5.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,3 +1,4 @@
1
+ -
1
2
  cms_qe
2
3
  cms_qe_analytical
3
4
  cms_qe_auth