Skip to content

Commit 3ec2d22

Browse files
committed
[client-python] Adding and Updating multi-tenant tests
1 parent 81073c2 commit 3ec2d22

9 files changed

Lines changed: 474 additions & 152 deletions
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Feature: Tenant ID handling in OpenAEV configuration
2+
3+
Scenario: tenant_id is not provided
4+
Given a configuration without tenant_id
5+
When the configuration is loaded
6+
Then tenant_id should be None
7+
8+
9+
Scenario: tenant_id is explicitly set to None
10+
Given a configuration with tenant_id set to None
11+
When the configuration is loaded
12+
Then tenant_id should be None
13+
14+
15+
Scenario Outline: tenant_id is invalid and should raise a validation error
16+
Given a configuration with tenant_id "<tenant_id>" invalid
17+
When the configuration is loaded
18+
Then a validation error should be raised
19+
20+
Examples:
21+
| tenant_id |
22+
| ChangeMe |
23+
| "" |
24+
| 550-e29-41d-a71-446 |
25+
26+
27+
Scenario: tenant_id is a valid UUID
28+
Given a configuration with tenant_id "2cffad3a-0001-4078-b0e2-ef74274022c3"
29+
When the configuration is loaded
30+
Then tenant_id should be a valid UUID
Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,63 @@
1+
"""URL normalization in OpenAEV client feature tests."""
2+
13
import pytest
4+
from pytest_bdd import given, parsers, scenario, then, when
25

36
from pyoaev import OpenAEV
47

8+
# --------------------------------------------------
9+
# SCENARIOS
10+
# --------------------------------------------------
11+
512

6-
@pytest.mark.parametrize(
7-
"base_url, input_path, expected",
8-
[
9-
(
10-
"base_url",
11-
"path",
12-
"base_url/api/path",
13-
),
14-
(
15-
"base_url/",
16-
"/path",
17-
"base_url/api/path",
18-
),
19-
(
20-
"base_url//",
21-
"//path",
22-
"base_url/api/path",
23-
),
24-
],
25-
ids=[
26-
"clean-base-url-and-relative-path",
27-
"base-url-trailing-slash",
28-
"base-url-double-slash-and-path-double-slash",
29-
],
13+
@scenario(
14+
"multi_tenant_api_routing_constraint.feature",
15+
"URL normalization combines base_url and path correctly",
3016
)
31-
def test_url_normalization(base_url, input_path, expected):
32-
client = OpenAEV(
17+
def test_url_normalization():
18+
pass
19+
20+
21+
# --------------------------------------------------
22+
# FIXTURE CONTEXT
23+
# --------------------------------------------------
24+
25+
26+
@pytest.fixture
27+
def context():
28+
return {}
29+
30+
31+
# --------------------------------------------------
32+
# GIVEN
33+
# --------------------------------------------------
34+
35+
36+
@given(parsers.parse('an OpenAEV client with base_url "{base_url}"'))
37+
def client(context, base_url):
38+
context["client"] = OpenAEV(
3339
url=base_url,
3440
token="token",
3541
tenant_id=None,
3642
)
37-
result = client._build_url(input_path)
38-
assert result == expected
43+
44+
45+
# --------------------------------------------------
46+
# WHEN
47+
# --------------------------------------------------
48+
49+
50+
@when(parsers.parse('I build the URL for "{path}"'))
51+
def build_url(context, path):
52+
client = context["client"]
53+
context["result"] = client._build_url(path)
54+
55+
56+
# --------------------------------------------------
57+
# THEN
58+
# --------------------------------------------------
59+
60+
61+
@then(parsers.parse('the resulting URL should be "{expected}"'))
62+
def check_url(context, expected):
63+
assert context["result"] == expected
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""Tenant ID handling in OpenAEV configuration feature tests."""
2+
3+
from uuid import UUID
4+
5+
import pytest
6+
from pydantic import ValidationError
7+
from pytest_bdd import given, parsers, scenario, then, when
8+
9+
from pyoaev.configuration.settings_loader import ConfigLoaderOAEV
10+
11+
# --------------------------------------------------
12+
# SCENARIOS
13+
# --------------------------------------------------
14+
15+
16+
@scenario(
17+
"multi_tenant_validation_uuid_constraint.feature",
18+
"tenant_id is a valid UUID",
19+
)
20+
def test_tenant_id_is_a_valid_uuid():
21+
pass
22+
23+
24+
@scenario(
25+
"multi_tenant_validation_uuid_constraint.feature",
26+
"tenant_id is explicitly set to None",
27+
)
28+
def test_tenant_id_is_explicitly_set_to_none():
29+
pass
30+
31+
32+
@scenario(
33+
"multi_tenant_validation_uuid_constraint.feature",
34+
"tenant_id is invalid and should raise a validation error",
35+
)
36+
def test_tenant_id_is_invalid_and_should_raise_a_validation_error():
37+
pass
38+
39+
40+
@scenario(
41+
"multi_tenant_validation_uuid_constraint.feature",
42+
"tenant_id is not provided",
43+
)
44+
def test_tenant_id_is_not_provided():
45+
pass
46+
47+
48+
# --------------------------------------------------
49+
# GIVEN
50+
# --------------------------------------------------
51+
52+
53+
@given(
54+
"a configuration without tenant_id",
55+
target_fixture="config",
56+
)
57+
def config_without():
58+
return {
59+
"url": "https://example.com",
60+
"token": "token",
61+
}
62+
63+
64+
@given(
65+
"a configuration with tenant_id set to None",
66+
target_fixture="config",
67+
)
68+
def config_none():
69+
return {
70+
"url": "https://example.com",
71+
"token": "token",
72+
"tenant_id": None,
73+
}
74+
75+
76+
@given(
77+
parsers.parse('a configuration with tenant_id "{tenant_id}" invalid'),
78+
target_fixture="config",
79+
)
80+
def config_with_tenant_invalid(tenant_id):
81+
return {
82+
"url": "https://example.com",
83+
"token": "token",
84+
"tenant_id": tenant_id,
85+
}
86+
87+
88+
@given(
89+
'a configuration with tenant_id "2cffad3a-0001-4078-b0e2-ef74274022c3"',
90+
target_fixture="config",
91+
)
92+
def config_with_tenant_valid():
93+
return {
94+
"url": "https://example.com",
95+
"token": "token",
96+
"tenant_id": "2cffad3a-0001-4078-b0e2-ef74274022c3",
97+
}
98+
99+
100+
# --------------------------------------------------
101+
# WHEN
102+
# --------------------------------------------------
103+
104+
105+
@when(
106+
"the configuration is loaded",
107+
target_fixture="result",
108+
)
109+
def load_config(config):
110+
try:
111+
return ConfigLoaderOAEV(**config)
112+
except ValidationError as err:
113+
return err
114+
115+
116+
# --------------------------------------------------
117+
# THEN
118+
# --------------------------------------------------
119+
120+
121+
@then("tenant_id should be None")
122+
def assert_none(result):
123+
assert result.tenant_id is None
124+
125+
126+
@then("tenant_id should be a valid UUID")
127+
def assert_uuid(result):
128+
assert isinstance(result.tenant_id, UUID)
129+
130+
131+
@then("a validation error should be raised")
132+
def assert_validation_error(result):
133+
assert isinstance(result, ValidationError)
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
Feature: Multi-tenant API routing in OpenAEV client
22

33
Scenario: Full URL bypasses tenant routing
4-
Given an OpenAEV client with tenant_id "2cffad3a-0001-4078-b0e2-ef74274022c3"
4+
Given an OpenAEV client with any tenant configuration
55
When I build the URL for "https://external.service/api/path"
66
Then the resulting URL should be "https://external.service/api/path"
77

8-
Scenario Outline: Relative path routing behavior
8+
9+
Scenario Outline: Relative path routing depends on tenant configuration
910
Given an OpenAEV client with tenant_id "<tenant_id>"
1011
When I build the URL for "/path"
1112
Then the resulting URL should be "<output>"
1213

1314
Examples:
14-
| tenant_id | output |
15-
| None | base_url/api/path |
16-
| 2cffad3a-0001-4078-b0e2-ef74274022c3 | base_url/api/tenants/2cffad3a-0001-4078-b0e2-ef74274022c3/path |
17-
15+
| tenant_id | output |
16+
| None | base_url/api/path |
17+
| 2cffad3a-0001-4078-b0e2-ef74274022c3 | base_url/api/tenants/2cffad3a-0001-4078-b0e2-ef74274022c3/path |
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
Feature: Tenant propagation in BaseDaemon API client initialization
22

33
Scenario Outline: BaseDaemon propagates tenant_id correctly from configuration
4-
Given a daemon configuration with <tenant_id>
4+
Given a daemon configuration with "<tenant_case>"
55
When the BaseDaemon is initialized
66
Then the API client should be created with tenant_id "<expected_tenant_id>"
77

88
Examples:
9-
| tenant_id | expected_tenant_id |
10-
| Missing tenant key | None |
11-
| None | None |
12-
| 2cffad3a-0001-4078-b0e2-ef74274022c3 | 2cffad3a-0001-4078-b0e2-ef74274022c3 |
9+
| tenant_case | expected_tenant_id |
10+
| missing_key | None |
11+
| explicit_none | None |
12+
| valid_uuid | 2cffad3a-0001-4078-b0e2-ef74274022c3 |

test/bdd/features/multi_tenant_endpoint_search_targets.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ Feature: searchTargets API routing with and without tenant_id
77
Then the request URL should be "<expected_url>"
88

99
Examples:
10-
| tenant_id | expected_url |
11-
| None | url/api/endpoints/targets |
10+
| tenant_id | expected_url |
11+
| None | url/api/endpoints/targets |
1212
| 2cffad3a-0001-4078-b0e2-ef74274022c3 | url/api/tenants/2cffad3a-0001-4078-b0e2-ef74274022c3/endpoints/targets |

0 commit comments

Comments
 (0)