@krisinc/node-rest-assured

Test framework for automating rest api & JS & typescript!

Usage no npm install needed!

<script type="module">
  import krisincNodeRestAssured from 'https://cdn.skypack.dev/@krisinc/node-rest-assured';
</script>

README

Node-Rest-Assured

  • Even non JavaScript developers can understand this simple library

Upcoming features

  • testrail integrations https://www.npmjs.com/package/testrail-integration

  • New JSON response utils to validate search filters

  • Fetching Server timestamps based on TimeZone

  • More handy json validations(ex: sorting ,date,limit, offset validations etc) for search filters(any GET calls) without writing asserts

Highlights

  • This API automation tool designed to support API automation like other tools Postman, RestAssured and Karate
  • It supports CommonJS, ES6 and TypeScript
  • It supports Cucumber, Mocha and other frameworks as well
  • API Developers can use for Unit and Pact testing
  • We can externalize JSON request and response files, easy to maintain test data
  • Pretty easy to validate JSON responses
  • Best feature, Chai asserts are supported implicitly for json response validations
  • Easy to find json paths and node values like https://jsonpath.com/
  • This tool helps integration testing with webui , mobile and other applications
  • It helps API integration (example : to automate combination of promo, tax and price services) testing as well.
  • Can send json request body as file and string
  • Include or exclude parameters from the request body for the negative testing
  • Dynamic parameters can be applied on json objects
  • Can send full json response as file for complete json schema validations
  • Https API
  • Promise API
  • Handled exceptions internally
  • Easy to use Request API's with basic knowledge of javascript and typescript
  • Going to add more utils for json validation to meet API's functionality
  • it supports fixtures similar to https://www.npmjs.com/package/fixtures
  • Actively maintained

Extra features: Chai asserts supported implicitly for json response validations Passing request body as json file , full json response validation as file for complete schema validations. It supports json path validations

|json path|value| |username| myname| using exact path : example: |json path|value| |data[*].username| myname|

Easy way of automation

Please refer GITHUB link JSDOC and sample code(CRUD operations) which helps you how framework supports json validations

Simple GET call for test

 const { prettyPrintJSON } = require("@krisinc/node-rest-assured");

 const response = await makeHttpRequest("https://gorest.co.in/public-api/users");
      console.log(prettyPrintJSON(JSON.parse(response.body)));

making request of api end point Same method can be used for GET(Default), PUT,POST, PATCH, DELETE

const { prettyPrintJSON } = require("@krisinc/node-rest-assured");

(async () => {
        const inputbody = `{"username: "firstname", "lastname" : "lst" }`;
        const headerOptions: string = JSON.stringify({"Authorization": authToken});
        const response = makeHttpRequest(url, JSON.parse(headerOptions), "POST", inputbody);
        console.log(${jsonValidationUtils.prettyPrintJSON(response.body)});
        //=> '<!doctype html> ...'
})();

FormData , uploading file to S3

const { prettyPrintJSON } = require("@krisinc/node-rest-assured");
import * as fs from "fs";

(async () => {
        const url: string = baseapiurl.toString() + urlParams;
             const headerOptions: string = JSON.stringify({"Authorization": authToken});
             const formDataMap: Map<string, any> = new Map<string, any> ();
             formDataMap.set(key, fs.createReadStream(value));
             response = await makeHttpRequestWithFormData(url, JSON.parse(headerOptions), "POST", formDataMap);
             const responseBody = JSON.parse(response.body);
             logger.info(() => `File Upload Response: ${jsonValidationUtils.prettyPrintJSON(responseBody)}`);
})();

ACCESS_TOKEN generation where sending request body as string

replacing dynamic values {username} if when sending username and password from env or config see github example

  /*world is like global variable in cucumberjs, you can initialize to local or global variables
  whichever  supports for other frameworks like Mocha */
      const inputbody = "{
            \"grant_type\": \"password\",
          \"username\": \"{username}\",
          \"password\": \"{password}\",
          }";

      const urlparams = urlparams.replace("denim_default", realmID);
      const url: string = baseidmurl + urlparams;
      let requestBody: string = inputbody.replace("{username}", idmUsername);
      requestBody = requestBody.replace("{password}", decodedPassword);
      const headerOptions: string = JSON.stringify({"Content-Type": "application/x-www-form-urlencoded"});
      response = await makeHttpRequest(url, JSON.parse(headerOptions), "POST", requestBody, true);
      logger.info(() => `Status code is: ${JSON.stringify(response.body)}`);
      world.responseBody = JSON.parse(response.body);
      const authenticationToken: string[] = await jsonValidationUtils.findNodeValue(world.responseBody,
          "access_token"); //access_token is a node name(json path parameter) from the JSON response"
      // world is global variable in cucumberjs, so you can store token global variable or file however you want it
      world.accessTokenConstants.authToken = "Bearer " + authenticationToken.toString();
      logger.info(() => `Access token is: ${world.accessTokenConstants.authToken}`);
      world.accessTokenConstants.statusCode = response.statusCode.toString();

ACCESS_TOKEN generation where request body sending it as a file

const url: string = baseidmurl + urlParams;
//json file path ./accessToken/accessTokenRequest.json
  const accessTokenRequest = await jsonValidationUtils.readJson("./accessToken/accessTokenRequest.json");
  let requestBody: string = JSON.stringify(accessTokenRequest).replace("{username}", idmUsername);
  requestBody = requestBody.replace("{password}", decodedPassword);
  logger.info(() => `Url is: ${baseidmurl}`);
  const headerOptions: string = JSON.stringify({"Content-Type": "application/x-www-form-urlencoded"});
  response = await makeHttpRequest(url, JSON.parse(headerOptions), "POST", requestBody, true);
  logger.info(() => `Status code is: ${JSON.stringify(response.body)}`);
  world.responseBody = JSON.parse(response.body);
  const authenticationToken: string[] = await jsonValidationUtils.findNodeValue(world.responseBody,
      "access_token");
  world.accessTokenConstants.authToken = "Bearer " + authenticationToken.toString();
  logger.info(() => `Access token is: ${world.accessTokenConstants.authToken}`);

one more method "makeHttpRequestWithProxy" to send request with proxy

/**
 * This method used to making http request
 * @param {string} url - form full url including path parameters if applicable
 * @param {object} headerOptions - pass header values
 * @param {string} HttpMethod - GET, POST , PUT, PATCH , DELETE etc , GET is default
 * @param {string} inputBody - json string
 * @param {boolean} formFlag - default false
 */

method
export async function makeHttpRequest(url: string, headerOptions?: object,
                                      HttpMethod?: string, inputBody?: string, formFlag?: boolean): Promise<object> {
                                      }


/**
 * This method used to make http request for FormData
 * @param {string} url - form full url including path parameters if applicable
 * @param {object} headerOptions - pass header values
 * @param {string} HttpMethod - GET, POST , PUT, PATCH , DELETE etc , GET is default
 * @param {Map<string, any>} formDataMap - json string
 * @returns {Promise<object>}
 */

export async function makeHttpRequestWithFormData(url: string, headerOptions?: object,
                                                  HttpMethod?: string,
                                                  formDataMap?: Map<string, any>): Promise<object> { }

/**
 * This method used to making http request
 * @param {string} url - form full url including path parameters if applicable
 * @param {string} _localHost - proxy server
 * @param {number} _port - port number
 * @param {object} headerOptions - pass header values
 * @param {string} HttpMethod - GET, POST , PUT, PATCH , DELETE etc , GET is default
 * @param {string} inputBody - json string
 * @param {boolean} formFlag - default false
 */

export async function makeHttpRequestWithProxy(url: string, _localHost: string, _port: number, _headerOptions?: object,
                                      HttpMethod?: string, inputBody?: string, formFlag?: boolean): Promise<object> { }

findNodeByName

(async) findNodeByName(jsonData, nodename) This method used to find the parent node by name , it returns json paths associated with json key. This helps to find json path for given node.

const { prettyPrintJSON, jsonValidationUtils } = require("@krisinc/node-rest-assured");

  const jsonfilepath = "./userresponse.json";
  const jsonfileobject = await jsonValidationUtils.readJsonToObject(jsonfilepath);
  const jsonpaths: string[] = await jsonValidationUtils.findNodeByName(jsonfileobject, "username");

Find Node Value

(async) findNodeValue(jsonData, nodename) This method used to find the parent node value by node name

 response = await makeHttpRequest(url, JSON.parse(headerOptions), "POST", resultString);
    world.responseBody = JSON.parse(response.body);
    logger.info(() => `Post Response is: ${jsonValidationUtils.prettyPrintJSON(world.responseBody)}`);
    const userid = await jsonValidationUtils.findNodeValue(world.responseBody, "id"); // it returns string array
//sometimes will be having multiple id's(with same node name) for user , security roles and external id's
// Better to give exact path, users[*].id or if index is fixed users[0].id

Fixtures

/*
Ex: users.json
{
    "my_own_user": {
      "name": "Charles",
      "type": "M"
    },
    "female": {
      "name": "Susana",
      "type": "F"
    }
  } */
const userdata = await jsonValidationUtils.readJson("./users.json");
const username: string[] = await jsonValidationUtils.findNodeValue(userdata,
    "my_own_user.name");
logger.info(username[0]);

Please download JS DOCS folder from GITHUB and refer global.html

createJsonResponseObjectFromMap

deepCompareOfJsonObjects

excludeFirstRowAndValidateJsonPathFollowedByParentIndex

excludeFirstRowFromTableAndValidateJsonPath

excludeHeadersAndPostRequestParametersFromDataTable

findNodeByName

findNodeValue

invalidJsonPathWithRegularExpression

invalidJsonPathWithRegularExpressionForMap

iterateNestedObects

makeHttpRequest

makeHttpRequestWithFormData

makeHttpRequestWithProxy

postJsonObjectRequestFromMap

postRequestParametersAsFile

postRequestParametersFromDataTable

postRequestParametersFromMap

prettyPrintJSON

readJson

readJsonToObject

readJsonToString

replaceJsonPathFollowedByParentIndex

validateJsonDataTableFollowedByParentIndex

validateJsonMapFollowedByParentIndex

validateJsonPathWithRegularExpression

validateJsonResponseFile

validJsonPathWithRegularExpressionForMap

Link

https://www.npmjs.com/package/cucumberjs-rest-assured

More documentation will be added Please refer github links for code snippets , these methods can be used for mocha and other frameworks as well Please contact in case any issues or support: letautomate@gmail.com , let.automate@gmail.com Please raise any issues that needs to be addressed

License

Please see LICENSE.md.