mirror of
https://github.com/valitydev/redash.git
synced 2024-11-07 01:25:16 +00:00
More tests (Dasboard API).
This commit is contained in:
parent
6ee3bc099d
commit
1e4f70747b
2
Makefile
2
Makefile
@ -1,5 +1,5 @@
|
|||||||
NAME=redash
|
NAME=redash
|
||||||
VERSION=0.2
|
VERSION=0.3
|
||||||
FULL_VERSION=$(VERSION).$(CIRCLE_BUILD_NUM)
|
FULL_VERSION=$(VERSION).$(CIRCLE_BUILD_NUM)
|
||||||
FILENAME=$(CIRCLE_ARTIFACTS)/$(NAME).$(FULL_VERSION).tar.gz
|
FILENAME=$(CIRCLE_ARTIFACTS)/$(NAME).$(FULL_VERSION).tar.gz
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ class DashboardListAPI(BaseResource):
|
|||||||
return dashboards
|
return dashboards
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
dashboard_properties = json.loads(self.request.body)
|
dashboard_properties = request.get_json(force=True)
|
||||||
dashboard = models.Dashboard(name=dashboard_properties['name'],
|
dashboard = models.Dashboard(name=dashboard_properties['name'],
|
||||||
user=self.current_user,
|
user=self.current_user,
|
||||||
layout='[]')
|
layout='[]')
|
||||||
@ -104,13 +104,18 @@ class DashboardListAPI(BaseResource):
|
|||||||
|
|
||||||
class DashboardAPI(BaseResource):
|
class DashboardAPI(BaseResource):
|
||||||
def get(self, dashboard_slug=None):
|
def get(self, dashboard_slug=None):
|
||||||
# TODO: prefetching?
|
# TODO: prefetching of widgets and queries?
|
||||||
dashboard = models.Dashboard.get_by_slug(dashboard_slug)
|
try:
|
||||||
|
dashboard = models.Dashboard.get_by_slug(dashboard_slug)
|
||||||
|
except models.Dashboard.DoesNotExist:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
return dashboard.to_dict(with_widgets=True)
|
return dashboard.to_dict(with_widgets=True)
|
||||||
|
|
||||||
def post(self, dashboard_id):
|
def post(self, dashboard_slug):
|
||||||
dashboard_properties = request.json
|
# TODO: either convert all requests to use slugs or ids
|
||||||
dashboard = models.Dashboard.get(models.Dashboard.id == dashboard_id)
|
dashboard_properties = request.get_json(force=True)
|
||||||
|
dashboard = models.Dashboard.get(models.Dashboard.id == dashboard_slug)
|
||||||
dashboard.layout = dashboard_properties['layout']
|
dashboard.layout = dashboard_properties['layout']
|
||||||
dashboard.name = dashboard_properties['name']
|
dashboard.name = dashboard_properties['name']
|
||||||
dashboard.save()
|
dashboard.save()
|
||||||
@ -128,7 +133,7 @@ api.add_resource(DashboardAPI, '/api/dashboards/<dashboard_slug>', endpoint='das
|
|||||||
|
|
||||||
class WidgetListAPI(BaseResource):
|
class WidgetListAPI(BaseResource):
|
||||||
def post(self):
|
def post(self):
|
||||||
widget_properties = request.json
|
widget_properties = request.get_json(force=True)
|
||||||
widget_properties['options'] = json.dumps(widget_properties['options'])
|
widget_properties['options'] = json.dumps(widget_properties['options'])
|
||||||
widget = models.Widget(**widget_properties)
|
widget = models.Widget(**widget_properties)
|
||||||
widget.save()
|
widget.save()
|
||||||
|
@ -202,4 +202,4 @@ def create_db(create_tables, drop_tables):
|
|||||||
if create_tables:
|
if create_tables:
|
||||||
model.create_table()
|
model.create_table()
|
||||||
|
|
||||||
db.close_db(None)
|
db.close_db(None)
|
@ -1 +1,56 @@
|
|||||||
from tests import controllers
|
from unittest import TestCase
|
||||||
|
from redash import settings, db, app
|
||||||
|
import redash.models
|
||||||
|
|
||||||
|
# TODO: this isn't pretty... :-)
|
||||||
|
settings.DATABASE_CONFIG = {
|
||||||
|
'name': 'rd_test',
|
||||||
|
'engine': 'peewee.PostgresqlDatabase',
|
||||||
|
'threadlocals': True
|
||||||
|
}
|
||||||
|
app.config['DATABASE'] = settings.DATABASE_CONFIG
|
||||||
|
db.load_database()
|
||||||
|
|
||||||
|
|
||||||
|
def model_factory(model, **kwargs):
|
||||||
|
def factory(**properties):
|
||||||
|
kwargs.update(properties)
|
||||||
|
|
||||||
|
return model(**kwargs)
|
||||||
|
|
||||||
|
return factory
|
||||||
|
|
||||||
|
|
||||||
|
class ModelFactory(object):
|
||||||
|
def __init__(self, model, **kwargs):
|
||||||
|
self.model = model
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
def _get_kwargs(self, override_kwargs):
|
||||||
|
kwargs = self.kwargs.copy()
|
||||||
|
kwargs.update(override_kwargs)
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def instance(self, **override_kwargs):
|
||||||
|
kwargs = self._get_kwargs(override_kwargs)
|
||||||
|
|
||||||
|
return self.model(**kwargs)
|
||||||
|
|
||||||
|
def create(self, **override_kwargs):
|
||||||
|
kwargs = self._get_kwargs(override_kwargs)
|
||||||
|
|
||||||
|
return self.model.create(**kwargs)
|
||||||
|
|
||||||
|
DashboardFactory = ModelFactory(redash.models.Dashboard,
|
||||||
|
name='test', user='test@everything.me', layout='[]')
|
||||||
|
|
||||||
|
dashboard_factory = model_factory(redash.models.Dashboard, name='test', user='test@everything.me', layout='[]')
|
||||||
|
|
||||||
|
|
||||||
|
class BaseTestCase(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
redash.models.create_db(True, True)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
db.close_db(None)
|
||||||
|
redash.models.create_db(False, True)
|
@ -1,16 +1,31 @@
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
import unittest
|
import json
|
||||||
from redash import app
|
from tests import BaseTestCase, DashboardFactory
|
||||||
|
from redash import app, models
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def authenticated_user(c):
|
def authenticated_user(c, user='test@example.com', name='John Test'):
|
||||||
with c.session_transaction() as sess:
|
with c.session_transaction() as sess:
|
||||||
sess['openid'] = {'email': 'test@example.com', 'name': 'John Test'}
|
sess['openid'] = {'email': user, 'name': name}
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
def json_request(method, path, data=None):
|
||||||
|
if data:
|
||||||
|
response = method(path, data=json.dumps(data))
|
||||||
|
else:
|
||||||
|
response = method(path)
|
||||||
|
|
||||||
|
if response.data:
|
||||||
|
response.json = json.loads(response.data)
|
||||||
|
else:
|
||||||
|
response.json = None
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationTestMixin():
|
class AuthenticationTestMixin():
|
||||||
def test_redirects_when_not_authenticated(self):
|
def test_redirects_when_not_authenticated(self):
|
||||||
with app.test_client() as c:
|
with app.test_client() as c:
|
||||||
@ -19,14 +34,13 @@ class AuthenticationTestMixin():
|
|||||||
self.assertEquals(302, rv.status_code)
|
self.assertEquals(302, rv.status_code)
|
||||||
|
|
||||||
def test_returns_content_when_authenticated(self):
|
def test_returns_content_when_authenticated(self):
|
||||||
with app.test_client() as c:
|
with app.test_client() as c, authenticated_user(c):
|
||||||
with authenticated_user(c):
|
for path in self.paths:
|
||||||
for path in self.paths:
|
rv = c.get(path)
|
||||||
rv = c.get(path)
|
self.assertEquals(200, rv.status_code)
|
||||||
self.assertEquals(200, rv.status_code)
|
|
||||||
|
|
||||||
|
|
||||||
class PingTest(unittest.TestCase):
|
class PingTest(BaseTestCase):
|
||||||
def test_ping(self):
|
def test_ping(self):
|
||||||
with app.test_client() as c:
|
with app.test_client() as c:
|
||||||
rv = c.get('/ping')
|
rv = c.get('/ping')
|
||||||
@ -34,36 +48,83 @@ class PingTest(unittest.TestCase):
|
|||||||
self.assertEquals('PONG.', rv.data)
|
self.assertEquals('PONG.', rv.data)
|
||||||
|
|
||||||
|
|
||||||
class IndexTest(unittest.TestCase, AuthenticationTestMixin):
|
class IndexTest(BaseTestCase, AuthenticationTestMixin):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.paths = ['/', '/dashboard/example', '/queries/1', '/admin/status']
|
self.paths = ['/', '/dashboard/example', '/queries/1', '/admin/status']
|
||||||
|
super(IndexTest, self).setUp()
|
||||||
|
|
||||||
|
|
||||||
class StatusTest(unittest.TestCase, AuthenticationTestMixin):
|
class StatusTest(BaseTestCase, AuthenticationTestMixin):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.paths = ['/status.json']
|
self.paths = ['/status.json']
|
||||||
|
super(StatusTest, self).setUp()
|
||||||
|
|
||||||
|
|
||||||
class DashboardAPITest(unittest.TestCase, AuthenticationTestMixin):
|
class DashboardAPITest(BaseTestCase, AuthenticationTestMixin):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.paths = ['/api/dashboards']
|
self.paths = ['/api/dashboards']
|
||||||
|
super(DashboardAPITest, self).setUp()
|
||||||
|
|
||||||
|
def test_get_dashboard(self):
|
||||||
|
d1 = DashboardFactory.create()
|
||||||
|
with app.test_client() as c, authenticated_user(c):
|
||||||
|
rv = c.get('/api/dashboards/{0}'.format(d1.slug))
|
||||||
|
self.assertEquals(rv.status_code, 200)
|
||||||
|
self.assertDictEqual(json.loads(rv.data), d1.to_dict(with_widgets=True))
|
||||||
|
|
||||||
|
def test_get_non_existint_dashbaord(self):
|
||||||
|
with app.test_client() as c, authenticated_user(c):
|
||||||
|
rv = c.get('/api/dashboards/not_existing')
|
||||||
|
self.assertEquals(rv.status_code, 404)
|
||||||
|
|
||||||
|
def test_create_new_dashboard(self):
|
||||||
|
user_email = 'test@everything.me'
|
||||||
|
with app.test_client() as c, authenticated_user(c, user=user_email):
|
||||||
|
dashboard_name = 'Test Dashboard'
|
||||||
|
rv = json_request(c.post, '/api/dashboards', data={'name': dashboard_name})
|
||||||
|
self.assertEquals(rv.status_code, 200)
|
||||||
|
self.assertEquals(rv.json['name'], 'Test Dashboard')
|
||||||
|
self.assertEquals(rv.json['user'], user_email)
|
||||||
|
self.assertEquals(rv.json['layout'], [])
|
||||||
|
|
||||||
|
def test_update_dashboard(self):
|
||||||
|
d = DashboardFactory.create()
|
||||||
|
new_name = 'New Name'
|
||||||
|
with app.test_client() as c, authenticated_user(c):
|
||||||
|
rv = json_request(c.post, '/api/dashboards/{0}'.format(d.id),
|
||||||
|
data={'name': new_name, 'layout': '[]'})
|
||||||
|
self.assertEquals(rv.status_code, 200)
|
||||||
|
self.assertEquals(rv.json['name'], new_name)
|
||||||
|
|
||||||
|
def test_delete_dashbaord(self):
|
||||||
|
d = DashboardFactory.create()
|
||||||
|
with app.test_client() as c, authenticated_user(c):
|
||||||
|
rv = json_request(c.delete, '/api/dashboards/{0}'.format(d.slug))
|
||||||
|
self.assertEquals(rv.status_code, 200)
|
||||||
|
|
||||||
|
d = models.Dashboard.get_by_slug(d.slug)
|
||||||
|
self.assertTrue(d.is_archived)
|
||||||
|
|
||||||
|
|
||||||
class QueryAPITest(unittest.TestCase, AuthenticationTestMixin):
|
class QueryAPITest(BaseTestCase, AuthenticationTestMixin):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.paths = ['/api/queries']
|
self.paths = ['/api/queries']
|
||||||
|
super(QueryAPITest, self).setUp()
|
||||||
|
|
||||||
|
|
||||||
class QueryResultAPITest(unittest.TestCase, AuthenticationTestMixin):
|
class QueryResultAPITest(BaseTestCase, AuthenticationTestMixin):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.paths = []
|
self.paths = []
|
||||||
|
super(QueryResultAPITest, self).setUp()
|
||||||
|
|
||||||
|
|
||||||
class JobAPITest(unittest.TestCase, AuthenticationTestMixin):
|
class JobAPITest(BaseTestCase, AuthenticationTestMixin):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.paths = []
|
self.paths = []
|
||||||
|
super(JobAPITest, self).setUp()
|
||||||
|
|
||||||
|
|
||||||
class CsvQueryResultAPITest(unittest.TestCase, AuthenticationTestMixin):
|
class CsvQueryResultAPITest(BaseTestCase, AuthenticationTestMixin):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.paths = []
|
self.paths = []
|
||||||
|
super(CsvQueryResultAPITest, self).setUp()
|
@ -1,31 +1,14 @@
|
|||||||
from unittest import TestCase
|
from tests import BaseTestCase, DashboardFactory
|
||||||
from redash import settings, db, app, models
|
|
||||||
|
|
||||||
settings.DATABASE_CONFIG = {
|
|
||||||
'name': 'rd_test',
|
|
||||||
'engine': 'peewee.PostgresqlDatabase',
|
|
||||||
'threadlocals': True
|
|
||||||
}
|
|
||||||
app.config['DATABASE'] = settings.DATABASE_CONFIG
|
|
||||||
db.load_database()
|
|
||||||
|
|
||||||
|
|
||||||
class DatabaseTestCase(TestCase):
|
class DashboardTest(BaseTestCase):
|
||||||
def setUp(self):
|
|
||||||
models.create_db(True, True)
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
models.create_db(False, True)
|
|
||||||
|
|
||||||
|
|
||||||
class DashboardTest(DatabaseTestCase):
|
|
||||||
def test_appends_suffix_to_slug_when_duplicate(self):
|
def test_appends_suffix_to_slug_when_duplicate(self):
|
||||||
d1 = models.Dashboard.create(name='test', user='arik', layout='')
|
d1 = DashboardFactory.create()
|
||||||
self.assertEquals(d1.slug, 'test')
|
self.assertEquals(d1.slug, 'test')
|
||||||
|
|
||||||
d2 = models.Dashboard.create(name='test', user='arik', layout='')
|
d2 = DashboardFactory.create()
|
||||||
self.assertNotEquals(d1.slug, d2.slug)
|
self.assertNotEquals(d1.slug, d2.slug)
|
||||||
|
|
||||||
d3 = models.Dashboard.create(name='test', user='arik', layout='')
|
d3 = DashboardFactory.create()
|
||||||
self.assertNotEquals(d1.slug, d3.slug)
|
self.assertNotEquals(d1.slug, d3.slug)
|
||||||
self.assertNotEquals(d2.slug, d3.slug)
|
self.assertNotEquals(d2.slug, d3.slug)
|
Loading…
Reference in New Issue
Block a user