mirror of
https://github.com/sissbruecker/linkding.git
synced 2025-08-07 10:58:25 +02:00
Allow searching for tags without hash character (#449)
* Allow searching for tags without hash character * Allow removing selected tags without hash * Add more tests
This commit is contained in:
@@ -23,7 +23,7 @@ class BookmarkViewSet(viewsets.GenericViewSet,
|
|||||||
# For list action, use query set that applies search and tag projections
|
# For list action, use query set that applies search and tag projections
|
||||||
if self.action == 'list':
|
if self.action == 'list':
|
||||||
query_string = self.request.GET.get('q')
|
query_string = self.request.GET.get('q')
|
||||||
return queries.query_bookmarks(user, query_string)
|
return queries.query_bookmarks(user, user.profile, query_string)
|
||||||
|
|
||||||
# For single entity actions use default query set without projections
|
# For single entity actions use default query set without projections
|
||||||
return Bookmark.objects.all().filter(owner=user)
|
return Bookmark.objects.all().filter(owner=user)
|
||||||
@@ -35,7 +35,7 @@ class BookmarkViewSet(viewsets.GenericViewSet,
|
|||||||
def archived(self, request):
|
def archived(self, request):
|
||||||
user = request.user
|
user = request.user
|
||||||
query_string = request.GET.get('q')
|
query_string = request.GET.get('q')
|
||||||
query_set = queries.query_archived_bookmarks(user, query_string)
|
query_set = queries.query_archived_bookmarks(user, user.profile, query_string)
|
||||||
page = self.paginate_queryset(query_set)
|
page = self.paginate_queryset(query_set)
|
||||||
serializer = self.get_serializer_class()
|
serializer = self.get_serializer_class()
|
||||||
data = serializer(page, many=True).data
|
data = serializer(page, many=True).data
|
||||||
@@ -45,7 +45,7 @@ class BookmarkViewSet(viewsets.GenericViewSet,
|
|||||||
def shared(self, request):
|
def shared(self, request):
|
||||||
filters = BookmarkFilters(request)
|
filters = BookmarkFilters(request)
|
||||||
user = User.objects.filter(username=filters.user).first()
|
user = User.objects.filter(username=filters.user).first()
|
||||||
query_set = queries.query_shared_bookmarks(user, filters.query)
|
query_set = queries.query_shared_bookmarks(user, request.user.profile, filters.query)
|
||||||
page = self.paginate_queryset(query_set)
|
page = self.paginate_queryset(query_set)
|
||||||
serializer = self.get_serializer_class()
|
serializer = self.get_serializer_class()
|
||||||
data = serializer(page, many=True).data
|
data = serializer(page, many=True).data
|
||||||
|
@@ -18,7 +18,7 @@ class BaseBookmarksFeed(Feed):
|
|||||||
def get_object(self, request, feed_key: str):
|
def get_object(self, request, feed_key: str):
|
||||||
feed_token = FeedToken.objects.get(key__exact=feed_key)
|
feed_token = FeedToken.objects.get(key__exact=feed_key)
|
||||||
query_string = request.GET.get('q')
|
query_string = request.GET.get('q')
|
||||||
query_set = queries.query_bookmarks(feed_token.user, query_string)
|
query_set = queries.query_bookmarks(feed_token.user, feed_token.user.profile, query_string)
|
||||||
return FeedContext(feed_token, query_set)
|
return FeedContext(feed_token, query_set)
|
||||||
|
|
||||||
def item_title(self, item: Bookmark):
|
def item_title(self, item: Bookmark):
|
||||||
|
18
bookmarks/migrations/0020_userprofile_tag_search.py
Normal file
18
bookmarks/migrations/0020_userprofile_tag_search.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.1.7 on 2023-04-10 01:55
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bookmarks', '0019_userprofile_enable_favicons'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='userprofile',
|
||||||
|
name='tag_search',
|
||||||
|
field=models.CharField(choices=[('strict', 'Strict'), ('lax', 'Lax')], default='strict', max_length=10),
|
||||||
|
),
|
||||||
|
]
|
@@ -153,6 +153,12 @@ class UserProfile(models.Model):
|
|||||||
(WEB_ARCHIVE_INTEGRATION_DISABLED, 'Disabled'),
|
(WEB_ARCHIVE_INTEGRATION_DISABLED, 'Disabled'),
|
||||||
(WEB_ARCHIVE_INTEGRATION_ENABLED, 'Enabled'),
|
(WEB_ARCHIVE_INTEGRATION_ENABLED, 'Enabled'),
|
||||||
]
|
]
|
||||||
|
TAG_SEARCH_STRICT = 'strict'
|
||||||
|
TAG_SEARCH_LAX = 'lax'
|
||||||
|
TAG_SEARCH_CHOICES = [
|
||||||
|
(TAG_SEARCH_STRICT, 'Strict'),
|
||||||
|
(TAG_SEARCH_LAX, 'Lax'),
|
||||||
|
]
|
||||||
user = models.OneToOneField(get_user_model(), related_name='profile', on_delete=models.CASCADE)
|
user = models.OneToOneField(get_user_model(), related_name='profile', on_delete=models.CASCADE)
|
||||||
theme = models.CharField(max_length=10, choices=THEME_CHOICES, blank=False, default=THEME_AUTO)
|
theme = models.CharField(max_length=10, choices=THEME_CHOICES, blank=False, default=THEME_AUTO)
|
||||||
bookmark_date_display = models.CharField(max_length=10, choices=BOOKMARK_DATE_DISPLAY_CHOICES, blank=False,
|
bookmark_date_display = models.CharField(max_length=10, choices=BOOKMARK_DATE_DISPLAY_CHOICES, blank=False,
|
||||||
@@ -161,6 +167,8 @@ class UserProfile(models.Model):
|
|||||||
default=BOOKMARK_LINK_TARGET_BLANK)
|
default=BOOKMARK_LINK_TARGET_BLANK)
|
||||||
web_archive_integration = models.CharField(max_length=10, choices=WEB_ARCHIVE_INTEGRATION_CHOICES, blank=False,
|
web_archive_integration = models.CharField(max_length=10, choices=WEB_ARCHIVE_INTEGRATION_CHOICES, blank=False,
|
||||||
default=WEB_ARCHIVE_INTEGRATION_DISABLED)
|
default=WEB_ARCHIVE_INTEGRATION_DISABLED)
|
||||||
|
tag_search = models.CharField(max_length=10, choices=TAG_SEARCH_CHOICES, blank=False,
|
||||||
|
default=TAG_SEARCH_STRICT)
|
||||||
enable_sharing = models.BooleanField(default=False, null=False)
|
enable_sharing = models.BooleanField(default=False, null=False)
|
||||||
enable_favicons = models.BooleanField(default=False, null=False)
|
enable_favicons = models.BooleanField(default=False, null=False)
|
||||||
|
|
||||||
@@ -168,7 +176,8 @@ class UserProfile(models.Model):
|
|||||||
class UserProfileForm(forms.ModelForm):
|
class UserProfileForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = UserProfile
|
model = UserProfile
|
||||||
fields = ['theme', 'bookmark_date_display', 'bookmark_link_target', 'web_archive_integration', 'enable_sharing', 'enable_favicons']
|
fields = ['theme', 'bookmark_date_display', 'bookmark_link_target', 'web_archive_integration', 'tag_search',
|
||||||
|
'enable_sharing', 'enable_favicons']
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=get_user_model())
|
@receiver(post_save, sender=get_user_model())
|
||||||
|
@@ -1,29 +1,29 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db.models import Q, QuerySet
|
from django.db.models import Q, QuerySet, Exists, OuterRef
|
||||||
|
|
||||||
from bookmarks.models import Bookmark, Tag
|
from bookmarks.models import Bookmark, Tag, UserProfile
|
||||||
from bookmarks.utils import unique
|
from bookmarks.utils import unique
|
||||||
|
|
||||||
|
|
||||||
def query_bookmarks(user: User, query_string: str) -> QuerySet:
|
def query_bookmarks(user: User, profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
return _base_bookmarks_query(user, query_string) \
|
return _base_bookmarks_query(user, profile, query_string) \
|
||||||
.filter(is_archived=False)
|
.filter(is_archived=False)
|
||||||
|
|
||||||
|
|
||||||
def query_archived_bookmarks(user: User, query_string: str) -> QuerySet:
|
def query_archived_bookmarks(user: User, profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
return _base_bookmarks_query(user, query_string) \
|
return _base_bookmarks_query(user, profile, query_string) \
|
||||||
.filter(is_archived=True)
|
.filter(is_archived=True)
|
||||||
|
|
||||||
|
|
||||||
def query_shared_bookmarks(user: Optional[User], query_string: str) -> QuerySet:
|
def query_shared_bookmarks(user: Optional[User], profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
return _base_bookmarks_query(user, query_string) \
|
return _base_bookmarks_query(user, profile, query_string) \
|
||||||
.filter(shared=True) \
|
.filter(shared=True) \
|
||||||
.filter(owner__profile__enable_sharing=True)
|
.filter(owner__profile__enable_sharing=True)
|
||||||
|
|
||||||
|
|
||||||
def _base_bookmarks_query(user: Optional[User], query_string: str) -> QuerySet:
|
def _base_bookmarks_query(user: Optional[User], profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
query_set = Bookmark.objects
|
query_set = Bookmark.objects
|
||||||
|
|
||||||
# Filter for user
|
# Filter for user
|
||||||
@@ -35,13 +35,16 @@ def _base_bookmarks_query(user: Optional[User], query_string: str) -> QuerySet:
|
|||||||
|
|
||||||
# Filter for search terms and tags
|
# Filter for search terms and tags
|
||||||
for term in query['search_terms']:
|
for term in query['search_terms']:
|
||||||
query_set = query_set.filter(
|
conditions = Q(title__icontains=term) \
|
||||||
Q(title__icontains=term)
|
| Q(description__icontains=term) \
|
||||||
| Q(description__icontains=term)
|
| Q(website_title__icontains=term) \
|
||||||
| Q(website_title__icontains=term)
|
| Q(website_description__icontains=term) \
|
||||||
| Q(website_description__icontains=term)
|
| Q(url__icontains=term)
|
||||||
| Q(url__icontains=term)
|
|
||||||
)
|
if profile.tag_search == UserProfile.TAG_SEARCH_LAX:
|
||||||
|
conditions = conditions | Exists(Bookmark.objects.filter(id=OuterRef('id'), tags__name__iexact=term))
|
||||||
|
|
||||||
|
query_set = query_set.filter(conditions)
|
||||||
|
|
||||||
for tag_name in query['tag_names']:
|
for tag_name in query['tag_names']:
|
||||||
query_set = query_set.filter(
|
query_set = query_set.filter(
|
||||||
@@ -65,32 +68,32 @@ def _base_bookmarks_query(user: Optional[User], query_string: str) -> QuerySet:
|
|||||||
return query_set
|
return query_set
|
||||||
|
|
||||||
|
|
||||||
def query_bookmark_tags(user: User, query_string: str) -> QuerySet:
|
def query_bookmark_tags(user: User, profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
bookmarks_query = query_bookmarks(user, query_string)
|
bookmarks_query = query_bookmarks(user, profile, query_string)
|
||||||
|
|
||||||
query_set = Tag.objects.filter(bookmark__in=bookmarks_query)
|
query_set = Tag.objects.filter(bookmark__in=bookmarks_query)
|
||||||
|
|
||||||
return query_set.distinct()
|
return query_set.distinct()
|
||||||
|
|
||||||
|
|
||||||
def query_archived_bookmark_tags(user: User, query_string: str) -> QuerySet:
|
def query_archived_bookmark_tags(user: User, profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
bookmarks_query = query_archived_bookmarks(user, query_string)
|
bookmarks_query = query_archived_bookmarks(user, profile, query_string)
|
||||||
|
|
||||||
query_set = Tag.objects.filter(bookmark__in=bookmarks_query)
|
query_set = Tag.objects.filter(bookmark__in=bookmarks_query)
|
||||||
|
|
||||||
return query_set.distinct()
|
return query_set.distinct()
|
||||||
|
|
||||||
|
|
||||||
def query_shared_bookmark_tags(user: Optional[User], query_string: str) -> QuerySet:
|
def query_shared_bookmark_tags(user: Optional[User], profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
bookmarks_query = query_shared_bookmarks(user, query_string)
|
bookmarks_query = query_shared_bookmarks(user, profile, query_string)
|
||||||
|
|
||||||
query_set = Tag.objects.filter(bookmark__in=bookmarks_query)
|
query_set = Tag.objects.filter(bookmark__in=bookmarks_query)
|
||||||
|
|
||||||
return query_set.distinct()
|
return query_set.distinct()
|
||||||
|
|
||||||
|
|
||||||
def query_shared_bookmark_users(query_string: str) -> QuerySet:
|
def query_shared_bookmark_users(profile: UserProfile, query_string: str) -> QuerySet:
|
||||||
bookmarks_query = query_shared_bookmarks(None, query_string)
|
bookmarks_query = query_shared_bookmarks(None, profile, query_string)
|
||||||
|
|
||||||
query_set = User.objects.filter(bookmark__in=bookmarks_query)
|
query_set = User.objects.filter(bookmark__in=bookmarks_query)
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
{% if bookmark.tag_names %}
|
{% if bookmark.tag_names %}
|
||||||
<span>
|
<span>
|
||||||
{% for tag_name in bookmark.tag_names %}
|
{% for tag_name in bookmark.tag_names %}
|
||||||
<a href="?{% append_to_query_param q=tag_name|hash_tag %}">{{ tag_name|hash_tag }}</a>
|
<a href="?{% add_tag_to_query tag_name %}">{{ tag_name|hash_tag }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
{% if has_selected_tags %}
|
{% if has_selected_tags %}
|
||||||
<p class="selected-tags">
|
<p class="selected-tags">
|
||||||
{% for tag in selected_tags %}
|
{% for tag in selected_tags %}
|
||||||
<a href="?{% remove_from_query_param q=tag.name|hash_tag %}"
|
<a href="?{% remove_tag_from_query tag.name %}"
|
||||||
class="text-bold mr-2">
|
class="text-bold mr-2">
|
||||||
<span>-{{ tag.name }}</span>
|
<span>-{{ tag.name }}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -17,14 +17,14 @@
|
|||||||
{% for tag in group.tags %}
|
{% for tag in group.tags %}
|
||||||
{# Highlight first char of first tag in group #}
|
{# Highlight first char of first tag in group #}
|
||||||
{% if forloop.counter == 1 %}
|
{% if forloop.counter == 1 %}
|
||||||
<a href="?{% append_to_query_param q=tag.name|hash_tag %}"
|
<a href="?{% add_tag_to_query tag.name %}"
|
||||||
class="mr-2" data-is-tag-item>
|
class="mr-2" data-is-tag-item>
|
||||||
<span
|
<span
|
||||||
class="highlight-char">{{ tag.name|first_char }}</span><span>{{ tag.name|remaining_chars:1 }}</span>
|
class="highlight-char">{{ tag.name|first_char }}</span><span>{{ tag.name|remaining_chars:1 }}</span>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
{# Render remaining tags normally #}
|
{# Render remaining tags normally #}
|
||||||
<a href="?{% append_to_query_param q=tag.name|hash_tag %}"
|
<a href="?{% add_tag_to_query tag.name %}"
|
||||||
class="mr-2" data-is-tag-item>
|
class="mr-2" data-is-tag-item>
|
||||||
<span>{{ tag.name }}</span>
|
<span>{{ tag.name }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
@@ -36,6 +36,15 @@
|
|||||||
Whether to open bookmarks a new page or in the same page.
|
Whether to open bookmarks a new page or in the same page.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{ form.tag_search.id_for_label }}" class="form-label">Tag search</label>
|
||||||
|
{{ form.tag_search|add_class:"form-select col-2 col-sm-12" }}
|
||||||
|
<div class="form-input-hint">
|
||||||
|
In strict mode, tags must be prefixed with a hash character (#).
|
||||||
|
In lax mode, tags can also be searched without the hash character.
|
||||||
|
Note that tags without the hash character are indistinguishable from search terms, which means the search result will also include bookmarks where a search term matches otherwise.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="{{ form.enable_favicons.id_for_label }}" class="form-checkbox">
|
<label for="{{ form.enable_favicons.id_for_label }}" class="form-checkbox">
|
||||||
{{ form.enable_favicons }}
|
{{ form.enable_favicons }}
|
||||||
|
@@ -3,6 +3,7 @@ import re
|
|||||||
from django import template
|
from django import template
|
||||||
|
|
||||||
from bookmarks import utils
|
from bookmarks import utils
|
||||||
|
from bookmarks.models import UserProfile
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@@ -19,36 +20,39 @@ def update_query_string(context, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def append_to_query_param(context, **kwargs):
|
def add_tag_to_query(context, tag_name: str):
|
||||||
query = context.request.GET.copy()
|
params = context.request.GET.copy()
|
||||||
|
|
||||||
# Append to or create query param
|
# Append to or create query string
|
||||||
for key in kwargs:
|
if params.__contains__('q'):
|
||||||
if query.__contains__(key):
|
query_string = params.__getitem__('q') + ' '
|
||||||
value = query.__getitem__(key) + ' '
|
else:
|
||||||
else:
|
query_string = ''
|
||||||
value = ''
|
query_string = query_string + '#' + tag_name
|
||||||
value = value + kwargs[key]
|
params.__setitem__('q', query_string)
|
||||||
query.__setitem__(key, value)
|
|
||||||
|
|
||||||
return query.urlencode()
|
return params.urlencode()
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def remove_from_query_param(context, **kwargs):
|
def remove_tag_from_query(context, tag_name: str):
|
||||||
query = context.request.GET.copy()
|
params = context.request.GET.copy()
|
||||||
|
if params.__contains__('q'):
|
||||||
|
# Split query string into parts
|
||||||
|
query_string = params.__getitem__('q')
|
||||||
|
query_parts = query_string.split()
|
||||||
|
# Remove tag with hash
|
||||||
|
tag_name_with_hash = '#' + tag_name
|
||||||
|
query_parts = [part for part in query_parts if str.lower(part) != str.lower(tag_name_with_hash)]
|
||||||
|
# When using lax tag search, also remove tag without hash
|
||||||
|
profile = context.request.user.profile
|
||||||
|
if profile.tag_search == UserProfile.TAG_SEARCH_LAX:
|
||||||
|
query_parts = [part for part in query_parts if str.lower(part) != str.lower(tag_name)]
|
||||||
|
# Rebuild query string
|
||||||
|
query_string = ' '.join(query_parts)
|
||||||
|
params.__setitem__('q', query_string)
|
||||||
|
|
||||||
# Remove item from query param
|
return params.urlencode()
|
||||||
for key in kwargs:
|
|
||||||
if query.__contains__(key):
|
|
||||||
value = query.__getitem__(key)
|
|
||||||
parts = value.split()
|
|
||||||
part_to_remove = kwargs[key]
|
|
||||||
updated_parts = [part for part in parts if str.lower(part) != str.lower(part_to_remove)]
|
|
||||||
updated_value = ' '.join(updated_parts)
|
|
||||||
query.__setitem__(key, updated_value)
|
|
||||||
|
|
||||||
return query.urlencode()
|
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
|
@@ -158,6 +158,37 @@ class BookmarkArchivedViewTestCase(TestCase, BookmarkFactoryMixin, HtmlTestMixin
|
|||||||
|
|
||||||
self.assertSelectedTags(response, [tags[0], tags[1]])
|
self.assertSelectedTags(response, [tags[0], tags[1]])
|
||||||
|
|
||||||
|
def test_should_not_display_search_terms_from_query_as_selected_tags_in_strict_mode(self):
|
||||||
|
tags = [
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
]
|
||||||
|
self.setup_bookmark(title=tags[0].name, tags=tags, is_archived=True)
|
||||||
|
|
||||||
|
response = self.client.get(reverse('bookmarks:archived') + f'?q={tags[0].name}+%23{tags[1].name.upper()}')
|
||||||
|
|
||||||
|
self.assertSelectedTags(response, [tags[1]])
|
||||||
|
|
||||||
|
def test_should_display_search_terms_from_query_as_selected_tags_in_lax_mode(self):
|
||||||
|
self.user.profile.tag_search = UserProfile.TAG_SEARCH_LAX
|
||||||
|
self.user.profile.save()
|
||||||
|
|
||||||
|
tags = [
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
]
|
||||||
|
self.setup_bookmark(tags=tags, is_archived=True)
|
||||||
|
|
||||||
|
response = self.client.get(reverse('bookmarks:archived') + f'?q={tags[0].name}+%23{tags[1].name.upper()}')
|
||||||
|
|
||||||
|
self.assertSelectedTags(response, [tags[0], tags[1]])
|
||||||
|
|
||||||
def test_should_open_bookmarks_in_new_page_by_default(self):
|
def test_should_open_bookmarks_in_new_page_by_default(self):
|
||||||
visible_bookmarks = [
|
visible_bookmarks = [
|
||||||
self.setup_bookmark(is_archived=True),
|
self.setup_bookmark(is_archived=True),
|
||||||
|
@@ -155,7 +155,38 @@ class BookmarkIndexViewTestCase(TestCase, BookmarkFactoryMixin, HtmlTestMixin):
|
|||||||
]
|
]
|
||||||
self.setup_bookmark(tags=tags)
|
self.setup_bookmark(tags=tags)
|
||||||
|
|
||||||
response = self.client.get(reverse('bookmarks:index') + f'?q=%23{tags[0].name}+%23{tags[1].name}')
|
response = self.client.get(reverse('bookmarks:index') + f'?q=%23{tags[0].name}+%23{tags[1].name.upper()}')
|
||||||
|
|
||||||
|
self.assertSelectedTags(response, [tags[0], tags[1]])
|
||||||
|
|
||||||
|
def test_should_not_display_search_terms_from_query_as_selected_tags_in_strict_mode(self):
|
||||||
|
tags = [
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
]
|
||||||
|
self.setup_bookmark(title=tags[0].name, tags=tags)
|
||||||
|
|
||||||
|
response = self.client.get(reverse('bookmarks:index') + f'?q={tags[0].name}+%23{tags[1].name.upper()}')
|
||||||
|
|
||||||
|
self.assertSelectedTags(response, [tags[1]])
|
||||||
|
|
||||||
|
def test_should_display_search_terms_from_query_as_selected_tags_in_lax_mode(self):
|
||||||
|
self.user.profile.tag_search = UserProfile.TAG_SEARCH_LAX
|
||||||
|
self.user.profile.save()
|
||||||
|
|
||||||
|
tags = [
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
self.setup_tag(),
|
||||||
|
]
|
||||||
|
self.setup_bookmark(tags=tags)
|
||||||
|
|
||||||
|
response = self.client.get(reverse('bookmarks:index') + f'?q={tags[0].name}+%23{tags[1].name.upper()}')
|
||||||
|
|
||||||
self.assertSelectedTags(response, [tags[0], tags[1]])
|
self.assertSelectedTags(response, [tags[0], tags[1]])
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@ from django.db.models import QuerySet
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from bookmarks import queries
|
from bookmarks import queries
|
||||||
from bookmarks.models import Bookmark
|
from bookmarks.models import Bookmark, UserProfile
|
||||||
from bookmarks.tests.helpers import BookmarkFactoryMixin, random_sentence
|
from bookmarks.tests.helpers import BookmarkFactoryMixin, random_sentence
|
||||||
from bookmarks.utils import unique
|
from bookmarks.utils import unique
|
||||||
|
|
||||||
@@ -13,6 +13,8 @@ User = get_user_model()
|
|||||||
|
|
||||||
|
|
||||||
class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
|
def setUp(self):
|
||||||
|
self.profile = self.get_or_create_test_user().profile
|
||||||
|
|
||||||
def setup_bookmark_search_data(self) -> None:
|
def setup_bookmark_search_data(self) -> None:
|
||||||
tag1 = self.setup_tag(name='tag1')
|
tag1 = self.setup_tag(name='tag1')
|
||||||
@@ -53,6 +55,13 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(website_title=random_sentence(), tags=[tag1]),
|
self.setup_bookmark(website_title=random_sentence(), tags=[tag1]),
|
||||||
self.setup_bookmark(website_description=random_sentence(), tags=[tag1]),
|
self.setup_bookmark(website_description=random_sentence(), tags=[tag1]),
|
||||||
]
|
]
|
||||||
|
self.tag1_as_term_bookmarks = [
|
||||||
|
self.setup_bookmark(url='http://example.com/tag1'),
|
||||||
|
self.setup_bookmark(title=random_sentence(including_word='tag1')),
|
||||||
|
self.setup_bookmark(description=random_sentence(including_word='tag1')),
|
||||||
|
self.setup_bookmark(website_title=random_sentence(including_word='tag1')),
|
||||||
|
self.setup_bookmark(website_description=random_sentence(including_word='tag1')),
|
||||||
|
]
|
||||||
self.term1_tag1_bookmarks = [
|
self.term1_tag1_bookmarks = [
|
||||||
self.setup_bookmark(url='http://example.com/term1', tags=[tag1]),
|
self.setup_bookmark(url='http://example.com/term1', tags=[tag1]),
|
||||||
self.setup_bookmark(title=random_sentence(including_word='term1'), tags=[tag1]),
|
self.setup_bookmark(title=random_sentence(including_word='term1'), tags=[tag1]),
|
||||||
@@ -110,6 +119,13 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(website_title=random_sentence(), tags=[tag1, self.setup_tag()]),
|
self.setup_bookmark(website_title=random_sentence(), tags=[tag1, self.setup_tag()]),
|
||||||
self.setup_bookmark(website_description=random_sentence(), tags=[tag1, self.setup_tag()]),
|
self.setup_bookmark(website_description=random_sentence(), tags=[tag1, self.setup_tag()]),
|
||||||
]
|
]
|
||||||
|
self.tag1_as_term_bookmarks = [
|
||||||
|
self.setup_bookmark(url='http://example.com/tag1'),
|
||||||
|
self.setup_bookmark(title=random_sentence(including_word='tag1')),
|
||||||
|
self.setup_bookmark(description=random_sentence(including_word='tag1')),
|
||||||
|
self.setup_bookmark(website_title=random_sentence(including_word='tag1')),
|
||||||
|
self.setup_bookmark(website_description=random_sentence(including_word='tag1')),
|
||||||
|
]
|
||||||
self.term1_tag1_bookmarks = [
|
self.term1_tag1_bookmarks = [
|
||||||
self.setup_bookmark(url='http://example.com/term1', tags=[tag1, self.setup_tag()]),
|
self.setup_bookmark(url='http://example.com/term1', tags=[tag1, self.setup_tag()]),
|
||||||
self.setup_bookmark(title=random_sentence(including_word='term1'), tags=[tag1, self.setup_tag()]),
|
self.setup_bookmark(title=random_sentence(including_word='term1'), tags=[tag1, self.setup_tag()]),
|
||||||
@@ -143,12 +159,13 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmarks_should_return_all_for_empty_query(self):
|
def test_query_bookmarks_should_return_all_for_empty_query(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '')
|
query = queries.query_bookmarks(self.user, self.profile, '')
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.other_bookmarks,
|
self.other_bookmarks,
|
||||||
self.term1_bookmarks,
|
self.term1_bookmarks,
|
||||||
self.term1_term2_bookmarks,
|
self.term1_term2_bookmarks,
|
||||||
self.tag1_bookmarks,
|
self.tag1_bookmarks,
|
||||||
|
self.tag1_as_term_bookmarks,
|
||||||
self.term1_tag1_bookmarks,
|
self.term1_tag1_bookmarks,
|
||||||
self.tag2_bookmarks,
|
self.tag2_bookmarks,
|
||||||
self.tag1_tag2_bookmarks
|
self.tag1_tag2_bookmarks
|
||||||
@@ -157,7 +174,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmarks_should_search_single_term(self):
|
def test_query_bookmarks_should_search_single_term(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), 'term1')
|
query = queries.query_bookmarks(self.user, self.profile, 'term1')
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.term1_bookmarks,
|
self.term1_bookmarks,
|
||||||
self.term1_term2_bookmarks,
|
self.term1_term2_bookmarks,
|
||||||
@@ -167,63 +184,101 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmarks_should_search_multiple_terms(self):
|
def test_query_bookmarks_should_search_multiple_terms(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), 'term2 term1')
|
query = queries.query_bookmarks(self.user, self.profile, 'term2 term1')
|
||||||
|
|
||||||
self.assertQueryResult(query, [self.term1_term2_bookmarks])
|
self.assertQueryResult(query, [self.term1_term2_bookmarks])
|
||||||
|
|
||||||
def test_query_bookmarks_should_search_single_tag(self):
|
def test_query_bookmarks_should_search_single_tag(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '#tag1')
|
query = queries.query_bookmarks(self.user, self.profile, '#tag1')
|
||||||
|
|
||||||
self.assertQueryResult(query, [self.tag1_bookmarks, self.tag1_tag2_bookmarks, self.term1_tag1_bookmarks])
|
self.assertQueryResult(query, [self.tag1_bookmarks, self.tag1_tag2_bookmarks, self.term1_tag1_bookmarks])
|
||||||
|
|
||||||
def test_query_bookmarks_should_search_multiple_tags(self):
|
def test_query_bookmarks_should_search_multiple_tags(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '#tag1 #tag2')
|
query = queries.query_bookmarks(self.user, self.profile, '#tag1 #tag2')
|
||||||
|
|
||||||
self.assertQueryResult(query, [self.tag1_tag2_bookmarks])
|
self.assertQueryResult(query, [self.tag1_tag2_bookmarks])
|
||||||
|
|
||||||
def test_query_bookmarks_should_search_multiple_tags_ignoring_casing(self):
|
def test_query_bookmarks_should_search_multiple_tags_ignoring_casing(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '#Tag1 #TAG2')
|
query = queries.query_bookmarks(self.user, self.profile, '#Tag1 #TAG2')
|
||||||
|
|
||||||
self.assertQueryResult(query, [self.tag1_tag2_bookmarks])
|
self.assertQueryResult(query, [self.tag1_tag2_bookmarks])
|
||||||
|
|
||||||
def test_query_bookmarks_should_search_terms_and_tags_combined(self):
|
def test_query_bookmarks_should_search_terms_and_tags_combined(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), 'term1 #tag1')
|
query = queries.query_bookmarks(self.user, self.profile, 'term1 #tag1')
|
||||||
|
|
||||||
self.assertQueryResult(query, [self.term1_tag1_bookmarks])
|
self.assertQueryResult(query, [self.term1_tag1_bookmarks])
|
||||||
|
|
||||||
|
def test_query_bookmarks_in_strict_mode_should_not_search_tags_as_terms(self):
|
||||||
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
|
self.profile.tag_search = UserProfile.TAG_SEARCH_STRICT
|
||||||
|
self.profile.save()
|
||||||
|
|
||||||
|
query = queries.query_bookmarks(self.user, self.profile, 'tag1')
|
||||||
|
self.assertQueryResult(query, [self.tag1_as_term_bookmarks])
|
||||||
|
|
||||||
|
def test_query_bookmarks_in_lax_mode_should_search_tags_as_terms(self):
|
||||||
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
|
self.profile.tag_search = UserProfile.TAG_SEARCH_LAX
|
||||||
|
self.profile.save()
|
||||||
|
|
||||||
|
query = queries.query_bookmarks(self.user, self.profile, 'tag1')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.tag1_bookmarks,
|
||||||
|
self.tag1_as_term_bookmarks,
|
||||||
|
self.tag1_tag2_bookmarks,
|
||||||
|
self.term1_tag1_bookmarks
|
||||||
|
])
|
||||||
|
|
||||||
|
query = queries.query_bookmarks(self.user, self.profile, 'tag1 term1')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.term1_tag1_bookmarks,
|
||||||
|
])
|
||||||
|
|
||||||
|
query = queries.query_bookmarks(self.user, self.profile, 'tag1 tag2')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.tag1_tag2_bookmarks,
|
||||||
|
])
|
||||||
|
|
||||||
|
query = queries.query_bookmarks(self.user, self.profile, 'tag1 #tag2')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.tag1_tag2_bookmarks,
|
||||||
|
])
|
||||||
|
|
||||||
def test_query_bookmarks_should_return_no_matches(self):
|
def test_query_bookmarks_should_return_no_matches(self):
|
||||||
self.setup_bookmark_search_data()
|
self.setup_bookmark_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), 'term3')
|
query = queries.query_bookmarks(self.user, self.profile, 'term3')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), 'term1 term3')
|
query = queries.query_bookmarks(self.user, self.profile, 'term1 term3')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), 'term1 #tag2')
|
query = queries.query_bookmarks(self.user, self.profile, 'term1 #tag2')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '#tag3')
|
query = queries.query_bookmarks(self.user, self.profile, '#tag3')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
# Unused tag
|
# Unused tag
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '#unused_tag1')
|
query = queries.query_bookmarks(self.user, self.profile, '#unused_tag1')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
# Unused tag combined with tag that is used
|
# Unused tag combined with tag that is used
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '#tag1 #unused_tag1')
|
query = queries.query_bookmarks(self.user, self.profile, '#tag1 #unused_tag1')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
# Unused tag combined with term that is used
|
# Unused tag combined with term that is used
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), 'term1 #unused_tag1')
|
query = queries.query_bookmarks(self.user, self.profile, 'term1 #unused_tag1')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
def test_query_bookmarks_should_not_return_archived_bookmarks(self):
|
def test_query_bookmarks_should_not_return_archived_bookmarks(self):
|
||||||
@@ -233,7 +288,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True)
|
self.setup_bookmark(is_archived=True)
|
||||||
self.setup_bookmark(is_archived=True)
|
self.setup_bookmark(is_archived=True)
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.get_or_create_test_user(), '')
|
query = queries.query_bookmarks(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [[bookmark1, bookmark2]])
|
self.assertQueryResult(query, [[bookmark1, bookmark2]])
|
||||||
|
|
||||||
@@ -244,7 +299,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark()
|
self.setup_bookmark()
|
||||||
self.setup_bookmark()
|
self.setup_bookmark()
|
||||||
|
|
||||||
query = queries.query_archived_bookmarks(self.get_or_create_test_user(), '')
|
query = queries.query_archived_bookmarks(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [[bookmark1, bookmark2]])
|
self.assertQueryResult(query, [[bookmark1, bookmark2]])
|
||||||
|
|
||||||
@@ -259,7 +314,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(user=other_user)
|
self.setup_bookmark(user=other_user)
|
||||||
self.setup_bookmark(user=other_user)
|
self.setup_bookmark(user=other_user)
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.user, '')
|
query = queries.query_bookmarks(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [owned_bookmarks])
|
self.assertQueryResult(query, [owned_bookmarks])
|
||||||
|
|
||||||
@@ -274,7 +329,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True, user=other_user)
|
self.setup_bookmark(is_archived=True, user=other_user)
|
||||||
self.setup_bookmark(is_archived=True, user=other_user)
|
self.setup_bookmark(is_archived=True, user=other_user)
|
||||||
|
|
||||||
query = queries.query_archived_bookmarks(self.user, '')
|
query = queries.query_archived_bookmarks(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [owned_bookmarks])
|
self.assertQueryResult(query, [owned_bookmarks])
|
||||||
|
|
||||||
@@ -284,7 +339,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.user, '!untagged')
|
query = queries.query_bookmarks(self.user, self.profile, '!untagged')
|
||||||
self.assertCountEqual(list(query), [untagged_bookmark])
|
self.assertCountEqual(list(query), [untagged_bookmark])
|
||||||
|
|
||||||
def test_query_bookmarks_untagged_should_be_combinable_with_search_terms(self):
|
def test_query_bookmarks_untagged_should_be_combinable_with_search_terms(self):
|
||||||
@@ -293,7 +348,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(title='term2')
|
self.setup_bookmark(title='term2')
|
||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.user, '!untagged term1')
|
query = queries.query_bookmarks(self.user, self.profile, '!untagged term1')
|
||||||
self.assertCountEqual(list(query), [untagged_bookmark])
|
self.assertCountEqual(list(query), [untagged_bookmark])
|
||||||
|
|
||||||
def test_query_bookmarks_untagged_should_not_be_combinable_with_tags(self):
|
def test_query_bookmarks_untagged_should_not_be_combinable_with_tags(self):
|
||||||
@@ -302,7 +357,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.user, f'!untagged #{tag.name}')
|
query = queries.query_bookmarks(self.user, self.profile, f'!untagged #{tag.name}')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
def test_query_archived_bookmarks_untagged_should_return_untagged_bookmarks_only(self):
|
def test_query_archived_bookmarks_untagged_should_return_untagged_bookmarks_only(self):
|
||||||
@@ -311,7 +366,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
|
|
||||||
query = queries.query_archived_bookmarks(self.user, '!untagged')
|
query = queries.query_archived_bookmarks(self.user, self.profile, '!untagged')
|
||||||
self.assertCountEqual(list(query), [untagged_bookmark])
|
self.assertCountEqual(list(query), [untagged_bookmark])
|
||||||
|
|
||||||
def test_query_archived_bookmarks_untagged_should_be_combinable_with_search_terms(self):
|
def test_query_archived_bookmarks_untagged_should_be_combinable_with_search_terms(self):
|
||||||
@@ -320,7 +375,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True, title='term2')
|
self.setup_bookmark(is_archived=True, title='term2')
|
||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
|
|
||||||
query = queries.query_archived_bookmarks(self.user, '!untagged term1')
|
query = queries.query_archived_bookmarks(self.user, self.profile, '!untagged term1')
|
||||||
self.assertCountEqual(list(query), [untagged_bookmark])
|
self.assertCountEqual(list(query), [untagged_bookmark])
|
||||||
|
|
||||||
def test_query_archived_bookmarks_untagged_should_not_be_combinable_with_tags(self):
|
def test_query_archived_bookmarks_untagged_should_not_be_combinable_with_tags(self):
|
||||||
@@ -329,7 +384,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
|
|
||||||
query = queries.query_archived_bookmarks(self.user, f'!untagged #{tag.name}')
|
query = queries.query_archived_bookmarks(self.user, self.profile, f'!untagged #{tag.name}')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
def test_query_bookmarks_unread_should_return_unread_bookmarks_only(self):
|
def test_query_bookmarks_unread_should_return_unread_bookmarks_only(self):
|
||||||
@@ -342,7 +397,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark()
|
self.setup_bookmark()
|
||||||
self.setup_bookmark()
|
self.setup_bookmark()
|
||||||
|
|
||||||
query = queries.query_bookmarks(self.user, '!unread')
|
query = queries.query_bookmarks(self.user, self.profile, '!unread')
|
||||||
self.assertCountEqual(list(query), unread_bookmarks)
|
self.assertCountEqual(list(query), unread_bookmarks)
|
||||||
|
|
||||||
def test_query_archived_bookmarks_unread_should_return_unread_bookmarks_only(self):
|
def test_query_archived_bookmarks_unread_should_return_unread_bookmarks_only(self):
|
||||||
@@ -355,13 +410,13 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True)
|
self.setup_bookmark(is_archived=True)
|
||||||
self.setup_bookmark(is_archived=True)
|
self.setup_bookmark(is_archived=True)
|
||||||
|
|
||||||
query = queries.query_archived_bookmarks(self.user, '!unread')
|
query = queries.query_archived_bookmarks(self.user, self.profile, '!unread')
|
||||||
self.assertCountEqual(list(query), unread_bookmarks)
|
self.assertCountEqual(list(query), unread_bookmarks)
|
||||||
|
|
||||||
def test_query_bookmark_tags_should_return_all_tags_for_empty_query(self):
|
def test_query_bookmark_tags_should_return_all_tags_for_empty_query(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, '')
|
query = queries.query_bookmark_tags(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.get_tags_from_bookmarks(self.other_bookmarks),
|
self.get_tags_from_bookmarks(self.other_bookmarks),
|
||||||
@@ -376,7 +431,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmark_tags_should_search_single_term(self):
|
def test_query_bookmark_tags_should_search_single_term(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, 'term1')
|
query = queries.query_bookmark_tags(self.user, self.profile, 'term1')
|
||||||
|
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.get_tags_from_bookmarks(self.term1_bookmarks),
|
self.get_tags_from_bookmarks(self.term1_bookmarks),
|
||||||
@@ -387,7 +442,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmark_tags_should_search_multiple_terms(self):
|
def test_query_bookmark_tags_should_search_multiple_terms(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, 'term2 term1')
|
query = queries.query_bookmark_tags(self.user, self.profile, 'term2 term1')
|
||||||
|
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.get_tags_from_bookmarks(self.term1_term2_bookmarks),
|
self.get_tags_from_bookmarks(self.term1_term2_bookmarks),
|
||||||
@@ -396,7 +451,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmark_tags_should_search_single_tag(self):
|
def test_query_bookmark_tags_should_search_single_tag(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, '#tag1')
|
query = queries.query_bookmark_tags(self.user, self.profile, '#tag1')
|
||||||
|
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.get_tags_from_bookmarks(self.tag1_bookmarks),
|
self.get_tags_from_bookmarks(self.tag1_bookmarks),
|
||||||
@@ -407,7 +462,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmark_tags_should_search_multiple_tags(self):
|
def test_query_bookmark_tags_should_search_multiple_tags(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, '#tag1 #tag2')
|
query = queries.query_bookmark_tags(self.user, self.profile, '#tag1 #tag2')
|
||||||
|
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.get_tags_from_bookmarks(self.tag1_tag2_bookmarks),
|
self.get_tags_from_bookmarks(self.tag1_tag2_bookmarks),
|
||||||
@@ -416,7 +471,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmark_tags_should_search_multiple_tags_ignoring_casing(self):
|
def test_query_bookmark_tags_should_search_multiple_tags_ignoring_casing(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, '#Tag1 #TAG2')
|
query = queries.query_bookmark_tags(self.user, self.profile, '#Tag1 #TAG2')
|
||||||
|
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.get_tags_from_bookmarks(self.tag1_tag2_bookmarks),
|
self.get_tags_from_bookmarks(self.tag1_tag2_bookmarks),
|
||||||
@@ -425,37 +480,75 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
def test_query_bookmark_tags_should_search_term_and_tag_combined(self):
|
def test_query_bookmark_tags_should_search_term_and_tag_combined(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, 'term1 #tag1')
|
query = queries.query_bookmark_tags(self.user, self.profile, 'term1 #tag1')
|
||||||
|
|
||||||
self.assertQueryResult(query, [
|
self.assertQueryResult(query, [
|
||||||
self.get_tags_from_bookmarks(self.term1_tag1_bookmarks),
|
self.get_tags_from_bookmarks(self.term1_tag1_bookmarks),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_query_bookmark_tags_in_strict_mode_should_not_search_tags_as_terms(self):
|
||||||
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
|
self.profile.tag_search = UserProfile.TAG_SEARCH_STRICT
|
||||||
|
self.profile.save()
|
||||||
|
|
||||||
|
query = queries.query_bookmark_tags(self.user, self.profile, 'tag1')
|
||||||
|
self.assertQueryResult(query, self.get_tags_from_bookmarks(self.tag1_as_term_bookmarks))
|
||||||
|
|
||||||
|
def test_query_bookmark_tags_in_lax_mode_should_search_tags_as_terms(self):
|
||||||
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
|
self.profile.tag_search = UserProfile.TAG_SEARCH_LAX
|
||||||
|
self.profile.save()
|
||||||
|
|
||||||
|
query = queries.query_bookmark_tags(self.user, self.profile, 'tag1')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.get_tags_from_bookmarks(self.tag1_bookmarks),
|
||||||
|
self.get_tags_from_bookmarks(self.tag1_as_term_bookmarks),
|
||||||
|
self.get_tags_from_bookmarks(self.tag1_tag2_bookmarks),
|
||||||
|
self.get_tags_from_bookmarks(self.term1_tag1_bookmarks)
|
||||||
|
])
|
||||||
|
|
||||||
|
query = queries.query_bookmark_tags(self.user, self.profile, 'tag1 term1')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.get_tags_from_bookmarks(self.term1_tag1_bookmarks),
|
||||||
|
])
|
||||||
|
|
||||||
|
query = queries.query_bookmark_tags(self.user, self.profile, 'tag1 tag2')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.get_tags_from_bookmarks(self.tag1_tag2_bookmarks),
|
||||||
|
])
|
||||||
|
|
||||||
|
query = queries.query_bookmark_tags(self.user, self.profile, 'tag1 #tag2')
|
||||||
|
self.assertQueryResult(query, [
|
||||||
|
self.get_tags_from_bookmarks(self.tag1_tag2_bookmarks),
|
||||||
|
])
|
||||||
|
|
||||||
def test_query_bookmark_tags_should_return_no_matches(self):
|
def test_query_bookmark_tags_should_return_no_matches(self):
|
||||||
self.setup_tag_search_data()
|
self.setup_tag_search_data()
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), 'term3')
|
query = queries.query_bookmark_tags(self.user, self.profile, 'term3')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), 'term1 term3')
|
query = queries.query_bookmark_tags(self.user, self.profile, 'term1 term3')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), 'term1 #tag2')
|
query = queries.query_bookmark_tags(self.user, self.profile, 'term1 #tag2')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), '#tag3')
|
query = queries.query_bookmark_tags(self.user, self.profile, '#tag3')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
# Unused tag
|
# Unused tag
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), '#unused_tag1')
|
query = queries.query_bookmark_tags(self.user, self.profile, '#unused_tag1')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
# Unused tag combined with tag that is used
|
# Unused tag combined with tag that is used
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), '#tag1 #unused_tag1')
|
query = queries.query_bookmark_tags(self.user, self.profile, '#tag1 #unused_tag1')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
# Unused tag combined with term that is used
|
# Unused tag combined with term that is used
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), 'term1 #unused_tag1')
|
query = queries.query_bookmark_tags(self.user, self.profile, 'term1 #unused_tag1')
|
||||||
self.assertQueryResult(query, [])
|
self.assertQueryResult(query, [])
|
||||||
|
|
||||||
def test_query_bookmark_tags_should_return_tags_for_unarchived_bookmarks_only(self):
|
def test_query_bookmark_tags_should_return_tags_for_unarchived_bookmarks_only(self):
|
||||||
@@ -465,7 +558,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark()
|
self.setup_bookmark()
|
||||||
self.setup_bookmark(is_archived=True, tags=[tag2])
|
self.setup_bookmark(is_archived=True, tags=[tag2])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), '')
|
query = queries.query_bookmark_tags(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [[tag1]])
|
self.assertQueryResult(query, [[tag1]])
|
||||||
|
|
||||||
@@ -475,7 +568,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.get_or_create_test_user(), '')
|
query = queries.query_bookmark_tags(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [[tag]])
|
self.assertQueryResult(query, [[tag]])
|
||||||
|
|
||||||
@@ -486,7 +579,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark()
|
self.setup_bookmark()
|
||||||
self.setup_bookmark(is_archived=True, tags=[tag2])
|
self.setup_bookmark(is_archived=True, tags=[tag2])
|
||||||
|
|
||||||
query = queries.query_archived_bookmark_tags(self.get_or_create_test_user(), '')
|
query = queries.query_archived_bookmark_tags(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [[tag2]])
|
self.assertQueryResult(query, [[tag2]])
|
||||||
|
|
||||||
@@ -496,7 +589,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
|
|
||||||
query = queries.query_archived_bookmark_tags(self.get_or_create_test_user(), '')
|
query = queries.query_archived_bookmark_tags(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [[tag]])
|
self.assertQueryResult(query, [[tag]])
|
||||||
|
|
||||||
@@ -511,7 +604,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(user=other_user, tags=[self.setup_tag(user=other_user)])
|
self.setup_bookmark(user=other_user, tags=[self.setup_tag(user=other_user)])
|
||||||
self.setup_bookmark(user=other_user, tags=[self.setup_tag(user=other_user)])
|
self.setup_bookmark(user=other_user, tags=[self.setup_tag(user=other_user)])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, '')
|
query = queries.query_bookmark_tags(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [self.get_tags_from_bookmarks(owned_bookmarks)])
|
self.assertQueryResult(query, [self.get_tags_from_bookmarks(owned_bookmarks)])
|
||||||
|
|
||||||
@@ -526,7 +619,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True, user=other_user, tags=[self.setup_tag(user=other_user)])
|
self.setup_bookmark(is_archived=True, user=other_user, tags=[self.setup_tag(user=other_user)])
|
||||||
self.setup_bookmark(is_archived=True, user=other_user, tags=[self.setup_tag(user=other_user)])
|
self.setup_bookmark(is_archived=True, user=other_user, tags=[self.setup_tag(user=other_user)])
|
||||||
|
|
||||||
query = queries.query_archived_bookmark_tags(self.user, '')
|
query = queries.query_archived_bookmark_tags(self.user, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query, [self.get_tags_from_bookmarks(owned_bookmarks)])
|
self.assertQueryResult(query, [self.get_tags_from_bookmarks(owned_bookmarks)])
|
||||||
|
|
||||||
@@ -537,13 +630,13 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(title='term1', tags=[tag])
|
self.setup_bookmark(title='term1', tags=[tag])
|
||||||
self.setup_bookmark(tags=[tag])
|
self.setup_bookmark(tags=[tag])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, '!untagged')
|
query = queries.query_bookmark_tags(self.user, self.profile, '!untagged')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, '!untagged term1')
|
query = queries.query_bookmark_tags(self.user, self.profile, '!untagged term1')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
query = queries.query_bookmark_tags(self.user, f'!untagged #{tag.name}')
|
query = queries.query_bookmark_tags(self.user, self.profile, f'!untagged #{tag.name}')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
def test_query_archived_bookmark_tags_untagged_should_never_return_any_tags(self):
|
def test_query_archived_bookmark_tags_untagged_should_never_return_any_tags(self):
|
||||||
@@ -553,13 +646,13 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(is_archived=True, title='term1', tags=[tag])
|
self.setup_bookmark(is_archived=True, title='term1', tags=[tag])
|
||||||
self.setup_bookmark(is_archived=True, tags=[tag])
|
self.setup_bookmark(is_archived=True, tags=[tag])
|
||||||
|
|
||||||
query = queries.query_archived_bookmark_tags(self.user, '!untagged')
|
query = queries.query_archived_bookmark_tags(self.user, self.profile, '!untagged')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
query = queries.query_archived_bookmark_tags(self.user, '!untagged term1')
|
query = queries.query_archived_bookmark_tags(self.user, self.profile, '!untagged term1')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
query = queries.query_archived_bookmark_tags(self.user, f'!untagged #{tag.name}')
|
query = queries.query_archived_bookmark_tags(self.user, self.profile, f'!untagged #{tag.name}')
|
||||||
self.assertCountEqual(list(query), [])
|
self.assertCountEqual(list(query), [])
|
||||||
|
|
||||||
def test_query_shared_bookmarks(self):
|
def test_query_shared_bookmarks(self):
|
||||||
@@ -582,14 +675,14 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(user=user4, shared=True, tags=[tag]),
|
self.setup_bookmark(user=user4, shared=True, tags=[tag]),
|
||||||
|
|
||||||
# Should return shared bookmarks from all users
|
# Should return shared bookmarks from all users
|
||||||
query_set = queries.query_shared_bookmarks(None, '')
|
query_set = queries.query_shared_bookmarks(None, self.profile, '')
|
||||||
self.assertQueryResult(query_set, [shared_bookmarks])
|
self.assertQueryResult(query_set, [shared_bookmarks])
|
||||||
|
|
||||||
# Should respect search query
|
# Should respect search query
|
||||||
query_set = queries.query_shared_bookmarks(None, 'test title')
|
query_set = queries.query_shared_bookmarks(None, self.profile, 'test title')
|
||||||
self.assertQueryResult(query_set, [[shared_bookmarks[0]]])
|
self.assertQueryResult(query_set, [[shared_bookmarks[0]]])
|
||||||
|
|
||||||
query_set = queries.query_shared_bookmarks(None, '#' + tag.name)
|
query_set = queries.query_shared_bookmarks(None, self.profile, '#' + tag.name)
|
||||||
self.assertQueryResult(query_set, [[shared_bookmarks[2]]])
|
self.assertQueryResult(query_set, [[shared_bookmarks[2]]])
|
||||||
|
|
||||||
def test_query_shared_bookmark_tags(self):
|
def test_query_shared_bookmark_tags(self):
|
||||||
@@ -613,7 +706,7 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(user=user3, shared=False, tags=[self.setup_tag(user=user3)]),
|
self.setup_bookmark(user=user3, shared=False, tags=[self.setup_tag(user=user3)]),
|
||||||
self.setup_bookmark(user=user4, shared=True, tags=[self.setup_tag(user=user4)]),
|
self.setup_bookmark(user=user4, shared=True, tags=[self.setup_tag(user=user4)]),
|
||||||
|
|
||||||
query_set = queries.query_shared_bookmark_tags(None, '')
|
query_set = queries.query_shared_bookmark_tags(None, self.profile, '')
|
||||||
|
|
||||||
self.assertQueryResult(query_set, [shared_tags])
|
self.assertQueryResult(query_set, [shared_tags])
|
||||||
|
|
||||||
@@ -638,9 +731,9 @@ class QueriesTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.setup_bookmark(user=users_without_shared_bookmarks[2], shared=True),
|
self.setup_bookmark(user=users_without_shared_bookmarks[2], shared=True),
|
||||||
|
|
||||||
# Should return users with shared bookmarks
|
# Should return users with shared bookmarks
|
||||||
query_set = queries.query_shared_bookmark_users('')
|
query_set = queries.query_shared_bookmark_users(self.profile, '')
|
||||||
self.assertQueryResult(query_set, [users_with_shared_bookmarks])
|
self.assertQueryResult(query_set, [users_with_shared_bookmarks])
|
||||||
|
|
||||||
# Should respect search query
|
# Should respect search query
|
||||||
query_set = queries.query_shared_bookmark_users('test title')
|
query_set = queries.query_shared_bookmark_users(self.profile, 'test title')
|
||||||
self.assertQueryResult(query_set, [[users_with_shared_bookmarks[0]]])
|
self.assertQueryResult(query_set, [[users_with_shared_bookmarks[0]]])
|
||||||
|
@@ -28,6 +28,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
'web_archive_integration': UserProfile.WEB_ARCHIVE_INTEGRATION_DISABLED,
|
'web_archive_integration': UserProfile.WEB_ARCHIVE_INTEGRATION_DISABLED,
|
||||||
'enable_sharing': False,
|
'enable_sharing': False,
|
||||||
'enable_favicons': False,
|
'enable_favicons': False,
|
||||||
|
'tag_search': UserProfile.TAG_SEARCH_STRICT,
|
||||||
}
|
}
|
||||||
|
|
||||||
return {**form_data, **overrides}
|
return {**form_data, **overrides}
|
||||||
@@ -52,6 +53,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
'web_archive_integration': UserProfile.WEB_ARCHIVE_INTEGRATION_ENABLED,
|
'web_archive_integration': UserProfile.WEB_ARCHIVE_INTEGRATION_ENABLED,
|
||||||
'enable_sharing': True,
|
'enable_sharing': True,
|
||||||
'enable_favicons': True,
|
'enable_favicons': True,
|
||||||
|
'tag_search': UserProfile.TAG_SEARCH_LAX,
|
||||||
}
|
}
|
||||||
response = self.client.post(reverse('bookmarks:settings.general'), form_data)
|
response = self.client.post(reverse('bookmarks:settings.general'), form_data)
|
||||||
html = response.content.decode()
|
html = response.content.decode()
|
||||||
@@ -65,6 +67,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
|||||||
self.assertEqual(self.user.profile.web_archive_integration, form_data['web_archive_integration'])
|
self.assertEqual(self.user.profile.web_archive_integration, form_data['web_archive_integration'])
|
||||||
self.assertEqual(self.user.profile.enable_sharing, form_data['enable_sharing'])
|
self.assertEqual(self.user.profile.enable_sharing, form_data['enable_sharing'])
|
||||||
self.assertEqual(self.user.profile.enable_favicons, form_data['enable_favicons'])
|
self.assertEqual(self.user.profile.enable_favicons, form_data['enable_favicons'])
|
||||||
|
self.assertEqual(self.user.profile.tag_search, form_data['tag_search'])
|
||||||
self.assertInHTML('''
|
self.assertInHTML('''
|
||||||
<p class="form-input-hint">Profile updated</p>
|
<p class="form-input-hint">Profile updated</p>
|
||||||
''', html)
|
''', html)
|
||||||
|
@@ -3,7 +3,7 @@ from typing import List
|
|||||||
from django.template import Template, RequestContext
|
from django.template import Template, RequestContext
|
||||||
from django.test import TestCase, RequestFactory
|
from django.test import TestCase, RequestFactory
|
||||||
|
|
||||||
from bookmarks.models import Tag
|
from bookmarks.models import Tag, UserProfile
|
||||||
from bookmarks.tests.helpers import BookmarkFactoryMixin, HtmlTestMixin
|
from bookmarks.tests.helpers import BookmarkFactoryMixin, HtmlTestMixin
|
||||||
|
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ class TagCloudTagTest(TestCase, BookmarkFactoryMixin, HtmlTestMixin):
|
|||||||
|
|
||||||
rf = RequestFactory()
|
rf = RequestFactory()
|
||||||
request = rf.get(url)
|
request = rf.get(url)
|
||||||
|
request.user = self.get_or_create_test_user()
|
||||||
context = RequestContext(request, {
|
context = RequestContext(request, {
|
||||||
'request': request,
|
'request': request,
|
||||||
'tags': tags,
|
'tags': tags,
|
||||||
@@ -118,6 +119,36 @@ class TagCloudTagTest(TestCase, BookmarkFactoryMixin, HtmlTestMixin):
|
|||||||
</a>
|
</a>
|
||||||
''', rendered_template)
|
''', rendered_template)
|
||||||
|
|
||||||
|
def test_selected_tags_with_lax_tag_search(self):
|
||||||
|
profile = self.get_or_create_test_user().profile
|
||||||
|
profile.tag_search = UserProfile.TAG_SEARCH_LAX
|
||||||
|
profile.save()
|
||||||
|
|
||||||
|
tags = [
|
||||||
|
self.setup_tag(name='tag1'),
|
||||||
|
self.setup_tag(name='tag2'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Filter by tag name without hash
|
||||||
|
rendered_template = self.render_template(tags, tags, url='/test?q=tag1 %23tag2')
|
||||||
|
|
||||||
|
self.assertNumSelectedTags(rendered_template, 2)
|
||||||
|
|
||||||
|
# Tag name should still be removed from query string
|
||||||
|
self.assertInHTML('''
|
||||||
|
<a href="?q=%23tag2"
|
||||||
|
class="text-bold mr-2">
|
||||||
|
<span>-tag1</span>
|
||||||
|
</a>
|
||||||
|
''', rendered_template)
|
||||||
|
|
||||||
|
self.assertInHTML('''
|
||||||
|
<a href="?q=tag1"
|
||||||
|
class="text-bold mr-2">
|
||||||
|
<span>-tag2</span>
|
||||||
|
</a>
|
||||||
|
''', rendered_template)
|
||||||
|
|
||||||
def test_selected_tags_ignore_casing_when_removing_query_part(self):
|
def test_selected_tags_ignore_casing_when_removing_query_part(self):
|
||||||
tags = [
|
tags = [
|
||||||
self.setup_tag(name='TEST'),
|
self.setup_tag(name='TEST'),
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
@@ -9,7 +10,7 @@ from django.shortcuts import render
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from bookmarks import queries
|
from bookmarks import queries
|
||||||
from bookmarks.models import Bookmark, BookmarkForm, BookmarkFilters, User, Tag, build_tag_string
|
from bookmarks.models import Bookmark, BookmarkForm, BookmarkFilters, User, UserProfile, Tag, build_tag_string
|
||||||
from bookmarks.services.bookmarks import create_bookmark, update_bookmark, archive_bookmark, archive_bookmarks, \
|
from bookmarks.services.bookmarks import create_bookmark, update_bookmark, archive_bookmark, archive_bookmarks, \
|
||||||
unarchive_bookmark, unarchive_bookmarks, delete_bookmarks, tag_bookmarks, untag_bookmarks
|
unarchive_bookmark, unarchive_bookmarks, delete_bookmarks, tag_bookmarks, untag_bookmarks
|
||||||
from bookmarks.utils import get_safe_return_url
|
from bookmarks.utils import get_safe_return_url
|
||||||
@@ -20,8 +21,8 @@ _default_page_size = 30
|
|||||||
@login_required
|
@login_required
|
||||||
def index(request):
|
def index(request):
|
||||||
filters = BookmarkFilters(request)
|
filters = BookmarkFilters(request)
|
||||||
query_set = queries.query_bookmarks(request.user, filters.query)
|
query_set = queries.query_bookmarks(request.user, request.user.profile, filters.query)
|
||||||
tags = queries.query_bookmark_tags(request.user, filters.query)
|
tags = queries.query_bookmark_tags(request.user, request.user.profile, filters.query)
|
||||||
base_url = reverse('bookmarks:index')
|
base_url = reverse('bookmarks:index')
|
||||||
context = get_bookmark_view_context(request, filters, query_set, tags, base_url)
|
context = get_bookmark_view_context(request, filters, query_set, tags, base_url)
|
||||||
return render(request, 'bookmarks/index.html', context)
|
return render(request, 'bookmarks/index.html', context)
|
||||||
@@ -30,8 +31,8 @@ def index(request):
|
|||||||
@login_required
|
@login_required
|
||||||
def archived(request):
|
def archived(request):
|
||||||
filters = BookmarkFilters(request)
|
filters = BookmarkFilters(request)
|
||||||
query_set = queries.query_archived_bookmarks(request.user, filters.query)
|
query_set = queries.query_archived_bookmarks(request.user, request.user.profile, filters.query)
|
||||||
tags = queries.query_archived_bookmark_tags(request.user, filters.query)
|
tags = queries.query_archived_bookmark_tags(request.user, request.user.profile, filters.query)
|
||||||
base_url = reverse('bookmarks:archived')
|
base_url = reverse('bookmarks:archived')
|
||||||
context = get_bookmark_view_context(request, filters, query_set, tags, base_url)
|
context = get_bookmark_view_context(request, filters, query_set, tags, base_url)
|
||||||
return render(request, 'bookmarks/archive.html', context)
|
return render(request, 'bookmarks/archive.html', context)
|
||||||
@@ -41,27 +42,23 @@ def archived(request):
|
|||||||
def shared(request):
|
def shared(request):
|
||||||
filters = BookmarkFilters(request)
|
filters = BookmarkFilters(request)
|
||||||
user = User.objects.filter(username=filters.user).first()
|
user = User.objects.filter(username=filters.user).first()
|
||||||
query_set = queries.query_shared_bookmarks(user, filters.query)
|
query_set = queries.query_shared_bookmarks(user, request.user.profile, filters.query)
|
||||||
tags = queries.query_shared_bookmark_tags(user, filters.query)
|
tags = queries.query_shared_bookmark_tags(user, request.user.profile, filters.query)
|
||||||
users = queries.query_shared_bookmark_users(filters.query)
|
users = queries.query_shared_bookmark_users(request.user.profile, filters.query)
|
||||||
base_url = reverse('bookmarks:shared')
|
base_url = reverse('bookmarks:shared')
|
||||||
context = get_bookmark_view_context(request, filters, query_set, tags, base_url)
|
context = get_bookmark_view_context(request, filters, query_set, tags, base_url)
|
||||||
context['users'] = users
|
context['users'] = users
|
||||||
return render(request, 'bookmarks/shared.html', context)
|
return render(request, 'bookmarks/shared.html', context)
|
||||||
|
|
||||||
|
|
||||||
def _get_selected_tags(tags: QuerySet[Tag], query_string: str):
|
def _get_selected_tags(tags: List[Tag], query_string: str, profile: UserProfile):
|
||||||
parsed_query = queries.parse_query_string(query_string)
|
parsed_query = queries.parse_query_string(query_string)
|
||||||
tag_names = parsed_query['tag_names']
|
tag_names = parsed_query['tag_names']
|
||||||
|
if profile.tag_search == UserProfile.TAG_SEARCH_LAX:
|
||||||
|
tag_names = tag_names + parsed_query['search_terms']
|
||||||
|
tag_names = [tag_name.lower() for tag_name in tag_names]
|
||||||
|
|
||||||
if len(tag_names) == 0:
|
return [tag for tag in tags if tag.name.lower() in tag_names]
|
||||||
return []
|
|
||||||
|
|
||||||
condition = Q()
|
|
||||||
for tag_name in parsed_query['tag_names']:
|
|
||||||
condition = condition | Q(name__iexact=tag_name)
|
|
||||||
|
|
||||||
return list(tags.filter(condition))
|
|
||||||
|
|
||||||
|
|
||||||
def get_bookmark_view_context(request: WSGIRequest,
|
def get_bookmark_view_context(request: WSGIRequest,
|
||||||
@@ -72,7 +69,8 @@ def get_bookmark_view_context(request: WSGIRequest,
|
|||||||
page = request.GET.get('page')
|
page = request.GET.get('page')
|
||||||
paginator = Paginator(query_set, _default_page_size)
|
paginator = Paginator(query_set, _default_page_size)
|
||||||
bookmarks = paginator.get_page(page)
|
bookmarks = paginator.get_page(page)
|
||||||
selected_tags = _get_selected_tags(tags, filters.query)
|
tags = list(tags)
|
||||||
|
selected_tags = _get_selected_tags(tags, filters.query, request.user.profile)
|
||||||
# Prefetch related objects, this avoids n+1 queries when accessing fields in templates
|
# Prefetch related objects, this avoids n+1 queries when accessing fields in templates
|
||||||
prefetch_related_objects(bookmarks.object_list, 'owner', 'tags')
|
prefetch_related_objects(bookmarks.object_list, 'owner', 'tags')
|
||||||
return_url = generate_return_url(base_url, page, filters)
|
return_url = generate_return_url(base_url, page, filters)
|
||||||
|
@@ -141,7 +141,7 @@ def bookmark_import(request):
|
|||||||
def bookmark_export(request):
|
def bookmark_export(request):
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
try:
|
try:
|
||||||
bookmarks = list(query_bookmarks(request.user, ''))
|
bookmarks = list(query_bookmarks(request.user, request.user.profile, ''))
|
||||||
# Prefetch tags to prevent n+1 queries
|
# Prefetch tags to prevent n+1 queries
|
||||||
prefetch_related_objects(bookmarks, 'tags')
|
prefetch_related_objects(bookmarks, 'tags')
|
||||||
file_content = exporter.export_netscape_html(bookmarks)
|
file_content = exporter.export_netscape_html(bookmarks)
|
||||||
|
Reference in New Issue
Block a user