CI and images / extension-version (push) Successful in 3s
CI and images / lint (push) Successful in 3s
CI and images / frontend-build (push) Successful in 19s
CI and images / backend-lint-and-test (push) Successful in 40s
CI and images / integration (push) Failing after 2m17s
CI and images / sign-extension (push) Skipped
CI and images / build-web (push) Skipped
CI and images / smoke-web (push) Skipped
CI and images / promote (push) Skipped
CI and images / build-agent (push) Skipped
Operator, 2026-09-23, on a Floppystack post: "this post has been updated as he implements hot fixes — any chance we have a way to scan for or see updated posts so we can update ours to match and pull the new attachments and pictures etc." The download half already worked: extract_media reads the media list off the LIVE feed response every walk, so a newly attached hotfix build is a ledger key we have never seen. Only REACHING the post was missing — a tick stopped after 20 contiguous already-have-it items, and a post edited three days after publication sits well below twenty. Not a bug in the early-out; a count cannot express "recent". The early-out now needs BOTH conditions: the run of seen items AND a post published before the horizon. Strictly a widening — window 0 is exactly the old behaviour, and no window can make a tick stop EARLIER than it used to, so a source paused for months still walks its whole unseen backlog. The horizon is a floor on how far to look, never a ceiling. Inside the window the post-record gate is bypassed too (write_post_record revisit=True): the body is re-read from the feed response already in hand, so a revisit costs zero requests, and a body that comes back empty writes NOTHING rather than blanking one a detail-fetch had filled. Revisits are kept out of the #862 body-drift canary's sample for the same reason — an empty revisit is healthy, and counting it would walk the alarm toward firing on good ticks. The run summary names what changed ("3 post(s) updated (5 new file(s))") with a line per post; the ask was to SEE updated posts, not only to end up with their bytes. download_revisit_days is a settings row, not a constant (rule 25) — how long a creator keeps editing is a property of the creator. Default 30, 0 turns it off. Migration 0108. Also corrects two stale docstrings: both clients described post_meta as feeding an Ingester.preview that no longer calls it. It had no consumer at all until this change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LVjrnpQjRgHdvq95rASoiR
106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
import pytest
|
|
|
|
pytestmark = pytest.mark.integration
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_includes_downloader_fields(client):
|
|
resp = await client.get("/api/settings/import")
|
|
assert resp.status_code == 200
|
|
body = await resp.get_json()
|
|
assert body["download_rate_limit_seconds"] == 3.0
|
|
assert body["download_validate_files"] is True
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_patch_download_rate_limit(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"download_rate_limit_seconds": 1.5}
|
|
)
|
|
assert resp.status_code == 200
|
|
assert (await resp.get_json())["download_rate_limit_seconds"] == 1.5
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_patch_download_validate_files_false(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"download_validate_files": False}
|
|
)
|
|
assert resp.status_code == 200
|
|
assert (await resp.get_json())["download_validate_files"] is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_patch_rejects_negative_rate_limit(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"download_rate_limit_seconds": -1.0}
|
|
)
|
|
assert resp.status_code == 400
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_patch_rejects_non_bool_validate(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"download_validate_files": "yes"}
|
|
)
|
|
assert resp.status_code == 400
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_extdl_host_toggles_default_on_and_patch(client):
|
|
body = await (await client.get("/api/settings/import")).get_json()
|
|
assert body["extdl_mega_enabled"] is True
|
|
assert body["extdl_pixeldrain_enabled"] is True
|
|
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"extdl_mega_enabled": False}
|
|
)
|
|
assert resp.status_code == 200
|
|
assert (await resp.get_json())["extdl_mega_enabled"] is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_extdl_toggle_rejects_non_bool(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"extdl_gdrive_enabled": "nope"}
|
|
)
|
|
assert resp.status_code == 400
|
|
|
|
|
|
# -- download_revisit_days: how far back a tick looks for EDITED posts --------
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_revisit_window_defaults_to_thirty_days(client):
|
|
body = await (await client.get("/api/settings/import")).get_json()
|
|
assert body["download_revisit_days"] == 30
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_revisit_window_is_settable(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"download_revisit_days": 7}
|
|
)
|
|
assert resp.status_code == 200
|
|
assert (await resp.get_json())["download_revisit_days"] == 7
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_zero_is_accepted_because_it_is_the_off_switch(client):
|
|
"""0 turns the revisit off and restores the pure count early-out. Pinned
|
|
because the obvious bounds check for a "days" field is `>= 1`, and that
|
|
would take the off switch away without anything failing."""
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"download_revisit_days": 0}
|
|
)
|
|
assert resp.status_code == 200
|
|
assert (await resp.get_json())["download_revisit_days"] == 0
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_a_negative_window_is_refused(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"download_revisit_days": -1}
|
|
)
|
|
assert resp.status_code == 400
|