From 31ffcc94a3b05fe51d716eea576e8d6002ce59c4 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Fri, 22 May 2020 13:16:54 +0200
Subject: [PATCH 2/2] opendatasoft: manage empty contents returned (#43223)

---
 passerelle/apps/opendatasoft/models.py | 32 +++++++++++++++++---------
 tests/test_opendatasoft.py             | 30 ++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/passerelle/apps/opendatasoft/models.py b/passerelle/apps/opendatasoft/models.py
index 9114bda1..8ce0c172 100644
--- a/passerelle/apps/opendatasoft/models.py
+++ b/passerelle/apps/opendatasoft/models.py
@@ -74,27 +74,37 @@ class OpenDataSoft(BaseResource):
             params.update({'rows': limit})
 
         result_response = self.requests.get(url, params=params)
         err_desc = result_response.json().get('error')
         if err_desc:
             return {'err': 1, 'err_desc': err_desc}
 
         result = []
-        for record in result_response.json().get('records'):
-            data = {}
-            data['id'] = record.get('recordid')
-
-            context = {}
-            for key, value in record.get('fields').items():
-                context[key] = force_text(value)
-            template = Template(text_template)
-            data['text'] = template.render(Context(context)).strip()
-
-            result.append(data)
+        err_desc = ''
+        if result_response.json().get('records') is None:
+            err_desc = "field records doesn't exist"
+        else:
+            for idx, record in enumerate(result_response.json().get('records')):
+                data = {}
+                data['id'] = record.get('recordid')
+                if not data['id']:
+                    err_desc = 'no recordid on record %s' % (idx + 1)
+                    break
+                if not isinstance(record.get('fields'), dict):
+                    err_desc = 'no fields dictionary on record %s' % (idx + 1)
+                    break
+                context = {}
+                for key, value in record.get('fields').items():
+                    context[key] = force_text(value)
+                template = Template(text_template)
+                data['text'] = template.render(Context(context)).strip()
+                result.append(data)
+        if err_desc:
+            return {'err': 1, 'err_desc': "The JSON reply is invalid: " + err_desc}
         return {'data': result}
 
     @endpoint(name='q',
               description=_('Query'),
               pattern=r'^(?P<query_slug>[\w:_-]+)/$',
               perm='can_access',
               show=False)
     def q(self, request, query_slug, **kwargs):
diff --git a/tests/test_opendatasoft.py b/tests/test_opendatasoft.py
index be91fd90..677a7cec 100644
--- a/tests/test_opendatasoft.py
+++ b/tests/test_opendatasoft.py
@@ -192,16 +192,46 @@ def test_search_empty_contents(mocked_get, app, connector):
 
     # error returned by opendadasoft server
     json_response = json.dumps({'error': "The query is invalid : Field 00 doesn't exist"})
     mocked_get.return_value = utils.FakedResponse(content=json_response, status_code=200)
     resp = app.get(endpoint, status=200)
     assert resp.json['err']
     assert resp.json['err_desc'] == "The query is invalid : Field 00 doesn't exist"
 
+    # empty reply
+    mocked_get.return_value = utils.FakedResponse(content='{"records": []}', status_code=200)
+    resp = app.get(endpoint, status=200)
+    assert not resp.json['err']
+    assert resp.json['data'] == []
+
+    # empty fields
+    json_response = json.dumps({'records': [{'recordid': '42', 'fields': {}}]})
+    mocked_get.return_value = utils.FakedResponse(content=json_response, status_code=200)
+    resp = app.get(endpoint, status=200)
+    assert not resp.json['err']
+    assert resp.json['data'] == [{'id': '42', 'text': ''}]
+
+    mocked_get.return_value = utils.FakedResponse(content='{}', status_code=200)
+    resp = app.get(endpoint, status=200)
+    assert resp.json['err']
+    assert resp.json['err_desc'] == "The JSON reply is invalid: field records doesn't exist"
+
+    json_response = json.dumps({'records': [{'fields': {}}]})
+    mocked_get.return_value = utils.FakedResponse(content=json_response, status_code=200)
+    resp = app.get(endpoint, status=200)
+    assert resp.json['err']
+    assert resp.json['err_desc'] == 'The JSON reply is invalid: no recordid on record 1'
+
+    json_response = json.dumps({'records': [{'recordid': '42'}]})
+    mocked_get.return_value = utils.FakedResponse(content=json_response, status_code=200)
+    resp = app.get(endpoint, status=200)
+    assert resp.json['err']
+    assert resp.json['err_desc'] == 'The JSON reply is invalid: no fields dictionary on record 1'
+
 
 @mock.patch('passerelle.utils.Request.get')
 def test_search_using_q(mocked_get, app, connector):
     endpoint = utils.generic_endpoint_url('opendatasoft', 'search', slug=connector.slug)
     assert endpoint == '/opendatasoft/my_connector/search'
     params = {
         'dataset': 'referentiel-adresse-test',
         'text_template': '{{numero}} {{nom_rue|safe}} {{nom_commun}}',
-- 
2.26.2

