Permalink
Browse files

Fix #1499: queries search should be case insensitive

  • Loading branch information...
1 parent 589634b commit c900e83bd9dba47cbf74e519bc3c729c2141ae91 @arikfr arikfr committed Jan 2, 2017
Showing with 161 additions and 153 deletions.
  1. +2 −2 redash/models.py
  2. +159 −2 tests/models/test_queries.py
  3. +0 −149 tests/test_models.py
View
@@ -789,8 +789,8 @@ def outdated_queries(cls):
@classmethod
def search(cls, term, group_ids):
# TODO: This is very naive implementation of search, to be replaced with PostgreSQL full-text-search solution.
- where = (Query.name.like(u"%{}%".format(term)) |
- Query.description.like(u"%{}%".format(term)))
+ where = (Query.name.ilike(u"%{}%".format(term)) |
+ Query.description.ilike(u"%{}%".format(term)))
if term.isdigit():
where |= Query.id == term
@@ -1,5 +1,163 @@
+# encoding: utf8
+
from tests import BaseTestCase
-from redash.models import Query, db
+import datetime
+from redash.models import Query, Group, Event, db
+from redash.utils import utcnow
+
+
+class QueryTest(BaseTestCase):
+ def test_changing_query_text_changes_hash(self):
+ q = self.factory.create_query()
+ old_hash = q.query_hash
+
+ q.query_text = "SELECT 2;"
+ db.session.flush()
+ self.assertNotEquals(old_hash, q.query_hash)
+
+ def test_search_finds_in_name(self):
+ q1 = self.factory.create_query(name=u"Testing seåřċħ")
+ q2 = self.factory.create_query(name=u"Testing seåřċħing")
+ q3 = self.factory.create_query(name=u"Testing seå řċħ")
+ queries = list(Query.search(u"seåřċħ", [self.factory.default_group.id]))
+
+ self.assertIn(q1, queries)
+ self.assertIn(q2, queries)
+ self.assertNotIn(q3, queries)
+
+ def test_search_finds_in_description(self):
+ q1 = self.factory.create_query(description=u"Testing seåřċħ")
+ q2 = self.factory.create_query(description=u"Testing seåřċħing")
+ q3 = self.factory.create_query(description=u"Testing seå řċħ")
+
+ queries = Query.search(u"seåřċħ", [self.factory.default_group.id])
+
+ self.assertIn(q1, queries)
+ self.assertIn(q2, queries)
+ self.assertNotIn(q3, queries)
+
+ def test_search_by_id_returns_query(self):
+ q1 = self.factory.create_query(description="Testing search")
+ q2 = self.factory.create_query(description="Testing searching")
+ q3 = self.factory.create_query(description="Testing sea rch")
+ db.session.flush()
+ queries = Query.search(str(q3.id), [self.factory.default_group.id])
+
+ self.assertIn(q3, queries)
+ self.assertNotIn(q1, queries)
+ self.assertNotIn(q2, queries)
+
+ def test_search_respects_groups(self):
+ other_group = Group(org=self.factory.org, name="Other Group")
+ db.session.add(other_group)
+ ds = self.factory.create_data_source(group=other_group)
+
+ q1 = self.factory.create_query(description="Testing search", data_source=ds)
+ q2 = self.factory.create_query(description="Testing searching")
+ q3 = self.factory.create_query(description="Testing sea rch")
+
+ queries = list(Query.search("Testing", [self.factory.default_group.id]))
+
+ self.assertNotIn(q1, queries)
+ self.assertIn(q2, queries)
+ self.assertIn(q3, queries)
+
+ queries = list(Query.search("Testing", [other_group.id, self.factory.default_group.id]))
+ self.assertIn(q1, queries)
+ self.assertIn(q2, queries)
+ self.assertIn(q3, queries)
+
+ queries = list(Query.search("Testing", [other_group.id]))
+ self.assertIn(q1, queries)
+ self.assertNotIn(q2, queries)
+ self.assertNotIn(q3, queries)
+
+ def test_returns_each_query_only_once(self):
+ other_group = self.factory.create_group()
+ second_group = self.factory.create_group()
+ ds = self.factory.create_data_source(group=other_group)
+ ds.add_group(second_group, False)
+
+ q1 = self.factory.create_query(description="Testing search", data_source=ds)
+ db.session.flush()
+ queries = list(Query.search("Testing", [self.factory.default_group.id, other_group.id, second_group.id]))
+
+ self.assertEqual(1, len(queries))
+
+ def test_save_updates_updated_at_field(self):
+ # This should be a test of ModelTimestampsMixin, but it's easier to test in context of existing model... :-\
+ one_day_ago = utcnow().date() - datetime.timedelta(days=1)
+ q = self.factory.create_query(created_at=one_day_ago, updated_at=one_day_ago)
+ db.session.flush()
+ q.name = 'x'
+ db.session.flush()
+ self.assertNotEqual(q.updated_at, one_day_ago)
+
+ def test_search_is_case_insensitive(self):
+ q = self.factory.create_query(name="Testing search")
+
+ self.assertIn(q, Query.search('testing', [self.factory.default_group.id]))
+
+
+class QueryRecentTest(BaseTestCase):
+ def test_global_recent(self):
+ q1 = self.factory.create_query()
+ q2 = self.factory.create_query()
+ db.session.flush()
+ e = Event(org=self.factory.org, user=self.factory.user, action="edit",
+ object_type="query", object_id=q1.id)
+ db.session.add(e)
+ recent = Query.recent([self.factory.default_group.id])
+ self.assertIn(q1, recent)
+ self.assertNotIn(q2, recent)
+
+ def test_recent_excludes_drafts(self):
+ q1 = self.factory.create_query()
+ q2 = self.factory.create_query(is_draft=True)
+
+ db.session.add_all([
+ Event(org=self.factory.org, user=self.factory.user,
+ action="edit", object_type="query",
+ object_id=q1.id),
+ Event(org=self.factory.org, user=self.factory.user,
+ action="edit", object_type="query",
+ object_id=q2.id)
+ ])
+ recent = Query.recent([self.factory.default_group.id])
+
+ self.assertIn(q1, recent)
+ self.assertNotIn(q2, recent)
+
+ def test_recent_for_user(self):
+ q1 = self.factory.create_query()
+ q2 = self.factory.create_query()
+ db.session.flush()
+ e = Event(org=self.factory.org, user=self.factory.user, action="edit",
+ object_type="query", object_id=q1.id)
+ db.session.add(e)
+ recent = Query.recent([self.factory.default_group.id], user_id=self.factory.user.id)
+
+ self.assertIn(q1, recent)
+ self.assertNotIn(q2, recent)
+
+ recent = Query.recent([self.factory.default_group.id], user_id=self.factory.user.id + 1)
+ self.assertNotIn(q1, recent)
+ self.assertNotIn(q2, recent)
+
+ def test_respects_groups(self):
+ q1 = self.factory.create_query()
+ ds = self.factory.create_data_source(group=self.factory.create_group())
+ q2 = self.factory.create_query(data_source=ds)
+ db.session.flush()
+ Event(org=self.factory.org, user=self.factory.user, action="edit",
+ object_type="query", object_id=q1.id)
+ Event(org=self.factory.org, user=self.factory.user, action="edit",
+ object_type="query", object_id=q2.id)
+
+ recent = Query.recent([self.factory.default_group.id])
+
+ self.assertIn(q1, recent)
+ self.assertNotIn(q2, recent)
class TestQueryByUser(BaseTestCase):
@@ -42,7 +200,6 @@ def assert_visualizations(self, origin_q, origin_v, forked_q, forked_v):
self.assertNotEqual(origin_v.query_rel, forked_v.query_rel)
self.assertEqual(forked_q.id, forked_v.query_rel.id)
-
def test_fork_with_visualizations(self):
# prepare original query and visualizations
data_source = self.factory.create_data_source(
View
@@ -26,155 +26,6 @@ def test_appends_suffix_to_slug_when_duplicate(self):
self.assertNotEquals(d2.slug, d3.slug)
-class QueryTest(BaseTestCase):
- def test_changing_query_text_changes_hash(self):
- q = self.factory.create_query()
- old_hash = q.query_hash
-
- q.query_text = "SELECT 2;"
- db.session.flush()
- self.assertNotEquals(old_hash, q.query_hash)
-
- def test_search_finds_in_name(self):
- q1 = self.factory.create_query(name=u"Testing seåřċħ")
- q2 = self.factory.create_query(name=u"Testing seåřċħing")
- q3 = self.factory.create_query(name=u"Testing seå řċħ")
- queries = list(models.Query.search(u"seåřċħ", [self.factory.default_group.id]))
-
- self.assertIn(q1, queries)
- self.assertIn(q2, queries)
- self.assertNotIn(q3, queries)
-
- def test_search_finds_in_description(self):
- q1 = self.factory.create_query(description=u"Testing seåřċħ")
- q2 = self.factory.create_query(description=u"Testing seåřċħing")
- q3 = self.factory.create_query(description=u"Testing seå řċħ")
-
- queries = models.Query.search(u"seåřċħ", [self.factory.default_group.id])
-
- self.assertIn(q1, queries)
- self.assertIn(q2, queries)
- self.assertNotIn(q3, queries)
-
- def test_search_by_id_returns_query(self):
- q1 = self.factory.create_query(description="Testing search")
- q2 = self.factory.create_query(description="Testing searching")
- q3 = self.factory.create_query(description="Testing sea rch")
- db.session.flush()
- queries = models.Query.search(str(q3.id), [self.factory.default_group.id])
-
- self.assertIn(q3, queries)
- self.assertNotIn(q1, queries)
- self.assertNotIn(q2, queries)
-
- def test_search_respects_groups(self):
- other_group = models.Group(org=self.factory.org, name="Other Group")
- db.session.add(other_group)
- ds = self.factory.create_data_source(group=other_group)
-
- q1 = self.factory.create_query(description="Testing search", data_source=ds)
- q2 = self.factory.create_query(description="Testing searching")
- q3 = self.factory.create_query(description="Testing sea rch")
-
- queries = list(models.Query.search("Testing", [self.factory.default_group.id]))
-
- self.assertNotIn(q1, queries)
- self.assertIn(q2, queries)
- self.assertIn(q3, queries)
-
- queries = list(models.Query.search("Testing", [other_group.id, self.factory.default_group.id]))
- self.assertIn(q1, queries)
- self.assertIn(q2, queries)
- self.assertIn(q3, queries)
-
- queries = list(models.Query.search("Testing", [other_group.id]))
- self.assertIn(q1, queries)
- self.assertNotIn(q2, queries)
- self.assertNotIn(q3, queries)
-
- def test_returns_each_query_only_once(self):
- other_group = self.factory.create_group()
- second_group = self.factory.create_group()
- ds = self.factory.create_data_source(group=other_group)
- ds.add_group(second_group, False)
-
- q1 = self.factory.create_query(description="Testing search", data_source=ds)
- db.session.flush()
- queries = list(models.Query.search("Testing", [self.factory.default_group.id, other_group.id, second_group.id]))
-
- self.assertEqual(1, len(queries))
-
- def test_save_updates_updated_at_field(self):
- # This should be a test of ModelTimestampsMixin, but it's easier to test in context of existing model... :-\
- one_day_ago = utcnow().date() - datetime.timedelta(days=1)
- q = self.factory.create_query(created_at=one_day_ago, updated_at=one_day_ago)
- db.session.flush()
- q.name = 'x'
- db.session.flush()
- self.assertNotEqual(q.updated_at, one_day_ago)
-
-
-class QueryRecentTest(BaseTestCase):
- def test_global_recent(self):
- q1 = self.factory.create_query()
- q2 = self.factory.create_query()
- db.session.flush()
- e = models.Event(org=self.factory.org, user=self.factory.user, action="edit",
- object_type="query", object_id=q1.id)
- db.session.add(e)
- recent = models.Query.recent([self.factory.default_group.id])
- self.assertIn(q1, recent)
- self.assertNotIn(q2, recent)
-
- def test_recent_excludes_drafts(self):
- q1 = self.factory.create_query()
- q2 = self.factory.create_query(is_draft=True)
-
- models.db.session.add_all([
- models.Event(org=self.factory.org, user=self.factory.user,
- action="edit", object_type="query",
- object_id=q1.id),
- models.Event(org=self.factory.org, user=self.factory.user,
- action="edit", object_type="query",
- object_id=q2.id)
- ])
- recent = models.Query.recent([self.factory.default_group.id])
-
- self.assertIn(q1, recent)
- self.assertNotIn(q2, recent)
-
- def test_recent_for_user(self):
- q1 = self.factory.create_query()
- q2 = self.factory.create_query()
- db.session.flush()
- e = models.Event(org=self.factory.org, user=self.factory.user, action="edit",
- object_type="query", object_id=q1.id)
- db.session.add(e)
- recent = models.Query.recent([self.factory.default_group.id], user_id=self.factory.user.id)
-
- self.assertIn(q1, recent)
- self.assertNotIn(q2, recent)
-
- recent = models.Query.recent([self.factory.default_group.id], user_id=self.factory.user.id + 1)
- self.assertNotIn(q1, recent)
- self.assertNotIn(q2, recent)
-
- def test_respects_groups(self):
- q1 = self.factory.create_query()
- ds = self.factory.create_data_source(group=self.factory.create_group())
- q2 = self.factory.create_query(data_source=ds)
- db.session.flush()
- models.Event(org=self.factory.org, user=self.factory.user, action="edit",
- object_type="query", object_id=q1.id)
- models.Event(org=self.factory.org, user=self.factory.user, action="edit",
- object_type="query", object_id=q2.id)
-
- recent = models.Query.recent([self.factory.default_group.id])
-
- self.assertIn(q1, recent)
- self.assertNotIn(q2, recent)
-
-
class ShouldScheduleNextTest(TestCase):
def test_interval_schedule_that_needs_reschedule(self):
now = utcnow()

0 comments on commit c900e83

Please sign in to comment.