8 Commitit a792dee3da ... 8da70e6a3c

Tekijä SHA1 Viesti Päivämäärä
  Wiliam Souza 8da70e6a3c Skyp bug test 9 vuotta sitten
  Wiliam Souza d8dadcf9e3 Merge pull request #2 from wiliamsouza/test/mock 9 vuotta sitten
  Wiliam Souza a203d95ea9 Removed path from expectation 9 vuotta sitten
  Wiliam Souza 285d0e51ec Adds more mock tests 9 vuotta sitten
  Wiliam Souza 449d24a7e0 Updated example 9 vuotta sitten
  Wiliam Souza 8ae7866a31 Removes asyncio from mock client 9 vuotta sitten
  Wiliam Souza 8e3982275e WIP 9 vuotta sitten
  Wiliam Souza f788614484 Adds mock using asyncio and context manager 9 vuotta sitten
5 muutettua tiedostoa jossa 167 lisäystä ja 23 poistoa
  1. 8 20
      README.md
  2. 1 2
      echod/api.py
  3. 72 0
      echod/mock.py
  4. 11 1
      echod/utils.py
  5. 75 0
      tests/test_mock.py

+ 8 - 20
README.md

@@ -24,33 +24,21 @@ Mock
 ----
 
 ```python
-import echod
+from echod.mock import Mock
 
+# This will create a mock that accepts `POST` in the path `/v1/users/`.
 expectation = {
     'method': 'POST',
-    'path': '/v1/users/',
     'response': {'body': {'email': 'john@doe.com', 'name': 'John Doe'},
                  'headers': {'content_type': 'application/json'},
                  'status_code': 201}
 }
 
+with Mock(expectation) as client:
+    # The mock URL is available to use
+    client.mock_url  # 'http://127.0.0.1:9876/mock/fbf01f94169640de9e585fe5e30a0958/'
 
-with echod.mock(**expectation) as client:
-    response = client.post()
-    response.status_code == 200
-```
-
-
-callback
---------
-
-```python
-import requests
-
-
-with echod.callback() as webhook:
-    settings.callback_url = webhook.url
-    requests.post()
-    webhook.wait_callback(timeout=10)
-    webhook.response.data == {...}
+    # This method will make a request to the mock
+    response = client.response()
+    assert response.status_code == 201
 ```

+ 1 - 2
echod/api.py

@@ -30,8 +30,7 @@ def get_mock(request):
 def put_mock(request):
     data = yield from request.json()
     uuid_hex = uuid.uuid4().hex
-    path = yield from normalize_path('/mock/{}/{}/'.format(uuid_hex,
-                                                           data['path']))
+    path = normalize_path('/mock/{}/'.format(uuid_hex))
     request.app.router.add_route(data['method'], path, mock)
     request.app['mock_db'][path] = data
     return web.Response(text=json.dumps({'path': path}),

+ 72 - 0
echod/mock.py

@@ -0,0 +1,72 @@
+# coding: utf-8
+
+import json
+
+from wtforms.validators import ValidationError
+
+from prettyconf import config
+
+import requests
+
+from echod.forms import MockForm
+from echod.utils import url_path_join
+
+request_headers = {
+    'content_type': 'application/json',
+    'accept': 'application/json',
+}
+
+
+class Mock(object):
+    def __init__(self, expectation, host=None, port=None, docker=False):
+        form = MockForm(data=expectation)
+        if not form.validate():
+            raise ValidationError(form.errors)
+
+        self.expectation = expectation
+
+        self.host = host or config('ECHOD_API_HOST', default='127.0.0.1')
+        self.port = port or config('ECHOD_API_PORT', default=9876)
+
+        self.base_url = 'http://{}:{}'.format(self.host, self.port)
+        self._session = requests.Session()
+
+        self._urls = {
+            'health': url_path_join(self.base_url, 'health', '/'),
+            'mocks': url_path_join(self.base_url, 'mocks', '/'),
+            'response': None,
+        }
+        self.mock_url = None
+
+    def __enter__(self):
+        response = self._session.request(method='PUT', url=self._urls['mocks'],
+                                         headers=request_headers,
+                                         data=json.dumps(self.expectation),
+                                         timeout=1)
+
+        if response.status_code != 201:
+            raise Exception('Erro creating mock.')
+
+        self.mock_url = url_path_join(self.base_url, response.json()['path'], '/')
+        self._urls['response'] = self.mock_url
+
+        return self
+
+    def __exit__(self, exec_type, exc, tb):
+        # Clean up
+        pass
+
+    def health(self):
+        return self._session.request(method='GET', url=self._urls['health'])
+
+    def response(self):
+        body = ''
+        headers = {}
+        method = self.expectation['method'].lower()
+
+        if 'request' in self.expectation:
+            headers = self.expectation['request']['headers']
+            body = self.expectation['request']['body']
+
+        return self._session.request(method=method, url=self._urls['response'],
+                                     headers=headers, data=json.dumps(body))

+ 11 - 1
echod/utils.py

@@ -3,6 +3,7 @@
 import json
 import hashlib
 import asyncio
+from urllib.parse import urlsplit, urlunsplit
 
 
 @asyncio.coroutine
@@ -40,7 +41,6 @@ def decode_json(data):
 
 # TODO: Changes to use https://github.com/rbaier/python-urltools/
 #       do not forget PUBLIC_SUFFIX_LIST env var!
-@asyncio.coroutine
 def normalize_path(path):
     """ Normalize path
 
@@ -65,3 +65,13 @@ def hash_dict(dictionary):
 
 def compare_hash(expected_hash, received_hash):
     return expected_hash == received_hash
+
+
+def url_path_join(*parts):
+    def first_of_each(*sequences):
+        return (next((x for x in sequence if x), '') for sequence in sequences)
+    schemes, netlocs, paths, queries, fragments = zip(*(urlsplit(part) for part in parts))
+    scheme, netloc, query, fragment = first_of_each(schemes, netlocs, queries,
+                                                    fragments)
+    path = '/'.join(x.strip('/') for x in paths if x)
+    return urlunsplit((scheme, netloc, path, query, fragment))

+ 75 - 0
tests/test_mock.py

@@ -0,0 +1,75 @@
+# coding: utf-8
+import json
+from urllib.parse import urlsplit, splitport
+
+import pytest
+
+import aiohttp
+
+from echod.mock import Mock
+
+request_headers = {
+    'content_type': 'application/json',
+    'accept': 'application/json',
+}
+
+
+@pytest.mark.skipif(True, reason='https://github.com/wiliamsouza/echod/issues/5')
+@pytest.mark.asyncio
+def test_mock_client(api_server):
+    expectation = {
+        'method': 'POST',
+        'request': {'body': {'email': 'john@doe.com',
+                             'name': 'John Doe',
+                             'password': 'secret'},
+                    'headers': {'accept': 'application/json',
+                                'content_type': 'application/json'}},
+        'response': {'body': {'email': 'john@doe.com', 'name': 'John Doe'},
+                     'headers': {'content_type': 'application/json'},
+                     'status_code': 201}
+    }
+
+    netloc = urlsplit(api_server).netloc
+    host, port = splitport(netloc)
+
+    # TODO: Fix this api_server not work inside a context manager
+    with Mock(expectation) as client:
+        health = client.health()
+        response = client.response()
+
+        assert health.status_code == 200
+        assert response.status_code == 201
+
+        data = json.dumps(expectation['request']['body'])
+        response = yield from aiohttp.request('POST', client.mock_url,
+                                              data=data,
+                                              headers=request_headers)
+        assert response.status == 201
+
+
+@pytest.mark.skipif(True, reason='https://github.com/wiliamsouza/echod/issues/5')
+@pytest.mark.asyncio
+def test_mock_client_without_request(api_server):
+    expectation = {
+        'method': 'POST',
+        'response': {'body': {'email': 'john@doe.com', 'name': 'John Doe'},
+                     'headers': {'content_type': 'application/json'},
+                     'status_code': 201}
+    }
+
+    netloc = urlsplit(api_server).netloc
+    host, port = splitport(netloc)
+
+    # TODO: Fix this api_server not work inside a context manager
+    with Mock(expectation) as client:
+        health = client.health()
+        response = client.response()
+
+        assert health.status_code == 200
+        assert response.status_code == 201
+
+        data = json.dumps('')
+        response = yield from aiohttp.request('POST', client.mock_url,
+                                              data=data,
+                                              headers=request_headers)
+        assert response.status == 201