2017-04-13 06:54:39 +03:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
// Licensed under the MIT License. See License.txt in the project root for license information.
|
2018-08-23 23:55:38 +03:00
|
|
|
import * as assert from "assert"
|
2019-03-28 21:47:48 +03:00
|
|
|
import * as globby from "globby"
|
|
|
|
import * as lodash from "lodash"
|
2019-03-09 02:38:37 +03:00
|
|
|
import * as os from "os"
|
|
|
|
import * as path from "path"
|
2018-07-20 01:32:36 +03:00
|
|
|
import { ResponsesObject } from "yasway"
|
2017-04-13 06:54:39 +03:00
|
|
|
|
2019-03-09 02:38:37 +03:00
|
|
|
import * as Constants from "../lib/util/constants"
|
|
|
|
import { LiveValidator } from "../lib/validators/liveValidator"
|
|
|
|
|
2019-09-30 05:47:47 +03:00
|
|
|
const numberOfSpecs = 10
|
2019-03-28 21:47:48 +03:00
|
|
|
jest.setTimeout(150000)
|
2019-03-20 20:46:05 +03:00
|
|
|
|
2018-06-04 23:06:00 +03:00
|
|
|
describe("Live Validator", () => {
|
|
|
|
describe("Initialization", () => {
|
|
|
|
it("should initialize with defaults", () => {
|
|
|
|
const options = {
|
|
|
|
swaggerPaths: [],
|
|
|
|
git: {
|
|
|
|
url: "https://github.com/Azure/azure-rest-api-specs.git",
|
|
|
|
shouldClone: false
|
2017-04-13 09:49:14 +03:00
|
|
|
},
|
2019-03-28 21:47:48 +03:00
|
|
|
directory: path.resolve(os.homedir(), "repo"),
|
|
|
|
isPathCaseSensitive: false
|
2019-03-09 02:38:37 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator()
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.deepStrictEqual(validator.cache, {})
|
|
|
|
assert.deepStrictEqual(validator.options, options)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-06-30 01:30:59 +03:00
|
|
|
it("should initialize with cloning", async () => {
|
|
|
|
const options = {
|
|
|
|
swaggerPaths: [],
|
|
|
|
git: {
|
|
|
|
url: "https://github.com/Azure/oav.git",
|
|
|
|
shouldClone: true
|
|
|
|
},
|
|
|
|
directory: path.resolve(os.homedir(), "repo")
|
2019-03-09 02:38:37 +03:00
|
|
|
}
|
2018-06-30 01:30:59 +03:00
|
|
|
const validator = new LiveValidator(options)
|
|
|
|
await validator.initialize()
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.deepStrictEqual(validator.cache, {})
|
|
|
|
assert.deepStrictEqual(validator.options, options)
|
2018-06-30 01:30:59 +03:00
|
|
|
})
|
|
|
|
it("should initialize without url", () => {
|
|
|
|
const options = {
|
|
|
|
swaggerPaths: [],
|
|
|
|
git: {
|
|
|
|
shouldClone: false
|
|
|
|
},
|
|
|
|
directory: path.resolve(os.homedir(), "repo")
|
2019-03-09 02:38:37 +03:00
|
|
|
}
|
2018-06-30 01:30:59 +03:00
|
|
|
const validator = new LiveValidator(options)
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.deepStrictEqual(validator.cache, {})
|
|
|
|
assert.deepStrictEqual(
|
2019-03-09 02:38:37 +03:00
|
|
|
validator.options.git.url,
|
|
|
|
"https://github.com/Azure/azure-rest-api-specs.git"
|
2018-08-23 23:55:38 +03:00
|
|
|
)
|
2018-06-30 01:30:59 +03:00
|
|
|
})
|
2018-06-04 23:06:00 +03:00
|
|
|
it("should initialize with user provided swaggerPaths", () => {
|
|
|
|
const swaggerPaths = ["swaggerPath1", "swaggerPath2"]
|
|
|
|
const options = {
|
2019-03-28 21:47:48 +03:00
|
|
|
isPathCaseSensitive: false,
|
2019-03-09 02:38:37 +03:00
|
|
|
swaggerPaths,
|
2018-06-04 23:06:00 +03:00
|
|
|
git: {
|
|
|
|
url: "https://github.com/Azure/azure-rest-api-specs.git",
|
|
|
|
shouldClone: false
|
2017-04-13 09:49:14 +03:00
|
|
|
},
|
2018-06-04 23:06:00 +03:00
|
|
|
directory: path.resolve(os.homedir(), "repo")
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2019-03-09 02:38:37 +03:00
|
|
|
const validator = new LiveValidator({ swaggerPaths })
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.deepStrictEqual(validator.cache, {})
|
|
|
|
assert.deepStrictEqual(validator.options, options)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-06-04 23:06:00 +03:00
|
|
|
it("should initialize with user provided swaggerPaths & directory", () => {
|
|
|
|
const swaggerPaths = ["swaggerPath1", "swaggerPath2"]
|
|
|
|
const directory = "/Users/username/repos/"
|
|
|
|
const options = {
|
2019-03-09 02:38:37 +03:00
|
|
|
swaggerPaths,
|
2019-03-28 21:47:48 +03:00
|
|
|
isPathCaseSensitive: false,
|
2018-06-04 23:06:00 +03:00
|
|
|
git: {
|
|
|
|
url: "https://github.com/Azure/azure-rest-api-specs.git",
|
|
|
|
shouldClone: false
|
2017-04-13 09:49:14 +03:00
|
|
|
},
|
2019-03-09 02:38:37 +03:00
|
|
|
directory
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2019-03-09 02:38:37 +03:00
|
|
|
const validator = new LiveValidator({ swaggerPaths, directory })
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.deepStrictEqual(validator.cache, {})
|
|
|
|
assert.deepStrictEqual(validator.options, options)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-06-04 23:06:00 +03:00
|
|
|
it("should initialize with user provided partial git configuration", () => {
|
|
|
|
const swaggerPaths = ["swaggerPath1", "swaggerPath2"]
|
|
|
|
const directory = "/Users/username/repos/"
|
|
|
|
const git = {
|
2019-03-28 21:47:48 +03:00
|
|
|
url: "https://github.com/Azure/azure-rest-api-specs.git",
|
|
|
|
shouldClone: false
|
2017-04-13 09:49:14 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const options = {
|
2019-03-09 02:38:37 +03:00
|
|
|
swaggerPaths,
|
2019-03-28 21:47:48 +03:00
|
|
|
isPathCaseSensitive: false,
|
2018-06-04 23:06:00 +03:00
|
|
|
git: {
|
|
|
|
url: git.url,
|
|
|
|
shouldClone: false
|
2017-04-13 09:49:14 +03:00
|
|
|
},
|
2019-03-09 02:38:37 +03:00
|
|
|
directory
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator({
|
2019-03-09 02:38:37 +03:00
|
|
|
swaggerPaths,
|
|
|
|
directory,
|
|
|
|
git
|
|
|
|
})
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.deepStrictEqual(validator.cache, {})
|
|
|
|
assert.deepStrictEqual(validator.options, options)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-06-04 23:06:00 +03:00
|
|
|
it("should initialize with user provided full git configuration", () => {
|
|
|
|
const swaggerPaths = ["swaggerPath1", "swaggerPath2"]
|
|
|
|
const directory = "/Users/username/repos/"
|
|
|
|
const git = {
|
|
|
|
url: "https://github.com/vladbarosan/azure-rest-api-specs.git",
|
|
|
|
shouldClone: true,
|
|
|
|
branch: "oav-test-branch"
|
2017-04-13 09:49:14 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const options = {
|
2019-03-09 02:38:37 +03:00
|
|
|
swaggerPaths,
|
|
|
|
git,
|
2019-03-28 21:47:48 +03:00
|
|
|
directory,
|
|
|
|
isPathCaseSensitive: false
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator({
|
2019-03-09 02:38:37 +03:00
|
|
|
swaggerPaths,
|
|
|
|
directory,
|
|
|
|
git
|
|
|
|
})
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.deepStrictEqual(validator.cache, {})
|
|
|
|
assert.deepStrictEqual(validator.options, options)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2019-12-05 12:43:14 +03:00
|
|
|
it("should initialize with multiple path patterns", async () => {
|
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/specification",
|
|
|
|
swaggerPathsPattern: [
|
|
|
|
"mediaservices/resource-manager/Microsoft.Media/2015-10-01/media.json",
|
|
|
|
"rpsaas/resource-manager/Microsoft.Contoso/**/*.json"
|
|
|
|
]
|
|
|
|
}
|
|
|
|
const validator = new LiveValidator(options)
|
|
|
|
await validator.initialize()
|
|
|
|
assert.strictEqual(2, Object.keys(validator.cache).length)
|
|
|
|
assert.strictEqual(true, "microsoft.media" in validator.cache)
|
|
|
|
assert.strictEqual(true, "microsoft.contoso" in validator.cache)
|
|
|
|
})
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2017-04-18 01:20:08 +03:00
|
|
|
|
2018-06-04 23:06:00 +03:00
|
|
|
describe("Initialize cache", () => {
|
2018-06-30 01:30:59 +03:00
|
|
|
it("should initialize for arm-mediaservices", async () => {
|
2018-06-04 23:06:00 +03:00
|
|
|
const expectedProvider = "microsoft.media"
|
|
|
|
const expectedApiVersion = "2015-10-01"
|
|
|
|
const options = {
|
2019-04-01 20:59:25 +03:00
|
|
|
directory: "./test/liveValidation/swaggers/specification",
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: [
|
|
|
|
"mediaservices/resource-manager/Microsoft.Media/2015-10-01/media.json"
|
|
|
|
]
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator(options)
|
2018-06-30 01:30:59 +03:00
|
|
|
try {
|
|
|
|
await validator.initialize()
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(true, expectedProvider in validator.cache)
|
2019-04-01 20:59:25 +03:00
|
|
|
assert.strictEqual(1, Object.keys(validator.cache).length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const x = validator.cache[expectedProvider]
|
|
|
|
if (x === undefined) {
|
|
|
|
throw new Error("x === undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(true, expectedApiVersion in x)
|
|
|
|
assert.strictEqual(1, Object.keys(x).length)
|
|
|
|
assert.strictEqual(2, x[expectedApiVersion].get.length)
|
|
|
|
assert.strictEqual(1, x[expectedApiVersion].put.length)
|
|
|
|
assert.strictEqual(1, x[expectedApiVersion].patch.length)
|
|
|
|
assert.strictEqual(1, x[expectedApiVersion].delete.length)
|
|
|
|
assert.strictEqual(4, x[expectedApiVersion].post.length)
|
2018-06-30 01:30:59 +03:00
|
|
|
} catch (err) {
|
2018-05-30 01:38:27 +03:00
|
|
|
assert.ifError(err)
|
2018-06-30 01:30:59 +03:00
|
|
|
}
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-06-30 01:30:59 +03:00
|
|
|
it("should initialize for arm-resources", async () => {
|
2018-06-04 23:06:00 +03:00
|
|
|
const expectedProvider = "microsoft.resources"
|
|
|
|
const expectedApiVersion = "2016-09-01"
|
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/"
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator(options)
|
2018-06-30 01:30:59 +03:00
|
|
|
await validator.initialize()
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(true, expectedProvider in validator.cache)
|
2018-11-17 01:47:04 +03:00
|
|
|
assert.strictEqual(numberOfSpecs, Object.keys(validator.cache).length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const x = validator.cache[expectedProvider]
|
|
|
|
if (x === undefined) {
|
|
|
|
throw new Error("x === undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(true, expectedApiVersion in x)
|
|
|
|
assert.strictEqual(1, Object.keys(x).length)
|
2018-06-30 01:30:59 +03:00
|
|
|
// 'microsoft.resources' -> '2016-09-01'
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(2, x[expectedApiVersion].get.length)
|
|
|
|
assert.strictEqual(1, x[expectedApiVersion].delete.length)
|
|
|
|
assert.strictEqual(3, x[expectedApiVersion].post.length)
|
|
|
|
assert.strictEqual(1, x[expectedApiVersion].head.length)
|
|
|
|
assert.strictEqual(1, x[expectedApiVersion].put.length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const p = validator.cache[Constants.unknownResourceProvider]
|
|
|
|
if (p === undefined) {
|
|
|
|
throw new Error("p === undefined")
|
|
|
|
}
|
2018-06-30 01:30:59 +03:00
|
|
|
// 'microsoft.unknown' -> 'unknown-api-version'
|
2019-03-09 02:38:37 +03:00
|
|
|
assert.strictEqual(4, p[Constants.unknownApiVersion].post.length)
|
|
|
|
assert.strictEqual(11, p[Constants.unknownApiVersion].get.length)
|
|
|
|
assert.strictEqual(3, p[Constants.unknownApiVersion].head.length)
|
|
|
|
assert.strictEqual(5, p[Constants.unknownApiVersion].put.length)
|
|
|
|
assert.strictEqual(5, p[Constants.unknownApiVersion].delete.length)
|
|
|
|
assert.strictEqual(1, p[Constants.unknownApiVersion].patch.length)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-11-17 01:47:04 +03:00
|
|
|
it("should initialize for batch", async () => {
|
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/specification",
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: [
|
2018-11-17 01:47:04 +03:00
|
|
|
"batch/resource-manager/Microsoft.Batch/stable/2017-01-01/BatchManagement.json"
|
2019-12-05 12:43:14 +03:00
|
|
|
]
|
2018-11-17 01:47:04 +03:00
|
|
|
}
|
|
|
|
const validator = new LiveValidator(options)
|
|
|
|
await validator.initialize()
|
|
|
|
assert.notStrictEqual(validator.cache["microsoft.batch"], undefined)
|
|
|
|
})
|
2018-06-30 01:30:59 +03:00
|
|
|
it("should initialize for all swaggers", async () => {
|
2018-06-04 23:06:00 +03:00
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/"
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator(options)
|
2018-06-30 01:30:59 +03:00
|
|
|
await validator.initialize()
|
2018-11-17 01:47:04 +03:00
|
|
|
assert.strictEqual(numberOfSpecs, Object.keys(validator.cache).length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const microsoftResources = validator.cache["microsoft.resources"]
|
|
|
|
if (microsoftResources === undefined) {
|
|
|
|
throw new Error("microsoftResources === undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(2, microsoftResources["2016-09-01"].get.length)
|
|
|
|
assert.strictEqual(1, microsoftResources["2016-09-01"].head.length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const microsoftMedia = validator.cache["microsoft.media"]
|
|
|
|
if (microsoftMedia === undefined) {
|
|
|
|
throw new Error("microsoftMedia === undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(1, microsoftMedia["2015-10-01"].patch.length)
|
|
|
|
assert.strictEqual(4, microsoftMedia["2015-10-01"].post.length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const microsoftSearch = validator.cache["microsoft.search"]
|
|
|
|
if (microsoftSearch === undefined) {
|
|
|
|
throw new Error("microsoftSearch === undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(2, microsoftSearch["2015-02-28"].get.length)
|
|
|
|
assert.strictEqual(3, microsoftSearch["2015-08-19"].get.length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const microsoftStorage = validator.cache["microsoft.storage"]
|
|
|
|
if (microsoftStorage === undefined) {
|
|
|
|
throw new Error("microsoftStorage === undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(1, microsoftStorage["2015-05-01-preview"].patch.length)
|
|
|
|
assert.strictEqual(4, microsoftStorage["2015-06-15"].get.length)
|
|
|
|
assert.strictEqual(3, microsoftStorage["2016-01-01"].post.length)
|
2018-08-17 11:22:53 +03:00
|
|
|
const microsoftTest = validator.cache["microsoft.test"]
|
|
|
|
if (microsoftTest === undefined) {
|
|
|
|
throw new Error("microsoftTest === undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(4, microsoftTest["2016-01-01"].post.length)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
|
|
|
})
|
2017-04-18 01:20:08 +03:00
|
|
|
|
2018-06-04 23:06:00 +03:00
|
|
|
describe("Initialize cache and search", () => {
|
2018-06-30 01:30:59 +03:00
|
|
|
it("should return one matched operation for arm-storage", async () => {
|
2018-06-04 23:06:00 +03:00
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/"
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const listRequestUrl =
|
|
|
|
"https://management.azure.com/" +
|
|
|
|
"subscriptions/subscriptionId/providers/Microsoft.Storage/storageAccounts" +
|
|
|
|
"?api-version=2015-06-15"
|
|
|
|
const postRequestUrl =
|
|
|
|
"https://management.azure.com/" +
|
|
|
|
"subscriptions/subscriptionId/providers/Microsoft.Storage/checkNameAvailability" +
|
|
|
|
"?api-version=2015-06-15"
|
|
|
|
const deleteRequestUrl =
|
|
|
|
"https://management.azure.com/" +
|
|
|
|
"subscriptions/subscriptionId/resourceGroups/myRG/providers/Microsoft.Storage/" +
|
|
|
|
"storageAccounts/accname?api-version=2015-06-15"
|
2019-03-28 21:47:48 +03:00
|
|
|
const validator: any = new LiveValidator(options)
|
2018-06-30 01:30:59 +03:00
|
|
|
await validator.initialize()
|
|
|
|
// Operations to match is StorageAccounts_List
|
2019-10-22 17:55:50 +03:00
|
|
|
let validationInfo = validator.parseValidationRequest(listRequestUrl, "Get", "randomId")
|
|
|
|
let operations = validator.getPotentialOperations(validationInfo).operations
|
2018-06-30 01:30:59 +03:00
|
|
|
let pathObject = operations[0].pathObject
|
|
|
|
if (pathObject === undefined) {
|
|
|
|
throw new Error("pathObject is undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(1, operations.length)
|
|
|
|
assert.strictEqual(
|
2018-06-30 01:30:59 +03:00
|
|
|
"/subscriptions/{subscriptionId}/providers/Microsoft.Storage/storageAccounts",
|
2019-03-09 02:38:37 +03:00
|
|
|
pathObject.path
|
|
|
|
)
|
2017-04-13 09:42:48 +03:00
|
|
|
|
2018-06-30 01:30:59 +03:00
|
|
|
// Operations to match is StorageAccounts_CheckNameAvailability
|
2019-10-22 17:55:50 +03:00
|
|
|
validationInfo = validator.parseValidationRequest(postRequestUrl, "PoSt", "randomId")
|
|
|
|
operations = validator.getPotentialOperations(validationInfo).operations
|
2018-06-30 01:30:59 +03:00
|
|
|
pathObject = operations[0].pathObject
|
|
|
|
if (pathObject === undefined) {
|
|
|
|
throw new Error("pathObject is undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(1, operations.length)
|
|
|
|
assert.strictEqual(
|
2018-06-30 01:30:59 +03:00
|
|
|
"/subscriptions/{subscriptionId}/providers/Microsoft.Storage/checkNameAvailability",
|
2019-03-09 02:38:37 +03:00
|
|
|
pathObject.path
|
|
|
|
)
|
2017-04-13 09:42:48 +03:00
|
|
|
|
2018-06-30 01:30:59 +03:00
|
|
|
// Operations to match is StorageAccounts_Delete
|
2019-10-22 17:55:50 +03:00
|
|
|
validationInfo = validator.parseValidationRequest(deleteRequestUrl, "Delete", "randomId")
|
|
|
|
operations = validator.getPotentialOperations(validationInfo).operations
|
2018-06-30 01:30:59 +03:00
|
|
|
pathObject = operations[0].pathObject
|
|
|
|
if (pathObject === undefined) {
|
|
|
|
throw new Error("pathObject is undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(1, operations.length)
|
|
|
|
assert.strictEqual(
|
2018-06-30 01:30:59 +03:00
|
|
|
"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/" +
|
|
|
|
"Microsoft.Storage/storageAccounts/{accountName}",
|
2019-03-09 02:38:37 +03:00
|
|
|
pathObject.path
|
|
|
|
)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-06-09 02:35:55 +03:00
|
|
|
it("should return reason for not matched operations", async () => {
|
2018-06-04 23:06:00 +03:00
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/"
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const nonCachedApiUrl =
|
|
|
|
"https://management.azure.com/" +
|
|
|
|
"subscriptions/subscriptionId/providers/Microsoft.Storage/storageAccounts" +
|
|
|
|
"?api-version=2015-08-15"
|
|
|
|
const nonCachedProviderUrl =
|
|
|
|
"https://management.azure.com/" +
|
|
|
|
"subscriptions/subscriptionId/providers/Hello.World/checkNameAvailability" +
|
|
|
|
"?api-version=2015-06-15"
|
|
|
|
const nonCachedVerbUrl =
|
|
|
|
"https://management.azure.com/" +
|
|
|
|
"subscriptions/subscriptionId/resourceGroups/myRG/providers/Microsoft.Storage/" +
|
|
|
|
"storageAccounts/accname?api-version=2015-06-15"
|
|
|
|
const nonCachedPath =
|
|
|
|
"https://management.azure.com/" +
|
|
|
|
"subscriptions/subscriptionId/providers/Microsoft.Storage/storageAccounts/accountName/" +
|
|
|
|
"properties?api-version=2015-06-15"
|
2019-03-28 21:47:48 +03:00
|
|
|
const validator: any = new LiveValidator(options)
|
2018-06-09 02:35:55 +03:00
|
|
|
await validator.initialize()
|
|
|
|
// Operations to match is StorageAccounts_List with api-version 2015-08-15
|
|
|
|
// [non cached api version]
|
2019-10-22 17:55:50 +03:00
|
|
|
let validationInfo = validator.parseValidationRequest(nonCachedApiUrl, "Get", "randomId")
|
|
|
|
let result = validator.getPotentialOperations(validationInfo)
|
2018-06-09 02:35:55 +03:00
|
|
|
let operations = result.operations
|
|
|
|
let reason = result.reason
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(0, operations.length)
|
2018-06-09 02:35:55 +03:00
|
|
|
if (reason === undefined) {
|
|
|
|
throw new Error("reason is undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(Constants.ErrorCodes.OperationNotFoundInCacheWithApi.name, reason.code)
|
2017-04-18 01:20:08 +03:00
|
|
|
|
2018-06-09 02:35:55 +03:00
|
|
|
// Operations to match is StorageAccounts_CheckNameAvailability with provider "Hello.World"
|
|
|
|
// [non cached provider]
|
2019-10-22 17:55:50 +03:00
|
|
|
validationInfo = validator.parseValidationRequest(nonCachedProviderUrl, "PoSt", "randomId")
|
|
|
|
result = validator.getPotentialOperations(validationInfo)
|
2018-06-09 02:35:55 +03:00
|
|
|
operations = result.operations
|
|
|
|
reason = result.reason
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(0, operations.length)
|
2018-06-09 02:35:55 +03:00
|
|
|
if (reason === undefined) {
|
|
|
|
throw new Error("reason is undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(
|
|
|
|
Constants.ErrorCodes.OperationNotFoundInCacheWithProvider.name,
|
|
|
|
reason.code
|
|
|
|
)
|
2017-04-18 01:20:08 +03:00
|
|
|
|
2018-06-09 02:35:55 +03:00
|
|
|
// Operations to match is StorageAccounts_Delete with verb "head" [non cached http verb]
|
2019-10-22 17:55:50 +03:00
|
|
|
validationInfo = validator.parseValidationRequest(nonCachedVerbUrl, "head", "randomId")
|
|
|
|
result = validator.getPotentialOperations(validationInfo)
|
2018-06-09 02:35:55 +03:00
|
|
|
operations = result.operations
|
|
|
|
reason = result.reason
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(0, operations.length)
|
2018-06-09 02:35:55 +03:00
|
|
|
if (reason === undefined) {
|
|
|
|
throw new Error("reason is undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(Constants.ErrorCodes.OperationNotFoundInCacheWithVerb.name, reason.code)
|
2017-04-18 01:20:08 +03:00
|
|
|
|
2018-06-09 02:35:55 +03:00
|
|
|
// Operations to match is with path
|
|
|
|
// "subscriptions/subscriptionId/providers/Microsoft.Storage/" +
|
|
|
|
// "storageAccounts/storageAccounts/accountName/properties/"
|
|
|
|
// [non cached path]
|
2019-10-22 17:55:50 +03:00
|
|
|
validationInfo = validator.parseValidationRequest(nonCachedPath, "get", "randomId")
|
|
|
|
result = validator.getPotentialOperations(validationInfo)
|
2018-06-09 02:35:55 +03:00
|
|
|
operations = result.operations
|
|
|
|
reason = result.reason
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(0, operations.length)
|
2018-06-09 02:35:55 +03:00
|
|
|
if (reason === undefined) {
|
|
|
|
throw new Error("reason is undefined")
|
|
|
|
}
|
2018-08-23 23:55:38 +03:00
|
|
|
assert.strictEqual(Constants.ErrorCodes.OperationNotFoundInCache.name, reason.code)
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
2018-12-07 03:11:21 +03:00
|
|
|
it("it shouldn't create an implicit default response", async () => {
|
2018-06-04 23:06:00 +03:00
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/specification/scenarios",
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: ["**/*.json"],
|
2018-06-04 23:06:00 +03:00
|
|
|
shouldModelImplicitDefaultResponse: true
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator(options)
|
2018-06-30 01:30:59 +03:00
|
|
|
await validator.initialize()
|
2018-08-17 11:22:53 +03:00
|
|
|
const microsoftTest = validator.cache["microsoft.test"]
|
|
|
|
if (microsoftTest === undefined) {
|
|
|
|
throw new Error("microsoftTest === undefined")
|
|
|
|
}
|
2018-06-30 01:30:59 +03:00
|
|
|
// Operations to match is StorageAccounts_List
|
2018-08-17 11:22:53 +03:00
|
|
|
const operations = microsoftTest["2016-01-01"].post
|
2018-03-16 00:53:01 +03:00
|
|
|
|
2018-06-30 01:30:59 +03:00
|
|
|
for (const operation of operations) {
|
2018-07-20 01:32:36 +03:00
|
|
|
const responses = operation.responses as ResponsesObject
|
2018-12-07 03:11:21 +03:00
|
|
|
assert.strictEqual(responses.default, undefined)
|
2018-06-30 01:30:59 +03:00
|
|
|
}
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
|
|
|
})
|
2017-04-18 01:20:08 +03:00
|
|
|
|
2018-06-04 23:06:00 +03:00
|
|
|
describe("Initialize cache and validate", () => {
|
2019-03-28 21:47:48 +03:00
|
|
|
const livePaths = globby.sync(
|
|
|
|
path.join(__dirname, "test/liveValidation/swaggers/**/live/*.json")
|
|
|
|
)
|
2018-08-13 22:16:26 +03:00
|
|
|
livePaths.forEach(livePath => {
|
2018-06-30 01:30:59 +03:00
|
|
|
it(`should validate request and response for "${livePath}"`, async () => {
|
2018-06-04 23:06:00 +03:00
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/specification/storage",
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: ["**/*.json"]
|
2018-05-30 01:38:27 +03:00
|
|
|
}
|
2018-06-04 23:06:00 +03:00
|
|
|
const validator = new LiveValidator(options)
|
2018-06-30 01:30:59 +03:00
|
|
|
await validator.initialize()
|
|
|
|
const reqRes = require(livePath)
|
|
|
|
const validationResult = validator.validateLiveRequestResponse(reqRes)
|
2018-11-16 04:04:07 +03:00
|
|
|
assert.notStrictEqual(validationResult, undefined)
|
2018-06-30 01:30:59 +03:00
|
|
|
/* tslint:disable-next-line */
|
2018-11-16 04:04:07 +03:00
|
|
|
// console.dir(validationResult, { depth: null, colors: true })
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
|
|
|
})
|
2018-12-08 02:04:17 +03:00
|
|
|
it("should initialize for defaultErrorOnly and fail on unknown status code", async () => {
|
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/specification/defaultIsErrorOnly",
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: ["test.json"]
|
2018-12-08 02:04:17 +03:00
|
|
|
}
|
|
|
|
const validator = new LiveValidator(options)
|
|
|
|
await validator.initialize()
|
|
|
|
const result = validator.validateLiveRequestResponse({
|
|
|
|
liveRequest: {
|
|
|
|
url: "https://xxx.com/providers/someprovider?api-version=2018-01-01",
|
|
|
|
method: "get",
|
|
|
|
headers: {
|
2019-03-09 02:38:37 +03:00
|
|
|
"content-type": "application/json"
|
2018-12-08 02:04:17 +03:00
|
|
|
},
|
|
|
|
query: {
|
|
|
|
"api-version": "2016-01-01"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
liveResponse: {
|
|
|
|
statusCode: "300",
|
|
|
|
headers: {
|
|
|
|
"content-Type": "application/json"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
const errors = result.responseValidationResult.errors
|
|
|
|
if (errors === undefined) {
|
|
|
|
throw new Error("errors === undefined")
|
|
|
|
}
|
|
|
|
assert.strictEqual((errors[0] as any).code, "INVALID_RESPONSE_CODE")
|
|
|
|
})
|
2019-11-21 10:26:44 +03:00
|
|
|
|
|
|
|
// should be case insensitive for api version
|
|
|
|
it("should be case-insensitive for resource provider and API version", async () => {
|
|
|
|
const options = {
|
|
|
|
directory:
|
|
|
|
"./test/liveValidation/swaggers/specification/storage/resource-manager/Microsoft.Storage/2015-05-01-preview",
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: ["*.json"]
|
2019-11-21 10:26:44 +03:00
|
|
|
}
|
|
|
|
// Upper and lowercased provider and api-version strings for testing purpose
|
|
|
|
const adjustedUrl =
|
|
|
|
"/subscriptions/rs/resourceGroups/rsg/providers/MICROsoft.stoRAGE/storageAccounts/test?api-version=2015-05-01-PREVIEW"
|
|
|
|
const validator = new LiveValidator(options)
|
|
|
|
await validator.initialize()
|
|
|
|
const result = validator.validateLiveRequestResponse({
|
|
|
|
liveRequest: {
|
|
|
|
url: adjustedUrl,
|
|
|
|
method: "get",
|
|
|
|
headers: {
|
|
|
|
"content-type": "application/json"
|
|
|
|
},
|
|
|
|
query: {
|
|
|
|
"api-version": "2015-05-01-PREVIEW"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
liveResponse: {
|
|
|
|
statusCode: "200",
|
|
|
|
headers: {
|
|
|
|
"content-type": "application/json"
|
|
|
|
},
|
|
|
|
body: {
|
|
|
|
location: "testLocation",
|
|
|
|
properties: {
|
|
|
|
creationTime: "2017-05-24T13:28:53.4540398Z",
|
|
|
|
primaryEndpoints: {
|
|
|
|
blob: "https://random.blob.core.windows.net/",
|
|
|
|
queue: "https://random.queue.core.windows.net/",
|
|
|
|
table: "https://random.table.core.windows.net/"
|
|
|
|
},
|
|
|
|
accountType: "Standard_LRS",
|
|
|
|
primaryLocation: "eastus2euap",
|
|
|
|
provisioningState: "Succeeded",
|
|
|
|
secondaryLocation: "centraluseuap",
|
|
|
|
statusOfPrimary: "Available",
|
|
|
|
statusOfSecondary: "Available"
|
|
|
|
},
|
|
|
|
type: "Microsoft.Storage/storageAccounts"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
// Should be able to find Microsoft.Storage with 2015-05-01-preview api version succesfully
|
|
|
|
const errors = result.responseValidationResult.errors
|
|
|
|
assert.deepStrictEqual(errors, [])
|
|
|
|
assert.equal(result.responseValidationResult.isSuccessful, true)
|
|
|
|
assert.equal(typeof result.responseValidationResult.runtimeException, "undefined")
|
|
|
|
})
|
|
|
|
|
2018-12-08 02:04:17 +03:00
|
|
|
it("should initialize for defaultErrorOnly and pass", async () => {
|
|
|
|
const options = {
|
|
|
|
directory: "./test/liveValidation/swaggers/specification/defaultIsErrorOnly",
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: ["test.json"]
|
2018-12-08 02:04:17 +03:00
|
|
|
}
|
|
|
|
const validator = new LiveValidator(options)
|
|
|
|
await validator.initialize()
|
|
|
|
const result = validator.validateLiveRequestResponse({
|
|
|
|
liveRequest: {
|
|
|
|
url: "https://xxx.com/providers/someprovider?api-version=2018-01-01",
|
|
|
|
method: "get",
|
|
|
|
headers: {
|
2019-03-09 02:38:37 +03:00
|
|
|
"content-type": "application/json"
|
2018-12-08 02:04:17 +03:00
|
|
|
},
|
|
|
|
query: {
|
|
|
|
"api-version": "2016-01-01"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
liveResponse: {
|
|
|
|
statusCode: "404",
|
|
|
|
headers: {
|
|
|
|
"content-Type": "application/json"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
const errors = result.responseValidationResult.errors
|
|
|
|
assert.deepStrictEqual(errors, [])
|
|
|
|
})
|
2018-05-30 01:38:27 +03:00
|
|
|
})
|
|
|
|
})
|
2019-03-28 21:47:48 +03:00
|
|
|
describe("Live validator snapshot validation", () => {
|
|
|
|
let validator: LiveValidator
|
2019-04-01 20:59:25 +03:00
|
|
|
let validatorOneOf: LiveValidator
|
2019-03-28 21:47:48 +03:00
|
|
|
const errors = [
|
|
|
|
"OBJECT_MISSING_REQUIRED_PROPERTY",
|
|
|
|
"OBJECT_ADDITIONAL_PROPERTIES",
|
2019-04-11 07:22:59 +03:00
|
|
|
"MISSING_REQUIRED_PARAMETER",
|
2019-03-28 21:47:48 +03:00
|
|
|
"MAX_LENGTH",
|
|
|
|
"INVALID_FORMAT",
|
|
|
|
"INVALID_TYPE",
|
|
|
|
"ENUM_MISMATCH",
|
2019-10-12 11:41:58 +03:00
|
|
|
"ENUM_CASE_MISMATCH",
|
2019-11-04 09:45:27 +03:00
|
|
|
"SECRET_PROPERTY",
|
|
|
|
"WRITEONLY_PROPERTY_NOT_ALLOWED_IN_RESPONSE"
|
2019-03-28 21:47:48 +03:00
|
|
|
]
|
|
|
|
beforeAll(async () => {
|
|
|
|
const options = {
|
|
|
|
directory: `${__dirname}/liveValidation/swaggers/`,
|
|
|
|
isPathCaseSensitive: false,
|
|
|
|
useRelativeSourceLocationUrl: true,
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: [
|
|
|
|
"specification\\apimanagement\\resource-manager\\Microsoft.ApiManagement\\preview\\2018-01-01\\*.json"
|
|
|
|
],
|
2019-03-28 21:47:48 +03:00
|
|
|
git: {
|
|
|
|
shouldClone: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
validator = new LiveValidator(options)
|
|
|
|
await validator.initialize()
|
2019-12-05 12:43:14 +03:00
|
|
|
options.swaggerPathsPattern = [
|
2019-04-01 20:59:25 +03:00
|
|
|
"specification\\mediaservices\\resource-manager\\Microsoft.Media\\2018-07-01\\*.json"
|
2019-12-05 12:43:14 +03:00
|
|
|
]
|
2019-04-01 20:59:25 +03:00
|
|
|
validatorOneOf = new LiveValidator(options)
|
|
|
|
await validatorOneOf.initialize()
|
2019-03-28 21:47:48 +03:00
|
|
|
}, 100000)
|
|
|
|
|
|
|
|
test(`should return no errors for valid input`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/valid_input.json`)
|
|
|
|
const validationResult = validator.validateLiveRequestResponse(payload)
|
|
|
|
expect(validationResult).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
2019-09-30 05:47:47 +03:00
|
|
|
test(`should return expected error for unresolvable reference`, async () => {
|
|
|
|
const options = {
|
|
|
|
directory: `${__dirname}/liveValidation/swaggers/`,
|
|
|
|
isPathCaseSensitive: false,
|
|
|
|
useRelativeSourceLocationUrl: true,
|
2019-12-05 12:43:14 +03:00
|
|
|
swaggerPathsPattern: [
|
|
|
|
"specification\\rpsaas\\resource-manager\\Microsoft.Contoso\\stable\\2019-01-01\\*.json"
|
|
|
|
],
|
2019-09-30 05:47:47 +03:00
|
|
|
git: {
|
|
|
|
shouldClone: false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const liveValidator = new LiveValidator(options)
|
|
|
|
await liveValidator.initialize()
|
|
|
|
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/unresolvableReference_input.json`)
|
|
|
|
const result = liveValidator.validateLiveRequest(payload.input.request, {
|
|
|
|
includeErrors: ["UNRESOLVABLE_REFERENCE"]
|
|
|
|
})
|
|
|
|
expect(result.isSuccessful === false)
|
|
|
|
expect(result.errors[0].code === "UNRESOLVABLE_REFERENCE")
|
|
|
|
})
|
|
|
|
|
2019-03-28 21:47:48 +03:00
|
|
|
errors.forEach(error => {
|
|
|
|
test(`should return the expected error requestResponse validation for ${error}`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/${lodash.camelCase(
|
|
|
|
error
|
|
|
|
)}_input.json`)
|
|
|
|
const validationResult = validator.validateLiveRequestResponse(payload)
|
|
|
|
expect(validationResult).toMatchSnapshot()
|
|
|
|
})
|
|
|
|
|
|
|
|
test(`should match pair validation with response request validation for ${error}`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/${lodash.camelCase(
|
|
|
|
error
|
|
|
|
)}_input.json`)
|
|
|
|
const validationResult = validator.validateLiveRequestResponse(payload)
|
|
|
|
const requestValidationResult = validator.validateLiveRequest(payload.liveRequest)
|
|
|
|
const responseValidationResult = validator.validateLiveResponse(payload.liveResponse, {
|
|
|
|
url: payload.liveRequest.url,
|
|
|
|
method: payload.liveRequest.method
|
|
|
|
})
|
|
|
|
expect(validationResult.requestValidationResult).toStrictEqual(requestValidationResult)
|
|
|
|
expect(validationResult.responseValidationResult).toStrictEqual(responseValidationResult)
|
|
|
|
})
|
|
|
|
})
|
2019-04-01 20:59:25 +03:00
|
|
|
test(`should match for one of missing`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/oneOfMissing_input.json`)
|
|
|
|
const result = validatorOneOf.validateLiveRequestResponse(payload)
|
|
|
|
expect(result).toMatchSnapshot()
|
|
|
|
})
|
2019-03-29 21:12:10 +03:00
|
|
|
test(`should return all errors for no options`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/multipleErrors_input.json`)
|
|
|
|
const result = validator.validateLiveRequestResponse(payload)
|
|
|
|
expect(result.responseValidationResult.errors.length === 3)
|
|
|
|
expect(result.responseValidationResult.errors.some(err => err.code === "INVALID_TYPE"))
|
|
|
|
expect(result.responseValidationResult.errors.some(err => err.code === "INVALID_FORMAT"))
|
|
|
|
expect(
|
|
|
|
result.responseValidationResult.errors.some(
|
|
|
|
err => err.code === "OBJECT_ADDITIONAL_PROPERTIES"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
})
|
2019-04-11 07:22:59 +03:00
|
|
|
test(`should match all errors for no options`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/multipleErrors_input.json`)
|
|
|
|
const result = validator.validateLiveRequestResponse(payload)
|
|
|
|
expect(result).toMatchSnapshot()
|
|
|
|
})
|
2019-03-29 21:12:10 +03:00
|
|
|
test(`should return all errors for empty includeErrors list`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/multipleErrors_input.json`)
|
|
|
|
const result = validator.validateLiveRequestResponse(payload, { includeErrors: [] })
|
|
|
|
expect(result.responseValidationResult.errors.length === 3)
|
|
|
|
expect(result.responseValidationResult.errors.some(err => err.code === "INVALID_TYPE"))
|
|
|
|
expect(result.responseValidationResult.errors.some(err => err.code === "INVALID_FORMAT"))
|
|
|
|
expect(
|
|
|
|
result.responseValidationResult.errors.some(
|
|
|
|
err => err.code === "OBJECT_ADDITIONAL_PROPERTIES"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
test(`should return only errors specified in the list`, async () => {
|
|
|
|
const payload = require(`${__dirname}/liveValidation/payloads/multipleErrors_input.json`)
|
|
|
|
const result = validator.validateLiveRequestResponse(payload, {
|
|
|
|
includeErrors: ["INVALID_TYPE"]
|
|
|
|
})
|
|
|
|
expect(result.responseValidationResult.errors.length === 1)
|
|
|
|
expect(result.responseValidationResult.errors[0].code === "INVALID_TYPE")
|
|
|
|
})
|
2019-03-28 21:47:48 +03:00
|
|
|
})
|