mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 11:12:35 +02:00
74 lines
3.2 KiB
Python
74 lines
3.2 KiB
Python
"""Every client-settable notification provider column must reach the API (#2945).
|
|
|
|
The defect this pins is not a wrong value, it is a field that exists everywhere
|
|
except the modules a toggle has to cross. `on_stock_reorder_alert` and
|
|
`on_stock_break_alert` had model columns, service producers, templates, UI
|
|
toggles and a frontend test asserting the PATCH — and no schema field, so
|
|
Pydantic dropped them, the PATCH answered 200, and nothing was written. #1184
|
|
introduced that gap and every layer it did touch worked, which is why it went
|
|
unnoticed for months.
|
|
|
|
These are structural checks of structural facts: a column that is absent from a
|
|
schema cannot be sent at all, whatever the routes do with it afterwards. The
|
|
behaviour behind them — create, both read routes and PATCH, over the same
|
|
derived column list — is covered through the API in
|
|
`backend/tests/integration/test_notifications_api.py`.
|
|
|
|
The two schemas here are the whole of it. The update route needs nothing
|
|
beyond `NotificationProviderUpdate`, because it applies changes with a generic
|
|
`model_dump(exclude_unset=True)` + `setattr` loop rather than a third
|
|
hand-maintained map: once the field survives the schema, it is written.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from backend.app.models.notification import NotificationProvider
|
|
from backend.app.schemas.notification import (
|
|
NotificationProviderCreate,
|
|
NotificationProviderUpdate,
|
|
)
|
|
from backend.tests._fixtures.notification_toggles import (
|
|
EVENT_TOGGLE_COLUMNS,
|
|
SETTABLE_COLUMNS,
|
|
TOGGLE_TARGET,
|
|
)
|
|
|
|
|
|
def test_there_are_event_columns_to_check() -> None:
|
|
"""Guard the guard: an empty enumeration would make every test below vacuous."""
|
|
assert len(EVENT_TOGGLE_COLUMNS) > 20
|
|
|
|
|
|
def test_the_targets_cover_both_directions() -> None:
|
|
"""Guard the other guard, the one the integration round-trips lean on.
|
|
|
|
``TOGGLE_TARGET`` exists so a test drives each toggle to whatever its
|
|
default is not. If every column defaulted the same way -- or if the default
|
|
lookup quietly started returning one constant -- the targets would collapse
|
|
to a single value and the round-trips would be answered by the default again
|
|
without anything failing. Both values have to appear.
|
|
"""
|
|
assert set(TOGGLE_TARGET.values()) == {True, False}
|
|
|
|
|
|
@pytest.mark.parametrize("column", EVENT_TOGGLE_COLUMNS)
|
|
def test_every_event_column_has_a_python_default(column: str) -> None:
|
|
"""``TOGGLE_TARGET`` derives each target from the Python-side default, so a
|
|
toggle that only has a ``server_default`` would get the wrong target and
|
|
its round trip would pass on the default alone. Fail here instead."""
|
|
assert NotificationProvider.__table__.columns[column].default is not None
|
|
|
|
|
|
@pytest.mark.parametrize("column", SETTABLE_COLUMNS)
|
|
def test_every_settable_column_is_settable_on_create(column: str) -> None:
|
|
"""Absent from the Create schema, the field is silently dropped from the POST."""
|
|
assert column in NotificationProviderCreate.model_fields
|
|
|
|
|
|
@pytest.mark.parametrize("column", SETTABLE_COLUMNS)
|
|
def test_every_settable_column_is_settable_on_update(column: str) -> None:
|
|
"""This is the one the report hit: the PATCH succeeds and writes nothing."""
|
|
assert column in NotificationProviderUpdate.model_fields
|