763e06c127
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
97 lines
3.1 KiB
Python
97 lines
3.1 KiB
Python
"""Tests para gsc_auth (sin credenciales reales ni red)."""
|
|
|
|
import os
|
|
import sys
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
|
|
|
|
from functions.infra.gsc_auth import gsc_auth # noqa: E402
|
|
|
|
_SCOPE = "https://www.googleapis.com/auth/webmasters.readonly"
|
|
|
|
|
|
def _patches():
|
|
"""Devuelve los context managers para mockear creds y build.
|
|
|
|
La funcion importa de forma diferida desde
|
|
``google.oauth2.service_account`` y ``googleapiclient.discovery``,
|
|
por eso se parchea en el modulo de origen.
|
|
"""
|
|
creds_patch = mock.patch(
|
|
"google.oauth2.service_account.Credentials.from_service_account_file"
|
|
)
|
|
build_patch = mock.patch("googleapiclient.discovery.build")
|
|
return creds_patch, build_patch
|
|
|
|
|
|
def test_build_se_llama_con_searchconsole_v1_y_cache_off():
|
|
creds_patch, build_patch = _patches()
|
|
with creds_patch as m_creds, build_patch as m_build:
|
|
fake_creds = mock.Mock(name="creds")
|
|
m_creds.return_value = fake_creds
|
|
fake_service = mock.Mock(name="service")
|
|
m_build.return_value = fake_service
|
|
|
|
result = gsc_auth(credentials_path="/tmp/sa.json")
|
|
|
|
assert result is fake_service
|
|
m_build.assert_called_once_with(
|
|
"searchconsole",
|
|
"v1",
|
|
credentials=fake_creds,
|
|
cache_discovery=False,
|
|
)
|
|
|
|
|
|
def test_credentials_se_cargan_con_scope_readonly():
|
|
creds_patch, build_patch = _patches()
|
|
with creds_patch as m_creds, build_patch as m_build:
|
|
m_creds.return_value = mock.Mock()
|
|
m_build.return_value = mock.Mock()
|
|
|
|
gsc_auth(credentials_path="/tmp/sa.json")
|
|
|
|
m_creds.assert_called_once_with("/tmp/sa.json", scopes=[_SCOPE])
|
|
|
|
|
|
def test_fallback_a_env_var_gsc_sa_json():
|
|
creds_patch, build_patch = _patches()
|
|
with creds_patch as m_creds, build_patch as m_build, mock.patch.dict(
|
|
os.environ, {"GSC_SA_JSON": "/env/sa.json"}, clear=False
|
|
):
|
|
m_creds.return_value = mock.Mock()
|
|
m_build.return_value = mock.Mock()
|
|
|
|
gsc_auth(credentials_path="")
|
|
|
|
m_creds.assert_called_once_with("/env/sa.json", scopes=[_SCOPE])
|
|
|
|
|
|
def test_subject_aplica_with_subject():
|
|
creds_patch, build_patch = _patches()
|
|
with creds_patch as m_creds, build_patch as m_build:
|
|
base_creds = mock.Mock(name="base_creds")
|
|
delegated = mock.Mock(name="delegated_creds")
|
|
base_creds.with_subject.return_value = delegated
|
|
m_creds.return_value = base_creds
|
|
m_build.return_value = mock.Mock()
|
|
|
|
gsc_auth(credentials_path="/tmp/sa.json", subject="user@dominio.com")
|
|
|
|
base_creds.with_subject.assert_called_once_with("user@dominio.com")
|
|
_, kwargs = m_build.call_args
|
|
assert kwargs["credentials"] is delegated
|
|
|
|
|
|
def test_error_cuando_falta_credential():
|
|
creds_patch, build_patch = _patches()
|
|
with creds_patch, build_patch, mock.patch.dict(
|
|
os.environ, {}, clear=True
|
|
):
|
|
with pytest.raises(ValueError) as exc:
|
|
gsc_auth(credentials_path="")
|
|
assert "GSC_SA_JSON" in str(exc.value)
|