Files
FabledCurator/tests/test_extension_url_derive.py
T
bvandeusen 69b5637bd6
CI / lint (push) Successful in 3s
extension / lint (push) Successful in 11s
CI / frontend-build (push) Successful in 21s
CI / backend-lint-and-test (push) Successful in 30s
CI / integration (push) Successful in 3m47s
extension / lint (pull_request) Successful in 9s
fix(extension): show Add-to-FC button on subscribed Patreon creators (#1485)
Symptom (operator-flagged): the extension injected the Add-as-source button on
a Patreon creator you had NOT subscribed to, but it disappeared once you were
subscribed — the opposite of when it's useful.

Root cause (extension logic, not Patreon security): Patreon serves a creator
under three URL shapes — bare patreon.com/Atole, patreon.com/c/Atole, and
patreon.com/cw/Atole (the 'creator workspace' URL you land on once subscribed;
documented in patreon_resolver._VANITY_RE). The button's artist-page gate
(PLATFORM_ARTIST_PATTERNS.patreon in platforms.js) and its byte-mirror probe
pattern (_PLATFORM_PATTERNS in extension_service._derive) only matched the bare
single-segment form and explicitly excluded c/. So the subscribed-view URL
failed the gate → no button. The ingestion resolver already handled all three;
only these two gates were too narrow.

Fix: both regexes now accept optional cw/ and c/ prefixes and drop the strict
single-segment end-anchor, so a creator's inner page (/cw/Atole/posts,
/Atole/membership) also matches — robust to whatever exact shape the subscribed
view uses. Nav-page exclusions (home/search/messages/notifications/library/
settings/posts + post permalinks) preserved. New unit test covers all three
prefixes, sub-paths, and nav-page rejection (both regexes validated identically).

Bump extension 1.0.7→1.0.8 so a fresh signed XPI ships the fix (also exercises
batch-5 web-ext-10's AMO sign path end-to-end on the main build).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 17:50:07 -04:00

66 lines
2.2 KiB
Python

"""Unit tests for ExtensionService._derive — the URL → (platform, slug)
parser that gates the browser extension's "Add as source" button and pulls
the creator slug on probe/add.
Regression cover for #1485: Patreon serves the same creator under three URL
shapes — bare `patreon.com/Atole`, `c/`, and `cw/` (the "creator workspace"
URL you land on once SUBSCRIBED). The button used to vanish while subscribed
because the pattern only matched the bare root and excluded `c/`.
_derive is pure URL parsing (no DB / no async), so a session-less instance is
fine to exercise directly.
"""
import pytest
from backend.app.services.extension_service import (
ExtensionService,
InvalidUrlError,
UnknownPlatformError,
)
_svc = ExtensionService(None)
@pytest.mark.parametrize(
"url, slug",
[
# All three Patreon creator prefixes resolve to the same vanity slug.
("https://www.patreon.com/Atole", "Atole"),
("https://www.patreon.com/c/Atole", "Atole"),
("https://www.patreon.com/cw/Atole", "Atole"), # subscribed-view URL
# A creator's inner page still derives the slug (trailing sub-path).
("https://www.patreon.com/cw/Atole/posts", "Atole"),
("https://www.patreon.com/Atole/membership", "Atole"),
("https://patreon.com/c/Atole", "Atole"), # bare host, no www
],
)
def test_derive_patreon_creator_urls(url, slug):
platform, got = _svc._derive(url)
assert platform == "patreon"
assert got == slug
@pytest.mark.parametrize(
"url",
[
# Patreon's own nav pages must never read as a creator slug.
"https://www.patreon.com/home",
"https://www.patreon.com/settings",
"https://www.patreon.com/search",
"https://www.patreon.com/messages",
"https://www.patreon.com/library",
"https://www.patreon.com/notifications",
"https://www.patreon.com/posts/12345", # post permalink
"https://www.patreon.com/settings/billing", # nav sub-page
],
)
def test_derive_patreon_nav_pages_rejected(url):
with pytest.raises(UnknownPlatformError):
_svc._derive(url)
def test_derive_rejects_missing_scheme():
with pytest.raises(InvalidUrlError):
_svc._derive("patreon.com/Atole")