From 57742eb08fb0137611a4532c3bd9087a49a59e88 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 9 Nov 2020 17:55:32 +0100
Subject: [PATCH 1/2] logs: better queryset to search for logs (#48074)

---
 passerelle/views.py   | 13 +++++++++----
 tests/test_manager.py | 40 +++++++++++++++++++++++++++++++++-------
 2 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/passerelle/views.py b/passerelle/views.py
index caa54334..052bb74e 100644
--- a/passerelle/views.py
+++ b/passerelle/views.py
@@ -27,8 +27,7 @@ from django.core.exceptions import PermissionDenied
 from django.contrib.auth import logout as auth_logout
 from django.contrib.auth import views as auth_views
 from django.db import transaction
-from django.db.models import TextField, Q
-from django.db.models.functions import Cast
+from django.db.models import Case, Value, When, BooleanField
 from django.http import HttpResponse, HttpResponseRedirect, Http404
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import (
@@ -250,8 +249,14 @@ class GenericViewLogsConnectorView(GenericConnectorMixin, ListView):
                 date = date_parser.parse(query, dayfirst=True)
             except Exception:
                 qs = qs.annotate(
-                    text_extra=Cast('extra', TextField())
-                ).filter(Q(text_extra__icontains=query) | Q(message__icontains=query))
+                    match=Case(
+                        When(extra__transaction_id=query, then=Value(True)),
+                        When(message__icontains=query, then=Value(True)),
+                        When(extra__icontains=query, then=Value(True)),
+                        default=False,
+                        output_field=BooleanField()
+                    )
+                ).filter(match=True)
             else:
                 date = make_aware(date)
                 if date.hour == 0 and date.minute == 0 and date.second == 0:
diff --git a/tests/test_manager.py b/tests/test_manager.py
index f1785882..140cdf86 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -1,5 +1,6 @@
 import datetime
 import re
+import uuid
 
 from webtest import Upload
 
@@ -247,22 +248,47 @@ def test_logs(app, admin_user):
     assert 'title="Level 42 - Oct. 6, 2020 14:08:12"' in resp.text
 
 
-def test_logs_search_in_message(app, admin_user):
+def test_logs_search(app, admin_user):
     csv = CsvDataSource.objects.create(csv_file=File(StringIO('1;t\n'), 't.csv'), slug='t', title='t')
     app = login(app)
 
-    ResourceLog.objects.create(appname=csv.get_connector_slug(), slug=csv.slug, levelno=1, message='hop')
-    resp = app.get(csv.get_absolute_url())
-    resp = resp.click('full page')
-    assert resp.text.count('<td class="timestamp">') == 1
+    transaction_id = str(uuid.uuid4())
+    log1 = ResourceLog.objects.create(
+        appname=csv.get_connector_slug(), slug=csv.slug, levelno=1, message='hop',
+        extra={'transaction_id': transaction_id, 'foo': 'plop'})
+    log2 = ResourceLog.objects.create(
+        appname=csv.get_connector_slug(), slug=csv.slug, levelno=1, message='plop',
+        extra={'transaction_id': transaction_id, 'bar': 'hop'})
+    log3 = ResourceLog.objects.create(
+        appname=csv.get_connector_slug(), slug=csv.slug, levelno=1, message='foo',
+        extra={'bar': 'hop'})
+
+    resp = app.get('/manage/csvdatasource/t/logs/')
+    assert list(resp.context['page_obj'].object_list) == [log3, log2, log1]
+
+    resp.form['q'] = transaction_id
+    resp = resp.form.submit()
+    assert list(resp.context['page_obj'].object_list) == [log2, log1]
+
+    resp.form['q'] = str(uuid.uuid4())
+    resp = resp.form.submit()
+    assert list(resp.context['page_obj'].object_list) == []
 
     resp.form['q'] = 'not there'
     resp = resp.form.submit()
-    assert resp.text.count('<td class="timestamp">') == 0
+    assert list(resp.context['page_obj'].object_list) == []
 
     resp.form['q'] = 'hop'
     resp = resp.form.submit()
-    assert resp.text.count('<td class="timestamp">') == 1
+    assert list(resp.context['page_obj'].object_list) == [log3, log2, log1]
+
+    resp.form['q'] = 'plop'
+    resp = resp.form.submit()
+    assert list(resp.context['page_obj'].object_list) == [log2, log1]
+
+    resp.form['q'] = 'foo'
+    resp = resp.form.submit()
+    assert list(resp.context['page_obj'].object_list) == [log3, log1]
 
 
 def test_logging_parameters(app, admin_user):
-- 
2.28.0

