fix(advice): the no-token guard must cover all three shapes of "no token"
The guard matches on the absence of a token. `{"$exists": False}` covers
a reading with no token field, but NOT one whose token field is present
and empty.
Verified against the live database, before the fix:
token present but empty -> write matched: 0 <-- missed it
`{"$in": [None, ""]}` covers all three - a missing field, an empty
field, and a null one - because `$in` with null also matches a missing
field.
no token field -> write matched: 1
token present but empty -> write matched: 1
token is null -> write matched: 1
183 tests (up from 182).
This commit is contained in:
@@ -278,7 +278,10 @@ class BeerRepository:
|
|||||||
# Falling back to the gravity here would re-open the hole
|
# Falling back to the gravity here would re-open the hole
|
||||||
# this guard exists to close - a comment-only correction
|
# this guard exists to close - a comment-only correction
|
||||||
# leaves the gravity unchanged.
|
# leaves the gravity unchanged.
|
||||||
query["advice_token"] = {"$exists": False}
|
# `$in` with null also matches a MISSING field, so this
|
||||||
|
# covers a reading with no token AND one whose token field
|
||||||
|
# is present but empty.
|
||||||
|
query["advice_token"] = {"$in": [None, ""]}
|
||||||
elif expected_sg is not None:
|
elif expected_sg is not None:
|
||||||
# A direct call with a gravity to check against.
|
# A direct call with a gravity to check against.
|
||||||
query["sg"] = str(expected_sg)
|
query["sg"] = str(expected_sg)
|
||||||
|
|||||||
@@ -826,6 +826,33 @@ def test_a_pre_token_reading_is_still_guarded_against_a_stale_write(repo):
|
|||||||
assert after["comment"] == "corrected comment"
|
assert after["comment"] == "corrected comment"
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_advice_is_written_for_a_reading_with_no_token_field(repo):
|
||||||
|
"""All three shapes of "no token" must work.
|
||||||
|
|
||||||
|
A reading read from the database has no token at all; one written by
|
||||||
|
an older version could have the field present but empty, or null.
|
||||||
|
The guard matches on the absence of a token, so it has to cover all
|
||||||
|
three - otherwise the advice is silently never written.
|
||||||
|
"""
|
||||||
|
for index, extra in enumerate(({}, {"advice_token": ""}, {"advice_token": None})):
|
||||||
|
reading_id = f"noToken{index:04d}"
|
||||||
|
repo.readings.insert_one({
|
||||||
|
"_id": reading_id,
|
||||||
|
"beer_run_id": str(index),
|
||||||
|
"beer_type": "Ale",
|
||||||
|
"sg": "1050",
|
||||||
|
"date": "2026-01-01",
|
||||||
|
"final_reading": "False",
|
||||||
|
"comment": "c",
|
||||||
|
**extra,
|
||||||
|
})
|
||||||
|
|
||||||
|
written = repo.set_reading_advice(reading_id, "THE ADVICE", True,
|
||||||
|
expected_sg=None,
|
||||||
|
expected_token="")
|
||||||
|
assert written == 1, f"the advice was not written for {extra!r}"
|
||||||
|
|
||||||
|
|
||||||
def test_a_reply_cut_off_at_the_token_ceiling_is_marked(repo):
|
def test_a_reply_cut_off_at_the_token_ceiling_is_marked(repo):
|
||||||
"""A reply that stopped at the token limit is incomplete.
|
"""A reply that stopped at the token limit is incomplete.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user