cumulocity-cypress
Version:
Cypress commands for Cumulocity IoT
228 lines (227 loc) • 7.35 kB
JavaScript
/// <reference types="cypress" />
// workaround for lodash import in Cypress nodejs typescript runtime and browser
import lodash1 from "lodash";
import * as lodash2 from "lodash";
const _ = lodash1 || lodash2;
export const C8yPactModeValues = [
"record",
"recording",
"apply",
"forward",
"disabled",
"mock",
];
export const C8yPactRecordingModeValues = [
"refresh",
"append",
"new",
"replace",
];
export function isValidPactId(value) {
if (value == null || value.length > 1000 || !_.isString(value))
return false;
const validPactIdRegex = /^[a-zA-Z0-9_-]+(__[a-zA-Z0-9_-]+)*$/;
return validPactIdRegex.test(value);
}
/**
* Creates an C8yPactID for a given string or array of strings.
* @param value The string or array of strings to convert to a pact id.
* @returns The pact id.
*/
export function pactId(value) {
let result = "";
const suiteSeparator = "__";
const normalize = (value) => value
.split(suiteSeparator)
.map((v) => _.words(_.deburr(v), /[a-zA-Z0-9_-]+/g).join("_"))
.join(suiteSeparator);
if (value != null && _.isArray(value)) {
result = value.map((v) => normalize(v)).join(suiteSeparator);
}
else if (value != null && _.isString(value)) {
result = normalize(value);
}
if (result == null || _.isEmpty(result)) {
return !value ? value : undefined;
}
return result;
}
/**
* Validate the given pact mode. Throws an error if the mode is not supported
* or undefined.
* @param mode The pact mode to validate.
*/
export function validatePactMode(mode) {
if (mode != null) {
const values = Object.values(C8yPactModeValues);
if (!_.isString(mode) ||
_.isEmpty(mode) ||
!values.includes(mode.toLowerCase())) {
const error = new Error(`Unsupported pact mode: "${mode}". Supported values are: ${values.join(", ")} or undefined.`);
error.name = "C8yPactError";
throw error;
}
}
}
/**
* Validate the given pact recording mode. Throws an error if the mode is not supported
* or undefined.
* @param mode The pact recording mode to validate.
*/
export function validatePactRecordingMode(mode) {
if (mode != null) {
const keys = Object.values(C8yPactRecordingModeValues);
if (!_.isString(mode) ||
_.isEmpty(mode) ||
!keys.includes(mode.toLowerCase())) {
const error = new Error(`Unsupported recording mode: "${mode}". Supported values are: ${keys.join(", ")} or undefined.`);
error.name = "C8yPactError";
throw error;
}
}
}
/**
* Checks if the given object is a C8yPact. This also includes checking
* all records to be valid C8yPactRecord instances.
*
* @param obj The object to check.
* @returns True if the object is a C8yPact, false otherwise.
*/
export function isPact(obj) {
return (_.isObjectLike(obj) &&
"info" in obj &&
_.isObjectLike(_.get(obj, "info")) &&
"records" in obj &&
_.isArray(_.get(obj, "records")) &&
_.every(_.get(obj, "records"), isPactRecord) &&
_.isFunction(_.get(obj, "nextRecord")) &&
_.isFunction(_.get(obj, "nextRecordMatchingRequest")) &&
_.isFunction(_.get(obj, "appendRecord")) &&
_.isFunction(_.get(obj, "replaceRecord")));
}
/**
* Checks if the given object is a C8yPactRecord.
*
* @param obj The object to check.
* @returns True if the object is a C8yPactRecord, false otherwise.
*/
export function isPactRecord(obj) {
return (_.isObjectLike(obj) &&
"request" in obj &&
_.isObjectLike(_.get(obj, "request")) &&
"response" in obj &&
_.isObjectLike(_.get(obj, "response")) &&
_.isFunction(_.get(obj, "toCypressResponse")));
}
/**
* Checks if the given object is a Cypress.Response.
*
* @param obj The object to check.
* @returns True if the object is a Cypress.Response, false otherwise.
*/
export function isCypressResponse(obj) {
return (_.isObjectLike(obj) &&
"body" in obj &&
"status" in obj &&
"headers" in obj &&
"requestHeaders" in obj &&
"duration" in obj &&
"url" in obj &&
"isOkStatusCode" in obj &&
// not a window.Response or Client.FetchResponse
!("ok" in obj || "arrayBuffer" in obj));
}
/**
* Checks if the given object is a C8yPactError. A C8yPactError is an error
* with the name "C8yPactError".
*
* @param error The object to check.
* @returns True if the object is a C8yPactError, false otherwise.
*/
export function isPactError(error) {
return _.isError(error) && _.get(error, "name") === "C8yPactError";
}
function isDefined(value) {
return !_.isUndefined(value);
}
/**
* Converts a Cypress.Response to a C8yPactRequest.
*/
export function toPactRequest(response) {
if (!response)
return response;
const result = _.pickBy(_.mapKeys(_.pick(response, ["url", "method", "requestHeaders", "requestBody"]), (v, k) => {
if (_.isEqual(k, "requestHeaders"))
return "headers";
if (_.isEqual(k, "requestBody"))
return "body";
return k;
}), isDefined);
if (_.isEmpty(result))
return undefined;
return result;
}
/**
* Converts a Cypress.Response to a C8yPactResponse.
*/
export function toPactResponse(response) {
if (!response)
return response;
const result = _.pickBy(_.pick(response, [
"status",
"statusText",
"body",
"headers",
"duration",
"isOkStatusCode",
"allRequestResponses",
"$body",
]), isDefined);
if (_.isEmpty(result))
return undefined;
return result;
}
/**
* Returns the value of the environment variable with the given name. The function
* tries to find the value in the global `process.env` or `Cypress.env()`. If `env`
* is provided, the function uses the given object as environment.
*
* The function tries to find the value in the following order:
* - `name`
* - `camelCase(name)`
* - `CYPRESS_name`
* - `name.replace(/^C8Y_/i, "")`
* - `CYPRESS_camelCase(name)`
* - `CYPRESS_camelCase(name.replace(/^C8Y_/i, ""))`
*
* @param name The name of the environment variable.
* @param env The environment object to use. Default is `process.env` or `Cypress.env()`
*
* @returns The value of the environment variable or `undefined` if not found.
*/
export function getEnvVar(name, env) {
if (!name)
return undefined;
const e = env ||
(typeof window !== "undefined" && window.Cypress
? Cypress.env()
: process.env);
function getFromEnv(key) {
return e[key];
}
function getForName(name) {
return getFromEnv(name) || getFromEnv(`CYPRESS_${name}`);
}
const plainName = name.replace(/^C8Y_/i, "");
const camelCasedName = _.camelCase(name).replace(/^c8Y/i, "c8y");
const camelCasedPlainName = _.camelCase(plainName);
return (getForName(name) ||
getForName(camelCasedName) ||
getForName(plainName) ||
getForName(camelCasedPlainName));
}
export function isOneOfStrings(value, values) {
if (!_.isString(value) || _.isEmpty(value))
return false;
return values.includes(value.toLowerCase());
}