class TestDeleteUser(TestCase): def setUp(self): self.lg = LocalGateway(app, Config()) def test_delete_user(self): response_1 = self.lg.handle_request( method='DELETE', path='/users/{user_id}'.format(user_id=user_id_1), headers=dict(), body='') assert response_1['statusCode'] == 204 response_2 = self.lg.handle_request( method='GET', path='/users/{user_id}'.format(user_id=user_id_1), headers=dict(), body='') assert response_2['statusCode'] == 404 def test_delete_non_existent_user(self): response_1 = self.lg.handle_request( method='DELETE', path='/users/{user_id}'.format( user_id='7c098790-fe62-4903-8699-0ea958e18602'), headers=dict(), body='') assert response_1['statusCode'] == 404
class TestGetUser(TestCase): def setUp(self): self.lg = LocalGateway(app, Config()) def test_get_user_basic_works(self): response = self.lg.handle_request( method='GET', path='/users/{user_id}'.format(user_id=user_id_1), headers=dict(), body='') assert response['statusCode'] == 200 assert json.loads(response['body'])['data'] == { 'emailAddress': '*****@*****.**', 'firstName': 'Nick', 'lastName': 'Plutt', 'metaData': [{ 'fieldData': '200 Grand Avenue', 'fieldType': 'address' }], 'userId': '9f1b15e8-dca7-427d-816d-44f519010c6b' } def test_get_user_raises_not_found(self): response = self.lg.handle_request( method='GET', path='/users/{user_id}'.format( user_id='7c098790-fe62-4903-8699-0ea958e18602'), headers=dict(), body='') assert response['statusCode'] == 404
def test_does_deny_with_forbidden_when_route_not_found( self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) with pytest.raises(ForbiddenError) as ei: gateway.handle_request('GET', '/badindex', {}, '') exception_body = str(ei.value.body) assert 'Missing Authentication Token' in exception_body
class UnitTests(unittest.TestCase): def setUp(self): self.lg = LocalGateway(app, Config()) def test_insert_volunteer(self): request = {'body': {'name': 'Raul', 'midname': 'Silverio', 'neighbor': 'Jurere', 'city': 'Florianopolis'}} request_body = request['body'] response = self.lg.handle_request(method='POST', path='/voluntario/add', headers={ 'Content-Type': 'application/json' }, body=json.dumps(request_body)) assert response['statusCode'] == 200 def test_insert_action(self): request = {'body': {"name": "Ambiental", "institution": "IBAMA", "location": "Amazonas", "description": "Organizacao nacional responsavel pela protecao ambiental"}} request_body = request['body'] response = self.lg.handle_request(method='POST', path='/voluntario/add', headers={ 'Content-Type': 'application/json' }, body=json.dumps(request_body)) assert response['statusCode'] == 200
def test_does_throw_unauthorized_when_no_auth_token_present_on_valid_route( self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) with pytest.raises(NotAuthorizedError) as ei: gateway.handle_request('GET', '/index', {}, '') exception_body = str(ei.value.body) assert '{"message":"Unauthorized"}' in exception_body
def test_does_throw_unauthorized_when_no_auth_token_present_on_valid_route( self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) with pytest.raises(NotAuthorizedError) as ei: gateway.handle_request( 'GET', '/index', {}, '') exception_body = str(ei.value.body) assert '{"message":"Unauthorized"}' in exception_body
def test_does_deny_unauthed_request(self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) with pytest.raises(ForbiddenError) as ei: gateway.handle_request( 'GET', '/index', {'Authorization': 'deny'}, '') exception_body = str(ei.value.body) assert ('{"Message": ' '"User is not authorized to ' 'access this resource"}') in exception_body
def test_does_deny_with_forbidden_when_auth_token_present( self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) with pytest.raises(ForbiddenError) as ei: gateway.handle_request('GET', '/badindex', {'Authorization': 'foobar'}, '') # The message should be a more complicated error message to do with # signing the request. It always ends with the Authorization token # that we passed up, so we can check for that. exception_body = str(ei.value.body) assert 'Authorization=foobar' in exception_body
class TestApp(TestCase): def setUp(self): self.lg = LocalGateway(app, Config()) def test_get_books(self): response = self.lg.handle_request(method='GET', path='/books', headers={}, body='') assert response['statusCode'] == 200 assert json.loads( response['body']) == [dict(book_id=1), dict(book_id=2)] def test_post_book(self): body = dict(book_info='hello') response = self.lg.handle_request( method='POST', path='/books', headers={'Content-Type': 'application/json'}, body=json.dumps(body)) assert response['statusCode'] == 201 assert response['headers'].get('Location') == '/books/3' def test_get_book_by_id(self): response = self.lg.handle_request(method='GET', path='/books/4', headers={}, body='') assert response['statusCode'] == 200 assert json.loads(response['body']) == dict(book_id=4) def test_put_book_by_id(self): body = dict(book_info='hello') response = self.lg.handle_request(method='PUT', path='/books/4', headers={}, body=json.dumps(body)) assert response['statusCode'] == 204 assert json.loads(response['body']) is None def test_delete_book_by_id(self): response = self.lg.handle_request(method='DELETE', path='/books/4', headers={}, body='') assert response['statusCode'] == 204 assert json.loads(response['body']) is None
class TestCreateUser(TestCase): def setUp(self): self.lg = LocalGateway(app, Config()) def test_create_user_returns_code_and_header(self): body = dict( emailAddress='*****@*****.**', firstName='Joe', lastName='Schmo', metaData=[dict(fieldType='favorite food', fieldData='tacos')]) response_1 = self.lg.handle_request( method='POST', path='/users', headers={'Content-Type': 'application/json'}, body=json.dumps(body)) assert response_1['statusCode'] == 201 assert response_1['headers']['Location'].index('users') response_2 = self.lg.handle_request( method='GET', path=response_1['headers']['Location'], headers=dict(), body='') assert response_2['statusCode'] == 200 body['userId'] = ANY assert json.loads(response_2['body'])['data'] == body def test_create_user_fails_on_badrequest(self): body = dict(emailAddress='*****@*****.**', firstName='Joe', lastName='Schmo', metaData=[dict(fieldType='favorite food')]) response_1 = self.lg.handle_request( method='POST', path='/users', headers={'Content-Type': 'application/json'}, body=json.dumps(body)) assert response_1['statusCode'] == 400 def test_create_user_fails_on_conflict(self): body = dict( emailAddress='*****@*****.**', firstName='Nick', lastName='Plutt', metaData=[dict(fieldType='favorite food', fieldData='tacos')]) response = self.lg.handle_request( method='POST', path='/users', headers={'Content-Type': 'application/json'}, body=json.dumps(body)) assert response['statusCode'] == 409
def test_does_populate_context(self): demo = app.Chalice('app-name') @demo.route('/context') def context_view(): context = demo.lambda_context return { 'name': context.function_name, 'memory': context.memory_limit_in_mb, 'version': context.function_version, 'timeout': context.get_remaining_time_in_millis(), 'request_id': context.aws_request_id, } disk_config = { 'lambda_timeout': 10, 'lambda_memory_size': 256, } config = Config(chalice_stage='api', config_from_disk=disk_config) gateway = LocalGateway(demo, config) response = gateway.handle_request('GET', '/context', {}, '') body = json.loads(response['body']) assert body['name'] == 'api_handler' assert body['memory'] == 256 assert body['version'] == '$LATEST' assert body['timeout'] > 10 assert body['timeout'] <= 10000 assert AWS_REQUEST_ID_PATTERN.match(body['request_id'])
def request(self, method="GET", path="/", headers=None, body=None): """Simulates a request to the app local gateway. Performs a request against the application. :path: (str) The URL path to request (default: '/'). :method: (str) An HTTP method to use in the request (default: GET). :headers: (dict) Additional headers to include in the request (default: ``None``). :body: (str) A string to send as the body of the request (default: ``None``). :returns: (dict) The result of the request. """ if not path.startswith("/"): raise ValueError("path must start with '/'") valid_methods = ["GET", "HEAD", "POST", "PUT", "DELETE"] if method not in valid_methods: raise ValueError(f"method must be one of: {valid_methods}") body = body or "" headers = headers or {} gateway = LocalGateway(self.app, Config()) response = gateway.handle_request(method, path, headers, body) return response
class ChaliceTestHarness: def __init__(self): project_dir = os.path.join(os.path.dirname(__file__), "..", "..") config = CLIFactory(project_dir=project_dir).create_config_obj( chalice_stage_name="dev") self._chalice_app = config.chalice_app self._gateway = LocalGateway(self._chalice_app, config) @functools.lru_cache(maxsize=128, typed=False) def __getattr__(self, item): item = item.upper() return functools.partial(self.request, method=item) def request(self, path, headers=None, data='', method="GET"): resp_obj = requests.Response() if not headers: headers = {} try: response = self._gateway.handle_request(method, path, headers, data) except LocalGatewayException as error: resp_obj.status_code = error.CODE resp_obj.headers = error.headers resp_obj.body = error.body else: resp_obj.status_code = response['statusCode'] resp_obj.headers = response['headers'] resp_obj.body = response['body'] resp_obj.headers['Content-Length'] = str(len(data)) return resp_obj
class ChaliceTestHarness: def __init__(self): project_dir = os.path.join(os.path.dirname(__file__), "..") config = CLIFactory(project_dir=project_dir).create_config_obj( chalice_stage_name="dev") self._chalice_app = config.chalice_app self._gateway = LocalGateway(self._chalice_app, config) @functools.lru_cache(maxsize=64, typed=False) def __getattr__(self, method): return functools.partial(self.request, method=method.upper()) def request(self, path, headers={}, body={}, method="GET"): resp_obj = requests.Response() try: response = self._gateway.handle_request(method, path, headers, body) except LocalGatewayException as error: resp_obj.status_code = error.CODE resp_obj.headers = error.headers resp_obj.body = error.body else: resp_obj.status_code = response["statusCode"] resp_obj.headers = response["headers"] resp_obj.body = response["body"] resp_obj.headers["Content-Length"] = str(len(body)) return resp_obj
class TestApp(TestCase): def setUp(self): self.lg = LocalGateway(app, Config()) def test_img_post(self): response = self._new_img_post() assert response['statusCode'] == 200 assert json.loads(response['body']).get("id", "") is not None # Use stored image in the next steps self.uuid = json.loads(response['body']).get("id", "") def test_img_get(self): uuid = json.loads(self._new_img_post()['body']).get("id", "") response = self.lg.handle_request(method='GET', path=f'/v1/img/{uuid}.png', headers={"Accept": "image/png"}, body='') assert response['statusCode'] == 200 assert response['body'][:4] == b'\x89PNG' def test_img_get_unsupported_format(self): uuid = json.loads(self._new_img_post()['body']).get("id", "") response = self.lg.handle_request(method='GET', path='/v1/img/{uuid}.bad', headers={"Accept": "image/png"}, body='') assert response['statusCode'] == 400 def _new_img_post(self): body = { "type": "base64", "data": "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" } response = self.lg.handle_request(method='POST', path='/v1/img', headers={'Content-Type': 'application/json'}, body=json.dumps(body)) return response
class TestHTTPClient(BaseClient): def __init__(self, app, config): # type: (Chalice, Config) -> None self._app = app self._config = config self._local_gateway = LocalGateway(app, self._config) def request(self, method, path, headers=None, body=b''): # type: (str, str, Optional[Dict[str, str]], bytes) -> HTTPResponse if headers is None: headers = {} scoped = self._config.scope(self._config.chalice_stage, 'api_handler') with self._patched_env_vars(scoped.environment_variables): try: response = self._local_gateway.handle_request( method=method.upper(), path=path, headers=headers, body=body ) except LocalGatewayException as e: return self._error_response(e) return HTTPResponse.create_from_dict(response) def _error_response(self, e): # type: (LocalGatewayException) -> HTTPResponse return HTTPResponse( headers=e.headers, body=e.body if e.body else b'', status_code=e.CODE ) def get(self, path, **kwargs): # type: (str, **Any) -> HTTPResponse return self.request('GET', path, **kwargs) def post(self, path, **kwargs): # type: (str, **Any) -> HTTPResponse return self.request('POST', path, **kwargs) def put(self, path, **kwargs): # type: (str, **Any) -> HTTPResponse return self.request('PUT', path, **kwargs) def patch(self, path, **kwargs): # type: (str, **Any) -> HTTPResponse return self.request('PATCH', path, **kwargs) def options(self, path, **kwargs): # type: (str, **Any) -> HTTPResponse return self.request('OPTIONS', path, **kwargs) def delete(self, path, **kwargs): # type: (str, **Any) -> HTTPResponse return self.request('DELETE', path, **kwargs) def head(self, path, **kwargs): # type: (str, **Any) -> HTTPResponse return self.request('HEAD', path, **kwargs)
def call_api(method: str, path: str, headers: (dict, None) = None, body: str = ""): gateway = LocalGateway(app, Config()) headers = HEADERS if headers is None else {**HEADERS, **headers} return gateway.handle_request(method=method, path=path, headers=headers, body=body)
class SelfContainedForm(unittest.TestCase): def setUp(self): with open(".chalice/config.json") as file: self.lg = LocalGateway( app, Config(chalice_stage="beta", config_from_disk=json.load(file))) body = dict(schema=TEST_SCHEMA) response = self.lg.handle_request( method='POST', path='/centers/{}/forms/new'.format(CENTER_ID), headers={ "authorization": "auth", "Content-Type": "application/json" }, body=json.dumps(body)) self.assertEqual(response['statusCode'], 200, response) body = json.loads(response['body']) self.form = body['res']['form'] self.formId = self.form['id'] def tearDown(self): response = self.lg.handle_request(method='DELETE', path='/forms/{}'.format(self.formId), headers={ "authorization": "auth", }, body='') self.assertEqual(response['statusCode'], 200, response) body = json.loads(response['body']) self.assertEqual(body, { "res": None, "success": True, "action": "delete" }) response = self.lg.handle_request(method='GET', path='/forms/{}/render'.format( self.formId), headers={ "authorization": "auth", }, body='') self.assertEqual(response['statusCode'], 500, response)
def test_can_invoke_function(self): demo = app.Chalice('app-name') @demo.route('/') def index_view(): return {'foo': 'bar'} gateway = LocalGateway(demo, Config()) response = gateway.handle_request('GET', '/', {}, '') body = json.loads(response['body']) assert body['foo'] == 'bar'
class TestApp(TestCase): def setUp(self): self.lg = LocalGateway(app, Config()) def test_get_index(self): response = self.lg.handle_request(method='GET', path='/', headers={}, body='') assert response['statusCode'] == 200 assert json.loads(response['hello']) == 'friend'
class TestApp(unittest.TestCase): def setUp(self): self.gateway = LocalGateway(app, Config()) @mock.patch("app.RankStatistics._load") def test_contains_all(self, mock_statistics_load): mock_statistics_load.return_value = { "PAGE_1": 5, "PAGE_2": 4, "PAGE_3": 7, "PAGE_4": 2 } states = ["PAGE_1", "PAGE_2", "PAGE_3", "PAGE_4", "PAGE_5"] body = {"states": states} response = self.gateway.handle_request( method='POST', path='/order', headers={'Content-Type': 'application/json'}, body=json.dumps(body)) logging.info(response) body = json.loads(response['body']) assert response['statusCode'] == 200 for state in states: assert state in body['order'] @mock.patch("app.write_metric", return_value=None) def test_reward(self, mock_write_metric): body = {"state": "PAGE_3", "reward": 700} response = self.gateway.handle_request( method='POST', path='/metric', headers={'Content-Type': 'application/json'}, body=json.dumps(body)) body = json.loads(response['body']) assert response['statusCode'] == 200 mock_write_metric.assert_called_once()
def test_defaults_timeout_if_needed(self): demo = app.Chalice('app-name') @demo.route('/context') def context_view(): context = demo.lambda_context return { 'remaining': context.get_remaining_time_in_millis(), } disk_config = {} config = Config(chalice_stage='api', config_from_disk=disk_config) gateway = LocalGateway(demo, config) response = gateway.handle_request('GET', '/context', {}, '') body = json.loads(response['body']) assert body['remaining'] <= gateway.MAX_LAMBDA_EXECUTION_TIME * 1000
def test_can_allow_route_with_variables(self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) response = gateway.handle_request( 'GET', '/resource/foobar', {'Authorization': 'allow'}, '') json_body = json.loads(response['body']) assert json_body['resource'] == 'foobar'
class TestUserService(BaseTestCase): """Tests for the Users Service.""" @pytest.fixture(autouse=True) def gateway_factory(self): config = Config() self.gateway = LocalGateway(app, config) def test_signup(self): """Ensure a new user signup resource.""" response = self.gateway.handle_request( method='POST', path='/users/signup', headers={'Content-Type': 'application/json'}, body=json.dumps(new_user)) self.assertEqual(response['statusCode'], 201) def test_bad_signup(self): """Check error handling for bad request.""" response = self.gateway.handle_request( method='POST', path='/users/signup', headers={'Content-Type': 'application/json'}, body=json.dumps(bad_user)) self.assertEqual(response['statusCode'], 400) def test_signup_duplicate_email(self): """Ensure error is thrown if the email already exists.""" response = self.gateway.handle_request( method='POST', path='/users/signup', headers={'Content-Type': 'application/json'}, body=json.dumps(existed_user)) self.assertEqual(response['statusCode'], 409) def test_signin(self): """Ensure signin request works well.""" response = self.gateway.handle_request( method='POST', path='/users/signin', headers={'Content-Type': 'application/json'}, body=json.dumps(existed_user)) self.assertEqual(response['statusCode'], 200) self.assertNotEqual(json.loads(response['body'])['accessToken'], None) def test_bad_signin(self): """Check error handling for bad request.""" response = self.gateway.handle_request( method='POST', path='/users/signin', headers={'Content-Type': 'application/json'}, body=json.dumps(bad_user)) self.assertEqual(response['statusCode'], 400) def test_signout(self): """Ensure signout request works well.""" client = boto3.client('cognito-idp') auth = cognito.generate_auth(existed_user) body = cognito.generate_token(client, auth, existed_user) response = self.gateway.handle_request(method='POST', path='/users/signout', headers={ 'Content-Type': 'application/json', 'Authorization': 'Bearer {0}'.format( body['accessToken']) }, body=json.dumps(bad_user)) self.assertEqual(response['statusCode'], 200)
class TestApp(TestCase): """Test the honeypie app""" def setUp(self): self.lg = LocalGateway(app, Config()) self.google_form_url = 'https://docs.google.com/forms/u/1/d/e/1FAIpQLSfM54cLPNZk4mvMWTtiRWDUi2divL2cCtGG-byj05ttig1iVQ/formResponse' # noqa def test_home(self): response = self.lg.handle_request(method='GET', path='/', headers={}, body='') assert response['statusCode'] == 200 def test_valid_form_success(self): """Test valid payload google form successful""" payload = { 'url': self.google_form_url, 'inputs': { 'entry.505110784': '3', 'entry.1915963433': 'Female', 'entry.948181294': 'Delhi', 'entry.700448681': 'C' } } response = self.lg.handle_request( method='POST', path='/google-forms', headers={'Content-Type': 'application/json'}, body=json.dumps(payload)) assert response['statusCode'] == 200 def test_invalid_form_failure(self): """Test invalid payload google form failure""" payload = { 'url': self.google_form_url, 'inputs': { 'entry.505110784': 'accepts nuber only', 'entry.1915963433': '', 'entry.948181294': '', 'entry.700448681': 'C' } } response = self.lg.handle_request( method='POST', path='/google-forms', headers={'Content-Type': 'application/json'}, body=json.dumps(payload)) assert response['statusCode'] == 422 assert json.loads(response['body']) == { 'errors': 'The given data was invalid.', 'validations': { 'entry.1915963433': 'This is a required question', 'entry.505110784': 'Must be a number', 'entry.948181294': 'This is a required question' } }
class TestPhotoService(BaseTestCase): """Tests for the Photo Service.""" @pytest.fixture(autouse=True) def gateway_factory(self): config = Config() self.gateway = LocalGateway(app, config) @pytest.fixture(autouse=True) def create_token_and_header(self): try: client = boto3.client('cognito-idp') dig = cognito.generate_digest(existed_user) cognito.signup(client, existed_user, dig) auth = cognito.generate_auth(existed_user) body = cognito.generate_token(client, auth, existed_user) self.access_token = body['accessToken'] except client.exceptions.UsernameExistsException as e: # Do nothing pass finally: auth = cognito.generate_auth(existed_user) body = cognito.generate_token(client, auth, existed_user) self.access_token = body['accessToken'] @pytest.fixture(autouse=True) def multipart_encode(self): with open('test_image.jpg', 'rb') as file: base64_image = base64.b64encode(file.read()) upload['base64_image'] = base64_image fields = [(k, v) for k, v in upload.items()] files = [('file', 'test_image.jpg', file)] self.multipart_content_type, self.multipart_body = MultipartFormdataEncoder().encode(fields, files) def test_list(self): """Ensure the /photos/ route behaves correctly.""" response = self.gateway.handle_request( method='GET', path='/photos/', headers={'Content-Type': 'application/json', 'Authorization': 'Bearer {0}'.format(self.access_token)}, body=None) self.assertEqual(response['statusCode'], 200) def test_upload(self): """Ensure the /photos/file behaves correctly.""" response = self.gateway.handle_request( method='POST', path='/photos/file', headers={'Content-Type': self.multipart_content_type, 'Authorization': 'Bearer {0}'.format(self.access_token)}, body=self.multipart_body) self.assertEqual(response['statusCode'], 200) def test_delete(self): """Ensure the /photos/<photo_id> route behaves correctly.""" # 1. upload response = self.gateway.handle_request( method='POST', path='/photos/file', headers={'Content-Type': self.multipart_content_type, 'Authorization': 'Bearer {0}'.format(self.access_token)}, body=self.multipart_body) self.assertEqual(response['statusCode'], 200) photo_id = [item.id for item in Photo.scan(Photo.filename_orig.startswith('test_image.jpg'), limit=1)] # 2. delete response = self.gateway.handle_request( method='DELETE', path='/photos/{}'.format(photo_id[0]), headers={'Content-Type': 'application/json', 'Authorization': 'Bearer {0}'.format(self.access_token)}, body=None) self.assertEqual(response['statusCode'], 200)
def test_can_deny_route_with_variables(self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) with pytest.raises(ForbiddenError): gateway.handle_request( 'GET', '/resource/foobarbaz', {'Authorization': 'allow'}, '')
def test_does_send_500_when_authorizer_returns_none(self, demo_app_auth): gateway = LocalGateway(demo_app_auth, Config()) with pytest.raises(InvalidAuthorizerError): gateway.handle_request( 'GET', '/none', {'Authorization': 'foobarbaz'}, '')
class BaseTestCase(unittest.TestCase): def setUp(self): with open(".chalice/config.json") as file: self.lg = LocalGateway( app, Config(chalice_stage="dev", config_from_disk=json.load(file)) ) def tearDown(self): if hasattr(self, "formId"): self.delete_form(self.formId) Org.objects.delete() def create_form(self, should_create_org=True): if should_create_org: from tests.unit.test_formCreate import create_org create_org(app.get_current_user_id()) response = self.lg.handle_request( method="POST", path="/forms", headers={"authorization": "auth"}, body="" ) self.assertEqual(response["statusCode"], 200, response) body = json.loads(response["body"]) self.assertIn("form", body["res"]) self.assertIn("_id", body["res"]["form"]) self.assertIn("name", body["res"]["form"]) self.assertEqual( {"owner": True}, body["res"]["form"]["cff_permissions"][app.test_user_id] ) self.assertEqual(body["res"]["form"]["version"], 1) DEFAULT_SCHEMA = { "properties": {"name": {"type": "string"}}, "title": "Form", "type": "object", } self.assertEqual(body["res"]["form"]["schema"], DEFAULT_SCHEMA) formId = body["res"]["form"]["_id"]["$oid"] return formId def render_form(self, formId, fail=False): response = self.lg.handle_request( method="GET", path=f"/forms/{formId}", headers={"authorization": "auth"}, body="", ) if fail: self.assertEqual(response["statusCode"], 404, response) return response self.assertEqual(response["statusCode"], 200, response) body = json.loads(response["body"]) return body["res"] def delete_form(self, formId): if not formId: return None response = self.lg.handle_request( method="DELETE", path=f"/forms/{formId}", headers={"authorization": "auth"}, body="", ) self.assertEqual(response["statusCode"], 200, response) body = json.loads(response["body"]) self.assertEqual(body.pop("formId"), formId) self.assertEqual(body, {"res": None, "success": True, "action": "delete"}) return body def edit_form(self, formId, body): response = self.lg.handle_request( method="PATCH", path=f"/forms/{formId}", headers={"authorization": "auth", "Content-Type": "application/json"}, body=json.dumps(body), ) self.assertEqual(response["statusCode"], 200, response) body = json.loads(response["body"]) return body["res"] def set_formOptions(self, formOptions): self.edit_form( self.formId, {"schema": {"a": "B"}, "uiSchema": {"a": "B"}, "formOptions": formOptions}, ) def submit_form(self, formId, formData, responseId=None, submitOptions=None): body = {"data": formData, "responseId": responseId} if submitOptions is not None: body["submitOptions"] = submitOptions response = self.lg.handle_request( method="POST", path=f"/forms/{formId}", headers={"authorization": "auth", "Content-Type": "application/json"}, body=json.dumps(body), ) self.assertEqual(response["statusCode"], 200, response) body = json.loads(response["body"]) responseIdNew = body["res"].pop("responseId", None) if responseId: # Check that response ids are the same after update. self.assertEqual(responseIdNew, responseId) return responseIdNew, body["res"] def view_response(self, responseId): response = self.lg.handle_request( method="GET", path="/responses/{}".format(responseId), headers={"authorization": "auth"}, body="", ) self.assertEqual(response["statusCode"], 200, response) body = json.loads(response["body"]) return body["res"] def set_permissions(self, formId, permissions): body = { "userId": app.get_current_user_id(), "permissions": {p: True for p in permissions} if len(permissions) else {"owner": False}, } response = self.lg.handle_request( method="POST", path=f"/forms/{formId}/permissions", headers={"authorization": "auth", "Content-Type": "application/json"}, body=json.dumps(body), ) self.assertEqual(response["statusCode"], 200, response) body = json.loads(response["body"]) return body["res"]
class TestChaliceApp(unittest.TestCase): def setUp(self): self.chalice_gateway = LocalGateway(app, Config()) def test_invalid_keys(self): body = json.dumps({"crons": "abc", "executions": "5"}) response = self.chalice_gateway.handle_request( method="POST", path="/", headers={"Content-Type": "application/json"}, body=body ) response_body = json.loads(response.get("body")) self.assertNotEqual(response.get("statusCode"), 200) self.assertEqual(response.get("statusCode"), 400) assert "Make sure that JSON contains" in response_body.get("message") @parameterized.expand([ ("2",), ("12",), ("50",), ("69",), ]) def test_get_number_of_iterations(self, input_string): body = json.dumps({"cron": "*/5 * * * *", "executions": input_string}) response = self.chalice_gateway.handle_request( method="POST", path="/", headers={"Content-Type": "application/json"}, body=body ) ranges = json.loads(response.get("body")).get("cron_ranges") self.assertEqual(int(input_string), len(ranges)) @parameterized.expand([ ("102", 100), ("1000", 100), ]) def test_get_number_of_iterations_limit_to_100(self, input_string, expected_ranges): body = json.dumps({"cron": "*/5 * * * *", "executions": input_string}) response = self.chalice_gateway.handle_request( method="POST", path="/", headers={"Content-Type": "application/json"}, body=body ) ranges = json.loads(response.get("body")).get("cron_ranges") self.assertEqual(expected_ranges, len(ranges)) @parameterized.expand([ ("2a",), ("a",), ("",), ("!2",), ("5.?",), ("'",), ]) def test_get_iterations_is_not_a_number(self, input_string): body = json.dumps({"cron": "*/5 * * * *", "executions": input_string}) response = self.chalice_gateway.handle_request( method="POST", path="/", headers={"Content-Type": "application/json"}, body=body ) response_body = json.loads(response.get("body")) assert "must be a number" in response_body.get("message") def test_invalid_json(self): with open("tests/invalid_body.json", "r") as input_file: response = self.chalice_gateway.handle_request( method="POST", path="/", headers={"Content-Type": "application/json"}, body=input_file.read() ) response_body = json.loads(response.get("body")) self.assertEqual(response.get("statusCode"), 400) assert "Malformed JSON" in response_body.get("message")
def do_request(method, path, body, headers): lg = LocalGateway(app, Config(chalice_stage='homolog')) return lg.handle_request(method=method, path=path, headers=headers, body=json.dumps(body))