From 342560e8f252e52dde853fa828f6e4a6cc2a9553 Mon Sep 17 00:00:00 2001
From: "Antoine R. Dumont (@ardumont)" <antoine.romain.dumont@gmail.com>
Date: Tue, 24 Nov 2015 13:57:42 +0100
Subject: [PATCH] Demonstrate via tests that our api deals with client's accept
 header

Accepted types: application/json, application/yaml, text/html

In browser, this means that our api is only browsable.

With curl (or other similar tools) however, you can ask with the Accept
headers

For example:

$ curl -v -H 'Accept:application/yaml' -X GET
http://localhost:6543/api/1/revision/edfbd9e840cc82e879d9aae8ecc29c7121ff750
Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying ::1...
* connect to ::1 port 6543 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 6543 (#0)
> GET /api/1/revision/edfbd9e840cc82e879d9aae8ecc29c7121ff750 HTTP/1.1
> Host: localhost:6543
> User-Agent: curl/7.45.0
> Accept:application/yaml
>
* HTTP 1.0, assume close after body
< HTTP/1.0 400 BAD REQUEST
< Content-Type: application/yaml
< Content-Length: 39
< Server: Werkzeug/0.10.4 Python/3.4.3+
< Date: Tue, 24 Nov 2015 13:00:23 GMT
<
{error: invalid checksum query string}
* Closing connection 0

$ curl -v -H 'Accept:application/json' -X GET
http://localhost:6543/api/1/revision/edfbd9e840cc82e879d9aae8ecc29c7121ff750
Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying ::1...
* connect to ::1 port 6543 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 6543 (#0)
> GET /api/1/revision/edfbd9e840cc82e879d9aae8ecc29c7121ff750 HTTP/1.1
> Host: localhost:6543
> User-Agent: curl/7.45.0
> Accept:application/json
>
* HTTP 1.0, assume close after body
< HTTP/1.0 400 BAD REQUEST
< Content-Type: application/json
< Content-Length: 42
< Server: Werkzeug/0.10.4 Python/3.4.3+
< Date: Tue, 24 Nov 2015 13:00:28 GMT
<
* Closing connection 0
{"error": "invalid checksum query string"}%
---
 swh/web/ui/main.py                  |  9 ++++++
 swh/web/ui/tests/test_app.py        |  6 +++-
 swh/web/ui/tests/test_controller.py | 48 ++++++++++++++++++++++++++++-
 3 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/swh/web/ui/main.py b/swh/web/ui/main.py
index 594ca43ff..b1e4b665e 100644
--- a/swh/web/ui/main.py
+++ b/swh/web/ui/main.py
@@ -60,6 +60,15 @@ def storage():
     return app.config['conf']['storage']
 
 
+def setup_app(app, conf):
+    app.secret_key = conf['secret_key']
+    app.config['conf'] = conf
+    app.config['MAX_CONTENT_LENGTH'] = conf['max_upload_size']
+    app.config['DEFAULT_RENDERERS'] = RENDERERS
+
+    return app
+
+
 def run_from_webserver(environ, start_response):
     """Run the WSGI app from the webserver, loading the configuration."""
 
diff --git a/swh/web/ui/tests/test_app.py b/swh/web/ui/tests/test_app.py
index 57b43c1dd..4811d8e8d 100644
--- a/swh/web/ui/tests/test_app.py
+++ b/swh/web/ui/tests/test_app.py
@@ -8,6 +8,7 @@
 
 from swh.web.ui import controller
 from swh.storage.api.client import RemoteStorage as Storage
+from swh.web.ui import renderers
 
 
 # Because the Storage's __init__ function does side effect at startup...
@@ -44,10 +45,13 @@ def init_app(base_url='https://somewhere.org:4321'):
     # inject the mock data
     conf = {'storage': storage,
             'upload_folder': '/some/upload-dir',
-            'upload_allowed_extensions': ['txt']}
+            'upload_allowed_extensions': ['txt'],
+            'max_upload_size': 1024}
 
     controller.app.config['TESTING'] = True
     controller.app.config.update({'conf': conf})
+    controller.app.config['MAX_CONTENT_LENGTH'] = conf['max_upload_size']
+    controller.app.config['DEFAULT_RENDERERS'] = renderers.RENDERERS
     app = controller.app.test_client()
 
     return app, controller.app.config, storage
diff --git a/swh/web/ui/tests/test_controller.py b/swh/web/ui/tests/test_controller.py
index d2cd3e667..ad3925966 100644
--- a/swh/web/ui/tests/test_controller.py
+++ b/swh/web/ui/tests/test_controller.py
@@ -5,6 +5,7 @@
 
 import unittest
 import json
+import yaml
 
 from nose.tools import istest
 from unittest.mock import patch, MagicMock
@@ -136,7 +137,7 @@ class ApiTestCase(unittest.TestCase):
 
     @patch('swh.web.ui.controller.service')
     @istest
-    def api_content_not_found(self, mock_service):
+    def api_content_not_found_as_json(self, mock_service):
         # given
         mock_service.lookup_content.return_value = None
         mock_service.lookup_hash_origin = MagicMock()
@@ -159,6 +160,33 @@ class ApiTestCase(unittest.TestCase):
             'be4735637006560c')
         mock_service.lookup_hash_origin.called = False
 
+    @patch('swh.web.ui.controller.service')
+    @istest
+    def api_content_not_found_as_yaml(self, mock_service):
+        # given
+        mock_service.lookup_content.return_value = None
+        mock_service.lookup_hash_origin = MagicMock()
+
+        # when
+        rv = self.app.get(
+            '/api/1/content/sha256:83c0e67cc80f60caf1fcbec2d84b0ccd7968b3'
+            'be4735637006560c/',
+            headers={'accept': 'application/yaml'})
+
+        self.assertEquals(rv.status_code, 404)
+        self.assertEquals(rv.mimetype, 'application/yaml')
+
+        response_data = yaml.load(rv.data.decode('utf-8'))
+        self.assertEquals(response_data, {
+            'error': 'Content with sha256:83c0e67cc80f60caf1fcbec2d84b0ccd79'
+            '68b3be4735637006560c not found.'
+        })
+
+        mock_service.lookup_content.assert_called_once_with(
+            'sha256:83c0e67cc80f60caf1fcbec2d84b0ccd7968b3'
+            'be4735637006560c')
+        mock_service.lookup_hash_origin.called = False
+
     @patch('swh.web.ui.controller.service')
     @istest
     def api_search(self, mock_service):
@@ -175,6 +203,24 @@ class ApiTestCase(unittest.TestCase):
 
         mock_service.lookup_hash.assert_called_once_with('sha1:blah')
 
+    @patch('swh.web.ui.controller.service')
+    @istest
+    def api_search_as_yaml(self, mock_service):
+        # given
+        mock_service.lookup_hash.return_value = True
+
+        # when
+        rv = self.app.get('/api/1/search/sha1:halb/',
+                          headers={'Accept': 'application/yaml'})
+
+        self.assertEquals(rv.status_code, 200)
+        self.assertEquals(rv.mimetype, 'application/yaml')
+
+        response_data = yaml.load(rv.data.decode('utf-8'))
+        self.assertEquals(response_data, {'found': True})
+
+        mock_service.lookup_hash.assert_called_once_with('sha1:halb')
+
     @patch('swh.web.ui.controller.service')
     @istest
     def api_search_not_found(self, mock_service):
-- 
GitLab