fix variable patches (#841)
* fix variable patches * add test case * update changelog * update snapshot
This commit is contained in:
Родитель
f37550d3cb
Коммит
c1996477d6
|
@ -1,6 +1,7 @@
|
|||
# Change Log - oav
|
||||
|
||||
## 07/20/2022 3.0.4
|
||||
|
||||
- GenerateExamples - Support data generation in byte format
|
||||
- ModelValidator - Support data validation in byte format
|
||||
- API Scenario
|
||||
|
@ -8,8 +9,10 @@
|
|||
- Fix step variable unresolved in newman collection
|
||||
- Fix bugs about html report
|
||||
- Aggregate reports into one per scenario file
|
||||
- Fix bug of object variables and patches
|
||||
|
||||
## 07/06/2022 3.0.3
|
||||
|
||||
- Generate high quality examples from API Scenario tests
|
||||
|
||||
## 06/30/2022 3.0.2
|
||||
|
|
|
@ -336,7 +336,7 @@ export class ApiScenarioLoader implements Loader<ScenarioDefinition> {
|
|||
throw new Error("Invalid step");
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to load step ${rawStep.step}: ${(error as any).message}`);
|
||||
throw new Error(`Failed to load step ${JSON.stringify(rawStep)}: ${(error as any).message}`);
|
||||
}
|
||||
|
||||
if (step.outputVariables) {
|
||||
|
@ -381,28 +381,40 @@ export class ApiScenarioLoader implements Loader<ScenarioDefinition> {
|
|||
|
||||
ctx.stepTracking.set(step.step, step);
|
||||
|
||||
const getVariable = (name: string): Variable => {
|
||||
const variable =
|
||||
step.variables[name] ?? ctx.scenario?.variables[name] ?? ctx.scenarioDef.variables[name];
|
||||
if (variable === undefined) {
|
||||
const requiredVariables =
|
||||
ctx.scenario?.requiredVariables ?? ctx.scenarioDef.requiredVariables;
|
||||
if (
|
||||
requiredVariables.includes(name) ||
|
||||
(ctx.scenarioDef.scope === "ResourceGroup" &&
|
||||
["subscriptionId", "resourceGroupName", "location"].indexOf(name) >= 0)
|
||||
) {
|
||||
const getVariable = (
|
||||
name: string,
|
||||
...scopes: Array<VariableScope | undefined>
|
||||
): Variable | undefined => {
|
||||
if (!scopes || scopes.length === 0) {
|
||||
scopes = [step, ctx.scenario, ctx.scenarioDef];
|
||||
}
|
||||
for (const scope of scopes) {
|
||||
if (scope && scope.variables[name]) {
|
||||
return scope.variables[name];
|
||||
}
|
||||
}
|
||||
for (const scope of scopes) {
|
||||
if (scope && scope.requiredVariables.includes(name)) {
|
||||
return {
|
||||
type: "string",
|
||||
value: `$(${name})`,
|
||||
};
|
||||
}
|
||||
}
|
||||
return variable;
|
||||
if (
|
||||
ctx.scenarioDef.scope === "ResourceGroup" &&
|
||||
["subscriptionId", "resourceGroupName", "location"].includes(name)
|
||||
) {
|
||||
return {
|
||||
type: "string",
|
||||
value: `$(${name})`,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const requireVariable = (name: string) => {
|
||||
if (["resourceGroupName"].includes(name)) {
|
||||
if (ctx.scenarioDef.scope === "ResourceGroup" && ["resourceGroupName"].includes(name)) {
|
||||
return;
|
||||
}
|
||||
const requiredVariables =
|
||||
|
@ -441,7 +453,13 @@ export class ApiScenarioLoader implements Loader<ScenarioDefinition> {
|
|||
|
||||
if (value.type === "object" || value.type === "secureObject" || value.type === "array") {
|
||||
if (value.patches) {
|
||||
const obj = cloneDeep(getVariable(name));
|
||||
const variable = ctx.scenario
|
||||
? getVariable(name, ctx.scenario, ctx.scenarioDef)
|
||||
: getVariable(name, ctx.scenarioDef);
|
||||
if (!variable) {
|
||||
throw new Error(`Variable ${name} not found in step ${step.step}`);
|
||||
}
|
||||
const obj = cloneDeep(variable);
|
||||
if (typeof obj !== "object") {
|
||||
// TODO dynamic json patch
|
||||
throw new Error(`Can not Json Patch on ${name}, type of ${typeof obj}`);
|
||||
|
@ -737,6 +755,11 @@ const convertVariables = (rawVariables: RawVariableScope["variables"]) => {
|
|||
if (val.value === undefined && val.prefix === undefined) {
|
||||
result.requiredVariables.push(key);
|
||||
}
|
||||
} else if (
|
||||
(val.type === "object" || val.type === "secureObject" || val.type === "array") &&
|
||||
val.patches !== undefined
|
||||
) {
|
||||
// ok
|
||||
} else {
|
||||
throw new Error(
|
||||
`Only string and secureString type is supported in environment variables, please specify value for: ${key}`
|
||||
|
|
|
@ -37,7 +37,7 @@ export class TemplateGenerator {
|
|||
|
||||
public exampleParameterConvention(
|
||||
step: Pick<StepRestCall, "parameters" | "responses" | "operation">,
|
||||
variables: (name: string) => any,
|
||||
getVariable: (name: string) => any,
|
||||
operation: Operation
|
||||
) {
|
||||
const toMatch: string[] = [];
|
||||
|
@ -45,7 +45,7 @@ export class TemplateGenerator {
|
|||
|
||||
const parameters = cloneDeep(step.parameters);
|
||||
for (const paramName of Object.keys(parameters)) {
|
||||
if (variables(paramName) === undefined) {
|
||||
if (getVariable(paramName) === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -771,6 +771,111 @@ Object {
|
|||
},
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"_scenarioDef": [Circular],
|
||||
"description": "",
|
||||
"requiredVariables": Array [
|
||||
"subscriptionId",
|
||||
"location",
|
||||
],
|
||||
"scenario": "patchVariables",
|
||||
"secretVariables": Array [],
|
||||
"shareScope": true,
|
||||
"steps": Array [
|
||||
Object {
|
||||
"description": undefined,
|
||||
"operation": Object {},
|
||||
"operationId": "StorageAccounts_Create",
|
||||
"outputVariables": Object {},
|
||||
"parameters": Object {
|
||||
"accountName": "$(accountName)",
|
||||
"api-version": "2021-08-01",
|
||||
"parameters": Object {
|
||||
"properties": Object {
|
||||
"kind": "StorageV2",
|
||||
"location": "$(location)",
|
||||
"patches": Array [
|
||||
Object {
|
||||
"add": "/properties/kind",
|
||||
"value": "StorageV2",
|
||||
},
|
||||
],
|
||||
"properties": Object {
|
||||
"encryption": Object {
|
||||
"keySource": "Microsoft.Storage",
|
||||
"services": Object {
|
||||
"blob": Object {},
|
||||
},
|
||||
},
|
||||
},
|
||||
"sku": "Standard",
|
||||
},
|
||||
},
|
||||
"resourceGroupName": "$(resourceGroupName)",
|
||||
"subscriptionId": "$(subscriptionId)",
|
||||
},
|
||||
"requiredVariables": Array [],
|
||||
"responses": Object {},
|
||||
"secretVariables": Array [],
|
||||
"step": "createStorageAccount",
|
||||
"type": "restCall",
|
||||
"variables": Object {
|
||||
"parameters": Object {
|
||||
"type": "object",
|
||||
"value": Object {
|
||||
"properties": Object {
|
||||
"kind": "StorageV2",
|
||||
"location": "$(location)",
|
||||
"patches": Array [
|
||||
Object {
|
||||
"add": "/properties/kind",
|
||||
"value": "StorageV2",
|
||||
},
|
||||
],
|
||||
"properties": Object {
|
||||
"encryption": Object {
|
||||
"keySource": "Microsoft.Storage",
|
||||
"services": Object {
|
||||
"blob": Object {},
|
||||
},
|
||||
},
|
||||
},
|
||||
"sku": "Standard",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"variables": Object {
|
||||
"parameters": Object {
|
||||
"type": "object",
|
||||
"value": Object {
|
||||
"properties": Object {
|
||||
"kind": "StorageV2",
|
||||
"location": "$(location)",
|
||||
"patches": Array [
|
||||
Object {
|
||||
"add": "/properties/kind",
|
||||
"value": "StorageV2",
|
||||
},
|
||||
],
|
||||
"properties": Object {
|
||||
"encryption": Object {
|
||||
"keySource": "Microsoft.Storage",
|
||||
"services": Object {
|
||||
"blob": Object {},
|
||||
},
|
||||
},
|
||||
},
|
||||
"sku": Object {
|
||||
"name": "Standard_LRS",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"scope": "ResourceGroup",
|
||||
"secretVariables": Array [],
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -28,7 +28,7 @@ scenarios:
|
|||
kind: StorageV2
|
||||
location: $(location)
|
||||
properties:
|
||||
encryption: {"services": {"blob": {}}, "keySource": "Microsoft.Storage"}
|
||||
encryption: { "services": { "blob": {} }, "keySource": "Microsoft.Storage" }
|
||||
- scenario: overrideVariable
|
||||
variables:
|
||||
accountName: $(accountName)2
|
||||
|
@ -52,7 +52,7 @@ scenarios:
|
|||
kind: StorageV2
|
||||
location: $(location)
|
||||
properties:
|
||||
encryption: {"services": {"blob": {}}, "keySource": "Microsoft.Storage"}
|
||||
encryption: { "services": { "blob": {} }, "keySource": "Microsoft.Storage" }
|
||||
- scenario: primitiveParameter
|
||||
variables:
|
||||
accountName:
|
||||
|
@ -78,7 +78,7 @@ scenarios:
|
|||
kind: StorageV2
|
||||
location: $(location)
|
||||
properties:
|
||||
encryption: {"services": {"blob": {}}, "keySource": "Microsoft.Storage"}
|
||||
encryption: { "services": { "blob": {} }, "keySource": "Microsoft.Storage" }
|
||||
- step: DeletedAccounts_Get
|
||||
operationId: DeletedAccounts_Get
|
||||
parameters:
|
||||
|
@ -87,3 +87,27 @@ scenarios:
|
|||
deletedAccountName:
|
||||
type: string
|
||||
prefix: foobar
|
||||
- scenario: patchVariables
|
||||
variables:
|
||||
parameters:
|
||||
type: object
|
||||
value:
|
||||
properties:
|
||||
sku:
|
||||
name: Standard_LRS
|
||||
kind: StorageV2
|
||||
location: $(location)
|
||||
properties:
|
||||
encryption: { "services": { "blob": {} }, "keySource": "Microsoft.Storage" }
|
||||
patches:
|
||||
- add: /properties/kind
|
||||
value: StorageV2
|
||||
steps:
|
||||
- step: createStorageAccount
|
||||
operationId: StorageAccounts_Create
|
||||
variables:
|
||||
parameters:
|
||||
type: object
|
||||
patches:
|
||||
- replace: /properties/sku
|
||||
value: Standard
|
||||
|
|
Загрузка…
Ссылка в новой задаче