"""FlowDeck — v6.0.0 PWA: offline-sync schema migrations. Validates the ``offline_sync_queue`` table, the ``sync_version`` columns and the BEFORE-UPDATE triggers that bump them on every write. """ from app.db import get_conn def _insert_page(title="Page"): with get_conn() as conn: cur = conn.execute( "INSERT INTO pages (workspace, title, content, content_format, parent_section) " "VALUES ('', ?, '', 'blocks', 'Private')", (title,), ) conn.commit() return cur.lastrowid def _insert_collection(name="Coll"): with get_conn() as conn: cur = conn.execute( "INSERT INTO collections (name, schema_json) VALUES (?, '[]')", (name,) ) conn.commit() return cur.lastrowid def _insert_collection_page(coll_id, title="Row"): with get_conn() as conn: cur = conn.execute( "INSERT INTO collection_pages (collection_id, title) VALUES (?, ?)", (coll_id, title), ) conn.commit() return cur.lastrowid def test_offline_sync_queue_table_and_indexes(client): with get_conn() as conn: cols = {r[1] for r in conn.execute("PRAGMA table_info(offline_sync_queue)")} for expected in ("id", "user_id", "device_id", "type", "payload", "client_timestamp", "server_version", "status", "retries", "error", "created_at"): assert expected in cols, f"offline_sync_queue missing column {expected}" indexes = {r[1] for r in conn.execute("PRAGMA index_list('offline_sync_queue')")} assert "idx_syncqueue_user" in indexes assert "idx_syncqueue_device" in indexes def test_offline_sync_queue_insert(client): with get_conn() as conn: uid = conn.execute( "INSERT INTO users (login, full_name, email) VALUES ('queuetest', 'Queue', 'q@t.co')" ).lastrowid cur = conn.execute( "INSERT INTO offline_sync_queue (user_id, device_id, type, payload, client_timestamp) " "VALUES (?, ?, ?, ?, ?)", (uid, "dev-abc", "page_update", '{"page_id": 1}', 1750000000000.0), ) conn.commit() qid = cur.lastrowid row = conn.execute( "SELECT status, server_version, retries FROM offline_sync_queue WHERE id=?", (qid,), ).fetchone() assert row["status"] == "pending" assert row["server_version"] == 0 assert row["retries"] == 0 def test_sync_version_column_and_defaults(client): pid = _insert_page() cid = _insert_collection() cpid = _insert_collection_page(cid) with get_conn() as conn: for table, pk in (("pages", pid), ("collection_pages", cpid), ("collections", cid)): row = conn.execute(f"SELECT sync_version FROM {table} WHERE id=?", (pk,)).fetchone() assert row is not None, f"sync_version missing on {table}" assert row["sync_version"] == 1, f"{table} default sync_version should be 1" def test_sync_version_increments_on_update(client): pid = _insert_page() with get_conn() as conn: conn.execute("UPDATE pages SET title='Renamed' WHERE id=?", (pid,)) conn.commit() v1 = conn.execute("SELECT sync_version FROM pages WHERE id=?", (pid,)).fetchone() conn.execute("UPDATE pages SET content='[...]' WHERE id=?", (pid,)) conn.commit() v2 = conn.execute("SELECT sync_version FROM pages WHERE id=?", (pid,)).fetchone() assert v1["sync_version"] == 2 assert v2["sync_version"] == 3 def test_sync_version_increments_on_soft_delete(client): """deleted_at changes must bump the version too (delta sync sees deletions).""" pid = _insert_page() with get_conn() as conn: conn.execute( "UPDATE pages SET deleted_at=CURRENT_TIMESTAMP WHERE id=? AND deleted_at IS NULL", (pid,), ) conn.commit() row = conn.execute("SELECT sync_version FROM pages WHERE id=?", (pid,)).fetchone() assert row["sync_version"] == 2 def test_sync_version_increments_collection_and_rows(client): cid = _insert_collection() cpid = _insert_collection_page(cid) with get_conn() as conn: conn.execute("UPDATE collections SET name='Renamed' WHERE id=?", (cid,)) conn.execute( "UPDATE collection_pages SET title='Row2', property_values_json='{}' WHERE id=?", (cpid,), ) conn.commit() col = conn.execute("SELECT sync_version FROM collections WHERE id=?", (cid,)).fetchone() row = conn.execute( "SELECT sync_version FROM collection_pages WHERE id=?", (cpid,) ).fetchone() assert col["sync_version"] == 2 assert row["sync_version"] == 2