diff options
author | 2018-05-20 21:11:18 +0200 | |
---|---|---|
committer | 2018-05-20 21:11:18 +0200 | |
commit | 687fedfffa402e049c59668f2a6248ad2ba17910 (patch) | |
tree | 834e909781213650b40508398ed5a9bef10686c5 | |
parent | remove set -e (diff) |
Tests directory (#73)
moves all tests into a testing directory and splits the tests into separate files
-rw-r--r-- | .coveragerc | 14 | ||||
-rw-r--r-- | Pipfile | 2 | ||||
-rw-r--r-- | app_test.py | 519 | ||||
-rw-r--r-- | tests/__init__.py | 43 | ||||
-rw-r--r-- | tests/test_api.py | 25 | ||||
-rw-r--r-- | tests/test_api_bot_snake.py | 42 | ||||
-rw-r--r-- | tests/test_api_bot_tags.py | 72 | ||||
-rw-r--r-- | tests/test_api_bot_users.py | 18 | ||||
-rw-r--r-- | tests/test_database.py | 31 | ||||
-rw-r--r-- | tests/test_decorators.py | 25 | ||||
-rw-r--r-- | tests/test_jams.py | 11 | ||||
-rw-r--r-- | tests/test_mixins.py | 66 | ||||
-rw-r--r-- | tests/test_oauth_backend.py | 39 | ||||
-rw-r--r-- | tests/test_roots.py | 84 | ||||
-rw-r--r-- | tests/test_rst.py | 11 | ||||
-rw-r--r-- | tests/test_staff.py | 16 | ||||
-rw-r--r-- | tests/test_utilities.py | 25 | ||||
-rw-r--r-- | tests/test_websocket.py | 12 | ||||
-rw-r--r-- | tests/test_wiki.py | 34 | ||||
-rw-r--r-- | tox.ini | 2 |
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 @@ -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) @@ -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 |