Add bundles for organizing bookmarks (#1097)

* 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
This commit is contained in:
Sascha Ißbrücker
2025-06-19 16:47:29 +02:00
committed by GitHub
parent 8be72a5d1f
commit 1672dc0152
59 changed files with 2290 additions and 267 deletions

View File

@@ -0,0 +1,50 @@
from django.urls import reverse
from playwright.sync_api import sync_playwright, expect
from bookmarks.tests_e2e.helpers import LinkdingE2ETestCase
class BookmarkItemE2ETestCase(LinkdingE2ETestCase):
def test_update_preview_on_filter_changes(self):
group1 = self.setup_numbered_bookmarks(3, prefix="foo")
group2 = self.setup_numbered_bookmarks(3, prefix="bar")
with sync_playwright() as p:
# shows all bookmarks initially
page = self.open(reverse("linkding:bundles.new"), p)
expect(
page.get_by_text(f"Found 6 bookmarks matching this bundle")
).to_be_visible()
self.assertVisibleBookmarks(group1 + group2)
# filter by group1
search = page.get_by_label("Search")
search.fill("foo")
expect(
page.get_by_text(f"Found 3 bookmarks matching this bundle")
).to_be_visible()
self.assertVisibleBookmarks(group1)
# filter by group2
search.fill("bar")
expect(
page.get_by_text(f"Found 3 bookmarks matching this bundle")
).to_be_visible()
self.assertVisibleBookmarks(group2)
# filter by invalid group
search.fill("invalid")
expect(
page.get_by_text(f"No bookmarks match the current bundle")
).to_be_visible()
self.assertVisibleBookmarks([])
def assertVisibleBookmarks(self, bookmarks):
self.assertEqual(len(bookmarks), self.count_bookmarks())
for bookmark in bookmarks:
expect(self.locate_bookmark(bookmark.title)).to_be_visible()

View File

@@ -49,6 +49,10 @@ class LinkdingE2ETestCase(LiveServerTestCase, BookmarkFactoryMixin):
bookmark_tags = self.page.locator("li[ld-bookmark-item]")
return bookmark_tags.filter(has_text=title)
def count_bookmarks(self):
bookmark_tags = self.page.locator("li[ld-bookmark-item]")
return bookmark_tags.count()
def locate_details_modal(self):
return self.page.locator(".modal.bookmark-details")