77import pickle
88import re
99from pathlib import Path
10- from typing import TYPE_CHECKING
10+ from typing import TYPE_CHECKING , Generator
1111
1212import pytest
1313from pytest_bdd import (
2424)
2525from tests .v3 .compatibility_suite .util .provider import (
2626 a_provider_is_started_that_can_generate_the_message ,
27+ a_provider_state_callback_is_configured ,
28+ start_provider ,
2729 the_provider_state_callback_will_be_called_after_the_verification_is_run ,
2830 the_provider_state_callback_will_be_called_before_the_verification_is_run ,
2931 the_provider_state_callback_will_receive_a_setup_call ,
30- the_verification_is_run_with_start_context ,
32+ the_verification_is_run ,
3133 the_verification_results_will_contain_a_error ,
3234 the_verification_will_be_successful ,
3335)
3436
3537if TYPE_CHECKING :
38+ from yarl import URL
39+
3640 from pact .v3 .verifier import Verifier
3741
3842TEST_PACT_FILE_DIRECTORY = Path (Path (__file__ ).parent / "pacts" )
@@ -191,6 +195,7 @@ def test_verifying_multiple_pact_files() -> None:
191195
192196
193197a_provider_is_started_that_can_generate_the_message ()
198+ a_provider_state_callback_is_configured ()
194199
195200
196201@given (
@@ -205,57 +210,63 @@ def a_pact_file_for_is_to_be_verified_with_the_following(
205210 verifier : Verifier ,
206211 temp_dir : Path ,
207212 name : str ,
208- table : dict [str , str ],
213+ table : dict [str , str | dict [ str , str ] ],
209214) -> None :
210- """A Pact file for "basic" is to be verified with the following."""
211- metadata = {}
212- if table .get ("metadata" ):
213-
214- def _repl (x : str ) -> tuple [str , str ]:
215- return (z .replace ("JSON: " , "" ) for z in x .split ("=" ))
216-
217- metadata = dict (_repl (x ) for x in table ["metadata" ].split ("; " ))
215+ """
216+ A Pact file for "basic" is to be verified with the following.
217+ """
218218 pact = Pact ("consumer" , "provider" )
219219 pact .with_specification ("V3" )
220+
221+ if "metadata" in table :
222+ assert isinstance (table ["metadata" ], str )
223+ metadata = {
224+ k : json .loads (v .replace ("JSON: " , "" )) if v .startswith ("JSON: " ) else v
225+ for k , _ , v in (s .partition ("=" ) for s in table ["metadata" ].split ("; " ))
226+ }
227+ table ["metadata" ] = metadata
228+
220229 interaction_definition = InteractionDefinition (
221- method = "POST" ,
222- path = f"/{ name } " ,
223- metadata = metadata ,
224- response_body = table ["body" ],
225- matching_rules = table .get ("matching rules" ),
226230 type = "Async" ,
231+ description = name ,
232+ ** table ,
227233 )
228234 interaction_definition .add_to_pact (pact , name )
229235 (temp_dir / "pacts" ).mkdir (exist_ok = True , parents = True )
230236 pact .write_file (temp_dir / "pacts" )
231237 verifier .add_source (temp_dir / "pacts" )
232238
233239
234- @given (parsers .parse ('a Pact file for "{name}":"{fixture}" is to be verified' ))
240+ @given (
241+ parsers .re (
242+ r'a Pact file for "(?P<name>[^"]+)":"(?P<fixture>[^"]+)" is to be verified'
243+ )
244+ )
235245def a_pact_file_for_is_to_be_verified (
236- verifier : Verifier , temp_dir : Path , name : str , fixture : str
246+ verifier : Verifier ,
247+ temp_dir : Path ,
248+ name : str ,
249+ fixture : str ,
237250) -> None :
238251 pact = Pact ("consumer" , "provider" )
239252 pact .with_specification ("V3" )
240253 interaction_definition = InteractionDefinition (
241- method = "POST" ,
242- path = f"/{ name } " ,
243- response_body = fixture ,
244254 type = "Async" ,
255+ description = name ,
256+ body = fixture ,
245257 )
246- # for plain text message, the mime type needs to be set
247- if not re .match (r"^(file:|JSON:)" , fixture ):
248- interaction_definition .response_body .mime_type = "text/html;charset=utf-8"
249258 interaction_definition .add_to_pact (pact , name )
250259 (temp_dir / "pacts" ).mkdir (exist_ok = True , parents = True )
251260 pact .write_file (temp_dir / "pacts" )
261+ with (temp_dir / "pacts" / "consumer-provider.json" ).open () as f :
262+ logger .debug ("Pact file contents: %s" , f .read ())
252263 verifier .add_source (temp_dir / "pacts" )
253264
254265
255266@given (
256- parsers .parse (
257- 'a Pact file for "{ name}":"{ fixture}" is to be '
258- ' verified with provider state "{ provider_state} "'
267+ parsers .re (
268+ r 'a Pact file for "(?P< name>[^"]+)":"(?P< fixture>[^"]+)" '
269+ r' is to be verified with provider state "(?P< provider_state>[^"]+) "'
259270 )
260271)
261272def a_pact_file_for_is_to_be_verified_with_provider_state (
@@ -269,13 +280,11 @@ def a_pact_file_for_is_to_be_verified_with_provider_state(
269280 pact = Pact ("consumer" , "provider" )
270281 pact .with_specification ("V3" )
271282 interaction_definition = InteractionDefinition (
272- method = "POST" ,
273- path = f"/{ name } " ,
274- response_body = fixture ,
275283 type = "Async" ,
284+ description = name ,
285+ body = fixture ,
276286 )
277- states = [InteractionDefinition .State (provider_state )]
278- interaction_definition .states = states
287+ interaction_definition .states = [InteractionDefinition .State (provider_state )]
279288 interaction_definition .add_to_pact (pact , name )
280289 (temp_dir / "pacts" ).mkdir (exist_ok = True , parents = True )
281290 pact .write_file (temp_dir / "pacts" )
@@ -301,17 +310,21 @@ def a_pact_file_for_is_to_be_verified_with_the_following_metadata(
301310 verifier : Verifier ,
302311 name : str ,
303312 fixture : str ,
304- metadata : dict [str , str ],
313+ metadata : list [ dict [str , str ] ],
305314) -> None :
306315 """A Pact file is to be verified with the following metadata."""
307316 pact = Pact ("consumer" , "provider" )
308317 pact .with_specification ("V3" )
309318 interaction_definition = InteractionDefinition (
310- method = "POST" ,
311- path = f"/{ name } " ,
312- metadata = {h ["key" ]: h ["value" ].replace ("JSON: " , "" ) for h in metadata },
313- response_body = fixture ,
314319 type = "Async" ,
320+ description = name ,
321+ body = fixture ,
322+ metadata = {
323+ row ["key" ]: json .loads (row ["value" ].replace ("JSON: " , "" ))
324+ if row ["value" ].startswith ("JSON: " )
325+ else row ["value" ]
326+ for row in metadata
327+ },
315328 )
316329 interaction_definition .add_to_pact (pact , name )
317330 (temp_dir / "pacts" ).mkdir (exist_ok = True , parents = True )
@@ -327,49 +340,45 @@ def a_pact_file_for_is_to_be_verified_with_the_following_metadata(
327340 re .DOTALL ,
328341 ),
329342 converters = {"metadata" : parse_markdown_table },
343+ target_fixture = "provider_url" ,
330344)
331345def a_provider_is_started_that_can_generate_the_message_with_the_following_metadata (
332346 temp_dir : Path ,
333347 name : str ,
334348 fixture : str ,
335- metadata : dict [str , str ],
336- ) -> None :
349+ metadata : list [ dict [str , str ] ],
350+ ) -> Generator [ URL , None , None ] :
337351 """A provider is started that can generate the message with the following metadata.""" # noqa: E501
338- interaction_definitions = []
352+ interaction_definitions : list [ InteractionDefinition ] = []
339353 if (temp_dir / "interactions.pkl" ).exists ():
340354 with (temp_dir / "interactions.pkl" ).open ("rb" ) as pkl_file :
341355 interaction_definitions = pickle .load (pkl_file ) # noqa: S301
342356
343- def parse_metadata_value (value : str ) -> str :
344- return (
345- json .loads (value .replace ("JSON: " , "" ))
346- if value .startswith ("JSON: " )
347- else value
348- )
349-
350357 interaction_definition = InteractionDefinition (
351- method = "POST" ,
352- path = f"/{ name } " ,
353- metadata = {m ["key" ]: parse_metadata_value (m ["value" ]) for m in metadata },
354- response_body = fixture ,
355358 type = "Async" ,
359+ description = name ,
360+ body = fixture ,
361+ metadata = {
362+ row ["key" ]: json .loads (row ["value" ].replace ("JSON: " , "" ))
363+ if row ["value" ].startswith ("JSON: " )
364+ else row ["value" ]
365+ for row in metadata
366+ },
356367 )
357368 interaction_definitions .append (interaction_definition )
369+
358370 with (temp_dir / "interactions.pkl" ).open ("wb" ) as pkl_file :
359371 pickle .dump (interaction_definitions , pkl_file )
360372
361-
362- @given ("a provider state callback is configured" , target_fixture = "callback" )
363- def a_provider_state_callback_is_configured () -> None :
364- """A provider state callback is configured."""
373+ yield from start_provider (temp_dir )
365374
366375
367376################################################################################
368377## When
369378################################################################################
370379
371380
372- the_verification_is_run_with_start_context ()
381+ the_verification_is_run ()
373382
374383
375384################################################################################
0 commit comments