lib/apiScenario/postmanAssertionRules.ts (128 lines of code) (raw):
import { Item } from "postman-collection";
import { StepArmTemplate, StepResponseAssertion, StepRestCall } from "./apiScenarioTypes";
type HttpMethod = "put" | "get" | "post" | "patch" | "delete" | "head" | "option";
type OpenapiType = "Dataplane" | "Management";
type AssertMatchParameter = { item?: Item; step?: StepArmTemplate | StepRestCall; opts?: any };
export type CallType = "lroPolling" | "lroFinalGet" | "stepCall" | "armTemplateCall";
export type AssertionRule = {
name: string;
assertion?: { stepAssertion?: StepResponseAssertion; postmanTestScript?: string[] };
conditions: {
openapiTypes: OpenapiType | OpenapiType[];
httpMethods: HttpMethod | HttpMethod[];
callTypes: CallType | CallType[];
isAsync?: boolean;
match?: (params: AssertMatchParameter) => boolean;
};
};
// RPC-Async-V1-08 Async PATCH should return 202.
const AsyncPatchShouldReturn202: AssertionRule = {
name: "AsyncPatchShouldReturn202",
assertion: { stepAssertion: { 202: {} } },
conditions: {
openapiTypes: "Management",
isAsync: true,
httpMethods: "patch",
callTypes: "stepCall",
},
};
// RPC-Async-V1-09 Async DELETE should return 202.
const AsyncDeleteShouldReturn202: AssertionRule = {
name: "AsyncDeleteShouldReturn202",
assertion: { stepAssertion: { 202: {} } },
conditions: {
openapiTypes: "Management",
isAsync: true,
httpMethods: "delete",
callTypes: "stepCall",
},
};
// RPC-Async-V1-11 Async POST should return 202.
const AsyncPostShouldReturn202: AssertionRule = {
name: "AsyncPostShouldReturn202",
assertion: { stepAssertion: { 202: {} } },
conditions: {
openapiTypes: "Management",
isAsync: true,
httpMethods: "post",
callTypes: "stepCall",
},
};
//RPC-Async-V1-01 Async PUT should return 201/200.
const AsyncPutShouldReturn201: AssertionRule = {
name: "AsyncPutShouldReturn201",
assertion: { stepAssertion: { 201: {}, 200: {} } },
conditions: {
openapiTypes: "Management",
isAsync: true,
httpMethods: "put",
callTypes: "stepCall",
},
};
// RPC-Async-V1-07 Location header must be supported for all async operations that return 202. Azure-AsyncOperation header is optional.
const Async202ResponseShouldIncludeLocationHeader: AssertionRule = {
name: "Async202ResponseShouldIncludeLocationHeader",
assertion: {
postmanTestScript: ['if(pm.response.code === 202) { pm.response.to.have.header("Location");}'],
},
conditions: {
openapiTypes: "Management",
isAsync: true,
httpMethods: ["put", "patch", "post", "delete"],
callTypes: "stepCall",
},
};
const ArmTemplateStatusCodeCheck: AssertionRule = {
name: "ArmTemplateStatusCodeCheck",
assertion: {
postmanTestScript: [
"pm.response.to.be.success;",
'pm.expect(pm.response.json().status).to.be.oneOf(["Succeeded", "Accepted", "Running", "Ready", "Creating", "Created", "Deleting", "Deleted", "Canceled", "Updating"]);',
],
},
conditions: {
openapiTypes: "Management",
httpMethods: "put",
callTypes: "armTemplateCall",
},
};
const DetailResponseLog: AssertionRule = {
name: "DetailResponseLog",
assertion: {
postmanTestScript: ["console.log(pm.response.text());"],
},
conditions: {
openapiTypes: ["Management", "Dataplane"],
httpMethods: ["put", "get", "delete", "patch", "option", "post", "head"],
callTypes: ["armTemplateCall", "lroFinalGet", "lroPolling", "stepCall"],
match: (params: AssertMatchParameter) => {
return params.opts?.verbose === true;
},
},
};
// RPC-Async-V1-06 x-ms-long-running-operation-options should indicate the type of response header to track the async operation.
// Here is for checking the case of final-state-via:azureAsyncOperation.
const AzureAsyncOperationFinalStateCheck: AssertionRule = {
name: "AzureAsyncOperationFinalStateCheck",
assertion: {
stepAssertion: {
"200": [{ test: "/body/properties", expression: "to.be.not.undefined" }],
},
},
conditions: {
openapiTypes: "Management",
httpMethods: ["put"],
callTypes: "lroFinalGet",
match: (params: AssertMatchParameter) => {
const step = params.step;
return (
step?.type === "restCall" &&
step.operation?.["x-ms-long-running-operation-options"]?.["final-state-via"] ===
"azure-async-operation"
);
},
},
};
export const postmanArmRules = [
AsyncPatchShouldReturn202,
AsyncDeleteShouldReturn202,
AsyncPostShouldReturn202,
AsyncPutShouldReturn201,
Async202ResponseShouldIncludeLocationHeader,
ArmTemplateStatusCodeCheck,
AzureAsyncOperationFinalStateCheck,
DetailResponseLog,
];