Setup Tests

This commit is contained in:
2024-05-21 13:29:43 +02:00
parent 2153bb07b9
commit bf6d3b737a
8 changed files with 99 additions and 42 deletions

View File

@ -2,7 +2,7 @@ import json
import asyncio import asyncio
from init import db, Meals, scheduler, app from init import db, Meals, scheduler, flask_app
import datetime import datetime
import time import time
import httpx import httpx
@ -143,5 +143,5 @@ async def refreshMeals():
@scheduler.task('cron', id="mensaschedule", hour='8-11', day_of_week='*', minute='*/15', week='*', second='5') @scheduler.task('cron', id="mensaschedule", hour='8-11', day_of_week='*', minute='*/15', week='*', second='5')
def mensaschedule(): def mensaschedule():
with app.app_context(): with flask_app.app_context():
asyncio.run(refreshMeals()) asyncio.run(refreshMeals())

View File

@ -9,7 +9,7 @@ import icalendar
from icalendar import Calendar, Event from icalendar import Calendar, Event
import json import json
from init import scheduler, app, Rapla, db from init import scheduler, flask_app, Rapla, db
async def fetchPlan(session, url): async def fetchPlan(session, url):
@ -98,7 +98,7 @@ def getIcal(kurs: str):
rapla = Rapla.query.filter(Rapla.name == kurs).first() rapla = Rapla.query.filter(Rapla.name == kurs).first()
try: try:
return rapla.file return rapla.file
except KeyError: except AttributeError or KeyError:
return None return None
@ -136,7 +136,7 @@ async def refreshRapla():
@scheduler.task('cron', id="raplaschedule", hour='*', day_of_week='*', minute='*/3', week='*', second='40') @scheduler.task('cron', id="raplaschedule", hour='*', day_of_week='*', minute='*/3', week='*', second='40')
def raplaSchedule(): def raplaSchedule():
with app.app_context(): with flask_app.app_context():
asyncio.run(refreshRapla()) asyncio.run(refreshRapla())

10
init.py
View File

@ -91,13 +91,13 @@ class Meals(db.Model):
scheduler = APScheduler() scheduler = APScheduler()
app = create() flask_app = create()
with app.app_context(): with flask_app.app_context():
print("Creating Tables....") print("Creating Tables....")
db.create_all() db.create_all()
def_src = ["*.paulmartin.cloud", '\'self\''] def_src = ["*.paulmartin.cloud", '\'self\'']
Talisman(app, content_security_policy={"default-src": def_src, "script-src": def_src # + ["'unsafe-inline'"] Talisman(flask_app, content_security_policy={"default-src": def_src, "script-src": def_src # + ["'unsafe-inline'"]
}) })
scheduler.init_app(app) scheduler.init_app(flask_app)
scheduler.start() scheduler.start()
scheduler.api_enabled = True scheduler.api_enabled = True

View File

@ -18,12 +18,12 @@ from calendar_generation import getWeek
from init import * from init import *
def init_routes(flask_app: Flask): def init_routes(app: Flask):
""" """
Initialisiert die App-Routen. Nötig für Tests. Initialisiert die App-Routen. Nötig für Tests.
""" """
@flask_app.route("/") @app.route("/")
def index(): def index():
""" """
Leitet den normalen Website-Aufruf zum Login weiter. Leitet den normalen Website-Aufruf zum Login weiter.
@ -31,7 +31,7 @@ def init_routes(flask_app: Flask):
""" """
return redirect(url_for("login")) return redirect(url_for("login"))
@flask_app.route("/dashboard") @app.route("/dashboard")
@login_required @login_required
def welcome(): def welcome():
""" """
@ -53,7 +53,7 @@ def init_routes(flask_app: Flask):
p = "" p = ""
return render_template('dashboard.html', kurs=kurs, name=name, theorie=t, praxis=p) return render_template('dashboard.html', kurs=kurs, name=name, theorie=t, praxis=p)
@flask_app.route("/theorie/noten", methods=["GET", "POST"]) @app.route("/theorie/noten", methods=["GET", "POST"])
@login_required @login_required
async def displayNoten(): async def displayNoten():
""" """
@ -76,7 +76,7 @@ def init_routes(flask_app: Flask):
noten = await fetchDUALIS.getResults(t, c, chosensemester) noten = await fetchDUALIS.getResults(t, c, chosensemester)
return render_template("noten.html", noten=noten, semester=semester, sel=chosensemester, s="n", praxis="hidden") return render_template("noten.html", noten=noten, semester=semester, sel=chosensemester, s="n", praxis="hidden")
@flask_app.route("/plan", methods=["GET"]) @app.route("/plan", methods=["GET"])
@login_required @login_required
async def displayRapla(): async def displayRapla():
""" """
@ -100,7 +100,7 @@ def init_routes(flask_app: Flask):
mon=events[4], mon=events[4],
s="p", praxis="hidden") s="p", praxis="hidden")
@flask_app.route("/plan/<string:kurs>") @app.route("/plan/<string:kurs>")
async def displayPlan(kurs): async def displayPlan(kurs):
""" """
Zeigt den Stundenplan ohne Login an. \n Zeigt den Stundenplan ohne Login an. \n
@ -130,7 +130,7 @@ def init_routes(flask_app: Flask):
else: else:
return redirect(url_for("login")) return redirect(url_for("login"))
@flask_app.route("/set-up") @app.route("/set-up")
def redKurs(): def redKurs():
""" """
Setup beginnt mit Kurs. Setup beginnt mit Kurs.
@ -138,7 +138,7 @@ def init_routes(flask_app: Flask):
""" """
return redirect(url_for("getKurs")) return redirect(url_for("getKurs"))
@flask_app.route("/set-up/kurs") @app.route("/set-up/kurs")
@login_required @login_required
async def getKurs(): async def getKurs():
""" """
@ -173,7 +173,7 @@ def init_routes(flask_app: Flask):
kurs = "" kurs = ""
return render_template('kurs.html', detected=(kurs, e), s="s", theorie="hidden", praxis="hidden", file=True) return render_template('kurs.html', detected=(kurs, e), s="s", theorie="hidden", praxis="hidden", file=True)
@flask_app.route("/set-up/semester") @app.route("/set-up/semester")
@login_required @login_required
async def getSemester(): async def getSemester():
""" """
@ -194,7 +194,7 @@ def init_routes(flask_app: Flask):
semester = getSemesterList(current_user.id) semester = getSemesterList(current_user.id)
return render_template("semester.html", semester=semester, s="s", theorie="hidden", praxis="hidden") return render_template("semester.html", semester=semester, s="s", theorie="hidden", praxis="hidden")
@flask_app.route("/set-up/semester", methods=["POST"]) @app.route("/set-up/semester", methods=["POST"])
@login_required @login_required
def setSemester(): def setSemester():
""" """
@ -209,7 +209,7 @@ def init_routes(flask_app: Flask):
db.session.commit() db.session.commit()
return redirect(n) return redirect(n)
@flask_app.route("/set-up/rapla") @app.route("/set-up/rapla")
@login_required @login_required
def chooseRaplas(): def chooseRaplas():
""" """
@ -219,7 +219,7 @@ def init_routes(flask_app: Flask):
r = getRaplas() r = getRaplas()
return render_template("rapla.html", raplas=r, s="s", theorie="hidden", praxis="hidden") return render_template("rapla.html", raplas=r, s="s", theorie="hidden", praxis="hidden")
@flask_app.route("/set-up/rapla", methods=["POST"]) @app.route("/set-up/rapla", methods=["POST"])
@login_required @login_required
async def getRapla(): async def getRapla():
""" """
@ -242,7 +242,7 @@ def init_routes(flask_app: Flask):
return redirect(url_for("error", ecode=900)) return redirect(url_for("error", ecode=900))
return redirect(url_for("welcome")) return redirect(url_for("welcome"))
@flask_app.route("/log-in") @app.route("/log-in")
def login(): def login():
""" """
Login-Maske. Login-Maske.
@ -250,7 +250,7 @@ def init_routes(flask_app: Flask):
""" """
return render_template("login.html", theorie="hidden", praxis="hidden", s="s") return render_template("login.html", theorie="hidden", praxis="hidden", s="s")
@flask_app.route("/log-in", methods=["POST"]) @app.route("/log-in", methods=["POST"])
async def login_post(): async def login_post():
""" """
Verarbeitet die Eingabe von login(). \n Verarbeitet die Eingabe von login(). \n
@ -283,7 +283,6 @@ def init_routes(flask_app: Flask):
elif not n: elif not n:
success = make_response(redirect(url_for("welcome"))) success = make_response(redirect(url_for("welcome")))
success.set_cookie("cnsc", value=newcookie, httponly=True, secure=True) success.set_cookie("cnsc", value=newcookie, httponly=True, secure=True)
else: else:
hashid = int(hashlib.sha1(email.encode("utf-8")).hexdigest(), 16) % (10 ** 8) hashid = int(hashlib.sha1(email.encode("utf-8")).hexdigest(), 16) % (10 ** 8)
pname = email.find(".") + 1 pname = email.find(".") + 1
@ -300,7 +299,7 @@ def init_routes(flask_app: Flask):
success.set_cookie("cnsc", value=cookie, httponly=True, secure=True) success.set_cookie("cnsc", value=cookie, httponly=True, secure=True)
return success return success
@flask_app.route("/log-out") @app.route("/log-out")
@login_required @login_required
async def logout(): async def logout():
""" """
@ -319,7 +318,7 @@ def init_routes(flask_app: Flask):
secure=True) secure=True)
return red return red
@flask_app.route("/error") @app.route("/error")
def error(): def error():
""" """
Error Page für custom-Errors. \n Error Page für custom-Errors. \n
@ -335,8 +334,8 @@ def init_routes(flask_app: Flask):
msg = str(error) msg = str(error)
return render_template('display-message.html', message=msg) return render_template('display-message.html', message=msg)
@flask_app.route("/error") @app.route("/error")
@flask_app.errorhandler(HTTPException) @app.errorhandler(HTTPException)
def handle(e): def handle(e):
"""" """"
HTTP-Exception-Handler HTTP-Exception-Handler
@ -345,5 +344,5 @@ def init_routes(flask_app: Flask):
if __name__ == "__main__": if __name__ == "__main__":
init_routes(app) init_routes(flask_app)
app.run(host='0.0.0.0', port=2024, debug=True) flask_app.run(host='0.0.0.0', port=2024, debug=True)

View File

@ -4,7 +4,7 @@
{% if file %} {% if file %}
<h1>Wir haben {{ detected[0] }} als deinen Kurs ermittelt. Falls er nicht stimmt, kannst du ihn unten auswählen.</h1> <h1>Wir haben {{ detected[0] }} als deinen Kurs ermittelt. Falls er nicht stimmt, kannst du ihn unten auswählen.</h1>
{% if not request.args.get("next") %} {% if not request.args.get("next") %}
<form action={{ url_for("getSemester") }}> <form id="autoForm" action={{ url_for("getSemester") }}>
{% else %} {% else %}
<form action={{ request.args.get("next") }}> <form action={{ request.args.get("next") }}>
{% endif %} {% endif %}
@ -16,7 +16,7 @@
{% else %} {% else %}
<h1>Dein Kurs konnte leider nicht ermittelt werden. Klicke den Button, um zur Auswahl zu kommen.</h1> <h1>Dein Kurs konnte leider nicht ermittelt werden. Klicke den Button, um zur Auswahl zu kommen.</h1>
{% endif %} {% endif %}
<form action={{ url_for("chooseRaplas", next=request.args.get("next")) }}> <form id="manualForm" action={{ url_for("chooseRaplas", next=request.args.get("next")) }}>
<input type="submit" value="Manuell auswählen!"> <input type="submit" value="Manuell auswählen!">
</form> </form>
{% endblock %} {% endblock %}

View File

@ -1,7 +1,7 @@
{% extends "index.html" %} {% extends "index.html" %}
{% block content %} {% block content %}
<h1>Verfügbare Raplas </h1> <h1>Verfügbare Raplas </h1>
<form method="post" action={{ url_for ("getRapla") }}> <form id="dbForm" method="post" action={{ url_for ("getRapla") }}>
<label for="file">Vefügbaren RAPLA wählen! </label> <label for="file">Vefügbaren RAPLA wählen! </label>
<select name="file" id="file"> <select name="file" id="file">
@ -13,7 +13,7 @@
<input type="submit" value="Importieren!"> <input type="submit" value="Importieren!">
</form> </form>
<h1>Eigenen Rapla hinzufügen</h1> <h1>Eigenen Rapla hinzufügen</h1>
<form method="post" action={{ url_for ("getRapla") }}> <form id="manualForm" method="post" action={{ url_for ("getRapla") }}>
<label for="url">Rapla-URL eingeben, falls Du Deinen Kurs nicht siehst:</label> <label for="url">Rapla-URL eingeben, falls Du Deinen Kurs nicht siehst:</label>
<input type="url" name="url" id="url"> <input type="url" name="url" id="url">
<input type="submit" value="Importieren!"> <input type="submit" value="Importieren!">

View File

@ -1,2 +1,3 @@
email = "EMAIL-GOES-HERE" email = "EMAIL-GOES-HERE"
password = "PASSWORD-GOES-HERE" password = "PASSWORD-GOES-HERE"
kurs_url = "RAPLA-URL-GOES-HERE"

View File

@ -24,7 +24,7 @@ def app():
@pytest.fixture() @pytest.fixture()
def client(app): def client(app):
return app.test_client() return app.test_client(use_cookies=True)
@pytest.fixture() @pytest.fixture()
@ -36,10 +36,13 @@ def login(client):
client.post('/log-in', data=dict(email=login_data.email, password=login_data.password), client.post('/log-in', data=dict(email=login_data.email, password=login_data.password),
follow_redirects=True) follow_redirects=True)
cookie = client.get_cookie("cnsc") cookie = client.get_cookie("cnsc")
return len(cookie.value) == 32 try:
return len(cookie.value) == 32 # CNSC-Länge: 32 → Wenn der Cookie so lang ist, ist man erfolgreich eingeloggt.
except AttributeError:
return False
def test_login(client): def tesst_login(client):
loginpage = client.get("/log-in", follow_redirects=True) loginpage = client.get("/log-in", follow_redirects=True)
assert b"Einloggen" in loginpage.data assert b"Einloggen" in loginpage.data
assert loginpage.status_code == 200 assert loginpage.status_code == 200
@ -49,21 +52,75 @@ def test_login(client):
login_request = client.post(login_action, data=dict(email=login_data.email, password=login_data.password), login_request = client.post(login_action, data=dict(email=login_data.email, password=login_data.password),
follow_redirects=True) follow_redirects=True)
assert login_request.status_code == 200 assert login_request.status_code == 200
assert b"Willkommen, " in login_request.data cookie = client.get_cookie("cnsc")
assert len(cookie.value) == 32 # CNSC-Länge: 32 → Wenn der Cookie so lang ist, ist man erfolgreich eingeloggt.
def tesst_kurssetup(client):
if login(client):
kurspage = client.get("/set-up", follow_redirects=True)
assert kurspage.status_code == 200
kurspage_html = BeautifulSoup(kurspage.text, "lxml")
kursbutton = kurspage_html.find("form", {"id": "manualForm"})
kursbutton_action = kursbutton.get("action")
planpage = client.get(kursbutton_action, follow_redirects=True)
assert planpage.status_code == 200
planpage_html = BeautifulSoup(planpage.text, "lxml")
planpage_form = planpage_html.find("form", {"id": "manualForm"})
planpage_action = planpage_form.get("action")
set_request = client.post(planpage_action, data=dict(url=login_data.kurs_url), follow_redirects=True)
assert set_request.status_code == 200
assert b"Willkommen, " in set_request.data
else:
assert False
def tesst_semestersetup(client):
if login(client):
semesterpage = client.get("/set-up/semester", follow_redirects=True)
assert semesterpage.status_code == 200
semesterpage_html = BeautifulSoup(semesterpage.text, "lxml")
semesterform = semesterpage_html.find("form")
semesterform_action = semesterform.get("action")
semesterform_options = semesterform.find_all("option")
nextpage = client.post(semesterform_action, data=dict(sem=semesterform_options[-1].get("value")),
follow_redirects=True)
assert nextpage.status_code == 200
assert b"Willkommen, " in nextpage.data
else:
assert False
def test_noten(client): def test_noten(client):
if login(client): if login(client):
notenpage = client.get("/theorie/noten", follow_redirects=True) notenpage = client.get("/theorie/noten", follow_redirects=True)
assert notenpage.status_code == 200 assert notenpage.status_code == 200
notenpage_html = BeautifulSoup(notenpage.text, "lxml")
assert b"Deine Noten im" in notenpage.data notenpage_heading = notenpage_html.find("h1")
notenpage_form = notenpage_html.find("form")
notenpage_action = notenpage_form.get("action")
notenpage_selection = notenpage_form.find("select")
notenpage_options = notenpage_selection.find_all("option")
notenpage_semester = "Not found!"
nextpage = "Not found!"
for i in notenpage_options:
if i.get("selected") == "":
notenpage_semester = i.text[:-1]
else:
nextpage = i.get("value")
assert notenpage_semester.encode("utf-8") in notenpage_heading.encode("utf-8")
nextpage = client.post(notenpage_action, data=dict(sem=nextpage), follow_redirects=True)
assert nextpage.status_code == 200
else:
assert False
def test_logout(client): def tesst_logout(client):
if login(client): if login(client):
loginpage = client.get("/log-out", follow_redirects=True) loginpage = client.get("/log-out", follow_redirects=True)
assert loginpage.status_code == 200 assert loginpage.status_code == 200
assert b"Einloggen" in loginpage.data assert b"Einloggen" in loginpage.data
cookie = client.get_cookie("cnsc") cookie = client.get_cookie("cnsc")
assert len(cookie.value) != 32 # CNSC-Länge: 32 → CNSC darf ausgeloggt nicht gesetzt sein assert len(cookie.value) != 32 # CNSC-Länge: 32 → CNSC darf ausgeloggt nicht gesetzt sein
else:
assert False