Files
colibre/tests/admin/test_tables.py
T
Colin Maudry 1551faaf0c Normaliser les échecs d'écriture set_cell en ValueError
- IntegrityError (ex: email déjà utilisé) est désormais capturée et
  reconvertie en ValueError, pour rester dans le funnel d'alerte
  existant du callback admin au lieu de faire planter le callback Dash.
- Une UPDATE qui touche 0 ligne (ligne supprimée entre le chargement du
  tableau et la soumission de l'édition) lève désormais une ValueError
  au lieu d'être silencieusement traitée comme un succès (ce qui aurait
  créé un log d'audit trompeur).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 23:10:32 +02:00

143 lines
4.4 KiB
Python

import pytest
from src.admin import tables
def test_get_rows_users_excludes_password_hash(users_db_path):
from src.auth import db as auth_db
auth_db.init_schema()
auth_db.create_user("a@ex.fr", "secret-hash")
rows = tables.get_rows("users")
assert rows[0]["email"] == "a@ex.fr"
assert "password_hash" not in rows[0]
def test_set_cell_rejects_unknown_table(users_db_path):
with pytest.raises(ValueError):
tables.set_cell("not_a_table", 1, "email", "x@ex.fr")
def test_set_cell_rejects_non_editable_column(users_db_path):
from src.auth import db as auth_db
auth_db.init_schema()
uid = auth_db.create_user("a@ex.fr", "hash")
with pytest.raises(ValueError):
tables.set_cell("users", uid, "id", "999")
def test_set_cell_rejects_invalid_dropdown_value(users_db_path):
from src.auth import db as auth_db
from src.subscriptions import db as sub_db
auth_db.init_schema()
sub_db.init_schema()
uid = auth_db.create_user("a@ex.fr", "hash")
_handle, sub_id = sub_db.create_pending(uid, "cust-1", "simple")
with pytest.raises(ValueError):
tables.set_cell("subscriptions", sub_id, "status", "not_a_status")
def test_set_cell_rejects_bad_type(users_db_path):
from src.auth import db as auth_db
from src.subscriptions import db as sub_db
auth_db.init_schema()
sub_db.init_schema()
uid = auth_db.create_user("a@ex.fr", "hash")
_handle, sub_id = sub_db.create_pending(uid, "cust-1", "simple")
with pytest.raises(ValueError):
tables.set_cell("subscriptions", sub_id, "prix_ht", "not-a-number")
def test_set_cell_writes_valid_value(users_db_path):
from src.auth import db as auth_db
auth_db.init_schema()
uid = auth_db.create_user("a@ex.fr", "hash")
tables.set_cell("users", uid, "siret", "12345678900011")
rows = tables.get_rows("users")
assert rows[0]["siret"] == "12345678900011"
def test_set_cell_raises_valueerror_on_unique_constraint_violation(users_db_path):
from src.auth import db as auth_db
auth_db.init_schema()
auth_db.create_user("first@ex.fr", "hash")
second_uid = auth_db.create_user("second@ex.fr", "hash")
with pytest.raises(ValueError):
tables.set_cell("users", second_uid, "email", "first@ex.fr")
def test_set_cell_raises_valueerror_when_row_missing(users_db_path):
from src.auth import db as auth_db
auth_db.init_schema()
uid = auth_db.create_user("a@ex.fr", "hash")
auth_db.delete_user(uid)
with pytest.raises(ValueError):
tables.set_cell("users", uid, "email", "new@ex.fr")
def test_set_cell_coerces_numeric_type(users_db_path):
from src.auth import db as auth_db
from src.subscriptions import db as sub_db
auth_db.init_schema()
sub_db.init_schema()
uid = auth_db.create_user("a@ex.fr", "hash")
_handle, sub_id = sub_db.create_pending(uid, "cust-1", "simple")
tables.set_cell("subscriptions", sub_id, "prix_ht", "30")
rows = tables.get_rows("subscriptions")
assert rows[0]["prix_ht"] == 30.0
def test_find_changed_cell_detects_single_diff():
data = [{"id": 1, "email": "new@ex.fr"}]
data_previous = [{"id": 1, "email": "old@ex.fr"}]
result = tables.find_changed_cell(data, data_previous)
assert result == (0, "email", "old@ex.fr", "new@ex.fr")
def test_find_changed_cell_returns_none_when_identical():
data = [{"id": 1, "email": "a@ex.fr"}]
data_previous = [{"id": 1, "email": "a@ex.fr"}]
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():
assert tables.find_changed_cell([{"id": 1}], None) is None
def test_target_user_id_per_table():
assert tables.TABLES["users"].target_user_id({"id": 7}) == 7
assert tables.TABLES["subscriptions"].target_user_id({"user_id": 9}) == 9
assert tables.TABLES["subscriber_state"].target_user_id({"user_id": 3}) == 3
assert tables.TABLES["admin_actions"].target_user_id({"id": 1}) is None