fix(quality_nudge): also guard Instagram silent-failure on INCLUDE_SOURCES allowlist
This commit is contained in:
@@ -95,7 +95,15 @@ def _is_instagram_silent_failure(config: dict, research_results: dict) -> bool:
|
|||||||
for s in (config.get("EXCLUDE_SOURCES") or "").split(",")
|
for s in (config.get("EXCLUDE_SOURCES") or "").split(",")
|
||||||
if s.strip()
|
if s.strip()
|
||||||
}
|
}
|
||||||
if "instagram" in excluded:
|
# Symmetric case: INCLUDE_SOURCES is an opt-in allowlist. If it is
|
||||||
|
# non-empty and does not name instagram, the source was intentionally
|
||||||
|
# filtered out, so a zero-item count is expected — not a silent failure.
|
||||||
|
included = {
|
||||||
|
s.strip().lower()
|
||||||
|
for s in (config.get("INCLUDE_SOURCES") or "").split(",")
|
||||||
|
if s.strip()
|
||||||
|
}
|
||||||
|
if "instagram" in excluded or (included and "instagram" not in included):
|
||||||
return False
|
return False
|
||||||
count = research_results.get("instagram_items_count")
|
count = research_results.get("instagram_items_count")
|
||||||
if count is None:
|
if count is None:
|
||||||
|
|||||||
@@ -515,3 +515,65 @@ class TestInstagramSilentFailure:
|
|||||||
)
|
)
|
||||||
assert "instagram" in q["bonus_errored"]
|
assert "instagram" in q["bonus_errored"]
|
||||||
|
|
||||||
|
def test_include_sources_without_instagram_suppresses_silent_failure(self):
|
||||||
|
"""User set INCLUDE_SOURCES to an opt-in allowlist that omits
|
||||||
|
instagram — the pipeline skips the source by allowlist filter, so
|
||||||
|
the zero-count instagram_items_count is intentional, not a silent
|
||||||
|
failure. Symmetric to the EXCLUDE_SOURCES=instagram guard.
|
||||||
|
"""
|
||||||
|
q = _compute(
|
||||||
|
config_overrides={
|
||||||
|
"AUTH_TOKEN": "tok123",
|
||||||
|
"SCRAPECREATORS_API_KEY": "sc_key",
|
||||||
|
"INCLUDE_SOURCES": "reddit,hn,x,youtube",
|
||||||
|
},
|
||||||
|
ytdlp_installed=True,
|
||||||
|
result_overrides={"instagram_items_count": 0},
|
||||||
|
)
|
||||||
|
assert "instagram" not in q["bonus_errored"]
|
||||||
|
assert q["nudge_text"] is None
|
||||||
|
|
||||||
|
def test_include_sources_multi_value_without_instagram(self):
|
||||||
|
"""Canonical parsing pattern is comma-separated; case-insensitive."""
|
||||||
|
q = _compute(
|
||||||
|
config_overrides={
|
||||||
|
"AUTH_TOKEN": "tok123",
|
||||||
|
"SCRAPECREATORS_API_KEY": "sc_key",
|
||||||
|
"INCLUDE_SOURCES": " Reddit, HN , YouTube ",
|
||||||
|
},
|
||||||
|
ytdlp_installed=True,
|
||||||
|
result_overrides={"instagram_items_count": 0},
|
||||||
|
)
|
||||||
|
assert "instagram" not in q["bonus_errored"]
|
||||||
|
|
||||||
|
def test_include_sources_with_instagram_still_flags(self):
|
||||||
|
"""INCLUDE_SOURCES that explicitly names instagram must not suppress
|
||||||
|
the silent-failure nudge — the source was opted in, so a zero count
|
||||||
|
is a real silent failure.
|
||||||
|
"""
|
||||||
|
q = _compute(
|
||||||
|
config_overrides={
|
||||||
|
"AUTH_TOKEN": "tok123",
|
||||||
|
"SCRAPECREATORS_API_KEY": "sc_key",
|
||||||
|
"INCLUDE_SOURCES": "reddit,instagram",
|
||||||
|
},
|
||||||
|
ytdlp_installed=True,
|
||||||
|
result_overrides={"instagram_items_count": 0},
|
||||||
|
)
|
||||||
|
assert "instagram" in q["bonus_errored"]
|
||||||
|
|
||||||
|
def test_include_sources_empty_does_not_suppress(self):
|
||||||
|
"""Empty/unset INCLUDE_SOURCES means no allowlist filter, so the
|
||||||
|
silent-failure gate should still fire when instagram is zero.
|
||||||
|
"""
|
||||||
|
q = _compute(
|
||||||
|
config_overrides={
|
||||||
|
"AUTH_TOKEN": "tok123",
|
||||||
|
"SCRAPECREATORS_API_KEY": "sc_key",
|
||||||
|
"INCLUDE_SOURCES": "",
|
||||||
|
},
|
||||||
|
ytdlp_installed=True,
|
||||||
|
result_overrides={"instagram_items_count": 0},
|
||||||
|
)
|
||||||
|
assert "instagram" in q["bonus_errored"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user