118 lines
4.1 KiB
Python
118 lines
4.1 KiB
Python
"""Regression tests for Google Workspace API credential validation."""
|
|
|
|
import importlib.util
|
|
import json
|
|
import sys
|
|
import types
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
SCRIPT_PATH = (
|
|
Path(__file__).resolve().parents[2]
|
|
/ "skills/productivity/google-workspace/scripts/google_api.py"
|
|
)
|
|
|
|
|
|
class FakeAuthorizedCredentials:
|
|
def __init__(self, *, valid=True, expired=False, refresh_token="refresh-token"):
|
|
self.valid = valid
|
|
self.expired = expired
|
|
self.refresh_token = refresh_token
|
|
self.refresh_calls = 0
|
|
|
|
def refresh(self, _request):
|
|
self.refresh_calls += 1
|
|
self.valid = True
|
|
self.expired = False
|
|
|
|
def to_json(self):
|
|
return json.dumps({
|
|
"token": "refreshed-token",
|
|
"refresh_token": self.refresh_token,
|
|
"token_uri": "https://oauth2.googleapis.com/token",
|
|
"client_id": "client-id",
|
|
"client_secret": "client-secret",
|
|
"scopes": [
|
|
"https://www.googleapis.com/auth/gmail.readonly",
|
|
"https://www.googleapis.com/auth/gmail.send",
|
|
"https://www.googleapis.com/auth/gmail.modify",
|
|
"https://www.googleapis.com/auth/calendar",
|
|
"https://www.googleapis.com/auth/drive.readonly",
|
|
"https://www.googleapis.com/auth/contacts.readonly",
|
|
"https://www.googleapis.com/auth/spreadsheets",
|
|
"https://www.googleapis.com/auth/documents.readonly",
|
|
],
|
|
})
|
|
|
|
|
|
class FakeCredentialsFactory:
|
|
creds = FakeAuthorizedCredentials()
|
|
|
|
@classmethod
|
|
def from_authorized_user_file(cls, _path, _scopes):
|
|
return cls.creds
|
|
|
|
|
|
@pytest.fixture
|
|
def google_api_module(monkeypatch, tmp_path):
|
|
google_module = types.ModuleType("google")
|
|
oauth2_module = types.ModuleType("google.oauth2")
|
|
credentials_module = types.ModuleType("google.oauth2.credentials")
|
|
credentials_module.Credentials = FakeCredentialsFactory
|
|
auth_module = types.ModuleType("google.auth")
|
|
transport_module = types.ModuleType("google.auth.transport")
|
|
requests_module = types.ModuleType("google.auth.transport.requests")
|
|
requests_module.Request = object
|
|
|
|
monkeypatch.setitem(sys.modules, "google", google_module)
|
|
monkeypatch.setitem(sys.modules, "google.oauth2", oauth2_module)
|
|
monkeypatch.setitem(sys.modules, "google.oauth2.credentials", credentials_module)
|
|
monkeypatch.setitem(sys.modules, "google.auth", auth_module)
|
|
monkeypatch.setitem(sys.modules, "google.auth.transport", transport_module)
|
|
monkeypatch.setitem(sys.modules, "google.auth.transport.requests", requests_module)
|
|
|
|
spec = importlib.util.spec_from_file_location("google_workspace_api_test", SCRIPT_PATH)
|
|
module = importlib.util.module_from_spec(spec)
|
|
assert spec.loader is not None
|
|
spec.loader.exec_module(module)
|
|
|
|
monkeypatch.setattr(module, "TOKEN_PATH", tmp_path / "google_token.json")
|
|
return module
|
|
|
|
|
|
def _write_token(path: Path, scopes):
|
|
path.write_text(json.dumps({
|
|
"token": "access-token",
|
|
"refresh_token": "refresh-token",
|
|
"token_uri": "https://oauth2.googleapis.com/token",
|
|
"client_id": "client-id",
|
|
"client_secret": "client-secret",
|
|
"scopes": scopes,
|
|
}))
|
|
|
|
|
|
def test_get_credentials_rejects_missing_scopes(google_api_module, capsys):
|
|
FakeCredentialsFactory.creds = FakeAuthorizedCredentials(valid=True)
|
|
_write_token(google_api_module.TOKEN_PATH, [
|
|
"https://www.googleapis.com/auth/drive.readonly",
|
|
"https://www.googleapis.com/auth/spreadsheets",
|
|
])
|
|
|
|
with pytest.raises(SystemExit):
|
|
google_api_module.get_credentials()
|
|
|
|
err = capsys.readouterr().err
|
|
assert "missing google workspace scopes" in err.lower()
|
|
assert "gmail.send" in err
|
|
|
|
|
|
def test_get_credentials_accepts_full_scope_token(google_api_module):
|
|
FakeCredentialsFactory.creds = FakeAuthorizedCredentials(valid=True)
|
|
_write_token(google_api_module.TOKEN_PATH, list(google_api_module.SCOPES))
|
|
|
|
creds = google_api_module.get_credentials()
|
|
|
|
assert creds is FakeCredentialsFactory.creds
|