minor bugfixes and impromvements
This commit is contained in:
parent
1adafc1fc7
commit
65cf19f2c4
@ -5,7 +5,7 @@ from the_works.database import db as _db
|
||||
TEST_DATABASE_URI = "sqlite:///:memory:"
|
||||
|
||||
@pytest.fixture()
|
||||
def app():
|
||||
def _app():
|
||||
test_config = {
|
||||
"ENV": "Testing",
|
||||
"SQLALCHEMY_DATABASE_URI": TEST_DATABASE_URI,
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
from sqlalchemy import select
|
||||
from the_works.database import db
|
||||
from the_works.models import Genre
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
import pytest
|
||||
from the_works.database import db
|
||||
from the_works.models import Genre
|
||||
|
||||
def test_genre_create(client, app):
|
||||
def test_genre_create(client, _app):
|
||||
"""Integrated testing of adding a Genre record."""
|
||||
response = client.post("/genre/create", data={"form_Genre": "Test-Genre"}, follow_redirects=True)
|
||||
response = client.post("/genre/create", data={"form_Genre": "spam"}, follow_redirects=True)
|
||||
|
||||
# assert there was exactly 1 redirect
|
||||
assert len(response.history) == 1
|
||||
@ -15,13 +15,12 @@ def test_genre_create(client, app):
|
||||
assert response.status_code == 200
|
||||
|
||||
# assert record was successfully added to DB
|
||||
with app.app_context():
|
||||
genre = db.session.scalars(select(Genre).where(Genre.Genre == "Test-Genre")).all()
|
||||
with _app.app_context():
|
||||
genre = db.session.scalars(select(Genre).where(Genre.Genre == "spam")).all()
|
||||
assert len(genre) == 1
|
||||
assert isinstance(genre[0], Genre)
|
||||
|
||||
# assert uniqueness of records
|
||||
with pytest.raises(IntegrityError) as excinfo:
|
||||
response = client.post("/genre/create", data={"form_Genre": "Test-Genre"})
|
||||
response = client.post("/genre/create", data={"form_Genre": "spam"})
|
||||
assert "UNIQUE constraint failed" in str(excinfo.value)
|
||||
|
||||
|
||||
@ -1,17 +1,16 @@
|
||||
from the_works.models import Genre
|
||||
import pytest
|
||||
from the_works.models import Genre
|
||||
|
||||
|
||||
def test_genre_all(client, mocker):
|
||||
"""Test view all() from genre.py."""
|
||||
|
||||
# mock database function
|
||||
# Note: The original method returns an sqlalchemy.engine.Result.ScalarResult, not a list, but the template code
|
||||
# uses the return value in a way that works for both ScalarResult and list
|
||||
# mocker.patch("the_works.database.db.session.scalars", return_value=[
|
||||
mocker.patch("flask_sqlalchemy.SQLAlchemy.session.scalars", return_value=[
|
||||
Genre(ID=4, Genre="bla"),
|
||||
Genre(ID=26, Genre="blubb")
|
||||
# Note: The original scalars() method returns an sqlalchemy.engine.Result.ScalarResult, not a list
|
||||
# but the template code uses the return value in a way which works for both ScalarResult and list
|
||||
mocker.patch("flask_sqlalchemy.session.Session.scalars", return_value=[
|
||||
Genre(ID=4, Genre="spam"),
|
||||
Genre(ID=26, Genre="eggs")
|
||||
])
|
||||
|
||||
# test case: get request
|
||||
@ -19,7 +18,7 @@ def test_genre_all(client, mocker):
|
||||
assert response.status_code == 200
|
||||
assert response.data.count(b'<tr id="genre-') == 2
|
||||
|
||||
# test case: post request
|
||||
# test case: post request
|
||||
response = client.post("/genre")
|
||||
assert response.status_code == 405
|
||||
|
||||
@ -28,10 +27,10 @@ def test_genre_create(client, mocker):
|
||||
"""Test view create() from genre.py."""
|
||||
|
||||
# mock database function
|
||||
mocker.patch("flask_sqlalchemy.SQLAlchemy.session.add")
|
||||
mocker.patch("flask_sqlalchemy.session.Session.add")
|
||||
|
||||
# test a POST request with good data
|
||||
response = client.post("/genre/create", data={"form_Genre": "Testname"}, follow_redirects=True)
|
||||
response = client.post("/genre/create", data={"form_Genre": "spam"}, follow_redirects=True)
|
||||
# exactly 1 redirect
|
||||
assert len(response.history) == 1
|
||||
# redirect to the right page
|
||||
@ -45,7 +44,7 @@ def test_genre_create(client, mocker):
|
||||
|
||||
# test a POST request with bad form data
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
response = client.post("/genre/create", data={"wrong_key": "Genrename"})
|
||||
response = client.post("/genre/create", data={"wrong_key": "eggs"})
|
||||
assert "value can't be empty" in str(excinfo.value)
|
||||
|
||||
# test a POST request with empty form data
|
||||
@ -53,7 +52,7 @@ def test_genre_create(client, mocker):
|
||||
response = client.post("/genre/create", data={"form_genre": ""})
|
||||
assert "value can't be empty" in str(excinfo.value)
|
||||
|
||||
# test a GET request
|
||||
response = client.get("/genre/create", query_string={"form_Genre": "GET-Genre"})
|
||||
# test a GET request
|
||||
response = client.get("/genre/create", query_string={"form_Genre": "spam eggs"})
|
||||
assert response.status_code == 405
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,12 @@
|
||||
def test_home_startpage(client):
|
||||
"""Test view startpage() from home.py."""
|
||||
|
||||
response = client.get("/")
|
||||
|
||||
# assert good status code
|
||||
assert response.status_code == 200
|
||||
|
||||
# assert that the returned data is good HTML
|
||||
assert response.data.startswith(b"<!DOCTYPE html>\n")
|
||||
|
||||
# more test cases: POST,
|
||||
@ -1,40 +1,39 @@
|
||||
import inspect
|
||||
from flask import Blueprint, render_template, request, jsonify
|
||||
from sqlalchemy import select
|
||||
from the_works.database import db
|
||||
import the_works.models
|
||||
import inspect
|
||||
|
||||
bp = Blueprint("home", __name__)
|
||||
|
||||
# prepare list of ORM classes to be searched by search_all()
|
||||
tables = []
|
||||
for name, obj in inspect.getmembers(the_works.models):
|
||||
if inspect.isclass(obj) and issubclass(obj, the_works.models.Base) and obj.__name__ != "Base":
|
||||
tables.append(obj)
|
||||
print(f"tables is {tables}") #DEBUG
|
||||
# prepare list of ORM classes to be searched by search_all()
|
||||
def __tables():
|
||||
return [obj for name, obj in inspect.getmembers(the_works.models) if inspect.isclass(obj) and issubclass(obj, the_works.models.Base) and obj.__name__ != "Base"]
|
||||
|
||||
|
||||
@bp.route("/")
|
||||
def startpage():
|
||||
return render_template("views/home.html")
|
||||
|
||||
|
||||
@bp.route("/search")
|
||||
def search_all():
|
||||
# return when query is empty
|
||||
if not request.args.get("query"):
|
||||
return jsonify({})
|
||||
|
||||
|
||||
# get URL parameters
|
||||
s = request.args.get("query")
|
||||
matchCase = True if request.args.get("case").lower() == "match" else False
|
||||
result = {}
|
||||
|
||||
# loop over database tables
|
||||
for table in tables:
|
||||
text_columns = [column.key for column in table.__table__.columns if type(column.type) == db.types.TEXT]
|
||||
for table in __tables():
|
||||
text_columns = [column.key for column in table.__table__.columns if isinstance(column.type, db.types.TEXT)]
|
||||
hits = []
|
||||
# loop over table rows
|
||||
for row in db.session.execute(select(table)):
|
||||
# loop over each text column in row
|
||||
# loop over each text column in row
|
||||
for column in text_columns:
|
||||
if row[0].__getattribute__(column) is None:
|
||||
continue
|
||||
@ -46,7 +45,7 @@ def search_all():
|
||||
if s.lower() in row[0].__getattribute__(column).lower():
|
||||
hits.append(row[0].asdict())
|
||||
break
|
||||
if hits != []:
|
||||
if hits:
|
||||
result[table.__table__.fullname] = hits
|
||||
# return results
|
||||
return jsonify(result)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user