2017-11-21 23:43:53 +03:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
|
|
|
|
2020-11-24 06:07:36 +03:00
|
|
|
import assert from "assert";
|
|
|
|
import * as constants from "../lib/util/constants";
|
|
|
|
import * as validate from "../lib/validate";
|
2019-01-09 02:03:51 +03:00
|
|
|
|
2020-11-24 06:07:36 +03:00
|
|
|
const testPath = __dirname;
|
2018-06-04 23:06:00 +03:00
|
|
|
|
|
|
|
describe("Semantic validation", () => {
|
2021-10-19 10:14:33 +03:00
|
|
|
describe("loadSwagger", () => {
|
|
|
|
// JSON_PARSING_ERROR
|
|
|
|
it("should fail when validating a JSON file which cannot be parsed successfully", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/loadSwagger/JSON_PARSING_ERROR.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].code,
|
|
|
|
constants.ErrorCodes.JsonParsingError.name
|
|
|
|
);
|
|
|
|
});
|
|
|
|
// UNRESOLVABLE_REFERENCE
|
|
|
|
it("should fail when validating a swagger with unresolvable reference", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateSwaggerSchema/UNRESOLVABLE_REFERENCE.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "UNRESOLVABLE_REFERENCE");
|
|
|
|
});
|
|
|
|
it("should validate correctly when the spec contains an x-ms-parameterized-host", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/parameterizedhost/face.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
// console.dir(result, { depth: null })
|
|
|
|
assert(
|
|
|
|
result.validityStatus === true,
|
|
|
|
`swagger "${specPath}" contains semantic validation errors.`
|
|
|
|
);
|
|
|
|
});
|
|
|
|
it("should validate correctly when the spec does not contain a definitions section", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/definitions/definitions.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
// console.dir(result, { depth: null })
|
|
|
|
assert(
|
|
|
|
result.validityStatus === true,
|
|
|
|
`swagger "${specPath}" contains semantic validation errors.`
|
|
|
|
);
|
|
|
|
});
|
|
|
|
it("should fail when validating a swagger with invalid internal reference", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/invalidReference/searchindex.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
});
|
2020-11-24 06:07:36 +03:00
|
|
|
});
|
2018-01-12 04:17:09 +03:00
|
|
|
|
2021-10-19 10:14:33 +03:00
|
|
|
describe("internalErrors", () => {
|
|
|
|
// internalErrors: INTERNAL_ERROR
|
|
|
|
it("should fail when validating a swagger with internal error", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateSwaggerSchema/internalErrors/INTERNAL_ERROR.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].code,
|
|
|
|
constants.ErrorCodes.InternalError.name
|
|
|
|
);
|
|
|
|
});
|
2020-11-24 06:07:36 +03:00
|
|
|
});
|
2018-12-03 22:15:31 +03:00
|
|
|
|
2021-10-19 10:14:33 +03:00
|
|
|
describe("validateSwaggerSchema", () => {
|
|
|
|
// OBJECT_ADDITIONAL_PROPERTIES
|
|
|
|
it("should fail when adding properties not allowed", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateSwaggerSchema/AddPropertiesNotAllowed.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "OBJECT_ADDITIONAL_PROPERTIES");
|
|
|
|
});
|
|
|
|
// ARRAY_UNIQUE
|
|
|
|
it("should fail when have array which items are not unique", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateSwaggerSchema/ARRAY_UNIQUE.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "ARRAY_UNIQUE");
|
|
|
|
});
|
|
|
|
// ENUM_MISMATCH
|
|
|
|
it("should fail when validating a swagger with No enum match error", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateSwaggerSchema/ENUM_MISMATCH.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "ENUM_MISMATCH");
|
|
|
|
});
|
2020-11-24 06:07:36 +03:00
|
|
|
});
|
2019-07-17 04:54:55 +03:00
|
|
|
|
2021-10-19 10:14:33 +03:00
|
|
|
describe("validateCompile", () => {
|
|
|
|
// INTERNAL_ERROR
|
|
|
|
it("should fail when cannot compile validator on operation", async () => {
|
2021-10-20 08:42:57 +03:00
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateCompile/Compile-INTERNAL_ERROR.json`;
|
2021-10-19 10:14:33 +03:00
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "INTERNAL_ERROR");
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].message.slice(0, 40),
|
|
|
|
"Failed to compile validator on operation"
|
|
|
|
);
|
|
|
|
});
|
2020-11-24 06:07:36 +03:00
|
|
|
});
|
2019-07-17 04:54:55 +03:00
|
|
|
|
2021-10-19 10:14:33 +03:00
|
|
|
describe("validateDiscriminator", () => {
|
|
|
|
// DISCRIMINATOR_NOT_REQUIRED
|
|
|
|
it("should fail when discriminator is not a required property", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/discriminator/notRequiredDiscriminator.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "DISCRIMINATOR_NOT_REQUIRED");
|
|
|
|
});
|
|
|
|
// OBJECT_MISSING_REQUIRED_PROPERTY_DEFINITION
|
|
|
|
it("should fail when missing required property in definition", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/discriminator/OBJECT_MISSING_REQUIRED_PROPERTY_DEFINITION.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].code,
|
|
|
|
"OBJECT_MISSING_REQUIRED_PROPERTY_DEFINITION"
|
|
|
|
);
|
|
|
|
});
|
2021-11-04 11:50:39 +03:00
|
|
|
// DISCRIMINATOR_PROPERTY_TYPE_NOT_STRING
|
|
|
|
it("should fail when discriminator property type is not string", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/discriminator/DISCRIMINATOR_PROPERTY_TYPE_NOT_STRING.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].code,
|
|
|
|
"DISCRIMINATOR_PROPERTY_TYPE_NOT_STRING"
|
|
|
|
);
|
|
|
|
});
|
2020-11-24 06:07:36 +03:00
|
|
|
});
|
2020-03-19 15:56:08 +03:00
|
|
|
|
2021-10-19 10:14:33 +03:00
|
|
|
describe("validateSchemaRequiredProperties", () => {
|
|
|
|
// OBJECT_MISSING_REQUIRED_PROPERTY_SCHEMA
|
|
|
|
it("should fail when validating a swagger with missing required property", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateSchemaRequiredProperties/OBJECT_MISSING_REQUIRED_PROPERTY_SCHEMA.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].code,
|
|
|
|
"OBJECT_MISSING_REQUIRED_PROPERTY_SCHEMA"
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("validateOperation", () => {
|
|
|
|
// EMPTY_PATH_PARAMETER_DECLARATION
|
|
|
|
it("should fail when has empty path parameter declaration", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/EMPTY_PATH_PARAMETER_DECLARATION.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "EMPTY_PATH_PARAMETER_DECLARATION");
|
|
|
|
});
|
|
|
|
// EQUIVALENT_PATH
|
|
|
|
it("should fail when equivalent path already exists", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/EQUIVALENT_PATH.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "EQUIVALENT_PATH");
|
|
|
|
});
|
|
|
|
// DUPLICATE_OPERATIONID
|
|
|
|
it("should fail when has multiple operations with the same operationId", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/DUPLICATE_OPERATIONID.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "DUPLICATE_OPERATIONID");
|
|
|
|
});
|
|
|
|
// DUPLICATE_PARAMETER
|
|
|
|
it("should fail when operation has duplicate parameters", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/DUPLICATE_PARAMETER.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "DUPLICATE_PARAMETER");
|
|
|
|
});
|
|
|
|
// MULTIPLE_BODY_PARAMETERS
|
|
|
|
it("should fail when operation has multiple body parameters", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/MULTIPLE_BODY_PARAMETERS.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "MULTIPLE_BODY_PARAMETERS");
|
|
|
|
});
|
|
|
|
// INVALID_PARAMETER_COMBINATION
|
|
|
|
it("should fail when operation has a body parameter and a formData parameter", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/INVALID_PARAMETER_COMBINATION.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
2021-10-20 08:42:57 +03:00
|
|
|
assert.strictEqual(result.validateSpec?.errors?.[0].code, "INVALID_PARAMETER_COMBINATION");
|
2021-10-19 10:14:33 +03:00
|
|
|
});
|
|
|
|
// MISSING_PATH_PARAMETER_DECLARATION
|
|
|
|
it("should fail when path parameter is defined but is not declared", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/MISSING_PATH_PARAMETER_DECLARATION.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].code,
|
|
|
|
"MISSING_PATH_PARAMETER_DECLARATION"
|
|
|
|
);
|
|
|
|
});
|
|
|
|
// MISSING_PATH_PARAMETER_DEFINITION
|
|
|
|
it("should fail when path parameter is declared but is not defined", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/validateOperation/MISSING_PATH_PARAMETER_DEFINITION.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === false);
|
|
|
|
assert.strictEqual(
|
|
|
|
result.validateSpec?.errors?.[0].code,
|
|
|
|
"MISSING_PATH_PARAMETER_DEFINITION"
|
|
|
|
);
|
|
|
|
});
|
|
|
|
it("should succeed when discriminator is not a required property and the error is suppressed", async () => {
|
|
|
|
const specPath = `${testPath}/semanticValidation/specification/discriminator/notRequiredDiscriminatorWithSuppression.json`;
|
|
|
|
const result = await validate.validateSpec(specPath, undefined);
|
|
|
|
assert(result.validityStatus === true);
|
|
|
|
});
|
2020-11-24 06:07:36 +03:00
|
|
|
});
|
|
|
|
});
|