From bf6d3b737a6e00da6fe669549b10eac5d6de4e23 Mon Sep 17 00:00:00 2001 From: paulmart-n Date: Tue, 21 May 2024 13:29:43 +0200 Subject: [PATCH] Setup Tests --- fetchMENSA.py | 4 +- fetchRAPLA.py | 6 +-- init.py | 10 ++--- routing.py | 41 ++++++++++----------- templates/kurs.html | 4 +- templates/rapla.html | 4 +- tests_examples/login_data.py | 1 + tests_examples/test_app.py | 71 ++++++++++++++++++++++++++++++++---- 8 files changed, 99 insertions(+), 42 deletions(-) diff --git a/fetchMENSA.py b/fetchMENSA.py index 2d9163f..ac16679 100644 --- a/fetchMENSA.py +++ b/fetchMENSA.py @@ -2,7 +2,7 @@ import json import asyncio -from init import db, Meals, scheduler, app +from init import db, Meals, scheduler, flask_app import datetime import time 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') def mensaschedule(): - with app.app_context(): + with flask_app.app_context(): asyncio.run(refreshMeals()) diff --git a/fetchRAPLA.py b/fetchRAPLA.py index 6ac29f5..569969d 100644 --- a/fetchRAPLA.py +++ b/fetchRAPLA.py @@ -9,7 +9,7 @@ import icalendar from icalendar import Calendar, Event import json -from init import scheduler, app, Rapla, db +from init import scheduler, flask_app, Rapla, db async def fetchPlan(session, url): @@ -98,7 +98,7 @@ def getIcal(kurs: str): rapla = Rapla.query.filter(Rapla.name == kurs).first() try: return rapla.file - except KeyError: + except AttributeError or KeyError: return None @@ -136,7 +136,7 @@ async def refreshRapla(): @scheduler.task('cron', id="raplaschedule", hour='*', day_of_week='*', minute='*/3', week='*', second='40') def raplaSchedule(): - with app.app_context(): + with flask_app.app_context(): asyncio.run(refreshRapla()) diff --git a/init.py b/init.py index df01769..4443af5 100644 --- a/init.py +++ b/init.py @@ -91,13 +91,13 @@ class Meals(db.Model): scheduler = APScheduler() -app = create() -with app.app_context(): +flask_app = create() +with flask_app.app_context(): print("Creating Tables....") db.create_all() def_src = ["*.paulmartin.cloud", '\'self\''] -Talisman(app, content_security_policy={"default-src": def_src, "script-src": def_src # + ["'unsafe-inline'"] - }) -scheduler.init_app(app) +Talisman(flask_app, content_security_policy={"default-src": def_src, "script-src": def_src # + ["'unsafe-inline'"] + }) +scheduler.init_app(flask_app) scheduler.start() scheduler.api_enabled = True diff --git a/routing.py b/routing.py index 220d849..0e4576c 100644 --- a/routing.py +++ b/routing.py @@ -18,12 +18,12 @@ from calendar_generation import getWeek from init import * -def init_routes(flask_app: Flask): +def init_routes(app: Flask): """ Initialisiert die App-Routen. Nötig für Tests. """ - @flask_app.route("/") + @app.route("/") def index(): """ Leitet den normalen Website-Aufruf zum Login weiter. @@ -31,7 +31,7 @@ def init_routes(flask_app: Flask): """ return redirect(url_for("login")) - @flask_app.route("/dashboard") + @app.route("/dashboard") @login_required def welcome(): """ @@ -53,7 +53,7 @@ def init_routes(flask_app: Flask): 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 async def displayNoten(): """ @@ -76,7 +76,7 @@ def init_routes(flask_app: Flask): noten = await fetchDUALIS.getResults(t, c, chosensemester) 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 async def displayRapla(): """ @@ -100,7 +100,7 @@ def init_routes(flask_app: Flask): mon=events[4], s="p", praxis="hidden") - @flask_app.route("/plan/") + @app.route("/plan/") async def displayPlan(kurs): """ Zeigt den Stundenplan ohne Login an. \n @@ -130,7 +130,7 @@ def init_routes(flask_app: Flask): else: return redirect(url_for("login")) - @flask_app.route("/set-up") + @app.route("/set-up") def redKurs(): """ Setup beginnt mit Kurs. @@ -138,7 +138,7 @@ def init_routes(flask_app: Flask): """ return redirect(url_for("getKurs")) - @flask_app.route("/set-up/kurs") + @app.route("/set-up/kurs") @login_required async def getKurs(): """ @@ -173,7 +173,7 @@ def init_routes(flask_app: Flask): kurs = "" 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 async def getSemester(): """ @@ -194,7 +194,7 @@ def init_routes(flask_app: Flask): semester = getSemesterList(current_user.id) 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 def setSemester(): """ @@ -209,7 +209,7 @@ def init_routes(flask_app: Flask): db.session.commit() return redirect(n) - @flask_app.route("/set-up/rapla") + @app.route("/set-up/rapla") @login_required def chooseRaplas(): """ @@ -219,7 +219,7 @@ def init_routes(flask_app: Flask): r = getRaplas() 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 async def getRapla(): """ @@ -242,7 +242,7 @@ def init_routes(flask_app: Flask): return redirect(url_for("error", ecode=900)) return redirect(url_for("welcome")) - @flask_app.route("/log-in") + @app.route("/log-in") def login(): """ Login-Maske. @@ -250,7 +250,7 @@ def init_routes(flask_app: Flask): """ 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(): """ Verarbeitet die Eingabe von login(). \n @@ -283,7 +283,6 @@ def init_routes(flask_app: Flask): elif not n: success = make_response(redirect(url_for("welcome"))) success.set_cookie("cnsc", value=newcookie, httponly=True, secure=True) - else: hashid = int(hashlib.sha1(email.encode("utf-8")).hexdigest(), 16) % (10 ** 8) pname = email.find(".") + 1 @@ -300,7 +299,7 @@ def init_routes(flask_app: Flask): success.set_cookie("cnsc", value=cookie, httponly=True, secure=True) return success - @flask_app.route("/log-out") + @app.route("/log-out") @login_required async def logout(): """ @@ -319,7 +318,7 @@ def init_routes(flask_app: Flask): secure=True) return red - @flask_app.route("/error") + @app.route("/error") def error(): """ Error Page für custom-Errors. \n @@ -335,8 +334,8 @@ def init_routes(flask_app: Flask): msg = str(error) return render_template('display-message.html', message=msg) - @flask_app.route("/error") - @flask_app.errorhandler(HTTPException) + @app.route("/error") + @app.errorhandler(HTTPException) def handle(e): """" HTTP-Exception-Handler @@ -345,5 +344,5 @@ def init_routes(flask_app: Flask): if __name__ == "__main__": - init_routes(app) - app.run(host='0.0.0.0', port=2024, debug=True) + init_routes(flask_app) + flask_app.run(host='0.0.0.0', port=2024, debug=True) diff --git a/templates/kurs.html b/templates/kurs.html index b5a7b7d..d47ac19 100644 --- a/templates/kurs.html +++ b/templates/kurs.html @@ -4,7 +4,7 @@ {% if file %}

Wir haben {{ detected[0] }} als deinen Kurs ermittelt. Falls er nicht stimmt, kannst du ihn unten auswählen.

{% if not request.args.get("next") %} -
+ {% else %} {% endif %} @@ -16,7 +16,7 @@ {% else %}

Dein Kurs konnte leider nicht ermittelt werden. Klicke den Button, um zur Auswahl zu kommen.

{% endif %} - +
{% endblock %} \ No newline at end of file diff --git a/templates/rapla.html b/templates/rapla.html index 149f98e..7ec5f29 100644 --- a/templates/rapla.html +++ b/templates/rapla.html @@ -1,7 +1,7 @@ {% extends "index.html" %} {% block content %}

Verfügbare Raplas

-
+

Eigenen Rapla hinzufügen

-
+ diff --git a/tests_examples/login_data.py b/tests_examples/login_data.py index 73b7d40..8c29109 100644 --- a/tests_examples/login_data.py +++ b/tests_examples/login_data.py @@ -1,2 +1,3 @@ email = "EMAIL-GOES-HERE" password = "PASSWORD-GOES-HERE" +kurs_url = "RAPLA-URL-GOES-HERE" diff --git a/tests_examples/test_app.py b/tests_examples/test_app.py index 9acfb33..436cee3 100644 --- a/tests_examples/test_app.py +++ b/tests_examples/test_app.py @@ -24,7 +24,7 @@ def app(): @pytest.fixture() def client(app): - return app.test_client() + return app.test_client(use_cookies=True) @pytest.fixture() @@ -36,10 +36,13 @@ def login(client): client.post('/log-in', data=dict(email=login_data.email, password=login_data.password), follow_redirects=True) 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) assert b"Einloggen" in loginpage.data 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), follow_redirects=True) 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): if login(client): notenpage = client.get("/theorie/noten", follow_redirects=True) assert notenpage.status_code == 200 - - assert b"Deine Noten im" in notenpage.data + notenpage_html = BeautifulSoup(notenpage.text, "lxml") + 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): loginpage = client.get("/log-out", follow_redirects=True) assert loginpage.status_code == 200 assert b"Einloggen" in loginpage.data cookie = client.get_cookie("cnsc") assert len(cookie.value) != 32 # CNSC-Länge: 32 → CNSC darf ausgeloggt nicht gesetzt sein + else: + assert False