wagtail 6.2.2__py3-none-any.whl → 6.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 +6 -0
- wagtail/actions/publish_revision.py +3 -3
- wagtail/admin/action_menu.py +5 -3
- wagtail/admin/forms/account.py +1 -1
- wagtail/admin/icons.py +2 -6
- wagtail/admin/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/cy/LC_MESSAGES/django.po +32 -0
- wagtail/admin/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/dv/LC_MESSAGES/django.po +28 -0
- wagtail/admin/locale/en/LC_MESSAGES/django.po +451 -485
- wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +7 -7
- wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/django.po +150 -0
- wagtail/admin/locale/sl/LC_MESSAGES/djangojs.mo +0 -0
- wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +9 -2
- wagtail/admin/locale/ug/LC_MESSAGES/django.mo +0 -0
- wagtail/admin/locale/ug/LC_MESSAGES/django.po +3250 -196
- wagtail/admin/localization.py +8 -2
- wagtail/admin/panels/model_utils.py +1 -1
- wagtail/admin/site_summary.py +0 -2
- wagtail/admin/static/wagtailadmin/css/core.css +1 -1
- wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
- wagtail/admin/static/wagtailadmin/images/email-header.jpg +0 -0
- wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js +1 -1
- wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +12 -0
- wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
- wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
- wagtail/admin/static/wagtailadmin/js/telepath/widgets.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/static/wagtailadmin/js/workflow-action.js +1 -1
- wagtail/admin/staticfiles.py +6 -4
- wagtail/admin/templates/wagtailadmin/account/account.html +42 -59
- wagtail/admin/templates/wagtailadmin/admin_base.html +0 -28
- wagtail/admin/templates/wagtailadmin/bulk_actions/footer.html +1 -1
- wagtail/admin/templates/wagtailadmin/chooser/_search_results.html +7 -5
- wagtail/admin/templates/wagtailadmin/chooser/tables/page_navigate_to_children_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/generic/chooser/results.html +7 -5
- wagtail/admin/templates/wagtailadmin/generic/edit.html +0 -8
- wagtail/admin/templates/wagtailadmin/generic/form.html +60 -17
- wagtail/admin/templates/wagtailadmin/generic/index.html +17 -0
- wagtail/admin/templates/wagtailadmin/generic/index_results.html +9 -35
- wagtail/admin/templates/wagtailadmin/generic/inspect.html +2 -21
- wagtail/admin/templates/wagtailadmin/generic/listing.html +11 -17
- wagtail/admin/templates/wagtailadmin/generic/listing_results.html +19 -1
- wagtail/admin/templates/wagtailadmin/home/account_summary.html +26 -0
- wagtail/admin/templates/wagtailadmin/home/locked_pages.html +28 -18
- wagtail/admin/templates/wagtailadmin/home/recent_edits.html +28 -17
- wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html +2 -2
- wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html +35 -13
- wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html +28 -18
- wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +43 -32
- wagtail/admin/templates/wagtailadmin/home.html +22 -5
- wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -11
- wagtail/admin/templates/wagtailadmin/pages/action_menu/menu_item.html +1 -6
- wagtail/admin/templates/wagtailadmin/pages/action_menu/page_locked.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/publish.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_delete.html +12 -6
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_move.html +12 -7
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html +17 -11
- wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html +15 -9
- wagtail/admin/templates/wagtailadmin/pages/confirm_delete.html +9 -9
- wagtail/admin/templates/wagtailadmin/pages/confirm_move.html +2 -2
- wagtail/admin/templates/wagtailadmin/pages/confirm_unpublish.html +4 -4
- wagtail/admin/templates/wagtailadmin/pages/create.html +15 -34
- wagtail/admin/templates/wagtailadmin/pages/edit.html +15 -30
- wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +6 -0
- wagtail/admin/templates/wagtailadmin/pages/explorable_index_results.html +60 -0
- wagtail/admin/templates/wagtailadmin/pages/index.html +1 -36
- wagtail/admin/templates/wagtailadmin/pages/index_results.html +2 -50
- wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_ordering_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_header_buttons.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +3 -3
- wagtail/admin/templates/wagtailadmin/pages/listing/_pagination.html +1 -1
- wagtail/admin/templates/wagtailadmin/pages/listing.html +24 -0
- wagtail/admin/templates/wagtailadmin/pages/search.html +1 -20
- wagtail/admin/templates/wagtailadmin/pages/search_results.html +27 -25
- wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_formset.html +0 -1
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +2 -2
- wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +6 -6
- wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/action_menu/menu.html +14 -0
- wagtail/admin/templates/wagtailadmin/shared/action_menu/menu_item.html +6 -0
- wagtail/admin/templates/wagtailadmin/shared/avatar.html +13 -3
- wagtail/admin/templates/wagtailadmin/shared/header.html +0 -5
- wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +4 -1
- wagtail/admin/templates/wagtailadmin/shared/pagination_nav.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/locale.html +1 -1
- wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +94 -52
- wagtail/admin/templates/wagtailadmin/{pages/_unsaved_changes_warning.html → shared/unsaved_changes_warning.html} +4 -4
- wagtail/admin/templates/wagtailadmin/shared/usage_summary.html +2 -2
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +1 -7
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/listing.html +1 -0
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/{list.html → listing_results.html} +33 -35
- wagtail/admin/templates/wagtailadmin/tables/references_cell.html +1 -1
- wagtail/admin/templates/wagtailadmin/workflows/create.html +11 -36
- wagtail/admin/templates/wagtailadmin/workflows/create_task.html +0 -38
- wagtail/admin/templates/wagtailadmin/workflows/edit.html +44 -74
- wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +27 -66
- wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -2
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +4 -4
- wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +15 -11
- wagtail/admin/templates/wagtailadmin/workflows/task_chooser/includes/results.html +7 -5
- wagtail/admin/templatetags/wagtailadmin_tags.py +51 -22
- wagtail/admin/tests/pages/test_content_type_use_view.py +82 -2
- wagtail/admin/tests/pages/test_edit_page.py +70 -0
- wagtail/admin/tests/pages/test_explorer_view.py +65 -4
- wagtail/admin/tests/pages/test_page_search.py +8 -7
- wagtail/admin/tests/pages/test_page_usage.py +3 -1
- wagtail/admin/tests/pages/test_preview.py +208 -63
- wagtail/admin/tests/pages/test_reorder_page.py +91 -1
- wagtail/admin/tests/pages/test_view_draft.py +32 -1
- wagtail/admin/tests/pages/test_workflow_history.py +288 -7
- wagtail/admin/tests/test_account_management.py +23 -3
- wagtail/admin/tests/test_audit_log.py +24 -2
- wagtail/admin/tests/test_collections_views.py +17 -5
- wagtail/admin/tests/test_dashboard.py +1 -1
- wagtail/admin/tests/test_edit_handlers.py +3 -2
- wagtail/admin/tests/test_icon_sprite.py +4 -0
- wagtail/admin/tests/test_privacy.py +5 -19
- wagtail/admin/tests/test_reports_views.py +1 -1
- wagtail/admin/tests/test_site_summary.py +3 -3
- wagtail/admin/tests/test_templatetags.py +27 -3
- wagtail/admin/tests/test_upgrade_notification.py +71 -18
- wagtail/admin/tests/test_views.py +2 -2
- wagtail/admin/tests/test_views_generic.py +13 -0
- wagtail/admin/tests/test_widgets.py +3 -3
- wagtail/admin/tests/test_workflows.py +172 -27
- wagtail/admin/tests/tests.py +1 -1
- wagtail/admin/tests/viewsets/test_model_viewset.py +55 -3
- wagtail/admin/ui/side_panels.py +19 -0
- wagtail/admin/ui/sidebar.py +4 -3
- wagtail/admin/ui/tables/__init__.py +14 -1
- wagtail/admin/ui/tables/pages.py +6 -1
- wagtail/admin/urls/pages.py +10 -1
- wagtail/admin/urls/workflows.py +6 -1
- wagtail/admin/views/account.py +5 -1
- wagtail/admin/views/collections.py +0 -2
- wagtail/admin/views/generic/base.py +118 -1
- wagtail/admin/views/generic/history.py +158 -26
- wagtail/admin/views/generic/models.py +113 -99
- wagtail/admin/views/home.py +24 -9
- wagtail/admin/views/page_privacy.py +54 -30
- wagtail/admin/views/pages/history.py +11 -4
- wagtail/admin/views/pages/listing.py +76 -89
- wagtail/admin/views/pages/preview.py +1 -1
- wagtail/admin/views/pages/search.py +27 -71
- wagtail/admin/views/pages/usage.py +63 -24
- wagtail/admin/views/pages/utils.py +4 -3
- wagtail/admin/views/reports/base.py +0 -6
- wagtail/admin/views/workflows.py +67 -25
- wagtail/admin/viewsets/model.py +4 -3
- wagtail/admin/widgets/chooser.py +2 -1
- wagtail/api/v2/tests/test_pages.py +15 -2
- wagtail/blocks/field_block.py +15 -3
- wagtail/blocks/static_block.py +3 -0
- wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.po +29 -1
- wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +15 -11
- wagtail/contrib/forms/templates/wagtailforms/confirm_delete.html +1 -0
- wagtail/contrib/forms/templates/wagtailforms/index.html +1 -1
- wagtail/contrib/forms/templates/wagtailforms/index_results.html +1 -1
- wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +2 -1
- wagtail/contrib/forms/templates/wagtailforms/panels/form_responses_panel.html +2 -2
- wagtail/contrib/forms/tests/test_views.py +234 -35
- wagtail/contrib/forms/utils.py +8 -14
- wagtail/contrib/forms/views.py +72 -27
- wagtail/contrib/frontend_cache/backends/azure.py +1 -1
- wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
- wagtail/contrib/frontend_cache/backends/dummy.py +11 -0
- wagtail/contrib/frontend_cache/tests.py +31 -37
- wagtail/contrib/frontend_cache/utils.py +12 -5
- wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +16 -1
- wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +20 -24
- wagtail/contrib/redirects/models.py +16 -1
- wagtail/contrib/redirects/signal_handlers.py +18 -3
- wagtail/contrib/redirects/templates/wagtailredirects/add.html +5 -16
- wagtail/contrib/redirects/templates/wagtailredirects/import_summary.html +1 -1
- wagtail/contrib/redirects/tests/test_redirects.py +49 -6
- wagtail/contrib/redirects/tests/test_signal_handlers.py +42 -1
- wagtail/contrib/redirects/views.py +27 -3
- wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +60 -1
- wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +12 -18
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/add.html +5 -8
- wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/edit.html +15 -10
- wagtail/contrib/search_promotions/tests.py +13 -2
- wagtail/contrib/search_promotions/views.py +15 -3
- wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.po +6 -1
- wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -10
- wagtail/contrib/settings/templates/wagtailsettings/edit.html +12 -45
- wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.po +13 -1
- wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.po +3 -0
- wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +4 -4
- wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +5 -2
- wagtail/contrib/simple_translation/tests/test_views.py +51 -0
- wagtail/contrib/simple_translation/wagtail_hooks.py +16 -11
- wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.po +5 -1
- wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.po +27 -1
- wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/contrib/typed_table_block/blocks.py +25 -0
- wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.po +12 -1
- wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
- wagtail/contrib/typed_table_block/tests.py +24 -1
- wagtail/coreutils.py +5 -11
- wagtail/documents/admin_urls.py +2 -2
- wagtail/documents/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/documents/locale/cy/LC_MESSAGES/django.po +10 -0
- wagtail/documents/locale/en/LC_MESSAGES/django.po +61 -76
- wagtail/documents/migrations/0014_alter_document_file_size.py +18 -0
- wagtail/documents/models.py +1 -1
- wagtail/documents/rich_text/__init__.py +1 -3
- wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_tags.html +5 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
- wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_delete.html +11 -5
- wagtail/documents/templates/wagtaildocs/documents/add.html +13 -41
- wagtail/documents/templates/wagtaildocs/documents/edit.html +28 -56
- wagtail/documents/templates/wagtaildocs/documents/index.html +1 -4
- wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html +2 -2
- wagtail/documents/templates/wagtaildocs/multiple/add.html +36 -41
- wagtail/documents/tests/test_admin_views.py +64 -6
- wagtail/documents/tests/test_site_summary.py +3 -3
- wagtail/documents/views/documents.py +103 -113
- wagtail/documents/views/multiple.py +19 -1
- wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/embeds/oembed_providers.py +9 -19
- wagtail/fields.py +43 -27
- wagtail/images/admin_urls.py +2 -2
- wagtail/images/blocks.py +230 -2
- wagtail/images/fields.py +17 -29
- wagtail/images/image_operations.py +1 -1
- wagtail/images/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/images/locale/cy/LC_MESSAGES/django.po +128 -1
- wagtail/images/locale/en/LC_MESSAGES/django.po +119 -129
- wagtail/images/migrations/0025_alter_image_file_alter_rendition_file.py +36 -43
- wagtail/images/migrations/0027_image_description.py +20 -0
- wagtail/images/models.py +120 -45
- wagtail/images/rich_text/__init__.py +1 -3
- wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
- wagtail/images/static/wagtailimages/js/image-block.js +1 -0
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_tags.html +5 -1
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
- wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_delete.html +11 -5
- wagtail/images/templates/wagtailimages/chooser/results.html +2 -2
- wagtail/images/templates/wagtailimages/homepage/site_summary_images.html +2 -2
- wagtail/images/templates/wagtailimages/images/_file_field.html +2 -2
- wagtail/images/templates/wagtailimages/images/add.html +13 -31
- wagtail/images/templates/wagtailimages/images/edit.html +53 -82
- wagtail/images/templates/wagtailimages/images/index.html +1 -4
- wagtail/images/templates/wagtailimages/images/url_generator.html +1 -1
- wagtail/images/templates/wagtailimages/multiple/add.html +40 -47
- wagtail/images/templates/wagtailimages/widgets/image.html +5 -0
- wagtail/images/templates/wagtailimages/widgets/image_chooser.html +1 -1
- wagtail/images/tests/test_admin_views.py +70 -10
- wagtail/images/tests/test_blocks.py +367 -1
- wagtail/images/tests/test_image_operations.py +23 -0
- wagtail/images/tests/test_models.py +20 -0
- wagtail/images/tests/test_signal_handlers.py +99 -95
- wagtail/images/tests/test_site_summary.py +3 -3
- wagtail/images/tests/test_templatetags.py +11 -7
- wagtail/images/tests/tests.py +4 -0
- wagtail/images/views/images.py +103 -104
- wagtail/images/views/multiple.py +17 -1
- wagtail/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/cy/LC_MESSAGES/django.po +3 -0
- wagtail/locale/en/LC_MESSAGES/django.po +137 -125
- wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/locale/sl/LC_MESSAGES/django.po +3 -0
- wagtail/locales/locale/en/LC_MESSAGES/django.po +8 -8
- wagtail/locales/views.py +4 -1
- wagtail/migrations/0089_log_entry_data_json_null_to_object.py +1 -7
- wagtail/models/__init__.py +122 -14
- wagtail/models/audit_log.py +1 -3
- wagtail/models/i18n.py +1 -2
- wagtail/project_template/Dockerfile +3 -3
- wagtail/project_template/requirements.txt +2 -2
- wagtail/query.py +17 -4
- wagtail/rich_text/__init__.py +2 -3
- wagtail/rich_text/pages.py +2 -4
- wagtail/rich_text/rewriters.py +2 -2
- wagtail/search/backends/database/mysql/query.py +3 -3
- wagtail/search/backends/database/sqlite/query.py +6 -6
- wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
- wagtail/sites/locale/en/LC_MESSAGES/django.po +6 -6
- wagtail/sites/views.py +0 -1
- wagtail/snippets/action_menu.py +14 -4
- wagtail/snippets/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/snippets/locale/cy/LC_MESSAGES/django.po +73 -1
- wagtail/snippets/locale/en/LC_MESSAGES/django.po +27 -33
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
- wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
- wagtail/snippets/templates/wagtailsnippets/bulk_actions/confirm_bulk_delete.html +5 -3
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/locked.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu.html +1 -11
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu_item.html +1 -6
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +1 -1
- wagtail/snippets/templates/wagtailsnippets/snippets/create.html +1 -18
- wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +1 -14
- wagtail/snippets/templates/wagtailsnippets/snippets/index.html +2 -5
- wagtail/snippets/tests/test_preview.py +193 -61
- wagtail/snippets/tests/test_snippets.py +247 -38
- wagtail/snippets/tests/test_usage.py +5 -0
- wagtail/snippets/tests/test_viewset.py +25 -9
- wagtail/snippets/tests/test_workflows.py +232 -19
- wagtail/snippets/views/snippets.py +1 -10
- wagtail/test/numberformat.py +104 -0
- wagtail/test/settings.py +10 -0
- wagtail/test/settings_ui.py +2 -0
- wagtail/test/testapp/migrations/0010_alter_customimage_file_and_more.py +71 -78
- wagtail/test/testapp/migrations/0040_nocreatablesubpagetypespage_nosubpagetypespage.py +54 -0
- wagtail/test/testapp/migrations/0041_alter_jsonstreammodel_options.py +17 -0
- wagtail/test/testapp/migrations/0042_alter_customdocument_file_size_and_more.py +28 -0
- wagtail/test/testapp/migrations/0043_customimage_description.py +41 -0
- wagtail/test/testapp/migrations/0044_custompreviewsizesmodel_custompreviewsizespage.py +52 -0
- wagtail/test/testapp/migrations/0045_alter_streampage_body.py +52 -0
- wagtail/test/testapp/models.py +62 -4
- wagtail/test/testapp/rich_text.py +2 -2
- wagtail/test/testapp/templates/tests/form_page_landing.html +2 -1
- wagtail/test/testapp/urls.py +5 -0
- wagtail/test/testapp/views.py +5 -0
- wagtail/test/utils/page_tests.py +5 -5
- wagtail/test/utils/template_tests.py +2 -2
- wagtail/tests/test_blocks.py +15 -0
- wagtail/tests/test_page_permissions.py +109 -0
- wagtail/tests/test_revision_model.py +27 -0
- wagtail/tests/test_signals.py +21 -2
- wagtail/tests/test_tests.py +30 -0
- wagtail/users/locale/cy/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/cy/LC_MESSAGES/django.po +118 -1
- wagtail/users/locale/dv/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/dv/LC_MESSAGES/django.po +3 -0
- wagtail/users/locale/en/LC_MESSAGES/django.po +89 -113
- wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
- wagtail/users/locale/sl/LC_MESSAGES/django.po +3 -0
- wagtail/users/migrations/0014_userprofile_contrast.py +23 -0
- wagtail/users/models.py +11 -0
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_assign_role.html +5 -1
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_delete.html +5 -1
- wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_set_active_state.html +5 -1
- wagtail/users/templates/wagtailusers/groups/create.html +19 -17
- wagtail/users/templates/wagtailusers/groups/edit.html +2 -40
- wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +1 -62
- wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.html +0 -1
- wagtail/users/templates/wagtailusers/users/create.html +46 -50
- wagtail/users/templates/wagtailusers/users/edit.html +45 -62
- wagtail/users/templates/wagtailusers/users/index.html +1 -4
- wagtail/users/templatetags/wagtailusers_tags.py +1 -5
- wagtail/users/tests/test_admin_views.py +85 -66
- wagtail/users/views/groups.py +4 -1
- wagtail/users/views/users.py +2 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/METADATA +6 -6
- {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/RECORD +378 -367
- wagtail/admin/static/wagtailadmin/js/preview-panel.js +0 -2
- wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +0 -11
- wagtail/admin/templates/wagtailadmin/generic/history_results.html +0 -1
- wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +0 -3
- wagtail/admin/templates/wagtailadmin/pages/usage_results.html +0 -6
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/index.html +0 -17
- wagtail/admin/templates/wagtailadmin/shared/workflow_history/results.html +0 -17
- wagtail/admin/templates/wagtailadmin/workflows/usage.html +0 -44
- {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/LICENSE +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/WHEEL +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/entry_points.txt +0 -0
- {wagtail-6.2.2.dist-info → wagtail-6.3rc1.dist-info}/top_level.txt +0 -0
|
@@ -2,8 +2,15 @@ import unittest.mock
|
|
|
2
2
|
|
|
3
3
|
from django.apps import apps
|
|
4
4
|
from django.test import TestCase
|
|
5
|
+
from django.utils.safestring import SafeString
|
|
5
6
|
|
|
6
|
-
from wagtail.
|
|
7
|
+
from wagtail.admin import compare
|
|
8
|
+
from wagtail.blocks.stream_block import StreamValue
|
|
9
|
+
from wagtail.blocks.struct_block import StructBlockValidationError
|
|
10
|
+
from wagtail.images.blocks import ImageBlock, ImageChooserBlock
|
|
11
|
+
from wagtail.telepath import JSContext
|
|
12
|
+
from wagtail.test.testapp.models import StreamPage
|
|
13
|
+
from wagtail.test.utils.wagtail_tests import WagtailTestUtils
|
|
7
14
|
|
|
8
15
|
from .utils import (
|
|
9
16
|
Image,
|
|
@@ -73,3 +80,362 @@ class TestImageChooserBlock(TestCase):
|
|
|
73
80
|
|
|
74
81
|
# None should not yield any references
|
|
75
82
|
self.assertListEqual(list(block.extract_references(None)), [])
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class TestImageChooserBlockComparison(TestCase):
|
|
86
|
+
comparison_class = compare.StreamFieldComparison
|
|
87
|
+
|
|
88
|
+
def setUp(self):
|
|
89
|
+
self.image_1 = Image.objects.create(
|
|
90
|
+
title="Test image 1",
|
|
91
|
+
file=get_test_image_file(),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
self.image_2 = Image.objects.create(
|
|
95
|
+
title="Test image 2",
|
|
96
|
+
file=get_test_image_file(),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
self.field = StreamPage._meta.get_field("body")
|
|
100
|
+
|
|
101
|
+
def test_hasnt_changed(self):
|
|
102
|
+
field = StreamPage._meta.get_field("body")
|
|
103
|
+
|
|
104
|
+
comparison = self.comparison_class(
|
|
105
|
+
field,
|
|
106
|
+
StreamPage(
|
|
107
|
+
body=StreamValue(
|
|
108
|
+
field.stream_block,
|
|
109
|
+
[
|
|
110
|
+
("image", self.image_1, "1"),
|
|
111
|
+
],
|
|
112
|
+
)
|
|
113
|
+
),
|
|
114
|
+
StreamPage(
|
|
115
|
+
body=StreamValue(
|
|
116
|
+
field.stream_block,
|
|
117
|
+
[
|
|
118
|
+
("image", self.image_1, "1"),
|
|
119
|
+
],
|
|
120
|
+
)
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
self.assertTrue(comparison.is_field)
|
|
125
|
+
self.assertFalse(comparison.is_child_relation)
|
|
126
|
+
self.assertEqual(comparison.field_label(), "Body")
|
|
127
|
+
htmldiff = comparison.htmldiff()
|
|
128
|
+
self.assertIsInstance(htmldiff, SafeString)
|
|
129
|
+
self.assertIn('class="comparison__child-object"', htmldiff)
|
|
130
|
+
self.assertIn('class="preview-image"', htmldiff)
|
|
131
|
+
self.assertNotIn("deletion", htmldiff)
|
|
132
|
+
self.assertNotIn("addition", htmldiff)
|
|
133
|
+
self.assertFalse(comparison.has_changed())
|
|
134
|
+
|
|
135
|
+
def test_has_changed(self):
|
|
136
|
+
field = StreamPage._meta.get_field("body")
|
|
137
|
+
|
|
138
|
+
comparison = self.comparison_class(
|
|
139
|
+
field,
|
|
140
|
+
StreamPage(
|
|
141
|
+
body=StreamValue(
|
|
142
|
+
field.stream_block,
|
|
143
|
+
[
|
|
144
|
+
("image", self.image_1, "1"),
|
|
145
|
+
],
|
|
146
|
+
)
|
|
147
|
+
),
|
|
148
|
+
StreamPage(
|
|
149
|
+
body=StreamValue(
|
|
150
|
+
field.stream_block,
|
|
151
|
+
[
|
|
152
|
+
("image", self.image_2, "1"),
|
|
153
|
+
],
|
|
154
|
+
)
|
|
155
|
+
),
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
self.assertTrue(comparison.is_field)
|
|
159
|
+
self.assertFalse(comparison.is_child_relation)
|
|
160
|
+
self.assertEqual(comparison.field_label(), "Body")
|
|
161
|
+
htmldiff = comparison.htmldiff()
|
|
162
|
+
self.assertIsInstance(htmldiff, SafeString)
|
|
163
|
+
self.assertIn('class="comparison__child-object"', htmldiff)
|
|
164
|
+
self.assertIn('class="preview-image deletion"', htmldiff)
|
|
165
|
+
self.assertIn('class="preview-image addition"', htmldiff)
|
|
166
|
+
self.assertTrue(comparison.has_changed())
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class TestImageBlock(TestImageChooserBlock):
|
|
170
|
+
def test_render(self):
|
|
171
|
+
block = ImageBlock()
|
|
172
|
+
value = {
|
|
173
|
+
"image": self.image.id, # An id is expected
|
|
174
|
+
"alt_text": "Sample alt text",
|
|
175
|
+
"decorative": False,
|
|
176
|
+
}
|
|
177
|
+
html = block.render(block.to_python(value))
|
|
178
|
+
soup = WagtailTestUtils.get_soup(html)
|
|
179
|
+
img_tag = soup.find("img")
|
|
180
|
+
|
|
181
|
+
# check specific attributes
|
|
182
|
+
self.assertEqual(img_tag["alt"], value.get("alt_text"))
|
|
183
|
+
self.assertIn("/media/images/test", img_tag["src"])
|
|
184
|
+
|
|
185
|
+
def test_render_basic(self):
|
|
186
|
+
block = ImageBlock()
|
|
187
|
+
value = {
|
|
188
|
+
"image": self.image.id, # An id is expected
|
|
189
|
+
"alt_text": "Sample alt text",
|
|
190
|
+
"decorative": False,
|
|
191
|
+
}
|
|
192
|
+
html = block.render_basic(block.to_python(value))
|
|
193
|
+
soup = WagtailTestUtils.get_soup(html)
|
|
194
|
+
img_tag = soup.find("img")
|
|
195
|
+
|
|
196
|
+
# check specific attributes
|
|
197
|
+
self.assertEqual(img_tag["alt"], value.get("alt_text"))
|
|
198
|
+
self.assertIn("/media/images/test", img_tag["src"])
|
|
199
|
+
|
|
200
|
+
def test_render_as_decorative(self):
|
|
201
|
+
block = ImageBlock()
|
|
202
|
+
value = {
|
|
203
|
+
"image": self.image.id, # An id is expected
|
|
204
|
+
"alt_text": "Sample alt text",
|
|
205
|
+
"decorative": True,
|
|
206
|
+
}
|
|
207
|
+
html = block.render(block.to_python(value))
|
|
208
|
+
soup = WagtailTestUtils.get_soup(html)
|
|
209
|
+
img_tag = soup.find("img")
|
|
210
|
+
|
|
211
|
+
# check specific attributes
|
|
212
|
+
self.assertEqual(img_tag["alt"], "")
|
|
213
|
+
self.assertIn("/media/images/test", img_tag["src"])
|
|
214
|
+
|
|
215
|
+
def test_no_alt_text(self):
|
|
216
|
+
block = ImageBlock()
|
|
217
|
+
value = {
|
|
218
|
+
"image": self.image.id, # An id is expected
|
|
219
|
+
"alt_text": None, # No alt text passed
|
|
220
|
+
"decorative": False,
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
# Invalid state when no alt text is given, and image not marked as decorative
|
|
224
|
+
# Should raise a StructBlock validation error
|
|
225
|
+
with self.assertRaises(StructBlockValidationError) as context:
|
|
226
|
+
block.clean(block.to_python(value))
|
|
227
|
+
|
|
228
|
+
# Check the error message
|
|
229
|
+
self.assertIn(
|
|
230
|
+
"Please add some alt text for your image or mark it as decorative",
|
|
231
|
+
str(context.exception.block_errors["alt_text"]),
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
def test_to_python_with_int(self):
|
|
235
|
+
block = ImageBlock()
|
|
236
|
+
value = block.to_python(self.image.id)
|
|
237
|
+
|
|
238
|
+
self.assertEqual(value.id, self.image.id)
|
|
239
|
+
self.assertEqual(value.contextual_alt_text, None)
|
|
240
|
+
self.assertFalse(value.decorative)
|
|
241
|
+
|
|
242
|
+
def test_to_python_with_dict(self):
|
|
243
|
+
block = ImageBlock()
|
|
244
|
+
value = {"image": self.image.id, "alt_text": "Sample text", "decorative": False}
|
|
245
|
+
result = block.to_python(value)
|
|
246
|
+
|
|
247
|
+
self.assertEqual(result.id, self.image.id)
|
|
248
|
+
self.assertEqual(result.contextual_alt_text, "Sample text")
|
|
249
|
+
self.assertFalse(result.decorative)
|
|
250
|
+
|
|
251
|
+
def test_get_searchable_content(self):
|
|
252
|
+
block = ImageBlock()
|
|
253
|
+
value = {
|
|
254
|
+
"image": self.image.id, # An id is expected
|
|
255
|
+
"alt_text": "Sample alt text",
|
|
256
|
+
"decorative": False,
|
|
257
|
+
}
|
|
258
|
+
result = block.get_searchable_content(block.to_python(value))
|
|
259
|
+
|
|
260
|
+
# check specific attributes
|
|
261
|
+
self.assertEqual(result, ["Sample alt text"])
|
|
262
|
+
|
|
263
|
+
def test_required_true(self):
|
|
264
|
+
block = ImageBlock()
|
|
265
|
+
|
|
266
|
+
# the inner ImageChooserBlock should appear as required
|
|
267
|
+
image_block_def = JSContext().pack(block)
|
|
268
|
+
image_chooser_block_def = image_block_def["_args"][1][0]
|
|
269
|
+
self.assertTrue(image_chooser_block_def["_args"][2]["required"])
|
|
270
|
+
|
|
271
|
+
value = block.to_python(
|
|
272
|
+
{
|
|
273
|
+
"image": None,
|
|
274
|
+
"alt_text": "",
|
|
275
|
+
"decorative": False,
|
|
276
|
+
}
|
|
277
|
+
)
|
|
278
|
+
with self.assertRaises(StructBlockValidationError) as context:
|
|
279
|
+
block.clean(value)
|
|
280
|
+
|
|
281
|
+
self.assertIn(
|
|
282
|
+
"This field is required",
|
|
283
|
+
str(context.exception.block_errors["image"]),
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def test_required_false(self):
|
|
287
|
+
block = ImageBlock(required=False)
|
|
288
|
+
|
|
289
|
+
# the inner ImageChooserBlock should appear as non-required
|
|
290
|
+
image_block_def = JSContext().pack(block)
|
|
291
|
+
image_chooser_block_def = image_block_def["_args"][1][0]
|
|
292
|
+
self.assertFalse(image_chooser_block_def["_args"][2]["required"])
|
|
293
|
+
|
|
294
|
+
value = block.to_python(
|
|
295
|
+
{
|
|
296
|
+
"image": None,
|
|
297
|
+
"alt_text": "",
|
|
298
|
+
"decorative": False,
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
self.assertIsNone(block.clean(value))
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class TestImageBlockComparison(TestCase):
|
|
305
|
+
comparison_class = compare.StreamFieldComparison
|
|
306
|
+
|
|
307
|
+
def setUp(self):
|
|
308
|
+
self.image_1 = Image.objects.create(
|
|
309
|
+
title="Test image 1",
|
|
310
|
+
file=get_test_image_file(),
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
self.image_2 = Image.objects.create(
|
|
314
|
+
title="Test image 2",
|
|
315
|
+
file=get_test_image_file(),
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
self.field = StreamPage._meta.get_field("body")
|
|
319
|
+
|
|
320
|
+
def test_hasnt_changed(self):
|
|
321
|
+
field = StreamPage._meta.get_field("body")
|
|
322
|
+
|
|
323
|
+
page_1 = StreamPage()
|
|
324
|
+
page_1.body = [
|
|
325
|
+
{
|
|
326
|
+
"type": "image_with_alt",
|
|
327
|
+
"value": {
|
|
328
|
+
"image": self.image_1.id,
|
|
329
|
+
"decorative": False,
|
|
330
|
+
"alt_text": "Some alt text",
|
|
331
|
+
},
|
|
332
|
+
"id": "1",
|
|
333
|
+
},
|
|
334
|
+
]
|
|
335
|
+
page_2 = StreamPage()
|
|
336
|
+
page_2.body = [
|
|
337
|
+
{
|
|
338
|
+
"type": "image_with_alt",
|
|
339
|
+
"value": {
|
|
340
|
+
"image": self.image_1.id,
|
|
341
|
+
"decorative": False,
|
|
342
|
+
"alt_text": "Some alt text",
|
|
343
|
+
},
|
|
344
|
+
"id": "1",
|
|
345
|
+
},
|
|
346
|
+
]
|
|
347
|
+
|
|
348
|
+
comparison = self.comparison_class(field, page_1, page_2)
|
|
349
|
+
|
|
350
|
+
self.assertTrue(comparison.is_field)
|
|
351
|
+
self.assertFalse(comparison.is_child_relation)
|
|
352
|
+
self.assertEqual(comparison.field_label(), "Body")
|
|
353
|
+
htmldiff = comparison.htmldiff()
|
|
354
|
+
self.assertIsInstance(htmldiff, SafeString)
|
|
355
|
+
self.assertIn('class="comparison__child-object"', htmldiff)
|
|
356
|
+
self.assertIn('class="preview-image"', htmldiff)
|
|
357
|
+
self.assertNotIn("deletion", htmldiff)
|
|
358
|
+
self.assertNotIn("addition", htmldiff)
|
|
359
|
+
self.assertFalse(comparison.has_changed())
|
|
360
|
+
|
|
361
|
+
def test_has_changed(self):
|
|
362
|
+
field = StreamPage._meta.get_field("body")
|
|
363
|
+
|
|
364
|
+
page_1 = StreamPage()
|
|
365
|
+
page_1.body = [
|
|
366
|
+
{
|
|
367
|
+
"type": "image_with_alt",
|
|
368
|
+
"value": {
|
|
369
|
+
"image": self.image_1.id,
|
|
370
|
+
"decorative": False,
|
|
371
|
+
"alt_text": "Some alt text",
|
|
372
|
+
},
|
|
373
|
+
"id": "1",
|
|
374
|
+
},
|
|
375
|
+
]
|
|
376
|
+
page_2 = StreamPage()
|
|
377
|
+
page_2.body = [
|
|
378
|
+
{
|
|
379
|
+
"type": "image_with_alt",
|
|
380
|
+
"value": {
|
|
381
|
+
"image": self.image_2.id,
|
|
382
|
+
"decorative": False,
|
|
383
|
+
"alt_text": "Some alt text",
|
|
384
|
+
},
|
|
385
|
+
"id": "1",
|
|
386
|
+
},
|
|
387
|
+
]
|
|
388
|
+
|
|
389
|
+
comparison = self.comparison_class(field, page_1, page_2)
|
|
390
|
+
|
|
391
|
+
self.assertTrue(comparison.is_field)
|
|
392
|
+
self.assertFalse(comparison.is_child_relation)
|
|
393
|
+
self.assertEqual(comparison.field_label(), "Body")
|
|
394
|
+
htmldiff = comparison.htmldiff()
|
|
395
|
+
self.assertIsInstance(htmldiff, SafeString)
|
|
396
|
+
self.assertIn('class="comparison__child-object"', htmldiff)
|
|
397
|
+
self.assertIn('class="preview-image deletion"', htmldiff)
|
|
398
|
+
self.assertIn('class="preview-image addition"', htmldiff)
|
|
399
|
+
self.assertTrue(comparison.has_changed())
|
|
400
|
+
|
|
401
|
+
def test_alt_text_has_changed(self):
|
|
402
|
+
field = StreamPage._meta.get_field("body")
|
|
403
|
+
|
|
404
|
+
page_1 = StreamPage()
|
|
405
|
+
page_1.body = [
|
|
406
|
+
{
|
|
407
|
+
"type": "image_with_alt",
|
|
408
|
+
"value": {
|
|
409
|
+
"image": self.image_1.id,
|
|
410
|
+
"decorative": False,
|
|
411
|
+
"alt_text": "a cat playing with some string",
|
|
412
|
+
},
|
|
413
|
+
"id": "1",
|
|
414
|
+
},
|
|
415
|
+
]
|
|
416
|
+
page_2 = StreamPage()
|
|
417
|
+
page_2.body = [
|
|
418
|
+
{
|
|
419
|
+
"type": "image_with_alt",
|
|
420
|
+
"value": {
|
|
421
|
+
"image": self.image_1.id,
|
|
422
|
+
"decorative": False,
|
|
423
|
+
"alt_text": "a kitten playing with some string",
|
|
424
|
+
},
|
|
425
|
+
"id": "1",
|
|
426
|
+
},
|
|
427
|
+
]
|
|
428
|
+
|
|
429
|
+
comparison = self.comparison_class(field, page_1, page_2)
|
|
430
|
+
|
|
431
|
+
self.assertTrue(comparison.is_field)
|
|
432
|
+
self.assertFalse(comparison.is_child_relation)
|
|
433
|
+
self.assertEqual(comparison.field_label(), "Body")
|
|
434
|
+
htmldiff = comparison.htmldiff()
|
|
435
|
+
self.assertIsInstance(htmldiff, SafeString)
|
|
436
|
+
self.assertIn('class="comparison__child-object"', htmldiff)
|
|
437
|
+
self.assertIn(
|
|
438
|
+
'<dd>a <span class="deletion">cat</span><span class="addition">kitten</span> playing with some string</dd>',
|
|
439
|
+
htmldiff,
|
|
440
|
+
)
|
|
441
|
+
self.assertTrue(comparison.has_changed())
|
|
@@ -719,6 +719,29 @@ class TestFormatFilter(TestCase):
|
|
|
719
719
|
# quality=80 is default for the Willow and PIL libraries
|
|
720
720
|
save.assert_called_with(f, "WEBP", quality=80, lossless=True)
|
|
721
721
|
|
|
722
|
+
def test_heic(self):
|
|
723
|
+
fil = Filter(spec="width-400|format-heic")
|
|
724
|
+
image = Image.objects.create(
|
|
725
|
+
title="Test image",
|
|
726
|
+
file=get_test_image_file(),
|
|
727
|
+
)
|
|
728
|
+
out = fil.run(image, BytesIO())
|
|
729
|
+
|
|
730
|
+
self.assertEqual(out.format_name, "heic")
|
|
731
|
+
|
|
732
|
+
def test_heic_lossless(self):
|
|
733
|
+
fil = Filter(spec="width-400|format-heic-lossless")
|
|
734
|
+
image = Image.objects.create(
|
|
735
|
+
title="Test image",
|
|
736
|
+
file=get_test_image_file(),
|
|
737
|
+
)
|
|
738
|
+
|
|
739
|
+
f = BytesIO()
|
|
740
|
+
with patch("PIL.Image.Image.save") as save:
|
|
741
|
+
fil.run(image, f)
|
|
742
|
+
|
|
743
|
+
save.assert_called_with(f, "HEIF", quality=-1, chroma=444)
|
|
744
|
+
|
|
722
745
|
def test_invalid(self):
|
|
723
746
|
fil = Filter(spec="width-400|format-foo")
|
|
724
747
|
image = Image.objects.create(
|
|
@@ -145,6 +145,23 @@ class TestImage(TestCase):
|
|
|
145
145
|
)
|
|
146
146
|
self.assertIsNone(image.get_suggested_focal_point())
|
|
147
147
|
|
|
148
|
+
def test_default_with_description(self):
|
|
149
|
+
# Primary default should be description
|
|
150
|
+
image = Image.objects.create(
|
|
151
|
+
title="Test Image",
|
|
152
|
+
description="This is a test description",
|
|
153
|
+
file=get_test_image_file(),
|
|
154
|
+
)
|
|
155
|
+
self.assertEqual(image.default_alt_text, image.description)
|
|
156
|
+
|
|
157
|
+
def test_default_without_description(self):
|
|
158
|
+
# Secondary default should be title
|
|
159
|
+
image = Image.objects.create(
|
|
160
|
+
title="Test Image",
|
|
161
|
+
file=get_test_image_file(),
|
|
162
|
+
)
|
|
163
|
+
self.assertEqual(image.default_alt_text, image.title)
|
|
164
|
+
|
|
148
165
|
|
|
149
166
|
class TestImageQuerySet(TransactionTestCase):
|
|
150
167
|
fixtures = ["test_empty.json"]
|
|
@@ -787,6 +804,9 @@ class TestRenditions(TestCase):
|
|
|
787
804
|
prefetched_rendition = fresh_image.get_rendition("width-500")
|
|
788
805
|
self.assertFalse(hasattr(prefetched_rendition, "_mark"))
|
|
789
806
|
|
|
807
|
+
# Check that the image instance is the same as the retrieved rendition
|
|
808
|
+
self.assertIs(new_rendition.image, self.image)
|
|
809
|
+
|
|
790
810
|
# changing the image file should invalidate the cache
|
|
791
811
|
self.image.file = get_test_image_file(colour="green")
|
|
792
812
|
self.image.save()
|
|
@@ -1,95 +1,99 @@
|
|
|
1
|
-
from django.db import transaction
|
|
2
|
-
from django.test import TestCase, TransactionTestCase, override_settings
|
|
3
|
-
|
|
4
|
-
from wagtail.images import get_image_model, signal_handlers
|
|
5
|
-
from wagtail.images.tests.utils import get_test_image_file
|
|
6
|
-
from wagtail.models import Collection
|
|
7
|
-
|
|
8
|
-
from .utils import Image
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class TestFilesDeletedForDefaultModels(TransactionTestCase):
|
|
12
|
-
"""
|
|
13
|
-
Because we expect file deletion to only happen once a transaction is
|
|
14
|
-
successfully committed, we must run these tests using TransactionTestCase
|
|
15
|
-
per the following documentation:
|
|
16
|
-
|
|
17
|
-
Django's TestCase class wraps each test in a transaction and rolls back that
|
|
18
|
-
transaction after each test, in order to provide test isolation. This means
|
|
19
|
-
that no transaction is ever actually committed, thus your on_commit()
|
|
20
|
-
callbacks will never be run. If you need to test the results of an
|
|
21
|
-
on_commit() callback, use a TransactionTestCase instead.
|
|
22
|
-
https://docs.djangoproject.com/en/1.10/topics/db/transactions/#use-in-tests
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def setUp(self):
|
|
26
|
-
# Required to create root collection because the TransactionTestCase
|
|
27
|
-
# does not make initial data loaded in migrations available and
|
|
28
|
-
# serialized_rollback=True causes other problems in the test suite.
|
|
29
|
-
# ref: https://docs.djangoproject.com/en/1.10/topics/testing/overview/#rollback-emulation
|
|
30
|
-
Collection.objects.get_or_create(
|
|
31
|
-
name="Root",
|
|
32
|
-
path="0001",
|
|
33
|
-
depth=1,
|
|
34
|
-
numchild=0,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
def test_image_file_deleted_oncommit(self):
|
|
38
|
-
with transaction.atomic():
|
|
39
|
-
image = get_image_model().objects.create(
|
|
40
|
-
title="Test Image",
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
image.
|
|
45
|
-
self.assertTrue(image.file.storage.exists(filename))
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
1
|
+
from django.db import transaction
|
|
2
|
+
from django.test import TestCase, TransactionTestCase, override_settings
|
|
3
|
+
|
|
4
|
+
from wagtail.images import get_image_model, signal_handlers
|
|
5
|
+
from wagtail.images.tests.utils import get_test_image_file
|
|
6
|
+
from wagtail.models import Collection
|
|
7
|
+
|
|
8
|
+
from .utils import Image
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestFilesDeletedForDefaultModels(TransactionTestCase):
|
|
12
|
+
"""
|
|
13
|
+
Because we expect file deletion to only happen once a transaction is
|
|
14
|
+
successfully committed, we must run these tests using TransactionTestCase
|
|
15
|
+
per the following documentation:
|
|
16
|
+
|
|
17
|
+
Django's TestCase class wraps each test in a transaction and rolls back that
|
|
18
|
+
transaction after each test, in order to provide test isolation. This means
|
|
19
|
+
that no transaction is ever actually committed, thus your on_commit()
|
|
20
|
+
callbacks will never be run. If you need to test the results of an
|
|
21
|
+
on_commit() callback, use a TransactionTestCase instead.
|
|
22
|
+
https://docs.djangoproject.com/en/1.10/topics/db/transactions/#use-in-tests
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def setUp(self):
|
|
26
|
+
# Required to create root collection because the TransactionTestCase
|
|
27
|
+
# does not make initial data loaded in migrations available and
|
|
28
|
+
# serialized_rollback=True causes other problems in the test suite.
|
|
29
|
+
# ref: https://docs.djangoproject.com/en/1.10/topics/testing/overview/#rollback-emulation
|
|
30
|
+
Collection.objects.get_or_create(
|
|
31
|
+
name="Root",
|
|
32
|
+
path="0001",
|
|
33
|
+
depth=1,
|
|
34
|
+
numchild=0,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def test_image_file_deleted_oncommit(self):
|
|
38
|
+
with transaction.atomic():
|
|
39
|
+
image = get_image_model().objects.create(
|
|
40
|
+
title="Test Image",
|
|
41
|
+
description="A test description",
|
|
42
|
+
file=get_test_image_file(),
|
|
43
|
+
)
|
|
44
|
+
filename = image.file.name
|
|
45
|
+
self.assertTrue(image.file.storage.exists(filename))
|
|
46
|
+
image.delete()
|
|
47
|
+
self.assertTrue(image.file.storage.exists(filename))
|
|
48
|
+
self.assertFalse(image.file.storage.exists(filename))
|
|
49
|
+
|
|
50
|
+
def test_rendition_file_deleted_oncommit(self):
|
|
51
|
+
with transaction.atomic():
|
|
52
|
+
image = get_image_model().objects.create(
|
|
53
|
+
title="Test Image",
|
|
54
|
+
description="A test description",
|
|
55
|
+
file=get_test_image_file(),
|
|
56
|
+
)
|
|
57
|
+
rendition = image.get_rendition("original")
|
|
58
|
+
filename = rendition.file.name
|
|
59
|
+
self.assertTrue(rendition.file.storage.exists(filename))
|
|
60
|
+
rendition.delete()
|
|
61
|
+
self.assertTrue(rendition.file.storage.exists(filename))
|
|
62
|
+
self.assertFalse(rendition.file.storage.exists(filename))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@override_settings(WAGTAILIMAGES_IMAGE_MODEL="tests.CustomImage")
|
|
66
|
+
class TestFilesDeletedForCustomModels(TestFilesDeletedForDefaultModels):
|
|
67
|
+
def setUp(self):
|
|
68
|
+
# Required to create root collection because the TransactionTestCase
|
|
69
|
+
# does not make initial data loaded in migrations available and
|
|
70
|
+
# serialized_rollback=True causes other problems in the test suite.
|
|
71
|
+
# ref: https://docs.djangoproject.com/en/1.10/topics/testing/overview/#rollback-emulation
|
|
72
|
+
Collection.objects.get_or_create(
|
|
73
|
+
name="Root",
|
|
74
|
+
path="0001",
|
|
75
|
+
depth=1,
|
|
76
|
+
numchild=0,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
#: Sadly signal receivers only get connected when starting django.
|
|
80
|
+
#: We will re-attach them here to mimic the django startup behaviour
|
|
81
|
+
#: and get the signals connected to our custom model..
|
|
82
|
+
signal_handlers.register_signal_handlers()
|
|
83
|
+
|
|
84
|
+
def test_image_model(self):
|
|
85
|
+
cls = get_image_model()
|
|
86
|
+
self.assertEqual(f"{cls._meta.app_label}.{cls.__name__}", "tests.CustomImage")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@override_settings(WAGTAILIMAGES_FEATURE_DETECTION_ENABLED=True)
|
|
90
|
+
class TestRawForPreSaveImageFeatureDetection(TestCase):
|
|
91
|
+
fixtures = ["test.json"]
|
|
92
|
+
|
|
93
|
+
# just to test the file is from a fixture doesn't actually exists.
|
|
94
|
+
# raw check in pre_save_image_feature_detection skips on the provided condition of this test
|
|
95
|
+
# hence avoiding an error
|
|
96
|
+
|
|
97
|
+
def test_image_does_not_exist(self):
|
|
98
|
+
bad_image = Image.objects.get(pk=1)
|
|
99
|
+
self.assertFalse(bad_image.file.storage.exists(bad_image.file.name))
|
|
@@ -126,9 +126,9 @@ class TestImagesSummary(WagtailTestUtils, TestCase):
|
|
|
126
126
|
|
|
127
127
|
def test_user_sees_proper_image_count(self):
|
|
128
128
|
cases = (
|
|
129
|
-
(self.superuser, "
|
|
130
|
-
(self.bird_adder, "
|
|
131
|
-
(self.bird_chooser, "
|
|
129
|
+
(self.superuser, "3 Images"),
|
|
130
|
+
(self.bird_adder, "2 Images"),
|
|
131
|
+
(self.bird_chooser, "2 Images"),
|
|
132
132
|
)
|
|
133
133
|
for user, content in cases:
|
|
134
134
|
with self.subTest(user=user):
|