wagtail 6.2.2__py3-none-any.whl → 6.3rc2__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.
Files changed (386) hide show
  1. wagtail/__init__.py +1 -1
  2. wagtail/actions/copy_for_translation.py +6 -0
  3. wagtail/actions/publish_revision.py +3 -3
  4. wagtail/admin/action_menu.py +5 -3
  5. wagtail/admin/forms/account.py +1 -1
  6. wagtail/admin/icons.py +2 -6
  7. wagtail/admin/locale/cy/LC_MESSAGES/django.mo +0 -0
  8. wagtail/admin/locale/cy/LC_MESSAGES/django.po +32 -0
  9. wagtail/admin/locale/dv/LC_MESSAGES/django.mo +0 -0
  10. wagtail/admin/locale/dv/LC_MESSAGES/django.po +28 -0
  11. wagtail/admin/locale/en/LC_MESSAGES/django.po +451 -485
  12. wagtail/admin/locale/en/LC_MESSAGES/djangojs.po +7 -7
  13. wagtail/admin/locale/sl/LC_MESSAGES/django.mo +0 -0
  14. wagtail/admin/locale/sl/LC_MESSAGES/django.po +150 -0
  15. wagtail/admin/locale/sl/LC_MESSAGES/djangojs.mo +0 -0
  16. wagtail/admin/locale/sl/LC_MESSAGES/djangojs.po +9 -2
  17. wagtail/admin/locale/ug/LC_MESSAGES/django.mo +0 -0
  18. wagtail/admin/locale/ug/LC_MESSAGES/django.po +3250 -196
  19. wagtail/admin/localization.py +12 -2
  20. wagtail/admin/panels/model_utils.py +1 -1
  21. wagtail/admin/site_summary.py +0 -2
  22. wagtail/admin/static/wagtailadmin/css/core.css +1 -1
  23. wagtail/admin/static/wagtailadmin/css/panels/draftail.css +1 -1
  24. wagtail/admin/static/wagtailadmin/images/email-header.jpg +0 -0
  25. wagtail/admin/static/wagtailadmin/js/bulk-actions.js +1 -1
  26. wagtail/admin/static/wagtailadmin/js/core.js +1 -1
  27. wagtail/admin/static/wagtailadmin/js/core.js.LICENSE.txt +12 -0
  28. wagtail/admin/static/wagtailadmin/js/draftail.js +1 -1
  29. wagtail/admin/static/wagtailadmin/js/sidebar.js +1 -1
  30. wagtail/admin/static/wagtailadmin/js/telepath/telepath.js +1 -1
  31. wagtail/admin/static/wagtailadmin/js/telepath/widgets.js +1 -1
  32. wagtail/admin/static/wagtailadmin/js/userbar.js +1 -1
  33. wagtail/admin/static/wagtailadmin/js/userbar.js.LICENSE.txt +1 -1
  34. wagtail/admin/static/wagtailadmin/js/vendor.js +1 -1
  35. wagtail/admin/static/wagtailadmin/js/wagtailadmin.js +1 -1
  36. wagtail/admin/static/wagtailadmin/js/workflow-action.js +1 -1
  37. wagtail/admin/staticfiles.py +6 -4
  38. wagtail/admin/templates/wagtailadmin/account/account.html +42 -59
  39. wagtail/admin/templates/wagtailadmin/admin_base.html +0 -28
  40. wagtail/admin/templates/wagtailadmin/bulk_actions/footer.html +1 -1
  41. wagtail/admin/templates/wagtailadmin/chooser/_search_results.html +7 -5
  42. wagtail/admin/templates/wagtailadmin/chooser/tables/page_navigate_to_children_cell.html +1 -1
  43. wagtail/admin/templates/wagtailadmin/generic/chooser/results.html +7 -5
  44. wagtail/admin/templates/wagtailadmin/generic/edit.html +0 -8
  45. wagtail/admin/templates/wagtailadmin/generic/form.html +60 -17
  46. wagtail/admin/templates/wagtailadmin/generic/index.html +17 -0
  47. wagtail/admin/templates/wagtailadmin/generic/index_results.html +9 -35
  48. wagtail/admin/templates/wagtailadmin/generic/inspect.html +2 -21
  49. wagtail/admin/templates/wagtailadmin/generic/listing.html +11 -17
  50. wagtail/admin/templates/wagtailadmin/generic/listing_results.html +19 -1
  51. wagtail/admin/templates/wagtailadmin/home/account_summary.html +26 -0
  52. wagtail/admin/templates/wagtailadmin/home/locked_pages.html +28 -18
  53. wagtail/admin/templates/wagtailadmin/home/recent_edits.html +28 -17
  54. wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html +2 -2
  55. wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html +35 -13
  56. wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html +28 -18
  57. wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +43 -32
  58. wagtail/admin/templates/wagtailadmin/home.html +22 -5
  59. wagtail/admin/templates/wagtailadmin/pages/_editor_js.html +0 -1
  60. wagtail/admin/templates/wagtailadmin/pages/action_menu/menu.html +1 -11
  61. wagtail/admin/templates/wagtailadmin/pages/action_menu/menu_item.html +1 -6
  62. wagtail/admin/templates/wagtailadmin/pages/action_menu/page_locked.html +1 -1
  63. wagtail/admin/templates/wagtailadmin/pages/action_menu/publish.html +1 -1
  64. wagtail/admin/templates/wagtailadmin/pages/action_menu/save_draft.html +1 -1
  65. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_delete.html +12 -6
  66. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_move.html +12 -7
  67. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_publish.html +17 -11
  68. wagtail/admin/templates/wagtailadmin/pages/bulk_actions/confirm_bulk_unpublish.html +15 -9
  69. wagtail/admin/templates/wagtailadmin/pages/confirm_delete.html +9 -9
  70. wagtail/admin/templates/wagtailadmin/pages/confirm_move.html +2 -2
  71. wagtail/admin/templates/wagtailadmin/pages/confirm_unpublish.html +4 -4
  72. wagtail/admin/templates/wagtailadmin/pages/create.html +15 -34
  73. wagtail/admin/templates/wagtailadmin/pages/edit.html +15 -30
  74. wagtail/admin/templates/wagtailadmin/pages/explorable_index.html +6 -0
  75. wagtail/admin/templates/wagtailadmin/pages/explorable_index_results.html +60 -0
  76. wagtail/admin/templates/wagtailadmin/pages/index.html +1 -36
  77. wagtail/admin/templates/wagtailadmin/pages/index_results.html +2 -50
  78. wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +1 -1
  79. wagtail/admin/templates/wagtailadmin/pages/listing/_ordering_cell.html +1 -1
  80. wagtail/admin/templates/wagtailadmin/pages/listing/_page_header_buttons.html +1 -1
  81. wagtail/admin/templates/wagtailadmin/pages/listing/_page_title_column_header.html +3 -3
  82. wagtail/admin/templates/wagtailadmin/pages/listing/_pagination.html +1 -1
  83. wagtail/admin/templates/wagtailadmin/pages/listing.html +24 -0
  84. wagtail/admin/templates/wagtailadmin/pages/search.html +1 -20
  85. wagtail/admin/templates/wagtailadmin/pages/search_results.html +27 -25
  86. wagtail/admin/templates/wagtailadmin/permissions/includes/collection_member_permissions_formset.html +0 -1
  87. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_report.html +2 -2
  88. wagtail/admin/templates/wagtailadmin/reports/listing/_list_page_types_usage.html +6 -6
  89. wagtail/admin/templates/wagtailadmin/reports/workflow_tasks_results.html +1 -1
  90. wagtail/admin/templates/wagtailadmin/shared/action_menu/menu.html +14 -0
  91. wagtail/admin/templates/wagtailadmin/shared/action_menu/menu_item.html +6 -0
  92. wagtail/admin/templates/wagtailadmin/shared/avatar.html +13 -3
  93. wagtail/admin/templates/wagtailadmin/shared/header.html +0 -5
  94. wagtail/admin/templates/wagtailadmin/shared/headers/slim_header.html +1 -1
  95. wagtail/admin/templates/wagtailadmin/shared/page_status_tag_new.html +4 -1
  96. wagtail/admin/templates/wagtailadmin/shared/pagination_nav.html +1 -1
  97. wagtail/admin/templates/wagtailadmin/shared/side_panel_toggle.html +1 -1
  98. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/locale.html +1 -1
  99. wagtail/admin/templates/wagtailadmin/shared/side_panels/includes/status/usage.html +2 -2
  100. wagtail/admin/templates/wagtailadmin/shared/side_panels/preview.html +94 -52
  101. wagtail/admin/templates/wagtailadmin/{pages/_unsaved_changes_warning.html → shared/unsaved_changes_warning.html} +4 -4
  102. wagtail/admin/templates/wagtailadmin/shared/usage_summary.html +2 -2
  103. wagtail/admin/templates/wagtailadmin/shared/workflow_history/detail.html +1 -7
  104. wagtail/admin/templates/wagtailadmin/shared/workflow_history/listing.html +1 -0
  105. wagtail/admin/templates/wagtailadmin/shared/workflow_history/{list.html → listing_results.html} +33 -35
  106. wagtail/admin/templates/wagtailadmin/tables/references_cell.html +1 -1
  107. wagtail/admin/templates/wagtailadmin/workflows/create.html +11 -36
  108. wagtail/admin/templates/wagtailadmin/workflows/create_task.html +0 -38
  109. wagtail/admin/templates/wagtailadmin/workflows/edit.html +44 -74
  110. wagtail/admin/templates/wagtailadmin/workflows/edit_task.html +27 -66
  111. wagtail/admin/templates/wagtailadmin/workflows/includes/task_usage_cell.html +4 -2
  112. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_tasks_cell.html +4 -4
  113. wagtail/admin/templates/wagtailadmin/workflows/includes/workflow_used_by_cell.html +15 -11
  114. wagtail/admin/templates/wagtailadmin/workflows/task_chooser/includes/results.html +7 -5
  115. wagtail/admin/templatetags/wagtailadmin_tags.py +51 -22
  116. wagtail/admin/tests/pages/test_content_type_use_view.py +82 -2
  117. wagtail/admin/tests/pages/test_edit_page.py +70 -0
  118. wagtail/admin/tests/pages/test_explorer_view.py +65 -4
  119. wagtail/admin/tests/pages/test_page_search.py +8 -7
  120. wagtail/admin/tests/pages/test_page_usage.py +3 -1
  121. wagtail/admin/tests/pages/test_preview.py +208 -63
  122. wagtail/admin/tests/pages/test_reorder_page.py +91 -1
  123. wagtail/admin/tests/pages/test_view_draft.py +32 -1
  124. wagtail/admin/tests/pages/test_workflow_history.py +288 -7
  125. wagtail/admin/tests/test_account_management.py +23 -3
  126. wagtail/admin/tests/test_audit_log.py +24 -2
  127. wagtail/admin/tests/test_collections_views.py +17 -5
  128. wagtail/admin/tests/test_dashboard.py +1 -1
  129. wagtail/admin/tests/test_edit_handlers.py +3 -2
  130. wagtail/admin/tests/test_icon_sprite.py +4 -0
  131. wagtail/admin/tests/test_privacy.py +5 -19
  132. wagtail/admin/tests/test_reports_views.py +1 -1
  133. wagtail/admin/tests/test_site_summary.py +3 -3
  134. wagtail/admin/tests/test_templatetags.py +27 -3
  135. wagtail/admin/tests/test_upgrade_notification.py +71 -18
  136. wagtail/admin/tests/test_views.py +2 -2
  137. wagtail/admin/tests/test_views_generic.py +13 -0
  138. wagtail/admin/tests/test_widgets.py +3 -3
  139. wagtail/admin/tests/test_workflows.py +172 -27
  140. wagtail/admin/tests/tests.py +1 -1
  141. wagtail/admin/tests/viewsets/test_model_viewset.py +55 -3
  142. wagtail/admin/ui/side_panels.py +19 -0
  143. wagtail/admin/ui/sidebar.py +4 -3
  144. wagtail/admin/ui/tables/__init__.py +14 -1
  145. wagtail/admin/ui/tables/pages.py +6 -1
  146. wagtail/admin/urls/pages.py +10 -1
  147. wagtail/admin/urls/workflows.py +6 -1
  148. wagtail/admin/views/account.py +5 -1
  149. wagtail/admin/views/collections.py +0 -2
  150. wagtail/admin/views/generic/base.py +118 -1
  151. wagtail/admin/views/generic/history.py +158 -26
  152. wagtail/admin/views/generic/models.py +113 -99
  153. wagtail/admin/views/home.py +24 -9
  154. wagtail/admin/views/page_privacy.py +54 -30
  155. wagtail/admin/views/pages/history.py +11 -4
  156. wagtail/admin/views/pages/listing.py +76 -89
  157. wagtail/admin/views/pages/preview.py +1 -1
  158. wagtail/admin/views/pages/search.py +27 -71
  159. wagtail/admin/views/pages/usage.py +63 -24
  160. wagtail/admin/views/pages/utils.py +4 -3
  161. wagtail/admin/views/reports/base.py +0 -6
  162. wagtail/admin/views/workflows.py +67 -25
  163. wagtail/admin/viewsets/model.py +4 -3
  164. wagtail/admin/widgets/chooser.py +2 -1
  165. wagtail/api/v2/tests/test_pages.py +15 -2
  166. wagtail/blocks/field_block.py +15 -3
  167. wagtail/blocks/static_block.py +3 -0
  168. wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.mo +0 -0
  169. wagtail/contrib/forms/locale/cy/LC_MESSAGES/django.po +29 -1
  170. wagtail/contrib/forms/locale/en/LC_MESSAGES/django.po +15 -11
  171. wagtail/contrib/forms/templates/wagtailforms/confirm_delete.html +1 -0
  172. wagtail/contrib/forms/templates/wagtailforms/index.html +1 -1
  173. wagtail/contrib/forms/templates/wagtailforms/index_results.html +1 -1
  174. wagtail/contrib/forms/templates/wagtailforms/list_submissions.html +2 -1
  175. wagtail/contrib/forms/templates/wagtailforms/panels/form_responses_panel.html +2 -2
  176. wagtail/contrib/forms/tests/test_views.py +234 -35
  177. wagtail/contrib/forms/utils.py +8 -14
  178. wagtail/contrib/forms/views.py +72 -27
  179. wagtail/contrib/frontend_cache/backends/azure.py +1 -1
  180. wagtail/contrib/frontend_cache/backends/cloudfront.py +2 -2
  181. wagtail/contrib/frontend_cache/backends/dummy.py +11 -0
  182. wagtail/contrib/frontend_cache/tests.py +31 -37
  183. wagtail/contrib/frontend_cache/utils.py +12 -5
  184. wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.mo +0 -0
  185. wagtail/contrib/redirects/locale/cy/LC_MESSAGES/django.po +16 -1
  186. wagtail/contrib/redirects/locale/en/LC_MESSAGES/django.po +20 -24
  187. wagtail/contrib/redirects/models.py +16 -1
  188. wagtail/contrib/redirects/signal_handlers.py +18 -3
  189. wagtail/contrib/redirects/templates/wagtailredirects/add.html +5 -16
  190. wagtail/contrib/redirects/templates/wagtailredirects/import_summary.html +1 -1
  191. wagtail/contrib/redirects/tests/test_redirects.py +49 -6
  192. wagtail/contrib/redirects/tests/test_signal_handlers.py +42 -1
  193. wagtail/contrib/redirects/views.py +27 -3
  194. wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.mo +0 -0
  195. wagtail/contrib/search_promotions/locale/cy/LC_MESSAGES/django.po +60 -1
  196. wagtail/contrib/search_promotions/locale/en/LC_MESSAGES/django.po +12 -18
  197. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/add.html +5 -8
  198. wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/edit.html +15 -10
  199. wagtail/contrib/search_promotions/tests.py +13 -2
  200. wagtail/contrib/search_promotions/views.py +15 -3
  201. wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.mo +0 -0
  202. wagtail/contrib/settings/locale/cy/LC_MESSAGES/django.po +6 -1
  203. wagtail/contrib/settings/locale/en/LC_MESSAGES/django.po +2 -10
  204. wagtail/contrib/settings/templates/wagtailsettings/edit.html +12 -45
  205. wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.mo +0 -0
  206. wagtail/contrib/simple_translation/locale/cy/LC_MESSAGES/django.po +13 -1
  207. wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.mo +0 -0
  208. wagtail/contrib/simple_translation/locale/dv/LC_MESSAGES/django.po +3 -0
  209. wagtail/contrib/simple_translation/locale/en/LC_MESSAGES/django.po +4 -4
  210. wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.mo +0 -0
  211. wagtail/contrib/simple_translation/locale/sl/LC_MESSAGES/django.po +5 -2
  212. wagtail/contrib/simple_translation/tests/test_views.py +51 -0
  213. wagtail/contrib/simple_translation/wagtail_hooks.py +16 -11
  214. wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.mo +0 -0
  215. wagtail/contrib/styleguide/locale/cy/LC_MESSAGES/django.po +5 -1
  216. wagtail/contrib/styleguide/locale/en/LC_MESSAGES/django.po +1 -1
  217. wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
  218. wagtail/contrib/table_block/locale/cy/LC_MESSAGES/django.po +27 -1
  219. wagtail/contrib/table_block/locale/en/LC_MESSAGES/django.po +1 -1
  220. wagtail/contrib/typed_table_block/blocks.py +25 -0
  221. wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.mo +0 -0
  222. wagtail/contrib/typed_table_block/locale/cy/LC_MESSAGES/django.po +12 -1
  223. wagtail/contrib/typed_table_block/locale/en/LC_MESSAGES/django.po +10 -10
  224. wagtail/contrib/typed_table_block/tests.py +24 -1
  225. wagtail/coreutils.py +5 -11
  226. wagtail/documents/admin_urls.py +2 -2
  227. wagtail/documents/locale/cy/LC_MESSAGES/django.mo +0 -0
  228. wagtail/documents/locale/cy/LC_MESSAGES/django.po +10 -0
  229. wagtail/documents/locale/en/LC_MESSAGES/django.po +61 -76
  230. wagtail/documents/migrations/0014_alter_document_file_size.py +18 -0
  231. wagtail/documents/models.py +1 -1
  232. wagtail/documents/rich_text/__init__.py +1 -3
  233. wagtail/documents/static/wagtaildocs/js/add-multiple.js +1 -1
  234. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_tags.html +5 -1
  235. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
  236. wagtail/documents/templates/wagtaildocs/bulk_actions/confirm_bulk_delete.html +11 -5
  237. wagtail/documents/templates/wagtaildocs/documents/add.html +13 -41
  238. wagtail/documents/templates/wagtaildocs/documents/edit.html +28 -56
  239. wagtail/documents/templates/wagtaildocs/documents/index.html +1 -4
  240. wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html +2 -2
  241. wagtail/documents/templates/wagtaildocs/multiple/add.html +36 -41
  242. wagtail/documents/tests/test_admin_views.py +64 -6
  243. wagtail/documents/tests/test_site_summary.py +3 -3
  244. wagtail/documents/views/documents.py +103 -113
  245. wagtail/documents/views/multiple.py +19 -1
  246. wagtail/embeds/locale/en/LC_MESSAGES/django.po +1 -1
  247. wagtail/embeds/oembed_providers.py +9 -19
  248. wagtail/fields.py +43 -27
  249. wagtail/images/admin_urls.py +2 -2
  250. wagtail/images/blocks.py +230 -2
  251. wagtail/images/fields.py +17 -29
  252. wagtail/images/image_operations.py +1 -1
  253. wagtail/images/locale/cy/LC_MESSAGES/django.mo +0 -0
  254. wagtail/images/locale/cy/LC_MESSAGES/django.po +128 -1
  255. wagtail/images/locale/en/LC_MESSAGES/django.po +119 -129
  256. wagtail/images/migrations/0025_alter_image_file_alter_rendition_file.py +36 -43
  257. wagtail/images/migrations/0027_image_description.py +20 -0
  258. wagtail/images/models.py +120 -45
  259. wagtail/images/rich_text/__init__.py +1 -3
  260. wagtail/images/static/wagtailimages/js/add-multiple.js +1 -1
  261. wagtail/images/static/wagtailimages/js/image-block.js +1 -0
  262. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_tags.html +5 -1
  263. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_add_to_collection.html +5 -1
  264. wagtail/images/templates/wagtailimages/bulk_actions/confirm_bulk_delete.html +11 -5
  265. wagtail/images/templates/wagtailimages/chooser/results.html +2 -2
  266. wagtail/images/templates/wagtailimages/homepage/site_summary_images.html +2 -2
  267. wagtail/images/templates/wagtailimages/images/_file_field.html +2 -2
  268. wagtail/images/templates/wagtailimages/images/add.html +13 -31
  269. wagtail/images/templates/wagtailimages/images/edit.html +53 -82
  270. wagtail/images/templates/wagtailimages/images/index.html +1 -4
  271. wagtail/images/templates/wagtailimages/images/url_generator.html +1 -1
  272. wagtail/images/templates/wagtailimages/multiple/add.html +40 -47
  273. wagtail/images/templates/wagtailimages/widgets/image.html +5 -0
  274. wagtail/images/templates/wagtailimages/widgets/image_chooser.html +1 -1
  275. wagtail/images/tests/test_admin_views.py +70 -10
  276. wagtail/images/tests/test_blocks.py +367 -1
  277. wagtail/images/tests/test_image_operations.py +23 -0
  278. wagtail/images/tests/test_models.py +20 -0
  279. wagtail/images/tests/test_signal_handlers.py +99 -95
  280. wagtail/images/tests/test_site_summary.py +3 -3
  281. wagtail/images/tests/test_templatetags.py +11 -7
  282. wagtail/images/tests/tests.py +4 -0
  283. wagtail/images/views/images.py +103 -104
  284. wagtail/images/views/multiple.py +17 -1
  285. wagtail/locale/cy/LC_MESSAGES/django.mo +0 -0
  286. wagtail/locale/cy/LC_MESSAGES/django.po +3 -0
  287. wagtail/locale/en/LC_MESSAGES/django.po +137 -125
  288. wagtail/locale/sl/LC_MESSAGES/django.mo +0 -0
  289. wagtail/locale/sl/LC_MESSAGES/django.po +3 -0
  290. wagtail/locales/locale/en/LC_MESSAGES/django.po +8 -8
  291. wagtail/locales/views.py +4 -1
  292. wagtail/migrations/0089_log_entry_data_json_null_to_object.py +1 -7
  293. wagtail/models/__init__.py +122 -14
  294. wagtail/models/audit_log.py +1 -3
  295. wagtail/models/i18n.py +1 -2
  296. wagtail/project_template/Dockerfile +3 -3
  297. wagtail/project_template/requirements.txt +2 -2
  298. wagtail/query.py +17 -4
  299. wagtail/rich_text/__init__.py +2 -3
  300. wagtail/rich_text/pages.py +2 -4
  301. wagtail/rich_text/rewriters.py +2 -2
  302. wagtail/search/backends/database/mysql/query.py +3 -3
  303. wagtail/search/backends/database/sqlite/query.py +6 -6
  304. wagtail/search/locale/en/LC_MESSAGES/django.po +1 -1
  305. wagtail/sites/locale/en/LC_MESSAGES/django.po +6 -6
  306. wagtail/sites/views.py +0 -1
  307. wagtail/snippets/action_menu.py +14 -4
  308. wagtail/snippets/locale/cy/LC_MESSAGES/django.mo +0 -0
  309. wagtail/snippets/locale/cy/LC_MESSAGES/django.po +73 -1
  310. wagtail/snippets/locale/en/LC_MESSAGES/django.po +27 -33
  311. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser-telepath.js +1 -1
  312. wagtail/snippets/static/wagtailsnippets/js/snippet-chooser.js +1 -1
  313. wagtail/snippets/templates/wagtailsnippets/bulk_actions/confirm_bulk_delete.html +5 -3
  314. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/locked.html +1 -1
  315. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu.html +1 -11
  316. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/menu_item.html +1 -6
  317. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/publish.html +1 -1
  318. wagtail/snippets/templates/wagtailsnippets/snippets/action_menu/save.html +1 -1
  319. wagtail/snippets/templates/wagtailsnippets/snippets/create.html +1 -18
  320. wagtail/snippets/templates/wagtailsnippets/snippets/edit.html +1 -14
  321. wagtail/snippets/templates/wagtailsnippets/snippets/index.html +2 -5
  322. wagtail/snippets/tests/test_preview.py +193 -61
  323. wagtail/snippets/tests/test_snippets.py +247 -38
  324. wagtail/snippets/tests/test_usage.py +5 -0
  325. wagtail/snippets/tests/test_viewset.py +25 -9
  326. wagtail/snippets/tests/test_workflows.py +232 -19
  327. wagtail/snippets/views/snippets.py +1 -10
  328. wagtail/test/numberformat.py +104 -0
  329. wagtail/test/settings.py +10 -0
  330. wagtail/test/settings_ui.py +2 -0
  331. wagtail/test/testapp/migrations/0010_alter_customimage_file_and_more.py +71 -78
  332. wagtail/test/testapp/migrations/0040_nocreatablesubpagetypespage_nosubpagetypespage.py +54 -0
  333. wagtail/test/testapp/migrations/0041_alter_jsonstreammodel_options.py +17 -0
  334. wagtail/test/testapp/migrations/0042_alter_customdocument_file_size_and_more.py +28 -0
  335. wagtail/test/testapp/migrations/0043_customimage_description.py +41 -0
  336. wagtail/test/testapp/migrations/0044_custompreviewsizesmodel_custompreviewsizespage.py +52 -0
  337. wagtail/test/testapp/migrations/0045_alter_streampage_body.py +52 -0
  338. wagtail/test/testapp/models.py +62 -4
  339. wagtail/test/testapp/rich_text.py +2 -2
  340. wagtail/test/testapp/templates/tests/form_page_landing.html +2 -1
  341. wagtail/test/testapp/urls.py +5 -0
  342. wagtail/test/testapp/views.py +5 -0
  343. wagtail/test/utils/page_tests.py +5 -5
  344. wagtail/test/utils/template_tests.py +2 -2
  345. wagtail/tests/test_blocks.py +15 -0
  346. wagtail/tests/test_page_permissions.py +109 -0
  347. wagtail/tests/test_revision_model.py +27 -0
  348. wagtail/tests/test_signals.py +21 -2
  349. wagtail/tests/test_tests.py +30 -0
  350. wagtail/users/locale/cy/LC_MESSAGES/django.mo +0 -0
  351. wagtail/users/locale/cy/LC_MESSAGES/django.po +118 -1
  352. wagtail/users/locale/dv/LC_MESSAGES/django.mo +0 -0
  353. wagtail/users/locale/dv/LC_MESSAGES/django.po +3 -0
  354. wagtail/users/locale/en/LC_MESSAGES/django.po +89 -113
  355. wagtail/users/locale/sl/LC_MESSAGES/django.mo +0 -0
  356. wagtail/users/locale/sl/LC_MESSAGES/django.po +3 -0
  357. wagtail/users/migrations/0014_userprofile_contrast.py +23 -0
  358. wagtail/users/models.py +11 -0
  359. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_assign_role.html +5 -1
  360. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_delete.html +5 -1
  361. wagtail/users/templates/wagtailusers/bulk_actions/confirm_bulk_set_active_state.html +5 -1
  362. wagtail/users/templates/wagtailusers/groups/create.html +19 -17
  363. wagtail/users/templates/wagtailusers/groups/edit.html +2 -40
  364. wagtail/users/templates/wagtailusers/groups/includes/formatted_permissions.html +1 -62
  365. wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.html +0 -1
  366. wagtail/users/templates/wagtailusers/users/create.html +46 -50
  367. wagtail/users/templates/wagtailusers/users/edit.html +45 -62
  368. wagtail/users/templates/wagtailusers/users/index.html +1 -4
  369. wagtail/users/templatetags/wagtailusers_tags.py +1 -5
  370. wagtail/users/tests/test_admin_views.py +85 -66
  371. wagtail/users/views/groups.py +4 -1
  372. wagtail/users/views/users.py +2 -0
  373. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/METADATA +6 -6
  374. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/RECORD +378 -367
  375. wagtail/admin/static/wagtailadmin/js/preview-panel.js +0 -2
  376. wagtail/admin/static/wagtailadmin/js/preview-panel.js.LICENSE.txt +0 -11
  377. wagtail/admin/templates/wagtailadmin/generic/history_results.html +0 -1
  378. wagtail/admin/templates/wagtailadmin/page_privacy/ancestor_privacy.html +0 -3
  379. wagtail/admin/templates/wagtailadmin/pages/usage_results.html +0 -6
  380. wagtail/admin/templates/wagtailadmin/shared/workflow_history/index.html +0 -17
  381. wagtail/admin/templates/wagtailadmin/shared/workflow_history/results.html +0 -17
  382. wagtail/admin/templates/wagtailadmin/workflows/usage.html +0 -44
  383. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/LICENSE +0 -0
  384. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/WHEEL +0 -0
  385. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/entry_points.txt +0 -0
  386. {wagtail-6.2.2.dist-info → wagtail-6.3rc2.dist-info}/top_level.txt +0 -0
@@ -1,13 +1,22 @@
1
+ import datetime
2
+
3
+ from django.conf import settings
1
4
  from django.contrib.auth.models import Permission
2
5
  from django.test import TestCase
3
6
  from django.urls import reverse
7
+ from django.utils import timezone
8
+ from django.utils.formats import localize
9
+ from freezegun import freeze_time
4
10
 
11
+ from wagtail.admin.utils import get_user_display_name
5
12
  from wagtail.models import Page
6
13
  from wagtail.test.utils import WagtailTestUtils
14
+ from wagtail.test.utils.template_tests import AdminTemplateTestUtils
7
15
 
8
16
 
9
- class TestWorkflowHistoryDetail(WagtailTestUtils, TestCase):
17
+ class TestWorkflowHistoryDetail(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
10
18
  fixtures = ["test.json"]
19
+ base_breadcrumb_items = []
11
20
 
12
21
  def setUp(self):
13
22
  self.user = self.create_test_user()
@@ -16,10 +25,42 @@ class TestWorkflowHistoryDetail(WagtailTestUtils, TestCase):
16
25
  self.christmas_event = Page.objects.get(
17
26
  url_path="/home/events/christmas/"
18
27
  ).specific
19
- self.christmas_event.save_revision()
28
+
29
+ self.site_root = Page.objects.specific().get(id=2)
30
+ self.events_page = self.christmas_event.get_parent().specific
20
31
 
21
32
  workflow = self.christmas_event.get_workflow()
22
- self.workflow_state = workflow.start(self.christmas_event, self.user)
33
+
34
+ self.timestamps = [
35
+ datetime.datetime(2020, 1, 1, 10, 0, 0),
36
+ datetime.datetime(2020, 1, 1, 11, 0, 0),
37
+ datetime.datetime(2020, 1, 2, 12, 0, 0),
38
+ datetime.datetime(2020, 1, 3, 13, 0, 0),
39
+ datetime.datetime(2020, 1, 4, 14, 0, 0),
40
+ ]
41
+
42
+ if settings.USE_TZ:
43
+ self.timestamps[:] = [
44
+ timezone.make_aware(timestamp, timezone=datetime.timezone.utc)
45
+ for timestamp in self.timestamps
46
+ ]
47
+ self.localized_timestamps = [
48
+ localize(timezone.localtime(timestamp), "c")
49
+ for timestamp in self.timestamps
50
+ ]
51
+ else:
52
+ self.localized_timestamps = [
53
+ localize(timestamp, "c") for timestamp in self.timestamps
54
+ ]
55
+
56
+ self.moderator = self.create_superuser("moderator")
57
+ self.moderator_name = get_user_display_name(self.moderator)
58
+ self.user_name = get_user_display_name(self.user)
59
+
60
+ with freeze_time(self.timestamps[0]):
61
+ self.christmas_event.save_revision()
62
+ with freeze_time(self.timestamps[1]):
63
+ self.workflow_state = workflow.start(self.christmas_event, self.user)
23
64
 
24
65
  def test_get_index(self):
25
66
  response = self.client.get(
@@ -40,6 +81,36 @@ class TestWorkflowHistoryDetail(WagtailTestUtils, TestCase):
40
81
  ),
41
82
  )
42
83
 
84
+ # Should show the currently in progress workflow
85
+ self.assertContains(response, "Moderators approval")
86
+ self.assertContains(response, "In progress")
87
+ self.assertContains(response, "test@email.com")
88
+
89
+ items = [
90
+ {
91
+ "url": reverse("wagtailadmin_explore_root"),
92
+ "label": "Root",
93
+ },
94
+ {
95
+ "url": reverse("wagtailadmin_explore", args=(self.site_root.id,)),
96
+ "label": self.site_root.get_admin_display_title(),
97
+ },
98
+ {
99
+ "url": reverse("wagtailadmin_explore", args=(self.events_page.id,)),
100
+ "label": self.events_page.get_admin_display_title(),
101
+ },
102
+ {
103
+ "url": reverse("wagtailadmin_explore", args=(self.christmas_event.id,)),
104
+ "label": self.christmas_event.get_admin_display_title(),
105
+ },
106
+ {
107
+ "url": "",
108
+ "label": "Workflow history",
109
+ "sublabel": self.christmas_event.get_admin_display_title(),
110
+ },
111
+ ]
112
+ self.assertBreadcrumbsItemsRendered(items, response.content)
113
+
43
114
  def test_get_index_with_bad_permissions(self):
44
115
  # Remove privileges from user
45
116
  self.user.is_superuser = False
@@ -59,12 +130,28 @@ class TestWorkflowHistoryDetail(WagtailTestUtils, TestCase):
59
130
  self.assertEqual(response.status_code, 302)
60
131
 
61
132
  def test_get_detail(self):
62
- response = self.client.get(
63
- reverse(
64
- "wagtailadmin_pages:workflow_history_detail",
65
- args=[self.christmas_event.id, self.workflow_state.id],
133
+ task_state = self.workflow_state.current_task_state
134
+
135
+ with freeze_time(self.timestamps[2]):
136
+ task_state.task.on_action(
137
+ task_state, user=self.moderator, action_name="reject"
66
138
  )
139
+ self.workflow_state.refresh_from_db()
140
+
141
+ with freeze_time(self.timestamps[3]):
142
+ self.christmas_event.save_revision(user=self.user)
143
+ self.workflow_state.resume(user=self.user)
144
+ self.workflow_state.refresh_from_db()
145
+
146
+ url = reverse(
147
+ "wagtailadmin_pages:workflow_history_detail",
148
+ args=[self.christmas_event.id, self.workflow_state.id],
67
149
  )
150
+ self.client.get(url)
151
+
152
+ with self.assertNumQueries(18):
153
+ response = self.client.get(url)
154
+
68
155
  self.assertEqual(response.status_code, 200)
69
156
 
70
157
  self.assertContains(
@@ -78,9 +165,203 @@ class TestWorkflowHistoryDetail(WagtailTestUtils, TestCase):
78
165
  )
79
166
 
80
167
  self.assertContains(response, '<div class="w-tabs" data-tabs>')
168
+ self.assertContains(response, '<div class="tab-content">')
169
+
170
+ soup = self.get_soup(response.content)
171
+ tasks = soup.select_one("#tab-tasks table")
172
+ self.assertIsNotNone(tasks)
173
+ cells = [
174
+ [td.get_text(separator=" ", strip=True) for td in tr.select("td")]
175
+ for tr in tasks.select("tr")
176
+ ]
81
177
 
178
+ self.assertEqual(
179
+ cells,
180
+ [
181
+ # This is divided into different columns per task, so it makes
182
+ # sense to start with the initial revision on the first cell and
183
+ # then it should be rendered in ascending order.
184
+ [
185
+ "Initial Revision",
186
+ f"Rejected by {self.moderator_name} at {self.localized_timestamps[2]}",
187
+ ],
188
+ [
189
+ f"Edited by {self.user_name} at {self.localized_timestamps[3]}",
190
+ "In progress",
191
+ ],
192
+ ],
193
+ )
194
+
195
+ timeline = soup.select_one("#tab-timeline table")
196
+ self.assertIsNotNone(timeline)
197
+ cells = [
198
+ [td.get_text(separator=" ", strip=True) for td in tr.select("td")]
199
+ for tr in timeline.select("tr")
200
+ ]
201
+ self.assertEqual(
202
+ cells,
203
+ [
204
+ # The items are merged into a single column as a timeline, so it
205
+ # should be rendered in reverse chronological order.
206
+ [
207
+ self.localized_timestamps[3],
208
+ "Edited",
209
+ ],
210
+ [
211
+ self.localized_timestamps[2],
212
+ f"Moderators approval Rejected by {self.moderator_name}",
213
+ ],
214
+ [
215
+ self.localized_timestamps[1],
216
+ "Workflow started",
217
+ ],
218
+ [
219
+ self.localized_timestamps[0],
220
+ "Edited",
221
+ ],
222
+ ],
223
+ )
224
+
225
+ items = [
226
+ {
227
+ "url": reverse("wagtailadmin_explore_root"),
228
+ "label": "Root",
229
+ },
230
+ {
231
+ "url": reverse("wagtailadmin_explore", args=(self.site_root.id,)),
232
+ "label": self.site_root.get_admin_display_title(),
233
+ },
234
+ {
235
+ "url": reverse("wagtailadmin_explore", args=(self.events_page.id,)),
236
+ "label": self.events_page.get_admin_display_title(),
237
+ },
238
+ {
239
+ "url": reverse("wagtailadmin_explore", args=(self.christmas_event.id,)),
240
+ "label": self.christmas_event.get_admin_display_title(),
241
+ },
242
+ {
243
+ "url": reverse(
244
+ "wagtailadmin_pages:workflow_history",
245
+ args=(self.christmas_event.id,),
246
+ ),
247
+ "label": "Workflow history",
248
+ },
249
+ {
250
+ "url": "",
251
+ "label": "Workflow progress",
252
+ "sublabel": self.christmas_event.get_admin_display_title(),
253
+ },
254
+ ]
255
+ self.assertBreadcrumbsItemsRendered(items, response.content)
256
+
257
+ def test_get_detail_completed(self):
258
+ task_state = self.workflow_state.current_task_state
259
+
260
+ with freeze_time(self.timestamps[2]):
261
+ task_state.task.on_action(
262
+ task_state, user=self.moderator, action_name="reject"
263
+ )
264
+ self.workflow_state.refresh_from_db()
265
+
266
+ with freeze_time(self.timestamps[3]):
267
+ self.christmas_event.save_revision(user=self.user)
268
+ self.workflow_state.resume(user=self.user)
269
+ self.workflow_state.refresh_from_db()
270
+
271
+ with freeze_time(self.timestamps[4]):
272
+ task_state = self.workflow_state.current_task_state
273
+ task_state.task.on_action(
274
+ task_state, user=self.moderator, action_name="approve"
275
+ )
276
+ self.workflow_state.refresh_from_db()
277
+
278
+ url = reverse(
279
+ "wagtailadmin_pages:workflow_history_detail",
280
+ args=[self.christmas_event.id, self.workflow_state.id],
281
+ )
282
+ self.client.get(url)
283
+
284
+ with self.assertNumQueries(19):
285
+ response = self.client.get(url)
286
+
287
+ self.assertEqual(response.status_code, 200)
288
+
289
+ self.assertContains(
290
+ response, reverse("wagtailadmin_pages:edit", args=[self.christmas_event.id])
291
+ )
292
+ self.assertContains(
293
+ response,
294
+ reverse(
295
+ "wagtailadmin_pages:workflow_history", args=[self.christmas_event.id]
296
+ ),
297
+ )
298
+
299
+ self.assertContains(response, '<div class="w-tabs" data-tabs>')
82
300
  self.assertContains(response, '<div class="tab-content">')
83
301
 
302
+ soup = self.get_soup(response.content)
303
+ tasks = soup.select_one("#tab-tasks table")
304
+ self.assertIsNotNone(tasks)
305
+ cells = [
306
+ [td.get_text(separator=" ", strip=True) for td in tr.select("td")]
307
+ for tr in tasks.select("tr")
308
+ ]
309
+
310
+ self.assertEqual(
311
+ cells,
312
+ [
313
+ # This is divided into different columns per task, so it makes
314
+ # sense to start with the initial revision on the first cell and
315
+ # then it should be rendered in ascending order.
316
+ [
317
+ "Initial Revision",
318
+ f"Rejected by {self.moderator_name} at {self.localized_timestamps[2]}",
319
+ ],
320
+ [
321
+ f"Edited by {self.user_name} at {self.localized_timestamps[3]}",
322
+ f"Approved by {self.moderator_name} at {self.localized_timestamps[4]}",
323
+ ],
324
+ ],
325
+ )
326
+
327
+ timeline = soup.select_one("#tab-timeline table")
328
+ self.assertIsNotNone(timeline)
329
+ cells = [
330
+ [td.get_text(separator=" ", strip=True) for td in tr.select("td")]
331
+ for tr in timeline.select("tr")
332
+ ]
333
+ self.assertEqual(
334
+ cells,
335
+ [
336
+ # The items are merged into a single column as a timeline, so it
337
+ # should be rendered in reverse chronological order.
338
+ [
339
+ self.localized_timestamps[4],
340
+ "Workflow completed Approved",
341
+ ],
342
+ [
343
+ self.localized_timestamps[4],
344
+ f"Moderators approval Approved by {self.moderator_name}",
345
+ ],
346
+ [
347
+ self.localized_timestamps[3],
348
+ "Edited",
349
+ ],
350
+ [
351
+ self.localized_timestamps[2],
352
+ f"Moderators approval Rejected by {self.moderator_name}",
353
+ ],
354
+ [
355
+ self.localized_timestamps[1],
356
+ "Workflow started",
357
+ ],
358
+ [
359
+ self.localized_timestamps[0],
360
+ "Edited",
361
+ ],
362
+ ],
363
+ )
364
+
84
365
  def test_get_detail_with_bad_permissions(self):
85
366
  # Remove privileges from user
86
367
  self.user.is_superuser = False
@@ -1,6 +1,6 @@
1
1
  import unittest
2
2
 
3
- import pytz
3
+ import zoneinfo
4
4
  from django.conf import settings
5
5
  from django.contrib.auth import get_user_model
6
6
  from django.contrib.auth import views as auth_views
@@ -232,6 +232,7 @@ class TestAccountSectionUtilsMixin:
232
232
  "locale-current_time_zone": "Europe/London",
233
233
  "theme-theme": "dark",
234
234
  "theme-density": "default",
235
+ "theme-contrast": "system",
235
236
  }
236
237
  post_data.update(extra_post_data)
237
238
  return self.client.post(reverse("wagtailadmin_account"), post_data)
@@ -244,6 +245,7 @@ class TestAccountSection(WagtailTestUtils, TestCase, TestAccountSectionUtilsMixi
244
245
 
245
246
  def setUp(self):
246
247
  self.user = self.login()
248
+ get_available_admin_time_zones.cache_clear()
247
249
 
248
250
  def test_account_view(self):
249
251
  """
@@ -479,7 +481,7 @@ class TestAccountSection(WagtailTestUtils, TestCase, TestAccountSectionUtilsMixi
479
481
  response = self.client.get(reverse("wagtailadmin_home"))
480
482
  self.assertContains(
481
483
  response,
482
- '<html lang="es" dir="ltr" class="w-theme-dark w-density-default">',
484
+ '<html lang="es" dir="ltr" class="w-theme-dark w-density-default w-contrast-system">',
483
485
  )
484
486
 
485
487
  def test_unset_language_preferences(self):
@@ -567,7 +569,10 @@ class TestAccountSection(WagtailTestUtils, TestCase, TestAccountSectionUtilsMixi
567
569
 
568
570
  @unittest.skipUnless(settings.USE_TZ, "Timezone support is disabled")
569
571
  def test_available_admin_time_zones_by_default(self):
570
- self.assertListEqual(get_available_admin_time_zones(), pytz.common_timezones)
572
+ self.assertListEqual(
573
+ get_available_admin_time_zones(),
574
+ sorted(zoneinfo.available_timezones()),
575
+ )
571
576
 
572
577
  @unittest.skipUnless(settings.USE_TZ, "Timezone support is disabled")
573
578
  @override_settings(WAGTAIL_USER_TIME_ZONES=["Europe/London"])
@@ -606,6 +611,21 @@ class TestAccountSection(WagtailTestUtils, TestCase, TestAccountSectionUtilsMixi
606
611
 
607
612
  self.assertEqual(profile.theme, "light")
608
613
 
614
+ def test_change_contrast_post(self):
615
+ response = self.post_form(
616
+ {
617
+ "theme-contrast": "more_contrast",
618
+ }
619
+ )
620
+
621
+ # Check that the user was redirected to the account page
622
+ self.assertRedirects(response, reverse("wagtailadmin_account"))
623
+
624
+ profile = UserProfile.get_for_user(self.user)
625
+ profile.refresh_from_db()
626
+
627
+ self.assertEqual(profile.contrast, "more_contrast")
628
+
609
629
  def test_change_density_post(self):
610
630
  response = self.post_form(
611
631
  {
@@ -1,7 +1,9 @@
1
1
  from datetime import timedelta
2
+ from io import StringIO
2
3
 
3
4
  from django.conf import settings
4
5
  from django.contrib.auth.models import Group, Permission
6
+ from django.core.management import call_command
5
7
  from django.test import TestCase
6
8
  from django.urls import reverse
7
9
  from django.utils import timezone
@@ -144,8 +146,8 @@ class TestAuditLogAdmin(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
144
146
  )
145
147
 
146
148
  self.assertContains(
147
- response, "system", 3
148
- ) # create without a user + remove restriction + 1 from unrelated admin color theme
149
+ response, "system", 4
150
+ ) # create without a user + remove restriction + 2 from unrelated admin color theme
149
151
  self.assertContains(
150
152
  response, "the_editor", 9
151
153
  ) # 7 entries by editor + 1 in sidebar menu + 1 in filter
@@ -305,6 +307,26 @@ class TestAuditLogAdmin(AdminTemplateTestUtils, WagtailTestUtils, TestCase):
305
307
  response = self.client.get(reverse("wagtailadmin_reports:site_history"))
306
308
  self.assertContains(response, expected_deleted_string)
307
309
 
310
+ def test_page_history_after_revision_purge(self):
311
+ self._update_page(self.hello_page)
312
+ call_command("purge_revisions", days=0, stdout=StringIO())
313
+
314
+ history_url = reverse(
315
+ "wagtailadmin_pages:history", kwargs={"page_id": self.hello_page.id}
316
+ )
317
+
318
+ self.login(user=self.editor)
319
+
320
+ response = self.client.get(history_url)
321
+ self.assertEqual(response.status_code, 200)
322
+
323
+ self.assertContains(response, "Created", 1)
324
+ self.assertContains(response, "Draft saved", 2)
325
+ self.assertContains(response, "Locked", 1)
326
+ self.assertContains(response, "Unlocked", 1)
327
+ self.assertContains(response, "Page scheduled for publishing", 1)
328
+ self.assertContains(response, "Published", 1)
329
+
308
330
  def test_edit_form_has_history_link(self):
309
331
  self.hello_page.save_revision()
310
332
  self.login(user=self.editor)
@@ -337,7 +337,11 @@ class TestEditCollectionAsSuperuser(AdminTemplateTestUtils, WagtailTestUtils, Te
337
337
  def test_get(self):
338
338
  response = self.get()
339
339
  self.assertEqual(response.status_code, 200)
340
- self.assertContains(response, "Delete collection")
340
+ delete_url = reverse(
341
+ "wagtailadmin_collections:delete",
342
+ args=(self.collection.id,),
343
+ )
344
+ self.assertContains(response, delete_url)
341
345
  self.assertBreadcrumbsItemsRendered(
342
346
  [
343
347
  {"url": "/admin/collections/", "label": "Collections"},
@@ -501,7 +505,11 @@ class TestEditCollection(CollectionInstanceTestUtils, WagtailTestUtils, TestCase
501
505
  response = self.get(collection_id=self.marketing_collection.id)
502
506
  self.assertEqual(response.status_code, 200)
503
507
  self.assertEqual(list(response.context["form"].fields.keys()), ["name"])
504
- self.assertNotContains(response, "Delete collection")
508
+ delete_url = reverse(
509
+ "wagtailadmin_collections:delete",
510
+ args=(self.marketing_collection.id,),
511
+ )
512
+ self.assertNotContains(response, delete_url)
505
513
 
506
514
  def test_cannot_move_collection_permissions_are_assigned_to_with_minimal_permission(
507
515
  self,
@@ -552,9 +560,13 @@ class TestEditCollection(CollectionInstanceTestUtils, WagtailTestUtils, TestCase
552
560
  self.test_marketing_user_cannot_move_collection_permissions_are_assigned_to_post()
553
561
 
554
562
  def test_page_shows_delete_link_only_if_delete_permitted(self):
563
+ delete_url = reverse(
564
+ "wagtailadmin_collections:delete",
565
+ args=(self.marketing_sub_collection.id,),
566
+ )
555
567
  # Retrieve edit form and check fields
556
568
  response = self.get(collection_id=self.marketing_sub_collection.id)
557
- self.assertNotContains(response, "Delete collection")
569
+ self.assertNotContains(response, delete_url)
558
570
 
559
571
  # Add delete permission to a different collection and try again,
560
572
  # ensure that it checks against the tree structure, and not just a
@@ -566,7 +578,7 @@ class TestEditCollection(CollectionInstanceTestUtils, WagtailTestUtils, TestCase
566
578
  permission=self.delete_permission,
567
579
  )
568
580
  response = self.get(collection_id=self.marketing_sub_collection.id)
569
- self.assertNotContains(response, "Delete collection")
581
+ self.assertNotContains(response, delete_url)
570
582
 
571
583
  # Add delete permission to parent collection and try again
572
584
  GroupCollectionPermission.objects.create(
@@ -575,7 +587,7 @@ class TestEditCollection(CollectionInstanceTestUtils, WagtailTestUtils, TestCase
575
587
  permission=self.delete_permission,
576
588
  )
577
589
  response = self.get(collection_id=self.marketing_sub_collection.id)
578
- self.assertContains(response, "Delete collection")
590
+ self.assertContains(response, delete_url)
579
591
 
580
592
 
581
593
  class TestDeleteCollectionAsSuperuser(
@@ -229,7 +229,7 @@ class TestLockedPagesQueryCount(WagtailTestUtils, TestCase):
229
229
  # Warm up the cache
230
230
  html = panel.render_html(parent_context)
231
231
 
232
- with self.assertNumQueries(1):
232
+ with self.assertNumQueries(7):
233
233
  html = panel.render_html(parent_context)
234
234
  soup = self.get_soup(html)
235
235
  # Should be sorted descending by locked_at
@@ -1,6 +1,7 @@
1
+ from collections.abc import Mapping
1
2
  from datetime import date, datetime, timezone
2
3
  from functools import wraps
3
- from typing import Any, List, Mapping, Optional
4
+ from typing import Any, Optional
4
5
  from unittest import mock
5
6
 
6
7
  from django import forms
@@ -846,7 +847,7 @@ class TestFieldPanel(TestCase):
846
847
  def _get_form(
847
848
  self,
848
849
  data: Optional[Mapping[str, Any]] = None,
849
- fields: Optional[List[str]] = None,
850
+ fields: Optional[list[str]] = None,
850
851
  ) -> WagtailAdminPageForm:
851
852
  cls = get_form_for_model(
852
853
  EventPage,
@@ -11,6 +11,10 @@ class TestIconSpriteView(SimpleTestCase):
11
11
  )
12
12
  self.assertEqual(response.wsgi_request.GET["h"], get_icon_sprite_hash())
13
13
 
14
+ def test_no_comments(self):
15
+ response = self.client.get(get_icon_sprite_url())
16
+ self.assertNotContains(response, "<!--")
17
+
14
18
 
15
19
  class TestIconSpriteHash(SimpleTestCase):
16
20
  def test_hash(self):
@@ -1,5 +1,3 @@
1
- import json
2
-
3
1
  from django.contrib.auth.models import Group
4
2
  from django.test import TestCase, override_settings
5
3
  from django.urls import reverse
@@ -116,27 +114,15 @@ class TestSetPrivacyView(WagtailTestUtils, TestCase):
116
114
 
117
115
  # Check response
118
116
  self.assertEqual(response.status_code, 200)
119
- self.assertTemplateUsed(
120
- response, "wagtailadmin/page_privacy/ancestor_privacy.html"
121
- )
122
- self.assertContains(
123
- response, "This page has been made private by a parent page."
124
- )
125
- self.assertEqual(
126
- response.context["page_with_restriction"].specific, self.private_page
127
- )
128
- # Should render without any heading, as the dialog already has a heading
129
- soup = self.get_soup(json.loads(response.content)["html"])
130
- self.assertIsNone(soup.select_one("header"))
131
- self.assertIsNone(soup.select_one("h1"))
132
-
133
- # Should link to the edit page for the collection with the restriction
134
- link = soup.select_one("a")
135
117
  parent_edit_url = reverse(
136
118
  "wagtailadmin_pages:edit",
137
119
  args=(self.private_page.pk,),
138
120
  )
139
- self.assertEqual(link.get("href"), parent_edit_url)
121
+ html = response.json()["html"]
122
+ self.assertIn(
123
+ f'<span>Privacy is inherited from the ancestor page - <a href="{parent_edit_url }">Private page (simple page)</a></span>',
124
+ html,
125
+ )
140
126
 
141
127
  def test_set_password_restriction(self):
142
128
  """
@@ -194,7 +194,7 @@ class TestLockedPagesView(BaseReportViewTestCase):
194
194
  self.assertActiveFilterNotRendered(soup)
195
195
 
196
196
  # Locked by current user shown in indicator
197
- self.assertContains(response, "locked-indicator indicator--is-inverse")
197
+ self.assertNotContains(response, "indicator--is-dimmed")
198
198
  self.assertContains(
199
199
  response, 'title="This page is locked, by you, to further editing"'
200
200
  )
@@ -57,11 +57,11 @@ class TestPagesSummary(WagtailTestUtils, TestCase):
57
57
  self.assertSummaryContainsLinkToPage(self.wagtail_root.pk)
58
58
 
59
59
  def test_summary_includes_page_count_without_wagtail_root(self):
60
- self.assertSummaryContains(f"<span>{Page.objects.count() - 1}</span> Pages")
60
+ self.assertSummaryContains(f"{Page.objects.count() - 1} Pages")
61
61
 
62
62
  def test_summary_shows_zero_pages_if_none_exist_except_wagtail_root(self):
63
63
  Page.objects.exclude(pk=self.wagtail_root.pk).delete()
64
- self.assertSummaryContains("<span>0</span> Pages")
64
+ self.assertSummaryContains("0 Pages")
65
65
 
66
66
  def test_user_with_no_page_permissions_is_not_shown_panel(self):
67
67
  self.user.is_superuser = False
@@ -78,4 +78,4 @@ class TestPagesSummary(WagtailTestUtils, TestCase):
78
78
  self.user.is_superuser = False
79
79
  self.user.save()
80
80
  self.user.groups.add(self.test_page_group)
81
- self.assertSummaryContains("<span>1</span> Page")
81
+ self.assertSummaryContains("1 Page")