mirror of https://github.com/Nezreka/SoulSync.git
Merge pull request #454 from Nezreka/fix/tidal-auth-instructions-port
Show Tidal callback port (not Spotify's) in auth instructionspull/455/head
commit
9fef64f1f8
@ -0,0 +1,147 @@
|
||||
"""Regression tests for Tidal auth instruction page port rendering.
|
||||
|
||||
Discord-reported bug: the auth-instructions page shown after clicking
|
||||
the Tidal "Authenticate" button rendered example callback URLs with
|
||||
port ``8888`` (Spotify's port) instead of ``8889`` (Tidal's port).
|
||||
Users who followed the instructions literally saved Spotify's port
|
||||
into their ``tidal.redirect_uri`` setting; that mismatched their
|
||||
Tidal Developer App's registered ``:8889`` redirect URI and Tidal
|
||||
returned error 1002 (invalid redirect URI) on every auth attempt.
|
||||
|
||||
These tests make sure the rendered instructions show whatever port
|
||||
the OAuth URL itself was built with, so the displayed example always
|
||||
matches what the user must register in their Tidal app.
|
||||
"""
|
||||
|
||||
from typing import Callable
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
# Run the route through Flask's test client so we get the real HTML
|
||||
# the user would see. We patch out:
|
||||
# - TidalClient (the real client tries to connect to Tidal),
|
||||
# - the activity-feed call (writes to runtime state),
|
||||
# - request.host detection (so the Docker code path is exercised
|
||||
# and the instructions page is the one with the example URL).
|
||||
@pytest.fixture
|
||||
def auth_route_client(monkeypatch: pytest.MonkeyPatch):
|
||||
"""Return a Flask test client wired up enough to render the
|
||||
Tidal auth-instructions page."""
|
||||
# Force the "remote/docker" branch by faking a remote-host request.
|
||||
# Easier than mocking is_docker; the route only needs ONE of the
|
||||
# two flags to render the instructions page.
|
||||
monkeypatch.setattr(
|
||||
"os.path.exists",
|
||||
lambda p: p == "/.dockerenv" or False,
|
||||
)
|
||||
|
||||
fake_client = MagicMock()
|
||||
fake_client.client_id = "fake-id"
|
||||
fake_client.code_verifier = "v" * 40
|
||||
fake_client.code_challenge = "c" * 40
|
||||
fake_client.auth_url = "https://login.tidal.com/authorize"
|
||||
|
||||
def _set_redirect_uri(value):
|
||||
fake_client.redirect_uri = value
|
||||
fake_client._generate_pkce_challenge = MagicMock()
|
||||
|
||||
with patch("core.tidal_client.TidalClient", return_value=fake_client):
|
||||
with patch("web_server.add_activity_item"):
|
||||
from web_server import app as flask_app
|
||||
flask_app.config['TESTING'] = True
|
||||
yield flask_app.test_client(), fake_client
|
||||
|
||||
|
||||
def _extract_html(response) -> str:
|
||||
return response.get_data(as_text=True)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_instructions_show_tidal_port_not_spotify_port_when_config_uses_8889(
|
||||
auth_route_client, monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""The reported scenario: tidal.redirect_uri config carries port
|
||||
8889, the rendered instructions must show 8889 (not Spotify's
|
||||
8888) in both the Step 2 example and the Step 3 highlighted URL."""
|
||||
client, fake_client = auth_route_client
|
||||
|
||||
fake_client.redirect_uri = "http://127.0.0.1:8889/tidal/callback"
|
||||
|
||||
from config.settings import config_manager
|
||||
monkeypatch.setattr(
|
||||
config_manager, "get",
|
||||
lambda key, default=None: (
|
||||
"http://127.0.0.1:8889/tidal/callback"
|
||||
if key == "tidal.redirect_uri" else default
|
||||
),
|
||||
)
|
||||
|
||||
response = client.get("/auth/tidal", base_url="http://192.168.1.50:8008")
|
||||
html = _extract_html(response)
|
||||
|
||||
# Both example URLs in the instructions must use Tidal's port.
|
||||
assert ":8889/tidal/callback" in html, (
|
||||
"Step 2/3 example URLs must reflect the configured Tidal port"
|
||||
)
|
||||
assert ":8888/tidal/callback" not in html, (
|
||||
"Spotify's port must not appear in Tidal auth instructions"
|
||||
)
|
||||
|
||||
|
||||
def test_instructions_respect_custom_callback_port_from_env(
|
||||
auth_route_client, monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""SOULSYNC_TIDAL_CALLBACK_PORT env var changes which port the
|
||||
Tidal callback server binds to; the instructions must reflect
|
||||
that custom port too, not assume the 8889 default."""
|
||||
client, fake_client = auth_route_client
|
||||
|
||||
fake_client.redirect_uri = "http://127.0.0.1:9999/tidal/callback"
|
||||
|
||||
from config.settings import config_manager
|
||||
monkeypatch.setattr(
|
||||
config_manager, "get",
|
||||
lambda key, default=None: (
|
||||
"http://127.0.0.1:9999/tidal/callback"
|
||||
if key == "tidal.redirect_uri" else default
|
||||
),
|
||||
)
|
||||
monkeypatch.setenv("SOULSYNC_TIDAL_CALLBACK_PORT", "9999")
|
||||
|
||||
response = client.get("/auth/tidal", base_url="http://192.168.1.50:8008")
|
||||
html = _extract_html(response)
|
||||
|
||||
assert ":9999/tidal/callback" in html
|
||||
|
||||
|
||||
def test_instructions_fall_back_to_default_port_when_redirect_uri_is_unparseable(
|
||||
auth_route_client, monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
"""Defensive: if redirect_uri somehow has no port (corrupted
|
||||
config, schemeless string, etc.), the instructions fall back to
|
||||
the default Tidal port from the env var instead of crashing or
|
||||
showing the Spotify port."""
|
||||
client, fake_client = auth_route_client
|
||||
|
||||
fake_client.redirect_uri = "not-a-valid-url"
|
||||
|
||||
from config.settings import config_manager
|
||||
monkeypatch.setattr(
|
||||
config_manager, "get",
|
||||
lambda key, default=None: (
|
||||
"not-a-valid-url" if key == "tidal.redirect_uri" else default
|
||||
),
|
||||
)
|
||||
|
||||
response = client.get("/auth/tidal", base_url="http://192.168.1.50:8008")
|
||||
html = _extract_html(response)
|
||||
|
||||
# Falls back to Tidal default 8889, never to Spotify's 8888.
|
||||
assert ":8889/tidal/callback" in html
|
||||
assert ":8888/tidal/callback" not in html
|
||||
Loading…
Reference in new issue