You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

155 lines
5.0 KiB

from __future__ import annotations
from pathlib import Path
from sqlalchemy import Table, UniqueConstraint
from sqlalchemy.dialects import mysql, sqlite
from app import create_app
from app.extensions import db
from app.models.base import ID_TYPE
EXPECTED_TABLES = {
"accounts",
"audit_logs",
"gift_records",
"household_members",
"households",
"option_items",
"share_links",
}
def get_table(table_name: str) -> Table:
return db.metadata.tables[table_name]
def test_create_app_uses_testing_config() -> None:
app = create_app("testing")
assert app.config["TESTING"] is True
assert app.config["SQLALCHEMY_DATABASE_URI"] == "sqlite:///:memory:"
def test_healthcheck_route() -> None:
app = create_app("testing")
client = app.test_client()
response = client.get("/health")
assert response.status_code == 200
assert response.get_json() == {
"project": "HappyWedding",
"short_name": "hw",
"status": "ok",
}
def test_auth_related_blueprints_are_registered() -> None:
app = create_app("testing")
assert {"auth", "admin", "main", "quick_entry", "health"}.issubset(app.blueprints.keys())
def test_metadata_contains_expected_tables() -> None:
app = create_app("testing")
with app.app_context():
db.create_all()
table_names = set(db.metadata.tables.keys())
assert EXPECTED_TABLES.issubset(table_names)
def test_household_table_contains_core_columns() -> None:
household_columns = get_table("households").columns.keys()
assert "household_code" in household_columns
assert "tag_option_ids_json" in household_columns
assert "total_gift_amount" in household_columns
assert "version" in household_columns
assert "deleted_at" in household_columns
def test_account_table_contains_tracking_columns() -> None:
account_columns = get_table("accounts").columns.keys()
assert "username" in account_columns
assert "password_hash" in account_columns
assert "role" in account_columns
assert "status" in account_columns
assert "created_by" in account_columns
assert "updated_by" in account_columns
def test_relationship_foreign_keys_exist() -> None:
household_fks = {fk.parent.name for fk in get_table("households").foreign_keys}
gift_record_fks = {fk.parent.name for fk in get_table("gift_records").foreign_keys}
member_fks = {fk.parent.name for fk in get_table("household_members").foreign_keys}
option_item_fks = {fk.parent.name for fk in get_table("option_items").foreign_keys}
audit_log_fks = {fk.parent.name for fk in get_table("audit_logs").foreign_keys}
assert {
"relation_category_option_id",
"relation_detail_option_id",
"gift_method_option_id",
"gift_scene_option_id",
"created_by",
"updated_by",
}.issubset(household_fks)
assert {"household_id", "method_option_id", "scene_option_id", "created_by", "updated_by"}.issubset(
gift_record_fks,
)
assert {"household_id", "created_by", "updated_by"}.issubset(member_fks)
assert {"parent_id", "created_by", "updated_by"}.issubset(option_item_fks)
assert {"actor_user_id"}.issubset(audit_log_fks)
def test_unique_constraints_exist_on_key_tables() -> None:
account_unique_columns = [
list(constraint.columns.keys())
for constraint in get_table("accounts").constraints
if isinstance(constraint, UniqueConstraint)
]
household_unique_columns = [
list(constraint.columns.keys())
for constraint in get_table("households").constraints
if isinstance(constraint, UniqueConstraint)
]
option_item_unique_columns = [
list(constraint.columns.keys())
for constraint in get_table("option_items").constraints
if isinstance(constraint, UniqueConstraint)
]
assert ["username"] in account_unique_columns
assert ["household_code"] in household_unique_columns
assert ["option_group", "option_code"] in option_item_unique_columns
def test_id_type_compiles_for_sqlite_and_mysql() -> None:
assert ID_TYPE.compile(dialect=sqlite.dialect()) == "INTEGER"
assert ID_TYPE.compile(dialect=mysql.dialect()) == "BIGINT"
def test_sqlite_connections_apply_runtime_pragmas(monkeypatch, tmp_path: Path) -> None:
db_path = tmp_path / "pragma-check.db"
monkeypatch.setenv("DATABASE_URL", f"sqlite:///{db_path}")
app = create_app("development")
with app.app_context():
db.create_all()
connection = db.session.connection()
journal_mode = connection.exec_driver_sql("PRAGMA journal_mode;").scalar()
busy_timeout = connection.exec_driver_sql("PRAGMA busy_timeout;").scalar()
temp_store = connection.exec_driver_sql("PRAGMA temp_store;").scalar()
synchronous = connection.exec_driver_sql("PRAGMA synchronous;").scalar()
foreign_keys = connection.exec_driver_sql("PRAGMA foreign_keys;").scalar()
assert str(journal_mode).lower() == "wal"
assert busy_timeout == 5000
assert temp_store == 2
assert synchronous == 1
assert foreign_keys == 1