feat: Use case-insensitive matching for document searches (#5166)

* fix: Use case insensitive match for group acronym in doc search

* fix: Use case insensitive match for doc.search_by_name view

* fix: Use case insensitive match for doc names in ipr.search view

* test: Test case insensitivity in doc search/search_for_name
This commit is contained in:
Jennifer Richards 2023-02-21 12:21:29 -04:00 committed by GitHub
parent c38ade6e1b
commit dcdc4af3e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 6 deletions

View file

@ -93,6 +93,10 @@ class SearchTests(TestCase):
self.assertEqual(r.status_code, 200)
self.assertContains(r, "draft-foo-mars-test")
r = self.client.get(base_url + "?olddrafts=on&name=FoO") # mixed case
self.assertEqual(r.status_code, 200)
self.assertContains(r, "draft-foo-mars-test")
# find by rfc/active/inactive
draft.set_state(State.objects.get(type="draft", slug="rfc"))
r = self.client.get(base_url + "?rfcs=on&name=%s" % draft.name)
@ -126,6 +130,10 @@ class SearchTests(TestCase):
self.assertEqual(r.status_code, 200)
self.assertContains(r, draft.title)
r = self.client.get(base_url + "?activedrafts=on&by=group&group=%s" % draft.group.acronym.swapcase())
self.assertEqual(r.status_code, 200)
self.assertContains(r, draft.title)
# find by area
r = self.client.get(base_url + "?activedrafts=on&by=area&area=%s" % draft.group.parent_id)
self.assertEqual(r.status_code, 200)
@ -167,16 +175,39 @@ class SearchTests(TestCase):
self.assertEqual(r.status_code, 302)
self.assertEqual(urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
# mixed-up case exact match
r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name=draft.name.swapcase())))
self.assertEqual(r.status_code, 302)
self.assertEqual(urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
# prefix match
r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(draft.name.split("-")[:-1]))))
self.assertEqual(r.status_code, 302)
self.assertEqual(urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
# mixed-up case prefix match
r = self.client.get(
urlreverse(
'ietf.doc.views_search.search_for_name',
kwargs=dict(name="-".join(draft.name.swapcase().split("-")[:-1])),
))
self.assertEqual(r.status_code, 302)
self.assertEqual(urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
# non-prefix match
r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name="-".join(draft.name.split("-")[1:]))))
self.assertEqual(r.status_code, 302)
self.assertEqual(urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
# mixed-up case non-prefix match
r = self.client.get(
urlreverse(
'ietf.doc.views_search.search_for_name',
kwargs=dict(name="-".join(draft.name.swapcase().split("-")[1:])),
))
self.assertEqual(r.status_code, 302)
self.assertEqual(urlparse(r["Location"]).path, urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name)))
# other doctypes than drafts
doc = Document.objects.get(name='charter-ietf-mars')
r = self.client.get(urlreverse('ietf.doc.views_search.search_for_name', kwargs=dict(name='charter-ietf-ma')))

View file

@ -188,7 +188,7 @@ def retrieve_search_results(form, all_types=False):
Q(documentauthor__person__email__address__icontains=query["author"])
)
elif by == "group":
docs = docs.filter(group__acronym=query["group"])
docs = docs.filter(group__acronym__iexact=query["group"])
elif by == "area":
docs = docs.filter(Q(group__type="wg", group__parent=query["area"]) |
Q(group=query["area"])).distinct()
@ -245,15 +245,15 @@ def frontpage(request):
def search_for_name(request, name):
def find_unique(n):
exact = DocAlias.objects.filter(name=n).first()
exact = DocAlias.objects.filter(name__iexact=n).first()
if exact:
return exact.name
aliases = DocAlias.objects.filter(name__startswith=n)[:2]
aliases = DocAlias.objects.filter(name__istartswith=n)[:2]
if len(aliases) == 1:
return aliases[0].name
aliases = DocAlias.objects.filter(name__contains=n)[:2]
aliases = DocAlias.objects.filter(name__icontains=n)[:2]
if len(aliases) == 1:
return aliases[0].name

View file

@ -147,10 +147,18 @@ class IprTests(TestCase):
r = self.client.get(url + "?submit=draft&id=%s" % draft.name)
self.assertContains(r, ipr.title)
# find by id, mixed case letters
r = self.client.get(url + "?submit=draft&id=%s" % draft.name.swapcase())
self.assertContains(r, ipr.title)
# find draft
r = self.client.get(url + "?submit=draft&draft=%s" % draft.name)
self.assertContains(r, ipr.title)
# find draft, mixed case letters
r = self.client.get(url + "?submit=draft&draft=%s" % draft.name.swapcase())
self.assertContains(r, ipr.title)
# search + select document
r = self.client.get(url + "?submit=draft&draft=draft")
self.assertContains(r, draft.name)

View file

@ -663,11 +663,11 @@ def search(request):
doc = q
if docid:
start = DocAlias.objects.filter(name=docid)
start = DocAlias.objects.filter(name__iexact=docid)
else:
if search_type == "draft":
q = normalize_draftname(q)
start = DocAlias.objects.filter(name__contains=q, name__startswith="draft")
start = DocAlias.objects.filter(name__icontains=q, name__startswith="draft")
elif search_type == "rfc":
start = DocAlias.objects.filter(name="rfc%s" % q.lstrip("0"))