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

feat: added glue code for dismissing an app #284

Open
wants to merge 21 commits into
base: deepLinkImplementation
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# [1.5.0-dev.7](https://github.com/rdkcentral/firebolt-certification-suite/compare/v1.5.0-dev.6...v1.5.0-dev.7) (2024-12-10)


### Features

* Update App Exit Handling ([#266](https://github.com/rdkcentral/firebolt-certification-suite/issues/266)) ([d4a96b7](https://github.com/rdkcentral/firebolt-certification-suite/commit/d4a96b709179688943de3968b4da19026af7060b))

# [1.5.0-dev.6](https://github.com/rdkcentral/firebolt-certification-suite/compare/v1.5.0-dev.5...v1.5.0-dev.6) (2024-12-09)


### Bug Fixes

* Trimming the new line in logs ([#285](https://github.com/rdkcentral/firebolt-certification-suite/issues/285)) ([36f7b2f](https://github.com/rdkcentral/firebolt-certification-suite/commit/36f7b2f9fe2950c5d7da0c51a8ee8d70385843b4))

# [1.5.0-dev.5](https://github.com/rdkcentral/firebolt-certification-suite/compare/v1.5.0-dev.4...v1.5.0-dev.5) (2024-12-06)


Expand Down
17 changes: 17 additions & 0 deletions cypress/fixtures/objects/appData/app_metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"defaultKeyPressSequence": {
"dismiss": ["exit", "exit", "exit"]
},
"appId": {
"intentName": {
"entityId": "<entityId>",
"keyPressSequence": {
"dismiss": ["exit", "exit", "exit"]
}
},
"defaultKeyPressSequence": {
"dismiss": ["exit", "exit", "exit"]
}
}

}
4 changes: 4 additions & 0 deletions cypress/support/constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,12 @@ module.exports = {
SETFIREBOLTINTERACTIONSHANDLER: 'fcs.setFireboltInteractionsHandler',
CREATE_MARKER: 'performance.createMarker',
UNLOADAPP: 'fcs.unloadApp',
CLOSEAPP: 'fcs.closeApp',
DISMISSAPP: 'fcs.dismissApp',
FETCHDEVICEDETAILS: 'fcs.fetchDeviceDetails',
SCREENSHOT: 'fcs.screenshot',
GETAPPSTATE: 'fcs.getAppState',
DISMISS: 'fcs.dismissApp',
},
REQUEST_MAP_INTERACTIONS_SERVICE: 'Request map for firebolt interactions service : ',
RESPONSE: 'Response: ',
Expand Down Expand Up @@ -466,6 +469,7 @@ module.exports = {
VALIDATIONJSONPATH: 'validationJsonPath',
VARIABLES_PREFIX_LIST: 'variableObjectsPrefixLists',
VERSION: 'version',
VISIBLE: 'VISIBLE',
WRITE_FAILED: 'Unable to write report json to file',
WRITE_TO_FILE: 'writeToFile',
CENSOR_DATA_PATH: 'censorData.json',
Expand Down
40 changes: 39 additions & 1 deletion cypress/support/cypress-commands/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
const CONSTANTS = require('../constants/constants');
const { _ } = Cypress;
import UTILS, { getEnvVariable } from '../cypress-support/src/utils';
import UTILS, { fireLog, getEnvVariable } from '../cypress-support/src/utils';
const logger = require('../Logger')('command.js');
import { apiObject, eventObject } from '../appObjectConfigs';

Expand Down Expand Up @@ -1622,6 +1622,44 @@ Cypress.Commands.add('envConfigSetup', () => {
fireLog.info('No additional config module environment setup');
});

/**
* @module commands
* @function exitAppSession
* @description Function to provide the test runner with various methods to end the current app session
* @param {String} exitType - Type of close operation to be performed.
* @param {String} appId - AppId to be closed.
* @example
* cy.exitAppSession('closeApp','testAppId')
* cy.exitAppSession('dismissApp','testAppId')
* cy.exitAppSession('unloadApp','testAppId')
*/
Cypress.Commands.add('exitAppSession', (exitType, appId) => {
fireLog.info('Invoking platform implementation to end session for appId: ' + appId);
let exitMethod;
switch (exitType) {
case 'closeApp':
exitMethod = CONSTANTS.REQUEST_OVERRIDE_CALLS.CLOSEAPP;
break;
case 'unloadApp':
exitMethod = CONSTANTS.REQUEST_OVERRIDE_CALLS.UNLOADAPP;
break;
case 'dismissApp':
exitMethod = CONSTANTS.REQUEST_OVERRIDE_CALLS.DISMISSAPP;
break;
default:
fireLog.info('Session for appId: ' + appId + ' will not be ended due to invalid exitType');
fireLog.error(CONSTANTS.CONFIG_IMPLEMENTATION_MISSING);
}
fireLog.info('Session for appId: ' + appId + ' will be ended with type: ' + exitType);
const requestMap = {
method: exitMethod,
params: appId,
};
cy.sendMessagetoPlatforms(requestMap).then((response) => {
fireLog.info('Platform has successfully ended app Session for appId: ' + appId);
});
});

/**
* @module commands
* @function initiatePerformanceMetrics
Expand Down
15 changes: 7 additions & 8 deletions cypress/support/cypress-support/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,13 @@ export default class Config {
);
return fireboltResponse;
}
typeof fireboltResponse == 'object'
? (fireboltResponse = JSON.stringify(fireboltResponse))
: fireboltResponse;

fireLog.info(
'Original Response to be converted to firebolt equivalent: ' +
fireboltResponse.replace(/\s|\\n?/g, '')
);
if (typeof fireboltResponse === 'object') {
fireboltResponse = JSON.stringify(fireboltResponse);
}
if (typeof fireboltResponse === 'string') {
fireboltResponse = fireboltResponse.replace(/\r?\n|\s{3,}/g, '');
}
fireLog.info('Original Response to be converted to firebolt equivalent: ' + fireboltResponse);
// If we've gotten to this point, we have a config override. Call it and return its response
return methodConfig(fireboltResponse);
}
Expand Down
4 changes: 4 additions & 0 deletions cypress/support/cypress-support/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,10 @@ class FireLog extends Function {
}

info(message) {}

error(message) {
throw new Error(message);
}
}

const fireLog = new FireLog();
Expand Down
2 changes: 1 addition & 1 deletion cypress/support/step_definitions/dynamicCalls.js
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ Given(/'(.+)' (on|with) '(.+)' page/, (validationObjectKey, type, page) => {

// Sending the request to the platform to retrieve the app state.
cy.sendMessagetoPlatforms(requestMap).then((response) => {
if (response.toUpperCase() === CONSTANTS.FOREGROUND) {
if (response.appState.toUpperCase() === CONSTANTS.FOREGROUND) {
fireLog.info(
`State validation successful: Current state of ${appId} app is ${response} as expected`
);
Expand Down
112 changes: 112 additions & 0 deletions cypress/support/step_definitions/fireboltCalls.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,115 @@ Given('device is rebooted', () => {
throw new Error(CONSTANTS.STEP_IMPLEMENTATION_MISSING);
});
});

/**
* @module fireboltCalls
* @function And 3rd party '(.+)' app is dismissed
* @description To dismiss the launched app
* @param {String} app - app name.
* @example
* And 3rd party 'firebolt' app is dismissed
*/
Given(/3rd party '(.+)' app is dismissed$/, async (appType) => {
const appId = Cypress.env(CONSTANTS.RUNTIME).appId;
let KeyPressSequence;
if (
// Check if keyPressSequence is defined in the runtime environment variables for the specific intent
Cypress.env(CONSTANTS.RUNTIME) &&
Cypress.env(CONSTANTS.RUNTIME).intent &&
Cypress.env(CONSTANTS.RUNTIME).intent.keyPressSequence
) {
KeyPressSequence = Cypress.env(CONSTANTS.RUNTIME).intent.keyPressSequence;
} else if (
// Check if defaultKeyPressSequence is defined for the specific appId in app_metadata
Cypress.env('app_metadata') &&
Cypress.env('app_metadata')[appId] &&
Cypress.env('app_metadata')[appId].defaultKeyPressSequence
) {
KeyPressSequence = Cypress.env('app_metadata')[appId].defaultKeyPressSequence;
} else if (
// Check if defaultKeyPressSequence is defined in the app_metadata globally
Cypress.env('app_metadata') &&
Cypress.env('app_metadata').defaultKeyPressSequence
) {
KeyPressSequence = Cypress.env('app_metadata').defaultKeyPressSequence;
} else {
// If no keyPressSequence is found, throw an error with details from the app_metadata file
const appMetadataJSON = require('../../fixtures/objects/appData/app_metadata.json');
throw new Error(
`Expected KeyPressSequence was not found for ${appId} in app_metadata.json. More details on app_metadata present in: ${appMetadataJSON}`
);
}
neeradanelxsi marked this conversation as resolved.
Show resolved Hide resolved
cy.exitAppSession('dismissApp', KeyPressSequence.dismiss).then((response) => {
fireLog.info(`Response from platform: ${JSON.stringify(response)}`);
});
});

/**
* @module fireboltCalls
* @function And 3rd party '(.+)' app should be exited
* @description To validate that the app is dismissed
* @param {String} app - app name.
* @example
* Then 3rd party 'firebolt' app should be exited
*/
Given(/3rd party '(.+)' app should be exited$/, async (app) => {
// getAppState validation
const appId = Cypress.env(CONSTANTS.CURRENT_APP_ID);
const requestMapForGetAppState = {
method: CONSTANTS.REQUEST_OVERRIDE_CALLS.GETAPPSTATE,
params: appId,
};
fireLog.info(
`Sending request to fetch ${appId} app state: ${JSON.stringify(requestMapForGetAppState)}`
);
cy.sendMessagetoPlatforms(requestMapForGetAppState)
.then((response) => {
neeradanelxsi marked this conversation as resolved.
Show resolved Hide resolved
const responseString = JSON.stringify(response);
if (
// Check if response exists and contains appState, visibilityState
// and if appState is INACTIVE and visibilityState is VISIBLE
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

give a generic comment on line 435. what is visibility state ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

response &&
response.appState &&
response.visibilityState &&
response.appState.toUpperCase() === CONSTANTS.LIFECYCLE_STATES.INACTIVE &&
response.visibilityState.toUpperCase() === CONSTANTS.VISIBLE
) {
fireLog.info(
`State validation successful: Current state of ${appId} app is ${responseString} as expected`
);
} else if (
// Check if appState is missing, visibilityState exists, and visibilityState is VISIBLE
response &&
!response.appState &&
response.visibilityState &&
response.visibilityState.toUpperCase() === CONSTANTS.VISIBLE
) {
fireLog.info(
`State validation successful: Current state of ${appId} app is ${responseString} as expected`
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 453 is not correct. we are not getting any app state and we are not validating app state here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the logs

} else {
// Log failure message if none of the above conditions are met
fireLog.fail(`${appId} app is not dismissed. Response :${responseString}`);
}
})
neeradanelxsi marked this conversation as resolved.
Show resolved Hide resolved
.then(() => {
// screenShot validation
neeradanelxsi marked this conversation as resolved.
Show resolved Hide resolved
fireLog.info('Started Screenshot validation');
const requestMapForScreenShotValidation = {
method: CONSTANTS.REQUEST_OVERRIDE_CALLS.SCREENSHOT,
neeradanelxsi marked this conversation as resolved.
Show resolved Hide resolved
params: {
validations: Cypress.env(CONSTANTS.RUNTIME).fireboltCall.screenshot.validations,
},
};
neeradanelxsi marked this conversation as resolved.
Show resolved Hide resolved
fireLog.info(
`Sending request to get screenshot : ${JSON.stringify(requestMapForScreenShotValidation)}`
);
cy.sendMessagetoPlatforms(requestMapForScreenShotValidation).then((response) => {
fireLog.info('Screenshot Validation Response: ' + JSON.stringify(response));
if (response.status != 'pass') {
fireLog.fail(`Screenshot validation failed ${response.validations}`);
}
});
});
});
4 changes: 4 additions & 0 deletions cypress/support/step_definitions/launchApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ import UTILS from '../cypress-support/src/utils';
Given(
/3rd party '(.+)' app is launched(?: with '(.+)' appId)?(?: with '(.+)' state)?(?: with '(.+)' intent)?$/,
(appType, appCallSign, state, intent) => {
Cypress.env(CONSTANTS.APP_TYPE, appType);
if (
!UTILS.getEnvVariable(CONSTANTS.APP_LAUNCH_STATUS, false) ||
UTILS.getEnvVariable(CONSTANTS.LIFECYCLE_CLOSE_TEST_TYPES).includes(
UTILS.getEnvVariable(CONSTANTS.TEST_TYPE)
) ||
UTILS.getEnvVariable(CONSTANTS.UNLOADING_APP_TEST_TYPES).includes(
UTILS.getEnvVariable(CONSTANTS.TEST_TYPE)
) ||
UTILS.isTestTypeChanged(CONSTANTS.TEST_TYPE)
) {
if (!state) {
Expand Down
85 changes: 19 additions & 66 deletions cypress/support/step_definitions/testSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Given('the environment has been set up for {string} tests', (test) => {
if (
!UTILS.getEnvVariable(CONSTANTS.ENV_SETUP_STATUS, false) ||
UTILS.getEnvVariable(CONSTANTS.LIFECYCLE_CLOSE_TEST_TYPES).includes(test) ||
UTILS.getEnvVariable(CONSTANTS.UNLOADING_APP_TEST_TYPES).includes(test) ||
UTILS.isTestTypeChanged(test)
) {
Cypress.env(CONSTANTS.PREVIOUS_TEST_TYPE, Cypress.env(CONSTANTS.TEST_TYPE));
Expand Down Expand Up @@ -119,80 +120,32 @@ Given('the environment has been set up for {string} tests', (test) => {
* destroyAppInstance('Parameters')
*/
function destroyAppInstance(testType) {
const isAllowedTestType = UTILS.getEnvVariable(CONSTANTS.LIFECYCLE_CLOSE_TEST_TYPES).includes(
// Checking if the current test type is present in unloadAppTestTypes and/or closeAppTestTypes
const isCloseTestType = UTILS.getEnvVariable(CONSTANTS.LIFECYCLE_CLOSE_TEST_TYPES).includes(
testType
);
const isUnloadTestType = UTILS.getEnvVariable(CONSTANTS.UNLOADING_APP_TEST_TYPES).includes(
testType
);
const appId = UTILS.getEnvVariable(CONSTANTS.THIRD_PARTY_APP_ID);

// Checking if the previous test type is different from the current test type.
const isDifferentFromPrevious =
UTILS.getEnvVariable(CONSTANTS.PREVIOUS_TEST_TYPE, false) != testType &&
UTILS.getEnvVariable(CONSTANTS.PREVIOUS_TEST_TYPE, false) != undefined;

if (isAllowedTestType || isDifferentFromPrevious) {
const requestTopic = UTILS.getTopic();
const responseTopic = UTILS.getTopic(null, CONSTANTS.SUBSCRIBE);

// The test type is present in the unloading app test list, taking the reason as 'error'. This will unload the app.
const closeReason = UTILS.getEnvVariable(CONSTANTS.UNLOADING_APP_TEST_TYPES).includes(testType)
? CONSTANTS.ERROR
: CONSTANTS.USER_EXIT_REASON;

const communicationMode = UTILS.getCommunicationMode();
additionalParams = {
communicationMode: communicationMode,
action: 'Lifecycle.validation',
};
const params = {
mode: 'Lifecycle.validation',
methodName: 'Lifecycle.close',
methodParams: { reason: closeReason },
};
const intentMessage = UTILS.createIntentMessage(
CONSTANTS.TASK.RUNTEST,
params,
additionalParams
);
cy.log(
'Sending lifecycle close intent to unload app, method: ' +
params.methodName +
' params: ' +
JSON.stringify(params.methodParams)
// If the current test type is present inside the closeAppTestTypes array then close the app.
// If the multiple test types are executed in one command then close the app between them
if (isCloseTestType || isDifferentFromPrevious) {
fireLog.info(
'Closing app since either Test Type is specified in closeAppTestTypes or is different from previous Test Type.'
);
cy.exitAppSession('closeApp', appId);
}

try {
cy.sendMessagetoApp(requestTopic, responseTopic, intentMessage).then((response) => {
let result;
try {
response = JSON.parse(response);
result = response.report.result;
fireLog.info(
'Received response from app to acknowledge close request. Response: ' +
JSON.stringify(response)
);
} catch {
result = response;
}
if (result === CONSTANTS.NO_RESPONSE || result === null) {
fireLog.info('App unloaded', 'destroyAppInstance');
} else {
fireLog.info(
false,
'App may have failed to unload. Response: ' + JSON.stringify(response)
);
fireLog.info('Falling back to platform implementation of force unload.');
const requestMap = {
method: CONSTANTS.REQUEST_OVERRIDE_CALLS.UNLOADAPP,
params: UTILS.getEnvVariable(CONSTANTS.THIRD_PARTY_APP_ID),
};
cy.sendMessagetoPlatforms(requestMap).then(() => {
// Config modules needs override for validation of app unload
fireLog.info('Platforms unload app execution complete');
});
}
cy.wait(5000);
});
} catch (error) {
fireLog.info('Failed to close the 3rd party app: ', error);
}
// If the current test type is present inside the unloadAppTestTypes array then unload the app.
if (isUnloadTestType) {
fireLog.info('Unloading app since Test Type is specified in unloadAppTestTypes.');
cy.exitAppSession('unloadApp', appId);
}
}

Expand Down
Loading
Loading