|
1 | 1 | import typing |
2 | 2 |
|
3 | 3 | import pytest |
4 | | -from pytest_bdd import given, parsers, then, when |
5 | | -from tests.e2e.parsers import to_bool |
| 4 | +from testcontainers.core.container import DockerContainer |
| 5 | +from tests.e2e.flagd_container import FlagDContainer |
| 6 | +from tests.e2e.steps import * # noqa: F403 |
6 | 7 |
|
7 | 8 | from openfeature import api |
8 | | -from openfeature.client import OpenFeatureClient |
9 | 9 | from openfeature.contrib.provider.flagd import FlagdProvider |
10 | | -from openfeature.contrib.provider.flagd.config import ResolverType |
11 | | -from openfeature.evaluation_context import EvaluationContext |
12 | 10 |
|
13 | 11 | JsonPrimitive = typing.Union[str, bool, float, int] |
14 | 12 |
|
15 | 13 |
|
16 | | -@pytest.fixture |
17 | | -def evaluation_context() -> EvaluationContext: |
18 | | - return EvaluationContext() |
19 | | - |
20 | | - |
21 | | -@given("a flagd provider is set", target_fixture="client") |
22 | | -def setup_provider(flag_file) -> OpenFeatureClient: |
| 14 | +@pytest.fixture(autouse=True, scope="package") |
| 15 | +def setup(request, port, image, resolver_type): |
| 16 | + container: DockerContainer = FlagDContainer( |
| 17 | + image=image, |
| 18 | + port=port, |
| 19 | + ) |
| 20 | + # Setup code |
| 21 | + c = container.start() |
23 | 22 | api.set_provider( |
24 | 23 | FlagdProvider( |
25 | | - resolver_type=ResolverType.IN_PROCESS, |
26 | | - offline_flag_source_path=flag_file, |
27 | | - offline_poll_interval_seconds=0.1, |
| 24 | + resolver_type=resolver_type, |
| 25 | + port=int(container.get_exposed_port(port)), |
28 | 26 | ) |
29 | 27 | ) |
30 | | - return api.get_client() |
31 | | - |
32 | | - |
33 | | -@when( |
34 | | - parsers.cfparse( |
35 | | - 'a zero-value boolean flag with key "{key}" is evaluated with default value "{default:bool}"', |
36 | | - extra_types={"bool": to_bool}, |
37 | | - ), |
38 | | - target_fixture="key_and_default", |
39 | | -) |
40 | | -@when( |
41 | | - parsers.cfparse( |
42 | | - 'a zero-value string flag with key "{key}" is evaluated with default value "{default}"', |
43 | | - ), |
44 | | - target_fixture="key_and_default", |
45 | | -) |
46 | | -@when( |
47 | | - parsers.cfparse( |
48 | | - 'a string flag with key "{key}" is evaluated with default value "{default}"' |
49 | | - ), |
50 | | - target_fixture="key_and_default", |
51 | | -) |
52 | | -@when( |
53 | | - parsers.cfparse( |
54 | | - 'a zero-value integer flag with key "{key}" is evaluated with default value {default:d}', |
55 | | - ), |
56 | | - target_fixture="key_and_default", |
57 | | -) |
58 | | -@when( |
59 | | - parsers.cfparse( |
60 | | - 'an integer flag with key "{key}" is evaluated with default value {default:d}', |
61 | | - ), |
62 | | - target_fixture="key_and_default", |
63 | | -) |
64 | | -@when( |
65 | | - parsers.cfparse( |
66 | | - 'a zero-value float flag with key "{key}" is evaluated with default value {default:f}', |
67 | | - ), |
68 | | - target_fixture="key_and_default", |
69 | | -) |
70 | | -def setup_key_and_default( |
71 | | - key: str, default: JsonPrimitive |
72 | | -) -> typing.Tuple[str, JsonPrimitive]: |
73 | | - return (key, default) |
74 | | - |
75 | | - |
76 | | -@when( |
77 | | - parsers.cfparse( |
78 | | - 'a context containing a targeting key with value "{targeting_key}"' |
79 | | - ), |
80 | | -) |
81 | | -def assign_targeting_context(evaluation_context: EvaluationContext, targeting_key: str): |
82 | | - """a context containing a targeting key with value <targeting key>.""" |
83 | | - evaluation_context.targeting_key = targeting_key |
84 | | - |
85 | | - |
86 | | -@when( |
87 | | - parsers.cfparse('a context containing a key "{key}", with value "{value}"'), |
88 | | -) |
89 | | -@when( |
90 | | - parsers.cfparse('a context containing a key "{key}", with value {value:d}'), |
91 | | -) |
92 | | -def update_context( |
93 | | - evaluation_context: EvaluationContext, key: str, value: JsonPrimitive |
94 | | -): |
95 | | - """a context containing a key and value.""" |
96 | | - evaluation_context.attributes[key] = value |
97 | | - |
98 | | - |
99 | | -@when( |
100 | | - parsers.cfparse( |
101 | | - 'a context containing a nested property with outer key "{outer}" and inner key "{inner}", with value "{value}"' |
102 | | - ), |
103 | | -) |
104 | | -@when( |
105 | | - parsers.cfparse( |
106 | | - 'a context containing a nested property with outer key "{outer}" and inner key "{inner}", with value {value:d}' |
107 | | - ), |
108 | | -) |
109 | | -def update_context_nested( |
110 | | - evaluation_context: EvaluationContext, |
111 | | - outer: str, |
112 | | - inner: str, |
113 | | - value: typing.Union[str, int], |
114 | | -): |
115 | | - """a context containing a nested property with outer key, and inner key, and value.""" |
116 | | - if outer not in evaluation_context.attributes: |
117 | | - evaluation_context.attributes[outer] = {} |
118 | | - evaluation_context.attributes[outer][inner] = value |
119 | | - |
120 | | - |
121 | | -@then( |
122 | | - parsers.cfparse( |
123 | | - 'the resolved boolean zero-value should be "{expected_value:bool}"', |
124 | | - extra_types={"bool": to_bool}, |
125 | | - ) |
126 | | -) |
127 | | -def assert_boolean_value( |
128 | | - client: OpenFeatureClient, |
129 | | - key_and_default: tuple, |
130 | | - expected_value: bool, |
131 | | - evaluation_context: EvaluationContext, |
132 | | -): |
133 | | - key, default = key_and_default |
134 | | - evaluation_result = client.get_boolean_value(key, default, evaluation_context) |
135 | | - assert evaluation_result == expected_value |
136 | | - |
137 | | - |
138 | | -@then( |
139 | | - parsers.cfparse( |
140 | | - "the resolved integer zero-value should be {expected_value:d}", |
141 | | - ) |
142 | | -) |
143 | | -@then(parsers.cfparse("the returned value should be {expected_value:d}")) |
144 | | -def assert_integer_value( |
145 | | - client: OpenFeatureClient, |
146 | | - key_and_default: tuple, |
147 | | - expected_value: bool, |
148 | | - evaluation_context: EvaluationContext, |
149 | | -): |
150 | | - key, default = key_and_default |
151 | | - evaluation_result = client.get_integer_value(key, default, evaluation_context) |
152 | | - assert evaluation_result == expected_value |
153 | | - |
154 | | - |
155 | | -@then( |
156 | | - parsers.cfparse( |
157 | | - "the resolved float zero-value should be {expected_value:f}", |
158 | | - ) |
159 | | -) |
160 | | -def assert_float_value( |
161 | | - client: OpenFeatureClient, |
162 | | - key_and_default: tuple, |
163 | | - expected_value: bool, |
164 | | - evaluation_context: EvaluationContext, |
165 | | -): |
166 | | - key, default = key_and_default |
167 | | - evaluation_result = client.get_float_value(key, default, evaluation_context) |
168 | | - assert evaluation_result == expected_value |
169 | | - |
170 | | - |
171 | | -@then(parsers.cfparse('the returned value should be "{expected_value}"')) |
172 | | -def assert_string_value( |
173 | | - client: OpenFeatureClient, |
174 | | - key_and_default: tuple, |
175 | | - expected_value: bool, |
176 | | - evaluation_context: EvaluationContext, |
177 | | -): |
178 | | - key, default = key_and_default |
179 | | - evaluation_result = client.get_string_value(key, default, evaluation_context) |
180 | | - assert evaluation_result == expected_value |
181 | | - |
182 | | - |
183 | | -@then( |
184 | | - parsers.cfparse( |
185 | | - 'the resolved string zero-value should be ""', |
186 | | - ) |
187 | | -) |
188 | | -def assert_empty_string( |
189 | | - client: OpenFeatureClient, |
190 | | - key_and_default: tuple, |
191 | | - evaluation_context: EvaluationContext, |
192 | | -): |
193 | | - key, default = key_and_default |
194 | | - evaluation_result = client.get_string_value(key, default, evaluation_context) |
195 | | - assert evaluation_result == "" |
196 | 28 |
|
| 29 | + def fin(): |
| 30 | + c.stop() |
197 | 31 |
|
198 | | -@then(parsers.cfparse('the returned reason should be "{reason}"')) |
199 | | -def assert_reason( |
200 | | - client: OpenFeatureClient, |
201 | | - key_and_default: tuple, |
202 | | - evaluation_context: EvaluationContext, |
203 | | - reason: str, |
204 | | -): |
205 | | - """the returned reason should be <reason>.""" |
206 | | - key, default = key_and_default |
207 | | - evaluation_result = client.get_string_details(key, default, evaluation_context) |
208 | | - assert evaluation_result.reason.value == reason |
| 32 | + # Teardown code |
| 33 | + request.addfinalizer(fin) |
0 commit comments