public async sendRestCallRequest()

in lib/apiScenario/postmanCollectionRunnerClient.ts [552:768]


  public async sendRestCallRequest(
    clientRequest: ApiScenarioClientRequest,
    step: StepRestCall,
    env: VariableEnv
  ): Promise<void> {
    env.resolve();

    const baseUri = convertPostmanFormat(env.tryResolveString(clientRequest.host));

    const { item, itemGroup } = this.addNewItem(
      step.isPrepareStep ? "Prepare" : step.isCleanUpStep ? "CleanUp" : "Scenario",
      {
        name: step.step,
        request: {
          method: clientRequest.method,
          url: clientRequest.path,
          body: clientRequest.body
            ? {
                mode: "raw",
                raw: JSON.stringify(convertPostmanFormat(clientRequest.body), null, 2),
              }
            : clientRequest.formData
            ? {
                mode: "formdata",
                formdata: Object.entries(clientRequest.formData).map(([key, value]) => {
                  if (value.type === "file") {
                    return {
                      key,
                      type: "file",
                      src: this.resolveFilePath(value.value),
                    };
                  } else {
                    return {
                      key,
                      type: value.type,
                      value: value.value,
                    };
                  }
                }),
              }
            : clientRequest.file
            ? {
                mode: "file",
                file: { src: this.resolveFilePath(clientRequest.file) },
              }
            : undefined,
        },
      },
      baseUri
    );

    // pre scripts
    const preScripts: string[] = [];

    if (step.authentication) {
      item.request.auth = this.checkAuthOption(step.authentication, preScripts, env);
    }

    item.description = step.operationId;

    item.request.url = new Url({
      host: this.opts.testProxy ?? baseUri,
      path: covertToPostmanVariable(clientRequest.path, true),
      variable: Object.entries(clientRequest.pathParameters ?? {}).map(([key, value]) => ({
        key,
        value: convertPostmanFormat(value),
      })),
      query: Object.entries(clientRequest.query).map(([key, value]) => ({
        key,
        value: convertPostmanFormat(value)?.toString(),
      })),
    });

    if (clientRequest.body) {
      item.request.addHeader({
        key: "Content-Type",
        value:
          step.operation?.consumes?.[0] ??
          step.operation?._path?._spec?.consumes?.[0] ??
          "application/json",
      });
    }
    Object.entries(clientRequest.headers).forEach(([key, value]) => {
      item.request.addHeader({ key, value: convertPostmanFormat(value) });
    });

    step._resolvedParameters = env.resolveObjectValues(step.parameters);

    if (Object.keys(step.variables).length > 0) {
      Object.entries(step.variables).forEach(([key, value]) =>
        preScripts.push(
          `pm.variables.set("${key}", ${JSON.stringify(env.resolveObjectValues(value.value))});`
        )
      );
    }

    const replaceKey = new Set<string>();
    const jsonLoader = this.opts.jsonLoader;

    const encodeVariable = function (variable: { key?: string | null; value: string | null }) {
      let skipEncode = false;
      step.operation?.parameters?.forEach((p) => {
        p = jsonLoader.resolveRefObj(p);
        if (p.name === variable.key && p.in === "path" && p[xmsSkipUrlEncoding]) {
          skipEncode = true;
        }
      });
      if (skipEncode) {
        return;
      }
      const regex = /\{\{([A-Za-z_$][A-Za-z0-9_]*)\}\}/g;
      const replaceArray: Array<[number, number, string]> = [];
      let match,
        index = variable.value!.length;
      while ((match = regex.exec(variable.value!))) {
        replaceKey.add(match[1]);
        replaceArray.push([match.index, match.index + match[0].length, `{{${match[1]}_encoded}}`]);
        index = match.index + match[0].length;
      }
      replaceArray.push([index, variable.value!.length, ""]);
      let r,
        value = "";
      index = 0;
      while ((r = replaceArray.shift())) {
        value += encodeURIComponent(variable.value!.substring(index, r[0])) + r[2];
        index = r[1];
      }
      variable.value = value;
    };

    item.request.url.variables.each(encodeVariable);
    item.request.url.query.each(encodeVariable);

    replaceKey.forEach((key) => {
      preScripts.push(
        `pm.variables.set("${key}_encoded", encodeURIComponent(pm.variables.get("${key}")));`
      );
    });

    if (preScripts.length > 0) {
      PostmanHelper.addEvent(item.events, "prerequest", preScripts);
    }

    // post scripts
    const postScripts: string[] = [];

    const getOverwriteVariables = () => {
      if (step.outputVariables !== undefined && Object.keys(step.outputVariables).length > 0) {
        const ret = new Map<string, string>();
        for (const k of Object.keys(step.outputVariables)) {
          ret.set(k, step.outputVariables[k].fromResponse);
        }
        return ret;
      }
      return undefined;
    };
    for (const outputName of Object.keys(step.outputVariables ?? {})) {
      env.output(outputName, {
        type: "string",
        value: `{{${outputName}}}`,
      });
    }
    const scriptTypes: PostmanHelper.TestScriptType[] = ["StatusCodeAssertion"];

    if (step.responseAssertion) {
      step.responseAssertion = env.resolveObjectValues(step.responseAssertion);
      scriptTypes.push("ResponseDataAssertion");
    }
    this.generatePostScripts(
      scriptTypes,
      getOverwriteVariables(),
      undefined,
      step.responseAssertion
    ).forEach((s) => postScripts.push(s));

    if (step.operation && step.operation[xmsLongRunningOperation]) {
      const metadata: LroItemMetadata = {
        type: "LRO",
        poller_item_name: `_${item.name}_poller`,
        operationId: step.operation.operationId || "",
        exampleName: step.exampleFile!,
        itemName: item.name,
        step: item.name,
      };
      item.description = JSON.stringify(metadata);

      this.lroPoll(itemGroup!, item, step, clientRequest.host, postScripts);

      // generate final get
      if (step.operation?._method !== "post") {
        itemGroup!.items.add(
          this.generateFinalGetItem(
            item.name,
            baseUri,
            step,
            step.operation._method,
            undefined,
            undefined
          )
        );
      }
    } else {
      const metadata: SimpleItemMetadata = {
        type: "simple",
        operationId: step.operation?.operationId || "",
        exampleName: step.exampleFile!,
        itemName: item.name,
        step: item.name,
      };
      item.description = JSON.stringify(metadata);
    }

    if (postScripts.length > 0) {
      PostmanHelper.addEvent(item.events, "test", postScripts);
    }
    generatePostmanAssertion({ step, type: "stepCall", item, opts: this.opts });
  }