diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index ddb5a4d..d8258fd 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -82,9 +82,11 @@ def db_session(): conn.execute(text("PRAGMA foreign_keys = OFF")) # Fetch all tables from the metadata for table_name in reversed(Base.metadata.tables.keys()): - # Avoid truncating internal alembic or FTS tables - if "alembic" not in table_name and "fts" not in table_name: + # Avoid truncating internal alembic tables + if "alembic" not in table_name: conn.execute(text(f"DELETE FROM {table_name}")) + # FTS5 virtual table is not in Base.metadata; clear it explicitly + conn.execute(text("DELETE FROM filesystem_fts")) conn.execute(text("PRAGMA foreign_keys = ON")) diff --git a/backend/tests/test_api_inventory.py b/backend/tests/test_api_inventory.py index 005bfa0..4b8d6be 100644 --- a/backend/tests/test_api_inventory.py +++ b/backend/tests/test_api_inventory.py @@ -147,14 +147,21 @@ def test_search_index(client, db_session): ) db_session.commit() - # Trigger FTS manually since we are using raw SQL triggers which might not have fired - # if we didn't insert via SQL or if there are issues in :memory: - # but conftest uses a real temp file. + # Manually insert into FTS5 since triggers may not fire on ORM inserts in tests + from sqlalchemy import text + + db_session.execute( + text("INSERT INTO filesystem_fts(rowid, file_path) VALUES (:rowid, :path)"), + {"rowid": file1.id, "path": file1.file_path}, + ) db_session.commit() response = client.get("/archive/search?q=important") assert response.status_code == 200 - # If FTS5 is working, it should return results. + data = response.json() + assert len(data) == 1 + assert data[0]["path"] == "data/important.doc" + assert data[0]["name"] == "important.doc" def test_get_metadata(client, db_session): diff --git a/backend/tests/test_api_system.py b/backend/tests/test_api_system.py index b0efcbc..739af8f 100644 --- a/backend/tests/test_api_system.py +++ b/backend/tests/test_api_system.py @@ -70,10 +70,17 @@ def test_get_scan_status(client): def test_ls_root(client): - """Tests listing the root directory.""" + """Tests listing the root directory returns actual subdirectories.""" response = client.get("/system/ls?path=/") assert response.status_code == 200 - assert isinstance(response.json(), list) + data = response.json() + assert isinstance(data, list) + assert len(data) > 0 + for entry in data: + assert "name" in entry + assert "path" in entry + assert entry["name"] != "" + assert entry["path"] != "" def test_ignore_hardware(client): @@ -465,10 +472,13 @@ def test_ignore_hardware_duplicate(client): def test_database_export(client): - """Tests database export endpoint returns a file response.""" + """Tests database export endpoint returns a SQLite file download.""" response = client.get("/system/database/export") - # May return 200 with file or 404 if db path not found - assert response.status_code in (200, 404) + assert response.status_code == 200 + assert "tapehoard_index_" in response.headers["content-disposition"] + assert ".db" in response.headers["content-disposition"] + # Should contain SQLite magic bytes + assert response.content[:16] == b"SQLite format 3\x00" # ── Tracking Batch ── @@ -548,5 +558,5 @@ def test_test_notification_invalid_url(client): response = client.post( "/system/notifications/test", json={"url": "not-a-valid-url"} ) - # Notification manager may succeed or fail depending on apprise parsing - assert response.status_code in (200, 500) + assert response.status_code == 500 + assert "Failed to dispatch test alert" in response.json()["detail"]