Skip to content

Commit de2344c

Browse files
committed
Restructure tests: split TransportOptions unit tests from Zitadel integration tests
1 parent 4ae3329 commit de2344c

3 files changed

Lines changed: 162 additions & 141 deletions

File tree

test/fixtures/mappings/settings.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
"headers": {
99
"Content-Type": "application/json"
1010
},
11-
"jsonBody": {}
11+
"jsonBody": {
12+
"defaultLanguage": "{{request.scheme}}",
13+
"defaultOrgId": "{{request.headers.X-Custom-Header}}"
14+
}
1215
}
1316
}

test/test_transport_options.py

Lines changed: 28 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,148 +1,40 @@
1-
import json
2-
import os
31
import unittest
4-
import urllib.request
5-
from typing import Optional
6-
7-
from testcontainers.core.container import DockerContainer
8-
from testcontainers.core.network import Network
9-
from testcontainers.core.wait_strategies import PortWaitStrategy
10-
from testcontainers.core.waiting_utils import wait_container_is_ready
112

123
from zitadel_client.transport_options import TransportOptions
13-
from zitadel_client.zitadel import Zitadel
14-
15-
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures")
16-
17-
18-
@wait_container_is_ready()
19-
def _wait_for_wiremock(host: str, port: str) -> None:
20-
url = f"http://{host}:{port}/__admin/mappings"
21-
with urllib.request.urlopen(url, timeout=5) as resp: # noqa: S310
22-
if resp.status != 200:
23-
raise ConnectionError(f"WireMock not ready: {resp.status}")
244

255

266
class TransportOptionsTest(unittest.TestCase):
27-
host: Optional[str] = None
28-
http_port: Optional[str] = None
29-
https_port: Optional[str] = None
30-
proxy_port: Optional[str] = None
31-
ca_cert_path: Optional[str] = None
32-
wiremock: DockerContainer = None
33-
proxy: DockerContainer = None
34-
network: Network = None
35-
36-
@classmethod
37-
def setup_class(cls) -> None:
38-
cls.ca_cert_path = os.path.join(FIXTURES_DIR, "ca.pem")
39-
keystore_path = os.path.join(FIXTURES_DIR, "keystore.p12")
40-
squid_conf = os.path.join(FIXTURES_DIR, "squid.conf")
41-
42-
cls.network = Network().create()
43-
44-
cls.wiremock = (
45-
DockerContainer("wiremock/wiremock:3.12.1")
46-
.with_network(cls.network)
47-
.with_network_aliases("wiremock")
48-
.with_exposed_ports(8080, 8443)
49-
.with_volume_mapping(keystore_path, "/home/wiremock/keystore.p12", mode="ro")
50-
.with_volume_mapping(
51-
os.path.join(FIXTURES_DIR, "mappings"), "/home/wiremock/mappings", mode="ro"
52-
)
53-
.with_command(
54-
"--https-port 8443"
55-
" --https-keystore /home/wiremock/keystore.p12"
56-
" --keystore-password password"
57-
" --keystore-type PKCS12"
58-
" --global-response-templating"
59-
)
60-
)
61-
cls.wiremock.start()
62-
63-
cls.proxy = (
64-
DockerContainer("ubuntu/squid:6.10-24.10_beta")
65-
.with_network(cls.network)
66-
.with_exposed_ports(3128)
67-
.with_volume_mapping(squid_conf, "/etc/squid/squid.conf", mode="ro")
68-
.waiting_for(PortWaitStrategy(3128))
69-
)
70-
cls.proxy.start()
717

72-
cls.host = cls.wiremock.get_container_host_ip()
73-
cls.http_port = cls.wiremock.get_exposed_port(8080)
74-
cls.https_port = cls.wiremock.get_exposed_port(8443)
75-
cls.proxy_port = cls.proxy.get_exposed_port(3128)
8+
def test_defaults_returns_empty(self) -> None:
9+
self.assertEqual({}, TransportOptions.defaults().to_session_kwargs())
7610

77-
_wait_for_wiremock(cls.host, cls.http_port)
11+
def test_insecure_sets_verify_false(self) -> None:
12+
opts = TransportOptions(insecure=True)
13+
self.assertEqual({"verify": False}, opts.to_session_kwargs())
7814

79-
@classmethod
80-
def teardown_class(cls) -> None:
81-
if cls.proxy is not None:
82-
cls.proxy.stop()
83-
if cls.wiremock is not None:
84-
cls.wiremock.stop()
85-
if cls.network is not None:
86-
cls.network.remove()
87-
88-
def test_custom_ca_cert(self) -> None:
89-
zitadel = Zitadel.with_client_credentials(
90-
f"https://{self.host}:{self.https_port}",
91-
"dummy-client",
92-
"dummy-secret",
93-
transport_options=TransportOptions(ca_cert_path=self.ca_cert_path),
94-
)
95-
self.assertIsNotNone(zitadel)
96-
97-
def test_insecure_mode(self) -> None:
98-
zitadel = Zitadel.with_client_credentials(
99-
f"https://{self.host}:{self.https_port}",
100-
"dummy-client",
101-
"dummy-secret",
102-
transport_options=TransportOptions(insecure=True),
103-
)
104-
self.assertIsNotNone(zitadel)
105-
106-
def test_default_headers(self) -> None:
107-
zitadel = Zitadel.with_client_credentials(
108-
f"http://{self.host}:{self.http_port}",
109-
"dummy-client",
110-
"dummy-secret",
111-
transport_options=TransportOptions(default_headers={"X-Custom-Header": "test-value"}),
112-
)
113-
self.assertIsNotNone(zitadel)
114-
115-
zitadel.settings.get_general_settings({})
116-
117-
verify_body = json.dumps(
118-
{
119-
"url": "/zitadel.settings.v2.SettingsService/GetGeneralSettings",
120-
"headers": {"X-Custom-Header": {"equalTo": "test-value"}},
121-
}
122-
).encode()
123-
req = urllib.request.Request(
124-
f"http://{self.host}:{self.http_port}/__admin/requests/count",
125-
data=verify_body,
126-
headers={"Content-Type": "application/json"},
127-
method="POST",
128-
)
129-
with urllib.request.urlopen(req) as resp: # noqa: S310
130-
result = json.loads(resp.read().decode())
131-
self.assertGreaterEqual(result["count"], 1, "Custom header should be present on API call")
15+
def test_ca_cert_path_sets_verify(self) -> None:
16+
opts = TransportOptions(ca_cert_path="/path/to/ca.pem")
17+
self.assertEqual({"verify": "/path/to/ca.pem"}, opts.to_session_kwargs())
13218

133-
def test_proxy_url(self) -> None:
134-
zitadel = Zitadel.with_access_token(
135-
"http://wiremock:8080",
136-
"test-token",
137-
transport_options=TransportOptions(proxy_url=f"http://{self.host}:{self.proxy_port}"),
19+
def test_proxy_url_sets_proxies(self) -> None:
20+
opts = TransportOptions(proxy_url="http://proxy:3128")
21+
self.assertEqual(
22+
{"proxies": {"http": "http://proxy:3128", "https": "http://proxy:3128"}},
23+
opts.to_session_kwargs(),
13824
)
139-
self.assertIsNotNone(zitadel)
140-
zitadel.settings.get_general_settings({})
14125

142-
def test_no_ca_cert_fails(self) -> None:
143-
with self.assertRaises(Exception): # noqa: B017
144-
Zitadel.with_client_credentials(
145-
f"https://{self.host}:{self.https_port}",
146-
"dummy-client",
147-
"dummy-secret",
148-
)
26+
def test_insecure_takes_precedence_over_ca_cert(self) -> None:
27+
opts = TransportOptions(insecure=True, ca_cert_path="/path/to/ca.pem")
28+
self.assertEqual({"verify": False}, opts.to_session_kwargs())
29+
30+
def test_immutability(self) -> None:
31+
opts = TransportOptions.defaults()
32+
with self.assertRaises(AttributeError):
33+
opts.insecure = True # type: ignore[misc]
34+
35+
def test_defaults_factory(self) -> None:
36+
opts = TransportOptions.defaults()
37+
self.assertEqual({}, dict(opts.default_headers))
38+
self.assertIsNone(opts.ca_cert_path)
39+
self.assertFalse(opts.insecure)
40+
self.assertIsNone(opts.proxy_url)

test/test_zitadel.py

Lines changed: 130 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
import importlib
22
import inspect
3+
import os
34
import pkgutil
45
import unittest
6+
import urllib.request
7+
from typing import Optional
8+
9+
from testcontainers.core.container import DockerContainer
10+
from testcontainers.core.network import Network
11+
from testcontainers.core.wait_strategies import PortWaitStrategy
12+
from testcontainers.core.waiting_utils import wait_container_is_ready
513

614
from zitadel_client.auth.no_auth_authenticator import NoAuthAuthenticator
15+
from zitadel_client.transport_options import TransportOptions
716
from zitadel_client.zitadel import Zitadel
817

18+
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), "fixtures")
19+
20+
21+
@wait_container_is_ready()
22+
def _wait_for_wiremock(host: str, port: str) -> None:
23+
url = f"http://{host}:{port}/__admin/mappings"
24+
with urllib.request.urlopen(url, timeout=5) as resp: # noqa: S310
25+
if resp.status != 200:
26+
raise ConnectionError(f"WireMock not ready: {resp.status}")
27+
928

1029
class ZitadelServicesTest(unittest.TestCase):
11-
"""
12-
Test to verify that all API service classes defined in the "zitadel_client.api" namespace
13-
are registered as attributes in the Zitadel class.
14-
"""
1530

1631
def test_services_dynamic(self) -> None:
1732
expected = set()
@@ -30,3 +45,114 @@ def test_services_dynamic(self) -> None:
3045
and getattr(zitadel, attr).__class__.__module__.startswith("zitadel_client.api")
3146
}
3247
self.assertEqual(expected, actual)
48+
49+
50+
class ZitadelTransportTest(unittest.TestCase):
51+
host: Optional[str] = None
52+
http_port: Optional[str] = None
53+
https_port: Optional[str] = None
54+
proxy_port: Optional[str] = None
55+
ca_cert_path: Optional[str] = None
56+
wiremock: DockerContainer = None
57+
proxy: DockerContainer = None
58+
network: Network = None
59+
60+
@classmethod
61+
def setup_class(cls) -> None:
62+
cls.ca_cert_path = os.path.join(FIXTURES_DIR, "ca.pem")
63+
keystore_path = os.path.join(FIXTURES_DIR, "keystore.p12")
64+
squid_conf = os.path.join(FIXTURES_DIR, "squid.conf")
65+
66+
cls.network = Network().create()
67+
68+
cls.wiremock = (
69+
DockerContainer("wiremock/wiremock:3.12.1")
70+
.with_network(cls.network)
71+
.with_network_aliases("wiremock")
72+
.with_exposed_ports(8080, 8443)
73+
.with_volume_mapping(keystore_path, "/home/wiremock/keystore.p12", mode="ro")
74+
.with_volume_mapping(
75+
os.path.join(FIXTURES_DIR, "mappings"), "/home/wiremock/mappings", mode="ro"
76+
)
77+
.with_command(
78+
"--https-port 8443"
79+
" --https-keystore /home/wiremock/keystore.p12"
80+
" --keystore-password password"
81+
" --keystore-type PKCS12"
82+
" --global-response-templating"
83+
)
84+
)
85+
cls.wiremock.start()
86+
87+
cls.proxy = (
88+
DockerContainer("ubuntu/squid:6.10-24.10_beta")
89+
.with_network(cls.network)
90+
.with_exposed_ports(3128)
91+
.with_volume_mapping(squid_conf, "/etc/squid/squid.conf", mode="ro")
92+
.waiting_for(PortWaitStrategy(3128))
93+
)
94+
cls.proxy.start()
95+
96+
cls.host = cls.wiremock.get_container_host_ip()
97+
cls.http_port = cls.wiremock.get_exposed_port(8080)
98+
cls.https_port = cls.wiremock.get_exposed_port(8443)
99+
cls.proxy_port = cls.proxy.get_exposed_port(3128)
100+
101+
_wait_for_wiremock(cls.host, cls.http_port)
102+
103+
@classmethod
104+
def teardown_class(cls) -> None:
105+
if cls.proxy is not None:
106+
cls.proxy.stop()
107+
if cls.wiremock is not None:
108+
cls.wiremock.stop()
109+
if cls.network is not None:
110+
cls.network.remove()
111+
112+
def test_custom_ca_cert(self) -> None:
113+
zitadel = Zitadel.with_client_credentials(
114+
f"https://{self.host}:{self.https_port}",
115+
"dummy-client",
116+
"dummy-secret",
117+
transport_options=TransportOptions(ca_cert_path=self.ca_cert_path),
118+
)
119+
response = zitadel.settings.get_general_settings({})
120+
self.assertEqual("https", response.default_language)
121+
122+
def test_insecure_mode(self) -> None:
123+
zitadel = Zitadel.with_client_credentials(
124+
f"https://{self.host}:{self.https_port}",
125+
"dummy-client",
126+
"dummy-secret",
127+
transport_options=TransportOptions(insecure=True),
128+
)
129+
response = zitadel.settings.get_general_settings({})
130+
self.assertEqual("https", response.default_language)
131+
132+
def test_default_headers(self) -> None:
133+
zitadel = Zitadel.with_client_credentials(
134+
f"http://{self.host}:{self.http_port}",
135+
"dummy-client",
136+
"dummy-secret",
137+
transport_options=TransportOptions(default_headers={"X-Custom-Header": "test-value"}),
138+
)
139+
response = zitadel.settings.get_general_settings({})
140+
self.assertEqual("http", response.default_language)
141+
self.assertEqual("test-value", response.default_org_id)
142+
143+
def test_proxy_url(self) -> None:
144+
zitadel = Zitadel.with_access_token(
145+
"http://wiremock:8080",
146+
"test-token",
147+
transport_options=TransportOptions(proxy_url=f"http://{self.host}:{self.proxy_port}"),
148+
)
149+
response = zitadel.settings.get_general_settings({})
150+
self.assertEqual("http", response.default_language)
151+
152+
def test_no_ca_cert_fails(self) -> None:
153+
with self.assertRaises(Exception): # noqa: B017
154+
Zitadel.with_client_credentials(
155+
f"https://{self.host}:{self.https_port}",
156+
"dummy-client",
157+
"dummy-secret",
158+
)

0 commit comments

Comments
 (0)