Setup Tests
This commit is contained in:
@ -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())
|
||||||
|
|||||||
@ -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())
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
8
init.py
8
init.py
@ -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
|
||||||
|
|||||||
41
routing.py
41
routing.py
@ -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)
|
||||||
|
|||||||
@ -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 %}
|
||||||
@ -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!">
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user