Skip to content

Commit 63009c0

Browse files
committed
Add tests for tiled check
1 parent acccb0c commit 63009c0

1 file changed

Lines changed: 91 additions & 2 deletions

File tree

tests/unit_tests/service/test_authorization.py

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
from unittest.mock import AsyncMock, MagicMock, patch
1+
from contextlib import AbstractContextManager, nullcontext
2+
from unittest.mock import AsyncMock, MagicMock, Mock, patch
23

34
import pytest
45
from pydantic import HttpUrl
56

6-
from blueapi.config import OpaConfig
7+
from blueapi.config import OIDCConfig, OpaConfig, ServiceAccount
78
from blueapi.service.authorization import (
89
OpaClient,
10+
validate_tiled_config,
911
)
1012

1113
# Reusable client patch decorator
@@ -20,9 +22,50 @@
2022
def opa_config() -> OpaConfig:
2123
return OpaConfig(
2224
root=HttpUrl("http://auth.example.com"),
25+
tiled_service_account_check="/auth/tiled",
2326
)
2427

2528

29+
@patch_client_session
30+
@pytest.mark.parametrize(
31+
"result,context",
32+
[
33+
(False, pytest.raises(ValueError, match="Tiled service account is not valid ")),
34+
(True, nullcontext()),
35+
],
36+
)
37+
async def test_tiled_service_account(
38+
session: MagicMock,
39+
opa_config: OpaConfig,
40+
result: bool,
41+
context: AbstractContextManager,
42+
):
43+
session.return_value.post = AsyncMock(
44+
return_value=MagicMock(json=AsyncMock(return_value={"result": result}))
45+
)
46+
47+
client = OpaClient(instrument="p99", config=opa_config)
48+
49+
session.assert_called_once_with(base_url="http://auth.example.com/")
50+
with context:
51+
await client.require_tiled_service_account(token="foo_bar")
52+
session().post.assert_called_once_with(
53+
"/auth/tiled",
54+
json={"input": {"token": "foo_bar", "beamline": "p99", "audience": "account"}},
55+
)
56+
57+
58+
@patch_client_session
59+
async def test_exception_raised_when_opa_fails(
60+
session: MagicMock, opa_config: OpaConfig
61+
):
62+
session.return_value.post = AsyncMock(side_effect=RuntimeError("Connection failed"))
63+
async with OpaClient.for_config("p45", opa_config) as client:
64+
assert client is not None
65+
with pytest.raises(RuntimeError, match="Connection failed"):
66+
await client.require_tiled_service_account(token="foo_bar")
67+
68+
2669
@patch_client_session
2770
async def test_session_closed(session: MagicMock, opa_config: OpaConfig):
2871
async with OpaClient.for_config("p45", opa_config):
@@ -60,3 +103,49 @@ async def test_opa_adds_input_fields(session: MagicMock, opa_config: OpaConfig):
60103
"foo/bar",
61104
json={"input": {"beamline": "p45", "audience": "account", "foo": "bar"}},
62105
)
106+
107+
108+
async def test_validate_tiled_config():
109+
opa = MagicMock(spec=OpaClient)
110+
tiled = ServiceAccount()
111+
oidc = Mock(spec=OIDCConfig)
112+
oidc.token_endpoint = "token-endpoint"
113+
with patch("blueapi.service.authorization.TiledAuth") as auth:
114+
auth.return_value.get_access_token.return_value = "tiled-token"
115+
await validate_tiled_config(tiled, oidc, opa)
116+
117+
auth.assert_called_once_with(tiled)
118+
opa.require_tiled_service_account.assert_called_once_with("tiled-token")
119+
120+
121+
@pytest.mark.parametrize(
122+
"tiled_auth,oidc,opa_client",
123+
[
124+
(None, None, MagicMock(spec=OpaClient)),
125+
(
126+
None,
127+
OIDCConfig(well_known_url="http://example.com", client_id="test-client"),
128+
MagicMock(spec=OpaClient),
129+
),
130+
("api_key", None, MagicMock(spec=OpaClient)),
131+
(
132+
"api_key",
133+
OIDCConfig(well_known_url="http://example.com", client_id="test-client"),
134+
MagicMock(spec=OpaClient),
135+
),
136+
(ServiceAccount(), None, MagicMock(spec=OpaClient)),
137+
(
138+
ServiceAccount(),
139+
OIDCConfig(well_known_url="http://example.com", client_id="test-client"),
140+
None,
141+
),
142+
],
143+
)
144+
async def test_validate_tiled_config_with_missing_config(
145+
tiled_auth: ServiceAccount | str | None,
146+
oidc: OIDCConfig | None,
147+
opa_client: MagicMock | None,
148+
):
149+
assert await validate_tiled_config(tiled_auth, oidc, opa_client) is None
150+
if opa_client is not None:
151+
opa_client.require_tiled_service_account.assert_not_called()

0 commit comments

Comments
 (0)