CI and images / lint (push) Failing after 2s
CI and images / extension-version (push) Successful in 2s
CI and images / frontend-build (push) Successful in 20s
CI and images / backend-lint-and-test (push) Successful in 31s
CI and images / integration (push) Failing after 2m15s
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-24: *"I don't want this to be manual that defeats the
convenience that I'm going for."*
Confirm-only was right while every signal was circumstantial. Time proximity
and a body that mentions Discord can never be more than suggestive, so asking
was the honest response to what FC actually knew. A shared working name is
different in kind: when the creator's own name for a piece appears in exactly
these two posts and nowhere else in their library, there is nothing left for
the operator to adjudicate, and asking is a chore FC invented for them.
AUTO_LINK_FLOOR is 1.0 and sits deliberately above IDENTITY_FLOOR's 0.75. The
gap between them IS the review queue — real evidence, not certain enough for
FC to act on alone. Measured on artist 8, of 15 name-sharing pairs: 11 are
conclusive, 2 more propose, 2 fall short of both.
Three refusals, because an auto-link is FC asserting something the operator
never saw:
* Exactly one candidate may be conclusive. Two is not a tie to be broken by
score — one post can tease two pieces dropped separately, and then each
drop carries a different name from the same teaser, each individually
conclusive. Two conclusive answers to "which drop is this" means the
question was wrong, so both queue and FC says nothing.
* Neither end may already be claimed by an accepted link. That link is the
operator's decision and reassigning its other end would overrule them
silently.
* The whole thing is one setting, defaulting on, reversible in the UI —
an accepted link is a row they can dismiss.
`match_post` now returns (proposed, linked) so a sweep can report what it did
on its own rather than only what it queued.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LVjrnpQjRgHdvq95rASoiR
138 lines
4.4 KiB
Python
138 lines
4.4 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
|
|
|
|
|
|
# --- the announcement matcher's own switch ---------------------------------
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_auto_linking_is_on_by_default(client):
|
|
"""Operator, 2026-09-24: "I don't want this to be manual that defeats the
|
|
convenience that I'm going for." Defaulting ON is the change of posture
|
|
that request asks for, so the default is what this pins."""
|
|
resp = await client.get("/api/settings/import")
|
|
assert resp.status_code == 200
|
|
assert (await resp.get_json())["discord_link_auto"] is True
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_auto_linking_can_be_turned_off(client):
|
|
"""Confirm-only has to stay reachable — linking without asking is a change
|
|
of posture, and not everyone wants it."""
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"discord_link_auto": False}
|
|
)
|
|
assert resp.status_code == 200
|
|
assert (await resp.get_json())["discord_link_auto"] is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_auto_linking_refuses_a_non_boolean(client):
|
|
resp = await client.patch(
|
|
"/api/settings/import", json={"discord_link_auto": "yes"}
|
|
)
|
|
assert resp.status_code == 400
|