mirror of
				https://github.com/sissbruecker/linkding.git
				synced 2025-11-04 13:04:00 +01:00 
			
		
		
		
	* add bundle model and query logic * cleanup tests * add basic form * add success message * Add form tests * Add bundle list view * fix edit view * Add remove button * Add basic preview logic * Make pagination use absolute URLs * Hide bookmark edits when rendering preview * Render bookmark list in preview * Reorder bundles * Show bundles in bookmark view * Make bookmark search respect selected bundle * UI tweaks * Fix bookmark scope * Improve bundle preview * Skip preview if form is submitted * Show correct preview after invalid form submission * Add option to hide bundles * Merge new migrations * Add tests for bundle menu * Improve check for preview being removed
		
			
				
	
	
		
			1105 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1105 lines
		
	
	
		
			39 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from unittest.mock import patch
 | 
						|
 | 
						|
from django.contrib.auth.models import User
 | 
						|
from django.core.files.uploadedfile import SimpleUploadedFile
 | 
						|
from django.forms import model_to_dict
 | 
						|
from django.http import HttpResponse
 | 
						|
from django.test import TestCase, override_settings
 | 
						|
from django.urls import reverse
 | 
						|
 | 
						|
from bookmarks.models import Bookmark, BookmarkAsset
 | 
						|
from bookmarks.services import assets, tasks
 | 
						|
from bookmarks.tests.helpers import (
 | 
						|
    BookmarkFactoryMixin,
 | 
						|
    BookmarkListTestMixin,
 | 
						|
    TagCloudTestMixin,
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
class BookmarkActionViewTestCase(
 | 
						|
    TestCase, BookmarkFactoryMixin, BookmarkListTestMixin, TagCloudTestMixin
 | 
						|
):
 | 
						|
 | 
						|
    def setUp(self) -> None:
 | 
						|
        user = self.get_or_create_test_user()
 | 
						|
        self.client.force_login(user)
 | 
						|
 | 
						|
    def assertBookmarksAreUnmodified(self, bookmarks: [Bookmark]):
 | 
						|
        self.assertEqual(len(bookmarks), Bookmark.objects.count())
 | 
						|
 | 
						|
        for bookmark in bookmarks:
 | 
						|
            self.assertEqual(
 | 
						|
                model_to_dict(bookmark),
 | 
						|
                model_to_dict(Bookmark.objects.get(id=bookmark.id)),
 | 
						|
            )
 | 
						|
 | 
						|
    def test_archive_should_archive_bookmark(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "archive": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
 | 
						|
        self.assertTrue(bookmark.is_archived)
 | 
						|
 | 
						|
    def test_can_only_archive_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark = self.setup_bookmark(user=other_user)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "archive": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
 | 
						|
        self.assertEqual(response.status_code, 404)
 | 
						|
        self.assertFalse(bookmark.is_archived)
 | 
						|
 | 
						|
    def test_unarchive_should_unarchive_bookmark(self):
 | 
						|
        bookmark = self.setup_bookmark(is_archived=True)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "unarchive": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
 | 
						|
        self.assertFalse(bookmark.is_archived)
 | 
						|
 | 
						|
    def test_unarchive_can_only_archive_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark = self.setup_bookmark(is_archived=True, user=other_user)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "unarchive": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
 | 
						|
        self.assertEqual(response.status_code, 404)
 | 
						|
        self.assertTrue(bookmark.is_archived)
 | 
						|
 | 
						|
    def test_delete_should_delete_bookmark(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "remove": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(Bookmark.objects.count(), 0)
 | 
						|
 | 
						|
    def test_delete_can_only_delete_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark = self.setup_bookmark(user=other_user)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "remove": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 404)
 | 
						|
        self.assertTrue(Bookmark.objects.filter(id=bookmark.id).exists())
 | 
						|
 | 
						|
    def test_mark_as_read(self):
 | 
						|
        bookmark = self.setup_bookmark(unread=True)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "mark_as_read": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
 | 
						|
        self.assertFalse(bookmark.unread)
 | 
						|
 | 
						|
    def test_unshare_should_unshare_bookmark(self):
 | 
						|
        bookmark = self.setup_bookmark(shared=True)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "unshare": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
 | 
						|
        self.assertFalse(bookmark.shared)
 | 
						|
 | 
						|
    def test_can_only_unshare_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark = self.setup_bookmark(user=other_user, shared=True)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "unshare": [bookmark.id],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
 | 
						|
        self.assertEqual(response.status_code, 404)
 | 
						|
        self.assertTrue(bookmark.shared)
 | 
						|
 | 
						|
    @override_settings(LD_ENABLE_SNAPSHOTS=True)
 | 
						|
    def test_create_html_snapshot(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
        with patch.object(tasks, "_create_html_snapshot_task"):
 | 
						|
            self.client.post(
 | 
						|
                reverse("linkding:bookmarks.index.action"),
 | 
						|
                {
 | 
						|
                    "create_html_snapshot": [bookmark.id],
 | 
						|
                },
 | 
						|
            )
 | 
						|
            self.assertEqual(bookmark.bookmarkasset_set.count(), 1)
 | 
						|
            asset = bookmark.bookmarkasset_set.first()
 | 
						|
            self.assertEqual(asset.asset_type, BookmarkAsset.TYPE_SNAPSHOT)
 | 
						|
 | 
						|
    @override_settings(LD_ENABLE_SNAPSHOTS=True)
 | 
						|
    def test_can_only_create_html_snapshot_for_own_bookmarks(self):
 | 
						|
        other_user = self.setup_user()
 | 
						|
        bookmark = self.setup_bookmark(user=other_user)
 | 
						|
        with patch.object(tasks, "_create_html_snapshot_task"):
 | 
						|
            response = self.client.post(
 | 
						|
                reverse("linkding:bookmarks.index.action"),
 | 
						|
                {
 | 
						|
                    "create_html_snapshot": [bookmark.id],
 | 
						|
                },
 | 
						|
            )
 | 
						|
            self.assertEqual(response.status_code, 404)
 | 
						|
            self.assertEqual(bookmark.bookmarkasset_set.count(), 0)
 | 
						|
 | 
						|
    def test_upload_asset(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
        file_content = b"file content"
 | 
						|
        upload_file = SimpleUploadedFile("test.txt", file_content)
 | 
						|
 | 
						|
        with patch.object(assets, "upload_asset") as mock_upload_asset:
 | 
						|
            response = self.client.post(
 | 
						|
                reverse("linkding:bookmarks.index.action"),
 | 
						|
                {"upload_asset": bookmark.id, "upload_asset_file": upload_file},
 | 
						|
            )
 | 
						|
            self.assertEqual(response.status_code, 302)
 | 
						|
 | 
						|
            mock_upload_asset.assert_called_once()
 | 
						|
 | 
						|
            args, _ = mock_upload_asset.call_args
 | 
						|
            self.assertEqual(args[0], bookmark)
 | 
						|
 | 
						|
            upload_file = args[1]
 | 
						|
            self.assertEqual(upload_file.name, "test.txt")
 | 
						|
 | 
						|
    def test_can_only_upload_asset_for_own_bookmarks(self):
 | 
						|
        other_user = self.setup_user()
 | 
						|
        bookmark = self.setup_bookmark(user=other_user)
 | 
						|
        file_content = b"file content"
 | 
						|
        upload_file = SimpleUploadedFile("test.txt", file_content)
 | 
						|
 | 
						|
        with patch.object(assets, "upload_asset") as mock_upload_asset:
 | 
						|
            response = self.client.post(
 | 
						|
                reverse("linkding:bookmarks.index.action"),
 | 
						|
                {"upload_asset": bookmark.id, "upload_asset_file": upload_file},
 | 
						|
            )
 | 
						|
            self.assertEqual(response.status_code, 404)
 | 
						|
 | 
						|
            mock_upload_asset.assert_not_called()
 | 
						|
 | 
						|
    @override_settings(LD_DISABLE_ASSET_UPLOAD=True)
 | 
						|
    def test_upload_asset_disabled(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
        file_content = b"file content"
 | 
						|
        upload_file = SimpleUploadedFile("test.txt", file_content)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {"upload_asset": bookmark.id, "upload_asset_file": upload_file},
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 403)
 | 
						|
 | 
						|
    def test_upload_asset_without_file(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {"upload_asset": bookmark.id},
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 400)
 | 
						|
 | 
						|
    def test_remove_asset(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
        asset = self.setup_asset(bookmark)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"), {"remove_asset": asset.id}
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 302)
 | 
						|
        self.assertFalse(BookmarkAsset.objects.filter(id=asset.id).exists())
 | 
						|
 | 
						|
    def test_can_only_remove_own_asset(self):
 | 
						|
        other_user = self.setup_user()
 | 
						|
        bookmark = self.setup_bookmark(user=other_user)
 | 
						|
        asset = self.setup_asset(bookmark)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"), {"remove_asset": asset.id}
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 404)
 | 
						|
        self.assertTrue(BookmarkAsset.objects.filter(id=asset.id).exists())
 | 
						|
 | 
						|
    def test_update_state(self):
 | 
						|
        bookmark = self.setup_bookmark()
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "update_state": bookmark.id,
 | 
						|
                "is_archived": "on",
 | 
						|
                "unread": "on",
 | 
						|
                "shared": "on",
 | 
						|
            },
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 302)
 | 
						|
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
        self.assertTrue(bookmark.unread)
 | 
						|
        self.assertTrue(bookmark.is_archived)
 | 
						|
        self.assertTrue(bookmark.shared)
 | 
						|
 | 
						|
    def test_can_only_update_own_bookmark_state(self):
 | 
						|
        other_user = self.setup_user()
 | 
						|
        bookmark = self.setup_bookmark(user=other_user)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "update_state": bookmark.id,
 | 
						|
                "is_archived": "on",
 | 
						|
                "unread": "on",
 | 
						|
                "shared": "on",
 | 
						|
            },
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 404)
 | 
						|
 | 
						|
        bookmark.refresh_from_db()
 | 
						|
        self.assertFalse(bookmark.unread)
 | 
						|
        self.assertFalse(bookmark.is_archived)
 | 
						|
        self.assertFalse(bookmark.shared)
 | 
						|
 | 
						|
    def test_bulk_archive(self):
 | 
						|
        bookmark1 = self.setup_bookmark()
 | 
						|
        bookmark2 = self.setup_bookmark()
 | 
						|
        bookmark3 = self.setup_bookmark()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_archive"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark1.id).is_archived)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark2.id).is_archived)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark3.id).is_archived)
 | 
						|
 | 
						|
    def test_can_only_bulk_archive_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_archive"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark1.id).is_archived)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark2.id).is_archived)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark3.id).is_archived)
 | 
						|
 | 
						|
    def test_bulk_unarchive(self):
 | 
						|
        bookmark1 = self.setup_bookmark(is_archived=True)
 | 
						|
        bookmark2 = self.setup_bookmark(is_archived=True)
 | 
						|
        bookmark3 = self.setup_bookmark(is_archived=True)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.archived.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_unarchive"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark1.id).is_archived)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark2.id).is_archived)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark3.id).is_archived)
 | 
						|
 | 
						|
    def test_can_only_bulk_unarchive_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(is_archived=True, user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(is_archived=True, user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(is_archived=True, user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.archived.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_unarchive"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark1.id).is_archived)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark2.id).is_archived)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark3.id).is_archived)
 | 
						|
 | 
						|
    def test_bulk_delete(self):
 | 
						|
        bookmark1 = self.setup_bookmark()
 | 
						|
        bookmark2 = self.setup_bookmark()
 | 
						|
        bookmark3 = self.setup_bookmark()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(id=bookmark1.id).first())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(id=bookmark2.id).first())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(id=bookmark3.id).first())
 | 
						|
 | 
						|
    def test_can_only_bulk_delete_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertIsNotNone(Bookmark.objects.filter(id=bookmark1.id).first())
 | 
						|
        self.assertIsNotNone(Bookmark.objects.filter(id=bookmark2.id).first())
 | 
						|
        self.assertIsNotNone(Bookmark.objects.filter(id=bookmark3.id).first())
 | 
						|
 | 
						|
    def test_bulk_tag(self):
 | 
						|
        bookmark1 = self.setup_bookmark()
 | 
						|
        bookmark2 = self.setup_bookmark()
 | 
						|
        bookmark3 = self.setup_bookmark()
 | 
						|
        tag1 = self.setup_tag()
 | 
						|
        tag2 = self.setup_tag()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_tag"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_tag_string": [f"{tag1.name} {tag2.name}"],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark1.refresh_from_db()
 | 
						|
        bookmark2.refresh_from_db()
 | 
						|
        bookmark3.refresh_from_db()
 | 
						|
 | 
						|
        self.assertCountEqual(bookmark1.tags.all(), [tag1, tag2])
 | 
						|
        self.assertCountEqual(bookmark2.tags.all(), [tag1, tag2])
 | 
						|
        self.assertCountEqual(bookmark3.tags.all(), [tag1, tag2])
 | 
						|
 | 
						|
    def test_can_only_bulk_tag_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(user=other_user)
 | 
						|
        tag1 = self.setup_tag()
 | 
						|
        tag2 = self.setup_tag()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_tag"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_tag_string": [f"{tag1.name} {tag2.name}"],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark1.refresh_from_db()
 | 
						|
        bookmark2.refresh_from_db()
 | 
						|
        bookmark3.refresh_from_db()
 | 
						|
 | 
						|
        self.assertCountEqual(bookmark1.tags.all(), [])
 | 
						|
        self.assertCountEqual(bookmark2.tags.all(), [])
 | 
						|
        self.assertCountEqual(bookmark3.tags.all(), [])
 | 
						|
 | 
						|
    def test_bulk_untag(self):
 | 
						|
        tag1 = self.setup_tag()
 | 
						|
        tag2 = self.setup_tag()
 | 
						|
        bookmark1 = self.setup_bookmark(tags=[tag1, tag2])
 | 
						|
        bookmark2 = self.setup_bookmark(tags=[tag1, tag2])
 | 
						|
        bookmark3 = self.setup_bookmark(tags=[tag1, tag2])
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_untag"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_tag_string": [f"{tag1.name} {tag2.name}"],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark1.refresh_from_db()
 | 
						|
        bookmark2.refresh_from_db()
 | 
						|
        bookmark3.refresh_from_db()
 | 
						|
 | 
						|
        self.assertCountEqual(bookmark1.tags.all(), [])
 | 
						|
        self.assertCountEqual(bookmark2.tags.all(), [])
 | 
						|
        self.assertCountEqual(bookmark3.tags.all(), [])
 | 
						|
 | 
						|
    def test_can_only_bulk_untag_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        tag1 = self.setup_tag()
 | 
						|
        tag2 = self.setup_tag()
 | 
						|
        bookmark1 = self.setup_bookmark(tags=[tag1, tag2], user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(tags=[tag1, tag2], user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(tags=[tag1, tag2], user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_untag"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_tag_string": [f"{tag1.name} {tag2.name}"],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        bookmark1.refresh_from_db()
 | 
						|
        bookmark2.refresh_from_db()
 | 
						|
        bookmark3.refresh_from_db()
 | 
						|
 | 
						|
        self.assertCountEqual(bookmark1.tags.all(), [tag1, tag2])
 | 
						|
        self.assertCountEqual(bookmark2.tags.all(), [tag1, tag2])
 | 
						|
        self.assertCountEqual(bookmark3.tags.all(), [tag1, tag2])
 | 
						|
 | 
						|
    def test_bulk_mark_as_read(self):
 | 
						|
        bookmark1 = self.setup_bookmark(unread=True)
 | 
						|
        bookmark2 = self.setup_bookmark(unread=True)
 | 
						|
        bookmark3 = self.setup_bookmark(unread=True)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_read"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark1.id).unread)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark2.id).unread)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark3.id).unread)
 | 
						|
 | 
						|
    def test_can_only_bulk_mark_as_read_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(unread=True, user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(unread=True, user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(unread=True, user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_read"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark1.id).unread)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark2.id).unread)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark3.id).unread)
 | 
						|
 | 
						|
    def test_bulk_mark_as_unread(self):
 | 
						|
        bookmark1 = self.setup_bookmark(unread=False)
 | 
						|
        bookmark2 = self.setup_bookmark(unread=False)
 | 
						|
        bookmark3 = self.setup_bookmark(unread=False)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_unread"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark1.id).unread)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark2.id).unread)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark3.id).unread)
 | 
						|
 | 
						|
    def test_can_only_bulk_mark_as_unread_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(unread=False, user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(unread=False, user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(unread=False, user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_unread"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark1.id).unread)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark2.id).unread)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark3.id).unread)
 | 
						|
 | 
						|
    def test_bulk_share(self):
 | 
						|
        bookmark1 = self.setup_bookmark(shared=False)
 | 
						|
        bookmark2 = self.setup_bookmark(shared=False)
 | 
						|
        bookmark3 = self.setup_bookmark(shared=False)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_share"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark1.id).shared)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark2.id).shared)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark3.id).shared)
 | 
						|
 | 
						|
    def test_can_only_bulk_share_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(shared=False, user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(shared=False, user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(shared=False, user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_share"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark1.id).shared)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark2.id).shared)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark3.id).shared)
 | 
						|
 | 
						|
    def test_bulk_unshare(self):
 | 
						|
        bookmark1 = self.setup_bookmark(shared=True)
 | 
						|
        bookmark2 = self.setup_bookmark(shared=True)
 | 
						|
        bookmark3 = self.setup_bookmark(shared=True)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_unshare"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark1.id).shared)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark2.id).shared)
 | 
						|
        self.assertFalse(Bookmark.objects.get(id=bookmark3.id).shared)
 | 
						|
 | 
						|
    def test_can_only_bulk_unshare_own_bookmarks(self):
 | 
						|
        other_user = User.objects.create_user(
 | 
						|
            "otheruser", "otheruser@example.com", "password123"
 | 
						|
        )
 | 
						|
        bookmark1 = self.setup_bookmark(shared=True, user=other_user)
 | 
						|
        bookmark2 = self.setup_bookmark(shared=True, user=other_user)
 | 
						|
        bookmark3 = self.setup_bookmark(shared=True, user=other_user)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_unshare"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark1.id).shared)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark2.id).shared)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark3.id).shared)
 | 
						|
 | 
						|
    def test_bulk_select_across(self):
 | 
						|
        bookmark1 = self.setup_bookmark()
 | 
						|
        bookmark2 = self.setup_bookmark()
 | 
						|
        bookmark3 = self.setup_bookmark()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_archive"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark1.id).is_archived)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark2.id).is_archived)
 | 
						|
        self.assertTrue(Bookmark.objects.get(id=bookmark3.id).is_archived)
 | 
						|
 | 
						|
    def test_bulk_select_across_ignores_page(self):
 | 
						|
        self.setup_numbered_bookmarks(100)
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action") + "?page=2",
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(0, Bookmark.objects.count())
 | 
						|
 | 
						|
    def setup_bulk_edit_scope_test_data(self):
 | 
						|
        # create a number of bookmarks with different states / visibility
 | 
						|
        self.setup_numbered_bookmarks(3, with_tags=True)
 | 
						|
        self.setup_numbered_bookmarks(3, with_tags=True, archived=True)
 | 
						|
        self.setup_numbered_bookmarks(
 | 
						|
            3,
 | 
						|
            shared=True,
 | 
						|
            prefix="Joe's Bookmark",
 | 
						|
            user=self.setup_user(enable_sharing=True),
 | 
						|
        )
 | 
						|
 | 
						|
    def test_index_action_bulk_select_across_only_affects_active_bookmarks(self):
 | 
						|
        self.setup_bulk_edit_scope_test_data()
 | 
						|
 | 
						|
        self.assertIsNotNone(Bookmark.objects.filter(title="Bookmark 1").first())
 | 
						|
        self.assertIsNotNone(Bookmark.objects.filter(title="Bookmark 2").first())
 | 
						|
        self.assertIsNotNone(Bookmark.objects.filter(title="Bookmark 3").first())
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(6, Bookmark.objects.count())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(title="Bookmark 1").first())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(title="Bookmark 2").first())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(title="Bookmark 3").first())
 | 
						|
 | 
						|
    def test_index_action_bulk_select_across_respects_query(self):
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="foo")
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="bar")
 | 
						|
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action") + "?q=foo",
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(0, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="bar").count())
 | 
						|
 | 
						|
    def test_index_action_bulk_select_across_respects_bundle(self):
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="foo")
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="bar")
 | 
						|
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
 | 
						|
        bundle = self.setup_bundle(search="foo")
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action") + f"?bundle={bundle.id}",
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(0, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="bar").count())
 | 
						|
 | 
						|
    def test_archived_action_bulk_select_across_only_affects_archived_bookmarks(self):
 | 
						|
        self.setup_bulk_edit_scope_test_data()
 | 
						|
 | 
						|
        self.assertIsNotNone(
 | 
						|
            Bookmark.objects.filter(title="Archived Bookmark 1").first()
 | 
						|
        )
 | 
						|
        self.assertIsNotNone(
 | 
						|
            Bookmark.objects.filter(title="Archived Bookmark 2").first()
 | 
						|
        )
 | 
						|
        self.assertIsNotNone(
 | 
						|
            Bookmark.objects.filter(title="Archived Bookmark 3").first()
 | 
						|
        )
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.archived.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(6, Bookmark.objects.count())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(title="Archived Bookmark 1").first())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(title="Archived Bookmark 2").first())
 | 
						|
        self.assertIsNone(Bookmark.objects.filter(title="Archived Bookmark 3").first())
 | 
						|
 | 
						|
    def test_archived_action_bulk_select_across_respects_query(self):
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="foo", archived=True)
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="bar", archived=True)
 | 
						|
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.archived.action") + "?q=foo",
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(0, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="bar").count())
 | 
						|
 | 
						|
    def test_archived_action_bulk_select_across_respects_bundle(self):
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="foo", archived=True)
 | 
						|
        self.setup_numbered_bookmarks(3, prefix="bar", archived=True)
 | 
						|
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
 | 
						|
        bundle = self.setup_bundle(search="foo")
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.archived.action") + f"?bundle={bundle.id}",
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertEqual(0, Bookmark.objects.filter(title__startswith="foo").count())
 | 
						|
        self.assertEqual(3, Bookmark.objects.filter(title__startswith="bar").count())
 | 
						|
 | 
						|
    def test_shared_action_bulk_select_across_not_supported(self):
 | 
						|
        self.setup_bulk_edit_scope_test_data()
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.shared.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_delete"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bulk_select_across": ["on"],
 | 
						|
            },
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 400)
 | 
						|
 | 
						|
    def test_handles_empty_bookmark_id(self):
 | 
						|
        bookmark1 = self.setup_bookmark()
 | 
						|
        bookmark2 = self.setup_bookmark()
 | 
						|
        bookmark3 = self.setup_bookmark()
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_archive"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
            },
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 302)
 | 
						|
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bulk_action": ["bulk_archive"],
 | 
						|
                "bulk_execute": [""],
 | 
						|
                "bookmark_id": [],
 | 
						|
            },
 | 
						|
        )
 | 
						|
        self.assertEqual(response.status_code, 302)
 | 
						|
 | 
						|
        self.assertBookmarksAreUnmodified([bookmark1, bookmark2, bookmark3])
 | 
						|
 | 
						|
    def test_empty_action_does_not_modify_bookmarks(self):
 | 
						|
        bookmark1 = self.setup_bookmark()
 | 
						|
        bookmark2 = self.setup_bookmark()
 | 
						|
        bookmark3 = self.setup_bookmark()
 | 
						|
 | 
						|
        self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            {
 | 
						|
                "bookmark_id": [
 | 
						|
                    str(bookmark1.id),
 | 
						|
                    str(bookmark2.id),
 | 
						|
                    str(bookmark3.id),
 | 
						|
                ],
 | 
						|
            },
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertBookmarksAreUnmodified([bookmark1, bookmark2, bookmark3])
 | 
						|
 | 
						|
    def test_index_action_redirects_to_index_with_query_params(self):
 | 
						|
        url = reverse("linkding:bookmarks.index.action") + "?q=foo&page=2"
 | 
						|
        redirect_url = reverse("linkding:bookmarks.index") + "?q=foo&page=2"
 | 
						|
        response = self.client.post(url)
 | 
						|
 | 
						|
        self.assertRedirects(response, redirect_url)
 | 
						|
 | 
						|
    def test_archived_action_redirects_to_archived_with_query_params(self):
 | 
						|
        url = reverse("linkding:bookmarks.archived.action") + "?q=foo&page=2"
 | 
						|
        redirect_url = reverse("linkding:bookmarks.archived") + "?q=foo&page=2"
 | 
						|
        response = self.client.post(url)
 | 
						|
 | 
						|
        self.assertRedirects(response, redirect_url)
 | 
						|
 | 
						|
    def test_shared_action_redirects_to_shared_with_query_params(self):
 | 
						|
        url = reverse("linkding:bookmarks.shared.action") + "?q=foo&page=2"
 | 
						|
        redirect_url = reverse("linkding:bookmarks.shared") + "?q=foo&page=2"
 | 
						|
        response = self.client.post(url)
 | 
						|
 | 
						|
        self.assertRedirects(response, redirect_url)
 | 
						|
 | 
						|
    def bookmark_update_fixture(self):
 | 
						|
        user = self.get_or_create_test_user()
 | 
						|
        profile = user.profile
 | 
						|
        profile.enable_sharing = True
 | 
						|
        profile.save()
 | 
						|
 | 
						|
        return {
 | 
						|
            "active": self.setup_numbered_bookmarks(3),
 | 
						|
            "archived": self.setup_numbered_bookmarks(3, archived=True),
 | 
						|
            "shared": self.setup_numbered_bookmarks(3, shared=True),
 | 
						|
        }
 | 
						|
 | 
						|
    def assertBookmarkUpdateResponse(self, response: HttpResponse):
 | 
						|
        self.assertEqual(response.status_code, 200)
 | 
						|
 | 
						|
        html = response.content.decode("utf-8")
 | 
						|
        soup = self.make_soup(html)
 | 
						|
 | 
						|
        # bookmark list update
 | 
						|
        self.assertIsNotNone(
 | 
						|
            soup.select_one(
 | 
						|
                "turbo-stream[action='update'][target='bookmark-list-container']"
 | 
						|
            )
 | 
						|
        )
 | 
						|
 | 
						|
        # tag cloud update
 | 
						|
        self.assertIsNotNone(
 | 
						|
            soup.select_one(
 | 
						|
                "turbo-stream[action='update'][target='tag-cloud-container']"
 | 
						|
            )
 | 
						|
        )
 | 
						|
 | 
						|
        # update event
 | 
						|
        self.assertInHTML(
 | 
						|
            """
 | 
						|
            <script>
 | 
						|
                document.dispatchEvent(new CustomEvent('bookmark-list-updated'));
 | 
						|
            </script>
 | 
						|
            """,
 | 
						|
            html,
 | 
						|
        )
 | 
						|
 | 
						|
    def test_index_action_with_turbo_returns_bookmark_update(self):
 | 
						|
        fixture = self.bookmark_update_fixture()
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.index.action"),
 | 
						|
            HTTP_ACCEPT="text/vnd.turbo-stream.html",
 | 
						|
        )
 | 
						|
 | 
						|
        visible_tags = self.get_tags_from_bookmarks(
 | 
						|
            fixture["active"] + fixture["shared"]
 | 
						|
        )
 | 
						|
        invisible_tags = self.get_tags_from_bookmarks(fixture["archived"])
 | 
						|
 | 
						|
        self.assertBookmarkUpdateResponse(response)
 | 
						|
        self.assertVisibleBookmarks(response, fixture["active"] + fixture["shared"])
 | 
						|
        self.assertInvisibleBookmarks(response, fixture["archived"])
 | 
						|
        self.assertVisibleTags(response, visible_tags)
 | 
						|
        self.assertInvisibleTags(response, invisible_tags)
 | 
						|
 | 
						|
    def test_archived_action_with_turbo_returns_bookmark_update(self):
 | 
						|
        fixture = self.bookmark_update_fixture()
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.archived.action"),
 | 
						|
            HTTP_ACCEPT="text/vnd.turbo-stream.html",
 | 
						|
        )
 | 
						|
 | 
						|
        visible_tags = self.get_tags_from_bookmarks(fixture["archived"])
 | 
						|
        invisible_tags = self.get_tags_from_bookmarks(
 | 
						|
            fixture["active"] + fixture["shared"]
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertBookmarkUpdateResponse(response)
 | 
						|
        self.assertVisibleBookmarks(response, fixture["archived"])
 | 
						|
        self.assertInvisibleBookmarks(response, fixture["active"] + fixture["shared"])
 | 
						|
        self.assertVisibleTags(response, visible_tags)
 | 
						|
        self.assertInvisibleTags(response, invisible_tags)
 | 
						|
 | 
						|
    def test_shared_action_with_turbo_returns_bookmark_update(self):
 | 
						|
        fixture = self.bookmark_update_fixture()
 | 
						|
        response = self.client.post(
 | 
						|
            reverse("linkding:bookmarks.shared.action"),
 | 
						|
            HTTP_ACCEPT="text/vnd.turbo-stream.html",
 | 
						|
        )
 | 
						|
 | 
						|
        visible_tags = self.get_tags_from_bookmarks(fixture["shared"])
 | 
						|
        invisible_tags = self.get_tags_from_bookmarks(
 | 
						|
            fixture["active"] + fixture["archived"]
 | 
						|
        )
 | 
						|
 | 
						|
        self.assertBookmarkUpdateResponse(response)
 | 
						|
        self.assertVisibleBookmarks(response, fixture["shared"])
 | 
						|
        self.assertInvisibleBookmarks(response, fixture["active"] + fixture["archived"])
 | 
						|
        self.assertVisibleTags(response, visible_tags)
 | 
						|
        self.assertInvisibleTags(response, invisible_tags)
 |