"""Test JSON schema.""" import copy from unittest.mock import MagicMock from jsonschema import Draft3Validator import pytest from project_manager import config from project_manager.constant import header_const from project_manager.validation import json_schema @pytest.fixture def example_schema(): """Return a JSON Draft3 Schema to use in our validator tests. Returns: schema (dict): JSON Draft3 Validation Schema """ schema = { 'properties': { 'account_type': { 'required': True, 'example': 'vendor', 'description': 'vendor | subaccount', 'type': 'string', 'pattern': '(vendor)|(subaccount)'}, 'account_id': { 'required': True, 'type': 'string', 'pattern': '^\\d+$', 'description': 'vendor_id | subaccount_id'}, 'correlation_id': { 'required': False, 'type': 'string', 'description': 'UUID'}, 'code': { 'type': 'string', 'required': True, 'maxLength': 10} }, 'additionalProperties': False, 'required': True, 'type': 'object', '$schema': 'http://json-schema.org/draft-03/schema' } return schema @pytest.fixture def example_data_to_validate(): """Return a dict that will successfully validate against our example. Returns: data (dict) """ data = { 'correlation_id': '123456678786485', 'account_type': 'vendor', 'account_id': '24', 'code': 'ABC123' } return data def test_raml_header_to_json_schema(): """Test the method that converts RAML parsed headers into JSON schema.""" response = json_schema.raml_header_to_json_schema( config.API_DEFINITION.resources['/project'].methods['post'].headers) properties = response.get('properties') assert properties.get(header_const.CORRELATION_ID).get('type') == 'string' assert properties.get(header_const.CONTENT_TYPE).get('type') == 'string' assert properties.get( header_const.GRASS_ACCOUNT_TYPE).get('type') == 'string' assert properties.get( header_const.GRASS_ACCOUNT_ID).get('type') == 'string' def test_raml_header_to_json_schema_load_draft3_validator(): """Test that the converted RAML to JSON Schema loads. Loads to Draft3Validator and doesn't load any properties set to None. """ schema = json_schema.raml_header_to_json_schema( config.API_DEFINITION.resources['/project'].methods['post'].headers) # we know we didn't set the pattern property of Correlation-Id validator = Draft3Validator(schema) assert validator.schema.get('properties').get('Correlation-Id').\ get('pattern') is None def test_json_schema_filter_input(): """Test json_schema.filter_input filters as expected.""" data = {} data['empty_string_test'] = '' data['whitespace_test'] = ' strip whitespace \n\t ' data = json_schema.filter_input( data=data) assert data['empty_string_test'] is None assert data['whitespace_test'] == 'strip whitespace' def test_json_schema_validate_success( monkeypatch, example_schema, example_data_to_validate): """Test general use case successful validation returns correct format.""" monkeypatch.setattr( json_schema, 'filter_input', value=MagicMock( return_value=example_data_to_validate)) response = json_schema.validate( data=example_data_to_validate, validator=Draft3Validator(example_schema)) assert response.status == 200 assert json_schema.filter_input.called def test_json_schema_validate_error( monkeypatch, example_schema, example_data_to_validate): """Test that the general use case 'fail' validation response is delivered. Our desired response.Response message format { field_name: error_message }. """ mutated_data = copy.copy(example_data_to_validate) mutated_data['account_type'] = 'banana' mutated_data['code'] = '12345678901' mutated_data['unknown_field'] = 'unknown_field_value' monkeypatch.setattr( json_schema, 'filter_input', value=MagicMock( return_value=mutated_data)) response = json_schema.validate( data=mutated_data, validator=Draft3Validator(example_schema)) errors = response.errors.get('message') assert response.status == 400 assert json_schema.filter_input.called assert 'match' in errors.get('account_type') assert 'long' in errors.get('code') assert 'unknown_field' in errors.get('additionalProperties')