diff --git a/pyproject.toml b/pyproject.toml index c54a1444..ce977e3c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,27 +26,19 @@ classifiers=[ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", -<<<<<<< HEAD "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", -======= - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", ->>>>>>> cf6e93a (chore: Package overhaul (#140)) "Framework :: Django", "Framework :: Django :: 3.2", "Framework :: Django :: 4.2", "Framework :: Django CMS", -<<<<<<< HEAD - "Framework :: Django CMS :: 4.0", -======= "Framework :: Django CMS :: 3.8", "Framework :: Django CMS :: 3.9", "Framework :: Django CMS :: 3.10", "Framework :: Django CMS :: 3.11", ->>>>>>> cf6e93a (chore: Package overhaul (#140)) + "Framework :: Django CMS :: 4.0", + "Framework :: Django CMS :: 4.1", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development", diff --git a/src/djangocms_snippet/admin.py b/src/djangocms_snippet/admin.py index f0c55536..9ade47ec 100644 --- a/src/djangocms_snippet/admin.py +++ b/src/djangocms_snippet/admin.py @@ -1,3 +1,7 @@ +from typing import ClassVar + +from cms.utils import get_current_site +from cms.utils.permissions import get_model_permission_codename from django.conf import settings from django.contrib import admin from django.contrib.admin import helpers @@ -9,17 +13,12 @@ from django.urls import path from django.utils.translation import gettext as _ -from cms.utils import get_current_site -from cms.utils.permissions import get_model_permission_codename - -from .cms_config import SnippetCMSAppConfig from .forms import SnippetForm from .models import Snippet - # Use the version mixin if djangocms-versioning is installed and enabled snippet_admin_classes = [admin.ModelAdmin] -djangocms_versioning_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled +djangocms_versioning_enabled = getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_ENABLED", True) try: from djangocms_versioning.admin import ExtendedVersionAdminMixin @@ -40,16 +39,16 @@ class Media: ) list_display = ('name',) - search_fields = ['name'] + search_fields: ClassVar[list[str]] = ['name'] change_form_template = 'djangocms_snippet/admin/change_form.html' - text_area_attrs = { + text_area_attrs: ClassVar[dict] = { 'rows': 20, 'data-editor': True, 'data-mode': getattr(settings, 'DJANGOCMS_SNIPPET_THEME', 'html'), 'data-theme': getattr(settings, 'DJANGOCMS_SNIPPET_MODE', 'github'), } form = SnippetForm - formfield_overrides = { + formfield_overrides: ClassVar[dict] = { models.TextField: {'widget': Textarea(attrs=text_area_attrs)} } # This was move here from model, otherwise first() and last() return the same when handling grouper queries @@ -114,22 +113,22 @@ def preview_view(self, request, snippet_id=None, form_url='', extra_context=None return self._get_obj_does_not_exist_redirect(request, opts, str(snippet_id)) fieldsets = self.get_fieldsets(request, obj) - ModelForm = self.get_form( + model_form = self.get_form( request, obj, change=False, fields=flatten_fieldsets(fieldsets) ) - form = ModelForm(instance=obj) + form = model_form(instance=obj) formsets, inline_instances = self._create_formsets(request, obj, change=True) readonly_fields = flatten_fieldsets(fieldsets) - adminForm = helpers.AdminForm( + admin_form = helpers.AdminForm( form, list(fieldsets), # Clear prepopulated fields on a view-only form to avoid a crash. {}, readonly_fields, model_admin=self) - media = self.media + adminForm.media + media = self.media + admin_form.media inline_formsets = self.get_inline_formsets(request, formsets, inline_instances, obj) for inline_formset in inline_formsets: @@ -140,7 +139,7 @@ def preview_view(self, request, snippet_id=None, form_url='', extra_context=None **self.admin_site.each_context(request), 'title': title % opts.verbose_name, 'subtitle': str(obj) if obj else None, - 'adminform': adminForm, + 'adminform': admin_form, 'object_id': snippet_id, 'original': obj, 'is_popup': IS_POPUP_VAR in request.POST or IS_POPUP_VAR in request.GET, @@ -163,7 +162,8 @@ def get_urls(self): self.admin_site.admin_view(self.preview_view), name="{}_{}_preview".format(*info), ), - ] + super().get_urls() + *super().get_urls(), + ] def has_delete_permission(self, request, obj=None): """ diff --git a/src/djangocms_snippet/cms_config.py b/src/djangocms_snippet/cms_config.py index 9d9d4629..e45cc725 100644 --- a/src/djangocms_snippet/cms_config.py +++ b/src/djangocms_snippet/cms_config.py @@ -1,11 +1,9 @@ -from django.conf import settings - from cms.app_base import CMSAppConfig +from django.conf import settings from djangocms_snippet.models import Snippet from djangocms_snippet.rendering import render_snippet - try: from djangocms_moderation import __version__ # NOQA @@ -24,14 +22,15 @@ class SnippetCMSAppConfig(CMSAppConfig): cms_enabled = True # cms toolbar enabled to allow for versioning compare view - cms_toolbar_enabled_models = [(Snippet, render_snippet), ] + cms_toolbar_enabled_models = ((Snippet, render_snippet),) if djangocms_moderation_enabled and djangocms_moderation_installed: moderated_models = [Snippet] if djangocms_versioning_enabled: from djangocms_versioning.datastructures import ( - VersionableItem, default_copy, + VersionableItem, + default_copy, ) versioning = [ diff --git a/src/djangocms_snippet/cms_plugins.py b/src/djangocms_snippet/cms_plugins.py index 7112bbdc..58e8f7aa 100644 --- a/src/djangocms_snippet/cms_plugins.py +++ b/src/djangocms_snippet/cms_plugins.py @@ -1,12 +1,11 @@ +from cms.plugin_base import CMSPluginBase +from cms.plugin_pool import plugin_pool from django import template from django.conf import settings from django.utils.html import escape from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ -from cms.plugin_base import CMSPluginBase -from cms.plugin_pool import plugin_pool - from .forms import SnippetPluginForm from .models import SnippetPtr from .utils import show_draft_content diff --git a/src/djangocms_snippet/conf.py b/src/djangocms_snippet/conf.py index b4dc989e..e69de29b 100644 --- a/src/djangocms_snippet/conf.py +++ b/src/djangocms_snippet/conf.py @@ -1,6 +0,0 @@ -from django.conf import settings - - -DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID = getattr( - settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", 1 -) diff --git a/src/djangocms_snippet/forms.py b/src/djangocms_snippet/forms.py index a616f265..3a315fcd 100644 --- a/src/djangocms_snippet/forms.py +++ b/src/djangocms_snippet/forms.py @@ -1,21 +1,14 @@ +from cms.utils.urlutils import admin_reverse from django import forms from django.contrib import admin from django.db import transaction from django.utils.translation import gettext_lazy as _ -from cms.utils.urlutils import admin_reverse - -from djangocms_snippet.cms_config import SnippetCMSAppConfig from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr - - -try: - from djangocms_versioning import __version__ # NOQA - is_versioning_installed = True -except ImportError: - is_versioning_installed = False - -djangocms_versioning_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled +from djangocms_snippet.utils import ( + djangocms_versioning_enabled, + is_versioning_installed, +) class SnippetForm(forms.ModelForm): @@ -43,8 +36,7 @@ def clean(self): snippet_grouper = data.get("snippet_grouper") snippet_queryset = Snippet.objects.all() - if djangocms_versioning_enabled and is_versioning_installed: - if snippet_grouper: + if djangocms_versioning_enabled and is_versioning_installed and snippet_grouper: snippet_queryset = snippet_queryset.exclude(snippet_grouper=snippet_grouper) for snippet in snippet_queryset: diff --git a/src/djangocms_snippet/migrations/0010_alter_snippet_id.py b/src/djangocms_snippet/migrations/0010_alter_snippet_id.py deleted file mode 100644 index a16a153c..00000000 --- a/src/djangocms_snippet/migrations/0010_alter_snippet_id.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 4.2.6 on 2023-10-25 23:30 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ("djangocms_snippet", "0009_alter_snippetptr_cmsplugin_ptr"), - ] - - operations = [ - migrations.AlterField( - model_name="snippet", - name="id", - field=models.BigAutoField( - auto_created=True, primary_key=True, serialize=False, verbose_name="ID" - ), - ), - ] diff --git a/src/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py b/src/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py index 17e9ecab..1354cb0a 100644 --- a/src/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py +++ b/src/djangocms_snippet/migrations/0010_cms4_grouper_version_data_migration.py @@ -3,11 +3,6 @@ from django.contrib.contenttypes.management import create_contenttypes from django.db import migrations -from djangocms_snippet.cms_config import SnippetCMSAppConfig -from djangocms_snippet.conf import ( - DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID, -) - try: from djangocms_versioning.constants import DRAFT, PUBLISHED @@ -16,11 +11,15 @@ except ImportError: djangocms_versioning_installed = False +djangocms_versioning_config_enabled = getattr( + settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', True +) + def cms4_grouper_version_migration(apps, schema_editor): create_contenttypes(global_apps.get_app_config("djangocms_snippet")) - djangocms_versioning_config_enabled = SnippetCMSAppConfig.djangocms_versioning_enabled + ContentType = apps.get_model('contenttypes', 'ContentType') Snippet = apps.get_model('djangocms_snippet', 'Snippet') @@ -33,8 +32,7 @@ def cms4_grouper_version_migration(apps, schema_editor): # Get a migration user to create a version. if djangocms_versioning_config_enabled and djangocms_versioning_installed and len(snippet_queryset): Version = apps.get_model('djangocms_versioning', 'Version') - - migration_user = User.objects.get(id=DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID) + migration_user = User.objects.get(id=getattr(settings, "DJANGOCMS_SNIPPET_VERSIONING_MIGRATION_USER_ID", 1)) for snippet in snippet_queryset: grouper = SnippetGrouper.objects.create() @@ -55,7 +53,7 @@ def cms4_grouper_version_migration(apps, schema_editor): class Migration(migrations.Migration): dependencies = [ - ('cms', '0034_remove_pagecontent_placeholders'), # Run after the CMS4 migrations + # ('cms', '0034_remove_pagecontent_placeholders'), # Run after the CMS4 migrations ('djangocms_snippet', '0009_auto_20210915_0445'), ] diff --git a/src/djangocms_snippet/models.py b/src/djangocms_snippet/models.py index 1f04e886..ac9d15dc 100644 --- a/src/djangocms_snippet/models.py +++ b/src/djangocms_snippet/models.py @@ -1,27 +1,42 @@ from typing import ClassVar +from cms.models import CMSPlugin from django.conf import settings from django.contrib.sites.models import Site from django.db import models from django.shortcuts import reverse from django.utils.translation import gettext_lazy as _ -from cms.models import CMSPlugin +# Search is enabled by default to keep backwards compatibility. +SEARCH_ENABLED = getattr(settings, "DJANGOCMS_SNIPPET_SEARCH", False) -from djangocms_versioning.constants import DRAFT, PUBLISHED -# Search is enabled by default to keep backwards compatibility. -SEARCH_ENABLED = getattr(settings, "DJANGOCMS_SNIPPET_SEARCH", False) + +class AdminQuerySet(models.QuerySet): + def current_content(self, **kwargs): + """If a versioning package is installed, this returns the currently valid content + that matches the filter given in kwargs. Used to find content to be copied, e.g.. + Without versioning every page is current.""" + return self.filter(**kwargs) + + def latest_content(self, **kwargs): + """If a versioning package is installed, returns the latest version that matches the + filter given in kwargs including discarded or unpublished page content. Without versioning + every page content is the latest.""" + return self.filter(**kwargs) class SnippetGrouper(models.Model): """ The Grouper model for snippet, this is required for versioning """ + def __str__(self): + return self.name + @property def name(self): - snippet_qs = Snippet._base_manager.filter( + snippet_qs = Snippet.admin_manager.filter( snippet_grouper=self ) return snippet_qs.first().name or super().__str__ @@ -29,16 +44,12 @@ def name(self): def snippet(self, show_editable=False): if show_editable: # When in "edit" or "preview" mode we should be able to see the latest content - return Snippet._base_manager.filter( - versions__state__in=[DRAFT, PUBLISHED], + return Snippet.admin_manager.current_content().filter( snippet_grouper=self, ).order_by("-pk").first() # When in "live" mode we should only be able to see the default published version return Snippet.objects.filter(snippet_grouper=self).first() - def __str__(self): - return self.name - # Stores the actual data class Snippet(models.Model): @@ -80,6 +91,9 @@ class Snippet(models.Model): ) site = models.ForeignKey(Site, on_delete=models.CASCADE, null=True, blank=True) + objects = models.Manager() + admin_manager = AdminQuerySet.as_manager() + class Meta: ordering: ClassVar[list[str]] = ["name"] verbose_name = _("Snippet") @@ -90,16 +104,10 @@ def __str__(self): def get_preview_url(self): return reverse( - "admin:{app}_{model}_preview".format( - app=self._meta.app_label, model=self._meta.model_name, - ), + f"admin:{self._meta.app_label}_{self._meta.model_name}_preview", args=[self.id], ) - class Meta: - verbose_name = _('Snippet') - verbose_name_plural = _('Snippets') - # Plugin model - just a pointer to Snippet class SnippetPtr(CMSPlugin): diff --git a/src/djangocms_snippet/utils.py b/src/djangocms_snippet/utils.py index 13d88b7f..e1af8434 100644 --- a/src/djangocms_snippet/utils.py +++ b/src/djangocms_snippet/utils.py @@ -1,4 +1,15 @@ from cms.toolbar.utils import get_toolbar_from_request +from django.conf import settings + +try: + import djangocms_versioning + is_versioning_installed = True +except ImportError: + is_versioning_installed = False + +djangocms_versioning_enabled = is_versioning_installed and getattr( + settings, 'DJANGOCMS_SNIPPET_VERSIONING_ENABLED', True +) def show_draft_content(request=None): @@ -8,4 +19,4 @@ def show_draft_content(request=None): if not request: return False request_toolbar = get_toolbar_from_request(request) - return request_toolbar.edit_mode_active or request_toolbar.preview_mode_active + return request_toolbar.edit_mode_active or getattr(request_toolbar, "preview_mode_active", True) diff --git a/tests/settings.py b/tests/settings.py index c5ec3774..0c7ef2f2 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -1,11 +1,18 @@ #!/usr/bin/env python + +try: + import djangocms_versioning + + add_apps = ['djangocms_versioning'] +except ImportError: + add_apps = [] + HELPER_SETTINGS = { 'SECRET_KEY': "djangocmssnippetstestsuitekey", 'INSTALLED_APPS': [ 'tests.utils', - 'djangocms_versioning', 'djangocms_snippet', - ], + ] + add_apps, 'CMS_LANGUAGES': { 1: [{ 'code': 'en', diff --git a/tests/test_admin.py b/tests/test_admin.py index 8440e3e6..f93916be 100644 --- a/tests/test_admin.py +++ b/tests/test_admin.py @@ -1,17 +1,21 @@ from importlib import reload +from unittest import skipIf from django.contrib import admin from django.contrib.sites.models import Site from django.shortcuts import reverse from django.test import RequestFactory, override_settings +from cms import __version__ as cms_version from cms.test_utils.testcases import CMSTestCase from cms.utils import get_current_site -from djangocms_versioning.models import Version +try: + from djangocms_versioning.models import Version +except ImportError: + from tests.utils.models import Version from djangocms_snippet import admin as snippet_admin -from djangocms_snippet import cms_config from djangocms_snippet.forms import SnippetForm from djangocms_snippet.models import Snippet, SnippetGrouper @@ -77,7 +81,6 @@ def test_admin_list_display_without_versioning(self): Without versioning enabled, list_display should not be extended with version related items """ admin.site.unregister(Snippet) - reload(cms_config) reload(snippet_admin) # This has to be declared again, since it will now be constructed without the versioning extension self.snippet_admin = snippet_admin.SnippetAdmin(Snippet, admin) @@ -87,6 +90,7 @@ def test_admin_list_display_without_versioning(self): self.assertEqual(self.snippet_admin.__class__.__bases__, (admin.ModelAdmin, )) self.assertEqual(list_display, ('slug', 'name')) + @skipIf(cms_version < "4", "Django CMS 4 required") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_admin_list_display_with_versioning(self): """ @@ -113,13 +117,13 @@ def test_admin_uses_form(self): """ self.assertEqual(self.snippet_admin.form, SnippetForm) + @skipIf(cms_version < "4", "Django CMS 4 required") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_admin_delete_button_disabled_versioning_enabled(self): """ If versioning is enabled, the delete button should not be rendered on the change form """ admin.site.unregister(Snippet) - reload(cms_config) reload(snippet_admin) with self.login_user_context(self.superuser): @@ -135,7 +139,6 @@ def test_admin_delete_button_available_versioning_disabled(self): If versioning is disabled, the delete button should be rendered on the change form """ admin.site.unregister(Snippet) - reload(cms_config) reload(snippet_admin) with self.login_user_context(self.superuser): @@ -145,13 +148,13 @@ def test_admin_delete_button_available_versioning_disabled(self): response, 'Delete' ) + @skipIf(cms_version < "4", "Django CMS 4 required") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_admin_delete_endpoint_inaccessible_versioning_enabled(self): """ If versioning is enabled, the delete endpoint should not be accessible. """ admin.site.unregister(Snippet) - reload(cms_config) reload(snippet_admin) with self.login_user_context(self.superuser): @@ -166,7 +169,6 @@ def test_admin_delete_endpoint_accessible_versioning_disabled(self): If versioning is disabled, the delete endpoint should be accessible. """ admin.site.unregister(Snippet) - reload(cms_config) reload(snippet_admin) with self.login_user_context(self.superuser): @@ -190,6 +192,7 @@ def setUp(self): ) self.snippet_version = Version.objects.create(content=self.snippet, created_by=self.superuser) + @skipIf(cms_version < "4", "Django CMS 4 required") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_admin_form_save_method(self): with self.login_user_context(self.superuser): @@ -206,6 +209,7 @@ def test_admin_form_save_method(self): self.assertEqual(Snippet._base_manager.count(), 2) self.assertEqual(SnippetGrouper._base_manager.count(), 2) + @skipIf(cms_version < "4", "Django CMS 4 required") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_admin_form_edit_when_locked(self): """ @@ -228,7 +232,6 @@ def test_slug_colomn_should_hyperlinked_with_versioning_disabled(self): Slug column should be visible and hyperlinked when versioning is disabled """ admin.site.unregister(Snippet) - reload(cms_config) reload(snippet_admin) with self.login_user_context(self.get_superuser()): @@ -236,6 +239,7 @@ def test_slug_colomn_should_hyperlinked_with_versioning_disabled(self): self.assertContains(response, 'test-snippet') + @skipIf(cms_version < "4", "Django CMS 4 required") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_name_colomn_should_not_be_hyperlinked_with_versioning_enabled(self): """ @@ -243,7 +247,6 @@ def test_name_colomn_should_not_be_hyperlinked_with_versioning_enabled(self): Slug column should not be visible when versioning is enabled. """ admin.site.unregister(Snippet) - reload(cms_config) reload(snippet_admin) with self.login_user_context(self.get_superuser()): diff --git a/tests/test_config.py b/tests/test_config.py index 9f93e773..07ce7340 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,5 +1,8 @@ +from unittest import skipIf + from django.apps import apps +from cms import __version__ as cms_version from cms.test_utils.testcases import CMSTestCase from djangocms_snippet.models import Snippet, SnippetGrouper @@ -7,6 +10,7 @@ from .utils.factories import SnippetWithVersionFactory +@skipIf(cms_version < "4", "Django CMS 4 required") class VersioningConfigTestCase(CMSTestCase): def test_snippet_copy_method(self): diff --git a/tests/test_forms.py b/tests/test_forms.py index 83c71a8e..4559449d 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -1,10 +1,12 @@ from importlib import reload +from unittest import skipIf from django.test import override_settings +from cms import __version__ as cms_version from cms.test_utils.testcases import CMSTestCase -from djangocms_snippet import cms_config, forms +from djangocms_snippet import forms from djangocms_snippet.forms import SnippetPluginForm from djangocms_snippet.models import Snippet, SnippetGrouper @@ -19,7 +21,6 @@ def test_snippet_form_creates_grouper_no_versioning(self): Without versioning enabled, the application still has the grouper implemented, therefore the form should be creating one for each new snippet created. """ - reload(cms_config) reload(forms) form_data = { "name": "test_snippet", @@ -41,7 +42,6 @@ def test_snippet_form_creates_grouper_with_versioning(self): """ With versioning enabled, groupers should also be created in the background. """ - reload(cms_config) reload(forms) form_data = { "name": "test_snippet", @@ -63,7 +63,6 @@ def test_snippet_form_doesnt_create_grouper_or_snippet_with_no_commit(self): """ With versioning enabled, but no commit flag, models should still be created """ - reload(cms_config) reload(forms) form_data = { "name": "test_snippet", @@ -80,12 +79,12 @@ def test_snippet_form_doesnt_create_grouper_or_snippet_with_no_commit(self): self.assertEqual(SnippetGrouper.objects.count(), 1) self.assertEqual(Snippet._base_manager.count(), 1) + @skipIf(cms_version < "4", "Django CMS 4 required") @override_settings(DJANGOCMS_SNIPPET_VERSIONING_ENABLED=True) def test_snippet_form_adds_to_existing_grouper_with_versioning(self): """ With versioning enabled, if a grouper already exists, a new one shouldn't be created """ - reload(cms_config) reload(forms) grouper = SnippetGrouper.objects.create() form_data = { @@ -122,7 +121,6 @@ def test_snippet_form_versioning_enabled(self): With versioning enabled, the snippet form doesn't have to create groupers, but does have to validate that no other active (i.e. the latest published snippet from a given grouper) shares the same name or slug. """ - reload(cms_config) reload(forms) form_data = { "name": "test_snippet", @@ -154,11 +152,11 @@ def test_snippet_form_versioning_enabled(self): self.assertDictEqual(new_form.errors, {'slug': ['A Snippet with this slug already exists']}) + @skipIf(cms_version < "4", "Django CMS 4 required") def test_snippet_form_validation_multiple_version_states_in_grouper(self): """ Snippet forms should be valid regardless of the versions, or states which already exist within its grouper. """ - reload(cms_config) reload(forms) # snippet_to_archive starts as draft snippet_to_archive = SnippetWithVersionFactory() diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 210af121..fec10de2 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,11 +1,14 @@ import datetime +from unittest import skipIf + +from cms import __version__ as cms_version from cms.api import add_plugin, create_page -from cms.models import PageContent from cms.test_utils.testcases import CMSTestCase -from cms.toolbar.utils import get_object_edit_url, get_object_structure_url - -from djangocms_versioning.models import Version +try: + from djangocms_versioning.models import Version +except ImportError: + from tests.utils.models import Version from djangocms_snippet.models import Snippet, SnippetGrouper @@ -23,10 +26,16 @@ def setUp(self): language=self.language, created_by=self.superuser, ) - # Publish our page content - self.pagecontent = PageContent._base_manager.filter(page=self.page, language=self.language).first() - version = self.pagecontent.versions.first() - version.publish(self.superuser) + if cms_version < "4": + self.page.publish(self.language) + self.placeholder, _ = self.page.placeholders.get_or_create(slot="content") + else: + # Publish our page content + from cms.models import PageContent + self.pagecontent = PageContent._base_manager.filter(page=self.page, language=self.language).first() + version = self.pagecontent.versions.first() + version.publish(self.superuser) + self.placholder, _ = self.pagecontent.placeholders.get_or_create(slot="content") def test_html_rendering(self): snippet = SnippetWithVersionFactory( @@ -36,7 +45,7 @@ def test_html_rendering(self): ) snippet_grouper = snippet.snippet_grouper plugin = add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.placeholder, "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -66,7 +75,7 @@ def test_failing_html_rendering(self): snippet.versions.last().publish(user=self.get_superuser()) add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.placeholder, "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -89,7 +98,7 @@ def test_template_rendering(self): snippet_grouper = snippet.snippet_grouper snippet.versions.last().publish(user=self.get_superuser()) plugin = add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.placeholder, "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -117,7 +126,7 @@ def test_failing_template_rendering(self): snippet_grouper = snippet.snippet_grouper snippet.versions.last().publish(user=self.get_superuser()) add_plugin( - self.pagecontent.placeholders.get(slot="content"), + self.placeholder, "SnippetPlugin", self.language, snippet_grouper=snippet_grouper, @@ -129,6 +138,7 @@ def test_failing_template_rendering(self): self.assertContains(response, "Template some_template does not exist") +@skipIf(cms_version < "4", "Django CMS 4 required") class SnippetPluginVersioningRenderTestCase(CMSTestCase): def setUp(self): self.language = "en" diff --git a/tests/utils/factories.py b/tests/utils/factories.py index 9d6210c6..3ec6512b 100644 --- a/tests/utils/factories.py +++ b/tests/utils/factories.py @@ -6,12 +6,18 @@ from cms.models import Placeholder import factory -from djangocms_versioning.models import Version +from django.db import models from factory.fuzzy import FuzzyInteger, FuzzyText from djangocms_snippet.models import Snippet, SnippetGrouper, SnippetPtr +try: + from djangocms_versioning.models import Version +except ImportError: + from tests.utils.models import Version + + class UserFactory(factory.django.DjangoModelFactory): username = FuzzyText(length=12) first_name = factory.Faker("first_name") @@ -100,7 +106,14 @@ def get_plugin_position(plugin): """Helper function to correctly calculate the plugin position. Use this in plugin factory classes """ - offset = plugin.placeholder.get_last_plugin_position(plugin.language) or 0 + if hasattr(plugin.placeholder, "get_last_plugin_position"): + # Placeholder is a CMS v4 Placeholder + return (plugin.placeholder.get_last_plugin_position() or 0) + 1 + last_plugin_pos = plugin.placeholder.cmsplugin_set.filter( + parent=None, + language=plugin.language, + ).aggregate(models.Max("position")).get("position__max") + offset = (last_plugin_pos or -1) + 1 return offset + 1 diff --git a/tests/utils/models.py b/tests/utils/models.py new file mode 100644 index 00000000..506ba12d --- /dev/null +++ b/tests/utils/models.py @@ -0,0 +1,22 @@ +from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django.db import models + + +class Version(models.Model): + content = models.ForeignKey("djangocms_snippet.Snippet", related_name="versions", on_delete=models.CASCADE) + created_by = models.ForeignKey( + settings.AUTH_USER_MODEL, on_delete=models.PROTECT, + ) + state = models.CharField(max_length=50, default="draft") + + def __init__(self, *args, **kwargs): + kwargs.pop("content_type", None) + obj_id = kwargs.pop("object_id", None) + if obj_id: + kwargs["content_id"] = obj_id + super().__init__(*args, **kwargs) + + + def publish(self, user): + pass diff --git a/tox.ini b/tox.ini index a3fc6a9d..cb6c839b 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,8 @@ requires = envlist = flake8 isort - py{38,39,'3.10'}-dj{32,42}-cms{311,40} + py{39,310,311}-dj{32,42}-cms{311,40} + skip_missing_interpreters=True @@ -38,15 +39,11 @@ known_cms = cms, menus known_django = django [testenv] -<<<<<<< HEAD -deps = - -r{toxinidir}/tests/requirements/base.txt - dj32: Django>=3.2,<4 - dj42: Django>=4.2,<5 - cms311: django-cms>=3.11.0,<3.12 - cms40: django-cms>=4.0.0,<4.1 commands = - python -m coverage run setup.py test + {envpython} --version + {env:COMMAND:coverage} erase + {env:COMMAND:coverage} run setup.py test + {env:COMMAND:coverage} report deps = -r tests/requirements/{envname}.txt package = wheel set_env =