Skip to content

Commit eb4eea2

Browse files
Improve the entire specification test suite (#17)
* Improved the spec tests by adding some tests for the session service * style: Apply automated code formatting [skip ci] * Test commit to trigger the workflow runs * Added more tests to better verify the auth * style: Apply automated code formatting [skip ci] * Added more tests to better verify the auth * Encapsulated all the specificiation tests into classes --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 41160d3 commit eb4eea2

10 files changed

+451
-190
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import os
2+
3+
import pytest
4+
5+
import zitadel_client as zitadel
6+
from zitadel_client.exceptions import OpenApiError
7+
8+
9+
@pytest.fixture(scope="module")
10+
def base_url() -> str:
11+
"""Provides the base URL for tests, skipping if unset."""
12+
url = os.getenv("BASE_URL")
13+
if not url:
14+
pytest.skip("Environment variable BASE_URL must be set", allow_module_level=True)
15+
return url
16+
17+
18+
@pytest.fixture(scope="module")
19+
def auth_token() -> str:
20+
"""Provides the auth token for tests, skipping if unset."""
21+
url = os.getenv("AUTH_TOKEN")
22+
if not url:
23+
pytest.skip("Environment variable AUTH_TOKEN must be set", allow_module_level=True)
24+
return url
25+
26+
27+
class TestUseAccessTokenSpec:
28+
"""
29+
SettingsService Integration Tests (Personal Access Token)
30+
31+
This suite verifies the Zitadel SettingsService API's general settings
32+
endpoint works when authenticating via a Personal Access Token:
33+
34+
1. Retrieve general settings successfully with a valid token
35+
2. Expect an ApiException when using an invalid token
36+
37+
Each test instantiates a new client to ensure a clean, stateless call.
38+
"""
39+
40+
def test_retrieves_general_settings_with_valid_token(
41+
self,
42+
base_url: str,
43+
auth_token: str,
44+
) -> None:
45+
"""Retrieves general settings successfully with a valid access token."""
46+
client = zitadel.Zitadel.with_access_token(
47+
base_url,
48+
auth_token,
49+
)
50+
client.settings.settings_service_get_general_settings()
51+
52+
def test_raises_api_exception_with_invalid_token(
53+
self,
54+
base_url: str,
55+
) -> None:
56+
"""Raises ApiException when using an invalid access token."""
57+
client = zitadel.Zitadel.with_access_token(
58+
base_url,
59+
"invalid",
60+
)
61+
with pytest.raises(OpenApiError):
62+
client.settings.settings_service_get_general_settings()
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import os
2+
3+
import pytest
4+
5+
import zitadel_client as zitadel
6+
from zitadel_client.exceptions import OpenApiError
7+
8+
9+
@pytest.fixture(scope="module")
10+
def base_url() -> str:
11+
"""Provides the base URL for tests, skipping if unset."""
12+
url = os.getenv("BASE_URL")
13+
if not url:
14+
pytest.skip("Environment variable BASE_URL must be set", allow_module_level=True)
15+
return url
16+
17+
18+
@pytest.fixture(scope="module")
19+
def client_id() -> str:
20+
"""Provides the client ID for tests, skipping if unset."""
21+
cid = os.getenv("CLIENT_ID")
22+
if not cid:
23+
pytest.skip("Environment variable CLIENT_ID must be set", allow_module_level=True)
24+
return cid
25+
26+
27+
@pytest.fixture(scope="module")
28+
def client_secret() -> str:
29+
"""Provides the client secret for tests, skipping if unset."""
30+
cs = os.getenv("CLIENT_SECRET")
31+
if not cs:
32+
pytest.skip("Environment variable CLIENT_SECRET must be set", allow_module_level=True)
33+
return cs
34+
35+
36+
class TestUseClientCredentialsSpec:
37+
"""
38+
SettingsService Integration Tests (Client Credentials)
39+
40+
This suite verifies the Zitadel SettingsService API's general settings
41+
endpoint works when authenticating via Client Credentials:
42+
43+
1. Retrieve general settings successfully with valid credentials
44+
2. Expect an ApiException when using invalid credentials
45+
46+
Each test instantiates a new client to ensure a clean, stateless call.
47+
"""
48+
49+
def test_retrieves_general_settings_with_valid_client_credentials(
50+
self,
51+
base_url: str,
52+
client_id: str,
53+
client_secret: str,
54+
) -> None:
55+
"""Retrieves general settings successfully with valid client credentials."""
56+
client = zitadel.Zitadel.with_client_credentials(
57+
base_url,
58+
client_id,
59+
client_secret,
60+
)
61+
client.settings.settings_service_get_general_settings()
62+
63+
def test_raises_api_exception_with_invalid_client_credentials(
64+
self,
65+
base_url: str,
66+
) -> None:
67+
"""Raises ApiException when using invalid client credentials."""
68+
client = zitadel.Zitadel.with_client_credentials(
69+
base_url,
70+
"invalid",
71+
"invalid",
72+
)
73+
with pytest.raises(OpenApiError):
74+
client.settings.settings_service_get_general_settings()
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import os
2+
import pathlib
3+
4+
import pytest
5+
6+
import zitadel_client as zitadel
7+
from zitadel_client import OpenApiError
8+
9+
10+
@pytest.fixture(scope="module")
11+
def base_url() -> str:
12+
"""Provides the base URL for tests, skipping if unset."""
13+
url = os.getenv("BASE_URL")
14+
if not url:
15+
pytest.skip("Environment variable BASE_URL must be set", allow_module_level=True)
16+
return url
17+
18+
19+
@pytest.fixture
20+
def key_file(tmp_path: pathlib.Path) -> str:
21+
raw: str = os.getenv("JWT_KEY") or ""
22+
file_path: pathlib.Path = tmp_path / "jwt.json"
23+
file_path.write_text(raw)
24+
return str(file_path)
25+
26+
27+
class TestUsePrivateKeySpec:
28+
"""
29+
SettingsService Integration Tests (Private Key Assertion)
30+
31+
This suite verifies the Zitadel SettingsService API's general settings
32+
endpoint works when authenticating via a private key assertion:
33+
34+
1. Retrieve general settings successfully with a valid private key
35+
2. Expect an ApiException when using an invalid private key path
36+
37+
Each test instantiates a new client to ensure a clean, stateless call.
38+
"""
39+
40+
def test_retrieves_general_settings_with_valid_private_key(
41+
self,
42+
base_url: str,
43+
key_file: str,
44+
) -> None:
45+
"""Retrieves general settings successfully with a valid private key."""
46+
client = zitadel.Zitadel.with_private_key(
47+
base_url,
48+
key_file,
49+
)
50+
client.settings.settings_service_get_general_settings()
51+
52+
def test_raises_api_exception_with_invalid_private_key(
53+
self,
54+
key_file: str,
55+
) -> None:
56+
"""Raises ApiException when using an invalid private key path."""
57+
client = zitadel.Zitadel.with_private_key(
58+
"https://zitadel.cloud",
59+
key_file,
60+
)
61+
with pytest.raises(OpenApiError):
62+
client.settings.settings_service_get_general_settings()

spec/check_session_service_spec.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import os
2+
import uuid
3+
from typing import Generator
4+
5+
import pytest
6+
7+
import zitadel_client as zitadel
8+
from zitadel_client.exceptions import ApiException
9+
from zitadel_client.models import (
10+
SessionServiceChecks,
11+
SessionServiceCheckUser,
12+
SessionServiceCreateSessionRequest,
13+
SessionServiceCreateSessionResponse,
14+
SessionServiceDeleteSessionBody,
15+
SessionServiceGetSessionResponse,
16+
SessionServiceListSessionsRequest,
17+
SessionServiceListSessionsResponse,
18+
SessionServiceSetSessionRequest,
19+
SessionServiceSetSessionResponse,
20+
)
21+
22+
23+
@pytest.fixture(scope="module")
24+
def base_url() -> str:
25+
"""Provides the base URL for tests, skipping if unset."""
26+
url = os.getenv("BASE_URL")
27+
if not url:
28+
pytest.skip("Environment variable BASE_URL must be set", allow_module_level=True)
29+
return url
30+
31+
32+
@pytest.fixture(scope="module")
33+
def auth_token() -> str:
34+
"""Provides a valid personal access token, skipping if unset."""
35+
token = os.getenv("AUTH_TOKEN")
36+
if not token:
37+
pytest.skip("Environment variable AUTH_TOKEN must be set", allow_module_level=True)
38+
return token
39+
40+
41+
@pytest.fixture(scope="module")
42+
def client(base_url: str, auth_token: str) -> zitadel.Zitadel:
43+
"""Provides a Zitadel client configured with a personal access token."""
44+
return zitadel.Zitadel.with_access_token(base_url, auth_token)
45+
46+
47+
@pytest.fixture
48+
def session(client: zitadel.Zitadel) -> Generator[SessionServiceCreateSessionResponse, None, None]:
49+
"""Creates a fresh session for each test and cleans up afterward."""
50+
request = SessionServiceCreateSessionRequest(
51+
checks=SessionServiceChecks(user=SessionServiceCheckUser(loginName="johndoe")),
52+
lifetime="18000s",
53+
)
54+
response = client.sessions.session_service_create_session(request)
55+
yield response
56+
# Teardown
57+
delete_body = SessionServiceDeleteSessionBody()
58+
try:
59+
client.sessions.session_service_delete_session(
60+
response.session_id if response.session_id is not None else "",
61+
delete_body,
62+
)
63+
except ApiException:
64+
pass
65+
66+
67+
class TestSessionServiceSanityCheckSpec:
68+
"""
69+
SessionService Integration Tests
70+
71+
This suite verifies the Zitadel SessionService API's basic operations using a
72+
personal access token:
73+
74+
1. Create a session with specified checks and lifetime
75+
2. Retrieve the session by ID
76+
3. List sessions and ensure the created session appears
77+
4. Update the session's lifetime and confirm a new token is returned
78+
5. Error when retrieving a non-existent session
79+
80+
Each test runs in isolation: a new session is created in the `session` fixture and
81+
deleted after the test to ensure a clean state.
82+
"""
83+
84+
def test_retrieves_session_details_by_id(
85+
self,
86+
client: zitadel.Zitadel,
87+
session: SessionServiceCreateSessionResponse,
88+
) -> None:
89+
"""Retrieves the session details by ID."""
90+
response: SessionServiceGetSessionResponse = client.sessions.session_service_get_session(
91+
session.session_id if session.session_id is not None else ""
92+
)
93+
assert response.session is not None
94+
assert response.session.id == session.session_id
95+
96+
def test_includes_created_session_when_listing(
97+
self,
98+
client: zitadel.Zitadel,
99+
session: SessionServiceCreateSessionResponse,
100+
) -> None:
101+
"""Includes the created session when listing all sessions."""
102+
request = SessionServiceListSessionsRequest(queries=[])
103+
response: SessionServiceListSessionsResponse = client.sessions.session_service_list_sessions(request)
104+
assert response.sessions is not None
105+
assert session.session_id in [session.id for session in response.sessions]
106+
107+
def test_updates_session_lifetime_and_returns_new_token(
108+
self,
109+
client: zitadel.Zitadel,
110+
session: SessionServiceCreateSessionResponse,
111+
) -> None:
112+
"""Updates the session lifetime and returns a new token."""
113+
request = SessionServiceSetSessionRequest(lifetime="36000s")
114+
response: SessionServiceSetSessionResponse = client.sessions.session_service_set_session(
115+
session.session_id if session.session_id is not None else "",
116+
request,
117+
)
118+
assert isinstance(response.session_token, str)
119+
120+
def test_raises_api_exception_for_nonexistent_session(
121+
self,
122+
client: zitadel.Zitadel,
123+
session: SessionServiceCreateSessionResponse,
124+
) -> None:
125+
"""Raises an ApiException when retrieving a non-existent session."""
126+
with pytest.raises(ApiException):
127+
client.sessions.session_service_get_session(
128+
str(uuid.uuid4()),
129+
session_token=session.session_token,
130+
)

0 commit comments

Comments
 (0)