Skip to content

Commit 53e058f

Browse files
committed
adding http_matcher.feature v3 compatibility test
1 parent 47143aa commit 53e058f

File tree

2 files changed

+192
-1
lines changed

2 files changed

+192
-1
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
"""Matching HTTP parts (request or response) feature tests."""
2+
3+
import pickle
4+
import re
5+
from pathlib import Path
6+
7+
import pytest
8+
from pytest_bdd import (
9+
given,
10+
parsers,
11+
scenario,
12+
then,
13+
when,
14+
)
15+
from yarl import URL
16+
17+
from pact.v3 import Pact
18+
from pact.v3.verifier import Verifier
19+
from tests.v3.compatibility_suite.util.interaction_definition import (
20+
InteractionDefinition,
21+
)
22+
from tests.v3.compatibility_suite.util.provider import start_provider
23+
24+
################################################################################
25+
## Scenarios
26+
################################################################################
27+
28+
29+
# tests/v3/compatibility_suite/definition/features/V3/
30+
@scenario(
31+
"definition/features/V3/http_matching.feature",
32+
"Comparing accept headers where the actual has additional parameters",
33+
)
34+
def test_comparing_accept_headers_where_the_actual_has_additional_parameters() -> None:
35+
"""Comparing accept headers where the actual has additional parameters."""
36+
37+
38+
@scenario(
39+
"definition/features/V3/http_matching.feature",
40+
"Comparing accept headers where the actual has is missing a value",
41+
)
42+
def test_comparing_accept_headers_where_the_actual_has_is_missing_a_value() -> None:
43+
"""Comparing accept headers where the actual has is missing a value."""
44+
45+
46+
@scenario(
47+
"definition/features/V3/http_matching.feature",
48+
"Comparing content type headers where the actual has a charset",
49+
)
50+
def test_comparing_content_type_headers_where_the_actual_has_a_charset() -> None:
51+
"""Comparing content type headers where the actual has a charset."""
52+
53+
54+
@scenario(
55+
"definition/features/V3/http_matching.feature",
56+
"Comparing content type headers where the actual has a different charset",
57+
)
58+
def test_comparing_content_type_headers_where_the_actual_has_a_different_charset() -> (
59+
None
60+
):
61+
"""Comparing content type headers where the actual has a different charset."""
62+
63+
64+
@scenario(
65+
"definition/features/V3/http_matching.feature",
66+
"Comparing content type headers where the actual is missing a charset",
67+
)
68+
def test_comparing_content_type_headers_where_the_actual_is_missing_a_charset() -> None:
69+
"""Comparing content type headers where the actual is missing a charset."""
70+
71+
72+
@scenario(
73+
"definition/features/V3/http_matching.feature",
74+
"Comparing content type headers where they have the same charset",
75+
)
76+
def test_comparing_content_type_headers_where_they_have_the_same_charset() -> None:
77+
"""Comparing content type headers where they have the same charset."""
78+
79+
80+
@scenario(
81+
"definition/features/V3/http_matching.feature",
82+
"Comparing content type headers which are equal",
83+
)
84+
def test_comparing_content_type_headers_which_are_equal() -> None:
85+
"""Comparing content type headers which are equal."""
86+
87+
88+
################################################################################
89+
## Given
90+
################################################################################
91+
92+
93+
@given(
94+
parsers.re(
95+
r'a request is received with an? "(?P<name>[^"]+)" header of "(?P<value>[^"]+)"'
96+
)
97+
)
98+
def a_request_is_received_with_header(name: str, value: str, temp_dir: Path) -> None:
99+
"""A request is received with a "content-type" header of "application/json"."""
100+
interaction_definition = InteractionDefinition(method="GET", path="/", type="HTTP")
101+
interaction_definition.response_headers.update({name: value})
102+
with (temp_dir / "interactions.pkl").open("wb") as pkl_file:
103+
pickle.dump([interaction_definition], pkl_file)
104+
105+
106+
@given(
107+
parsers.re(
108+
r'an expected request with an? "(?P<name>[^"]+)" header of "(?P<value>[^"]+)"'
109+
),
110+
)
111+
def an_expected_request_with_header(name: str, value: str, temp_dir: Path) -> None:
112+
"""An expected request with a "content-type" header of "application/json"."""
113+
pact = Pact("consumer", "provider")
114+
pact.with_specification("V3")
115+
interaction_definition = InteractionDefinition(method="GET", path="/", type="HTTP")
116+
interaction_definition.response_headers.update({name: value})
117+
interaction_definition.add_to_pact(pact, name)
118+
(temp_dir / "pacts").mkdir(exist_ok=True, parents=True)
119+
pact.write_file(temp_dir / "pacts")
120+
121+
122+
################################################################################
123+
## When
124+
################################################################################
125+
126+
127+
@when("the request is compared to the expected one", target_fixture="provider_url")
128+
def the_request_is_compared_to_the_expected_one(temp_dir: Path) -> None:
129+
"""The request is compared to the expected one."""
130+
yield from start_provider(temp_dir)
131+
132+
133+
################################################################################
134+
## Then
135+
################################################################################
136+
137+
138+
@then(
139+
parsers.re("the comparison should(?P<negated>( NOT)?) be OK"),
140+
converters={"negated": lambda x: x == " NOT"},
141+
target_fixture="verifier_result",
142+
)
143+
def the_comparison_should_not_be_ok(
144+
provider_url: URL,
145+
verifier: Verifier,
146+
temp_dir: Path,
147+
negated: bool, # noqa: FBT001
148+
) -> Verifier:
149+
"""The comparison should NOT be OK."""
150+
verifier.set_info("provider", url=provider_url)
151+
verifier.add_transport(
152+
protocol="http",
153+
port=provider_url.port,
154+
path="/",
155+
)
156+
verifier.add_source(temp_dir / "pacts")
157+
if negated:
158+
with pytest.raises(RuntimeError):
159+
verifier.verify()
160+
else:
161+
verifier.verify()
162+
return verifier
163+
164+
165+
@then(
166+
parsers.parse(
167+
'the mismatches will contain a mismatch with error "{mismatch_key}" '
168+
"-> \"Expected header '{header_name}' to have value '{expected_value}'"
169+
"but was '{actual_value}'\""
170+
)
171+
)
172+
def the_mismatches_will_contain_a_mismatch_with_error(
173+
verifier_result: Verifier,
174+
mismatch_key: str,
175+
header_name: str,
176+
expected_value: str,
177+
actual_value: str,
178+
) -> None:
179+
"""Mismatches will contain a mismatch with error."""
180+
expected_value_matcher = re.compile(expected_value)
181+
actual_value_matcher = re.compile(actual_value)
182+
expected_error_matcher = re.compile(
183+
rf"Mismatch with header \'{mismatch_key}\': Expected header \'{header_name}\' "
184+
rf"to have value \'{expected_value}\' but was \'{actual_value}\'"
185+
)
186+
mismatch = verifier_result.results["errors"][0]["mismatch"]["mismatches"][0]
187+
assert mismatch["key"] == mismatch_key
188+
assert mismatch["type"] == "HeaderMismatch"
189+
assert expected_value_matcher.match(mismatch["expected"]) is not None
190+
assert actual_value_matcher.match(mismatch["actual"]) is not None
191+
assert expected_error_matcher.match(mismatch["mismatch"]) is not None

tests/v3/compatibility_suite/util/interaction_definition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ def add_to_pact( # noqa: C901, PLR0912, PLR0915
576576
interaction, HttpInteraction
577577
), "Response headers require an HTTP interaction"
578578
logger.info("with_headers(%r)", self.response_headers)
579-
interaction.with_headers(self.response_headers.items())
579+
interaction.with_headers(self.response_headers.items(), "Response")
580580

581581
if self.response_body:
582582
assert isinstance(

0 commit comments

Comments
 (0)