eb8dbf66a1
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
207 lines
6.1 KiB
Python
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"
|