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

Simple pub sub integration #113

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ To execute the certification suite against any platform, the following setup mus
| healthCheckRetries | number | 8 | Health check retry count |
| communicationMode | string | 'SDK' or 'Transport' | Set communicationMode as SDK/transport. Default mode is SDK |
| performanceMetrics | boolean | true | Makes a call to platform to start/stop the recording of performance metrics if value is true |
| pubSubUrl | string | ws://127.0.0.1:8081 | Sets the the url to use for a PubSub server which will be used for 3rd party app communication.



- Provide the specPattern mapping details.
Expand Down Expand Up @@ -370,5 +372,21 @@ Example Usage:
logger.info('This is an informational message', 'moduleName');
logger.debug('This is a debugging message');
logger.error('This is an error message');
```

```
## Using Simple PubSub

If you want to use simplePubSub server as the means of communication for 3rd party app calls follow these steps:

1. Clone SimplePubSub [server](https://github.com/comcast-firebolt/simplePubSub).
2. Setup SimplePubSub server (i.e. `npm install`) and start (i.e. `npm start`).
3. Clone [firebolt-certification-app](https://github.com/rdkcentral/firebolt-certification-app).
5. In FCA hange the `host` in /webpack.dev.js to <YOUR_IP>.
6. Setup firebolt-certification-app (FCA) (i.e. `npm install`) and start (i.e. `npm start`).
7. Point your device to use your local instance of FCA (i.e. `http://<YOUR_IP>:8081`).
8. When running FCS include env variables:
- deviceMac: `<DEVICE_UNDER_TEST>`
- pubSubUrl: `ws://<YOUR_IP>:8080`



1 change: 1 addition & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const env = {
thirdPartyMockUser: '456~A',
MFOS_base_url: 'http://localhost:3333/api/v1/',
firstPartyAppId: 'firstPartyAppId',
failOnPubSubConnectionError: false,
certification: false,
reportType: 'cucumber',
deleteReport: false,
Expand Down
59 changes: 29 additions & 30 deletions cypress/plugins/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,40 @@ const CONSTANTS = require('../support/constants/constants');

// If "genericSupport" is set to a falsy value (false, null, etc), take no further action. Simply "return"
function genericSupport(config) {
let data;
// Read additional config.
try {
const data = JSON.parse(fs.readFileSync('supportConfig.json'));

// Get the arguments passed from command line during run time.
const commandLineArgs = Object.entries(config.resolved.env)
.filter(([key, value]) => value.from === 'cli')
.reduce((acc, [key, value]) => {
acc[key] = value.value;
return acc;
}, {});

// fireboltCalls JSON
generateIndexFile(CONSTANTS.FIREBOLTCALLS_FROM_FCS, 'fireboltCalls');
generateIndexFile(CONSTANTS.FIREBOLTCALLS_FROM_CONFIGMODULE, 'fireboltCalls');
// fireboltMocks JSON
generateIndexFile(CONSTANTS.FIREBOLTMOCK_FROM_FCS, 'fireboltMocks');
generateIndexFile(CONSTANTS.FIREBOLTMOCK_FROM_CONFIGMODULE, 'fireboltMocks');

// The sequence of override - the default config in the config.js file, overriden by supportConfig.json and then by the command line arguments.
config.env = {
...config.env,
...data,
...commandLineArgs,
};
// To read device data JSON
preprocessDeviceData(config);
const testDataEnv = testDataProcessor.testDataProcessor(config.env);
Object.assign(config.env, testDataEnv);

return config;
data = JSON.parse(fs.readFileSync('supportConfig.json'));
} catch (error) {
logger.error('Received following error while trying to read supportConfig json', error);
return config;
}
// Get the arguments passed from command line during run time.
const commandLineArgs = Object.entries(config.resolved.env)
.filter(([key, value]) => value.from === 'cli')
.reduce((acc, [key, value]) => {
acc[key] = value.value;
return acc;
}, {});

// fireboltCalls JSON
generateIndexFile(CONSTANTS.FIREBOLTCALLS_FROM_FCS, 'fireboltCalls');
generateIndexFile(CONSTANTS.FIREBOLTCALLS_FROM_CONFIGMODULE, 'fireboltCalls');
// fireboltMocks JSON
generateIndexFile(CONSTANTS.FIREBOLTMOCK_FROM_FCS, 'fireboltMocks');
generateIndexFile(CONSTANTS.FIREBOLTMOCK_FROM_CONFIGMODULE, 'fireboltMocks');

// The sequence of override - the default config in the config.js file, overriden by supportConfig.json and then by the command line arguments.
config.env = {
...config.env,
...data,
...commandLineArgs,
};
// To read device data JSON
preprocessDeviceData(config);
const testDataEnv = testDataProcessor.testDataProcessor(config.env);
Object.assign(config.env, testDataEnv);

return config;
}

module.exports = {
Expand Down
5 changes: 4 additions & 1 deletion cypress/support/constants/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ module.exports = {
EVENT_SCHEMA_RESULT: 'eventSchemaResult',
EXCEPTION_ERROR_OBJECT: 'exceptionErrorObject',
EXCEPTION_METHODS: 'exceptionMethods',
EXCLUDED_METHODS: [],
EXCLUDED_METHODS: ['Lifecycle.close'],
EXCLUDED_MODULES: [],
EXCLUDED_VALUES: [null, undefined],
EXECUTE_SHELL: 'executeShell',
Expand All @@ -134,6 +134,7 @@ module.exports = {
EXTERNAL_PREREQUISITE_DATA: './cypress/fixtures/external/PreRequisiteData.json',
EXTRACTEDAPI_PATH: 'extractedApiObject.response.',
FAIL: 'FAIL',
FAIL_ON_PUBSUB_CONNECTION_ERROR: 'failOnPubSubConnectionError',
FAILED_TO_PARSE_LIEFECYCLE_ERROR:
'Failed to parse error object from response while setting lifecycle state. Response received : ',
FAILED_TO_SET_LIFECYCLE_STATE:
Expand Down Expand Up @@ -226,6 +227,7 @@ module.exports = {
LIMITADTRACKING_OFF: 'limitAdTrackingOFF',
LIMITADTRACKING_ON: 'limitAdTrackingON',
LONGPOLL_TIMEOUT: 15000,
MACADDRESS_PARAM: 'macaddress',
MESSAGE_QUEUE: 'messageQueue',
MESSAGE_QUEUE_SIZE: 100,
MESSAGE_QUEUE_TIME_DIFF: 150000,
Expand Down Expand Up @@ -289,6 +291,7 @@ module.exports = {
'Platform returned response in invalid format, which could lead to failures in validations. Response must be an object',
PLATFORM_NOT_SUPPORT_LOG: 'Platform does not support method',
PREREQUISITE_DATA: 'PreRequisiteData.json',
PUB_SUB_URL: 'pubSubUrl', // Env Var for the URL for the Default Module's pubSub implementation
SETUPCHECK: 'Setup Check',
SETUPVALUES: 'external/setupValues.json',
SETUPVALUES_FILEPATH: 'cypress/fixtures/external/setupValues.json',
Expand Down
21 changes: 16 additions & 5 deletions 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 from '../cypress-support/src/utils';
import UTILS, { getEnvVariable } from '../cypress-support/src/utils';
const logger = require('../Logger')('command.js');

/**
Expand Down Expand Up @@ -653,12 +653,12 @@ Cypress.Commands.add('launchApp', (appType, appCallSign) => {
? UTILS.getEnvVariable(CONSTANTS.APP_TYPE)
: CONSTANTS.FIREBOLT; // appType defines in which mode app should be launched
data = {
query: JSON.stringify({
query: {
params: {
[CONSTANTS.APP_ID]: appId,
[CONSTANTS.APP_TYPE]: appCategory,
},
}),
},
};
const messageIntent = {
action: CONSTANTS.SEARCH,
Expand All @@ -676,17 +676,28 @@ Cypress.Commands.add('launchApp', (appType, appCallSign) => {
Cypress.env(CONSTANTS.TEST_TYPE).toLowerCase() == CONSTANTS.MODULE_NAMES.LIFECYCLE
) {
data = {
query: JSON.stringify({
query: {
params: {
[CONSTANTS.APP_ID]: appId,
[CONSTANTS.LIFECYCLE_VALIDATION]: true,
[CONSTANTS.APP_TYPE]: appCategory,
},
}),
},
};
requestMap.params.intent.data = data;
}

// Add the PubSub URL if required
if (getEnvVariable(CONSTANTS.PUB_SUB_URL, false)) {
data.query.params[CONSTANTS.PUB_SUB_URL] = getEnvVariable(CONSTANTS.PUB_SUB_URL);

Choose a reason for hiding this comment

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

Medium impact. Quality issue.
Null pointer dereferences. Bad use of null-like value.
Performing an operation that would be invalid on a null or undefined value.
If the value is null or undefined, this code will cause an exception such as a TypeError.

if (getEnvVariable(CONSTANTS.DEVICE_MAC, false) {
data.query.params[CONSTANTS.MACADDRESS_PARAM] = getEnvVariable(CONSTANTS.DEVICE_MAC);
}
}

// Stringify the query (The intent requires it be a string)
data.query = JSON.stringify(data.query);

Choose a reason for hiding this comment

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

Medium impact. Quality issue.
Null pointer dereferences. Bad use of null-like value.
Performing an operation that would be invalid on a null or undefined value.
If the value is null or undefined, this code will cause an exception such as a TypeError.


Cypress.env(CONSTANTS.CURRENT_APP_ID, appId);

const requestTopic = UTILS.getTopic(appId);
Expand Down
10 changes: 7 additions & 3 deletions cypress/support/cypress-support/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ function overideParamsFromConfigModule(overrideParams) {
: CONSTANTS.EXCLUDED_METHODS;
overrideParams.modulesToBeExcluded = getEnvVariable('excludedModules', false)
? getEnvVariable('excludedModules')
: CONSTANTS.EXCLUDED_METHODS;
: CONSTANTS.EXCLUDED_MODULES;
return overrideParams;
}

Expand Down Expand Up @@ -547,8 +547,12 @@ function pubSubClientCreation(appTransport) {
clientCreated = true;
resolve(true);
} catch (error) {
// If an error occurs, reject the promise with the error
reject('Failed to initiate PubSubClient' + error);
if (getEnvVariable(CONSTANTS.FAIL_ON_PUBSUB_CONNECTION_ERROR, false)) {
// If an error occurs, reject the promise with the error
reject('Failed to initiate PubSubClient' + error);
} else {
resolve(false);
}
}
} else {
resolve(false);
Expand Down
32 changes: 18 additions & 14 deletions defaultModule/appTransport/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
const logger = require('../../../cypress/support/Logger')('index.js');
const constants = require('../../cypress/support/constants/constants');
const { getEnvVariable } = require('../../cypress/support/cypress-support/src/utils');

const client = {
ws: null,
Expand All @@ -37,9 +39,12 @@ const client = {
function init() {
logger.info('Establishing pubsub connection');

return new Promise((resolve, reject) => {
return new Promise((resolve) => {
// Enter a valid WebSocket URL
client.ws = new WebSocket('ws://your-ws-url-here.com');
const url = getEnvVariable(constants.PUB_SUB_URL, false)
? getEnvVariable(constants.PUB_SUB_URL)
: 'ws://localhost:8080';
client.ws = new WebSocket(url);

const websocket = client.ws;

Expand All @@ -48,14 +53,14 @@ function init() {
websocket.removeEventListener('error', openCallback);
resolve(event.data);
};
// if WebSocket connection fails (error or close event), the errorHandler logs the error and resolves the promise with a default message instead of rejecting it.
const errorHandler = function (event) {
logger.info('WebSocket connection failed. Continuing execution...', event.data);
reject('Default: Connection could not be established');
};

client.ws.addEventListener('error', function (event) {
reject(event.data);
});

client.ws.addEventListener('close', function (event) {
reject(event.data);
});
client.ws.addEventListener('error', errorHandler);
client.ws.addEventListener('close', errorHandler);

client.ws.addEventListener('open', openCallback);
});
Expand Down Expand Up @@ -129,19 +134,18 @@ function subscribe(topic, callback) {
const formattedMsg = {
operation: data.operation,
topic: data.topic,
headers: data.payload?.headers,
payload: data.payload.message,
payload: data.payload?.message,
};

// Add headers to top level of formatted message if they exist
if (data.payload.headers) {
if (data.payload?.headers) {
formattedMsg.headers = data.payload.headers;
}
// If a callback function is provided, call it with the formattedMsg payload and headers
if (typeof callback == 'function') {
logger.info(
'Incoming notification is valid. Calling callback:' + JSON.stringify(data),
'sunscribe'
'subscribe'
);
callback(formattedMsg.payload, formattedMsg.headers);
}
Expand Down Expand Up @@ -171,4 +175,4 @@ function unsubscribe(topic) {
}

// Uncomment the line below to get app transport working
// module.exports = { init, publish, subscribe, unsubscribe };
module.exports = { init, publish, subscribe, unsubscribe };
Loading