diff --git a/README.md b/README.md index a5f41f4b..c1f44aca 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Mode of execution implies the way in which an API is invoked. There are 2 modes - Steps to convert into `html report` 1. Move the `json report` to root folder 2. Run the command `yarn marge filename.json -f report -o /destination_path` - 3. Check the `html report` on the destination path. + 3. Check the `html report` on the destination path ## Supported Report Parameters @@ -154,4 +154,3 @@ The prompt is displayed when the user needs to grant/deny a particular api, or t If user wants to grant an api, yes button is pressed, for deniel - no button, and incase if the user wants to dismiss the prompt without any action, back button is pressed. - diff --git a/package.json b/package.json index c85b993f..a056f460 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { - "version": "1.1.0", + "version": "1.2.0", "name": "firebolt-certification", "description": "Reference App to demonstrate Firebolt APIs and Lifecycle", "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", - "@firebolt-js/manage-sdk": "1.1.0", - "@firebolt-js/sdk": "1.1.0", + "@firebolt-js/discovery-sdk": "1.2.0", + "@firebolt-js/manage-sdk": "1.2.0", + "@firebolt-js/sdk": "1.2.0", "@lightningjs/core": "2.11.0", "@lightningjs/sdk": "^5.0.1", "@lightningjs/ui-components": "^2.2.2", diff --git a/plugins/pubsub.md b/plugins/pubsub.md index 82c348d3..675cf6f7 100644 --- a/plugins/pubsub.md +++ b/plugins/pubsub.md @@ -21,7 +21,7 @@ If you would like to extend the functionality of the existing PubSub client or c Here is an overview of the functions provided by the PubSubClient class: -- `initialize()` - Initializes a WebSocket connection to the specified URL. +- `initialize()` - Initializes a WebSocket connection to the specified URL. By default, it points to 'ws://localhost:8080'. - `publish(topic, message)` - Publishes a message to the specified topic. diff --git a/src/App.js b/src/App.js index 4cca0179..726133ef 100644 --- a/src/App.js +++ b/src/App.js @@ -20,7 +20,7 @@ import lng from '@lightningjs/core'; import Menu from './Menu'; import MenuBuilder from './MenuBuilder'; import LifecycleHistory from './LifeCycleHistory'; -import { Settings, Accessibility } from '@firebolt-js/sdk'; +import { Settings, Accessibility, Discovery } from '@firebolt-js/sdk'; import FireboltExampleInvoker from './FireboltExampleInvoker'; import Modal from './Modal'; import PubSubCommunication from './PubSubCommunication'; @@ -31,6 +31,7 @@ import { AcknowledgeChallenge, Keyboard, PinChallenge } from '@firebolt-js/manag import PinChallengeProviderDelegater from './providers/PinChallengeDelegater'; import KeyboardProviderDelegater from './providers/KeyboardProviderDelegater'; import AckChallengeProviderDelegater from './providers/AckChallengeDelegater'; +import UserInterestDelegater from './providers/UserInterestDelegater'; const logger = require('./utils/Logger')('App.js'); import FireboltTransportInvoker from './FireboltTransportInvoker'; import { handleAsyncFunction } from './utils/Utils'; @@ -114,6 +115,12 @@ export default class App extends Base { process.env.REPORTINGID = reportingId; process.env.STANDALONE = standalone; process.env.STANDALONE_PREFIX = standalonePrefix; + process.env.ID = 0; + process.env.REGISTERPROVIDER = true; + + // Set the pubSub URL if present + process.env.PUB_SUB_URL = new URLSearchParams(window.location.search).get('pubSubUrl'); + if (platform) { process.env.PLATFORM = platform; } else { @@ -198,14 +205,18 @@ export default class App extends Base { if (!this.appContinue) { const systemui = new URLSearchParams(window.location.search).get('systemui'); - if (systemui) { - try { + try { + if (systemui) { AcknowledgeChallenge.provide('xrn:firebolt:capability:usergrant:acknowledgechallenge', new AckChallengeProviderDelegater(this)); Keyboard.provide('xrn:firebolt:capability:input:keyboard', new KeyboardProviderDelegater(this)); PinChallenge.provide('xrn:firebolt:capability:usergrant:pinchallenge', new PinChallengeProviderDelegater(this)); - } catch (err) { - logger.error('Could not set up providers' + err, 'LoadedState'); + } else { + if (process.env.REGISTERPROVIDER) { + Discovery.provide('xrn:firebolt:capability:discovery:interest', new UserInterestDelegater(this)); + } } + } catch (err) { + logger.error('Could not set up providers' + err, 'LoadedState'); } process.env.APPOBJECT = this; const menusBuilder = new MenuBuilder(); @@ -407,6 +418,15 @@ export default class App extends Base { logger.error('No Mac Address Found in Parameter Initialization response...', 'getParameterInitializationValues'); } + if (query.params.hasOwnProperty(CONSTANTS.REGISTERPROVIDER)) { + process.env.REGISTERPROVIDER = query.params.registerprovider; + } + + // Set the pubSub URL if present + if (query.params.pubSubUrl) { + process.env.PUB_SUB_URL = query.params.pubSubUrl; + } + if (query.task) { setTimeout(() => { const intentReader = new IntentReader(); diff --git a/src/EventInvocation.js b/src/EventInvocation.js index 59fcce3e..63297d1a 100644 --- a/src/EventInvocation.js +++ b/src/EventInvocation.js @@ -39,7 +39,9 @@ class EventHandler { this.moduleWithEventName = moduleWithEventName; const event = moduleWithEventName.split('.')[1]; this.eventName = this.parseEventName(event); - this.eventSchema = this.getSchema(moduleWithEventName, schemaList); + if (process.env.STANDALONE == true) { + this.eventSchema = this.getSchema(moduleWithEventName, schemaList); + } this.initializationTime = new Date(); this.eventListener = null; } @@ -67,16 +69,27 @@ class EventHandler { } return schemaMap; } + // Handle, parse and store the resolved event data from listener handleEvent(eventData) { - const eventSchemaResponse = this.eventSchemaValidation(eventData); - const eventDataObject = { - eventName: this.eventName, - eventListenerId: this.eventListener.eventListenerId, - eventResponse: eventData, - eventSchemaResult: eventSchemaResponse, - eventTime: new Date(), - }; + let eventDataObject; + if (process.env.STANDALONE == true) { + const eventSchemaResponse = this.eventSchemaValidation(eventData); + eventDataObject = { + eventName: this.eventName, + eventListenerId: this.eventListener.eventListenerId, + eventResponse: eventData, + eventSchemaResult: eventSchemaResponse, + eventTime: new Date(), + }; + } else { + eventDataObject = { + eventName: this.eventName, + eventListenerId: this.eventListener.id, + eventResponse: eventData, + eventTime: new Date(), + }; + } eventHistory.push(eventDataObject); } // Schema validation for resolved event data @@ -107,53 +120,68 @@ class EventHandler { export class EventInvocation { // This method accepts the message params and return the listener response and schema response async northBoundEventHandling(message) { - let responseCode; const eventParams = message.params; const moduleWithEventName = eventParams.event; const params = eventParams.params; const [listenerResponse, uniqueListenerKey] = await this.registerEvent(moduleWithEventName, params); - const registrationResponse = {}; - registrationResponse['eventName'] = moduleWithEventName; - registrationResponse['eventListenerId'] = uniqueListenerKey; - if (listenerResponse && Number.isInteger(listenerResponse) && listenerResponse > 0) { - registrationResponse['eventListenerResponse'] = { - listenerResponse: listenerResponse, - error: null, - }; - // Handling not supported api to check error schema if it gives a valid response - let schemaValidationResult = {}; - let schemaValidationStatus = CONSTANTS.PASS; - if (message.params.isNotSupportedApi == true) { - schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE); - schemaValidationStatus = CONSTANTS.FAIL; - } - registrationResponse['eventListenerSchemaResult'] = { - status: schemaValidationStatus, - eventSchemaResult: schemaValidationResult, - }; - eventHandlerMap.get(uniqueListenerKey).setEventListener(registrationResponse); - } else { - if (CONSTANTS.ERROR_LIST.includes(listenerResponse.message)) { - responseCode = CONSTANTS.STATUS_CODE[3]; - registrationResponse['responseCode'] = responseCode; - } - registrationResponse['eventListenerResponse'] = { result: null, error: listenerResponse }; - // In case of error, validate error against errorschema - const schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE); - if (schemaValidationResult && schemaValidationResult.errors && schemaValidationResult.errors.length > 0) { - registrationResponse['eventListenerSchemaResult'] = { - status: CONSTANTS.FAIL, - eventSchemaResult: {}, + + if (process.env.STANDALONE == true) { + registrationResponse['eventName'] = moduleWithEventName; + registrationResponse['eventListenerId'] = uniqueListenerKey; + if (listenerResponse && Number.isInteger(listenerResponse) && listenerResponse > 0) { + registrationResponse['eventListenerResponse'] = { + listenerResponse: listenerResponse, + error: null, }; - } else { + // Handling not supported api to check error schema if it gives a valid response + let schemaValidationResult = {}; + let schemaValidationStatus = CONSTANTS.PASS; + if (message.params.isNotSupportedApi == true) { + schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE); + schemaValidationStatus = CONSTANTS.FAIL; + } registrationResponse['eventListenerSchemaResult'] = { - status: CONSTANTS.PASS, + status: schemaValidationStatus, eventSchemaResult: schemaValidationResult, }; + eventHandlerMap.get(uniqueListenerKey).setEventListener(registrationResponse); + } else { + if (CONSTANTS.ERROR_LIST.includes(listenerResponse.message)) { + const responseCode = CONSTANTS.STATUS_CODE[3]; + registrationResponse['responseCode'] = responseCode; + } + registrationResponse['eventListenerResponse'] = { result: null, error: listenerResponse }; + // In case of error, validate error against errorschema + const schemaValidationResult = errorSchemaCheck(listenerResponse, process.env.COMMUNICATION_MODE); + if (schemaValidationResult && schemaValidationResult.errors && schemaValidationResult.errors.length > 0) { + registrationResponse['eventListenerSchemaResult'] = { + status: CONSTANTS.FAIL, + eventSchemaResult: {}, + }; + } else { + registrationResponse['eventListenerSchemaResult'] = { + status: CONSTANTS.PASS, + eventSchemaResult: schemaValidationResult, + }; + } + } + return registrationResponse; + } else { + registrationResponse['jsonrpc'] = '2.0'; + registrationResponse['id'] = null; + if (listenerResponse && Number.isInteger(listenerResponse) && listenerResponse > 0) { + registrationResponse['id'] = listenerResponse; + registrationResponse['result'] = { + listening: true, + event: moduleWithEventName, + }; + eventHandlerMap.get(uniqueListenerKey).setEventListener(registrationResponse); + } else { + registrationResponse['error'] = listenerResponse; } + return registrationResponse; } - return registrationResponse; } // This method will listen to event and capture the event response after triggering @@ -298,8 +326,13 @@ export class EventInvocation { // Return the event response object for the eventName passed as the param getEventResponse(message) { try { + let filteredEventDataObjectList; const eventName = message.params.event; - const filteredEventDataObjectList = eventHistory.filter((element) => element.eventListenerId == eventName); + if (process.env.STANDALONE == true) { + filteredEventDataObjectList = eventHistory.filter((element) => element.eventListenerId == eventName); + } else { + filteredEventDataObjectList = eventHistory.filter((element) => element.eventListenerId.toString() == eventName.split('-').pop()); + } if (filteredEventDataObjectList.length) { const eventDataObject = filteredEventDataObjectList[filteredEventDataObjectList.length - 1]; return eventDataObject; diff --git a/src/FireboltExampleInvoker.js b/src/FireboltExampleInvoker.js index 14afe21f..ffa1f666 100644 --- a/src/FireboltExampleInvoker.js +++ b/src/FireboltExampleInvoker.js @@ -36,6 +36,7 @@ import { AudioDescriptions, HDMIInput, } from '@firebolt-js/manage-sdk'; +import { Content } from '@firebolt-js/discovery-sdk'; import DiscoveryInvoker from './invokers/DiscoveryInvoker'; const discoveryInvoker = new DiscoveryInvoker(); const logger = require('./utils/Logger')('FireboltExampleInvoker.js'); @@ -48,7 +49,7 @@ const MAP = { 'discovery.purchasedContent': discoveryInvoker.purchasedContent.bind(discoveryInvoker), 'discovery.entityInfo': discoveryInvoker.entityInfo.bind(discoveryInvoker), // 'content.purchases': discoveryInvoker.getPurchasedContent.bind(discoveryInvoker), - // 'content.entity': discoveryInvoker.getEntityInfo.bind(discoveryInvoker) + // 'content.entity': discoveryInvoker.getEntityInfo.bind(discoveryInvoker), }; const CORE_MODULE_MAP = { @@ -89,9 +90,14 @@ const MANAGE_MODULE_MAP = { hdmiinput: HDMIInput, }; +const DISCOVERY_MODULE_MAP = { + content: Content, +}; + export const MODULE_MAP = { core: CORE_MODULE_MAP, manage: MANAGE_MODULE_MAP, + discovery: DISCOVERY_MODULE_MAP, }; let instance = null; diff --git a/src/MenuBuilder.js b/src/MenuBuilder.js index 4d2fdb76..c17fcf31 100644 --- a/src/MenuBuilder.js +++ b/src/MenuBuilder.js @@ -169,18 +169,18 @@ export default class MenuBuilder { const certificationMenu = []; const sdkMenuArray = this.constructMenuBasedOnMode(CONSTANTS.SDK); + const sdkMenuObject = this.createMenuObject(CONSTANTS.SDK, sdkMenuArray); + certificationMenu.push(sdkMenuObject); + + const transportMenuArray = this.constructMenuBasedOnMode(CONSTANTS.TRANSPORT); CONSTANTS.additionalSDKs.forEach( function (sdkObject) { const sdkObjectCopy = { ...sdkObject }; // dynamically construct menu items using additionalSDKs config const menuObject = this.createSubMenuObject(sdkObjectCopy.name, ValidationView, sdkObjectCopy.name, CONSTANTS.SDK); - sdkMenuArray.push(menuObject); + transportMenuArray.push(menuObject); }.bind(this) ); - const sdkMenuObject = this.createMenuObject(CONSTANTS.SDK, sdkMenuArray); - certificationMenu.push(sdkMenuObject); - - const transportMenuArray = this.constructMenuBasedOnMode(CONSTANTS.TRANSPORT); const transportMenuObject = this.createMenuObject(CONSTANTS.TRANSPORT, transportMenuArray); certificationMenu.push(transportMenuObject); return [...certificationMenu]; diff --git a/src/MethodInvoker.js b/src/MethodInvoker.js index 73eb9bd3..d5d2305b 100644 --- a/src/MethodInvoker.js +++ b/src/MethodInvoker.js @@ -29,9 +29,8 @@ const responseList = []; export class MethodInvoker { // This method accepts the message(method name, params) and return Api response with Schema validation result. async invoke(message) { - let response, method, params, mode, err, paramNames, module, methodObj; - let schemaMap; - let schemaValidationResult; + let response, method, params, mode, err, paramNames, module, methodObj, schemaMap, schemaValidationResult; + process.env.ID = process.env.ID + 1; process.env.COMMUNICATION_MODE = message.context.communicationMode; params = message.params.methodParams; if (message.params.method.includes('_')) { @@ -70,12 +69,14 @@ export class MethodInvoker { try { // Fetching the method Object from the deSchemaList if (method.includes('set') && params[0] == undefined && !CONSTANTS.METHODS_T0_IGNORE_WHICH_HAS_SET.includes(method)) { - methodObj = deSchemaList.methods.find((obj) => obj.name.toLowerCase() == updatedMethod.toLowerCase()); + methodObj = deSchemaList.methods.some((obj) => obj.name.toLowerCase() == updatedMethod.toLowerCase()); } else { - methodObj = deSchemaList.methods.find((obj) => obj.name.toLowerCase() == method.toLowerCase()); + methodObj = deSchemaList.methods.some((obj) => obj.name.toLowerCase() == method.toLowerCase()); } if (methodObj) { - schemaMap = methodObj.result.schema; + if (process.env.STANDALONE == true) { + schemaMap = methodObj.result.schema; + } const moduleClass = MODULE_MAP[invokedSdk][module]; if (moduleClass) { @@ -88,16 +89,22 @@ export class MethodInvoker { } else if (process.env.COMMUNICATION_MODE === CONSTANTS.TRANSPORT) { [response, err] = await handleAsyncFunction(FireboltTransportInvoker.get().invoke(method, params, paramNames), process.env.TimeoutInMS); } - schemaValidationResult = validator.validate(response, schemaMap); + if (process.env.STANDALONE == true) { + schemaValidationResult = validator.validate(response, schemaMap); + } } else if (!methodObj && process.env.COMMUNICATION_MODE === CONSTANTS.TRANSPORT) { [response, err] = await handleAsyncFunction(FireboltTransportInvoker.get().invoke(method, params, paramNames), process.env.TimeoutInMS); - schemaValidationResult = []; + if (process.env.STANDALONE == true) { + schemaValidationResult = []; + } } else { err = CONSTANTS.ERROR_MESSAGE_WRONG_METHOD_NAME; } - // if the method is not supported and it gives a valid response, validate against errorschema instead of api schema - if (message.params.isNotSupportedApi == true && response != undefined) { - schemaValidationResult = errorSchemaCheck(response, process.env.COMMUNICATION_MODE); + if (process.env.STANDALONE == true) { + // if the method is not supported and it gives a valid response, validate against errorschema instead of api schema + if (message.params.isNotSupportedApi == true && response != undefined) { + schemaValidationResult = errorSchemaCheck(response, process.env.COMMUNICATION_MODE); + } } } catch (error) { logger.error('Error: ', error); @@ -113,8 +120,15 @@ export class MethodInvoker { }, }; responseList.push(resultObject); - - return this.formatResult(message.task, response, err, schemaValidationResult, params, schemaMap); + if (process.env.STANDALONE == true) { + return this.formatResult(message.task, response, err, schemaValidationResult, params, schemaMap); + } else { + if (err === undefined) { + return { jsonrpc: '2.0', result: response, id: process.env.ID }; + } else { + return { jsonrpc: '2.0', error: err, id: process.env.ID }; + } + } } formatResult(task, response, err, schemaValidationResult, params, schemaMap) { diff --git a/src/Test_Runner.js b/src/Test_Runner.js index 836e8284..3f46f0f4 100644 --- a/src/Test_Runner.js +++ b/src/Test_Runner.js @@ -490,7 +490,7 @@ export class Test_Runner { executionMode = executionMode.toUpperCase(); apiExecutionStartTime = new Date(); // api execution start time - if (executionMode.includes(CONSTANTS.MANAGE) || executionMode.includes(CONSTANTS.CORE)) { + if (executionMode.includes(CONSTANTS.MANAGE) || executionMode.includes(CONSTANTS.CORE) || executionMode.includes(CONSTANTS.DISCOVERY)) { [response, err] = paramsArray ? await handleAsyncFunction(FireboltTransportInvoker.get().invoke(method, params, paramsArray)) : await handleAsyncFunction(FireboltExampleInvoker.get().invoke(sdk, method, params, null, paramsArray)); @@ -555,13 +555,19 @@ export class Test_Runner { case CONSTANTS.LIFECYCLE_METHOD_LIST[0]: try { result = await this.lifecycleMethodCalls(method, params); - const stateSchema = this.getMethodSchema('Lifecycle.ready', lifecycleMethods); - schemaResult = this.schemaValidation(result.response, stateSchema); + if (process.env.STANDALONE == true) { + const stateSchema = this.getMethodSchema('Lifecycle.ready', lifecycleMethods); + schemaResult = this.schemaValidation(result.response, stateSchema); + } } catch (err) { error = err; result.error = error; } - response = this.createResultObject(result.response, result.error, schemaResult); + if (process.env.STANDALONE == true) { + response = this.createResultObject(result.response, result.error, schemaResult); + } else { + response = this.createResultObject(result.response, result.error); + } break; case CONSTANTS.LIFECYCLE_METHOD_LIST[1]: /* @@ -571,24 +577,36 @@ export class Test_Runner { */ try { result = await this.lifecycleMethodCalls(method, params); - const stateSchema = this.getMethodSchema('Lifecycle.state', lifecycleMethods); - schemaResult = this.schemaValidation(result.response, stateSchema); + if (process.env.STANDALONE == true) { + const stateSchema = this.getMethodSchema('Lifecycle.state', lifecycleMethods); + schemaResult = this.schemaValidation(result.response, stateSchema); + } } catch (err) { error = err; result.error = error; } - response = this.createResultObject(result.response, result.error, schemaResult); + if (process.env.STANDALONE == true) { + response = this.createResultObject(result.response, result.error, schemaResult); + } else { + response = this.createResultObject(result.response, result.error); + } break; case CONSTANTS.LIFECYCLE_METHOD_LIST[2]: try { result = await this.lifecycleMethodCalls(method, methods.methodParams); - const stateSchema = this.getMethodSchema('Lifecycle.close', lifecycleMethods); - schemaResult = this.schemaValidation(result.response, stateSchema); + if (process.env.STANDALONE == true) { + const stateSchema = this.getMethodSchema('Lifecycle.close', lifecycleMethods); + schemaResult = this.schemaValidation(result.response, stateSchema); + } } catch (err) { error = err; result.error = error; } - response = this.createResultObject(result.response, result.error, schemaResult); + if (process.env.STANDALONE == true) { + response = this.createResultObject(result.response, result.error, schemaResult); + } else { + response = this.createResultObject(result.response, result.error); + } break; case CONSTANTS.LIFECYCLE_METHOD_LIST[3]: @@ -609,52 +627,64 @@ export class Test_Runner { response = this.createResultObject(result, error); break; case CONSTANTS.LIFECYCLE_METHOD_LIST[5]: - try { - const OnInactiveEvent = LifecycleHistory.get(); - const OnInactiveHistory = OnInactiveEvent._history._value[0].event; - const OnInActiveList = this.getMethodSchema('Lifecycle.onInactive', lifecycleMethods); - schemaResult = this.schemaValidation(OnInactiveHistory, OnInActiveList); - if (OnInactiveHistory.state == 'inactive' && OnInactiveHistory.previous == 'initializing') { - contentResult = CONSTANTS.PASS; - } else { - contentResult = CONSTANTS.FAIL; + if (process.env.STANDALONE == true) { + try { + const OnInactiveEvent = LifecycleHistory.get(); + const OnInactiveHistory = OnInactiveEvent._history._value[0].event; + const OnInActiveList = this.getMethodSchema('Lifecycle.onInactive', lifecycleMethods); + schemaResult = this.schemaValidation(OnInactiveHistory, OnInActiveList); + if (OnInactiveHistory.state == 'inactive' && OnInactiveHistory.previous == 'initializing') { + contentResult = CONSTANTS.PASS; + } else { + contentResult = CONSTANTS.FAIL; + } + } catch (err) { + error = err; } - } catch (err) { - error = err; + response = this.createResultObject(result, error, schemaResult, contentResult); + } else { + response = this.createResultObject(result, error); } - response = this.createResultObject(result, error, schemaResult, contentResult); break; case CONSTANTS.LIFECYCLE_METHOD_LIST[6]: - try { - const onForegroundEvent = LifecycleHistory.get(); - const onForegroundHistory = onForegroundEvent._history._value[1].event; - const onForegroundList = this.getMethodSchema('Lifecycle.onForeground', lifecycleMethods); - schemaResult = this.schemaValidation(onForegroundHistory, onForegroundList); - if (onForegroundHistory.state == 'foreground' && onForegroundHistory.previous == 'inactive') { - contentResult = CONSTANTS.PASS; - } else { - contentResult = CONSTANTS.FAIL; + if (process.env.STANDALONE == true) { + try { + const onForegroundEvent = LifecycleHistory.get(); + const onForegroundHistory = onForegroundEvent._history._value[1].event; + const onForegroundList = this.getMethodSchema('Lifecycle.onForeground', lifecycleMethods); + schemaResult = this.schemaValidation(onForegroundHistory, onForegroundList); + if (onForegroundHistory.state == 'foreground' && onForegroundHistory.previous == 'inactive') { + contentResult = CONSTANTS.PASS; + } else { + contentResult = CONSTANTS.FAIL; + } + } catch (err) { + error = err; } - } catch (err) { - error = err; + response = this.createResultObject(result, error, schemaResult, contentResult); + } else { + response = this.createResultObject(result, error); } - response = this.createResultObject(result, error, schemaResult, contentResult); break; case CONSTANTS.LIFECYCLE_METHOD_LIST[7]: - try { - const onBackgroundEvent = LifecycleHistory.get(); - const onBackgroundHistory = onBackgroundEvent._history._value[2].event; - const onBackgroundList = this.getMethodSchema('Lifecycle.onBackground', lifecycleMethods); - schemaResult = this.schemaValidation(onBackgroundHistory, onBackgroundList); - if (onBackgroundHistory.state == 'background' && onBackgroundHistory.previous == 'foreground') { - contentResult = CONSTANTS.PASS; - } else { - contentResult = CONSTANTS.FAIL; + if (process.env.STANDALONE == true) { + try { + const onBackgroundEvent = LifecycleHistory.get(); + const onBackgroundHistory = onBackgroundEvent._history._value[2].event; + const onBackgroundList = this.getMethodSchema('Lifecycle.onBackground', lifecycleMethods); + schemaResult = this.schemaValidation(onBackgroundHistory, onBackgroundList); + if (onBackgroundHistory.state == 'background' && onBackgroundHistory.previous == 'foreground') { + contentResult = CONSTANTS.PASS; + } else { + contentResult = CONSTANTS.FAIL; + } + } catch (err) { + error = err; } - } catch (err) { - error = err; + response = this.createResultObject(result, error, schemaResult, contentResult); + } else { + response = this.createResultObject(result, error); } - response = this.createResultObject(result, error, schemaResult, contentResult); break; case CONSTANTS.LIFECYCLE_METHOD_LIST[8]: result = await this.lifecycleMethodCalls(method, params); @@ -677,7 +707,6 @@ export class Test_Runner { } return response; } - getMethodSchema(method, apiSchema) { const methodSchema = []; for (let i = 0; i < apiSchema.length; i++) { @@ -712,13 +741,30 @@ export class Test_Runner { }; } - createResultObject(result, error, schemaResult, contentResult) { - const resultObject = { - result: result, - error: error, - schemaResult: schemaResult, - contentResult: contentResult, - }; + createResultObject(result, error) { + let resultObject; + if (process.env.STANDALONE == true) { + resultObject = { + result: result, + error: error, + schemaResult: schemaResult, + contentResult: contentResult, + }; + } else { + if (error == null) { + resultObject = { + jsonrpc: '2.0', + result: result, + id: process.env.ID + 1, + }; + } else { + resultObject = { + jsonrpc: '2.0', + error: error, + id: process.env.ID + 1, + }; + } + } return resultObject; } diff --git a/src/constant.js b/src/constant.js index 116b9cae..7e0ec2d8 100644 --- a/src/constant.js +++ b/src/constant.js @@ -19,6 +19,7 @@ import CONFIG_CONSTANTS from 'config'; import CORE_OPEN_RPC from '@firebolt-js/sdk/dist/firebolt-core-open-rpc'; import MANAGE_OPEN_RPC from '@firebolt-js/manage-sdk/dist/firebolt-manage-open-rpc'; +import DISCOVERY_OPEN_RPC from '@firebolt-js/discovery-sdk/dist/firebolt-discovery-open-rpc'; export const CONSTANTS = { ALL_SDKS: 'ALL SDKS', SDK: 'SDK', @@ -106,6 +107,7 @@ export const CONSTANTS = { EXCEPTION_METHODS: [], CORE: 'CORE', MANAGE: 'MANAGE', + DISCOVERY: 'DISCOVERY', FIREBOLT_ALL: 'FIREBOLT-ALL', ERROR_MESSAGE_WRONG_METHOD_NAME: { code: -32601, message: 'Wrong Method Name' }, INVALID_REQUEST_TYPE: 'Error: Invalid requestType', @@ -138,6 +140,7 @@ export const CONSTANTS = { WRONG_RESPONSE_MESSAGE_FORMAT: 'Unexpected error format encountered in the response', EXCLUDED_METHODS_FOR_SDK: [], EXCLUDED_METHODS_FOR_TRANSPORT: [], + REGISTERPROVIDER: 'registerprovider', defaultSDKs: [ { name: 'Core', @@ -155,6 +158,14 @@ export const CONSTANTS = { }, unavailableMessage: 'MockOs is not running', }, + { + name: 'Discovery', + openRpc: DISCOVERY_OPEN_RPC, + validation: function () { + return !(process.env.MF_VALUE && !process.env.MOCKOS); + }, + unavailableMessage: 'MockOs is not running', + }, ], additionalSDKs: [], diff --git a/src/invokers/DiscoveryInvoker.js b/src/invokers/DiscoveryInvoker.js index 854ecd73..8677bb5e 100644 --- a/src/invokers/DiscoveryInvoker.js +++ b/src/invokers/DiscoveryInvoker.js @@ -17,7 +17,6 @@ */ import { Discovery } from '@firebolt-js/sdk'; -// import { Content } from '@firebolt-js/discovery-sdk' import { testDataHandler, filterExamples } from '../utils/Utils'; const MOCK_PURCHASED_CONTENT = { diff --git a/src/providers/KeyboardUIProvider.js b/src/providers/KeyboardUIProvider.js index af31ffea..6c56a7b5 100644 --- a/src/providers/KeyboardUIProvider.js +++ b/src/providers/KeyboardUIProvider.js @@ -68,11 +68,11 @@ export default class KeyboardUIProvider { session: { onDone: (keyboard, text) => { this._app.overlayDismissTimer = setTimeout(() => this._app.$dismissOverlay(), 500); // Try and get lightning-ui component to use onkeyup - responder({ text, canceled: false }); + responder(text); }, onCancel: (keyboard) => { this._app.$dismissOverlay(); - responder({ text: '', canceled: true }); + responder(''); }, mask: mask, title: session.message, diff --git a/src/providers/KeyboardUIProviderTest.js b/src/providers/KeyboardUIProviderTest.js index 651868bd..f34b1d89 100644 --- a/src/providers/KeyboardUIProviderTest.js +++ b/src/providers/KeyboardUIProviderTest.js @@ -39,7 +39,7 @@ export default class KeyboardUIProviderTest { }); } else { this._app.$dismissOverlay(); - return Promise.resolve({ text: process.env.ApiText, canceled: process.env.isCancelled }); + return Promise.resolve(process.env.ApiText); } } @@ -56,7 +56,7 @@ export default class KeyboardUIProviderTest { }); } else { this._app.$dismissOverlay(); - return Promise.resolve({ text: process.env.ApiText, canceled: process.env.isCancelled }); + return Promise.resolve(process.env.ApiText); } } @@ -73,7 +73,7 @@ export default class KeyboardUIProviderTest { }); } else { this._app.$dismissOverlay(); - return Promise.resolve({ text: process.env.ApiText, canceled: process.env.isCancelled }); + return Promise.resolve(process.env.ApiText); } } @@ -108,7 +108,7 @@ export default class KeyboardUIProviderTest { onDone(responder, text, isCancelled) { setTimeout(() => this._app.$dismissOverlay(), 500); // Try and get lightning-ui component to use onkeyup - responder({ text, canceled: isCancelled }); + responder(text); } sleep(ms) { diff --git a/src/providers/UserInterestDelegater.js b/src/providers/UserInterestDelegater.js new file mode 100644 index 00000000..c513d30b --- /dev/null +++ b/src/providers/UserInterestDelegater.js @@ -0,0 +1,30 @@ +/** + * Copyright 2023 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import UserIntrestProvider from './UserInterestProvider'; + +export default class UserIntrestDelegater { + constructor() { + this.delegate = new UserIntrestProvider(); + process.env.UserInterestDelegater = this; + } + + userInterest() { + return this.delegate.userInterest(); + } +} diff --git a/src/providers/UserInterestProvider.js b/src/providers/UserInterestProvider.js new file mode 100644 index 00000000..77178b5a --- /dev/null +++ b/src/providers/UserInterestProvider.js @@ -0,0 +1,39 @@ +/** + * Copyright 2023 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +export default class UserIntrestProvider { + userInterest() { + try { + if (process.env.userInterestError == null || process.env.userInterestError.toLowerCase() != 'timeout') { + if (process.env.userInterestError && process.env.userInterestError.toLowerCase() == 'error') { + return Promise.reject({ code: 1000, message: 'Custom error from provider' }); + } else { + const USERINTERESTDATA = require('../source/userInterest.json'); + if (USERINTERESTDATA.hasOwnProperty(process.env.userInterestKey)) { + const data = USERINTERESTDATA[process.env.userInterestKey]; + return Promise.resolve(data); + } else { + return Promise.resolve(null); + } + } + } + } catch (err) { + logger.error('Error in userInterest provider: ', err.message); + } + } +} diff --git a/src/pubSubClient.js b/src/pubSubClient.js index 6a5deedf..1a65c668 100644 --- a/src/pubSubClient.js +++ b/src/pubSubClient.js @@ -15,16 +15,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ - const logger = require('../src/utils/Logger')('pubSubClient.js'); require('dotenv').config({ override: true }); -const defaultWsUrl = 'ws://your-ws-url-here.com'; - class PubSubClient { constructor() { this.ws = null; - this.url = defaultWsUrl; + this.url = process.env.PUB_SUB_URL ? process.env.PUB_SUB_URL : 'ws://localhost:8080'; this.PUBSUB_SUBSCRIBE_TOPIC_SUFFIX = '_FCS'; this.PUBSUB_PUBLISH_TOPIC_SUFFIX = '_FCA'; } @@ -35,6 +32,7 @@ class PubSubClient { const appUrl = window.location; const pubSubTopicUUID = new URLSearchParams(appUrl.search).get('pubsub_uuid'); const macAddress = process.env.MACADDRESS; + const appId = process.env.CURRENT_APPID; // Priority #1: Use pubSubTopicUUID if it's available if (pubSubTopicUUID) { @@ -51,12 +49,12 @@ class PubSubClient { console.warn(`WARNING: No pubsub_uuid query parameter or MAC address found. Using default value: ${pubSubTopic}`); } - process.env.PUBSUB_SUBSCRIBE_TOPIC = pubSubTopic + this.PUBSUB_SUBSCRIBE_TOPIC_SUFFIX; - process.env.PUBSUB_PUBLISH_TOPIC = pubSubTopic + this.PUBSUB_PUBLISH_TOPIC_SUFFIX; + process.env.PUBSUB_SUBSCRIBE_TOPIC = pubSubTopic + '_' + appId + this.PUBSUB_SUBSCRIBE_TOPIC_SUFFIX; + process.env.PUBSUB_PUBLISH_TOPIC = pubSubTopic + '_' + appId + this.PUBSUB_PUBLISH_TOPIC_SUFFIX; // Establish WS Connection this.ws = new WebSocket(this.url); - logger.info('Establishing a WS connection...', 'initialize'); + logger.info(`Establishing a WS connection to ${this.url}...`, 'initialize'); return new Promise((resolve, reject) => { this.ws.addEventListener('open', (event) => { @@ -65,13 +63,13 @@ class PubSubClient { }); this.ws.addEventListener('error', (event) => { - if (this.url === defaultWsUrl) { - logger.error('WARNING: WebSocket connections will fail to initialize. The file has not been properly configured. Please update the URL to point to your WebSocket server for communication to work.'); - } else { - logger.error('Failed to initialize a WS connection...', 'initialize'); - } + logger.info('Failed to initialize a WS connection...', event); + this.ws = null; // Ensure ws is null if connection fails reject(false); }); + }).catch((error) => { + logger.info('Continuing without PubSub due to WS connection failure.'); + return false; }); } @@ -82,6 +80,11 @@ class PubSubClient { return false; } + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + logger.error('WS connection is not open. Cannot publish message.'); + return false; + } + const publishMsg = { operation: 'pub', topic, @@ -92,7 +95,7 @@ class PubSubClient { // If headers are passed in, add them to the payload object if (headers) { - payload.payload.headers = headers; + publishMsg.payload.headers = headers; } logger.info('Publishing message: ', JSON.stringify(publishMsg)); @@ -109,6 +112,11 @@ class PubSubClient { // Subscribe to a topic subscribe(topic, callback) { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + logger.error('WS connection is not open. Cannot subscribe to topic.'); + return false; + } + const subscribeMsg = { operation: 'sub', topic, @@ -146,6 +154,11 @@ class PubSubClient { // Unsubscribe to a topic unsubscribe(topic) { + if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { + logger.error('WS connection is not open. Cannot unsubscribe from topic.'); + return false; + } + const payload = { operation: 'unsub', topic, @@ -164,8 +177,8 @@ class PubSubClient { // Checks WebSocket connection status isConnected() { let status = false; - if (this.ws && this.ws.readyState == this.ws.OPEN) { - logger.info('WS connection already Established'); + if (this.ws && this.ws.readyState === WebSocket.OPEN) { + logger.info('WS connection already established'); status = true; } return status; @@ -174,7 +187,11 @@ class PubSubClient { const getClient = async () => { const pubSubClient = new PubSubClient(); - await pubSubClient.initialize(); + try { + await pubSubClient.initialize(); + } catch (error) { + logger.error(error); + } return pubSubClient; }; diff --git a/src/pubsub/handlers/CallMethodHandler.js b/src/pubsub/handlers/CallMethodHandler.js index 63fc7ccd..ac98b8bb 100644 --- a/src/pubsub/handlers/CallMethodHandler.js +++ b/src/pubsub/handlers/CallMethodHandler.js @@ -48,13 +48,21 @@ export default class CallMethodHandler extends BaseHandler { process.env.TimeoutInMS = message.responseTimeout ? message.responseTimeout : null; const result = await invoker.invoke(message); - return JSON.stringify({ report: result }); + if (process.env.STANDALONE == true) { + return JSON.stringify({ report: result }); + } else { + return JSON.stringify(result); + } } catch (e) { const result = { responseCode: CONSTANTS.STATUS_CODE[1], error: { message: 'FCA in exception block: ' + e.message, code: 'FCAError' }, }; - return JSON.stringify({ report: result }); + if (process.env.STANDALONE == true) { + return JSON.stringify({ report: result }); + } else { + return JSON.stringify(result); + } } } } diff --git a/src/pubsub/handlers/GetEventResponse.js b/src/pubsub/handlers/GetEventResponse.js index 4a9ff571..06713b7c 100644 --- a/src/pubsub/handlers/GetEventResponse.js +++ b/src/pubsub/handlers/GetEventResponse.js @@ -28,6 +28,11 @@ export default class GetEventResponse extends BaseHandler { async handle(message) { const eventInvocation = new EventInvocation(); const validationReport = eventInvocation.getEventResponse(message); - return JSON.stringify({ report: validationReport }); + if (process.env.STANDALONE == true) { + return JSON.stringify({ report: validationReport }); + } else { + const validationReportObject = { jsonrpc: '2.0', result: validationReport, id: process.env.ID + 1 }; + return JSON.stringify(validationReportObject); + } } } diff --git a/src/pubsub/handlers/LifecycleMethodHandler.js b/src/pubsub/handlers/LifecycleMethodHandler.js index 32dda655..f1a3ee6e 100644 --- a/src/pubsub/handlers/LifecycleMethodHandler.js +++ b/src/pubsub/handlers/LifecycleMethodHandler.js @@ -19,6 +19,7 @@ import BaseHandler from './BaseHandler'; import { Test_Runner } from 'Test_Runner'; const logger = require('../../utils/Logger')('LifecycleMethodHandler.js'); +import { CONSTANTS } from '../../constant'; const { v4: uuidv4 } = require('uuid'); require('dotenv').config(); @@ -32,13 +33,21 @@ export default class LifecycleMethodHandler extends BaseHandler { const sdkInvokerInfo = new Test_Runner(); try { const lifecycleApiResponse = await sdkInvokerInfo.invokeLifecycleAPI(message.params); - return JSON.stringify({ report: lifecycleApiResponse }); + if (process.env.STANDALONE == true) { + return JSON.stringify({ report: lifecycleApiResponse }); + } else { + return JSON.stringify(lifecycleApiResponse); + } } catch (e) { const result = { responseCode: CONSTANTS.STATUS_CODE[1], error: { message: 'FCA in exception block: ' + e.message, code: 'FCAError' }, }; - return JSON.stringify({ report: result }); + if (process.env.STANDALONE == true) { + return JSON.stringify({ report: result }); + } else { + return JSON.stringify(result); + } } } } diff --git a/src/pubsub/handlers/RegisterEventHandler.js b/src/pubsub/handlers/RegisterEventHandler.js index a7c176ab..c60cb539 100644 --- a/src/pubsub/handlers/RegisterEventHandler.js +++ b/src/pubsub/handlers/RegisterEventHandler.js @@ -29,7 +29,11 @@ export default class RegisterEventHandler extends BaseHandler { async handle(message) { const validationReport = await this.eventSwitchMode(message); - return JSON.stringify({ report: validationReport }); + if (process.env.STANDALONE == true) { + return JSON.stringify({ report: validationReport }); + } else { + return JSON.stringify(validationReport); + } } async eventSwitchMode(message) { @@ -50,7 +54,7 @@ export default class RegisterEventHandler extends BaseHandler { let validatedMenu; // Switch creation for the type of invocation that needs to happen. - if ([CONSTANTS.CORE.toLowerCase(), CONSTANTS.MANAGE.toLowerCase()].includes(sdkType)) { + if ([CONSTANTS.CORE.toLowerCase(), CONSTANTS.MANAGE.toLowerCase(), CONSTANTS.DISCOVERY.toLowerCase()].includes(sdkType)) { validatedMenu = await eventInvokerInfo.northBoundEventHandling(message); } else { validatedMenu = { diff --git a/src/pubsub/handlers/VisibilityStateHandler.js b/src/pubsub/handlers/VisibilityStateHandler.js index 7e835e9e..cd56ef75 100644 --- a/src/pubsub/handlers/VisibilityStateHandler.js +++ b/src/pubsub/handlers/VisibilityStateHandler.js @@ -25,11 +25,17 @@ export default class VisibilityStateHandler extends BaseHandler { super(handlerName); } - async handle() { + async handle(message) { try { - const visibilityState = window.document.visibilityState; - const reportIdString = JSON.stringify({ report: visibilityState }); - return reportIdString; + if (message.params.params && message.params.params == 'visibilityState') { + const visibilityState = window.document.visibilityState; + const reportIdString = JSON.stringify({ report: visibilityState }); + return reportIdString; + } else if (message.params.params && message.params.params == 'language') { + const language = window.navigator.language; + const reportIdString = JSON.stringify({ report: language }); + return reportIdString; + } } catch (e) { const result = { responseCode: CONSTANTS.STATUS_CODE[1], diff --git a/src/pubsub/handlers/setApiResponseHandler.js b/src/pubsub/handlers/setApiResponseHandler.js index 7c792b3e..364e26de 100644 --- a/src/pubsub/handlers/setApiResponseHandler.js +++ b/src/pubsub/handlers/setApiResponseHandler.js @@ -43,6 +43,8 @@ export default class SetApiResponseHandler extends BaseHandler { return this.setResponseFederatedDataPurchasedContent(message); case 'ackchallenge': return this.setResponseAckChallenge(message); + case 'userinterest': + return this.setResponseUserInterestChallenge(message); default: const defaultIdString = JSON.stringify({ report: 'Selected module provider is not available', @@ -92,4 +94,12 @@ export default class SetApiResponseHandler extends BaseHandler { return reportIdString; } + + setResponseUserInterestChallenge(message) { + const userInterestData = message.params.apiResponse.attributes[0]; + process.env.userInterestKey = userInterestData.userInterestKey; + process.env.userInterestError = userInterestData.userInterestError; + const reportIdString = JSON.stringify({ report: 'Received UserInterest apiResponse parameters' }); + return reportIdString; + } } diff --git a/src/source/userInterest.json b/src/source/userInterest.json new file mode 100644 index 00000000..d3d85e90 --- /dev/null +++ b/src/source/userInterest.json @@ -0,0 +1,63 @@ +{ + "USERINTEREST_PLAYLIST": { + "identifiers": { + "entityId": "345", + "entityType": "playlist" + }, + "info": { + "title": "User Interest", + "synopsis": "User Interest request provider", + "releaseDate": "1993-01-01T00:00:00.000Z", + "contentRatings": [ + { + "scheme": "US-Movie", + "rating": "PG" + }, + { + "scheme": "CA-Movie", + "rating": "G" + } + ] + } + }, + "USERINTEREST_REACTION": { + "identifiers": { + "entityId": "123", + "entityType": "channel", + "channelType": "streaming" + }, + "info": { + "title": "User Interest", + "synopsis": "User Interest request provider", + "releaseDate": "1993-01-01T00:00:00.000Z", + "contentRatings": [ + { + "scheme": "US-Movie", + "rating": "PG" + }, + { + "scheme": "CA-Movie", + "rating": "G" + } + ] + } + }, + "USERINTEREST_RECORDING": { + "identifiers": { + "entityId": "981", + "entityType": "music", + "musicType": "song" + }, + "info": { + "title": "User Interest", + "synopsis": "User Interest request provider", + "releaseDate": "1993-01-01T00:00:00.000Z", + "contentRatings": [ + { + "scheme": "US-TV", + "rating": "PG" + } + ] + } + } +} \ No newline at end of file diff --git a/src/utils/Utils.js b/src/utils/Utils.js index 22940a25..1d954147 100644 --- a/src/utils/Utils.js +++ b/src/utils/Utils.js @@ -150,7 +150,7 @@ function pushReportToS3(report) { const parser = new xml2js.Parser(); let parsingSuccessful = false; if (!process.env.MACADDRESS) { - [result, err] = await handleAsyncFunction(FireboltExampleInvoker.get().invoke(CONSTANTS.CORE.toLowerCase(), 'Authentication.token', ['device'])); + [result, err] = await handleAsyncFunction(FireboltExampleInvoker.get().invoke(CONSTANTS.CORE.toLowerCase(), 'Authentication.root', [])); if (result && result.value && !err) { const bufferObj = Buffer.from(result.value, 'base64'); const xmlData = bufferObj.toString('utf8'); diff --git a/test/unit/CallMethodHandler.test.js b/test/unit/CallMethodHandler.test.js index f7bcfbef..b1158735 100644 --- a/test/unit/CallMethodHandler.test.js +++ b/test/unit/CallMethodHandler.test.js @@ -27,20 +27,9 @@ jest.mock('../../src/MethodInvoker', () => { switch (message.params.method) { case 'firebolt.mockMethod': return { - method: 'callMethod', - params: [], - responseCode: 0, - apiResponse: { result: 'mockFireboltResult', error: null }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: { - instance: 'mockFireboltResult', - schema: { type: 'string' }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, + id: 1, + result: 'mockFireboltResult', + jsonrpc: '2.0', }; default: throw new Error('Firebolt error'); @@ -55,20 +44,9 @@ jest.mock('externalInvokers', () => ({ myExternalInvoker: function () { this.invoke = () => Promise.resolve({ - method: 'callMethod', - params: [], - responseCode: 0, - apiResponse: { result: 'mockResult', error: null }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: { - instance: 'mockResult', - schema: { type: 'string' }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, + id: 1, + result: 'mockResult', + jsonrpc: '2.0', }); }, })); @@ -104,9 +82,9 @@ describe('CallMethodHandler', () => { const responseString = await callMethodHandler.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); expect(responseString).toBeTruthy(); - expect(responseString).toContain('report'); + expect(responseString).toContain('result'); const report = JSON.parse(responseString); - expect(report.report.apiResponse.result).toEqual('mockResult'); + expect(report.result).toEqual('mockResult'); }); test('Validate method invoker is invoked', async () => { const message = { @@ -123,9 +101,9 @@ describe('CallMethodHandler', () => { const responseString = await callMethodHandler.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); expect(responseString).toBeTruthy(); - expect(responseString).toContain('report'); + expect(responseString).toContain('result'); const report = JSON.parse(responseString); - expect(report.report.apiResponse.result).toEqual('mockFireboltResult'); + expect(report.result).toEqual('mockFireboltResult'); }); test('Validate exception handling', async () => { const message = { @@ -141,9 +119,8 @@ describe('CallMethodHandler', () => { const responseString = await callMethodHandler.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); const report = JSON.parse(responseString); - expect(report.report.responseCode).toEqual(1); // indicating failure - expect(report.report.error.code).toEqual('FCAError'); // indicating failure is within FCA app - expect(report.report.error.message).toContain('FCA in exception block'); // indicating failure is within FCA app + expect(report.error.code).toEqual('FCAError'); // indicating failure is within FCA app + expect(report.error.message).toContain('FCA in exception block'); // indicating failure is within FCA app }); }); }); diff --git a/test/unit/EventInvocation.test.js b/test/unit/EventInvocation.test.js index 1a8b3e4e..b30fc89c 100644 --- a/test/unit/EventInvocation.test.js +++ b/test/unit/EventInvocation.test.js @@ -534,7 +534,7 @@ describe('EventInvocation', () => { const eventParams = { params: { event: 'mocksdk_mockmodule.onmodulechanged' } }; // register listener let result = await eventInvocation.northBoundEventHandling(eventParams); - expect(result.eventListenerId).toBeDefined(); + expect(result.id).toBeDefined(); // check no errors when no listeners are registered result = eventInvocation.clearAllListeners(); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); @@ -546,11 +546,11 @@ describe('EventInvocation', () => { const eventParams = { params: { event: 'mocksdk_mockmodule.onmodulechanged' } }; // register listener let result = await eventInvocation.northBoundEventHandling(eventParams); - expect(result.eventListenerId).toBeDefined(); + expect(result.id).toBeDefined(); // register second listener listener const eventParams1 = { params: { event: 'mocksdk_mockeventmodule.oneventmodulechanged' } }; const response = await eventInvocation.northBoundEventHandling(eventParams1); - expect(response.eventListenerId).toBeDefined(); + expect(response.id).toBeDefined(); // check no errors when no listeners are registered result = eventInvocation.clearAllListeners(); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); @@ -572,17 +572,18 @@ describe('EventInvocation', () => { test('validate EventInvocation method with communicationMode SDK', async () => { const eventParams = { params: { event: 'mocksdk_mockmodule.onmodulechanged' } }; const expectedResponse = { - eventName: 'mocksdk_mockmodule.onmodulechanged', - eventListenerId: 'mockmodule.onmodulechanged-1', - eventListenerResponse: { listenerResponse: 1, error: null }, - eventListenerSchemaResult: { status: 'PASS', eventSchemaResult: {} }, + jsonrpc: '2.0', + result: { + listening: true, + event: 'mocksdk_mockmodule.onmodulechanged', + }, + id: 4, }; const result = await eventInvocation.northBoundEventHandling(eventParams); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); expect(MODULE_MAP.mocksdk.mockmodule.listen).toHaveBeenCalled(); - // expect(result.eventListenerId).toBe(expectedResponse.eventListenerId) - expect(result.eventListenerResponse.error).toBeNull(); - expect(result.eventListenerSchemaResult.status).toEqual(expectedResponse.eventListenerSchemaResult.status); + expect(result.id).toBe(expectedResponse.id); + expect(result.result).not.toBeNull(); }); test('should fail if not supported api returns a valid response and not error object', async () => { @@ -590,46 +591,17 @@ describe('EventInvocation', () => { params: { event: 'mocksdk_mockmodule.onmodulechanged', isNotSupportedApi: true }, }; const expectedResponse = { - eventName: 'mocksdk_mockmodule.onmodulechanged', - eventListenerId: 'mockmodule.onmodulechanged-1', - eventListenerResponse: { listenerResponse: 1, error: null }, - eventListenerSchemaResult: { - status: 'FAIL', - eventSchemaResult: { - instance: 1, - schema: { - type: 'object', - properties: { code: { type: 'number' }, message: { type: 'string' } }, - required: ['code', 'message'], - }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [ - { - path: [], - property: 'instance', - message: 'is not of a type(s) object', - schema: { - type: 'object', - properties: { code: { type: 'number' }, message: { type: 'string' } }, - required: ['code', 'message'], - }, - instance: 1, - name: 'type', - argument: ['object'], - stack: 'instance is not of a type(s) object', - }, - ], - disableFormat: false, - }, + jsonrpc: '2.0', + result: { + listening: true, + event: 'mocksdk_mockmodule.onmodulechanged', }, + id: 4, }; const result = await eventInvocation.northBoundEventHandling(eventParams); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); expect(MODULE_MAP.mocksdk.mockmodule.listen).toHaveBeenCalled(); - expect(result.eventListenerResponse.error).toStrictEqual(expectedResponse.eventListenerResponse.error); - expect(result.eventListenerSchemaResult.status).toEqual(expectedResponse.eventListenerSchemaResult.status); + expect(result.error).toStrictEqual(expectedResponse.error); }); test('should pass if not supported api returns an error object', async () => { @@ -638,67 +610,36 @@ describe('EventInvocation', () => { isNotSupportedApi: true, }; const expectedResponse = { - eventName: 'mocksdk_mockmodule.onnotsupported', - eventListenerId: null, - eventListenerResponse: { - result: null, - error: { code: -52001, message: 'Method not supported' }, - }, - eventListenerSchemaResult: { - status: 'PASS', - eventSchemaResult: { - instance: { code: -52001, message: 'Method not supported' }, - schema: { - type: 'object', - properties: { code: { type: 'number' }, message: { type: 'string' } }, - required: ['code', 'message'], - }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, + jsonrpc: '2.0', + error: { + code: -52001, + message: 'Method not supported', }, + id: 16, }; const result = await eventInvocation.northBoundEventHandling(eventParams); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); expect(MODULE_MAP.mocksdk.mockmodule.listen).toHaveBeenCalled(); - expect(result.eventListenerResponse.error).toStrictEqual(expectedResponse.eventListenerResponse.error); - expect(result.eventListenerSchemaResult.status).toEqual(expectedResponse.eventListenerSchemaResult.status); + expect(result.error).toStrictEqual(expectedResponse.error); }); test('validate invalid EventInvocation method with communicationMode SDK - Method not found', async () => { const eventParams = { params: { event: 'mocksdk_mockmodule.oninvalidevent' } }; const expectedResponse = { - eventName: 'mocksdk_mockmodule.oninvalidevent', - eventListenerId: null, - responseCode: 3, - eventListenerResponse: { result: null, error: { code: '', message: 'Method not found' } }, - eventListenerSchemaResult: { status: 'FAIL', eventSchemaResult: {} }, - }; - const result = await eventInvocation.northBoundEventHandling(eventParams); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(MODULE_MAP.mocksdk.mockmodule.listen).toHaveBeenCalled(); - expect(result.eventListenerId).toBeNull(); - expect(result.responseCode).toBe(expectedResponse.responseCode); - expect(result.eventListenerResponse).toStrictEqual(expectedResponse.eventListenerResponse); - expect(result.eventListenerSchemaResult.status).toEqual(expectedResponse.eventListenerSchemaResult.status); - }); - test('validate invalid EventInvocation method with communicationMode SDK - schema failure', async () => { - const eventParams = { params: { event: 'mocksdk_mockmodule.oninvalidschema' } }; - const expectedResponse = { - eventName: 'mocksdk_mockmodule.oninvalidschema', - eventListenerId: 'mockmodule.oninvalidschema-[object Object]', - eventListenerResponse: { result: null, error: { listen: 2 } }, - eventListenerSchemaResult: { status: 'FAIL', eventSchemaResult: {} }, + jsonrpc: '2.0', + error: { + code: '', + message: 'Method not found', + }, + id: 16, }; const result = await eventInvocation.northBoundEventHandling(eventParams); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); expect(MODULE_MAP.mocksdk.mockmodule.listen).toHaveBeenCalled(); - expect(result.eventListenerResponse).toStrictEqual(expectedResponse.eventListenerResponse); - expect(result.eventListenerSchemaResult.status).toEqual(expectedResponse.eventListenerSchemaResult.status); + expect(result.id).toBeNull(); + expect(result.error).toStrictEqual(expectedResponse.error); }); + test('validate getEventResponse method', async () => { const message = { params: { event: 'lifecycle.onForeground' } }; await eventInvocation.getEventResponse(message); @@ -708,17 +649,19 @@ describe('EventInvocation', () => { process.env.COMMUNICATION_MODE = 'Transport'; const eventParams = { params: { event: 'mocksdk_mockmodule.onmodulechanged' } }; const expectedResponse = { - eventName: 'mocksdk_mockmodule.onmodulechanged', - eventListenerId: 'mockmodule.onmodulechanged-1', - eventListenerResponse: { listenerResponse: 1, error: null }, - eventListenerSchemaResult: { status: 'PASS', eventSchemaResult: {} }, + jsonrpc: '2.0', + result: { + listening: true, + event: 'mocksdk_mockmodule.onmodulechanged', + }, + id: 1, }; + const result = await eventInvocation.northBoundEventHandling(eventParams); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); expect(Transport.listen).toHaveBeenCalled(); - expect(result.eventListenerId).toBe(expectedResponse.eventListenerId); - expect(result.eventListenerResponse).toStrictEqual(expectedResponse.eventListenerResponse); - expect(result.eventListenerSchemaResult.status).toEqual(expectedResponse.eventListenerSchemaResult.status); + expect(result.id).toBe(expectedResponse.id); + expect(result.result).toStrictEqual(expectedResponse.result); }); }); @@ -811,7 +754,7 @@ describe('EventInvocation', () => { eventInvocation = new EventInvocation(); const eventParams = { params: { event: 'mocksdk_mockmodule.onmodulechanged' } }; const result = await eventInvocation.northBoundEventHandling(eventParams); - eventRegistrationID = result.eventListenerId; + eventRegistrationID = result.id; console.log('printing received eventRegistrationId: ' + eventRegistrationID); }); @@ -823,12 +766,11 @@ describe('EventInvocation', () => { test('should return event object with response - single event fired', () => { currentCallback({ foo: 'bar1' }); - const message = { params: { event: eventRegistrationID } }; + const message = { params: { event: 'accessibility.onClosedCaptionsSettingsChanged-6' } }; const expectedResponse = { eventName: 'modulechanged', - eventListenerId: eventRegistrationID, + eventListenerId: 6, eventResponse: { foo: 'bar1' }, - eventSchemaResult: { status: 'PASS', eventSchemaResult: [] }, eventTime: '2023-05-10T14:27:35.806Z', }; result = eventInvocation.getEventResponse(message); @@ -837,7 +779,6 @@ describe('EventInvocation', () => { eventName: expectedResponse.eventName, eventListenerId: expectedResponse.eventListenerId, eventResponse: expectedResponse.eventResponse, - eventSchemaResult: expectedResponse.eventSchemaResult, }); expect(result.eventTime).toBeDefined(); expect(result.eventTime).toBeInstanceOf(Date); @@ -845,12 +786,11 @@ describe('EventInvocation', () => { test('should return event object with last response - multiple events fired', () => { currentCallback({ foo: 'bar2' }); - const message = { params: { event: eventRegistrationID } }; + const message = { params: { event: 'accessibility.onClosedCaptionsSettingsChanged-6' } }; const expectedResponse = { eventName: 'modulechanged', - eventListenerId: eventRegistrationID, + eventListenerId: 6, eventResponse: { foo: 'bar2' }, - eventSchemaResult: { status: 'PASS', eventSchemaResult: [] }, eventTime: '2023-05-10T14:18:18.347Z', }; result = eventInvocation.getEventResponse(message); @@ -859,7 +799,6 @@ describe('EventInvocation', () => { eventName: expectedResponse.eventName, eventListenerId: expectedResponse.eventListenerId, eventResponse: expectedResponse.eventResponse, - eventSchemaResult: expectedResponse.eventSchemaResult, }); expect(result.eventTime).toBeDefined(); expect(result.eventTime).toBeInstanceOf(Date); @@ -895,31 +834,5 @@ describe('EventInvocation', () => { expect(result.error.code).toEqual(expectedResponse.error.code); expect(result.error.message).toBeDefined(); }); - - test('should return failure for schema', async () => { - // register for invalid schema - const message = { params: { event: eventRegistrationID } }; - const expectedResponse = { - eventName: 'modulechanged', - eventListenerId: eventRegistrationID, - eventResponse: true, - eventSchemaResult: { - status: 'FAIL', - eventSchemaResult: 'is not any of "ListenResponse","EventResponse"', - }, - eventTime: '2023-05-11T20:34:05.219Z', - }; - currentCallback(true); - result = eventInvocation.getEventResponse(message); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toMatchObject({ - eventName: expectedResponse.eventName, - eventListenerId: expectedResponse.eventListenerId, - eventResponse: expectedResponse.eventResponse, - eventSchemaResult: expectedResponse.eventSchemaResult, - }); - expect(result.eventTime).toBeDefined(); - expect(result.eventTime).toBeInstanceOf(Date); - }); }); }); diff --git a/test/unit/GetEventResponse.test.js b/test/unit/GetEventResponse.test.js index 51ac53af..defe74d5 100644 --- a/test/unit/GetEventResponse.test.js +++ b/test/unit/GetEventResponse.test.js @@ -55,8 +55,7 @@ describe('GetEventResponse Test Case', () => { const responseString = await getEventResponse.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); expect(responseString).toBeTruthy(); - expect(responseString).toContain('report'); - expect(responseString).toEqual('{"report":{"event":"null"}}'); + expect(JSON.parse(responseString).result).toEqual({ event: 'null' }); }); test('Event response- when no event is passed', async () => { @@ -64,7 +63,6 @@ describe('GetEventResponse Test Case', () => { const responseString = await getEventResponse.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); expect(responseString).toBeTruthy(); - expect(responseString).toContain('report'); - expect(responseString).toEqual('{"report":{"undefined":"null"}}'); + expect(JSON.parse(responseString).result).toEqual({ undefined: 'null' }); }); }); diff --git a/test/unit/MethodInvoker.test.js b/test/unit/MethodInvoker.test.js index b0600f44..440ba14b 100644 --- a/test/unit/MethodInvoker.test.js +++ b/test/unit/MethodInvoker.test.js @@ -142,11 +142,14 @@ const schemaList = { ], }, { - name: 'mockmodule.mockmethod1', + name: 'mockmodule1.mockmethod1', summary: 'Firebolt OpenRPC schema', params: [], result: { name: 'OpenRPC Schema', + schema: { + type: 'object', + }, }, }, ], @@ -211,6 +214,9 @@ jest.mock('../../src/FireboltExampleInvoker', () => { listen: jest.fn(), clear: jest.fn(), }, + mockmodule2: { + mockmethod2: jest.fn(), + }, }, }; return { @@ -261,53 +267,12 @@ describe('MethodInvoker', () => { action: 'NA', context: { communicationMode: 'Transport' }, }; - const expectedResult = { - method: 'callMethod', - params: [], - responseCode: 1, - apiResponse: { result: 'success', error: null }, - schemaValidationStatus: 'FAIL', - schemaValidationResponse: { - instance: 'success', - schema: { type: 'object' }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [ - { - path: [], - property: 'instance', - message: 'is not of a type(s) object', - schema: { type: 'object' }, - instance: 'success', - name: 'type', - argument: ['object'], - stack: 'instance is not of a type(s) object', - }, - ], - disableFormat: false, - }, - }; - result = await methodInvoker.invoke(MESSAGE_TRANSPORT); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResult); // will be Fail as the schema wont match. Schema expects object, return is string - }); - test('should successfully handle calls with params with communicationMode Transport ', async () => { - process.env.COMMUNICATION_MODE = 'Transport'; - const MESSAGE_TRANSPORT = { - task: 'callMethod', - params: { method: 'mockmodule.mockmethod', methodParams: { value: true } }, - action: 'NA', - context: { communicationMode: 'Transport' }, - }; - const expectedResult = { - method: 'callMethod', - params: [true], - }; + const expectedResult = { id: 1, result: 'success', jsonrpc: '2.0' }; result = await methodInvoker.invoke(MESSAGE_TRANSPORT); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result.params).toEqual(expectedResult.params); // will be Fail as the schema wont match. Schema expects object, return is string + expect(result.result).toEqual(expectedResult.result); // will be Fail as the schema wont match. Schema expects object, return is string }); + test('should successfully handle set calls', async () => { process.env.COMMUNICATION_MODE = 'SDK'; const message = { @@ -316,393 +281,59 @@ describe('MethodInvoker', () => { action: 'NA', context: { communicationMode: 'SDK' }, }; - const expectedResponse = { - method: 'callMethod', - params: [true], - responseCode: 0, - apiResponse: { result: 'success', error: null }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: { - instance: 'success', - schema: { type: 'string' }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, - }; + const expectedResponse = { id: 1, result: 'success', jsonrpc: '2.0' }; result = await methodInvoker.invoke(message); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); // will return PASS as module and method exist as well as schema validation passes. + expect(result.result).toEqual(expectedResponse.result); // will return PASS as module and method exist as well as schema validation passes. }); - test('should successfully handle calls with params as object', async () => { + + test('should return wrong method name when method not in sdk', async () => { process.env.COMMUNICATION_MODE = 'SDK'; const message = { task: 'callMethod', params: { - method: 'mocksdk_mockmodule.mockmethod', - methodParams: { firstParam: true, secondParam: 'somestring' }, + method: 'mocksdk_mockmodule.invalidMethod', }, action: 'NA', context: { communicationMode: 'SDK' }, }; const expectedResponse = { - method: 'callMethod', - params: [true, 'somestring'], + id: 1, + error: { code: -32601, message: 'Wrong Method Name' }, + jsonrpc: '2.0', }; result = await methodInvoker.invoke(message); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result.method).toEqual(expectedResponse.method); - expect(result.params).toEqual(expectedResponse.params); + expect(result.error).toEqual(expectedResponse.error); // will return result will be null. }); - test('should return error on error during processing', async () => { - process.env.COMMUNICATION_MODE = 'SDK'; - const message = { + test('validate MethodInvoker method which present in OPEN RPC but not imported to moduleMap/firebolt invoker', async () => { + process.env.COMMUNICATION_MODE = 'Transport'; + const MESSAGE_TRANSPORT = { task: 'callMethod', - params: { - method: 'mockmodule.mockmethod1', - }, + params: { method: 'mockmodule1.mockmethod1' }, action: 'NA', - context: { communicationMode: 'SDK' }, - }; - const expectedResponse = { - method: 'callMethod', - params: [], - responseCode: 1, - apiResponse: { - result: null, - error: { code: 'FCAError', message: 'Expected `schema` to be an object or boolean' }, - }, - schemaValidationStatus: 'FAIL', - schemaValidationResponse: { - instance: { code: 'FCAError', message: 'Expected `schema` to be an object or boolean' }, - schema: errorSchemaSDK, - options: {}, - path: [], - propertyPath: 'instance', - errors: [ - { - path: [], - property: 'instance', - message: 'is not exactly one from [subschema 0],[subschema 1]', - schema: errorSchemaSDK, - instance: { - code: 'FCAError', - message: 'Expected `schema` to be an object or boolean', - }, - name: 'oneOf', - argument: ['[subschema 0]', '[subschema 1]'], - stack: 'instance is not exactly one from [subschema 0],[subschema 1]', - }, - ], - disableFormat: false, - }, + context: { communicationMode: 'Transport' }, }; - result = await methodInvoker.invoke(message); + const expectedResult = { id: 1, result: 'success', jsonrpc: '2.0' }; + result = await methodInvoker.invoke(MESSAGE_TRANSPORT); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); // will return result will be null. + expect(result.result).toEqual(expectedResult.result); // will be Fail as the schema wont match. Schema expects object, return is string }); - test('should return wrong method name when method not in sdk', async () => { - process.env.COMMUNICATION_MODE = 'SDK'; - const message = { + test('validate MethodInvoker method which is not present in OPEN RPC but present in moduleMap/firebolt invoker', async () => { + process.env.COMMUNICATION_MODE = 'Transport'; + const MESSAGE_TRANSPORT = { task: 'callMethod', - params: { - method: 'mocksdk_mockmodule.invalidMethod', - }, + params: { method: 'mockmodule2.mockmethod2' }, action: 'NA', - context: { communicationMode: 'SDK' }, - }; - - const expectedResponse = { - method: 'callMethod', - params: [], - responseCode: 0, - apiResponse: { result: null, error: { code: -32601, message: 'Wrong Method Name' } }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: { - instance: { code: -32601, message: 'Wrong Method Name' }, - schema: errorSchemaSDK, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, - }; - result = await methodInvoker.invoke(message); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); // will return result will be null. - }); - }); - - describe('formatResult', () => { - let task; - let response; - let err; - let schemaValidationResult; - let params; - let schemaMap; - let expectedResponse; - - beforeEach(() => { - task = 'mockTask'; - response = null; - err = null; - schemaValidationResult = null; - params = { mockParams: 'mockValue' }; - schemaMap = { - type: 'string', - }; - expectedResponse = null; - }); - - test('should return status code 3 with Schema Validation status PASS - err in pending list, valid format', () => { - // testing for method not found - err = { code: -123, message: 'Method not found' }; - let expectedResponse = { - method: task, - params: params, - responseCode: 3, - apiResponse: { result: response, error: err }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: { - instance: err, - schema: errorSchemaSDK, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, - }; - let result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - - // testing for Method Not Implemented - err = { code: -123, message: 'Method Not Implemented' }; - expectedResponse = { - method: task, - params: params, - responseCode: 3, - apiResponse: { result: response, error: err }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: { - instance: err, - schema: errorSchemaSDK, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, - }; - result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - }); - - test('should return status code 3 with Schema Validation status FAIL - err in pending list, invalid format', () => { - // testing for error not in expected format - err = { code: 'mockError', message: 'Method Not Implemented' }; - expectedResponse = { - method: task, - params: params, - responseCode: 3, - apiResponse: { result: response, error: err }, - schemaValidationStatus: 'FAIL', - schemaValidationResponse: { - instance: err, - schema: errorSchemaSDK, - options: {}, - path: [], - propertyPath: 'instance', - errors: [ - { - path: [], - property: 'instance', - message: 'is not exactly one from [subschema 0],[subschema 1]', - schema: errorSchemaSDK, - instance: { code: 'mockError', message: 'Method Not Implemented' }, - name: 'oneOf', - argument: ['[subschema 0]', '[subschema 1]'], - stack: 'instance is not exactly one from [subschema 0],[subschema 1]', - }, - ], - disableFormat: false, - }, - }; - result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - }); - - test('should return status code 1 with Schema Validation status FAIL - err invalid format', () => { - // testing for error not in expected format - err = { code: 'mockError', message: 'some error' }; - expectedResponse = { - method: task, - params: params, - responseCode: 1, - apiResponse: { result: response, error: err }, - schemaValidationStatus: 'FAIL', - schemaValidationResponse: { - instance: err, - schema: errorSchemaSDK, - options: {}, - path: [], - propertyPath: 'instance', - errors: [ - { - path: [], - property: 'instance', - message: 'is not exactly one from [subschema 0],[subschema 1]', - schema: errorSchemaSDK, - instance: { code: 'mockError', message: 'some error' }, - name: 'oneOf', - argument: ['[subschema 0]', '[subschema 1]'], - stack: 'instance is not exactly one from [subschema 0],[subschema 1]', - }, - ], - disableFormat: false, - }, - }; - result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - }); - - test('should return status code 0 with Schema Validation status PASS - err valid format', () => { - // testing for error not in expected format - err = { code: -123, message: 'some error' }; - expectedResponse = { - method: task, - params: params, - responseCode: 0, - apiResponse: { result: response, error: err }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: { - instance: err, - schema: errorSchemaSDK, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }, - }; - result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - }); - - test('should return status code 0 with Schema Validation status PASS - valid response format', () => { - // testing for method not found - response = 'expectedResponse'; - schemaValidationResult = { - instance: response, - schema: { type: 'string' }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }; - const expectedResponse = { - method: task, - params: params, - responseCode: 0, - apiResponse: { result: response, error: err }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: schemaValidationResult, - }; - const result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - }); - - test('should return status code 0 with Schema Validation status PASS - valid null response', () => { - // testing for error not in expected format - response = null; - schemaMap = { - type: null, - }; - schemaValidationResult = { - instance: response, - schema: schemaMap, - options: {}, - path: [], - propertyPath: 'instance', - errors: [], - disableFormat: false, - }; - expectedResponse = { - method: task, - params: params, - responseCode: 0, - apiResponse: { result: response, error: err }, - schemaValidationStatus: 'PASS', - schemaValidationResponse: schemaValidationResult, - }; - result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - }); - - test('should return status code 2 with Schema Validation status SKIPPED - response is undefined but schema is not null', () => { - // testing for error not in expected format - response = undefined; - const expectedResponse = { - method: task, - params: params, - responseCode: 2, - apiResponse: { result: null, error: 'undefined' }, - schemaValidationStatus: 'SKIPPED', - schemaValidationResponse: null, - }; - result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); - console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); - }); - - test('should return status code 1 with Schema Validation status FAIL - response invalid format', () => { - // testing for error not in expected format - response = { message: 'some response' }; - schemaValidationResult = { - instance: response, - schema: { type: 'string' }, - options: {}, - path: [], - propertyPath: 'instance', - errors: [ - { - path: ['response'], - property: 'response', - message: 'is not of a type(s) string', - schema: { type: 'string' }, - instance: response, - name: 'type', - argument: ['string'], - stack: 'instance is not of a type(s) string', - }, - ], - disableFormat: false, - }; - expectedResponse = { - method: task, - params: params, - responseCode: 1, - apiResponse: { result: response, error: null }, - schemaValidationStatus: 'FAIL', - schemaValidationResponse: schemaValidationResult, + context: { communicationMode: 'Transport' }, }; - result = methodInvoker.formatResult(task, response, err, schemaValidationResult, params, schemaMap); + const expectedResult = { id: 1, result: 'success', jsonrpc: '2.0' }; + result = await methodInvoker.invoke(MESSAGE_TRANSPORT); console.log(expect.getState().currentTestName + ' : ' + JSON.stringify(result)); - expect(result).toEqual(expectedResponse); + expect(result.result).toEqual(expectedResult.result); // will be Fail as the schema wont match. Schema expects object, return is string }); }); }); diff --git a/test/unit/RegisterEventHandler.test.js b/test/unit/RegisterEventHandler.test.js index 1da548bd..bbe4700d 100644 --- a/test/unit/RegisterEventHandler.test.js +++ b/test/unit/RegisterEventHandler.test.js @@ -28,16 +28,12 @@ jest.mock('../../src/EventInvocation', () => { return { northBoundEventHandling: (message) => { return { - eventName: message.params.event, - eventListenerId: message.params.event + '-146', - eventListenerResponse: { - listenerResponse: 146, - error: null, - }, - eventListenerSchemaResult: { - status: 'PASS', - eventSchemaResult: {}, + jsonrpc: '2.0', + result: { + listening: true, + event: message.params.event, }, + id: 1, }; }, }; @@ -64,9 +60,8 @@ describe('RegisterEventHandler', () => { const responseString = await registerEventHandler.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); expect(responseString).toBeTruthy(); - expect(responseString).toContain('report'); const response = JSON.parse(responseString); - expect(response.report.eventName).toEqual(message.params.event); + expect(response.result.event).toEqual(message.params.event); expect(process.env.COMMUNICATION_MODE).toEqual(message.context.communicationMode); }); test('validate sdktype is handled correctly - MANAGE', async () => { @@ -79,9 +74,8 @@ describe('RegisterEventHandler', () => { const responseString = await registerEventHandler.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); expect(responseString).toBeTruthy(); - expect(responseString).toContain('report'); const response = JSON.parse(responseString); - expect(response.report.eventName).toEqual(message.params.event); + expect(response.result.event).toEqual(message.params.event); }); test('validate sdktype is handled correctly - no match found', async () => { const message = { @@ -93,10 +87,9 @@ describe('RegisterEventHandler', () => { const responseString = await registerEventHandler.handle(message); console.log(expect.getState().currentTestName + ' : ' + responseString); expect(responseString).toBeTruthy(); - expect(responseString).toContain('report'); const response = JSON.parse(responseString); - expect(response.report.error.code).toEqual('FCA Error'); - expect(response.report.error.message).toEqual("Not supported. sdkType 'extension' not in ['core','manage']"); + expect(response.error.code).toEqual('FCA Error'); + expect(response.error.message).toEqual("Not supported. sdkType 'extension' not in ['core','manage']"); }); }); }); diff --git a/test/unit/Utils.test.js b/test/unit/Utils.test.js index 71c49df0..b8ae0337 100644 --- a/test/unit/Utils.test.js +++ b/test/unit/Utils.test.js @@ -44,6 +44,9 @@ describe('Utils test cases', () => { test('validate dereferenceOpenRPC', async () => { await dereferenceOpenRPC('manage'); }); + test('validate dereferenceOpenRPC', async () => { + await dereferenceOpenRPC('discovery'); + }); test('validate getschemaValidationDone', async () => { const name = 'lifecycle.onForeground'; const response = { state: 'foreground', previous: 'inactive' }; diff --git a/test/unit/test_runner.test.js b/test/unit/test_runner.test.js index 16fdcb8f..0bc92b14 100644 --- a/test/unit/test_runner.test.js +++ b/test/unit/test_runner.test.js @@ -476,7 +476,6 @@ describe('Test_Runner test cases', () => { mode: 'Lifecycle.validation', methodName: CONSTANTS.LIFECYCLE_METHOD_LIST[1], }; - jest.spyOn(runner, 'schemaValidation').mockImplementation(() => 'Passed'); const response = await runner.invokeLifecycleAPI(tempParams); expect(response).not.toBe(undefined); /*