wagtail 7.2.1__py3-none-any.whl → 7.3rc1__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.
- wagtail/__init__.py +1 -1
- wagtail/actions/copy_for_translation.py +4 -2
- wagtail/admin/action_menu.py +4 -1
- wagtail/admin/api/actions/convert_alias.py +2 -2
- wagtail/admin/api/actions/copy.py +2 -2
- wagtail/admin/api/actions/copy_for_translation.py +2 -2
- wagtail/admin/api/actions/create_alias.py +2 -2
- wagtail/admin/api/actions/delete.py +1 -1
- wagtail/admin/api/actions/move.py +1 -1
- wagtail/admin/api/actions/publish.py +2 -2
- wagtail/admin/api/actions/revert_to_page_revision.py +2 -2
- wagtail/admin/api/actions/unpublish.py +1 -1
- wagtail/admin/api/filters.py +2 -2
- wagtail/admin/compare.py +22 -0
- wagtail/admin/forms/account.py +52 -1
- wagtail/admin/forms/comments.py +53 -0
- wagtail/admin/forms/models.py +36 -0
- wagtail/admin/forms/pages.py +7 -0
- wagtail/admin/forms/workflows.py +5 -2
- wagtail/admin/icons.py +4 -3
- wagtail/admin/locale/ar/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ar/LC_MESSAGES/django.po +35 -0
- wagtail/admin/locale/en/LC_MESSAGES/django.po +262 -234
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +72 -43
- wagtail/admin/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/django.po +566 -6
- wagtail/admin/locale/it/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/it/LC_MESSAGES/djangojs.po +40 -2
- wagtail/admin/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/nl/LC_MESSAGES/django.po +2 -2
- wagtail/admin/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sv/LC_MESSAGES/django.po +330 -15
- wagtail/admin/locale/sv/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/sv/LC_MESSAGES/djangojs.po +3 -2
- wagtail/admin/panels/comment_panel.py +1 -51
- wagtail/admin/panels/title_field_panel.py +3 -1
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/comments.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/privacy-switch.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/blocks.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +1 -1
- wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
- wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
- wagtail/admin/templates/wagtailadmin/base.html +1 -1
- wagtail/admin/templates/wagtailadmin/generic/edit_partials.html +100 -0
- wagtail/admin/templates/wagtailadmin/generic/form.html +26 -5
- wagtail/admin/templates/wagtailadmin/generic/includes/_loaded_revision_inputs.html +3 -0
- wagtail/admin/templates/wagtailadmin/generic/listing_results.html +1 -17
- wagtail/admin/templates/wagtailadmin/pages/create.html +14 -4
- wagtail/admin/templates/wagtailadmin/pages/edit.html +16 -3
- wagtail/admin/templates/wagtailadmin/pages/edit_partials.html +31 -0
- wagtail/admin/templates/wagtailadmin/pages/index_results.html +1 -9
- wagtail/admin/templates/wagtailadmin/shared/autosave/indicator.html +36 -0
- wagtail/admin/templates/wagtailadmin/shared/breadcrumbs.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/editing_sessions/list.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/editing_sessions/module.html +19 -3
- wagtail/admin/templates/wagtailadmin/shared/headers/_actions.html +5 -0
- wagtail/admin/templates/wagtailadmin/shared/headers/_history_icon_link.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +8 -9
- wagtail/admin/templates/wagtailadmin/shared/listing/filter_partials.html +19 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +3 -3
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/side_panel.html +3 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/privacy.html +18 -6
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +11 -4
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/workflow.html +22 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +1 -0
- wagtail/admin/templates/wagtailadmin/shared/side_panels.html +1 -2
- wagtail/admin/templates/wagtailadmin/shared/unsaved_changes_warning.html +20 -20
- wagtail/admin/templates/wagtailadmin/userbar/base.html +2 -0
- wagtail/admin/templates/wagtailadmin/userbar/item_accessibility.html +1 -1
- wagtail/admin/templatetags/wagtailadmin_tags.py +6 -14
- wagtail/admin/tests/pages/test_create_page.py +298 -1
- wagtail/admin/tests/pages/test_custom_listing.py +48 -2
- wagtail/admin/tests/pages/test_edit_page.py +721 -7
- wagtail/admin/tests/pages/test_explorer_view.py +9 -5
- wagtail/admin/tests/pages/test_page_search.py +15 -0
- wagtail/admin/tests/pages/test_revisions.py +4 -0
- wagtail/admin/tests/test_account_management.py +88 -2
- wagtail/admin/tests/test_collections_views.py +15 -15
- wagtail/admin/tests/test_compare.py +34 -0
- wagtail/admin/tests/test_editing_sessions.py +230 -8
- wagtail/admin/tests/test_forms.py +192 -1
- wagtail/admin/tests/test_icon_sprite.py +22 -2
- wagtail/admin/tests/test_page_chooser.py +13 -13
- wagtail/admin/tests/test_reports_views.py +4 -1
- wagtail/admin/tests/test_userbar.py +69 -5
- wagtail/admin/tests/test_views_generic.py +5 -5
- wagtail/admin/tests/test_workflows.py +14 -12
- wagtail/admin/tests/viewsets/test_model_viewset.py +13 -0
- wagtail/admin/ui/autosave.py +5 -0
- wagtail/admin/ui/editing_sessions.py +3 -0
- wagtail/admin/ui/side_panels.py +19 -20
- wagtail/admin/userbar.py +48 -27
- wagtail/admin/views/bulk_action/dispatcher.py +2 -2
- wagtail/admin/views/chooser.py +6 -6
- wagtail/admin/views/editing_sessions.py +20 -7
- wagtail/admin/views/generic/__init__.py +1 -0
- wagtail/admin/views/generic/chooser.py +5 -5
- wagtail/admin/views/generic/mixins.py +143 -26
- wagtail/admin/views/generic/models.py +157 -27
- wagtail/admin/views/generic/ordering.py +1 -1
- wagtail/admin/views/generic/preview.py +4 -4
- wagtail/admin/views/home.py +3 -1
- wagtail/admin/views/pages/create.py +77 -29
- wagtail/admin/views/pages/edit.py +160 -34
- wagtail/admin/views/pages/preview.py +4 -4
- wagtail/admin/views/pages/revisions.py +3 -0
- wagtail/admin/views/pages/search.py +4 -4
- wagtail/admin/views/pages/usage.py +2 -2
- wagtail/admin/views/tags.py +2 -2
- wagtail/admin/views/workflows.py +73 -54
- wagtail/admin/viewsets/model.py +34 -8
- wagtail/admin/widgets/button.py +11 -4
- wagtail/admin/widgets/chooser.py +6 -4
- wagtail/admin/widgets/slug.py +1 -1
- wagtail/api/v2/filters.py +27 -21
- wagtail/api/v2/pagination.py +4 -4
- wagtail/api/v2/views.py +7 -7
- wagtail/blocks/list_block.py +0 -8
- wagtail/blocks/migrations/migrate_operation.py +8 -1
- wagtail/blocks/stream_block.py +2 -10
- wagtail/blocks/struct_block.py +192 -12
- wagtail/compat.py +2 -2
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/forms/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/it/LC_MESSAGES/django.po +40 -2
- wagtail/contrib/frontend_cache/backends/azure.py +6 -6
- wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
- wagtail/contrib/frontend_cache/utils.py +1 -1
- wagtail/contrib/redirects/forms.py +1 -1
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +14 -14
- wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/it/LC_MESSAGES/django.po +15 -2
- wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/sv/LC_MESSAGES/django.po +16 -3
- wagtail/contrib/redirects/middleware.py +11 -7
- wagtail/contrib/redirects/models.py +17 -1
- wagtail/contrib/redirects/tests/test_import_admin_views.py +3 -3
- wagtail/contrib/redirects/tests/test_redirects.py +56 -8
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +6 -6
- wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/it/LC_MESSAGES/django.po +43 -2
- wagtail/contrib/search_promotions/tests.py +1 -1
- wagtail/contrib/search_promotions/views/settings.py +24 -25
- wagtail/contrib/settings/jinja2tags.py +2 -2
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -2
- wagtail/contrib/settings/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/it/LC_MESSAGES/django.po +6 -2
- wagtail/contrib/settings/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/sv/LC_MESSAGES/django.po +3 -2
- wagtail/contrib/settings/tests/generic/test_admin.py +118 -2
- wagtail/contrib/settings/tests/site_specific/test_admin.py +78 -15
- wagtail/contrib/settings/tests/site_specific/test_model.py +2 -2
- wagtail/contrib/settings/views.py +7 -0
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/simple_translation/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/it/LC_MESSAGES/django.po +5 -2
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +7 -7
- wagtail/contrib/styleguide/tests.py +2 -0
- wagtail/contrib/styleguide/views.py +4 -5
- wagtail/contrib/table_block/locale/ar/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/ar/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/it/LC_MESSAGES/django.po +5 -2
- wagtail/contrib/typed_table_block/blocks.py +37 -0
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/contrib/typed_table_block/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/sv/LC_MESSAGES/django.po +4 -3
- wagtail/contrib/typed_table_block/tests.py +108 -0
- wagtail/coreutils.py +4 -4
- wagtail/documents/__init__.py +4 -4
- wagtail/documents/locale/en/LC_MESSAGES/django.po +15 -15
- wagtail/documents/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/it/LC_MESSAGES/django.po +32 -2
- wagtail/documents/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/sv/LC_MESSAGES/django.po +32 -4
- wagtail/documents/models.py +1 -1
- wagtail/documents/tests/test_admin_views.py +19 -4
- wagtail/documents/tests/test_search.py +0 -2
- wagtail/documents/tests/test_views.py +6 -4
- wagtail/documents/views/bulk_actions/add_tags.py +1 -1
- wagtail/embeds/finders/facebook.py +3 -3
- wagtail/embeds/finders/instagram.py +3 -3
- wagtail/embeds/finders/oembed.py +7 -2
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/oembed_providers.py +8 -0
- wagtail/embeds/tests/test_embeds.py +35 -0
- wagtail/images/__init__.py +4 -4
- wagtail/images/admin_urls.py +3 -3
- wagtail/images/blocks.py +1 -1
- wagtail/images/formats.py +2 -2
- wagtail/images/image_operations.py +2 -2
- wagtail/images/locale/en/LC_MESSAGES/django.po +44 -40
- wagtail/images/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/it/LC_MESSAGES/django.po +50 -4
- wagtail/images/locale/nl/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/nl/LC_MESSAGES/django.po +3 -3
- wagtail/images/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/sv/LC_MESSAGES/django.po +49 -6
- wagtail/images/models.py +11 -10
- wagtail/images/templates/wagtailimages/images/index_results.html +1 -1
- wagtail/images/templates/wagtailimages/images/url_generator.html +17 -38
- wagtail/images/templates/wagtailimages/images/url_generator_output.html +28 -0
- wagtail/images/templatetags/wagtailimages_tags.py +4 -4
- wagtail/images/tests/test_admin_views.py +432 -59
- wagtail/images/tests/test_image_operations.py +2 -2
- wagtail/images/tests/test_models.py +0 -2
- wagtail/images/views/bulk_actions/add_tags.py +1 -1
- wagtail/images/views/images.py +72 -39
- wagtail/locale/en/LC_MESSAGES/django.po +103 -105
- wagtail/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/it/LC_MESSAGES/django.po +105 -2
- wagtail/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/sv/LC_MESSAGES/django.po +95 -12
- wagtail/locales/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/locales/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/it/LC_MESSAGES/django.po +13 -2
- wagtail/locales/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/locales/locale/sv/LC_MESSAGES/django.po +4 -3
- wagtail/locales/tests.py +5 -5
- wagtail/models/i18n.py +4 -6
- wagtail/models/media.py +18 -0
- wagtail/models/pages.py +65 -11
- wagtail/models/reference_index.py +15 -0
- wagtail/models/revisions.py +40 -12
- wagtail/models/workflows.py +0 -3
- wagtail/permission_policies/base.py +2 -2
- wagtail/permission_policies/collections.py +2 -2
- wagtail/project_template/requirements.txt +2 -2
- wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/signal_handlers.py +1 -0
- wagtail/sites/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/sites/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/sites/locale/sv/LC_MESSAGES/django.po +3 -2
- wagtail/sites/tests.py +7 -7
- wagtail/snippets/action_menu.py +2 -1
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +23 -13
- wagtail/snippets/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/sv/LC_MESSAGES/django.po +12 -1
- wagtail/snippets/tests/test_chooser_block.py +197 -0
- wagtail/snippets/tests/test_chooser_panel.py +149 -0
- wagtail/snippets/tests/test_chooser_views.py +375 -0
- wagtail/snippets/tests/test_chooser_widget.py +22 -0
- wagtail/snippets/tests/test_compare_revisions_view.py +167 -0
- wagtail/snippets/tests/test_copy_view.py +38 -0
- wagtail/snippets/tests/test_create_view.py +1159 -0
- wagtail/snippets/tests/test_delete_view.py +225 -0
- wagtail/snippets/tests/test_edit_view.py +2882 -0
- wagtail/snippets/tests/test_history_view.py +182 -0
- wagtail/snippets/tests/test_index_view.py +105 -0
- wagtail/snippets/tests/test_list_view.py +786 -0
- wagtail/snippets/tests/test_locking.py +28 -0
- wagtail/snippets/tests/test_permissions.py +167 -0
- wagtail/snippets/tests/test_preview.py +3 -3
- wagtail/snippets/tests/test_revert_view.py +343 -0
- wagtail/snippets/tests/test_snippet_models.py +112 -0
- wagtail/snippets/tests/test_unpublish_view.py +228 -0
- wagtail/snippets/tests/test_unschedule_view.py +151 -0
- wagtail/snippets/tests/test_viewset.py +38 -5
- wagtail/snippets/views/snippets.py +78 -30
- wagtail/snippets/widgets.py +2 -2
- wagtail/templatetags/wagtailcore_tags.py +2 -2
- wagtail/test/dummy_external_storage.py +1 -1
- wagtail/test/testapp/fixtures/test.json +22 -0
- wagtail/test/testapp/fixtures/test_empty.json +2 -0
- wagtail/test/testapp/fixtures/test_explorable_pages.json +10 -0
- wagtail/test/testapp/fixtures/test_specific.json +9 -0
- wagtail/test/testapp/migrations/0059_nopromotepage.py +25 -0
- wagtail/test/testapp/models.py +7 -0
- wagtail/test/testapp/views.py +5 -0
- wagtail/test/utils/page_tests.py +7 -7
- wagtail/test/utils/wagtail_factories/builder.py +2 -2
- wagtail/tests/streamfield_migrations/test_migrations.py +35 -0
- wagtail/tests/test_blocks.py +321 -61
- wagtail/tests/test_collection_model.py +12 -0
- wagtail/tests/test_page_model.py +190 -1
- wagtail/tests/test_page_privacy.py +5 -0
- wagtail/tests/test_reference_index.py +42 -0
- wagtail/tests/test_revision_model.py +118 -1
- wagtail/tests/test_utils.py +2 -2
- wagtail/users/locale/en/LC_MESSAGES/django.po +14 -14
- wagtail/users/locale/id_ID/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/id_ID/LC_MESSAGES/django.po +6 -2
- wagtail/users/locale/it/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/it/LC_MESSAGES/django.po +14 -2
- wagtail/users/locale/sv/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sv/LC_MESSAGES/django.po +48 -17
- wagtail/users/tests/test_admin_views.py +39 -25
- wagtail/users/utils.py +4 -1
- wagtail/users/views/groups.py +19 -5
- wagtail/users/wagtail_hooks.py +1 -1
- wagtail/utils/loading.py +2 -2
- wagtail-7.3rc1.data/data/AGENTS.md +21 -0
- wagtail-7.3rc1.data/data/CHANGELOG.txt +4941 -0
- wagtail-7.3rc1.data/data/CODE_OF_CONDUCT.md +71 -0
- wagtail-7.3rc1.data/data/CONTRIBUTORS.md +999 -0
- wagtail-7.3rc1.data/data/SPONSORS.md +55 -0
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/METADATA +6 -6
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/RECORD +310 -280
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/WHEEL +1 -1
- wagtail/images/static/wagtailimages/js/image-url-generator.js +0 -1
- wagtail/snippets/tests/test_snippets.py +0 -6377
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/licenses/LICENSE +0 -0
- {wagtail-7.2.1.dist-info → wagtail-7.3rc1.dist-info}/top_level.txt +0 -0
|
@@ -7,13 +7,13 @@ from django.conf import settings
|
|
|
7
7
|
from django.contrib.auth.models import Group, Permission
|
|
8
8
|
from django.core import mail
|
|
9
9
|
from django.core.files.base import ContentFile
|
|
10
|
-
from django.http import HttpRequest, HttpResponse
|
|
10
|
+
from django.http import HttpRequest, HttpResponse, JsonResponse
|
|
11
11
|
from django.test import TestCase, modify_settings, override_settings
|
|
12
12
|
from django.urls import reverse
|
|
13
13
|
from django.utils import timezone
|
|
14
14
|
from django.utils.translation import gettext_lazy as _
|
|
15
15
|
|
|
16
|
-
from wagtail.admin.action_menu import ActionMenuItem
|
|
16
|
+
from wagtail.admin.action_menu import ActionMenuItem, PublishMenuItem
|
|
17
17
|
from wagtail.admin.admin_url_finder import AdminURLFinder
|
|
18
18
|
from wagtail.exceptions import PageClassNotFoundError
|
|
19
19
|
from wagtail.models import (
|
|
@@ -119,6 +119,28 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
119
119
|
# Login
|
|
120
120
|
self.user = self.login()
|
|
121
121
|
|
|
122
|
+
def get_publish_button_label(self, response):
|
|
123
|
+
soup = self.get_soup(response.content)
|
|
124
|
+
publish_button = soup.select_one('.w-dropdown-button > [name="action-publish"]')
|
|
125
|
+
if publish_button is None:
|
|
126
|
+
publish_button = soup.select_one('[name="action-publish"]')
|
|
127
|
+
self.assertIsNotNone(publish_button)
|
|
128
|
+
label = publish_button.select_one('[data-w-progress-target="label"]')
|
|
129
|
+
self.assertIsNotNone(label)
|
|
130
|
+
return label.get_text(strip=True)
|
|
131
|
+
|
|
132
|
+
def schedule_child_page(self, go_live_at):
|
|
133
|
+
edit_url = reverse("wagtailadmin_pages:edit", args=(self.child_page.id,))
|
|
134
|
+
post_data = {
|
|
135
|
+
"title": self.child_page.title,
|
|
136
|
+
"content": self.child_page.content,
|
|
137
|
+
"slug": self.child_page.slug,
|
|
138
|
+
"go_live_at": submittable_timestamp(go_live_at),
|
|
139
|
+
}
|
|
140
|
+
self.client.post(edit_url, post_data, follow=True)
|
|
141
|
+
self.child_page.refresh_from_db(fields=["go_live_at"])
|
|
142
|
+
return edit_url
|
|
143
|
+
|
|
122
144
|
def assertSchedulingDialogRendered(self, response, edit_url):
|
|
123
145
|
# Should show the "Edit schedule" button
|
|
124
146
|
html = response.content.decode()
|
|
@@ -220,6 +242,106 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
220
242
|
expected_url = "/admin/pages/%d/edit/" % self.event_page.id
|
|
221
243
|
self.assertEqual(url_finder.get_edit_url(self.event_page), expected_url)
|
|
222
244
|
|
|
245
|
+
# Autosave defaults to enabled with 500ms interval
|
|
246
|
+
soup = self.get_soup(response.content)
|
|
247
|
+
form = soup.select_one("form[data-edit-form]")
|
|
248
|
+
self.assertIsNotNone(form)
|
|
249
|
+
self.assertIn("w-autosave", form["data-controller"].split())
|
|
250
|
+
self.assertTrue(
|
|
251
|
+
{
|
|
252
|
+
"w-unsaved:add->w-autosave#save:prevent",
|
|
253
|
+
"w-autosave:success->w-unsaved#clear",
|
|
254
|
+
}.issubset(form["data-action"].split())
|
|
255
|
+
)
|
|
256
|
+
self.assertEqual(form.attrs.get("data-w-autosave-interval-value"), "500")
|
|
257
|
+
|
|
258
|
+
def test_loaded_revision_id_and_timestamp_included_in_form(self):
|
|
259
|
+
# Ensure there's a revision for the page
|
|
260
|
+
self.event_page.title = "Updated event page"
|
|
261
|
+
revision = self.event_page.save_revision()
|
|
262
|
+
self.assertEqual(self.event_page.revisions.count(), 1)
|
|
263
|
+
|
|
264
|
+
response = self.client.get(
|
|
265
|
+
reverse("wagtailadmin_pages:edit", args=(self.event_page.id,)),
|
|
266
|
+
)
|
|
267
|
+
self.assertEqual(response.status_code, 200)
|
|
268
|
+
soup = self.get_soup(response.content)
|
|
269
|
+
form = soup.select_one("form[data-edit-form]")
|
|
270
|
+
self.assertIsNotNone(form)
|
|
271
|
+
loaded_revision = form.select_one("input[name='loaded_revision_id']")
|
|
272
|
+
self.assertIsNotNone(loaded_revision)
|
|
273
|
+
self.assertEqual(int(loaded_revision["value"]), revision.pk)
|
|
274
|
+
loaded_timestamp = form.select_one("input[name='loaded_revision_created_at']")
|
|
275
|
+
self.assertIsNotNone(loaded_timestamp)
|
|
276
|
+
self.assertEqual(loaded_timestamp["value"], revision.created_at.isoformat())
|
|
277
|
+
|
|
278
|
+
@override_settings(WAGTAIL_AUTOSAVE_INTERVAL=0)
|
|
279
|
+
def test_autosave_disabled(self):
|
|
280
|
+
response = self.client.get(
|
|
281
|
+
reverse("wagtailadmin_pages:edit", args=(self.event_page.id,))
|
|
282
|
+
)
|
|
283
|
+
self.assertEqual(response.status_code, 200)
|
|
284
|
+
soup = self.get_soup(response.content)
|
|
285
|
+
form = soup.select_one("form[data-edit-form]")
|
|
286
|
+
self.assertIsNotNone(form)
|
|
287
|
+
self.assertNotIn("w-autosave", form["data-controller"].split())
|
|
288
|
+
self.assertNotIn("w-autosave", form["data-action"])
|
|
289
|
+
self.assertIsNone(form.attrs.get("data-w-autosave-interval-value"))
|
|
290
|
+
|
|
291
|
+
@override_settings(WAGTAIL_AUTOSAVE_INTERVAL=2000)
|
|
292
|
+
def test_autosave_custom_interval(self):
|
|
293
|
+
response = self.client.get(
|
|
294
|
+
reverse("wagtailadmin_pages:edit", args=(self.event_page.id,))
|
|
295
|
+
)
|
|
296
|
+
self.assertEqual(response.status_code, 200)
|
|
297
|
+
soup = self.get_soup(response.content)
|
|
298
|
+
form = soup.select_one("form[data-edit-form]")
|
|
299
|
+
self.assertIsNotNone(form)
|
|
300
|
+
self.assertIn("w-autosave", form["data-controller"].split())
|
|
301
|
+
self.assertTrue(
|
|
302
|
+
{
|
|
303
|
+
"w-unsaved:add->w-autosave#save:prevent",
|
|
304
|
+
"w-autosave:success->w-unsaved#clear",
|
|
305
|
+
}.issubset(form["data-action"].split())
|
|
306
|
+
)
|
|
307
|
+
self.assertEqual(form.attrs.get("data-w-autosave-interval-value"), "2000")
|
|
308
|
+
|
|
309
|
+
def test_publish_button_shows_schedule_label_for_future_go_live(self):
|
|
310
|
+
go_live_at = timezone.now() + datetime.timedelta(hours=1)
|
|
311
|
+
|
|
312
|
+
response = self.client.get(self.schedule_child_page(go_live_at))
|
|
313
|
+
self.assertEqual(response.status_code, 200)
|
|
314
|
+
|
|
315
|
+
publish_menu_item = next(
|
|
316
|
+
item
|
|
317
|
+
for item in response.context["action_menu"].menu_items
|
|
318
|
+
if getattr(item, "name", "") == "action-publish"
|
|
319
|
+
)
|
|
320
|
+
publish_context = publish_menu_item.get_context_data(
|
|
321
|
+
response.context["action_menu"].context
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
self.assertTrue(publish_context["is_scheduled"])
|
|
325
|
+
self.assertEqual(self.get_publish_button_label(response), "Schedule to publish")
|
|
326
|
+
|
|
327
|
+
def test_publish_button_shows_publish_label_for_past_schedule(self):
|
|
328
|
+
go_live_at = timezone.now() - datetime.timedelta(hours=1)
|
|
329
|
+
|
|
330
|
+
response = self.client.get(self.schedule_child_page(go_live_at))
|
|
331
|
+
self.assertEqual(response.status_code, 200)
|
|
332
|
+
|
|
333
|
+
publish_menu_item = next(
|
|
334
|
+
item
|
|
335
|
+
for item in response.context["action_menu"].menu_items
|
|
336
|
+
if getattr(item, "name", "") == "action-publish"
|
|
337
|
+
)
|
|
338
|
+
publish_context = publish_menu_item.get_context_data(
|
|
339
|
+
response.context["action_menu"].context
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
self.assertFalse(publish_context["is_scheduled"])
|
|
343
|
+
self.assertEqual(self.get_publish_button_label(response), "Publish")
|
|
344
|
+
|
|
223
345
|
def test_construct_page_action_menu_hook_with_custom_default_button(self):
|
|
224
346
|
class CustomDefaultItem(ActionMenuItem):
|
|
225
347
|
label = "Custom button"
|
|
@@ -468,6 +590,292 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
468
590
|
# The draft_title should have a new title
|
|
469
591
|
self.assertEqual(child_page_new.draft_title, post_data["title"])
|
|
470
592
|
|
|
593
|
+
def test_page_edit_post_with_json_response(self):
|
|
594
|
+
self.assertEqual(self.child_page.revisions.count(), 1)
|
|
595
|
+
loaded_revision = self.child_page.get_latest_revision()
|
|
596
|
+
# Tests simple editing
|
|
597
|
+
post_data = {
|
|
598
|
+
"title": "I've been edited!",
|
|
599
|
+
"content": "Some content",
|
|
600
|
+
"slug": "hello-world",
|
|
601
|
+
"loaded_revision_id": loaded_revision.pk,
|
|
602
|
+
"loaded_revision_created_at": loaded_revision.created_at.isoformat(),
|
|
603
|
+
}
|
|
604
|
+
response = self.client.post(
|
|
605
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
606
|
+
post_data,
|
|
607
|
+
headers={"Accept": "application/json"},
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
# Should be a 200 OK JSON response
|
|
611
|
+
self.assertEqual(response.status_code, 200)
|
|
612
|
+
self.assertEqual(response["Content-Type"], "application/json")
|
|
613
|
+
response_json = response.json()
|
|
614
|
+
self.assertEqual(response_json["success"], True)
|
|
615
|
+
self.assertEqual(response_json["pk"], self.child_page.pk)
|
|
616
|
+
self.assertEqual(response_json["field_updates"], {})
|
|
617
|
+
|
|
618
|
+
# Should create a new revision to be overwritten later
|
|
619
|
+
self.assertEqual(self.child_page.revisions.count(), 2)
|
|
620
|
+
self.assertNotEqual(response_json["revision_id"], loaded_revision.pk)
|
|
621
|
+
revision = self.child_page.revisions.get(pk=response_json["revision_id"])
|
|
622
|
+
self.assertEqual(
|
|
623
|
+
response_json["revision_created_at"],
|
|
624
|
+
revision.created_at.isoformat(),
|
|
625
|
+
)
|
|
626
|
+
self.assertEqual(revision.content["title"], "I've been edited!")
|
|
627
|
+
soup = self.get_soup(response_json["html"])
|
|
628
|
+
status_side_panel = soup.find(
|
|
629
|
+
"template",
|
|
630
|
+
{
|
|
631
|
+
"data-controller": "w-teleport",
|
|
632
|
+
"data-w-teleport-target-value": "[data-side-panel='status']",
|
|
633
|
+
"data-w-teleport-mode-value": "innerHTML",
|
|
634
|
+
},
|
|
635
|
+
)
|
|
636
|
+
self.assertIsNotNone(status_side_panel)
|
|
637
|
+
breadcrumbs = soup.find(
|
|
638
|
+
"template",
|
|
639
|
+
{
|
|
640
|
+
"data-controller": "w-teleport",
|
|
641
|
+
"data-w-teleport-target-value": "header [data-w-breadcrumbs]",
|
|
642
|
+
"data-w-teleport-mode-value": "outerHTML",
|
|
643
|
+
},
|
|
644
|
+
)
|
|
645
|
+
self.assertIsNotNone(breadcrumbs)
|
|
646
|
+
form_title_heading = soup.find(
|
|
647
|
+
"template",
|
|
648
|
+
{
|
|
649
|
+
"data-controller": "w-teleport",
|
|
650
|
+
"data-w-teleport-target-value": "#header-title span",
|
|
651
|
+
"data-w-teleport-mode-value": "textContent",
|
|
652
|
+
},
|
|
653
|
+
)
|
|
654
|
+
self.assertIsNone(form_title_heading)
|
|
655
|
+
header_title = soup.find(
|
|
656
|
+
"template",
|
|
657
|
+
{
|
|
658
|
+
"data-controller": "w-teleport",
|
|
659
|
+
"data-w-teleport-target-value": "head title",
|
|
660
|
+
"data-w-teleport-mode-value": "textContent",
|
|
661
|
+
},
|
|
662
|
+
)
|
|
663
|
+
self.assertIsNotNone(header_title)
|
|
664
|
+
self.assertEqual(
|
|
665
|
+
header_title.text.strip(),
|
|
666
|
+
# Looks a bit off because get_admin_display_title for SimplePage
|
|
667
|
+
# adds (simple page) suffix
|
|
668
|
+
"Editing Simple page: I've been edited! (simple page)",
|
|
669
|
+
)
|
|
670
|
+
|
|
671
|
+
# The page should have "has_unpublished_changes" flag set
|
|
672
|
+
child_page_new = SimplePage.objects.get(id=self.child_page.id)
|
|
673
|
+
self.assertTrue(child_page_new.has_unpublished_changes)
|
|
674
|
+
|
|
675
|
+
# Page fields should not be changed (because we just created a new draft)
|
|
676
|
+
self.assertEqual(child_page_new.title, self.child_page.title)
|
|
677
|
+
self.assertEqual(child_page_new.content, self.child_page.content)
|
|
678
|
+
self.assertEqual(child_page_new.slug, self.child_page.slug)
|
|
679
|
+
|
|
680
|
+
# The draft_title should have a new title
|
|
681
|
+
self.assertEqual(child_page_new.draft_title, post_data["title"])
|
|
682
|
+
|
|
683
|
+
def test_save_outdated_revision_with_json_response(self):
|
|
684
|
+
self.assertEqual(self.child_page.revisions.count(), 1)
|
|
685
|
+
loaded_revision = self.child_page.get_latest_revision()
|
|
686
|
+
self.child_page.title = "Someone else edited after the page is loaded"
|
|
687
|
+
other_revision = self.child_page.save_revision(user=self.user)
|
|
688
|
+
self.assertEqual(self.child_page.revisions.count(), 2)
|
|
689
|
+
|
|
690
|
+
post_data = {
|
|
691
|
+
"title": "Just another edit submitted after the other edit is done",
|
|
692
|
+
"content": "Some content",
|
|
693
|
+
"slug": "hello-world",
|
|
694
|
+
"loaded_revision_id": loaded_revision.pk,
|
|
695
|
+
}
|
|
696
|
+
response = self.client.post(
|
|
697
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
698
|
+
post_data,
|
|
699
|
+
headers={"Accept": "application/json"},
|
|
700
|
+
)
|
|
701
|
+
|
|
702
|
+
# Instead of creating a new revision for autosave (which means the user
|
|
703
|
+
# would unknowingly replace a newer revision), we return an error
|
|
704
|
+
# response that should be a 400 response
|
|
705
|
+
self.assertEqual(response.status_code, 400)
|
|
706
|
+
self.assertEqual(response["Content-Type"], "application/json")
|
|
707
|
+
self.assertEqual(
|
|
708
|
+
response.json(),
|
|
709
|
+
{
|
|
710
|
+
"success": False,
|
|
711
|
+
"error_code": "invalid_revision",
|
|
712
|
+
"error_message": "Saving will overwrite a newer version.",
|
|
713
|
+
},
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
# Page fields should still be from the published version
|
|
717
|
+
self.child_page.refresh_from_db()
|
|
718
|
+
self.assertEqual(self.child_page.title, "Hello world!")
|
|
719
|
+
|
|
720
|
+
# The initially loaded revision, and the actual latest revision,
|
|
721
|
+
# should both be unchanged
|
|
722
|
+
self.assertEqual(self.child_page.revisions.count(), 2)
|
|
723
|
+
loaded_revision.refresh_from_db()
|
|
724
|
+
self.assertEqual(loaded_revision.content["title"], "Hello world!")
|
|
725
|
+
other_revision.refresh_from_db()
|
|
726
|
+
self.assertEqual(
|
|
727
|
+
other_revision.content["title"],
|
|
728
|
+
"Someone else edited after the page is loaded",
|
|
729
|
+
)
|
|
730
|
+
self.assertEqual(self.child_page.get_latest_revision().id, other_revision.id)
|
|
731
|
+
|
|
732
|
+
def test_save_outdated_revision_timestamp_with_json_response(self):
|
|
733
|
+
self.assertEqual(self.child_page.revisions.count(), 1)
|
|
734
|
+
loaded_revision = self.child_page.get_latest_revision()
|
|
735
|
+
loaded_revision_created_at = loaded_revision.created_at.isoformat()
|
|
736
|
+
# Simulate the loaded revision being updated via another session's autosave,
|
|
737
|
+
# which means the revision is overwritten with new content and created_at
|
|
738
|
+
self.child_page.title = "Someone else edited after the page is loaded"
|
|
739
|
+
self.child_page.save_revision(overwrite_revision=loaded_revision)
|
|
740
|
+
self.assertEqual(self.child_page.revisions.count(), 1)
|
|
741
|
+
|
|
742
|
+
post_data = {
|
|
743
|
+
"title": "Just another edit submitted after the other edit is done",
|
|
744
|
+
"content": "Some content",
|
|
745
|
+
"slug": "hello-world",
|
|
746
|
+
"loaded_revision_id": loaded_revision.pk,
|
|
747
|
+
"loaded_revision_created_at": loaded_revision_created_at,
|
|
748
|
+
}
|
|
749
|
+
response = self.client.post(
|
|
750
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
751
|
+
post_data,
|
|
752
|
+
headers={"Accept": "application/json"},
|
|
753
|
+
)
|
|
754
|
+
|
|
755
|
+
# Instead of creating a new revision for autosave (which means the user
|
|
756
|
+
# would unknowingly replace the updated revision), we return an error
|
|
757
|
+
# response that should be a 400 response
|
|
758
|
+
self.assertEqual(response.status_code, 400)
|
|
759
|
+
self.assertEqual(response["Content-Type"], "application/json")
|
|
760
|
+
self.assertEqual(
|
|
761
|
+
response.json(),
|
|
762
|
+
{
|
|
763
|
+
"success": False,
|
|
764
|
+
"error_code": "invalid_revision",
|
|
765
|
+
"error_message": "Saving will overwrite a newer version.",
|
|
766
|
+
},
|
|
767
|
+
)
|
|
768
|
+
|
|
769
|
+
# Page fields should still be from the published version
|
|
770
|
+
self.child_page.refresh_from_db()
|
|
771
|
+
self.assertEqual(self.child_page.title, "Hello world!")
|
|
772
|
+
|
|
773
|
+
# The initially loaded revision should prefer the other session's autosave
|
|
774
|
+
self.assertEqual(self.child_page.revisions.count(), 1)
|
|
775
|
+
loaded_revision.refresh_from_db()
|
|
776
|
+
self.assertEqual(
|
|
777
|
+
loaded_revision.content["title"],
|
|
778
|
+
"Someone else edited after the page is loaded",
|
|
779
|
+
)
|
|
780
|
+
self.assertEqual(self.child_page.get_latest_revision().id, loaded_revision.id)
|
|
781
|
+
|
|
782
|
+
def test_page_edit_post_with_overwrite_revision_and_json_response(self):
|
|
783
|
+
self.assertEqual(self.child_page.revisions.count(), 1)
|
|
784
|
+
loaded_revision = self.child_page.get_latest_revision()
|
|
785
|
+
self.child_page.title = "A changed title"
|
|
786
|
+
revision = self.child_page.save_revision(user=self.user)
|
|
787
|
+
self.assertEqual(self.child_page.revisions.count(), 2)
|
|
788
|
+
|
|
789
|
+
post_data = {
|
|
790
|
+
"title": "I've been edited again!",
|
|
791
|
+
"content": "Some content",
|
|
792
|
+
"slug": "hello-world",
|
|
793
|
+
# The page was originally loaded with loaded_revision, but
|
|
794
|
+
# a successful autosave created a new revision which we now
|
|
795
|
+
# want to overwrite with a new autosave request
|
|
796
|
+
"loaded_revision_id": loaded_revision.pk,
|
|
797
|
+
"overwrite_revision_id": revision.id,
|
|
798
|
+
}
|
|
799
|
+
response = self.client.post(
|
|
800
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
801
|
+
post_data,
|
|
802
|
+
headers={"Accept": "application/json"},
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
# Should be a 200 OK JSON response
|
|
806
|
+
self.assertEqual(response.status_code, 200)
|
|
807
|
+
self.assertEqual(response["Content-Type"], "application/json")
|
|
808
|
+
revision.refresh_from_db()
|
|
809
|
+
response_json = response.json()
|
|
810
|
+
self.assertEqual(response_json["success"], True)
|
|
811
|
+
self.assertEqual(response_json["pk"], self.child_page.pk)
|
|
812
|
+
self.assertEqual(response_json["revision_id"], revision.pk)
|
|
813
|
+
self.assertEqual(
|
|
814
|
+
response_json["revision_created_at"],
|
|
815
|
+
revision.created_at.isoformat(),
|
|
816
|
+
)
|
|
817
|
+
|
|
818
|
+
# The page should have "has_unpublished_changes" flag set
|
|
819
|
+
child_page_new = SimplePage.objects.get(id=self.child_page.id)
|
|
820
|
+
self.assertTrue(child_page_new.has_unpublished_changes)
|
|
821
|
+
|
|
822
|
+
# Page fields should still be from the published version
|
|
823
|
+
self.assertEqual(child_page_new.title, "Hello world!")
|
|
824
|
+
|
|
825
|
+
# The draft_title should have a new title
|
|
826
|
+
self.assertEqual(child_page_new.draft_title, "I've been edited again!")
|
|
827
|
+
|
|
828
|
+
# There should still be only two revisions, but the latest one should be overwritten
|
|
829
|
+
self.assertEqual(self.child_page.revisions.count(), 2)
|
|
830
|
+
self.assertEqual(self.child_page.get_latest_revision().id, revision.id)
|
|
831
|
+
revision.refresh_from_db()
|
|
832
|
+
self.assertEqual(revision.content["title"], "I've been edited again!")
|
|
833
|
+
|
|
834
|
+
def test_overwrite_non_latest_revision(self):
|
|
835
|
+
self.child_page.title = "A changed title"
|
|
836
|
+
user_revision = self.child_page.save_revision(user=self.user)
|
|
837
|
+
self.child_page.title = "Someone else's changed title"
|
|
838
|
+
later_revision = self.child_page.save_revision()
|
|
839
|
+
self.assertEqual(self.child_page.revisions.count(), 3)
|
|
840
|
+
|
|
841
|
+
post_data = {
|
|
842
|
+
"title": "I've been edited again!",
|
|
843
|
+
"content": "Some content",
|
|
844
|
+
"slug": "hello-world",
|
|
845
|
+
"overwrite_revision_id": user_revision.id,
|
|
846
|
+
}
|
|
847
|
+
response = self.client.post(
|
|
848
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
849
|
+
post_data,
|
|
850
|
+
headers={"Accept": "application/json"},
|
|
851
|
+
)
|
|
852
|
+
|
|
853
|
+
# Should be a 400 response
|
|
854
|
+
self.assertEqual(response.status_code, 400)
|
|
855
|
+
self.assertEqual(response["Content-Type"], "application/json")
|
|
856
|
+
self.assertEqual(
|
|
857
|
+
response.json(),
|
|
858
|
+
{
|
|
859
|
+
"success": False,
|
|
860
|
+
"error_code": "invalid_revision",
|
|
861
|
+
"error_message": "Saving will overwrite a newer version.",
|
|
862
|
+
},
|
|
863
|
+
)
|
|
864
|
+
|
|
865
|
+
# Page fields should still be from the published version
|
|
866
|
+
self.child_page.refresh_from_db()
|
|
867
|
+
self.assertEqual(self.child_page.title, "Hello world!")
|
|
868
|
+
|
|
869
|
+
# The passed revision for overwriting, and the actual latest revision, should both be unchanged
|
|
870
|
+
self.assertEqual(self.child_page.revisions.count(), 3)
|
|
871
|
+
user_revision.refresh_from_db()
|
|
872
|
+
self.assertEqual(user_revision.content["title"], "A changed title")
|
|
873
|
+
later_revision.refresh_from_db()
|
|
874
|
+
self.assertEqual(
|
|
875
|
+
later_revision.content["title"], "Someone else's changed title"
|
|
876
|
+
)
|
|
877
|
+
self.assertEqual(self.child_page.get_latest_revision().id, later_revision.id)
|
|
878
|
+
|
|
471
879
|
def test_page_edit_post_unpublished_page(self):
|
|
472
880
|
# Based on test_page_edit_post(), but tests changes on a draft page vs. live page.
|
|
473
881
|
post_data = {
|
|
@@ -655,6 +1063,39 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
655
1063
|
child_page_new = SimplePage.objects.get(id=self.child_page.id)
|
|
656
1064
|
self.assertFalse(child_page_new.has_unpublished_changes)
|
|
657
1065
|
|
|
1066
|
+
def test_page_edit_post_when_locked_with_json_response(self):
|
|
1067
|
+
# Tests that trying to edit a locked page results in an error
|
|
1068
|
+
|
|
1069
|
+
# Lock the page
|
|
1070
|
+
self.child_page.locked = True
|
|
1071
|
+
self.child_page.save()
|
|
1072
|
+
|
|
1073
|
+
# Post
|
|
1074
|
+
post_data = {
|
|
1075
|
+
"title": "I've been edited!",
|
|
1076
|
+
"content": "Some content",
|
|
1077
|
+
"slug": "hello-world",
|
|
1078
|
+
}
|
|
1079
|
+
response = self.client.post(
|
|
1080
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
1081
|
+
post_data,
|
|
1082
|
+
headers={"Accept": "application/json"},
|
|
1083
|
+
)
|
|
1084
|
+
|
|
1085
|
+
self.assertEqual(response.status_code, 400)
|
|
1086
|
+
self.assertEqual(
|
|
1087
|
+
response.json(),
|
|
1088
|
+
{
|
|
1089
|
+
"success": False,
|
|
1090
|
+
"error_code": "locked",
|
|
1091
|
+
"error_message": "The page could not be saved as it is locked.",
|
|
1092
|
+
},
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
# The page shouldn't have "has_unpublished_changes" flag set
|
|
1096
|
+
child_page_new = SimplePage.objects.get(id=self.child_page.id)
|
|
1097
|
+
self.assertFalse(child_page_new.has_unpublished_changes)
|
|
1098
|
+
|
|
658
1099
|
def test_edit_post_scheduled(self):
|
|
659
1100
|
# put go_live_at and expire_at several days away from the current date, to avoid
|
|
660
1101
|
# false matches in content__ tests
|
|
@@ -1979,6 +2420,44 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
1979
2420
|
self.assertEqual(response.status_code, 200)
|
|
1980
2421
|
self.assertEqual(response.content, b"Overridden!")
|
|
1981
2422
|
|
|
2423
|
+
def test_before_edit_page_hook_with_json_response(self):
|
|
2424
|
+
def non_json_hook_func(request, page):
|
|
2425
|
+
self.assertIsInstance(request, HttpRequest)
|
|
2426
|
+
self.assertEqual(page.id, self.child_page.id)
|
|
2427
|
+
|
|
2428
|
+
return HttpResponse("Overridden!")
|
|
2429
|
+
|
|
2430
|
+
def json_hook_func(request, page):
|
|
2431
|
+
self.assertIsInstance(request, HttpRequest)
|
|
2432
|
+
self.assertEqual(page.id, self.child_page.id)
|
|
2433
|
+
|
|
2434
|
+
return JsonResponse({"status": "purple"})
|
|
2435
|
+
|
|
2436
|
+
with self.register_hook("before_edit_page", non_json_hook_func):
|
|
2437
|
+
response = self.client.get(
|
|
2438
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
2439
|
+
headers={"Accept": "application/json"},
|
|
2440
|
+
)
|
|
2441
|
+
|
|
2442
|
+
self.assertEqual(response.status_code, 400)
|
|
2443
|
+
self.assertEqual(
|
|
2444
|
+
response.json(),
|
|
2445
|
+
{
|
|
2446
|
+
"success": False,
|
|
2447
|
+
"error_code": "blocked_by_hook",
|
|
2448
|
+
"error_message": "Request to edit page was blocked by hook.",
|
|
2449
|
+
},
|
|
2450
|
+
)
|
|
2451
|
+
|
|
2452
|
+
with self.register_hook("before_edit_page", json_hook_func):
|
|
2453
|
+
response = self.client.get(
|
|
2454
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
2455
|
+
headers={"Accept": "application/json"},
|
|
2456
|
+
)
|
|
2457
|
+
|
|
2458
|
+
self.assertEqual(response.status_code, 200)
|
|
2459
|
+
self.assertEqual(response.json(), {"status": "purple"})
|
|
2460
|
+
|
|
1982
2461
|
def test_before_edit_page_hook_post(self):
|
|
1983
2462
|
def hook_func(request, page):
|
|
1984
2463
|
self.assertIsInstance(request, HttpRequest)
|
|
@@ -2004,6 +2483,72 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
2004
2483
|
# page should not be edited
|
|
2005
2484
|
self.assertEqual(Page.objects.get(id=self.child_page.id).title, "Hello world!")
|
|
2006
2485
|
|
|
2486
|
+
def test_before_edit_page_hook_post_with_json_response(self):
|
|
2487
|
+
def non_json_hook_func(request, page):
|
|
2488
|
+
self.assertIsInstance(request, HttpRequest)
|
|
2489
|
+
self.assertEqual(page.id, self.child_page.id)
|
|
2490
|
+
|
|
2491
|
+
return HttpResponse("Overridden!")
|
|
2492
|
+
|
|
2493
|
+
def json_hook_func(request, page):
|
|
2494
|
+
self.assertIsInstance(request, HttpRequest)
|
|
2495
|
+
self.assertEqual(page.id, self.child_page.id)
|
|
2496
|
+
|
|
2497
|
+
return JsonResponse({"status": "purple"})
|
|
2498
|
+
|
|
2499
|
+
with self.register_hook("before_edit_page", non_json_hook_func):
|
|
2500
|
+
post_data = {
|
|
2501
|
+
"title": "I've been edited!",
|
|
2502
|
+
"content": "Some content",
|
|
2503
|
+
"slug": "hello-world-new",
|
|
2504
|
+
}
|
|
2505
|
+
response = self.client.post(
|
|
2506
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
2507
|
+
post_data,
|
|
2508
|
+
headers={"Accept": "application/json"},
|
|
2509
|
+
)
|
|
2510
|
+
|
|
2511
|
+
self.assertEqual(response.status_code, 400)
|
|
2512
|
+
self.assertEqual(
|
|
2513
|
+
response.json(),
|
|
2514
|
+
{
|
|
2515
|
+
"success": False,
|
|
2516
|
+
"error_code": "blocked_by_hook",
|
|
2517
|
+
"error_message": "Request to edit page was blocked by hook.",
|
|
2518
|
+
},
|
|
2519
|
+
)
|
|
2520
|
+
|
|
2521
|
+
# page should not be edited
|
|
2522
|
+
self.assertEqual(
|
|
2523
|
+
Page.objects.get(id=self.child_page.id)
|
|
2524
|
+
.get_latest_revision_as_object()
|
|
2525
|
+
.title,
|
|
2526
|
+
"Hello world!",
|
|
2527
|
+
)
|
|
2528
|
+
|
|
2529
|
+
with self.register_hook("before_edit_page", json_hook_func):
|
|
2530
|
+
post_data = {
|
|
2531
|
+
"title": "I've been edited!",
|
|
2532
|
+
"content": "Some content",
|
|
2533
|
+
"slug": "hello-world-new",
|
|
2534
|
+
}
|
|
2535
|
+
response = self.client.post(
|
|
2536
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
2537
|
+
post_data,
|
|
2538
|
+
headers={"Accept": "application/json"},
|
|
2539
|
+
)
|
|
2540
|
+
|
|
2541
|
+
self.assertEqual(response.status_code, 200)
|
|
2542
|
+
self.assertEqual(response.json(), {"status": "purple"})
|
|
2543
|
+
|
|
2544
|
+
# page should not be edited
|
|
2545
|
+
self.assertEqual(
|
|
2546
|
+
Page.objects.get(id=self.child_page.id)
|
|
2547
|
+
.get_latest_revision_as_object()
|
|
2548
|
+
.title,
|
|
2549
|
+
"Hello world!",
|
|
2550
|
+
)
|
|
2551
|
+
|
|
2007
2552
|
def test_after_edit_page_hook(self):
|
|
2008
2553
|
def hook_func(request, page):
|
|
2009
2554
|
self.assertIsInstance(request, HttpRequest)
|
|
@@ -2031,6 +2576,66 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
2031
2576
|
Page.objects.get(id=self.child_page.id).title, "I've been edited!"
|
|
2032
2577
|
)
|
|
2033
2578
|
|
|
2579
|
+
def test_after_edit_page_hook_with_json_response(self):
|
|
2580
|
+
def non_json_hook_func(request, page):
|
|
2581
|
+
self.assertIsInstance(request, HttpRequest)
|
|
2582
|
+
self.assertEqual(page.id, self.child_page.id)
|
|
2583
|
+
|
|
2584
|
+
return HttpResponse("Overridden!")
|
|
2585
|
+
|
|
2586
|
+
def json_hook_func(request, page):
|
|
2587
|
+
self.assertIsInstance(request, HttpRequest)
|
|
2588
|
+
self.assertEqual(page.id, self.child_page.id)
|
|
2589
|
+
|
|
2590
|
+
return JsonResponse({"status": "purple"})
|
|
2591
|
+
|
|
2592
|
+
with self.register_hook("after_edit_page", non_json_hook_func):
|
|
2593
|
+
post_data = {
|
|
2594
|
+
"title": "I've been edited!",
|
|
2595
|
+
"content": "Some content",
|
|
2596
|
+
"slug": "hello-world-new",
|
|
2597
|
+
}
|
|
2598
|
+
response = self.client.post(
|
|
2599
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
2600
|
+
post_data,
|
|
2601
|
+
headers={"Accept": "application/json"},
|
|
2602
|
+
)
|
|
2603
|
+
|
|
2604
|
+
self.assertEqual(response.status_code, 200)
|
|
2605
|
+
# hook response is ignored, since it's not a JSON response
|
|
2606
|
+
self.assertEqual(response.json()["success"], True)
|
|
2607
|
+
|
|
2608
|
+
# page should be edited
|
|
2609
|
+
self.assertEqual(
|
|
2610
|
+
Page.objects.get(id=self.child_page.id)
|
|
2611
|
+
.get_latest_revision_as_object()
|
|
2612
|
+
.title,
|
|
2613
|
+
"I've been edited!",
|
|
2614
|
+
)
|
|
2615
|
+
|
|
2616
|
+
with self.register_hook("after_edit_page", json_hook_func):
|
|
2617
|
+
post_data = {
|
|
2618
|
+
"title": "I've been edited again!",
|
|
2619
|
+
"content": "Some content",
|
|
2620
|
+
"slug": "hello-world-new",
|
|
2621
|
+
}
|
|
2622
|
+
response = self.client.post(
|
|
2623
|
+
reverse("wagtailadmin_pages:edit", args=(self.child_page.id,)),
|
|
2624
|
+
post_data,
|
|
2625
|
+
headers={"Accept": "application/json"},
|
|
2626
|
+
)
|
|
2627
|
+
|
|
2628
|
+
self.assertEqual(response.status_code, 200)
|
|
2629
|
+
self.assertEqual(response.json(), {"status": "purple"})
|
|
2630
|
+
|
|
2631
|
+
# page should be edited
|
|
2632
|
+
self.assertEqual(
|
|
2633
|
+
Page.objects.get(id=self.child_page.id)
|
|
2634
|
+
.get_latest_revision_as_object()
|
|
2635
|
+
.title,
|
|
2636
|
+
"I've been edited again!",
|
|
2637
|
+
)
|
|
2638
|
+
|
|
2034
2639
|
def test_after_publish_page(self):
|
|
2035
2640
|
def hook_func(request, page):
|
|
2036
2641
|
self.assertIsInstance(request, HttpRequest)
|
|
@@ -2103,11 +2708,14 @@ class TestPageEdit(WagtailTestUtils, TestCase):
|
|
|
2103
2708
|
self.assertIsNotNone(publish_button)
|
|
2104
2709
|
|
|
2105
2710
|
def test_override_publish_action_menu_item_label(self):
|
|
2711
|
+
class CustomPublishMenuItem(PublishMenuItem):
|
|
2712
|
+
label = "Foobar"
|
|
2713
|
+
|
|
2106
2714
|
def hook_func(menu_items, request, context):
|
|
2107
|
-
|
|
2108
|
-
if item.name == "action-publish"
|
|
2109
|
-
|
|
2110
|
-
|
|
2715
|
+
menu_items[:] = [
|
|
2716
|
+
CustomPublishMenuItem() if item.name == "action-publish" else item
|
|
2717
|
+
for item in menu_items
|
|
2718
|
+
]
|
|
2111
2719
|
|
|
2112
2720
|
with self.register_hook("construct_page_action_menu", hook_func):
|
|
2113
2721
|
response = self.client.get(
|
|
@@ -2947,7 +3555,7 @@ class TestParentalM2M(WagtailTestUtils, TestCase):
|
|
|
2947
3555
|
self.assertIn(self.men_with_beards_category, updated_page.categories.all())
|
|
2948
3556
|
|
|
2949
3557
|
|
|
2950
|
-
class
|
|
3558
|
+
class TestValidationerror_messages(WagtailTestUtils, TestCase):
|
|
2951
3559
|
fixtures = ["test.json"]
|
|
2952
3560
|
|
|
2953
3561
|
def setUp(self):
|
|
@@ -3013,6 +3621,46 @@ class TestValidationErrorMessages(WagtailTestUtils, TestCase):
|
|
|
3013
3621
|
)
|
|
3014
3622
|
self.assertIn("This field is required", error_message.get_text())
|
|
3015
3623
|
|
|
3624
|
+
def test_field_error_with_json_response(self):
|
|
3625
|
+
post_data = {
|
|
3626
|
+
"title": "",
|
|
3627
|
+
"date_from": "2017-12-25",
|
|
3628
|
+
"slug": "christmas",
|
|
3629
|
+
"audience": "public",
|
|
3630
|
+
"location": "The North Pole",
|
|
3631
|
+
"cost": "Free",
|
|
3632
|
+
"carousel_items-TOTAL_FORMS": 0,
|
|
3633
|
+
"carousel_items-INITIAL_FORMS": 0,
|
|
3634
|
+
"carousel_items-MIN_NUM_FORMS": 0,
|
|
3635
|
+
"carousel_items-MAX_NUM_FORMS": 0,
|
|
3636
|
+
"speakers-TOTAL_FORMS": 0,
|
|
3637
|
+
"speakers-INITIAL_FORMS": 0,
|
|
3638
|
+
"speakers-MIN_NUM_FORMS": 0,
|
|
3639
|
+
"speakers-MAX_NUM_FORMS": 0,
|
|
3640
|
+
"related_links-TOTAL_FORMS": 0,
|
|
3641
|
+
"related_links-INITIAL_FORMS": 0,
|
|
3642
|
+
"related_links-MIN_NUM_FORMS": 0,
|
|
3643
|
+
"related_links-MAX_NUM_FORMS": 0,
|
|
3644
|
+
"head_counts-TOTAL_FORMS": 0,
|
|
3645
|
+
"head_counts-INITIAL_FORMS": 0,
|
|
3646
|
+
"head_counts-MIN_NUM_FORMS": 0,
|
|
3647
|
+
"head_counts-MAX_NUM_FORMS": 0,
|
|
3648
|
+
}
|
|
3649
|
+
response = self.client.post(
|
|
3650
|
+
reverse("wagtailadmin_pages:edit", args=(self.christmas_page.id,)),
|
|
3651
|
+
post_data,
|
|
3652
|
+
headers={"Accept": "application/json"},
|
|
3653
|
+
)
|
|
3654
|
+
self.assertEqual(response.status_code, 400)
|
|
3655
|
+
self.assertEqual(
|
|
3656
|
+
response.json(),
|
|
3657
|
+
{
|
|
3658
|
+
"success": False,
|
|
3659
|
+
"error_code": "validation_error",
|
|
3660
|
+
"error_message": "There are validation errors, click save to highlight them.",
|
|
3661
|
+
},
|
|
3662
|
+
)
|
|
3663
|
+
|
|
3016
3664
|
def test_non_field_error(self):
|
|
3017
3665
|
"""Non-field errors should be shown in the header message"""
|
|
3018
3666
|
post_data = {
|
|
@@ -3231,6 +3879,72 @@ class TestNestedInlinePanel(WagtailTestUtils, TestCase):
|
|
|
3231
3879
|
self.assertEqual(awards[0].name, "Beard Of The Century")
|
|
3232
3880
|
self.assertEqual(awards[1].name, "Bobsleigh Olympic gold medallist")
|
|
3233
3881
|
|
|
3882
|
+
def test_post_edit_with_json_response(self):
|
|
3883
|
+
self.christmas_page.unpublish() # so that draft changes are applied to the database record
|
|
3884
|
+
|
|
3885
|
+
post_data = nested_form_data(
|
|
3886
|
+
{
|
|
3887
|
+
"title": "Christmas",
|
|
3888
|
+
"date_from": "2017-12-25",
|
|
3889
|
+
"date_to": "2017-12-25",
|
|
3890
|
+
"slug": "christmas",
|
|
3891
|
+
"audience": "public",
|
|
3892
|
+
"location": "The North Pole",
|
|
3893
|
+
"cost": "Free",
|
|
3894
|
+
"carousel_items": inline_formset([]),
|
|
3895
|
+
"speakers": inline_formset(
|
|
3896
|
+
[
|
|
3897
|
+
{
|
|
3898
|
+
"id": self.speaker.id,
|
|
3899
|
+
"first_name": "Jeff",
|
|
3900
|
+
"last_name": "Christmas",
|
|
3901
|
+
"awards": inline_formset(
|
|
3902
|
+
[
|
|
3903
|
+
{
|
|
3904
|
+
"id": self.speaker.awards.first().id,
|
|
3905
|
+
"name": "Beard Of The Century",
|
|
3906
|
+
"date_awarded": "1997-12-25",
|
|
3907
|
+
},
|
|
3908
|
+
{
|
|
3909
|
+
"name": "Bobsleigh Olympic gold medallist",
|
|
3910
|
+
"date_awarded": "2018-02-01",
|
|
3911
|
+
},
|
|
3912
|
+
],
|
|
3913
|
+
initial=1,
|
|
3914
|
+
),
|
|
3915
|
+
},
|
|
3916
|
+
],
|
|
3917
|
+
initial=1,
|
|
3918
|
+
),
|
|
3919
|
+
"related_links": inline_formset([]),
|
|
3920
|
+
"head_counts": inline_formset([]),
|
|
3921
|
+
}
|
|
3922
|
+
)
|
|
3923
|
+
response = self.client.post(
|
|
3924
|
+
reverse("wagtailadmin_pages:edit", args=(self.christmas_page.id,)),
|
|
3925
|
+
post_data,
|
|
3926
|
+
headers={"Accept": "application/json"},
|
|
3927
|
+
)
|
|
3928
|
+
self.assertEqual(response.status_code, 200)
|
|
3929
|
+
response_json = response.json()
|
|
3930
|
+
self.assertEqual(response_json["success"], True)
|
|
3931
|
+
self.assertEqual(response_json["pk"], self.christmas_page.id)
|
|
3932
|
+
self.christmas_page.refresh_from_db()
|
|
3933
|
+
self.assertEqual(
|
|
3934
|
+
response_json["revision_id"], self.christmas_page.get_latest_revision().pk
|
|
3935
|
+
)
|
|
3936
|
+
|
|
3937
|
+
new_award = self.christmas_page.speakers.first().awards.get(
|
|
3938
|
+
name="Bobsleigh Olympic gold medallist"
|
|
3939
|
+
)
|
|
3940
|
+
self.assertEqual(
|
|
3941
|
+
response_json["field_updates"],
|
|
3942
|
+
{
|
|
3943
|
+
"speakers-0-awards-INITIAL_FORMS": "2",
|
|
3944
|
+
"speakers-0-awards-1-id": str(new_award.id),
|
|
3945
|
+
},
|
|
3946
|
+
)
|
|
3947
|
+
|
|
3234
3948
|
|
|
3235
3949
|
@override_settings(WAGTAIL_I18N_ENABLED=True)
|
|
3236
3950
|
class TestLocaleSelector(WagtailTestUtils, TestCase):
|