Files
OpenBB/cli/tests/test_codegen_credentials.py
Danglewood 5b20e24352 [V5] openbb-cli: Modular OpenAPI Refs (#7589)
* follow up to #7585

* add another codegen test
2026-07-14 12:49:37 -07:00

197 lines
5.5 KiB
Python

"""Tests for openbb_cli.codegen.credentials — credential name detection."""
from __future__ import annotations
import pytest
from openbb_cli.codegen import credentials as cr
# --- normalize_credential_key ---
@pytest.mark.parametrize(
"raw,expected",
[
("api_key", "api_key"),
("API-KEY", "api_key"),
("X-API-Key", "x_api_key"),
("apikey", "apikey"),
("App-Token", "app_token"),
("Authorization", "authorization"),
("__leading__trailing__", "leading__trailing"),
],
)
def test_normalize_credential_key_canonicalizes_separators_and_case(raw, expected):
assert cr.normalize_credential_key(raw) == expected
# --- is_credential_name ---
@pytest.mark.parametrize(
"name",
[
"api_key",
"api_token",
"api-token",
"apikey",
"API_KEY",
"X-API-Key",
"x-api-key",
"app_token",
"client_id",
"client_secret",
"Authorization",
"subscription_key",
"Ocp-Apim-Subscription-Key",
"bearer_token",
"session_token",
"private_key",
],
)
def test_is_credential_name_recognizes_canonical_credentials(name):
assert cr.is_credential_name(name) is True
@pytest.mark.parametrize(
"name",
[
"symbol",
"limit",
"from_date",
"x_columns",
"interval",
"format",
"page_size",
],
)
def test_is_credential_name_rejects_regular_params(name):
assert cr.is_credential_name(name) is False
# --- classify_parameter ---
def test_classify_parameter_returns_query_for_query_credential():
p = {"name": "api_key", "in": "query"}
assert cr.classify_parameter(p) == "query"
def test_classify_parameter_returns_header_for_header_credential():
p = {"name": "Authorization", "in": "header"}
assert cr.classify_parameter(p) == "header"
def test_classify_parameter_defaults_to_query_when_in_unset():
"""A credential without an ``in`` location is treated as query (most common)."""
p = {"name": "api_key"}
assert cr.classify_parameter(p) == "query"
def test_classify_parameter_returns_none_for_regular_param():
p = {"name": "symbol", "in": "query"}
assert cr.classify_parameter(p) is None
def test_classify_parameter_returns_none_for_unnamed_param():
"""A malformed param entry without ``name`` is gracefully skipped."""
assert cr.classify_parameter({}) is None
assert cr.classify_parameter({"name": 42, "in": "query"}) is None # type: ignore[arg-type]
def test_classify_parameter_returns_none_for_non_dict_input():
"""Defensive: a stray non-dict in the parameters list doesn't crash."""
assert cr.classify_parameter("not-a-dict") is None # type: ignore[arg-type]
# --- credentials_from_command ---
def test_credentials_from_command_extracts_query_and_header_entries():
cmd = {
"parameters": [
{"name": "symbol", "in": "query"},
{"name": "api_key", "in": "query"},
{"name": "Authorization", "in": "header"},
]
}
out = cr.credentials_from_command(cmd)
assert out == {
"api_key": {"name": "api_key", "in": "query"},
"authorization": {"name": "Authorization", "in": "header"},
}
def test_credentials_from_command_returns_empty_when_no_creds():
assert cr.credentials_from_command({"parameters": [{"name": "limit"}]}) == {}
def test_credentials_from_command_handles_missing_parameters_key():
assert cr.credentials_from_command({}) == {}
# --- credentials_from_spec ---
def test_credentials_from_spec_aggregates_across_commands():
spec = {
"commands": {
"a": {"parameters": [{"name": "api_key", "in": "query"}]},
"b": {"parameters": [{"name": "Authorization", "in": "header"}]},
"c": {"parameters": [{"name": "symbol", "in": "query"}]},
}
}
out = cr.credentials_from_spec(spec)
assert set(out) == {"api_key", "authorization"}
assert out["api_key"]["name"] == "api_key"
assert out["authorization"]["in"] == "header"
def test_credentials_from_spec_first_occurrence_wins_on_collision():
"""If two commands declare the same canonical key with different spellings,
the first one encountered keeps its on-the-wire spelling."""
spec = {
"commands": {
"a": {"parameters": [{"name": "API-KEY", "in": "query"}]},
"b": {"parameters": [{"name": "api_key", "in": "header"}]},
}
}
out = cr.credentials_from_spec(spec)
assert out["api_key"]["name"] == "API-KEY"
assert out["api_key"]["in"] == "query"
def test_credentials_from_spec_returns_empty_when_no_commands():
assert cr.credentials_from_spec({}) == {}
# --- filter_user_params ---
def test_filter_user_params_strips_credential_entries():
params = [
{"name": "symbol", "in": "query"},
{"name": "api_key", "in": "query"},
{"name": "limit", "in": "query"},
{"name": "Authorization", "in": "header"},
]
out = cr.filter_user_params(params)
names = [p["name"] for p in out]
assert names == ["symbol", "limit"]
def test_filter_user_params_returns_empty_for_none_or_empty():
assert cr.filter_user_params(None) == [] # type: ignore[arg-type]
assert cr.filter_user_params([]) == []
def test_filter_user_params_does_not_mutate_input():
"""Defensive: the input list is unchanged after filtering."""
params = [
{"name": "api_key", "in": "query"},
{"name": "symbol", "in": "query"},
]
original = list(params)
cr.filter_user_params(params)
assert params == original