aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christopher Baklid <[email protected]>2018-05-20 21:11:18 +0200
committerGravatar GitHub <[email protected]>2018-05-20 21:11:18 +0200
commit687fedfffa402e049c59668f2a6248ad2ba17910 (patch)
tree834e909781213650b40508398ed5a9bef10686c5
parentremove set -e (diff)
Tests directory (#73)
moves all tests into a testing directory and splits the tests into separate files
-rw-r--r--.coveragerc14
-rw-r--r--Pipfile2
-rw-r--r--app_test.py519
-rw-r--r--tests/__init__.py43
-rw-r--r--tests/test_api.py25
-rw-r--r--tests/test_api_bot_snake.py42
-rw-r--r--tests/test_api_bot_tags.py72
-rw-r--r--tests/test_api_bot_users.py18
-rw-r--r--tests/test_database.py31
-rw-r--r--tests/test_decorators.py25
-rw-r--r--tests/test_jams.py11
-rw-r--r--tests/test_mixins.py66
-rw-r--r--tests/test_oauth_backend.py39
-rw-r--r--tests/test_roots.py84
-rw-r--r--tests/test_rst.py11
-rw-r--r--tests/test_staff.py16
-rw-r--r--tests/test_utilities.py25
-rw-r--r--tests/test_websocket.py12
-rw-r--r--tests/test_wiki.py34
-rw-r--r--tox.ini2
20 files changed, 568 insertions, 523 deletions
diff --git a/.coveragerc b/.coveragerc
index aee4d336..60ef892f 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,5 +1,15 @@
[run]
-omit = /usr/*, gunicorn_config.py, deploy.py, app_test.py, app.py, pysite/websockets.py, pysite/views/*__init__.py, pysite/route_manager.py
+omit = /usr/*,
+ gunicorn_config.py,
+ deploy.py,
+ app_test.py,
+ app.py,
+ pysite/websockets.py,
+ pysite/views/*__init__.py,
+ pysite/route_manager.py,
+ pysite/migrations/runner.py
[report]
-exclude_lines = return jsonify
+exclude_lines = return jsonify,
+ raise RuntimeError,
+ return
diff --git a/Pipfile b/Pipfile
index 8a4c11b8..ce4b1379 100644
--- a/Pipfile
+++ b/Pipfile
@@ -39,7 +39,7 @@ python_version = "3.6"
[scripts]
start = "gunicorn -w 12 -b 0.0.0.0:10012 -c gunicorn_config.py --log-level info -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker app:app"
lint = "python -m flake8"
-test = "py.test app_test.py --cov pysite --cov-report term-missing -v"
+test = "py.test tests --cov pysite --cov-report term-missing -v"
clean = "rm -rf __pycache__ htmlcov .coverage .pytest_cache"
build = "docker build -t pythondiscord/site:latest -f docker/Dockerfile ."
push = "docker push pythondiscord/site:latest"
diff --git a/app_test.py b/app_test.py
deleted file mode 100644
index bc565112..00000000
--- a/app_test.py
+++ /dev/null
@@ -1,519 +0,0 @@
-
-import json
-import os
-
-from flask import Blueprint
-from flask_testing import TestCase
-
-os.environ["BOT_API_KEY"] = "abcdefg" # This is a constant, must be done first
-try:
- del os.environ["FLASK_DEBUG"] # Some unit tests fail if this is set
-except KeyError:
- pass
-
-from app import manager
-from gunicorn_config import _when_ready as when_ready
-
-from pysite.constants import DISCORD_OAUTH_REDIRECT, DISCORD_OAUTH_AUTHORIZED
-
-when_ready()
-
-manager.app.tests_blueprint = Blueprint("tests", __name__)
-manager.load_views(manager.app.tests_blueprint, "pysite/views/tests")
-manager.app.register_blueprint(manager.app.tests_blueprint)
-app = manager.app
-
-app.config["WTF_CSRF_CHECK_DEFAULT"] = False
-
-
-class SiteTest(TestCase):
- """ Extend TestCase with flask app instantiation """
-
- def create_app(self):
- """ Add flask app configuration settings """
- server_name = 'pytest.local'
-
- app.config['TESTING'] = True
- app.config['LIVESERVER_TIMEOUT'] = 10
- app.config['SERVER_NAME'] = server_name
- app.config['API_SUBDOMAIN'] = f'http://api.{server_name}'
- app.config['STAFF_SUBDOMAIN'] = f'http://staff.{server_name}'
- app.config['WIKI_SUBDOMAIN'] = f'http://wiki.{server_name}'
- app.allow_subdomain_redirects = True
-
- return app
-
-
-class RootEndpoint(SiteTest):
- """ Test cases for the root endpoint and error handling """
-
- def test_index(self):
- """ Check the root path responds with 200 OK """
- response = self.client.get('/', 'http://pytest.local')
- self.assertEqual(response.status_code, 200)
-
- def test_info_index(self):
- """ Check the info index path responds with a 301 """
- response = self.client.get('/info')
- self.assertEqual(response.status_code, 301)
-
- def test_info_help(self):
- """ Check the info help path responds with 200 OK """
- response = self.client.get('/info/help')
- self.assertEqual(response.status_code, 200)
-
- def test_info_resources(self):
- """ Check the info resources path responds with 200 OK """
- response = self.client.get('/info/resources')
- self.assertEqual(response.status_code, 200)
-
- def test_info_resources_json(self):
- """ Check the resources JSON loads correctly """
- response = self.client.get('/static/resources.json')
- self.assertEqual(response.status_code, 200)
- self.assertIsInstance(json.loads(response.data), dict)
-
- def test_info_rules(self):
- """ Check the info rules path responds with 200 OK """
- response = self.client.get('/info/help')
- self.assertEqual(response.status_code, 200)
-
- def test_not_found(self):
- """ Check paths without handlers returns 404 Not Found """
- response = self.client.get('/nonexistentpath')
- self.assertEqual(response.status_code, 404)
-
- def test_error(self):
- """ Check the /error/XYZ page """
- response = self.client.get('/error/418')
- self.assertEqual(response.status_code, 418)
-
- def test_invite(self):
- """ Check invite redirects """
- response = self.client.get('/invite')
- self.assertEqual(response.status_code, 302)
-
- def test_ws_test(self):
- """ Check ws_test responds """
- response = self.client.get('/ws_test')
- self.assertEqual(response.status_code, 200)
-
- def test_oauth_redirects(self):
- """ Check oauth redirects """
- response = self.client.get(DISCORD_OAUTH_REDIRECT)
- self.assertEqual(response.status_code, 302)
-
- def test_oauth_logout(self):
- """ Check oauth redirects """
- response = self.client.get('/auth/logout')
- self.assertEqual(response.status_code, 302)
-
- def test_oauth_authorized(self):
- """ Check oauth authorization """
- response = self.client.get(DISCORD_OAUTH_AUTHORIZED)
- self.assertEqual(response.status_code, 302)
-
- def test_stats_redirect(self):
- """ Check stats path redirects """
- response = self.client.get('/stats')
- self.assertEqual(response.status_code, 302)
-
- def test_500_easter_egg(self):
- """ Check the status of the /500 page"""
- response = self.client.get("/500")
- self.assertEqual(response.status_code, 500)
-
-
-class WikiEndpoints(SiteTest):
- """ Test cases for the wiki subdomain """
- def test_wiki_edit(self):
- """Test that the wiki edit page redirects to login"""
- response = self.client.get("/edit/page", app.config['WIKI_SUBDOMAIN'])
- self.assertEqual(response.status_code, 302)
-
- def test_wiki_edit_post_empty_request(self):
- """Empty request should redirect to login"""
- response = self.client.post("/edit/page", app.config['WIKI_SUBDOMAIN'])
- self.assertEqual(response.status_code, 302)
-
- def test_wiki_history(self):
- """Test the history show"""
- response = self.client.get("/history/show/blahblah-non-existant-page", app.config['WIKI_SUBDOMAIN'])
- self.assertEqual(response.status_code, 404) # Test that unknown routes 404
-
- def test_wiki_diff(self):
- """Test whether invalid revision IDs error"""
- response = self.client.get("/history/compare/ABC/XYZ", app.config['WIKI_SUBDOMAIN'])
- self.assertEqual(response.status_code, 404) # Test that unknown revisions 404
-
-
-class ApiEndpoints(SiteTest):
- """ Test cases for the api subdomain """
- def test_api_unknown_route(self):
- """ Check api unknown route """
- response = self.client.get('/', app.config['API_SUBDOMAIN'])
- self.assertEqual(response.json, {'error_code': 0, 'error_message': 'Unknown API route'})
- self.assertEqual(response.status_code, 404)
-
- def test_api_healthcheck(self):
- """ Check healthcheck url responds """
- response = self.client.get('/healthcheck', app.config['API_SUBDOMAIN'])
- self.assertEqual(response.json, {'status': 'ok'})
- self.assertEqual(response.status_code, 200)
-
- def test_snake_endpoints(self):
- """
- Tests the following endpoints:
- - snake_movies
- - snake_quiz
- - snake_names
- - snake_idioms
- - snake_facts
- """
-
- os.environ['BOT_API_KEY'] = 'abcdefg'
- headers = {'X-API-Key': 'abcdefg', 'Content-Type': 'application/json'}
-
- # GET method - get snake fact
- response = self.client.get('/bot/snake_facts', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(type(response.json), str)
-
- # GET method - get snake idiom
- response = self.client.get('/bot/snake_idioms', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(type(response.json), str)
-
- # GET method - get snake quiz
- response = self.client.get('/bot/snake_quiz', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(type(response.json), dict)
-
- # GET method - get snake name
- response = self.client.get('/bot/snake_names', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(type(response.json), dict)
-
- # GET method - get all snake names
- response = self.client.get('/bot/snake_names?get_all=True', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(type(response.json), list)
-
- def test_api_tags(self):
- """ Check tag API """
- os.environ['BOT_API_KEY'] = 'abcdefg'
- headers = {'X-API-Key': 'abcdefg', 'Content-Type': 'application/json'}
-
- post_data = json.dumps({
- 'tag_name': 'testing',
- 'tag_content': 'testing'
- })
-
- get_data = json.dumps({
- 'tag_name': 'testing'
- })
-
- bad_data = json.dumps({
- 'not_a_valid_key': 'gross_faceman'
- })
-
- # POST method - no headers
- response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'])
- self.assertEqual(response.status_code, 401)
-
- # POST method - no data
- response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 400)
-
- # POST method - bad data
- response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'], headers=headers, data=bad_data)
- self.assertEqual(response.status_code, 400)
-
- # POST method - save tag
- response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'], headers=headers, data=post_data)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.json, {"success": True})
-
- # GET method - no headers
- response = self.client.get('/bot/tags', app.config['API_SUBDOMAIN'])
- self.assertEqual(response.status_code, 401)
-
- # GET method - get all tags
- response = self.client.get('/bot/tags', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(type(response.json), list)
-
- # GET method - get specific tag
- response = self.client.get('/bot/tags?tag_name=testing', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.json, {
- 'tag_content': 'testing',
- 'tag_name': 'testing'
- })
- self.assertEqual(response.status_code, 200)
-
- # DELETE method - no headers
- response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'])
- self.assertEqual(response.status_code, 401)
-
- # DELETE method - no data
- response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 400)
-
- # DELETE method - bad data
- response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'], headers=headers, data=bad_data)
- self.assertEqual(response.status_code, 400)
-
- # DELETE method - delete the testing tag
- response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'], headers=headers, data=get_data)
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.json, {"success": True})
-
- def test_api_user(self):
- """ Check insert user """
-
- os.environ['BOT_API_KEY'] = 'abcdefg'
- headers = {'X-API-Key': 'abcdefg', 'Content-Type': 'application/json'}
- single_data = json.dumps({'user_id': "1234", 'roles': ["5678"], "username": "test", "discriminator": "0000"})
- list_data = json.dumps([{'user_id': "1234", 'roles': ["5678"], "username": "test", "discriminator": "0000"}])
-
- response = self.client.get('/bot/users', app.config['API_SUBDOMAIN'], headers=headers)
- self.assertEqual(response.status_code, 405)
-
- response = self.client.post('/bot/users', app.config['API_SUBDOMAIN'], headers=headers, data=single_data)
- self.assertTrue("inserted" in response.json)
-
- response = self.client.post('/bot/users', app.config['API_SUBDOMAIN'], headers=headers, data=list_data)
- self.assertTrue("inserted" in response.json)
-
- def test_api_route_errors(self):
- """ Check api route errors """
- from pysite.base_route import APIView
- from pysite.constants import ErrorCodes
-
- av = APIView()
- av.error(ErrorCodes.unauthorized)
- av.error(ErrorCodes.bad_data_format)
-
- def test_not_found(self):
- """ Check paths without handlers returns 404 Not Found """
- response = self.client.get('/nonexistentpath')
- self.assertEqual(response.status_code, 404)
-
-
-class StaffEndpoints(SiteTest):
- """ Test cases for staff subdomain """
- def test_staff_view(self):
- """ Check staff view redirects """
- response = self.client.get('/', app.config['STAFF_SUBDOMAIN'])
- self.assertEqual(response.status_code, 302)
-
-
-class Utilities(SiteTest):
- """ Test cases for internal utility code """
- def test_error_view_runtime_error(self):
- """ Check that wrong values for error view setup raises runtime error """
- import pysite.base_route
-
- ev = pysite.base_route.ErrorView()
- try:
- ev.setup(manager, 'sdfsdf')
- except RuntimeError:
- return True
- raise Exception('Expected runtime error on setup() when giving wrongful arguments')
-
- def test_websocket_callback(self):
- """ Check that websocket default callbacks work """
- import pysite.websockets
-
- class TestWS(pysite.websockets.WS):
- pass
-
- try:
- TestWS(None).on_message("test")
- return False
- except NotImplementedError:
- return True
-
-
-class MixinTests(SiteTest):
- """ Test cases for mixins """
-
- def test_handler_5xx(self):
- """ Check error view returns error message """
- from werkzeug.exceptions import InternalServerError
- from pysite.views.error_handlers import http_5xx
-
- error_view = http_5xx.Error500View()
- error_message = error_view.get(InternalServerError)
- self.assertEqual(error_message[1], 500)
-
- def test_route_view_runtime_error(self):
- """ Check that wrong values for route view setup raises runtime error """
- from pysite.base_route import RouteView
-
- rv = RouteView()
- try:
- rv.setup(manager, 'sdfsdf')
- except RuntimeError:
- return True
- raise Exception('Expected runtime error on setup() when giving wrongful arguments')
-
- def test_route_manager(self):
- """ Check route manager """
- from pysite.route_manager import RouteManager
-
- os.environ['WEBPAGE_SECRET_KEY'] = 'super_secret'
- rm = RouteManager()
- self.assertEqual(rm.app.secret_key, 'super_secret')
-
- def test_oauth_property(self):
- """ Make sure the oauth property works"""
- from flask import Blueprint
-
- from pysite.route_manager import RouteView
- from pysite.oauth import OauthBackend
-
- class TestRoute(RouteView):
- name = "test"
- path = "/test"
-
- tr = TestRoute()
- tr.setup(manager, Blueprint("test", "test_name"))
- self.assertIsInstance(tr.oauth, OauthBackend)
-
- def test_user_data_property(self):
- """ Make sure the user_data property works"""
- from flask import Blueprint
-
- from pysite.route_manager import RouteView
-
- class TestRoute(RouteView):
- name = "test"
- path = "/test"
-
- tr = TestRoute()
- tr.setup(manager, Blueprint("test", "test_name"))
- self.assertIs(tr.user_data, None)
-
- def test_logged_in_property(self):
- """ Make sure the user_data property works"""
- from flask import Blueprint
-
- from pysite.route_manager import RouteView
-
- class TestRoute(RouteView):
- name = "test"
- path = "/test"
-
- tr = TestRoute()
- tr.setup(manager, Blueprint("test", "test_name"))
- self.assertIs(tr.logged_in, False)
-
-
-class DecoratorTests(SiteTest):
- def test_decorator_api_json(self):
- """ Check the json validation decorator """
- from pysite.decorators import api_params
- from pysite.constants import ValidationTypes
- from schema import Schema
-
- SCHEMA = Schema([{"user_id": int, "role": int}])
-
- @api_params(schema=SCHEMA, validation_type=ValidationTypes.json)
- def try_json_type(data):
- return data
-
- try:
- try_json_type("not json")
- except Exception as error_message:
- self.assertEqual(type(error_message), AttributeError)
-
- def test_decorator_params(self):
- """ Check the params validation decorator """
-
- response = self.client.post('/testparams?test=params')
-
- self.assertEqual(response.status_code, 200)
- self.assertEqual(response.json, [{'test': 'params'}])
-
-
-class DatabaseTests(SiteTest):
- """ Test cases for the database module """
- def test_table_actions(self):
- import string
- import secrets
- from pysite.database import RethinkDB
-
- alphabet = string.ascii_letters
- generated_table_name = ''.join(secrets.choice(alphabet) for i in range(8))
-
- rdb = RethinkDB()
- # Create table name and expect it to work
- result = rdb.create_table(generated_table_name)
- self.assertEqual(result, True)
-
- # Create the same table name and expect it to already exist
- result = rdb.create_table(generated_table_name)
- self.assertEqual(result, False)
-
- # Drop table and expect it to work
- result = rdb.drop_table(generated_table_name)
- self.assertEqual(result, True)
-
- # Drop the same table and expect it to already be gone
- result = rdb.drop_table(generated_table_name)
- self.assertEqual(result, False)
-
- # This is to get some more code coverage
- self.assertEqual(rdb.teardown_request('_'), None)
-
-
-class TestWebsocketEcho(SiteTest):
- """ Test cases for the echo endpoint """
- def testEcho(self):
- """ Check rudimentary websockets handlers work """
- from geventwebsocket.websocket import WebSocket
- from pysite.views.ws.echo import EchoWebsocket
- ew = EchoWebsocket(WebSocket)
- ew.on_open()
- ew.on_message('message')
- ew.on_close()
-
-
-class TestOauthBackend(SiteTest):
- """ Test cases for the oauth.py file """
-
- def test_get(self):
- """ Make sure the get function returns nothing """
- self.assertIs(manager.oauth_backend.get(), None)
-
- def test_delete(self):
- """ Make sure the delete function returns nothing """
- self.assertIs(manager.oauth_backend.delete(None), None)
-
- def test_logout(self):
- """ Make sure at least apart of logout is working :/ """
- self.assertIs(manager.oauth_backend.logout(), None)
-
- def test_add_user(self):
- """ Make sure function adds values to database and session """
- from flask import session
-
- from pysite.constants import OAUTH_DATABASE
-
- sess_id = "hey bro wazup"
- fake_token = {"access_token": "access_token", "id": sess_id, "refresh_token": "refresh_token", "expires_at": 5}
- fake_user = {"id": 1235678987654321, "username": "Zwacky", "discriminator": "#6660", "email": "[email protected]"}
- manager.db.conn = manager.db.get_connection()
- manager.oauth_backend.add_user(fake_token, fake_user, sess_id)
-
- self.assertEqual(sess_id, session["session_id"])
- fake_token["snowflake"] = fake_user["id"]
- fake_user["user_id"] = fake_user["id"]
- del fake_user["id"]
- self.assertEqual(fake_token, manager.db.get(OAUTH_DATABASE, sess_id))
- self.assertEqual(fake_user, manager.db.get("users", fake_user["user_id"]))
-
- manager.db.delete(OAUTH_DATABASE, sess_id)
- manager.db.delete("users", fake_user["user_id"])
- manager.db.teardown_request(None)
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 00000000..84e69105
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,43 @@
+import json
+import os
+
+from flask import Blueprint
+from flask_testing import TestCase
+
+os.environ["BOT_API_KEY"] = "abcdefg" # This is a constant, must be done first
+os.environ["PAPERTRAIL_ADDRESS"] = 'localhost' # satisfies coverage
+os.environ["DATADOG_ADDRESS"] = 'localhost' # satisfies coverage
+
+if "FLASK_DEBUG" in os.environ:
+ del os.environ["FLASK_DEBUG"] # Some unit tests fail if this is set
+
+from app import manager
+from gunicorn_config import _when_ready as when_ready
+
+when_ready()
+
+manager.app.tests_blueprint = Blueprint("tests", __name__)
+manager.load_views(manager.app.tests_blueprint, "pysite/views/tests")
+manager.app.register_blueprint(manager.app.tests_blueprint)
+app = manager.app
+
+app.config["WTF_CSRF_CHECK_DEFAULT"] = False
+
+
+class SiteTest(TestCase):
+ """ Extend TestCase with flask app instantiation """
+
+ def create_app(self):
+ """ Add flask app configuration settings """
+ server_name = 'pytest.local'
+
+ app.config['TESTING'] = True
+ app.config['LIVESERVER_TIMEOUT'] = 10
+ app.config['SERVER_NAME'] = server_name
+ app.config['API_SUBDOMAIN'] = f'http://api.{server_name}'
+ app.config['STAFF_SUBDOMAIN'] = f'http://staff.{server_name}'
+ app.config['WIKI_SUBDOMAIN'] = f'http://wiki.{server_name}'
+ app.config['TEST_HEADER'] = {'X-API-Key': 'abcdefg', 'Content-Type': 'application/json'}
+ app.allow_subdomain_redirects = True
+
+ return app
diff --git a/tests/test_api.py b/tests/test_api.py
new file mode 100644
index 00000000..a0b22846
--- /dev/null
+++ b/tests/test_api.py
@@ -0,0 +1,25 @@
+from tests import SiteTest, app
+
+class ApiEndpointsRootEndpoints(SiteTest):
+ """ Test cases for the api subdomain """
+ def test_api_unknown_route(self):
+ """ Check api unknown route """
+ response = self.client.get('/', app.config['API_SUBDOMAIN'])
+ self.assertEqual(response.json, {'error_code': 0, 'error_message': 'Unknown API route'})
+ self.assertEqual(response.status_code, 404)
+
+ def test_api_healthcheck(self):
+ """ Check healthcheck url responds """
+ response = self.client.get('/healthcheck', app.config['API_SUBDOMAIN'])
+ self.assertEqual(response.json, {'status': 'ok'})
+ self.assertEqual(response.status_code, 200)
+
+ def test_api_route_errors(self):
+ """ Check api route errors """
+ from pysite.base_route import APIView
+ from pysite.constants import ErrorCodes
+
+ av = APIView()
+ av.error(ErrorCodes.unauthorized)
+ av.error(ErrorCodes.bad_data_format)
+
diff --git a/tests/test_api_bot_snake.py b/tests/test_api_bot_snake.py
new file mode 100644
index 00000000..b5aa3bab
--- /dev/null
+++ b/tests/test_api_bot_snake.py
@@ -0,0 +1,42 @@
+import os
+from tests import SiteTest, app
+
+class ApiBotSnakeEndpoints(SiteTest):
+ """
+ Tests the following endpoints:
+ - snake_movies
+ - snake_quiz
+ - snake_names
+ - snake_idioms
+ - snake_facts
+ """
+
+ def test_snake_facts(self):
+ # GET method - get snake fact
+ response = self.client.get('/bot/snake_facts', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(type(response.json), str)
+
+ def test_snake_idiom(self):
+ # GET method - get snake idiom
+ response = self.client.get('/bot/snake_idioms', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(type(response.json), str)
+
+ def test_snake_quiz(self):
+ # GET method - get snake quiz
+ response = self.client.get('/bot/snake_quiz', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(type(response.json), dict)
+
+ def test_snake_names(self):
+ # GET method - get snake name
+ response = self.client.get('/bot/snake_names', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(type(response.json), dict)
+
+ def test_snake_names_all(self):
+ # GET method - get all snake names
+ response = self.client.get('/bot/snake_names?get_all=True', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(type(response.json), list)
diff --git a/tests/test_api_bot_tags.py b/tests/test_api_bot_tags.py
new file mode 100644
index 00000000..66940f7e
--- /dev/null
+++ b/tests/test_api_bot_tags.py
@@ -0,0 +1,72 @@
+import os
+import json
+from tests import SiteTest, app
+
+class ApiBotTagsEndpoint(SiteTest):
+
+ def test_api_tags(self):
+ """ Check tag API """
+
+ post_data = json.dumps({
+ 'tag_name': 'testing',
+ 'tag_content': 'testing'
+ })
+
+ get_data = json.dumps({
+ 'tag_name': 'testing'
+ })
+
+ bad_data = json.dumps({
+ 'not_a_valid_key': 'gross_faceman'
+ })
+
+ # POST method - no headers
+ response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 401)
+
+ # POST method - no data
+ response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 400)
+
+ # POST method - bad data
+ response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'], data=bad_data)
+ self.assertEqual(response.status_code, 400)
+
+ # POST method - save tag
+ response = self.client.post('/bot/tags', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'], data=post_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.json, {"success": True})
+
+ # GET method - no headers
+ response = self.client.get('/bot/tags', app.config['API_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 401)
+
+ # GET method - get all tags
+ response = self.client.get('/bot/tags', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(type(response.json), list)
+
+ # GET method - get specific tag
+ response = self.client.get('/bot/tags?tag_name=testing', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.json, {
+ 'tag_content': 'testing',
+ 'tag_name': 'testing'
+ })
+ self.assertEqual(response.status_code, 200)
+
+ # DELETE method - no headers
+ response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 401)
+
+ # DELETE method - no data
+ response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 400)
+
+ # DELETE method - bad data
+ response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'], data=bad_data)
+ self.assertEqual(response.status_code, 400)
+
+ # DELETE method - delete the testing tag
+ response = self.client.delete('/bot/tags', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'], data=get_data)
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.json, {"success": True})
diff --git a/tests/test_api_bot_users.py b/tests/test_api_bot_users.py
new file mode 100644
index 00000000..85390210
--- /dev/null
+++ b/tests/test_api_bot_users.py
@@ -0,0 +1,18 @@
+import os
+import json
+from tests import SiteTest, app
+
+class ApiBotUsersEndpoint(SiteTest):
+ def test_api_user(self):
+ """ Check insert user """
+ single_data = json.dumps({'user_id': "1234", 'roles': ["5678"], "username": "test", "discriminator": "0000"})
+ list_data = json.dumps([{'user_id': "1234", 'roles': ["5678"], "username": "test", "discriminator": "0000"}])
+
+ response = self.client.get('/bot/users', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'])
+ self.assertEqual(response.status_code, 405)
+
+ response = self.client.post('/bot/users', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'], data=single_data)
+ self.assertTrue("inserted" in response.json)
+
+ response = self.client.post('/bot/users', app.config['API_SUBDOMAIN'], headers=app.config['TEST_HEADER'], data=list_data)
+ self.assertTrue("inserted" in response.json)
diff --git a/tests/test_database.py b/tests/test_database.py
new file mode 100644
index 00000000..237cd68d
--- /dev/null
+++ b/tests/test_database.py
@@ -0,0 +1,31 @@
+from tests import SiteTest
+
+class DatabaseTests(SiteTest):
+ """ Test cases for the database module """
+ def test_table_actions(self):
+ import string
+ import secrets
+ from pysite.database import RethinkDB
+
+ alphabet = string.ascii_letters
+ generated_table_name = ''.join(secrets.choice(alphabet) for i in range(8))
+
+ rdb = RethinkDB()
+ # Create table name and expect it to work
+ result = rdb.create_table(generated_table_name)
+ self.assertEqual(result, True)
+
+ # Create the same table name and expect it to already exist
+ result = rdb.create_table(generated_table_name)
+ self.assertEqual(result, False)
+
+ # Drop table and expect it to work
+ result = rdb.drop_table(generated_table_name)
+ self.assertEqual(result, True)
+
+ # Drop the same table and expect it to already be gone
+ result = rdb.drop_table(generated_table_name)
+ self.assertEqual(result, False)
+
+ # This is to get some more code coverage
+ self.assertEqual(rdb.teardown_request('_'), None)
diff --git a/tests/test_decorators.py b/tests/test_decorators.py
new file mode 100644
index 00000000..a73052e4
--- /dev/null
+++ b/tests/test_decorators.py
@@ -0,0 +1,25 @@
+from tests import SiteTest
+
+class DecoratorTests(SiteTest):
+ def test_decorator_api_json(self):
+ """ Check the json validation decorator """
+ from pysite.decorators import api_params
+ from pysite.constants import ValidationTypes
+ from schema import Schema
+
+ SCHEMA = Schema([{"user_id": int, "role": int}])
+
+ @api_params(schema=SCHEMA, validation_type=ValidationTypes.json)
+ def try_json_type(data):
+ return data
+
+ with self.assertRaises(AttributeError):
+ try_json_type("not json")
+
+ def test_decorator_params(self):
+ """ Check the params validation decorator """
+
+ response = self.client.post('/testparams?test=params')
+
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(response.json, [{'test': 'params'}])
diff --git a/tests/test_jams.py b/tests/test_jams.py
new file mode 100644
index 00000000..cf0d8952
--- /dev/null
+++ b/tests/test_jams.py
@@ -0,0 +1,11 @@
+from tests import SiteTest, app
+
+class JamsEndpoint(SiteTest):
+ """ Test cases for the root endpoint and error handling """
+
+ def test_jams_page(self):
+ """ Check the jams path responds with 200 OK """
+ response = self.client.get('/jams', 'http://'+app.config['SERVER_NAME'])
+ self.assertEqual(response.status_code, 200)
+
+
diff --git a/tests/test_mixins.py b/tests/test_mixins.py
new file mode 100644
index 00000000..58118ae0
--- /dev/null
+++ b/tests/test_mixins.py
@@ -0,0 +1,66 @@
+import os
+from tests import SiteTest, manager
+
+class MixinTests(SiteTest):
+ """ Test cases for mixins """
+
+ def test_handler_5xx(self):
+ """ Check error view returns error message """
+ from werkzeug.exceptions import InternalServerError
+ from pysite.views.error_handlers import http_5xx
+
+ error_view = http_5xx.Error500View()
+ error_message = error_view.get(InternalServerError)
+ self.assertEqual(error_message[1], 500)
+
+ def test_route_view_runtime_error(self):
+ """ Check that wrong values for route view setup raises runtime error """
+ from pysite.base_route import RouteView
+
+ rv = RouteView()
+
+ with self.assertRaises(RuntimeError):
+ rv.setup(manager, 'sdfsdf')
+
+ def test_oauth_property(self):
+ """ Make sure the oauth property works"""
+ from flask import Blueprint
+
+ from pysite.route_manager import RouteView
+ from pysite.oauth import OauthBackend
+
+ class TestRoute(RouteView):
+ name = "test"
+ path = "/test"
+
+ tr = TestRoute()
+ tr.setup(manager, Blueprint("test", "test_name"))
+ self.assertIsInstance(tr.oauth, OauthBackend)
+
+ def test_user_data_property(self):
+ """ Make sure the user_data property works"""
+ from flask import Blueprint
+
+ from pysite.route_manager import RouteView
+
+ class TestRoute(RouteView):
+ name = "test"
+ path = "/test"
+
+ tr = TestRoute()
+ tr.setup(manager, Blueprint("test", "test_name"))
+ self.assertIsNone(tr.user_data)
+
+ def test_logged_in_property(self):
+ """ Make sure the user_data property works"""
+ from flask import Blueprint
+
+ from pysite.route_manager import RouteView
+
+ class TestRoute(RouteView):
+ name = "test"
+ path = "/test"
+
+ tr = TestRoute()
+ tr.setup(manager, Blueprint("test", "test_name"))
+ self.assertFalse(tr.logged_in)
diff --git a/tests/test_oauth_backend.py b/tests/test_oauth_backend.py
new file mode 100644
index 00000000..58e40c25
--- /dev/null
+++ b/tests/test_oauth_backend.py
@@ -0,0 +1,39 @@
+from tests import SiteTest, manager
+
+class TestOauthBackend(SiteTest):
+ """ Test cases for the oauth.py file """
+
+ def test_get(self):
+ """ Make sure the get function returns nothing """
+ self.assertIsNone(manager.oauth_backend.get())
+
+ def test_delete(self):
+ """ Make sure the delete function returns nothing """
+ self.assertIsNone(manager.oauth_backend.delete(None))
+
+ def test_logout(self):
+ """ Make sure at least apart of logout is working :/ """
+ self.assertIsNone(manager.oauth_backend.logout())
+
+ def test_add_user(self):
+ """ Make sure function adds values to database and session """
+ from flask import session
+
+ from pysite.constants import OAUTH_DATABASE
+
+ sess_id = "hey bro wazup"
+ fake_token = {"access_token": "access_token", "id": sess_id, "refresh_token": "refresh_token", "expires_at": 5}
+ fake_user = {"id": 1235678987654321, "username": "Zwacky", "discriminator": "#6660", "email": "[email protected]"}
+ manager.db.conn = manager.db.get_connection()
+ manager.oauth_backend.add_user(fake_token, fake_user, sess_id)
+
+ self.assertEqual(sess_id, session["session_id"])
+ fake_token["snowflake"] = fake_user["id"]
+ fake_user["user_id"] = fake_user["id"]
+ del fake_user["id"]
+ self.assertEqual(fake_token, manager.db.get(OAUTH_DATABASE, sess_id))
+ self.assertEqual(fake_user, manager.db.get("users", fake_user["user_id"]))
+
+ manager.db.delete(OAUTH_DATABASE, sess_id)
+ manager.db.delete("users", fake_user["user_id"])
+ manager.db.teardown_request(None)
diff --git a/tests/test_roots.py b/tests/test_roots.py
new file mode 100644
index 00000000..0b7b129c
--- /dev/null
+++ b/tests/test_roots.py
@@ -0,0 +1,84 @@
+from tests import SiteTest
+from pysite.constants import DISCORD_OAUTH_REDIRECT
+from pysite.constants import DISCORD_OAUTH_AUTHORIZED
+from pysite.constants import ERROR_DESCRIPTIONS
+
+class RootEndpoint(SiteTest):
+ """ Test cases for the root endpoint and error handling """
+
+ def test_index(self):
+ """ Check the root path responds with 200 OK """
+ response = self.client.get('/', 'http://pytest.local')
+ self.assertEqual(response.status_code, 200)
+
+ def test_info_index(self):
+ """ Check the info index path responds with a 301 """
+ response = self.client.get('/info')
+ self.assertEqual(response.status_code, 301)
+
+ def test_info_help(self):
+ """ Check the info help path responds with 200 OK """
+ response = self.client.get('/info/help')
+ self.assertEqual(response.status_code, 200)
+
+ def test_info_resources(self):
+ """ Check the info resources path responds with 200 OK """
+ response = self.client.get('/info/resources')
+ self.assertEqual(response.status_code, 200)
+
+ def test_info_resources_json(self):
+ """ Check the resources JSON loads correctly """
+ response = self.client.get('/static/resources.json')
+ self.assertEqual(response.status_code, 200)
+ self.assertIsInstance(response.json, dict)
+
+ def test_info_rules(self):
+ """ Check the info rules path responds with 200 OK """
+ response = self.client.get('/info/help')
+ self.assertEqual(response.status_code, 200)
+
+ def test_not_found(self):
+ """ Check paths without handlers returns 404 Not Found """
+ response = self.client.get('/nonexistentpath')
+ self.assertEqual(response.status_code, 404)
+
+ def test_error(self):
+ """ Check the error pages """
+ for code in ERROR_DESCRIPTIONS.keys():
+ response = self.client.get(f'/error/{code}')
+ self.assertEqual(response.status_code, code)
+
+ def test_invite(self):
+ """ Check invite redirects """
+ response = self.client.get('/invite')
+ self.assertEqual(response.status_code, 302)
+
+ def test_ws_test(self):
+ """ Check ws_test responds """
+ response = self.client.get('/ws_test')
+ self.assertEqual(response.status_code, 200)
+
+ def test_oauth_redirects(self):
+ """ Check oauth redirects """
+ response = self.client.get(DISCORD_OAUTH_REDIRECT)
+ self.assertEqual(response.status_code, 302)
+
+ def test_oauth_logout(self):
+ """ Check oauth redirects """
+ response = self.client.get('/auth/logout')
+ self.assertEqual(response.status_code, 302)
+
+ def test_oauth_authorized(self):
+ """ Check oauth authorization """
+ response = self.client.get(DISCORD_OAUTH_AUTHORIZED)
+ self.assertEqual(response.status_code, 302)
+
+ def test_stats_redirect(self):
+ """ Check stats path redirects """
+ response = self.client.get('/stats')
+ self.assertEqual(response.status_code, 302)
+
+ def test_500_easter_egg(self):
+ """ Check the status of the /500 page"""
+ response = self.client.get("/500")
+ self.assertEqual(response.status_code, 500)
diff --git a/tests/test_rst.py b/tests/test_rst.py
new file mode 100644
index 00000000..d6328bc4
--- /dev/null
+++ b/tests/test_rst.py
@@ -0,0 +1,11 @@
+import os
+import json
+from tests import SiteTest, app
+
+class RstEndpoints(SiteTest):
+ """ Test cases for staff subdomain """
+
+ def test_staff_view(self):
+ """ Check staff view redirects """
+ response = self.client.get('/', "http://"+app.config['SERVER_NAME'])
+ self.assertEqual(response.status_code, 200)
diff --git a/tests/test_staff.py b/tests/test_staff.py
new file mode 100644
index 00000000..68c182b5
--- /dev/null
+++ b/tests/test_staff.py
@@ -0,0 +1,16 @@
+import os
+import json
+from tests import SiteTest, app
+
+class StaffEndpoints(SiteTest):
+ """ Test cases for staff subdomain """
+
+ def test_staff_view(self):
+ """ Check staff view redirects """
+ response = self.client.get('/', app.config['STAFF_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 302)
+
+ def test_jams_infractions(self):
+ """ Check staff jams infractions view redirects """
+ response = self.client.get('/jams/infractions', app.config['STAFF_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 302)
diff --git a/tests/test_utilities.py b/tests/test_utilities.py
new file mode 100644
index 00000000..61a480e2
--- /dev/null
+++ b/tests/test_utilities.py
@@ -0,0 +1,25 @@
+from tests import SiteTest, manager
+
+class Utilities(SiteTest):
+ """ Test cases for internal utility code """
+ def test_error_view_runtime_error(self):
+ """ Check that wrong values for error view setup raises runtime error """
+ import pysite.base_route
+
+ ev = pysite.base_route.ErrorView()
+
+ with self.assertRaises(RuntimeError):
+ ev.setup(manager, 'sdfsdf')
+
+ def test_websocket_callback(self):
+ """ Check that websocket default callbacks work """
+ import pysite.websockets
+
+ class TestWS(pysite.websockets.WS):
+ pass
+
+ try:
+ TestWS(None).on_message("test")
+ return False
+ except NotImplementedError:
+ return True
diff --git a/tests/test_websocket.py b/tests/test_websocket.py
new file mode 100644
index 00000000..d8a616bf
--- /dev/null
+++ b/tests/test_websocket.py
@@ -0,0 +1,12 @@
+from tests import SiteTest
+
+class TestWebsocketEcho(SiteTest):
+ """ Test cases for the echo endpoint """
+ def testEcho(self):
+ """ Check rudimentary websockets handlers work """
+ from geventwebsocket.websocket import WebSocket
+ from pysite.views.ws.echo import EchoWebsocket
+ ew = EchoWebsocket(WebSocket)
+ ew.on_open()
+ ew.on_message('message')
+ ew.on_close()
diff --git a/tests/test_wiki.py b/tests/test_wiki.py
new file mode 100644
index 00000000..e16152a1
--- /dev/null
+++ b/tests/test_wiki.py
@@ -0,0 +1,34 @@
+import os
+from tests import SiteTest, app
+
+class WikiEndpoints(SiteTest):
+ """ Test cases for the wiki subdomain """
+ def test_wiki_edit(self):
+ """Test that the wiki edit page redirects to login"""
+ response = self.client.get("/edit/page", app.config['WIKI_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 302)
+
+ def test_wiki_edit_post_empty_request(self):
+ """Empty request should redirect to login"""
+ response = self.client.post("/edit/page", app.config['WIKI_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 302)
+
+ def test_wiki_history(self):
+ """Test the history show"""
+ response = self.client.get("/history/show/blahblah-non-existant-page", app.config['WIKI_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 404) # Test that unknown routes 404
+
+ def test_wiki_diff(self):
+ """Test whether invalid revision IDs error"""
+ response = self.client.get("/history/compare/ABC/XYZ", app.config['WIKI_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 404) # Test that unknown revisions 404
+
+ def test_wiki_special(self):
+ """Test whether invalid revision IDs error"""
+ response = self.client.get("/special", app.config['WIKI_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 200)
+
+ def test_wiki_special_all_pages(self):
+ """Test whether invalid revision IDs error"""
+ response = self.client.get("/special/all_pages", app.config['WIKI_SUBDOMAIN'])
+ self.assertEqual(response.status_code, 200)
diff --git a/tox.ini b/tox.ini
index 3574bdba..9232706e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -2,5 +2,5 @@
max-line-length=120
application_import_names=pysite
ignore=P102,B311,W503,E226,S311
-exclude=__pycache__, venv, app_test.py, .venv
+exclude=__pycache__, venv, .venv, tests
import-order-style=pycharm