Files
fn_registry/python/functions/infra/hoppscotch_run_request_test.py
T
egutierrez eb8dbf66a1 feat(infra): auto-commit con 88 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-11 00:16:46 +02:00

207 lines
6.1 KiB
Python

"""Tests para hoppscotch_run_request.
Deterministas: monkeypatchean requests.request (ejecucion HTTP) y requests.post
(mutation createUserHistory). Verifican la resolucion de placedores `<<>>`/`{{}}`
para EJECUTAR, que el History recibe la request SIN resolver, y los caminos de
record_history=False y de error de transporte.
"""
import json
import sys
from datetime import timedelta
import infra.hoppscotch_run_request # noqa: F401
# El __init__ rebinds el nombre a la funcion; recuperamos el submodulo real.
mod = sys.modules["infra.hoppscotch_run_request"]
class _FakeResponse:
"""Respuesta minima para requests.request (ejecucion)."""
def __init__(self, status_code=200, text="OK", headers=None, elapsed_ms=12):
self.status_code = status_code
self.text = text
self.headers = headers or {"Content-Type": "text/plain"}
self.elapsed = timedelta(milliseconds=elapsed_ms)
class _FakeGraphQLResponse:
"""Respuesta minima para requests.post (createUserHistory)."""
def __init__(self, status_code=200, json_data=None):
self.status_code = status_code
self._json = json_data
def json(self):
if self._json is None:
raise ValueError("no json")
return self._json
def _patch_history_ok(monkeypatch, captured):
def fake_post(url, **kwargs):
captured["history_url"] = url
captured["history_kwargs"] = kwargs
return _FakeGraphQLResponse(
200, {"data": {"createUserHistory": {"id": "hist-42"}}}
)
monkeypatch.setattr(mod.requests, "post", fake_post)
def test_ejecuta_resolviendo_variables_angle(monkeypatch):
captured = {}
def fake_request(method, url, **kwargs):
captured["method"] = method
captured["url"] = url
captured["kwargs"] = kwargs
return _FakeResponse(200, text="pong")
monkeypatch.setattr(mod.requests, "request", fake_request)
_patch_history_ok(monkeypatch, captured)
result = mod.hoppscotch_run_request(
"GET",
"<<baseURL>>/x",
variables={"baseURL": "https://h"},
access_token="A",
)
# La request ejecutada lleva la url resuelta.
assert captured["url"] == "https://h/x"
assert result["status"] == "ok"
assert result["status_code"] == 200
assert result["response_body"] == "pong"
assert result["duration_ms"] == 12
def test_ejecuta_resolviendo_variables_brace(monkeypatch):
captured = {}
def fake_request(method, url, **kwargs):
captured["url"] = url
return _FakeResponse(200)
monkeypatch.setattr(mod.requests, "request", fake_request)
_patch_history_ok(monkeypatch, captured)
mod.hoppscotch_run_request(
"GET",
"{{baseURL}}/x",
variables={"baseURL": "https://h"},
access_token="A",
)
# {{var}} resuelve igual que <<var>>.
assert captured["url"] == "https://h/x"
def test_record_history_registra_request_sin_resolver(monkeypatch):
captured = {}
def fake_request(method, url, **kwargs):
return _FakeResponse(200, text="body", headers={"X-Test": "1"})
monkeypatch.setattr(mod.requests, "request", fake_request)
_patch_history_ok(monkeypatch, captured)
result = mod.hoppscotch_run_request(
"GET",
"<<baseURL>>/api/status",
title="Status",
variables={"baseURL": "https://h"},
access_token="ACCESS-JWT",
record_history=True,
)
assert result["recorded"] is True
assert result["history_id"] == "hist-42"
# El POST de History fue al endpoint GraphQL con la cookie access_token.
assert captured["history_url"].endswith("/graphql")
assert captured["history_kwargs"]["cookies"] == {"access_token": "ACCESS-JWT"}
payload = captured["history_kwargs"]["json"]
assert "createUserHistory" in payload["query"]
variables = payload["variables"]
assert variables["t"] == "REST"
# reqData es el json string de un HoppRESTRequest v:"2" con la url SIN resolver.
req = json.loads(variables["d"])
assert req["v"] == "2"
assert req["method"] == "GET"
assert req["endpoint"] == "<<baseURL>>/api/status"
assert req["name"] == "Status"
# resMetadata minimo: statusCode + duration.
res_meta = json.loads(variables["m"])
assert res_meta == {"statusCode": 200, "duration": 12}
def test_record_history_false_no_llama_create_user_history(monkeypatch):
calls = {"post": 0}
def fake_request(method, url, **kwargs):
return _FakeResponse(200)
def fake_post(url, **kwargs):
calls["post"] += 1
return _FakeGraphQLResponse(200, {"data": {"createUserHistory": {"id": "x"}}})
monkeypatch.setattr(mod.requests, "request", fake_request)
monkeypatch.setattr(mod.requests, "post", fake_post)
result = mod.hoppscotch_run_request(
"GET",
"https://h/x",
access_token="A",
record_history=False,
)
assert result["recorded"] is False
assert result["history_id"] is None
assert calls["post"] == 0
def test_request_exception_status_error(monkeypatch):
def fake_request(method, url, **kwargs):
raise mod.requests.RequestException("boom")
# Si llegara a postear seria un fallo del test: no debe.
def fake_post(url, **kwargs):
raise AssertionError("no debe registrar history si la ejecucion fallo")
monkeypatch.setattr(mod.requests, "request", fake_request)
monkeypatch.setattr(mod.requests, "post", fake_post)
result = mod.hoppscotch_run_request(
"GET", "https://h/x", access_token="A"
)
assert result["status"] == "error"
assert result["recorded"] is False
assert "boom" in result["error"]
def test_variable_faltante_conserva_literal(monkeypatch):
captured = {}
def fake_request(method, url, **kwargs):
captured["url"] = url
return _FakeResponse(200)
monkeypatch.setattr(mod.requests, "request", fake_request)
_patch_history_ok(monkeypatch, captured)
mod.hoppscotch_run_request(
"GET",
"<<baseURL>>/x",
variables={"otra": "y"},
access_token="A",
)
# baseURL no esta en variables -> el literal se conserva.
assert captured["url"] == "<<baseURL>>/x"