Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f5db7db

Browse files
author
Pijush Chakraborty
committed
Adding validation errors and test
1 parent b6acf10 commit f5db7db

File tree

2 files changed

+80
-26
lines changed

2 files changed

+80
-26
lines changed

firebase_admin/remote_config.py

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"""
1818

1919
import json
20-
from typing import Dict, Optional
20+
from typing import Any, Dict, Optional
21+
import requests
2122
from firebase_admin import App, _http_client, _utils
2223
import firebase_admin
2324

@@ -31,12 +32,41 @@ def __init__(self, etag, template_data):
3132
Args:
3233
etag: The string to be used for initialize the ETag property.
3334
template_data: The data to be parsed for getting the parameters and conditions.
35+
36+
Raises:
37+
ValueError: If the template data is not valid.
3438
"""
35-
self._parameters = template_data['parameters']
36-
self._conditions = template_data['conditions']
37-
self._version = template_data['version']
38-
self._parameter_groups = template_data['parameterGroups']
39-
self._etag = etag
39+
if 'parameters' in template_data:
40+
if template_data['parameters'] is not None:
41+
self._parameters = template_data['parameters']
42+
else:
43+
raise ValueError('Remote Config parameters must be a non-null object')
44+
else:
45+
self._parameters = {}
46+
47+
if 'conditions' in template_data:
48+
if template_data['conditions'] is not None:
49+
self._conditions = template_data['conditions']
50+
else:
51+
raise ValueError('Remote Config conditions must be a non-null object')
52+
else:
53+
self._conditions = []
54+
55+
self._version = ''
56+
if 'version' in template_data:
57+
self._version = template_data['version']
58+
59+
if 'parameterGroups' in template_data:
60+
if template_data['parameterGroups'] is not None:
61+
self._parameter_groups = template_data['parameterGroups']
62+
else:
63+
raise ValueError('Remote Config parameterGroups must be a non-null object')
64+
else:
65+
self.parameter_groups = {}
66+
67+
self._etag = ''
68+
if etag is not None and isinstance(etag, str):
69+
self._etag = etag
4070

4171
@property
4272
def parameters(self):
@@ -90,14 +120,13 @@ def evaluate(self, context):
90120
self._evaluator = _ConditionEvaluator(self._cache.conditions, context)
91121
return ServerConfig(config_values=self._evaluator.evaluate())
92122

93-
def set(self, template):
123+
def set(self, template: ServerTemplateData):
94124
"""Updates the cache to store the given template is of type ServerTemplateData.
95125
96126
Args:
97127
template: An object of type ServerTemplateData to be cached.
98128
"""
99-
if isinstance(template, ServerTemplateData):
100-
self._cache = template
129+
self._cache = template
101130

102131

103132
class ServerConfig:
@@ -140,21 +169,27 @@ def __init__(self, app):
140169
base_url=remote_config_base_url,
141170
headers=rc_headers, timeout=timeout)
142171

143-
144172
def get_server_template(self):
145173
"""Requests for a server template and converts the response to an instance of
146174
ServerTemplateData for storing the template parameters and conditions."""
147175
url_prefix = self._get_url_prefix()
148-
headers, response_json = self._client.headers_and_body('get',
149-
url=url_prefix+'/namespaces/ \
150-
firebase-server/serverRemoteConfig')
151-
return ServerTemplateData(headers.get('ETag'), response_json)
176+
try:
177+
headers, response_json = self._client.headers_and_body(
178+
'get', url=url_prefix+'/namespaces/firebase-server/serverRemoteConfig')
179+
except requests.exceptions.RequestException as error:
180+
raise self._handle_remote_config_error(error)
181+
else:
182+
return ServerTemplateData(headers.get('etag'), response_json)
152183

153184
def _get_url_prefix(self):
154-
# Returns project prefix for url, in the format of
155-
# /v1/projects/${projectId}
185+
"""Returns project prefix for url, in the format of /v1/projects/${projectId}"""
156186
return "/v1/projects/{0}".format(self._project_id)
157187

188+
@classmethod
189+
def _handle_remote_config_error(cls, error: Any):
190+
"""Handles errors received from the Cloud Functions API."""
191+
return _utils.handle_platform_error_from_requests(error)
192+
158193

159194
class _ConditionEvaluator:
160195
"""Internal class that facilitates sending requests to the Firebase Remote

tests/test_remote_config.py

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,30 +31,49 @@ def __init__(self, data, status, recorder, etag=ETAG):
3131

3232
def send(self, request, **kwargs):
3333
resp = super(MockAdapter, self).send(request, **kwargs)
34-
resp.headers = {'ETag': self._etag}
34+
resp.headers = {'etag': self._etag}
3535
return resp
3636

3737

3838
class TestGetServerTemplate:
3939
_DEFAULT_APP = firebase_admin.initialize_app(testutils.MockCredential(), name='no_project_id')
4040
_RC_INSTANCE = _utils.get_app_service(_DEFAULT_APP,
4141
_REMOTE_CONFIG_ATTRIBUTE, _RemoteConfigService)
42-
_DEFAULT_RESPONSE = json.dumps({
43-
'parameters': {
44-
'test_key': 'test_value'
45-
},
46-
'conditions': {},
47-
'parameterGroups': {},
48-
'version': 'test'
49-
})
5042

5143
def test_rc_instance_get_server_template(self):
5244
recorder = []
45+
response = json.dumps({
46+
'parameters': {
47+
'test_key': 'test_value'
48+
},
49+
'conditions': [],
50+
'parameterGroups': {},
51+
'version': 'test'
52+
})
5353
self._RC_INSTANCE._client.session.mount(
5454
'https://firebaseremoteconfig.googleapis.com',
55-
MockAdapter(self._DEFAULT_RESPONSE, 200, recorder))
55+
MockAdapter(response, 200, recorder))
5656

5757
template = self._RC_INSTANCE.get_server_template()
5858

5959
assert template.parameters == dict(test_key="test_value")
6060
assert str(template.version) == 'test'
61+
assert str(template.etag) == '0'
62+
63+
def test_rc_instance_get_server_template_empty_params(self):
64+
recorder = []
65+
response = json.dumps({
66+
'conditions': [],
67+
'parameterGroups': {},
68+
'version': 'test'
69+
})
70+
71+
self._RC_INSTANCE._client.session.mount(
72+
'https://firebaseremoteconfig.googleapis.com',
73+
MockAdapter(response, 200, recorder))
74+
75+
template = self._RC_INSTANCE.get_server_template()
76+
77+
assert template.parameters == {}
78+
assert str(template.version) == 'test'
79+
assert str(template.etag) == '0'

0 commit comments

Comments
 (0)