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