Ejemplo n.º 1
0
 def test_attributes(self) -> None:
     """
     Checks:
     * All endpoints have `operationId` and `tag` attributes.
     * All example responses match their schema.
     * That no opaque object exists.
     """
     EXCLUDE = ["/real-time"]
     VALID_TAGS = [
         "users",
         "server_and_organizations",
         "authentication",
         "real_time_events",
         "streams",
         "messages",
         "users",
         "webhooks",
     ]
     paths = OpenAPISpec(OPENAPI_SPEC_PATH).openapi()["paths"]
     for path, path_item in paths.items():
         if path in EXCLUDE:
             continue
         for method, operation in path_item.items():
             # Check if every file has an operationId
             assert "operationId" in operation
             assert "tags" in operation
             tag = operation["tags"][0]
             assert tag in VALID_TAGS
             for status_code, response in operation["responses"].items():
                 schema = response["content"]["application/json"]["schema"]
                 if "oneOf" in schema:
                     for subschema_index, subschema in enumerate(
                             schema["oneOf"]):
                         validate_schema(subschema)
                         assert validate_against_openapi_schema(
                             subschema["example"],
                             path,
                             method,
                             status_code + "_" + str(subschema_index),
                         )
                     continue
                 validate_schema(schema)
                 assert validate_against_openapi_schema(
                     schema["example"], path, method, status_code)
Ejemplo n.º 2
0
 def test_attributes(self) -> None:
     EXCLUDE = ["/real-time"]
     VALID_TAGS = ["users", "server_and_organizations", "authentication",
                   "real_time_events", "streams", "messages", "users",
                   "webhooks"]
     openapi_spec = OpenAPISpec(OPENAPI_SPEC_PATH).spec()["paths"]
     for path in openapi_spec:
         if path in EXCLUDE:
             continue
         for method in openapi_spec[path]:
             # Check if every file has an operationId
             assert("operationId" in openapi_spec[path][method])
             assert("tags" in openapi_spec[path][method])
             tag = openapi_spec[path][method]["tags"][0]
             assert(tag in VALID_TAGS)
Ejemplo n.º 3
0
 def test_attributes(self) -> None:
     """
     Checks:
     * All endpoints have `operationId` and `tag` attributes.
     * All example responses match their schema.
     * That no opaque object exists.
     """
     EXCLUDE = ["/real-time", "/register", "/events"]
     VALID_TAGS = [
         "users", "server_and_organizations", "authentication",
         "real_time_events", "streams", "messages", "users", "webhooks"
     ]
     openapi_spec = OpenAPISpec(OPENAPI_SPEC_PATH).spec()["paths"]
     for path in openapi_spec:
         if path in EXCLUDE:
             continue
         for method in openapi_spec[path]:
             # Check if every file has an operationId
             assert ("operationId" in openapi_spec[path][method])
             assert ("tags" in openapi_spec[path][method])
             tag = openapi_spec[path][method]["tags"][0]
             assert (tag in VALID_TAGS)
             for response in openapi_spec[path][method]['responses']:
                 response_schema = (
                     openapi_spec[path][method]['responses'][response]
                     ['content']['application/json']['schema'])
                 if 'oneOf' in response_schema:
                     cnt = 0
                     for entry in response_schema['oneOf']:
                         validate_schema(entry)
                         assert (validate_against_openapi_schema(
                             entry['example'], path, method,
                             response + '_' + str(cnt)))
                         cnt += 1
                     continue
                 validate_schema(response_schema)
                 assert (validate_against_openapi_schema(
                     response_schema['example'], path, method, response))
Ejemplo n.º 4
0
    def test_validate_against_openapi_schema(self) -> None:
        with self.assertRaisesRegex(
                SchemaError,
                r"Additional properties are not allowed \('foo' was unexpected\)"
        ):
            bad_content: Dict[str, object] = {
                "msg": "",
                "result": "success",
                "foo": "bar",
            }
            validate_against_openapi_schema(bad_content, TEST_ENDPOINT,
                                            TEST_METHOD, TEST_RESPONSE_SUCCESS)

        with self.assertRaisesRegex(SchemaError, r"42 is not of type string"):
            bad_content = {
                "msg": 42,
                "result": "success",
            }
            validate_against_openapi_schema(bad_content, TEST_ENDPOINT,
                                            TEST_METHOD, TEST_RESPONSE_SUCCESS)

        with self.assertRaisesRegex(SchemaError,
                                    r"'msg' is a required property"):
            bad_content = {
                "result": "success",
            }
            validate_against_openapi_schema(bad_content, TEST_ENDPOINT,
                                            TEST_METHOD, TEST_RESPONSE_SUCCESS)

        # No exceptions should be raised here.
        good_content = {
            "msg": "",
            "result": "success",
        }
        validate_against_openapi_schema(good_content, TEST_ENDPOINT,
                                        TEST_METHOD, TEST_RESPONSE_SUCCESS)

        # Overwrite the exception list with a mocked one
        test_dict: Dict[str, Any] = {}

        # Check that validate_against_openapi_schema correctly
        # descends into 'deep' objects and arrays.  Test 1 should
        # pass, Test 2 has a 'deep' extraneous key and Test 3 has a
        # 'deep' opaque object. Also the parameters are a heterogeneous
        # mix of arrays and objects to verify that our descent logic
        # correctly gets to the the deeply nested objects.
        test_filename = os.path.join(os.path.dirname(OPENAPI_SPEC_PATH),
                                     "testing.yaml")
        with open(test_filename) as test_file:
            test_dict = yaml.safe_load(test_file)
        with patch("zerver.openapi.openapi.openapi_spec",
                   OpenAPISpec(test_filename)):
            validate_against_openapi_schema(
                {
                    "top_array": [
                        {
                            "obj": {
                                "str3": "test"
                            }
                        },
                        [{
                            "str1": "success",
                            "str2": "success"
                        }],
                    ],
                },
                "/test1",
                "get",
                "200",
            )
            with self.assertRaisesRegex(
                    SchemaError,
                    r"\{'obj': \{'str3': 'test', 'str4': 'extraneous'\}\} is not valid under any of the given schemas",
            ):
                validate_against_openapi_schema(
                    {
                        "top_array": [
                            {
                                "obj": {
                                    "str3": "test",
                                    "str4": "extraneous"
                                }
                            },
                            [{
                                "str1": "success",
                                "str2": "success"
                            }],
                        ],
                    },
                    "/test2",
                    "get",
                    "200",
                )
            with self.assertRaisesRegex(
                    SchemaError,
                    r"additionalProperties needs to be defined for objects to makesure they have no additional properties left to be documented\.",
            ):
                # Checks for opaque objects
                validate_schema(
                    test_dict["paths"]["/test3"]["get"]["responses"]["200"]
                    ["content"]["application/json"]["schema"])