fix(admin): guard find_changed_cell against cross-table schema mismatch

When switching tables, the table-switch branch writes fresh data for the
new table, which re-fires the same callback with data_previous still
holding the old table's rows. find_changed_cell only checked row count
before diffing, so if the two tables happened to have the same number of
rows it would zip mismatched-schema dicts and report a spurious changed
cell (usually the PK column), producing a confusing red alert right after
switching tables.
This commit is contained in:
Colin Maudry
2026-07-03 14:46:12 +02:00
parent d229b58f3b
commit caf800e5e8
2 changed files with 14 additions and 0 deletions
+4
View File
@@ -144,6 +144,10 @@ def find_changed_cell(
) -> tuple[int, str, object, object] | None: ) -> tuple[int, str, object, object] | None:
if data_previous is None or len(data) != len(data_previous): if data_previous is None or len(data) != len(data_previous):
return None return None
if not data or not data_previous:
return None
if set(data[0].keys()) != set(data_previous[0].keys()):
return None
for i, (new_row, old_row) in enumerate(zip(data, data_previous)): for i, (new_row, old_row) in enumerate(zip(data, data_previous)):
for col, new_val in new_row.items(): for col, new_val in new_row.items():
old_val = old_row.get(col) old_val = old_row.get(col)
+10
View File
@@ -99,6 +99,16 @@ def test_find_changed_cell_returns_none_when_identical():
assert tables.find_changed_cell(data, data_previous) is None assert tables.find_changed_cell(data, data_previous) is None
def test_find_changed_cell_returns_none_when_schemas_differ():
# Mimics switching from "users" to "admin_actions" mid-callback: the two
# tables' row lists happen to have the same length but different
# columns, so this must not be mistaken for a genuine cell edit.
data = [{"id": 1, "email": "a@ex.fr"}]
data_previous = [{"id": 1, "admin_email": "x@ex.fr"}]
assert tables.find_changed_cell(data, data_previous) is None
def test_find_changed_cell_returns_none_when_previous_is_none(): def test_find_changed_cell_returns_none_when_previous_is_none():
assert tables.find_changed_cell([{"id": 1}], None) is None assert tables.find_changed_cell([{"id": 1}], None) is None