"""POST /product Schema Validation. What this is testing is essentially the business-level validations that we have codified in our API definition doc for the POST /product endpoint (RAML). This means required fields, types, and maxlengths submitted in the POST body. NOTE: This means that the API documentation is ALSO the machine-readable spec for the API. Changing field definitions will directly affect the business-level logic. For that reason, theses tests will break if the API contract (RAML) is changed. """ import copy import random import string from ows_product_physical.constant import field from ows_product_physical.constant import header from tests.validation.validation_test_utils import get_validation_response from tests.validation.validation_test_utils import parse_data def _random_string(size=16): chars = string.ascii_uppercase + string.digits return ''.join(random.choice(chars) for _ in range(size)) def test_post_product_validate_success(valid_post_header, valid_post_product_data): """Test valid POST header success.""" valid_post_product_data.update({field.COUNTRY_OF_ORIGIN: 3}) response = get_validation_response('/product', 'POST', valid_post_header, valid_post_product_data) assert response.status_code == 200 def test_post_product_validate_header_fail(valid_post_header, valid_post_product_data): """Test invalid POST header fail.""" mutated_header = copy.copy(valid_post_header) mutated_header.pop(header.CONTENT_TYPE) response = get_validation_response('/product', 'POST', mutated_header, valid_post_product_data) assert response.status_code == 400 message = parse_data(response).get('message') assert 'required' in message.get(header.CONTENT_TYPE).get('validator') def test_post_product_validate_required_fields(valid_post_header, valid_post_product_data): """Validate the required fields.""" mutated_product = copy.copy(valid_post_product_data) mutated_product.pop(field.PROJECT_ID) mutated_product.pop(field.PRODUCT_NAME) mutated_product.pop(field.PRODUCT_CODE) mutated_product.pop(field.LABEL) mutated_product.pop(field.PRIMARY_ARTIST) mutated_product.pop(field.GENRE_ID) mutated_product.pop(field.RELEASE_DATE) mutated_product.pop(field.SALE_START_DATE) mutated_product.pop(field.DISTRIBUTION_FORMAT_ID) mutated_product.pop(field.ARTIST_IS_INDIVIDUAL) response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PROJECT_ID in message assert field.PRODUCT_NAME in message assert field.PRODUCT_CODE in message assert field.LABEL in message assert field.PRIMARY_ARTIST in message assert field.GENRE_ID in message assert field.RELEASE_DATE in message assert field.SALE_START_DATE in message assert field.DISTRIBUTION_FORMAT_ID in message assert field.ARTIST_IS_INDIVIDUAL in message required_fields = [ field.PROJECT_ID, field.PRODUCT_NAME, field.PRODUCT_CODE, field.LABEL, field.PRIMARY_ARTIST, field.GENRE_ID, field.RELEASE_DATE, field.SALE_START_DATE, field.DISTRIBUTION_FORMAT_ID, field.ARTIST_IS_INDIVIDUAL] for required_field in required_fields: assert 'required' in message.get( required_field).get('validator') def test_post_product_validate_integer_fields(valid_post_header, valid_post_product_data): """Validate the integer fields.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.PROJECT_ID] = _random_string(5) mutated_product[field.GENRE_ID] = _random_string(5) mutated_product[field.SUBGENRE_ID] = _random_string(5) mutated_product[field.DISTRIBUTION_FORMAT_ID] = _random_string(5) mutated_product[field.PACKAGING_ID] = _random_string(5) mutated_product[field.INITIAL_STOCK] = _random_string(5) mutated_product[field.UNITS_PER_SET] = _random_string(5) mutated_product[field.BOX_LOT] = _random_string(5) response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PROJECT_ID in message assert field.GENRE_ID in message assert field.SUBGENRE_ID in message assert field.DISTRIBUTION_FORMAT_ID in message assert field.PACKAGING_ID in message assert field.INITIAL_STOCK in message assert field.UNITS_PER_SET in message assert field.BOX_LOT in message integer_fields = [ field.PROJECT_ID, field.GENRE_ID, field.SUBGENRE_ID, field.DISTRIBUTION_FORMAT_ID, field.PACKAGING_ID, field.INITIAL_STOCK, field.UNITS_PER_SET, field.BOX_LOT] for integer_field in integer_fields: assert 'type' in message.get( integer_field).get('validator') def test_post_product_validate_maximum_fields(valid_post_header, valid_post_product_data): """Validate the fields with maximum value.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.PRICING] = 10000 mutated_product[field.WHOLESALE_PRICE] = 10000 response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PRICING in message assert message.get(field.PRICING).get('validator') == 'maximum' assert message.get(field.PRICING).get('validator_value') == 9999.99 def test_post_product_validate_minimum_fields(valid_post_header, valid_post_product_data): """Validate the fields with minimum value.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.PRICING] = -0.01 mutated_product[field.WHOLESALE_PRICE] = -0.01 response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PRICING in message assert message.get(field.PRICING).get('validator') == 'minimum' assert message.get(field.PRICING).get('validator_value') == 0 def test_post_product_validate_enum_fields(valid_post_header, valid_post_product_data): """Validate the fields with enum value.""" invalid_post_product_data = valid_post_product_data invalid_post_product_data[field.ARTIST_IS_INDIVIDUAL] = 'yes' invalid_post_product_data[field.EXPLICIT] = 'yes' response = get_validation_response('/product', 'POST', valid_post_header, valid_post_product_data) message = parse_data(response).get('message') assert response.status_code == 400 assert field.ARTIST_IS_INDIVIDUAL in message assert field.EXPLICIT in message assert message.get(field.ARTIST_IS_INDIVIDUAL).get('validator') == 'enum' assert message.get(field.ARTIST_IS_INDIVIDUAL).get( 'validator_value') == ['Y', 'N'] assert message.get(field.EXPLICIT).get('validator') == 'enum' assert message.get(field.EXPLICIT).get('validator_value') == ['Y', 'N'] def test_post_product_validate_number_fields(valid_post_header, valid_post_product_data): """Validate the number fields.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.PRICING] = _random_string(5) mutated_product[field.WHOLESALE_PRICE] = _random_string(5) response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PRICING in message assert message.get(field.PRICING).get('validator') == 'type' assert message.get(field.PRICING).get('validator_value') == 'number' def test_post_product_validate_string_fields(valid_post_header, valid_post_product_data): """Validate the string fields.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.PRODUCT_NAME] = 555 mutated_product[field.PRODUCT_CODE] = 555 mutated_product[field.DISPLAY_UPC] = 555 mutated_product[field.LABEL] = 555 mutated_product[field.VERSION] = 555 mutated_product[field.RELEASE_DATE] = 555 mutated_product[field.SALE_START_DATE] = 555 mutated_product[field.END_DATE] = 555 mutated_product[field.PRODUCT_TYPE] = 555 mutated_product[field.EXCLUSIVE_FOR] = 555 mutated_product[field.SPECIAL_INSTRUCTIONS] = 555 mutated_product[field.PRIMARY_ARTIST] = 555 mutated_product[field.CLINE] = 555 mutated_product[field.DESCRIPTION] = 555 response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PRODUCT_NAME in message assert field.PRODUCT_CODE in message assert field.DISPLAY_UPC in message assert field.LABEL in message assert field.VERSION in message assert field.RELEASE_DATE in message assert field.SALE_START_DATE in message assert field.END_DATE in message assert field.PRODUCT_TYPE in message assert field.EXCLUSIVE_FOR in message assert field.SPECIAL_INSTRUCTIONS in message assert field.PRIMARY_ARTIST in message assert field.CLINE in message assert field.DESCRIPTION in message string_fields = [ field.PRODUCT_NAME, field.PRODUCT_CODE, field.DISPLAY_UPC, field.LABEL, field.VERSION, field.RELEASE_DATE, field.SALE_START_DATE, field.END_DATE, field.PRODUCT_TYPE, field.EXCLUSIVE_FOR, field.SPECIAL_INSTRUCTIONS, field.PRIMARY_ARTIST, field.DESCRIPTION] for string_field in string_fields: assert 'type' in message.get( string_field).get('validator') def test_post_product_validate_pattern_fields(valid_post_header, valid_post_product_data): """Validate the pattern fields.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.PRODUCT_TYPE] = 'Pizza' mutated_product[field.DISPLAY_UPC] = _random_string(13) mutated_product[field.SALE_START_DATE] = '10-13-35' mutated_product[field.RELEASE_DATE] = '2016-13-31' DATE_PATTERN = '^[1-9]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\\d|3[0-1])$' response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PRODUCT_TYPE in message assert field.DISPLAY_UPC in message assert field.SALE_START_DATE in message assert field.RELEASE_DATE in message assert message.get(field.PRODUCT_TYPE).get('validator') == 'pattern' assert message.get(field.SALE_START_DATE).get('validator') == 'pattern' assert message.get(field.RELEASE_DATE).get('validator') == 'pattern' assert message.get(field.DISPLAY_UPC).get('validator') == 'pattern' assert message.get(field.PRODUCT_TYPE).get( 'validator_value') == '^(New|Catalog)$' assert message.get(field.DISPLAY_UPC).get('validator_value') == '^\\d*$' assert message.get(field.SALE_START_DATE).get( 'validator_value') == DATE_PATTERN assert message.get(field.RELEASE_DATE).get( 'validator_value') == DATE_PATTERN def test_post_product_validate_string_max_length(valid_post_header, valid_post_product_data): """Validate the string fields with maxLength value.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.PRODUCT_NAME] = _random_string(256) mutated_product[field.PRODUCT_CODE] = _random_string(15) mutated_product[field.LABEL] = _random_string(71) mutated_product[field.VERSION] = _random_string(256) mutated_product[field.EXCLUSIVE_FOR] = _random_string(129) mutated_product[field.DISPLAY_UPC] = _random_string(14) response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.PRODUCT_NAME in message assert field.PRODUCT_CODE in message assert field.LABEL in message assert field.VERSION in message assert field.EXCLUSIVE_FOR in message assert field.DISPLAY_UPC in message assert message.get(field.EXCLUSIVE_FOR).get('validator') == 'maxLength' assert message.get(field.EXCLUSIVE_FOR).get('validator_value') == 128 assert message.get(field.LABEL).get('validator') == 'maxLength' assert message.get(field.LABEL).get('validator_value') == 70 assert message.get(field.PRODUCT_CODE).get('validator') == 'maxLength' assert message.get(field.PRODUCT_CODE).get('validator_value') == 14 assert message.get(field.PRODUCT_NAME).get('validator') == 'maxLength' assert message.get(field.PRODUCT_NAME).get('validator_value') == 255 assert message.get(field.DISPLAY_UPC).get('validator') == 'maxLength' assert message.get(field.DISPLAY_UPC).get('validator_value') == 13 assert message.get(field.VERSION).get('validator') == 'maxLength' assert message.get(field.VERSION).get('validator_value') == 255 def test_post_product_validate_string_min_length(valid_post_header, valid_post_product_data): """Validate the string fields with minLength value.""" mutated_product = copy.copy(valid_post_product_data) mutated_product[field.DISPLAY_UPC] = _random_string(11) response = get_validation_response('/product', 'POST', valid_post_header, mutated_product) message = parse_data(response).get('message') assert response.status_code == 400 assert field.DISPLAY_UPC in message assert message.get(field.DISPLAY_UPC).get('validator') == 'minLength' assert message.get(field.DISPLAY_UPC).get('validator_value') == 12