diff --git a/requirements-dev.txt b/requirements-dev.txt index 81da515..fc37628 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,3 @@ pytest bandit +beautifulsoup4 \ No newline at end of file diff --git a/src/tests/__init__.py b/src/tests/__init__.py index c72974e..32a4ed1 100644 --- a/src/tests/__init__.py +++ b/src/tests/__init__.py @@ -2,4 +2,5 @@ import os os.environ['CAFF_PREVIEWER_ENDPOINT'] = '' os.environ['MINIO_ENDPOINT'] = '' os.environ['MINIO_ACCESS_KEY'] = '' -os.environ['MINIO_SECRET_KEY'] = '' \ No newline at end of file +os.environ['MINIO_SECRET_KEY'] = '' +os.environ['SECURITY_PASSWORD_SALT'] = 'test' \ No newline at end of file diff --git a/src/tests/test_access_allowed.py b/src/tests/test_access_allowed.py deleted file mode 100644 index 357a8f4..0000000 --- a/src/tests/test_access_allowed.py +++ /dev/null @@ -1,20 +0,0 @@ -import pytest - -import app - - -@pytest.fixture -def client(): - app.app.config['TESTING'] = True - - with app.app.test_client() as client: - yield client - - -def test_login_required(client): - - r = client.get('/content/caff/1') - - assert r.status_code == 302 - - # TODO Test eache endpoint with an anonymus, registered and admin user \ No newline at end of file diff --git a/src/tests/test_blackbox.py b/src/tests/test_blackbox.py new file mode 100644 index 0000000..9167bc2 --- /dev/null +++ b/src/tests/test_blackbox.py @@ -0,0 +1,183 @@ +import pytest + +from bs4 import BeautifulSoup + +from utils import user_datastore +from models import db +import app + + +@pytest.fixture +def anonymous_client(): + app.app.config['TESTING'] = True + + with app.app.test_client() as client: + with app.app.app_context(): + db.drop_all() + db.create_all() + yield client + + +@pytest.fixture +def logged_in_client(): + app.app.config['TESTING'] = True + + with app.app.test_client() as client: + with app.app.app_context(): + db.drop_all() + db.create_all() + user = user_datastore.create_user(email="test", password="test") + user.name = 'test' + + r = client.get('/login') + + soup = BeautifulSoup(r.data.decode(), 'html.parser') + + for input_tag in soup.find_all('input'): + if input_tag['name'] == 'csrf_token': + csrf_token = input_tag['value'] + + r = client.post('/login', data=dict( + email='test', + password='test', + csrf_token=csrf_token + ), follow_redirects=True) + + assert r.status_code == 200 + yield client + + +@pytest.fixture +def admin_client(): + app.app.config['TESTING'] = True + + with app.app.test_client() as client: + with app.app.app_context(): + db.drop_all() + db.create_all() + user_datastore.create_role(name='administrator') + user = user_datastore.create_user(email="test", password="test", roles=['administrator']) + user.name = 'test' + + r = client.get('/login') + + soup = BeautifulSoup(r.data.decode(), 'html.parser') + + for input_tag in soup.find_all('input'): + if input_tag['name'] == 'csrf_token': + csrf_token = input_tag['value'] + + r = client.post('/login', data=dict( + email='test', + password='test', + csrf_token=csrf_token + ), follow_redirects=True) + + assert r.status_code == 200 + yield client + + +# +# The actual tests +# +# Syntax: +# test_{username}_{type of test}_{subject of test}(...) +# username: admin, user, anonymous + + +# +# Some simple ux tests first +# + +def test_admin_have_admin_button_homepage(admin_client): + r = admin_client.get('/') + assert r.status_code == 200 + + soup = BeautifulSoup(r.data.decode(), 'html.parser') + + menu_items = soup.body.nav.div.div.find_all('li') + have_button = False + for item in menu_items: + if item.a.string == 'Administrate': + have_button = True + + assert have_button + + +def test_user_not_have_admin_button_homepage(logged_in_client): + r = logged_in_client.get('/') + assert r.status_code == 200 + + soup = BeautifulSoup(r.data.decode(), 'html.parser') + + menu_items = soup.body.nav.div.div.find_all('li') + have_button = False + for item in menu_items: + if item.a.string == 'Administrate': + have_button = True + + assert not have_button + + +def test_anonymous_not_have_admin_button_homepage(anonymous_client): + r = anonymous_client.get('/') + assert r.status_code == 200 + + soup = BeautifulSoup(r.data.decode(), 'html.parser') + + menu_items = soup.body.nav.div.div.find_all('li') + have_button = False + for item in menu_items: + if item.a.string == 'Administrate': + have_button = True + + assert not have_button + + +def test_anonymous_have_to_login_protected_pages(anonymous_client): + r = anonymous_client.get('/upload') + assert r.status_code == 200 + + soup = BeautifulSoup(r.data.decode(), 'html.parser') + + assert 'Log in' == soup.find_all('p')[0].a.string + + +def test_anonymous_get_login_required_redirect(anonymous_client): + for path in ['/content/caff/1', '/profile']: + r = anonymous_client.get(path) + assert r.status_code == 302 + + +def test_anonymous_post_login_required_redirect(anonymous_client): + for path in ['/upload', '/item/1']: + r = anonymous_client.post(path) + assert r.status_code == 302 + + +def test_logged_in_ok(logged_in_client): + r = logged_in_client.get('/profile') + assert r.status_code == 200 + + +# +# Admin pages +# + + +def test_admin_access_admin(admin_client): + for path in ['/admin/', '/admin/user/', '/admin/comment/', '/admin/item/', '/admin/purchase/']: + r = admin_client.get(path) + assert r.status_code == 200 + + +def test_user_access_admin(logged_in_client): + for path in ['/admin/', '/admin/user/', '/admin/comment/', '/admin/item/', '/admin/purchase/']: + r = logged_in_client.get(path) + assert r.status_code == 401 + + +def test_anonymus_access_admin(anonymous_client): + for path in ['/admin/', '/admin/user/', '/admin/comment/', '/admin/item/', '/admin/purchase/']: + r = anonymous_client.get(path) + assert r.status_code == 401