From dd183a3c6100759f538410264c8a9583c422752d Mon Sep 17 00:00:00 2001 From: David Wang Date: Thu, 16 Jan 2020 19:01:17 -0800 Subject: [PATCH 1/2] initial pact-message support --- pact/constants.py | 9 +++++++++ pact/pact.py | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/pact/constants.py b/pact/constants.py index 801689a33..2ba49a445 100644 --- a/pact/constants.py +++ b/pact/constants.py @@ -10,6 +10,12 @@ def mock_service_exe(): else: return 'pact-mock-service' +def message_exe(): + """Get the appropriate executable name for this platform.""" + if os.name == 'nt': + return 'pact-message.bat' + else: + return 'pact-message' def provider_verifier_exe(): """Get the appropriate provider executable name for this platform.""" @@ -24,3 +30,6 @@ def provider_verifier_exe(): VERIFIER_PATH = normpath(join( dirname(__file__), 'bin', 'pact', 'bin', provider_verifier_exe())) + +MESSAGE_PATH = normpath(join( + dirname(__file__), 'bin', 'pact', 'bin', message_exe())) diff --git a/pact/pact.py b/pact/pact.py index 45326dee8..45772ed24 100644 --- a/pact/pact.py +++ b/pact/pact.py @@ -1,6 +1,6 @@ """API for creating a contract and configuring the mock service.""" from __future__ import unicode_literals - +import json import os import platform from subprocess import Popen @@ -11,7 +11,9 @@ from requests.packages.urllib3 import Retry from .constants import MOCK_SERVICE_PATH +from .constants import MESSAGE_PATH from .matchers import from_term +from .message import Message class Pact(object): @@ -102,7 +104,9 @@ def __init__(self, consumer, provider, host_name='localhost', port=1234, self.sslkey = sslkey self.version = version self._interactions = [] + self._message_interactions = [] self._process = None + self._message_process = None def given(self, provider_state): """ @@ -127,11 +131,15 @@ def setup(self): self.uri + '/interactions', headers=self.HEADERS) assert resp.status_code == 200, resp.text + + print("********** uri: {}".format(self.uri)) resp = requests.put( self.uri + '/interactions', headers=self.HEADERS, json={"interactions": self._interactions}) + print("****** interactions: {}".format(self._interactions)) + assert resp.status_code == 200, resp.text except AssertionError: raise @@ -197,6 +205,22 @@ def upon_receiving(self, scenario): self._interactions[0]['description'] = scenario return self + def verify_message(self, handler): + + for x in self._message_interactions: + command = [ + MESSAGE_PATH, + 'update', + json.dumps(x._messages[0]), + '--pact-dir', self.pact_dir, + '--pact-specification-version={}'.format(self.version), + '--consumer', self.consumer.name + "_message", + '--provider', self.provider.name + "_message"] + + print("********* command: {}".format(command)) + + self._message_process = Popen(command) + def verify(self): """ Have the mock service verify all interactions occurred. @@ -215,6 +239,14 @@ def verify(self): self.uri + '/pact', headers=self.HEADERS) assert resp.status_code == 200, resp.text + def add_message(self): + + message = Message() + + self._message_interactions.append(message) + + return message + def with_request(self, method, path, body=None, headers=None, query=None): """ Define the request the request that the client is expected to perform. @@ -297,6 +329,9 @@ def __enter__(self): Sets up the mock service to expect the client requests. """ + + print("******** __enter__") + self.setup() def __exit__(self, exc_type, exc_val, exc_tb): @@ -309,6 +344,8 @@ def __exit__(self, exc_type, exc_val, exc_tb): if (exc_type, exc_val, exc_tb) != (None, None, None): return + print("******** __exit___") + self.verify() From da03551e812508652e062fc4ba6071f1119e5bf2 Mon Sep 17 00:00:00 2001 From: David Wang Date: Thu, 16 Jan 2020 19:04:16 -0800 Subject: [PATCH 2/2] add message.py file --- pact/message.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 pact/message.py diff --git a/pact/message.py b/pact/message.py new file mode 100644 index 000000000..65c989ae6 --- /dev/null +++ b/pact/message.py @@ -0,0 +1,43 @@ +class Message(object): + + HEADERS = {'X-Pact-Mock-Service': 'true'} + + MANDATORY_FIELDS = {'provider_state', 'description', 'metadata', 'contents'} + + def __init__(self): + self._messages = [] + + def _insert_message_if_complete(self): + """ + Insert a new message if current message is complete. + + An interaction is complete if it has all the mandatory fields. + If there are no interactions, a new interaction will be added. + + :rtype: None + """ + if not self._messages: + self._messages.append({}) + elif all(field in self._messages[0] + for field in self.MANDATORY_FIELDS): + self._messages.insert(0, {}) + + def given(self, provider_state): + self._insert_message_if_complete() + self._messages[0]['provider_state'] = provider_state + return self + + def expects_to_receive(self, description): + self._insert_message_if_complete() + self._messages[0]['description'] = description + return self + + def with_metadata(self, metadata): + self._insert_message_if_complete() + self._messages[0]['metadata'] = metadata + return self + + def with_contents(self, contents): + self._insert_message_if_complete() + self._messages[0]['contents'] = contents + return self