diff --git a/.gitignore b/.gitignore index a023bfb..aa89320 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .idea/ __pycache__/ venv/ +test.db diff --git a/QuizTheWord/admin/admin.py b/QuizTheWord/admin/admin.py index 702e860..316e025 100644 --- a/QuizTheWord/admin/admin.py +++ b/QuizTheWord/admin/admin.py @@ -68,9 +68,6 @@ def query_questions(): "multiple_choice": getattr(question, "multiple_choice", None) is not None, "hidden_answer": getattr(question, "hidden_answer", None) is not None, }) - # question1 = get_question(database.AllQuestions, 0) - # question2 = get_question(database.AllQuestions, 1) - # question3 = get_question(database.AllQuestions, 2) return jsonify(response_dict) diff --git a/QuizTheWord/config.py b/QuizTheWord/config.py index d35bc9a..a5cf603 100644 --- a/QuizTheWord/config.py +++ b/QuizTheWord/config.py @@ -29,3 +29,11 @@ class Development(Config): DEBUG = True TESTING = True DB_URL = f"postgresql+psycopg2://{Config.DB_USER}:{Config.DB_PASSWORD}@{Config.DB_HOST}:{Config.DB_PORT}/{Config.DB_NAME}" + + +class Testing(Config): + FLASK_ENV = "testing" + DEBUG = True + TESTING = True + WTF_CSRF_ENABLED = False + DB_URL = "sqlite:///test.db" diff --git a/QuizTheWord/database.py b/QuizTheWord/database.py index 3ec37b5..35c2f5f 100644 --- a/QuizTheWord/database.py +++ b/QuizTheWord/database.py @@ -3,8 +3,7 @@ from flask_security import UserMixin, RoleMixin import sqlalchemy from typing import Union, Optional, Literal, Type, List, Tuple import random -from sqlalchemy import Column, JSON, String, Integer, create_engine, ForeignKey, func, ARRAY, Boolean, UnicodeText, \ - DateTime +from sqlalchemy import Column, JSON, String, Integer, create_engine, ForeignKey, func, Boolean, UnicodeText, DateTime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.orm import sessionmaker, relationship, scoped_session @@ -31,6 +30,11 @@ def init_db(): Base.metadata.create_all(engine) +def destroy_db(): + engine = create_engine(current_app.config["DB_URL"]) + Base.metadata.drop_all(engine) + + Base = declarative_base() @@ -134,7 +138,7 @@ class MultipleChoice(Base): question_id = Column(Integer, ForeignKey("all_questions.question_id"), primary_key=True) multiple_choice_difficulty = Column(Integer) multiple_choice_hint = Column(JSON) - wrong_answers = Column(ARRAY(String)) + wrong_answers = Column(JSON) all_question_relationship = relationship("AllQuestions", lazy="joined", back_populates="multiple_choice") question_text = association_proxy("all_question_relationship", "question_text") diff --git a/requirements.txt b/requirements.txt index 65826dd..44bc5b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,3 +10,4 @@ scramp==1.2.0 SQLAlchemy==1.3.23 Werkzeug==1.0.1 Flask-Security-Too~=4.0.0 +pytest~=6.2.2 \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..67d5cdb --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,60 @@ +import os +from flask_security import hash_password, SQLAlchemySessionUserDatastore +from QuizTheWord.database import User, Role, AllQuestions, MultipleChoice, HiddenAnswer, get_session, init_db, destroy_db +import pytest + + +@pytest.fixture(scope="module") +def client(): + os.environ["CONFIGURATION_SETUP"] = "QuizTheWord.config.Testing" + from QuizTheWord import app + with app.app.test_client() as client: + with app.app.app_context(): + yield client + + +@pytest.fixture(scope="module") +def session(): + return get_session() + + +@pytest.fixture(scope="module") +def init_database(client, session): + init_db() + + user_datastore = SQLAlchemySessionUserDatastore(session, User, Role) + + admin_role = user_datastore.create_role(name="admin") + basic_user = user_datastore.create_user(email="basic@test.com", password=hash_password("password")) + admin_user = user_datastore.create_user(email="admin@test.com", password=hash_password("admin")) + + main_question = AllQuestions(question_id=0, question="question", answer="answer", addresses="") + multiple_choice = MultipleChoice(question_id=0, difficulty=1, hint="", wrong_answers=["", ""], base_question=main_question) + hidden_answer = HiddenAnswer(question_id=0, difficulty=1, hint="", base_question=main_question) + + session.add(admin_role) + session.add(basic_user) + session.add(admin_user) + session.add(main_question) + session.add(multiple_choice) + session.add(hidden_answer) + user_datastore.add_role_to_user(admin_user, admin_role) + session.commit() + + yield + + destroy_db() + + +@pytest.fixture +def login_basic_user(client, init_database): + client.post("/login", data=dict(email="basic@test.com", password="password", remember=False), follow_redirects=True) + yield + client.get('/logout', follow_redirects=True) + + +@pytest.fixture +def login_admin_user(client, init_database): + client.post("/login", data=dict(email="admin@test.com", password="admin", remember=False), follow_redirects=True) + yield + client.get('/logout', follow_redirects=True) diff --git a/tests/test_admin.py b/tests/test_admin.py new file mode 100644 index 0000000..dc13d48 --- /dev/null +++ b/tests/test_admin.py @@ -0,0 +1,11 @@ +from flask.testing import FlaskClient + + +def test_admin_home_with_basic_user(client: FlaskClient, login_basic_user): + response = client.get("/admin/") + assert response.status_code == 403 + + +def test_admin_home_with_admin_user(client: FlaskClient, login_admin_user): + response = client.get("/admin/") + assert response.status_code == 200