Watch history - fix for restock.previous_price returns the first-ever price once a watch has 3+ snapshots (#4268)
Build and push containers / metadata (push) Canceled after 0s
Build and push containers / build-push-containers (push) Canceled after 0s
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Canceled after 0s
ChangeDetection.io App Test / lint-code (push) Canceled after 0s
ChangeDetection.io App Test / lint-translations (push) Canceled after 0s
ChangeDetection.io App Test / lint-template-i18n (push) Canceled after 0s
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built package works basically. (push) Canceled after 0s
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Canceled after 0s
ChangeDetection.io App Test / test-application-3-10 (push) Canceled after 0s
ChangeDetection.io App Test / test-application-3-11 (push) Canceled after 0s
ChangeDetection.io App Test / test-application-3-12 (push) Canceled after 0s
ChangeDetection.io App Test / test-application-3-13 (push) Canceled after 0s
ChangeDetection.io App Test / test-application-3-14 (push) Canceled after 0s

This commit is contained in:
dgtlmoon
2026-07-22 11:23:53 +02:00
committed by GitHub
parent 966f89736b
commit fdfa3859ee
2 changed files with 22 additions and 2 deletions
@@ -115,10 +115,13 @@ class Watch(BaseWatch):
history = self.history
if history and len(history) >=2:
"""Unfortunately for now timestamp is stored as string key"""
# Keys are stored oldest-first (ascending). worker.py saves the new snapshot
# BEFORE sending the notification, so the newest key ([-1]) is the current check
# and the previous check is the second-newest ([-2]). Guaranteed to exist here
# because len(history) >= 2.
sorted_keys = sorted(list(history), key=lambda x: int(x))
sorted_keys.reverse()
price_str = self.get_history_snapshot(timestamp=sorted_keys[-1])
price_str = self.get_history_snapshot(timestamp=sorted_keys[-2])
if price_str:
values['restock']['previous_price'] = get_price_from_history_str(price_str)
return values
@@ -405,6 +405,23 @@ def test_change_with_notification_values(client, live_server, measure_memory_usa
assert "title new price 1950.45" in notification
assert "previous price 960.45" in notification
# Regression for #4260: with 3+ snapshots, {{restock.previous_price}} must report the price at
# the PREVIOUS check (1950.45), not the first-ever price in history (960.45). Before the fix the
# newest-first history list was indexed at [-1] (the oldest snapshot), so from the 3rd check on
# this was stuck on the first price ever recorded. The two-snapshot case above passed only by
# coincidence (with two entries the oldest snapshot IS the previous check).
os.unlink(os.path.join(datastore_path, "notification.txt"))
set_original_response(props_markup=instock_props[0], price='2500.45', datastore_path=datastore_path)
client.get(url_for("ui.form_watch_checknow"))
wait_for_all_checks(client)
wait_for_notification_endpoint_output(datastore_path=datastore_path)
assert os.path.isfile(os.path.join(datastore_path, "notification.txt")), "Notification received"
with open(os.path.join(datastore_path, "notification.txt"), 'r') as f:
notification = f.read()
assert "new price 2500.45" in notification
assert "previous price 1950.45" in notification # the actual previous check
assert "previous price 960.45" not in notification # the pre-fix bug (first-ever price)
## Now test the "SEND TEST NOTIFICATION" is working
os.unlink(os.path.join(datastore_path, "notification.txt"))
uuid = next(iter(live_server.app.config['DATASTORE'].data['watching']))