mirror of
https://github.com/sissbruecker/linkding.git
synced 2025-08-13 21:49:26 +02:00
Add button for creating missing HTML snapshots (#696)
* add button for creating missing HTML snapshots * refactor messages in settings view * show alternative text when there are no missing snapshots
This commit is contained in:
@@ -611,3 +611,89 @@ class BookmarkTasksTestCase(TestCase, BookmarkFactoryMixin):
|
||||
tasks.create_html_snapshot(bookmark)
|
||||
|
||||
self.assertEqual(BookmarkAsset.objects.count(), 0)
|
||||
|
||||
@override_settings(LD_ENABLE_SNAPSHOTS=True)
|
||||
def test_create_missing_html_snapshots(self):
|
||||
bookmarks_with_snapshots = []
|
||||
bookmarks_without_snapshots = []
|
||||
|
||||
# setup bookmarks with snapshots
|
||||
bookmark = self.setup_bookmark()
|
||||
self.setup_asset(
|
||||
bookmark=bookmark,
|
||||
asset_type=BookmarkAsset.TYPE_SNAPSHOT,
|
||||
status=BookmarkAsset.STATUS_COMPLETE,
|
||||
)
|
||||
bookmarks_with_snapshots.append(bookmark)
|
||||
|
||||
bookmark = self.setup_bookmark()
|
||||
self.setup_asset(
|
||||
bookmark=bookmark,
|
||||
asset_type=BookmarkAsset.TYPE_SNAPSHOT,
|
||||
status=BookmarkAsset.STATUS_PENDING,
|
||||
)
|
||||
bookmarks_with_snapshots.append(bookmark)
|
||||
|
||||
# setup bookmarks without snapshots
|
||||
bookmark = self.setup_bookmark()
|
||||
bookmarks_without_snapshots.append(bookmark)
|
||||
|
||||
bookmark = self.setup_bookmark()
|
||||
self.setup_asset(
|
||||
bookmark=bookmark,
|
||||
asset_type=BookmarkAsset.TYPE_SNAPSHOT,
|
||||
status=BookmarkAsset.STATUS_FAILURE,
|
||||
)
|
||||
bookmarks_without_snapshots.append(bookmark)
|
||||
|
||||
bookmark = self.setup_bookmark()
|
||||
self.setup_asset(
|
||||
bookmark=bookmark,
|
||||
asset_type="some_other_type",
|
||||
status=BookmarkAsset.STATUS_PENDING,
|
||||
)
|
||||
bookmarks_without_snapshots.append(bookmark)
|
||||
|
||||
bookmark = self.setup_bookmark()
|
||||
self.setup_asset(
|
||||
bookmark=bookmark,
|
||||
asset_type="some_other_type",
|
||||
status=BookmarkAsset.STATUS_COMPLETE,
|
||||
)
|
||||
bookmarks_without_snapshots.append(bookmark)
|
||||
|
||||
initial_assets = list(BookmarkAsset.objects.all())
|
||||
initial_assets_count = len(initial_assets)
|
||||
initial_asset_ids = [asset.id for asset in initial_assets]
|
||||
count = tasks.create_missing_html_snapshots(self.get_or_create_test_user())
|
||||
|
||||
self.assertEqual(count, 4)
|
||||
self.assertEqual(BookmarkAsset.objects.count(), initial_assets_count + count)
|
||||
|
||||
for bookmark in bookmarks_without_snapshots:
|
||||
new_assets = BookmarkAsset.objects.filter(bookmark=bookmark).exclude(
|
||||
id__in=initial_asset_ids
|
||||
)
|
||||
self.assertEqual(new_assets.count(), 1)
|
||||
|
||||
for bookmark in bookmarks_with_snapshots:
|
||||
new_assets = BookmarkAsset.objects.filter(bookmark=bookmark).exclude(
|
||||
id__in=initial_asset_ids
|
||||
)
|
||||
self.assertEqual(new_assets.count(), 0)
|
||||
|
||||
@override_settings(LD_ENABLE_SNAPSHOTS=True)
|
||||
def test_create_missing_html_snapshots_respects_current_user(self):
|
||||
self.setup_bookmark()
|
||||
self.setup_bookmark()
|
||||
self.setup_bookmark()
|
||||
|
||||
other_user = self.setup_user()
|
||||
self.setup_bookmark(user=other_user)
|
||||
self.setup_bookmark(user=other_user)
|
||||
self.setup_bookmark(user=other_user)
|
||||
|
||||
count = tasks.create_missing_html_snapshots(self.get_or_create_test_user())
|
||||
|
||||
self.assertEqual(count, 3)
|
||||
self.assertEqual(BookmarkAsset.objects.count(), count)
|
||||
|
@@ -44,6 +44,24 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
|
||||
return {**form_data, **overrides}
|
||||
|
||||
def assertSuccessMessage(self, html, message: str, count=1):
|
||||
self.assertInHTML(
|
||||
f"""
|
||||
<div class="toast toast-success mb-4">{ message }</div>
|
||||
""",
|
||||
html,
|
||||
count=count,
|
||||
)
|
||||
|
||||
def assertErrorMessage(self, html, message: str, count=1):
|
||||
self.assertInHTML(
|
||||
f"""
|
||||
<div class="toast toast-error mb-4">{ message }</div>
|
||||
""",
|
||||
html,
|
||||
count=count,
|
||||
)
|
||||
|
||||
def test_should_render_successfully(self):
|
||||
response = self.client.get(reverse("bookmarks:settings.general"))
|
||||
|
||||
@@ -138,12 +156,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
self.user.profile.permanent_notes, form_data["permanent_notes"]
|
||||
)
|
||||
self.assertEqual(self.user.profile.custom_css, form_data["custom_css"])
|
||||
self.assertInHTML(
|
||||
"""
|
||||
<p class="form-input-hint">Profile updated</p>
|
||||
""",
|
||||
html,
|
||||
)
|
||||
self.assertSuccessMessage(html, "Profile updated")
|
||||
|
||||
def test_update_profile_should_not_be_called_without_respective_form_action(self):
|
||||
form_data = {
|
||||
@@ -156,13 +169,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(self.user.profile.theme, UserProfile.THEME_AUTO)
|
||||
self.assertInHTML(
|
||||
"""
|
||||
<p class="form-input-hint">Profile updated</p>
|
||||
""",
|
||||
html,
|
||||
count=0,
|
||||
)
|
||||
self.assertSuccessMessage(html, "Profile updated", count=0)
|
||||
|
||||
def test_enable_favicons_should_schedule_icon_update(self):
|
||||
with patch.object(
|
||||
@@ -210,13 +217,8 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
html = response.content.decode()
|
||||
|
||||
mock_schedule_refresh_favicons.assert_called_once()
|
||||
self.assertInHTML(
|
||||
"""
|
||||
<p class="form-input-hint">
|
||||
Scheduled favicon update. This may take a while...
|
||||
</p>
|
||||
""",
|
||||
html,
|
||||
self.assertSuccessMessage(
|
||||
html, "Scheduled favicon update. This may take a while..."
|
||||
)
|
||||
|
||||
def test_refresh_favicons_should_not_be_called_without_respective_form_action(self):
|
||||
@@ -230,14 +232,8 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
html = response.content.decode()
|
||||
|
||||
mock_schedule_refresh_favicons.assert_not_called()
|
||||
self.assertInHTML(
|
||||
"""
|
||||
<p class="form-input-hint">
|
||||
Scheduled favicon update. This may take a while...
|
||||
</p>
|
||||
""",
|
||||
html,
|
||||
count=0,
|
||||
self.assertSuccessMessage(
|
||||
html, "Scheduled favicon update. This may take a while...", count=0
|
||||
)
|
||||
|
||||
def test_refresh_favicons_should_be_visible_when_favicons_enabled_in_profile(self):
|
||||
@@ -365,3 +361,57 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
with patch.object(requests, "get", return_value=latest_version_response_mock):
|
||||
version_info = get_version_info(random.random())
|
||||
self.assertEqual(version_info, app_version)
|
||||
|
||||
@override_settings(LD_ENABLE_SNAPSHOTS=True)
|
||||
def test_create_missing_html_snapshots(self):
|
||||
with patch.object(
|
||||
tasks, "create_missing_html_snapshots"
|
||||
) as mock_create_missing_html_snapshots:
|
||||
mock_create_missing_html_snapshots.return_value = 5
|
||||
form_data = {
|
||||
"create_missing_html_snapshots": "",
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("bookmarks:settings.general"), form_data
|
||||
)
|
||||
html = response.content.decode()
|
||||
|
||||
mock_create_missing_html_snapshots.assert_called_once()
|
||||
self.assertSuccessMessage(
|
||||
html, "Queued 5 missing snapshots. This may take a while..."
|
||||
)
|
||||
|
||||
@override_settings(LD_ENABLE_SNAPSHOTS=True)
|
||||
def test_create_missing_html_snapshots_no_missing_snapshots(self):
|
||||
with patch.object(
|
||||
tasks, "create_missing_html_snapshots"
|
||||
) as mock_create_missing_html_snapshots:
|
||||
mock_create_missing_html_snapshots.return_value = 0
|
||||
form_data = {
|
||||
"create_missing_html_snapshots": "",
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse("bookmarks:settings.general"), form_data
|
||||
)
|
||||
html = response.content.decode()
|
||||
|
||||
mock_create_missing_html_snapshots.assert_called_once()
|
||||
self.assertSuccessMessage(html, "No missing snapshots found.")
|
||||
|
||||
def test_create_missing_html_snapshots_should_not_be_called_without_respective_form_action(
|
||||
self,
|
||||
):
|
||||
with patch.object(
|
||||
tasks, "create_missing_html_snapshots"
|
||||
) as mock_create_missing_html_snapshots:
|
||||
mock_create_missing_html_snapshots.return_value = 5
|
||||
form_data = {}
|
||||
response = self.client.post(
|
||||
reverse("bookmarks:settings.general"), form_data
|
||||
)
|
||||
html = response.content.decode()
|
||||
|
||||
mock_create_missing_html_snapshots.assert_not_called()
|
||||
self.assertSuccessMessage(
|
||||
html, "Queued 5 missing snapshots. This may take a while...", count=0
|
||||
)
|
||||
|
@@ -11,19 +11,27 @@ class SettingsImportViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
user = self.get_or_create_test_user()
|
||||
self.client.force_login(user)
|
||||
|
||||
def assertFormSuccessHint(self, response, text: str):
|
||||
self.assertContains(response, '<div class="has-success">')
|
||||
self.assertContains(response, text)
|
||||
def assertSuccessMessage(self, response, message: str):
|
||||
self.assertInHTML(
|
||||
f"""
|
||||
<div class="toast toast-success mb-4">{ message }</div>
|
||||
""",
|
||||
response.content.decode("utf-8"),
|
||||
)
|
||||
|
||||
def assertNoFormSuccessHint(self, response):
|
||||
self.assertNotContains(response, '<div class="has-success">')
|
||||
def assertNoSuccessMessage(self, response):
|
||||
self.assertNotContains(response, '<div class="toast toast-success mb-4">')
|
||||
|
||||
def assertFormErrorHint(self, response, text: str):
|
||||
self.assertContains(response, '<div class="has-error">')
|
||||
self.assertContains(response, text)
|
||||
def assertErrorMessage(self, response, message: str):
|
||||
self.assertInHTML(
|
||||
f"""
|
||||
<div class="toast toast-error mb-4">{ message }</div>
|
||||
""",
|
||||
response.content.decode("utf-8"),
|
||||
)
|
||||
|
||||
def assertNoFormErrorHint(self, response):
|
||||
self.assertNotContains(response, '<div class="has-error">')
|
||||
def assertNoErrorMessage(self, response):
|
||||
self.assertNotContains(response, '<div class="toast toast-error mb-4">')
|
||||
|
||||
def test_should_import_successfully(self):
|
||||
with open(
|
||||
@@ -36,10 +44,10 @@ class SettingsImportViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
)
|
||||
|
||||
self.assertRedirects(response, reverse("bookmarks:settings.general"))
|
||||
self.assertFormSuccessHint(
|
||||
response, "3 bookmarks were successfully imported"
|
||||
self.assertSuccessMessage(
|
||||
response, "3 bookmarks were successfully imported."
|
||||
)
|
||||
self.assertNoFormErrorHint(response)
|
||||
self.assertNoErrorMessage(response)
|
||||
|
||||
def test_should_check_authentication(self):
|
||||
self.client.logout()
|
||||
@@ -53,8 +61,8 @@ class SettingsImportViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
response = self.client.post(reverse("bookmarks:settings.import"), follow=True)
|
||||
|
||||
self.assertRedirects(response, reverse("bookmarks:settings.general"))
|
||||
self.assertNoFormSuccessHint(response)
|
||||
self.assertFormErrorHint(response, "Please select a file to import.")
|
||||
self.assertNoSuccessMessage(response)
|
||||
self.assertErrorMessage(response, "Please select a file to import.")
|
||||
|
||||
@disable_logging
|
||||
def test_should_show_hint_if_import_raises_exception(self):
|
||||
@@ -68,8 +76,8 @@ class SettingsImportViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
)
|
||||
|
||||
self.assertRedirects(response, reverse("bookmarks:settings.general"))
|
||||
self.assertNoFormSuccessHint(response)
|
||||
self.assertFormErrorHint(
|
||||
self.assertNoSuccessMessage(response)
|
||||
self.assertErrorMessage(
|
||||
response, "An error occurred during bookmark import."
|
||||
)
|
||||
|
||||
@@ -87,10 +95,13 @@ class SettingsImportViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||
)
|
||||
|
||||
self.assertRedirects(response, reverse("bookmarks:settings.general"))
|
||||
self.assertFormSuccessHint(
|
||||
response, "2 bookmarks were successfully imported"
|
||||
self.assertSuccessMessage(
|
||||
response, "2 bookmarks were successfully imported."
|
||||
)
|
||||
self.assertErrorMessage(
|
||||
response,
|
||||
"1 bookmarks could not be imported. Please check the logs for more details.",
|
||||
)
|
||||
self.assertFormErrorHint(response, "1 bookmarks could not be imported")
|
||||
|
||||
def test_should_respect_map_private_flag_option(self):
|
||||
with open(
|
||||
|
Reference in New Issue
Block a user