2015-02-18 10:11:22 +00:00
|
|
|
#encoding: utf8
|
2014-03-19 11:48:48 +00:00
|
|
|
import datetime
|
2014-09-27 14:41:50 +00:00
|
|
|
import json
|
2015-04-01 08:23:26 +00:00
|
|
|
from unittest import TestCase
|
2015-03-30 08:06:15 +00:00
|
|
|
import mock
|
2015-10-16 20:10:50 +00:00
|
|
|
from dateutil.parser import parse as date_parse
|
2014-02-06 09:10:04 +00:00
|
|
|
from tests import BaseTestCase
|
2014-02-13 11:08:48 +00:00
|
|
|
from redash import models
|
2016-11-21 15:34:44 +00:00
|
|
|
from redash.models import db
|
2015-06-03 04:58:28 +00:00
|
|
|
from redash.utils import gen_query_hash, utcnow
|
2014-02-03 07:59:50 +00:00
|
|
|
|
|
|
|
|
2014-02-05 09:01:06 +00:00
|
|
|
class DashboardTest(BaseTestCase):
|
2014-02-03 07:59:50 +00:00
|
|
|
def test_appends_suffix_to_slug_when_duplicate(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
d1 = self.factory.create_dashboard()
|
2016-11-21 15:34:44 +00:00
|
|
|
db.session.flush()
|
2014-02-03 07:59:50 +00:00
|
|
|
self.assertEquals(d1.slug, 'test')
|
|
|
|
|
2015-12-01 13:44:08 +00:00
|
|
|
d2 = self.factory.create_dashboard(user=d1.user)
|
2016-11-21 15:34:44 +00:00
|
|
|
db.session.flush()
|
2014-02-03 07:59:50 +00:00
|
|
|
self.assertNotEquals(d1.slug, d2.slug)
|
|
|
|
|
2015-12-01 13:44:08 +00:00
|
|
|
d3 = self.factory.create_dashboard(user=d1.user)
|
2016-11-21 15:34:44 +00:00
|
|
|
db.session.flush()
|
2014-02-03 07:59:50 +00:00
|
|
|
self.assertNotEquals(d1.slug, d3.slug)
|
2014-02-13 11:08:48 +00:00
|
|
|
self.assertNotEquals(d2.slug, d3.slug)
|
|
|
|
|
|
|
|
|
2015-04-01 08:23:26 +00:00
|
|
|
class ShouldScheduleNextTest(TestCase):
|
|
|
|
def test_interval_schedule_that_needs_reschedule(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
now = utcnow()
|
2015-04-01 08:23:26 +00:00
|
|
|
two_hours_ago = now - datetime.timedelta(hours=2)
|
2017-02-02 04:39:27 +00:00
|
|
|
self.assertTrue(models.should_schedule_next(two_hours_ago, now, "3600",
|
|
|
|
0))
|
2015-04-01 08:23:26 +00:00
|
|
|
|
|
|
|
def test_interval_schedule_that_doesnt_need_reschedule(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
now = utcnow()
|
2015-04-01 08:23:26 +00:00
|
|
|
half_an_hour_ago = now - datetime.timedelta(minutes=30)
|
2017-02-02 04:39:27 +00:00
|
|
|
self.assertFalse(models.should_schedule_next(half_an_hour_ago, now,
|
|
|
|
"3600", 0))
|
2015-04-01 08:23:26 +00:00
|
|
|
|
|
|
|
def test_exact_time_that_needs_reschedule(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
now = utcnow()
|
2015-04-01 08:23:26 +00:00
|
|
|
yesterday = now - datetime.timedelta(days=1)
|
2016-02-16 04:16:31 +00:00
|
|
|
scheduled_datetime = now - datetime.timedelta(hours=3)
|
|
|
|
scheduled_time = "{:02d}:00".format(scheduled_datetime.hour)
|
2017-02-02 04:39:27 +00:00
|
|
|
self.assertTrue(models.should_schedule_next(yesterday, now,
|
|
|
|
scheduled_time, 0))
|
2015-04-01 08:23:26 +00:00
|
|
|
|
|
|
|
def test_exact_time_that_doesnt_need_reschedule(self):
|
2015-10-16 20:10:50 +00:00
|
|
|
now = date_parse("2015-10-16 20:10")
|
|
|
|
yesterday = date_parse("2015-10-15 23:07")
|
|
|
|
schedule = "23:00"
|
2017-02-02 04:39:27 +00:00
|
|
|
self.assertFalse(models.should_schedule_next(yesterday, now, schedule,
|
|
|
|
0))
|
2015-04-01 08:23:26 +00:00
|
|
|
|
|
|
|
def test_exact_time_with_day_change(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
now = utcnow().replace(hour=0, minute=1)
|
2017-02-02 04:39:27 +00:00
|
|
|
previous = (now - datetime.timedelta(days=2)).replace(hour=23,
|
|
|
|
minute=59)
|
2015-04-01 08:23:26 +00:00
|
|
|
schedule = "23:59".format(now.hour + 3)
|
2017-02-02 04:39:27 +00:00
|
|
|
self.assertTrue(models.should_schedule_next(previous, now, schedule,
|
|
|
|
0))
|
2015-04-01 08:23:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
class QueryOutdatedQueriesTest(BaseTestCase):
|
|
|
|
# TODO: this test can be refactored to use mock version of should_schedule_next to simplify it.
|
|
|
|
def test_outdated_queries_skips_unscheduled_queries(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
query = self.factory.create_query(schedule=None)
|
2015-04-01 08:23:26 +00:00
|
|
|
queries = models.Query.outdated_queries()
|
|
|
|
|
|
|
|
self.assertNotIn(query, queries)
|
|
|
|
|
|
|
|
def test_outdated_queries_works_with_ttl_based_schedule(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
two_hours_ago = utcnow() - datetime.timedelta(hours=2)
|
2015-12-01 13:44:08 +00:00
|
|
|
query = self.factory.create_query(schedule="3600")
|
2016-11-29 15:48:39 +00:00
|
|
|
query_result = self.factory.create_query_result(query=query.query_text, retrieved_at=two_hours_ago)
|
2015-04-01 08:23:26 +00:00
|
|
|
query.latest_query_data = query_result
|
|
|
|
|
|
|
|
queries = models.Query.outdated_queries()
|
|
|
|
self.assertIn(query, queries)
|
|
|
|
|
|
|
|
def test_skips_fresh_queries(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
half_an_hour_ago = utcnow() - datetime.timedelta(minutes=30)
|
2015-12-01 13:44:08 +00:00
|
|
|
query = self.factory.create_query(schedule="3600")
|
2016-11-29 15:48:39 +00:00
|
|
|
query_result = self.factory.create_query_result(query=query.query_text, retrieved_at=half_an_hour_ago)
|
2015-04-01 08:23:26 +00:00
|
|
|
query.latest_query_data = query_result
|
|
|
|
|
|
|
|
queries = models.Query.outdated_queries()
|
|
|
|
self.assertNotIn(query, queries)
|
|
|
|
|
|
|
|
def test_outdated_queries_works_with_specific_time_schedule(self):
|
2015-06-03 04:58:28 +00:00
|
|
|
half_an_hour_ago = utcnow() - datetime.timedelta(minutes=30)
|
2015-12-01 13:44:08 +00:00
|
|
|
query = self.factory.create_query(schedule=half_an_hour_ago.strftime('%H:%M'))
|
2016-11-29 15:48:39 +00:00
|
|
|
query_result = self.factory.create_query_result(query=query.query_text, retrieved_at=half_an_hour_ago - datetime.timedelta(days=1))
|
2015-04-01 08:23:26 +00:00
|
|
|
query.latest_query_data = query_result
|
|
|
|
|
|
|
|
queries = models.Query.outdated_queries()
|
|
|
|
self.assertIn(query, queries)
|
|
|
|
|
2017-02-02 04:39:27 +00:00
|
|
|
def test_enqueues_query_only_once(self):
|
|
|
|
"""
|
|
|
|
Only one query per data source with the same text will be reported by
|
|
|
|
Query.outdated_queries().
|
|
|
|
"""
|
|
|
|
query = self.factory.create_query(schedule="60")
|
|
|
|
query2 = self.factory.create_query(
|
|
|
|
schedule="60", query_text=query.query_text,
|
|
|
|
query_hash=query.query_hash)
|
|
|
|
retrieved_at = utcnow() - datetime.timedelta(minutes=10)
|
|
|
|
query_result = self.factory.create_query_result(
|
|
|
|
retrieved_at=retrieved_at, query_text=query.query_text,
|
|
|
|
query_hash=query.query_hash)
|
|
|
|
query.latest_query_data = query_result
|
|
|
|
query2.latest_query_data = query_result
|
|
|
|
|
|
|
|
self.assertEqual(list(models.Query.outdated_queries()), [query2])
|
|
|
|
|
|
|
|
def test_enqueues_query_with_correct_data_source(self):
|
|
|
|
"""
|
|
|
|
Queries from different data sources will be reported by
|
|
|
|
Query.outdated_queries() even if they have the same query text.
|
|
|
|
"""
|
|
|
|
query = self.factory.create_query(
|
|
|
|
schedule="60", data_source=self.factory.create_data_source())
|
|
|
|
query2 = self.factory.create_query(
|
|
|
|
schedule="60", query_text=query.query_text,
|
|
|
|
query_hash=query.query_hash)
|
|
|
|
retrieved_at = utcnow() - datetime.timedelta(minutes=10)
|
|
|
|
query_result = self.factory.create_query_result(
|
|
|
|
retrieved_at=retrieved_at, query_text=query.query_text,
|
|
|
|
query_hash=query.query_hash)
|
|
|
|
query.latest_query_data = query_result
|
|
|
|
query2.latest_query_data = query_result
|
|
|
|
|
|
|
|
self.assertEqual(list(models.Query.outdated_queries()),
|
|
|
|
[query2, query])
|
|
|
|
|
|
|
|
def test_enqueues_only_for_relevant_data_source(self):
|
|
|
|
"""
|
|
|
|
If multiple queries with the same text exist, only ones that are
|
|
|
|
scheduled to be refreshed are reported by Query.outdated_queries().
|
|
|
|
"""
|
|
|
|
query = self.factory.create_query(schedule="60")
|
|
|
|
query2 = self.factory.create_query(
|
|
|
|
schedule="3600", query_text=query.query_text,
|
|
|
|
query_hash=query.query_hash)
|
|
|
|
retrieved_at = utcnow() - datetime.timedelta(minutes=10)
|
|
|
|
query_result = self.factory.create_query_result(
|
|
|
|
retrieved_at=retrieved_at, query_text=query.query_text,
|
|
|
|
query_hash=query.query_hash)
|
|
|
|
query.latest_query_data = query_result
|
|
|
|
query2.latest_query_data = query_result
|
|
|
|
|
|
|
|
self.assertEqual(list(models.Query.outdated_queries()), [query])
|
|
|
|
|
|
|
|
def test_failure_extends_schedule(self):
|
|
|
|
"""
|
|
|
|
Execution failures recorded for a query result in exponential backoff
|
|
|
|
for scheduling future execution.
|
|
|
|
"""
|
|
|
|
query = self.factory.create_query(schedule="60", schedule_failures=4)
|
|
|
|
retrieved_at = utcnow() - datetime.timedelta(minutes=14)
|
|
|
|
query_result = self.factory.create_query_result(
|
|
|
|
retrieved_at=retrieved_at, query_text=query.query_text,
|
|
|
|
query_hash=query.query_hash)
|
|
|
|
query.latest_query_data = query_result
|
|
|
|
|
|
|
|
self.assertEqual(list(models.Query.outdated_queries()), [])
|
|
|
|
|
|
|
|
query_result.retrieved_at = utcnow() - datetime.timedelta(minutes=15)
|
|
|
|
self.assertEqual(list(models.Query.outdated_queries()), [query])
|
|
|
|
|
2015-04-01 08:23:26 +00:00
|
|
|
|
2014-09-25 14:42:33 +00:00
|
|
|
class QueryArchiveTest(BaseTestCase):
|
|
|
|
def setUp(self):
|
|
|
|
super(QueryArchiveTest, self).setUp()
|
|
|
|
|
|
|
|
def test_archive_query_sets_flag(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
query = self.factory.create_query()
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2014-09-25 14:42:33 +00:00
|
|
|
query.archive()
|
|
|
|
|
|
|
|
self.assertEquals(query.is_archived, True)
|
|
|
|
|
|
|
|
def test_archived_query_doesnt_return_in_all(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
query = self.factory.create_query(schedule="1")
|
2016-11-23 18:35:18 +00:00
|
|
|
yesterday = utcnow() - datetime.timedelta(days=1)
|
|
|
|
query_result, _ = models.QueryResult.store_result(
|
2016-11-29 15:48:39 +00:00
|
|
|
query.org, query.data_source, query.query_hash, query.query_text,
|
2016-11-23 18:35:18 +00:00
|
|
|
"1", 123, yesterday)
|
2014-09-25 14:42:33 +00:00
|
|
|
|
|
|
|
query.latest_query_data = query_result
|
2016-11-23 18:35:18 +00:00
|
|
|
groups = list(models.Group.query.filter(models.Group.id.in_(query.groups)))
|
2016-12-08 14:07:25 +00:00
|
|
|
self.assertIn(query, list(models.Query.all_queries([g.id for g in groups])))
|
2014-09-25 14:42:33 +00:00
|
|
|
self.assertIn(query, models.Query.outdated_queries())
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2014-09-25 14:42:33 +00:00
|
|
|
query.archive()
|
|
|
|
|
2016-12-08 14:07:25 +00:00
|
|
|
self.assertNotIn(query, list(models.Query.all_queries([g.id for g in groups])))
|
2014-09-25 14:42:33 +00:00
|
|
|
self.assertNotIn(query, models.Query.outdated_queries())
|
|
|
|
|
|
|
|
def test_removes_associated_widgets_from_dashboards(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
widget = self.factory.create_widget()
|
2016-11-29 15:48:39 +00:00
|
|
|
query = widget.visualization.query_rel
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.commit()
|
2014-09-25 14:42:33 +00:00
|
|
|
query.archive()
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
self.assertEqual(db.session.query(models.Widget).get(widget.id), None)
|
2014-09-25 14:42:33 +00:00
|
|
|
|
|
|
|
def test_removes_scheduling(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
query = self.factory.create_query(schedule="1")
|
2014-09-25 14:42:33 +00:00
|
|
|
|
|
|
|
query.archive()
|
|
|
|
|
2015-04-01 08:23:26 +00:00
|
|
|
self.assertEqual(None, query.schedule)
|
2014-09-25 14:42:33 +00:00
|
|
|
|
2016-06-14 08:09:35 +00:00
|
|
|
def test_deletes_alerts(self):
|
|
|
|
subscription = self.factory.create_alert_subscription()
|
2016-11-29 15:48:39 +00:00
|
|
|
query = subscription.alert.query_rel
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.commit()
|
2016-06-14 08:09:35 +00:00
|
|
|
query.archive()
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
self.assertEqual(db.session.query(models.Alert).get(subscription.alert.id), None)
|
|
|
|
self.assertEqual(db.session.query(models.AlertSubscription).get(subscription.id), None)
|
2016-06-14 08:09:35 +00:00
|
|
|
|
|
|
|
|
2015-03-30 08:06:15 +00:00
|
|
|
class DataSourceTest(BaseTestCase):
|
|
|
|
def test_get_schema(self):
|
2015-04-02 14:05:16 +00:00
|
|
|
return_value = [{'name': 'table', 'columns': []}]
|
|
|
|
|
2015-03-30 08:06:15 +00:00
|
|
|
with mock.patch('redash.query_runner.pg.PostgreSQL.get_schema') as patched_get_schema:
|
|
|
|
patched_get_schema.return_value = return_value
|
|
|
|
|
2015-12-01 13:44:08 +00:00
|
|
|
schema = self.factory.data_source.get_schema()
|
2015-03-30 08:06:15 +00:00
|
|
|
|
|
|
|
self.assertEqual(return_value, schema)
|
|
|
|
|
|
|
|
def test_get_schema_uses_cache(self):
|
2015-04-02 14:05:16 +00:00
|
|
|
return_value = [{'name': 'table', 'columns': []}]
|
2015-03-30 08:06:15 +00:00
|
|
|
with mock.patch('redash.query_runner.pg.PostgreSQL.get_schema') as patched_get_schema:
|
|
|
|
patched_get_schema.return_value = return_value
|
|
|
|
|
2015-12-01 13:44:08 +00:00
|
|
|
self.factory.data_source.get_schema()
|
|
|
|
schema = self.factory.data_source.get_schema()
|
2015-03-30 08:06:15 +00:00
|
|
|
|
|
|
|
self.assertEqual(return_value, schema)
|
|
|
|
self.assertEqual(patched_get_schema.call_count, 1)
|
|
|
|
|
|
|
|
def test_get_schema_skips_cache_with_refresh_true(self):
|
2015-04-02 14:05:16 +00:00
|
|
|
return_value = [{'name': 'table', 'columns': []}]
|
2015-03-30 08:06:15 +00:00
|
|
|
with mock.patch('redash.query_runner.pg.PostgreSQL.get_schema') as patched_get_schema:
|
|
|
|
patched_get_schema.return_value = return_value
|
|
|
|
|
2015-12-01 13:44:08 +00:00
|
|
|
self.factory.data_source.get_schema()
|
2015-04-02 14:05:16 +00:00
|
|
|
new_return_value = [{'name': 'new_table', 'columns': []}]
|
2015-03-30 08:06:15 +00:00
|
|
|
patched_get_schema.return_value = new_return_value
|
2015-12-01 13:44:08 +00:00
|
|
|
schema = self.factory.data_source.get_schema(refresh=True)
|
2015-03-30 08:06:15 +00:00
|
|
|
|
|
|
|
self.assertEqual(new_return_value, schema)
|
|
|
|
self.assertEqual(patched_get_schema.call_count, 2)
|
|
|
|
|
2014-09-25 14:42:33 +00:00
|
|
|
|
2014-03-19 11:48:48 +00:00
|
|
|
class QueryResultTest(BaseTestCase):
|
|
|
|
def setUp(self):
|
|
|
|
super(QueryResultTest, self).setUp()
|
|
|
|
|
|
|
|
def test_get_latest_returns_none_if_not_found(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
found_query_result = models.QueryResult.get_latest(self.factory.data_source, "SELECT 1", 60)
|
2014-03-20 18:57:35 +00:00
|
|
|
self.assertIsNone(found_query_result)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
|
|
|
def test_get_latest_returns_when_found(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
qr = self.factory.create_query_result()
|
2016-11-30 14:12:53 +00:00
|
|
|
found_query_result = models.QueryResult.get_latest(qr.data_source, qr.query_text, 60)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
|
|
|
self.assertEqual(qr, found_query_result)
|
|
|
|
|
|
|
|
def test_get_latest_doesnt_return_query_from_different_data_source(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
qr = self.factory.create_query_result()
|
|
|
|
data_source = self.factory.create_data_source()
|
2016-11-30 14:12:53 +00:00
|
|
|
found_query_result = models.QueryResult.get_latest(data_source, qr.query_text, 60)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
|
|
|
self.assertIsNone(found_query_result)
|
|
|
|
|
|
|
|
def test_get_latest_doesnt_return_if_ttl_expired(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
yesterday = utcnow() - datetime.timedelta(days=1)
|
2015-12-01 13:44:08 +00:00
|
|
|
qr = self.factory.create_query_result(retrieved_at=yesterday)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
2016-11-30 14:12:53 +00:00
|
|
|
found_query_result = models.QueryResult.get_latest(qr.data_source, qr.query_text, max_age=60)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
|
|
|
self.assertIsNone(found_query_result)
|
|
|
|
|
|
|
|
def test_get_latest_returns_if_ttl_not_expired(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
yesterday = utcnow() - datetime.timedelta(seconds=30)
|
2015-12-01 13:44:08 +00:00
|
|
|
qr = self.factory.create_query_result(retrieved_at=yesterday)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
2016-11-30 14:12:53 +00:00
|
|
|
found_query_result = models.QueryResult.get_latest(qr.data_source, qr.query_text, max_age=120)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
|
|
|
self.assertEqual(found_query_result, qr)
|
|
|
|
|
|
|
|
def test_get_latest_returns_the_most_recent_result(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
yesterday = utcnow() - datetime.timedelta(seconds=30)
|
2015-12-01 13:44:08 +00:00
|
|
|
old_qr = self.factory.create_query_result(retrieved_at=yesterday)
|
|
|
|
qr = self.factory.create_query_result()
|
2014-03-19 11:48:48 +00:00
|
|
|
|
2016-11-30 14:12:53 +00:00
|
|
|
found_query_result = models.QueryResult.get_latest(qr.data_source, qr.query_text, 60)
|
2014-03-19 11:48:48 +00:00
|
|
|
|
2014-04-29 13:02:10 +00:00
|
|
|
self.assertEqual(found_query_result.id, qr.id)
|
|
|
|
|
|
|
|
def test_get_latest_returns_the_last_cached_result_for_negative_ttl(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
yesterday = utcnow() + datetime.timedelta(days=-100)
|
2015-12-01 13:44:08 +00:00
|
|
|
very_old = self.factory.create_query_result(retrieved_at=yesterday)
|
2014-04-29 13:02:10 +00:00
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
yesterday = utcnow() + datetime.timedelta(days=-1)
|
2015-12-01 13:44:08 +00:00
|
|
|
qr = self.factory.create_query_result(retrieved_at=yesterday)
|
2016-11-30 14:12:53 +00:00
|
|
|
found_query_result = models.QueryResult.get_latest(qr.data_source, qr.query_text, -1)
|
2014-04-29 13:02:10 +00:00
|
|
|
|
2014-05-16 14:56:04 +00:00
|
|
|
self.assertEqual(found_query_result.id, qr.id)
|
|
|
|
|
2014-09-30 05:37:59 +00:00
|
|
|
|
2014-12-25 13:39:49 +00:00
|
|
|
class TestUnusedQueryResults(BaseTestCase):
|
|
|
|
def test_returns_only_unused_query_results(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
two_weeks_ago = utcnow() - datetime.timedelta(days=14)
|
2015-12-01 13:44:08 +00:00
|
|
|
qr = self.factory.create_query_result()
|
|
|
|
query = self.factory.create_query(latest_query_data=qr)
|
2016-12-08 01:59:48 +00:00
|
|
|
db.session.flush()
|
2015-12-01 13:44:08 +00:00
|
|
|
unused_qr = self.factory.create_query_result(retrieved_at=two_weeks_ago)
|
2016-12-08 01:59:48 +00:00
|
|
|
self.assertIn((unused_qr.id,), models.QueryResult.unused())
|
|
|
|
self.assertNotIn((qr.id,), list(models.QueryResult.unused()))
|
2014-12-25 13:39:49 +00:00
|
|
|
|
|
|
|
def test_returns_only_over_a_week_old_results(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
two_weeks_ago = utcnow() - datetime.timedelta(days=14)
|
2015-12-01 13:44:08 +00:00
|
|
|
unused_qr = self.factory.create_query_result(retrieved_at=two_weeks_ago)
|
2016-12-08 01:59:48 +00:00
|
|
|
db.session.flush()
|
2015-12-01 13:44:08 +00:00
|
|
|
new_unused_qr = self.factory.create_query_result()
|
2014-12-25 13:39:49 +00:00
|
|
|
|
2016-12-08 01:59:48 +00:00
|
|
|
self.assertIn((unused_qr.id,), models.QueryResult.unused())
|
|
|
|
self.assertNotIn((new_unused_qr.id,), models.QueryResult.unused())
|
2014-12-25 13:39:49 +00:00
|
|
|
|
|
|
|
|
2015-12-01 13:44:08 +00:00
|
|
|
class TestQueryAll(BaseTestCase):
|
|
|
|
def test_returns_only_queries_in_given_groups(self):
|
|
|
|
ds1 = self.factory.create_data_source()
|
|
|
|
ds2 = self.factory.create_data_source()
|
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
group1 = models.Group(name="g1", org=ds1.org, permissions=['create', 'view'])
|
|
|
|
group2 = models.Group(name="g2", org=ds1.org, permissions=['create', 'view'])
|
2015-12-01 13:44:08 +00:00
|
|
|
|
|
|
|
q1 = self.factory.create_query(data_source=ds1)
|
|
|
|
q2 = self.factory.create_query(data_source=ds2)
|
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.add_all([
|
|
|
|
ds1, ds2,
|
|
|
|
group1, group2,
|
|
|
|
q1, q2,
|
|
|
|
models.DataSourceGroup(
|
|
|
|
group=group1, data_source=ds1),
|
|
|
|
models.DataSourceGroup(group=group2, data_source=ds2)
|
|
|
|
])
|
|
|
|
db.session.flush()
|
2016-12-08 14:07:25 +00:00
|
|
|
self.assertIn(q1, list(models.Query.all_queries([group1.id])))
|
|
|
|
self.assertNotIn(q2, list(models.Query.all_queries([group1.id])))
|
|
|
|
self.assertIn(q1, list(models.Query.all_queries([group1.id, group2.id])))
|
|
|
|
self.assertIn(q2, list(models.Query.all_queries([group1.id, group2.id])))
|
2015-12-01 13:44:08 +00:00
|
|
|
|
2017-01-24 19:46:02 +00:00
|
|
|
def test_skips_drafts(self):
|
|
|
|
q = self.factory.create_query(is_draft=True)
|
|
|
|
self.assertNotIn(q, models.Query.all_queries([self.factory.default_group.id]))
|
|
|
|
|
|
|
|
def test_includes_drafts_of_given_user(self):
|
|
|
|
q = self.factory.create_query(is_draft=True)
|
|
|
|
self.assertIn(q, models.Query.all_queries([self.factory.default_group.id], user_id=q.user_id))
|
|
|
|
|
2015-12-01 13:44:08 +00:00
|
|
|
|
2016-05-17 19:01:18 +00:00
|
|
|
class TestGroup(BaseTestCase):
|
|
|
|
def test_returns_groups_with_specified_names(self):
|
|
|
|
org1 = self.factory.create_org()
|
|
|
|
org2 = self.factory.create_org()
|
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
matching_group1 = models.Group(id=999, name="g1", org=org1)
|
|
|
|
matching_group2 = models.Group(id=888, name="g2", org=org1)
|
|
|
|
non_matching_group = models.Group(id=777, name="g1", org=org2)
|
2016-05-17 19:01:18 +00:00
|
|
|
|
|
|
|
groups = models.Group.find_by_name(org1, ["g1", "g2"])
|
|
|
|
self.assertIn(matching_group1, groups)
|
|
|
|
self.assertIn(matching_group2, groups)
|
|
|
|
self.assertNotIn(non_matching_group, groups)
|
|
|
|
|
|
|
|
def test_returns_no_groups(self):
|
|
|
|
org1 = self.factory.create_org()
|
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
models.Group(id=999, name="g1", org=org1)
|
2016-05-17 19:01:18 +00:00
|
|
|
self.assertEqual([], models.Group.find_by_name(org1, ["non-existing"]))
|
|
|
|
|
|
|
|
|
2014-05-16 14:56:04 +00:00
|
|
|
class TestQueryResultStoreResult(BaseTestCase):
|
|
|
|
def setUp(self):
|
|
|
|
super(TestQueryResultStoreResult, self).setUp()
|
2015-12-01 13:44:08 +00:00
|
|
|
self.data_source = self.factory.data_source
|
2014-05-16 14:56:04 +00:00
|
|
|
self.query = "SELECT 1"
|
|
|
|
self.query_hash = gen_query_hash(self.query)
|
|
|
|
self.runtime = 123
|
2015-06-03 04:58:28 +00:00
|
|
|
self.utcnow = utcnow()
|
2014-05-16 14:56:04 +00:00
|
|
|
self.data = "data"
|
|
|
|
|
|
|
|
def test_stores_the_result(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
query_result, _ = models.QueryResult.store_result(
|
|
|
|
self.data_source.org, self.data_source, self.query_hash,
|
|
|
|
self.query, self.data, self.runtime, self.utcnow)
|
2014-05-16 14:56:04 +00:00
|
|
|
|
|
|
|
self.assertEqual(query_result.data, self.data)
|
|
|
|
self.assertEqual(query_result.runtime, self.runtime)
|
|
|
|
self.assertEqual(query_result.retrieved_at, self.utcnow)
|
2016-11-30 14:12:53 +00:00
|
|
|
self.assertEqual(query_result.query_text, self.query)
|
2014-05-16 14:56:04 +00:00
|
|
|
self.assertEqual(query_result.query_hash, self.query_hash)
|
|
|
|
self.assertEqual(query_result.data_source, self.data_source)
|
|
|
|
|
|
|
|
def test_updates_existing_queries(self):
|
2016-11-29 15:48:39 +00:00
|
|
|
query1 = self.factory.create_query(query_text=self.query)
|
|
|
|
query2 = self.factory.create_query(query_text=self.query)
|
|
|
|
query3 = self.factory.create_query(query_text=self.query)
|
2014-05-16 14:56:04 +00:00
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
query_result, _ = models.QueryResult.store_result(
|
|
|
|
self.data_source.org, self.data_source, self.query_hash,
|
|
|
|
self.query, self.data, self.runtime, self.utcnow)
|
2014-05-16 14:56:04 +00:00
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertEqual(query1.latest_query_data, query_result)
|
|
|
|
self.assertEqual(query2.latest_query_data, query_result)
|
|
|
|
self.assertEqual(query3.latest_query_data, query_result)
|
2014-05-16 14:56:04 +00:00
|
|
|
|
|
|
|
def test_doesnt_update_queries_with_different_hash(self):
|
2016-11-29 15:48:39 +00:00
|
|
|
query1 = self.factory.create_query(query_text=self.query)
|
|
|
|
query2 = self.factory.create_query(query_text=self.query)
|
|
|
|
query3 = self.factory.create_query(query_text=self.query + "123")
|
2014-05-16 14:56:04 +00:00
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
query_result, _ = models.QueryResult.store_result(
|
|
|
|
self.data_source.org, self.data_source, self.query_hash,
|
|
|
|
self.query, self.data, self.runtime, self.utcnow)
|
2016-11-29 15:48:39 +00:00
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertEqual(query1.latest_query_data, query_result)
|
|
|
|
self.assertEqual(query2.latest_query_data, query_result)
|
|
|
|
self.assertNotEqual(query3.latest_query_data, query_result)
|
2014-05-16 14:56:04 +00:00
|
|
|
|
|
|
|
def test_doesnt_update_queries_with_different_data_source(self):
|
2016-11-29 15:48:39 +00:00
|
|
|
query1 = self.factory.create_query(query_text=self.query)
|
|
|
|
query2 = self.factory.create_query(query_text=self.query)
|
|
|
|
query3 = self.factory.create_query(query_text=self.query, data_source=self.factory.create_data_source())
|
2014-05-16 14:56:04 +00:00
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
query_result, _ = models.QueryResult.store_result(
|
|
|
|
self.data_source.org, self.data_source, self.query_hash,
|
|
|
|
self.query, self.data, self.runtime, self.utcnow)
|
2014-05-16 14:56:04 +00:00
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertEqual(query1.latest_query_data, query_result)
|
|
|
|
self.assertEqual(query2.latest_query_data, query_result)
|
|
|
|
self.assertNotEqual(query3.latest_query_data, query_result)
|
2014-09-27 14:41:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TestEvents(BaseTestCase):
|
|
|
|
def raw_event(self):
|
|
|
|
timestamp = 1411778709.791
|
2015-12-01 13:44:08 +00:00
|
|
|
user = self.factory.user
|
2014-09-27 14:41:50 +00:00
|
|
|
created_at = datetime.datetime.utcfromtimestamp(timestamp)
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2014-09-27 14:41:50 +00:00
|
|
|
raw_event = {"action": "view",
|
|
|
|
"timestamp": timestamp,
|
|
|
|
"object_type": "dashboard",
|
|
|
|
"user_id": user.id,
|
2015-12-01 13:44:08 +00:00
|
|
|
"object_id": 1,
|
|
|
|
"org_id": 1}
|
2014-09-27 14:41:50 +00:00
|
|
|
|
|
|
|
return raw_event, user, created_at
|
|
|
|
|
|
|
|
def test_records_event(self):
|
|
|
|
raw_event, user, created_at = self.raw_event()
|
|
|
|
|
|
|
|
event = models.Event.record(raw_event)
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2014-09-27 14:41:50 +00:00
|
|
|
self.assertEqual(event.user, user)
|
|
|
|
self.assertEqual(event.action, "view")
|
|
|
|
self.assertEqual(event.object_type, "dashboard")
|
|
|
|
self.assertEqual(event.object_id, 1)
|
|
|
|
self.assertEqual(event.created_at, created_at)
|
|
|
|
|
|
|
|
def test_records_additional_properties(self):
|
|
|
|
raw_event, _, _ = self.raw_event()
|
|
|
|
additional_properties = {'test': 1, 'test2': 2, 'whatever': "abc"}
|
|
|
|
raw_event.update(additional_properties)
|
|
|
|
|
|
|
|
event = models.Event.record(raw_event)
|
|
|
|
|
2017-02-02 08:39:21 +00:00
|
|
|
self.assertDictEqual(event.additional_properties, additional_properties)
|
2014-09-25 14:42:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TestWidgetDeleteInstance(BaseTestCase):
|
|
|
|
def test_delete_removes_from_layout(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
widget = self.factory.create_widget()
|
|
|
|
widget2 = self.factory.create_widget(dashboard=widget.dashboard)
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2014-09-25 14:42:33 +00:00
|
|
|
widget.dashboard.layout = json.dumps([[widget.id, widget2.id]])
|
2016-12-06 12:30:00 +00:00
|
|
|
widget.delete()
|
2014-09-25 14:42:33 +00:00
|
|
|
self.assertEquals(json.dumps([[widget2.id]]), widget.dashboard.layout)
|
|
|
|
|
|
|
|
def test_delete_removes_empty_rows(self):
|
2015-12-01 13:44:08 +00:00
|
|
|
widget = self.factory.create_widget()
|
|
|
|
widget2 = self.factory.create_widget(dashboard=widget.dashboard)
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2014-09-25 14:42:33 +00:00
|
|
|
widget.dashboard.layout = json.dumps([[widget.id, widget2.id]])
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2016-12-06 12:30:00 +00:00
|
|
|
widget.delete()
|
|
|
|
widget2.delete()
|
2014-09-25 14:42:33 +00:00
|
|
|
self.assertEquals("[]", widget.dashboard.layout)
|
2016-03-29 16:27:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
def _set_up_dashboard_test(d):
|
2016-11-23 18:35:18 +00:00
|
|
|
d.g1 = d.factory.create_group(name='First', permissions=['create', 'view'])
|
|
|
|
d.g2 = d.factory.create_group(name='Second', permissions=['create', 'view'])
|
2016-03-29 16:27:35 +00:00
|
|
|
d.ds1 = d.factory.create_data_source()
|
|
|
|
d.ds2 = d.factory.create_data_source()
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
2016-11-21 15:34:44 +00:00
|
|
|
d.u1 = d.factory.create_user(group_ids=[d.g1.id])
|
|
|
|
d.u2 = d.factory.create_user(group_ids=[d.g2.id])
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.add_all([
|
|
|
|
models.DataSourceGroup(group=d.g1, data_source=d.ds1),
|
|
|
|
models.DataSourceGroup(group=d.g2, data_source=d.ds2)
|
|
|
|
])
|
2016-03-29 16:27:35 +00:00
|
|
|
d.q1 = d.factory.create_query(data_source=d.ds1)
|
|
|
|
d.q2 = d.factory.create_query(data_source=d.ds2)
|
2016-11-29 15:48:39 +00:00
|
|
|
d.v1 = d.factory.create_visualization(query_rel=d.q1)
|
|
|
|
d.v2 = d.factory.create_visualization(query_rel=d.q2)
|
2016-03-29 16:27:35 +00:00
|
|
|
d.w1 = d.factory.create_widget(visualization=d.v1)
|
|
|
|
d.w2 = d.factory.create_widget(visualization=d.v2)
|
2016-04-20 15:30:31 +00:00
|
|
|
d.w3 = d.factory.create_widget(visualization=d.v2, dashboard=d.w2.dashboard)
|
|
|
|
d.w4 = d.factory.create_widget(visualization=d.v2)
|
|
|
|
d.w5 = d.factory.create_widget(visualization=d.v1, dashboard=d.w4.dashboard)
|
2016-11-29 15:48:39 +00:00
|
|
|
d.w1.dashboard.is_draft = False
|
|
|
|
d.w2.dashboard.is_draft = False
|
|
|
|
d.w4.dashboard.is_draft = False
|
2016-03-29 16:27:35 +00:00
|
|
|
|
|
|
|
class TestDashboardAll(BaseTestCase):
|
|
|
|
def setUp(self):
|
|
|
|
super(TestDashboardAll, self).setUp()
|
|
|
|
_set_up_dashboard_test(self)
|
|
|
|
|
|
|
|
def test_requires_group_or_user_id(self):
|
|
|
|
d1 = self.factory.create_dashboard()
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertNotIn(d1, list(models.Dashboard.all(
|
|
|
|
d1.user.org, d1.user.group_ids, None)))
|
|
|
|
l2 = list(models.Dashboard.all(
|
|
|
|
d1.user.org, [0], d1.user.id))
|
|
|
|
self.assertIn(d1, l2)
|
2016-03-29 16:27:35 +00:00
|
|
|
|
|
|
|
def test_returns_dashboards_based_on_groups(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertIn(self.w1.dashboard, list(models.Dashboard.all(
|
|
|
|
self.u1.org, self.u1.group_ids, None)))
|
|
|
|
self.assertIn(self.w2.dashboard, list(models.Dashboard.all(
|
|
|
|
self.u2.org, self.u2.group_ids, None)))
|
|
|
|
self.assertNotIn(self.w1.dashboard, list(models.Dashboard.all(
|
|
|
|
self.u2.org, self.u2.group_ids, None)))
|
|
|
|
self.assertNotIn(self.w2.dashboard, list(models.Dashboard.all(
|
|
|
|
self.u1.org, self.u1.group_ids, None)))
|
2016-03-29 16:27:35 +00:00
|
|
|
|
2016-04-20 15:30:31 +00:00
|
|
|
def test_returns_each_dashboard_once(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
dashboards = list(models.Dashboard.all(self.u2.org, self.u2.group_ids, None))
|
2016-04-20 15:30:31 +00:00
|
|
|
self.assertEqual(len(dashboards), 2)
|
|
|
|
|
|
|
|
def test_returns_dashboard_you_have_partial_access_to(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertIn(self.w5.dashboard, models.Dashboard.all(self.u1.org, self.u1.group_ids, None))
|
2016-04-20 15:30:31 +00:00
|
|
|
|
2016-03-29 16:27:35 +00:00
|
|
|
def test_returns_dashboards_created_by_user(self):
|
|
|
|
d1 = self.factory.create_dashboard(user=self.u1)
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
self.assertIn(d1, list(models.Dashboard.all(self.u1.org, self.u1.group_ids, self.u1.id)))
|
|
|
|
self.assertIn(d1, list(models.Dashboard.all(self.u1.org, [0], self.u1.id)))
|
|
|
|
self.assertNotIn(d1, list(models.Dashboard.all(self.u2.org, self.u2.group_ids, self.u2.id)))
|
2016-03-29 16:27:35 +00:00
|
|
|
|
|
|
|
def test_returns_dashboards_with_text_widgets(self):
|
|
|
|
w1 = self.factory.create_widget(visualization=None)
|
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertIn(w1.dashboard, models.Dashboard.all(self.u1.org, self.u1.group_ids, None))
|
|
|
|
self.assertIn(w1.dashboard, models.Dashboard.all(self.u2.org, self.u2.group_ids, None))
|
2016-05-04 13:32:49 +00:00
|
|
|
|
|
|
|
def test_returns_dashboards_from_current_org_only(self):
|
|
|
|
w1 = self.factory.create_widget(visualization=None)
|
|
|
|
|
|
|
|
user = self.factory.create_user(org=self.factory.create_org())
|
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertIn(w1.dashboard, models.Dashboard.all(self.u1.org, self.u1.group_ids, None))
|
|
|
|
self.assertNotIn(w1.dashboard, models.Dashboard.all(user.org, user.group_ids, None))
|
2016-03-29 16:27:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TestDashboardRecent(BaseTestCase):
|
|
|
|
def setUp(self):
|
|
|
|
super(TestDashboardRecent, self).setUp()
|
|
|
|
_set_up_dashboard_test(self)
|
|
|
|
|
|
|
|
def test_returns_recent_dashboards_basic(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.add(models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w1.dashboard.id))
|
2016-11-29 15:48:39 +00:00
|
|
|
db.session.flush()
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertIn(self.w1.dashboard, models.Dashboard.recent(self.u1.org, self.u1.group_ids, None))
|
|
|
|
self.assertNotIn(self.w2.dashboard, models.Dashboard.recent(self.u1.org, self.u1.group_ids, None))
|
|
|
|
self.assertNotIn(self.w1.dashboard, models.Dashboard.recent(self.u1.org, self.u2.group_ids, None))
|
2016-03-29 16:27:35 +00:00
|
|
|
|
2016-10-14 22:25:30 +00:00
|
|
|
def test_recent_excludes_drafts(self):
|
2016-11-29 15:48:39 +00:00
|
|
|
models.db.session.add_all([
|
|
|
|
models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w1.dashboard.id),
|
|
|
|
models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w2.dashboard.id)])
|
|
|
|
|
|
|
|
self.w2.dashboard.is_draft = True
|
|
|
|
self.assertIn(self.w1.dashboard, models.Dashboard.recent(
|
|
|
|
self.u1.org, self.u1.group_ids, None))
|
|
|
|
self.assertNotIn(self.w2.dashboard, models.Dashboard.recent(
|
|
|
|
self.u1.org, self.u1.group_ids, None))
|
2016-10-14 22:25:30 +00:00
|
|
|
|
2016-03-29 16:27:35 +00:00
|
|
|
def test_returns_recent_dashboards_created_by_user(self):
|
2016-11-29 15:48:39 +00:00
|
|
|
d1 = self.factory.create_dashboard(user=self.u1, is_draft=False)
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
db.session.add(models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=d1.id))
|
2016-05-04 13:32:49 +00:00
|
|
|
self.assertIn(d1, models.Dashboard.recent(self.u1.org, [0], self.u1.id))
|
|
|
|
self.assertNotIn(self.w2.dashboard, models.Dashboard.recent(self.u1.org, [0], self.u1.id))
|
|
|
|
self.assertNotIn(d1, models.Dashboard.recent(self.u2.org, [0], self.u2.id))
|
2016-03-29 16:27:35 +00:00
|
|
|
|
|
|
|
def test_returns_recent_dashboards_with_no_visualizations(self):
|
|
|
|
w1 = self.factory.create_widget(visualization=None)
|
2016-11-29 15:48:39 +00:00
|
|
|
w1.dashboard.is_draft = False
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
db.session.add(models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=w1.dashboard.id))
|
|
|
|
db.session.flush()
|
2016-05-04 13:32:49 +00:00
|
|
|
self.assertIn(w1.dashboard, models.Dashboard.recent(self.u1.org, [0], self.u1.id))
|
|
|
|
self.assertNotIn(self.w2.dashboard, models.Dashboard.recent(self.u1.org, [0], self.u1.id))
|
2016-03-29 16:27:35 +00:00
|
|
|
|
|
|
|
def test_restricts_dashboards_for_user(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
db.session.add_all([
|
|
|
|
models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w1.dashboard.id),
|
|
|
|
models.Event(org=self.factory.org, user=self.u2, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w2.dashboard.id),
|
|
|
|
models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w5.dashboard.id),
|
|
|
|
models.Event(org=self.factory.org, user=self.u2, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w5.dashboard.id)
|
|
|
|
])
|
|
|
|
db.session.flush()
|
|
|
|
self.assertIn(self.w1.dashboard, models.Dashboard.recent(self.u1.org, self.u1.group_ids, self.u1.id, for_user=True))
|
|
|
|
self.assertIn(self.w2.dashboard, models.Dashboard.recent(self.u2.org, self.u2.group_ids, self.u2.id, for_user=True))
|
|
|
|
self.assertNotIn(self.w1.dashboard, models.Dashboard.recent(self.u2.org, self.u2.group_ids, self.u2.id, for_user=True))
|
|
|
|
self.assertNotIn(self.w2.dashboard, models.Dashboard.recent(self.u1.org, self.u1.group_ids, self.u1.id, for_user=True))
|
|
|
|
self.assertIn(self.w5.dashboard, models.Dashboard.recent(self.u1.org, self.u1.group_ids, self.u1.id, for_user=True))
|
|
|
|
self.assertIn(self.w5.dashboard, models.Dashboard.recent(self.u2.org, self.u2.group_ids, self.u2.id, for_user=True))
|
2016-04-20 15:30:31 +00:00
|
|
|
|
|
|
|
def test_returns_each_dashboard_once(self):
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
db.session.add_all([
|
|
|
|
models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w1.dashboard.id),
|
|
|
|
models.Event(org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=self.w1.dashboard.id)
|
|
|
|
])
|
|
|
|
db.session.flush()
|
|
|
|
dashboards = list(models.Dashboard.recent(self.u1.org, self.u1.group_ids, None))
|
2016-04-20 15:30:31 +00:00
|
|
|
self.assertEqual(len(dashboards), 1)
|
2016-05-04 13:32:49 +00:00
|
|
|
|
|
|
|
def test_returns_dashboards_from_current_org_only(self):
|
|
|
|
w1 = self.factory.create_widget(visualization=None)
|
2016-11-29 15:48:39 +00:00
|
|
|
w1.dashboard.is_draft = False
|
2016-11-23 18:35:18 +00:00
|
|
|
db.session.flush()
|
|
|
|
db.session.add(models.Event(
|
|
|
|
org=self.factory.org, user=self.u1, action="view",
|
|
|
|
object_type="dashboard", object_id=w1.dashboard.id))
|
|
|
|
db.session.flush()
|
2016-05-04 13:32:49 +00:00
|
|
|
user = self.factory.create_user(org=self.factory.create_org())
|
|
|
|
|
2016-11-23 18:35:18 +00:00
|
|
|
self.assertIn(w1.dashboard, models.Dashboard.recent(self.u1.org, self.u1.group_ids, None))
|
|
|
|
self.assertNotIn(w1.dashboard, models.Dashboard.recent(user.org, user.group_ids, None))
|