Add fallback for blank string representations in audit log, and add tests for creating/editing invalid draft snippets

pull/12964/head
Matt Westcott 2025-03-03 18:52:00 +00:00 zatwierdzone przez Matt Westcott
rodzic f649856cf4
commit 3f70a0a52f
2 zmienionych plików z 118 dodań i 1 usunięć

Wyświetl plik

@ -97,7 +97,7 @@ class BaseLogEntryManager(models.Manager):
return LogEntryQuerySet(self.model, using=self._db)
def get_instance_title(self, instance):
return str(instance)
return str(instance) or f"{instance.__class__.__name__} object ({instance.pk})"
def log_action(self, instance, action, **kwargs):
"""

Wyświetl plik

@ -1325,6 +1325,45 @@ class TestCreateDraftStateSnippet(WagtailTestUtils, TestCase):
# The revision content should contain the data
self.assertEqual(snippet.latest_revision.content["text"], "Draft-enabled Foo")
# A log entry should be created
log_entry = ModelLogEntry.objects.for_instance(snippet).get(
action="wagtail.create"
)
self.assertEqual(log_entry.revision, snippet.latest_revision)
self.assertEqual(log_entry.label, "Draft-enabled Foo")
def test_create_skips_validation_when_saving_draft(self):
response = self.post(post_data={"text": ""})
snippet = DraftStateModel.objects.get(text="")
self.assertRedirects(
response,
reverse(
"wagtailsnippets_tests_draftstatemodel:edit", args=[quote(snippet.pk)]
),
)
self.assertFalse(snippet.live)
# A log entry should be created (with a fallback label)
log_entry = ModelLogEntry.objects.for_instance(snippet).get(
action="wagtail.create"
)
self.assertEqual(log_entry.revision, snippet.latest_revision)
self.assertEqual(log_entry.label, f"DraftStateModel object ({snippet.pk})")
def test_create_will_not_publish_invalid_snippet(self):
response = self.post(
post_data={"text": "", "action-publish": "Publish"},
)
self.assertEqual(response.status_code, 200)
self.assertContains(
response, "The draft state model could not be created due to errors."
)
snippets = DraftStateModel.objects.filter(text="")
self.assertEqual(snippets.count(), 0)
def test_publish(self):
# Connect a mock signal handler to published signal
mock_handler = mock.MagicMock()
@ -2238,6 +2277,84 @@ class TestEditDraftStateSnippet(BaseTestSnippetEditView):
# The revision content should contain the new data
self.assertEqual(latest_revision.content["text"], "Draft-enabled Bar")
# A log entry should be created
log_entry = (
ModelLogEntry.objects.for_instance(self.test_snippet)
.filter(action="wagtail.edit")
.order_by("-timestamp")
.first()
)
self.assertEqual(log_entry.revision, self.test_snippet.latest_revision)
self.assertEqual(log_entry.label, "Draft-enabled Bar")
def test_skip_validation_on_save_draft(self):
response = self.post(post_data={"text": ""})
self.test_snippet.refresh_from_db()
revisions = Revision.objects.for_instance(self.test_snippet)
latest_revision = self.test_snippet.latest_revision
self.assertRedirects(response, self.get_edit_url())
# The instance should be updated, since it is still a draft
self.assertEqual(self.test_snippet.text, "")
# The instance should be a draft
self.assertFalse(self.test_snippet.live)
self.assertTrue(self.test_snippet.has_unpublished_changes)
self.assertIsNone(self.test_snippet.first_published_at)
self.assertIsNone(self.test_snippet.last_published_at)
self.assertIsNone(self.test_snippet.live_revision)
# The revision should be created and set as latest_revision
self.assertEqual(revisions.count(), 1)
self.assertEqual(latest_revision, revisions.first())
# The revision content should contain the new data
self.assertEqual(latest_revision.content["text"], "")
# A log entry should be created (with a fallback label)
log_entry = (
ModelLogEntry.objects.for_instance(self.test_snippet)
.filter(action="wagtail.edit")
.order_by("-timestamp")
.first()
)
self.assertEqual(log_entry.revision, self.test_snippet.latest_revision)
self.assertEqual(
log_entry.label,
f"DraftStateCustomPrimaryKeyModel object ({self.test_snippet.pk})",
)
def test_cannot_publish_invalid(self):
# Connect a mock signal handler to published signal
mock_handler = mock.MagicMock()
published.connect(mock_handler)
try:
response = self.post(
post_data={
"text": "",
"action-publish": "action-publish",
}
)
self.test_snippet.refresh_from_db()
self.assertEqual(response.status_code, 200)
self.assertContains(
response,
"The draft state custom primary key model could not be saved due to errors.",
)
# The instance should be unchanged
self.assertEqual(self.test_snippet.text, "Draft-enabled Foo")
self.assertFalse(self.test_snippet.live)
# The published signal should not have been fired
self.assertEqual(mock_handler.call_count, 0)
finally:
published.disconnect(mock_handler)
def test_publish(self):
# Connect a mock signal handler to published signal
mock_handler = mock.MagicMock()