Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FCS] Setter/Getter Code Refactoring #147

Merged
merged 19 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions cypress/support/constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module.exports = {
ALPHANUMERIC: 'alphanumeric',
API_NAME: 'apiName',
API_VERSION: 'apiVersion',
APP: 'App',
APP_HISTORY_EMPTY: 'App history is empty',
APP_ID: 'appId',
APP_LIFECYCLE_HISTORY: 'appLifeCycleHistory',
Expand Down Expand Up @@ -96,6 +97,7 @@ module.exports = {
ERROR: 'error',
ERROR_CONTENT_JSON_PATH: 'objects/errorObjects/errorContent.json',
ERROR_CONTENT_OBJECTS_PATH: 'cypress/fixtures/objects/errorObjects/errorContent.json',
ERROR_CONTENT_VALIDATIONJSON: 'errorContentValidationJson',
ERROR_EXPECTED: 'Expected response.error not to be null',
ERROR_EXPECTED_DEFINED: 'Expected response.error to be defined',
ERROR_EXPECTED_NULL: 'Expected response.error to be null',
Expand Down Expand Up @@ -297,8 +299,7 @@ module.exports = {
PARAMS: 'Params',
PASS: 'PASS',
PASSWORD: 'password',
PLATFORM_INVALID_RESPONSE_LOG:
'Platform returned response in invalid format, which could lead to failures in validations. Response must be an object',
PLATFORM: 'Platform',
PLATFORM_NOT_SUPPORT_LOG: 'Platform does not support method',
PLATFORM_NOT_TRIGGER_EVENT: 'Platform MUST not trigger event ',
PLATFORM_TRIGGER_EVENT: 'Platform MUST trigger event ',
Expand Down Expand Up @@ -331,6 +332,8 @@ module.exports = {
},
PERFORMANCE_METRICS: 'performanceMetrics',
RESPONSE: 'Response: ',
RESPONSE_INVALID_RESPONSE_LOG:
'Platform or App returned response in invalid format, which could lead to failures in validations. Response must be in JSON RPC format',
RESPONSE_NOT_FOUND: 'No_Response',
RESPONSE_STATUS: {
OK: 'OK',
Expand Down
292 changes: 292 additions & 0 deletions cypress/support/cypress-commands/commands.js
Abhishk123 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const CONSTANTS = require('../constants/constants');
const { _ } = Cypress;
import UTILS, { getEnvVariable } from '../cypress-support/src/utils';
const logger = require('../Logger')('command.js');
import { apiObject, eventObject } from '../appObjectConfigs';

/**
* @module commands
Expand Down Expand Up @@ -833,3 +834,294 @@ Cypress.Commands.add('clearCache', () => {
cy.clearAllSessionStorage();
cy.reload(true);
});


Cypress.Commands.add('sendMessageToPlatformOrApp', (target, additionalParams, task) => {
const { method, params, context, action, expected, appId } = additionalParams;
task = task ? task : CONSTANTS.TASK.CALLMETHOD;
let isNotSupportedApi = false;

if (UTILS.isScenarioExempted(method, params)) {
isNotSupportedApi = true;
Cypress.env(CONSTANTS.IS_SCENARIO_EXEMPTED, true);
}

cy.then(() => {
if (target === CONSTANTS.APP) {
const additionalParams = {
communicationMode: UTILS.getCommunicationMode(),
action: action,
isNotSupportedApi: isNotSupportedApi,
};
const methodKey = task == CONSTANTS.TASK.REGISTEREVENT ? CONSTANTS.EVENT : CONSTANTS.METHOD;
const paramKey = task == CONSTANTS.TASK.REGISTEREVENT ? 'params' : 'methodParams';

const requestParams = { [methodKey]: method, [paramKey]: params };

// Creating intent message using above details to send it to 3rd party app.
const intentMessage = UTILS.createIntentMessage(task, requestParams, additionalParams);

// Adding additional details to created intent if any platform specific data is present in configModule.
cy.runIntentAddon(task, intentMessage).then((parsedIntent) => {
const requestTopic = UTILS.getTopic(appId);
const responseTopic = UTILS.getTopic(appId, CONSTANTS.SUBSCRIBE);
cy.sendMessagetoApp(requestTopic, responseTopic, parsedIntent);
});
} else if (target === CONSTANTS.PLATFORM) {
const requestMap = {
method: method,
params: params,
action: action,
task: task,
};
// Assigning event_param env if param has empty object
if (task == CONSTANTS.TASK.REGISTEREVENT && Object.keys(requestMap.params).length === 0) {
// To Do :debug event_param issue by passing isrequired as false for getEnvVariable,need to debug further
requestMap.params = UTILS.getEnvVariable(CONSTANTS.EVENT_PARAM, false);
}

cy.sendMessagetoPlatforms(requestMap);
} else {
fireLog.assert(false, `Invalid ${target} target, it should be either app or platfrom`);
}
}).then((response) => {
if (Cypress.env(CONSTANTS.IS_RPC_ONLY)) {
fireLog.info(
`${method} response will be retrieved in subsequent steps and validated when the rpc-only methods are invoked. Proceeding to the next step.`
);
return;
}
if (
(response && typeof response == CONSTANTS.TYPE_OBJECT) ||
(typeof response == CONSTANTS.TYPE_STRING &&
(JSON.parse(response).hasOwnProperty(CONSTANTS.RESULT) ||
JSON.parse(response).hasOwnProperty(CONSTANTS.ERROR)))
) {
if (response === CONSTANTS.NO_RESPONSE) {
assert(false, CONSTANTS.NO_MATCHED_RESPONSE);
}

response = typeof response === CONSTANTS.TYPE_STRING ? JSON.parse(response) : response;

if (
response &&
response.error &&
response.error.message &&
CONSTANTS.ERROR_LIST.includes(response.error.message)
) {
if (UTILS.getEnvVariable(CONSTANTS.CERTIFICATION) == true) {
fireLog.assert(false, `${target} does not support method: ${method}`);
} else {
fireLog.info(`NotSupported: ${target} does not support method: ${method}`).then(() => {
throw new Error(CONSTANTS.STEP_IMPLEMENTATION_MISSING);
});
}
}

if (task == CONSTANTS.TASK.REGISTEREVENT) {
if (response && response.result && response.result.hasOwnProperty(CONSTANTS.LISTENING)) {
const eventResponse = {
eventListenerId: response.result.event + '-' + response.id,
eventListenerResponse: response.result,
};
response.result = eventResponse;
}
if (response && response.error && response.error.message) {
fireLog.assert(
false,
`Event registration failed for event ${method} with error message: ${response.error.message} `
);
}
}

cy.updateResponseForFCS(method, params, response).then((updatedResponse) => {
// Create a deep copy to avoid reference mutation
const dataToBeCensored = _.cloneDeep(response);

// Call the 'censorData' command to hide sensitive data
cy.censorData(method, dataToBeCensored).then((maskedResult) => {
const appLog = target === CONSTANTS.PLATFORM ? 'Firebolt platform' : `app: ${appId}`;
fireLog.info(`Response from ${appLog}: ${JSON.stringify(maskedResult)}`);
});
// Creating object with event name, params, and response etc and storing it in a global list for further validation.
const apiOrEventAppObject =
task === CONSTANTS.TASK.REGISTEREVENT
? new eventObject(method, params, context, updatedResponse, appId, expected)
: new apiObject(method, params, context, updatedResponse, expected, appId);

const globalList =
task === CONSTANTS.TASK.REGISTEREVENT
? CONSTANTS.GLOBAL_EVENT_OBJECT_LIST
: CONSTANTS.GLOBAL_API_OBJECT_LIST;
UTILS.getEnvVariable(globalList).push(apiOrEventAppObject);
});
} else {
fireLog.info(
`${target} returned response in invalid format, which could lead to failures in validations. Response must be in JSON RPC format - ${response}`
);
}
});
});

Cypress.Commands.add('methodorEventResponseValidation', (validationType, additionalParams) => {
const { method, context, contentObject, expectingError, appId, eventExpected } = additionalParams;
Abhishk123 marked this conversation as resolved.
Show resolved Hide resolved
let validationJsonPath = additionalParams.validationJsonPath;

// Extracting the api or event object from the global list.
const methodOrEventObject = UTILS.getApiOrEventObjectFromGlobalList(
method,
context,
appId,
validationType
);
const param = methodOrEventObject.params;

cy.validateResponseErrorAndSchemaResult(methodOrEventObject, validationType).then(() => {
// If passed method is exception method or expecting a error in response, doing error content validation.
if (UTILS.isScenarioExempted(method, param) || expectingError) {
// If not expecting for an error and it's a exception method, storing "exceptionErrorObject" to errorContent variable to fetch the error content object based on the exception type.
let errorContent = expectingError === true ? contentObject : CONSTANTS.EXCEPTION_ERROR_OBJECT;
cy.validateErrorObject(method, errorContent, validationType, context, appId, param);
} else {
if (validationType == CONSTANTS.EVENT) {
const eventName = methodOrEventObject.eventObjectId;
if (appId === UTILS.getEnvVariable(CONSTANTS.FIRST_PARTY_APPID)) {
const requestMap = {
method: CONSTANTS.REQUEST_OVERRIDE_CALLS.FETCH_EVENT_RESPONSE,
params: eventName,
};

cy.sendMessagetoPlatforms(requestMap).then((result) => {
cy.updateResponseForFCS(method, null, result, true).then((updatedResponse) => {
cy.saveEventResponse(
updatedResponse,
methodOrEventObject,
eventName,
eventExpected === 'triggers' ? true : false
);
});
});
} else {
const params = { event: eventName };
// Generating an intent message using the provided information to send it to a third-party app
const intentMessage = UTILS.createIntentMessage(CONSTANTS.TASK.GETEVENTRESPONSE, params);
const requestTopic = UTILS.getTopic(appId);
const responseTopic = UTILS.getTopic(appId, CONSTANTS.SUBSCRIBE);
cy.sendMessagetoApp(requestTopic, responseTopic, intentMessage).then((response) => {
response = JSON.parse(response);
if (
response &&
response.result &&
response.result.hasOwnProperty(CONSTANTS.EVENT_RESPONSE)
) {
response.result = response.result.eventResponse;
}
cy.updateResponseForFCS(method, null, response, true).then((updatedResponse) => {
cy.saveEventResponse(
updatedResponse,
methodOrEventObject,
eventName,
eventExpected === 'triggers' ? true : false
);
});
});
}
}

try {
if (contentObject && contentObject.data) {
contentObject.data.forEach((object) => {
if (object.validations) {
const scenario = object.type;
const methodOrEventResponse =
validationType == CONSTANTS.EVENT
? methodOrEventObject.eventResponse
: validationType == CONSTANTS.METHOD
? methodOrEventObject.apiResponse
: null;

// Looping through validationJsonPath to find the valid path for validation.
if (validationJsonPath && Array.isArray(validationJsonPath)) {
const validationPath = validationJsonPath.find((path) => {
if (
path
.split('.')
.reduce((acc, part) => acc && acc[part], methodOrEventResponse) !== undefined
) {
return path;
}
});
validationPath
? (validationJsonPath = validationPath)
: fireLog.assert(
false,
'Could not find the valid validation path from the validationJsonPath list'
);
}
switch (scenario) {
case CONSTANTS.REGEX:
cy.regExValidation(
method,
object.validations[0].type,
validationJsonPath,
methodOrEventResponse
);
break;
case CONSTANTS.MISC:
cy.miscellaneousValidation(method, object.validations[0], methodOrEventObject);
break;
case CONSTANTS.DECODE:
const decodeType = object.specialCase;
const responseForDecodeValidation =
validationType == CONSTANTS.EVENT
? methodOrEventResponse
: validationType == CONSTANTS.METHOD
? methodOrEventResponse.result
: null;

cy.decodeValidation(
method,
decodeType,
responseForDecodeValidation,
object.validations[0],
null
);
break;
case CONSTANTS.FIXTURE:
cy.validateContent(
method,
context,
validationJsonPath,
object.validations[0].type,
validationType,
appId
);
break;
case CONSTANTS.CUSTOM:
cy.customValidation(object, methodOrEventObject);
break;
case CONSTANTS.UNDEFINED:
cy.undefinedValidation(object, methodOrEventObject, validationType);
break;
default:
assert(false, 'Unsupported validation type');
break;
}
}
});
} else {
cy.validateContent(
method,
context,
validationJsonPath,
contentObject,
validationType,
appId
);
}
} catch (error) {
assert(false, `Unable to validate the response: ${error}`);
}
}
});
});
25 changes: 25 additions & 0 deletions cypress/support/cypress-support/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,11 @@ function parseValue(str) {
if (str === 'false') return false;

if (!isNaN(str)) return Number(str);

// If the string contains comma, split it into an array
if (str.includes(',')) {
return str.split(',');
}
}

return str;
Expand Down Expand Up @@ -880,6 +885,25 @@ global.resolveAtRuntime = function (input) {
};
};

// A Function that recursively check each fields and invokes if it's a function within an array or object.
function resolveRecursiveValues(input) {
if (Array.isArray(input)) {
return input.map((item) => resolveRecursiveValues(item));
} else if (typeof input == CONSTANTS.TYPE_OBJECT && input !== null) {
const newObj = {};
for (const key in input) {
if (Object.hasOwnProperty.call(input, key)) {
newObj[key] = resolveRecursiveValues(input[key]);
}
}
return newObj;
} else if (input && typeof input === CONSTANTS.TYPE_FUNCTION) {
return input();
} else {
return input;
}
}

module.exports = {
replaceJsonStringWithEnvVar,
createIntentMessage,
Expand All @@ -905,4 +929,5 @@ module.exports = {
fireLog,
parseValue,
checkForSecondaryAppId,
resolveRecursiveValues,
};
Loading
Loading