Repository: Yelp/swagger_spec_validator

Issue:
Spec validation will not fail if items is not present and type is array
The following specs are not valid according to [Swagger 2.0 Specs](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#parameter-object), editor.swagger.io and according to `swagger-tools` npm package.
```yaml
swagger: '2.0'
info:
  title: Example
produces:
- application/json
paths:
  /test:
    get:
      responses:
        '200':
          description: HTTP200
          schema:
            type: array
```

Error reported by editor.swagger.io
![https://image.ibb.co/ghkioJ/5186391944200192.png](https://image.ibb.co/ghkioJ/5186391944200192.png)

Error reported by npm
```
API Errors:

  #/paths/~1test/get/responses/200/schema: Missing required property: items

1 error and 0 warnings
```

Discussion:

Patch:
diff --git a/swagger_spec_validator/validator20.py b/swagger_spec_validator/validator20.py
index fe17ded..002eb44 100644
--- a/swagger_spec_validator/validator20.py
+++ b/swagger_spec_validator/validator20.py
@@ -268,6 +268,15 @@ def validate_defaults_in_definition(definition_spec, deref):
         validate_property_default(property_spec, deref)
 
 
+def validate_arrays_in_definition(definition_spec, def_name=None):
+    if definition_spec.get('type') == 'array' and 'items' not in definition_spec:
+        raise SwaggerValidationError(
+            'Definition of type array must define `items` property{}.'.format(
+                '' if not def_name else ' (definition {})'.format(def_name),
+            ),
+        )
+
+
 def validate_definition(definition, deref, def_name=None):
     definition = deref(definition)
 
@@ -286,6 +295,7 @@ def validate_definition(definition, deref, def_name=None):
             )
 
         validate_defaults_in_definition(definition, deref)
+        validate_arrays_in_definition(definition, def_name=def_name)
 
     if 'discriminator' in definition:
         required_props, not_required_props = get_collapsed_properties_type_mappings(definition, deref)


Test patch:
diff --git a/tests/validator20/validate_definitions_test.py b/tests/validator20/validate_definitions_test.py
index 0b61dc0..6c2b6aa 100644
--- a/tests/validator20/validate_definitions_test.py
+++ b/tests/validator20/validate_definitions_test.py
@@ -95,3 +95,30 @@ def test_api_check_default_fails(property_spec, validator, instance):
     validation_error = excinfo.value.args[1]
     assert validation_error.instance == instance
     assert validation_error.validator == validator
+
+
+def test_type_array_with_items_succeed_validation():
+    definitions = {
+        'definition_1': {
+            'type': 'array',
+            'items': {
+                'type': 'string',
+            },
+        },
+    }
+
+    # Success if no exception are raised
+    validate_definitions(definitions, lambda x: x)
+
+
+def test_type_array_without_items_succeed_fails():
+    definitions = {
+        'definition_1': {
+            'type': 'array',
+        },
+    }
+
+    with pytest.raises(SwaggerValidationError) as excinfo:
+        validate_definitions(definitions, lambda x: x)
+
+    assert str(excinfo.value) == 'Definition of type array must define `items` property (definition definition_1).'
diff --git a/tests/validator20/validate_spec_test.py b/tests/validator20/validate_spec_test.py
index 5bc9e53..981255c 100644
--- a/tests/validator20/validate_spec_test.py
+++ b/tests/validator20/validate_spec_test.py
@@ -341,3 +341,37 @@ def test_failure_because_references_in_operation_responses():
         validate_spec(invalid_spec)
     assert 'GET /endpoint does not have a valid responses section. ' \
            'That section cannot be just a reference to another object.' in str(excinfo.value)
+
+
+def test_type_array_with_items_succeed_validation(minimal_swagger_dict):
+    minimal_swagger_dict['definitions'] = {
+        'definition_1': {
+            'type': 'array',
+            'items': {
+                'type': 'string',
+            },
+        },
+    }
+
+    # Success if no exception are raised
+    validate_spec(minimal_swagger_dict)
+
+
+@pytest.mark.parametrize(
+    'swagger_dict_override',
+    (
+        {
+            'definitions': {
+                'definition_1': {
+                    'type': 'array',
+                },
+            },
+        },
+    )
+)
+def test_type_array_without_items_succeed_fails(minimal_swagger_dict, swagger_dict_override):
+    minimal_swagger_dict.update(swagger_dict_override)
+    with pytest.raises(SwaggerValidationError) as excinfo:
+        validate_spec(minimal_swagger_dict)
+
+    assert str(excinfo.value) == 'Definition of type array must define `items` property (definition definition_1).'