diff --git a/gpii/node_modules/flowManager/src/Capture.js b/gpii/node_modules/flowManager/src/Capture.js new file mode 100755 index 000000000..8332f724c --- /dev/null +++ b/gpii/node_modules/flowManager/src/Capture.js @@ -0,0 +1,200 @@ +/** + * GPII Capture Component + * + * Copyright 2020 Raising the Floor - International + * + * Licensed under the New BSD license. You may not use this file except in + * compliance with this License. + * + * You may obtain a copy of the License at + * https://github.com/gpii/universal/LICENSE.txt + */ +"use strict"; + +var fluid = require("infusion"), + gpii = fluid.registerNamespace("gpii"); + +fluid.defaults("gpii.flowManager.capture", { + gradeNames: ["fluid.component"], + events: { + // Pseudoevents for transforming promise chains to fetch the solutions on the current device + // and capture the settings for the device. + onSolutionsForCurrentDevice: null, + onCaptureSettingsForCurrentDevice: null + }, + listeners: { + // Begin declaration of Promise Chain for onSolutionsForCurrentDevice + "onSolutionsForCurrentDevice.getDeviceContextPromise": { + funcName: "gpii.lifecycleManager.getDeviceContextPromise", + args: ["{flowManager}.deviceReporter"], + priority: "first" + }, + "onSolutionsForCurrentDevice.getSolutions": { + funcName: "gpii.flowManager.getSolutions", + args: [ "{flowManager}.solutionsRegistryDataSource", "{arguments}.0"], + priority: "after:getDeviceContextPromise" + }, + "onSolutionsForCurrentDevice.solutionsRegistryEntriesToPromise": { + funcName: "fluid.toPromise", + args: ["{arguments}.0.solutionsRegistryEntries"], + priority: "after:getSolutions" + }, + // Begin declaration of Promise Chain for onCaptureSettingsForCurrentDevice + "onCaptureSettingsForCurrentDevice.getInstalledSolutionsForCurrentDevice": { + func: "{that}.getInstalledSolutionsForCurrentDevice", + priority: "first" + }, + "onCaptureSettingsForCurrentDevice.captureSystemSettings": { + funcName: "gpii.flowManager.capture.captureSystemSettings", + args: ["{lifecycleManager}.read", "{arguments}.0", "{arguments}.1"], // solutionsRegistryEntries, options + priority: "after:getInstalledSolutionsForCurrentDevice" + }, + "onCaptureSettingsForCurrentDevice.formatRawCapturedSettings": { + func: "gpii.flowManager.capture.formatRawCapturedSettings", + args: ["{arguments}.0"], + priority: "after:captureSystemSettings" + } + }, + invokers: { + getInstalledSolutionsForCurrentDevice: { + funcName: "fluid.promise.fireTransformEvent", + args: ["{that}.events.onSolutionsForCurrentDevice"] + }, + getSystemSettingsCapture: { + funcName: "fluid.promise.fireTransformEvent", + args: ["{that}.events.onCaptureSettingsForCurrentDevice", null, "{arguments}.0"] // options + } + } +}); + +/** + * Invoker `{gpii.flowManager.capture}.getInstalledSolutionsForCurrentDevice` + * + * @method + * @name {gpii.flowManager.capture}.getInstalledSolutionsForCurrentDevice + * + * This invoker method will return the solution registry entries, in their usual json format, + * that are available on the current device. + * + * @return {Promise} A promise resolved with an object of solutions registry entries available on the + * current device. As with the solutions registry itself, these are keyed by the solution ID. + */ + +/** + * Invoker `{gpii.flowManager.capture}.getSystemSettingsCapture` + * + * @method + * @name {gpii.flowManager.capture}.getSystemSettingsCapture + * + * This main API entry point for capturing settings from a system or computer. This captures + * the actual settings on the device, so it assumed to be running in a local untrusted flow + * manager. + * + * @param {Object} options - Options for this chain. + * @param {Array} options.solutionsList - An array of solution IDs to filter by when + * retreiving settings. If this option is not included, all available settings will be + * returned. ex: `["com.microsoft.windows.mouseSettings", "com.freedomscientific.jaws"]`. + * @return {Promise} A promise resolved with the payload of captured system settings. + */ + +/** + * Runs through all the solutions currently available on the system, pulls the current + * setting for each supportedSetting and returns them in an object. Primary use case + * is for backing Capture tools that would allow a user to set up their GPII profile + * starting with the current settings for their applications on the local machine. + * + * @param {Function|gpii.lifecycleManager.read} readSettingsFunc - lifecycleManager.read (or suitable implementation), + * that takes solution registry entries, reads their current values on the device, and returns a promise resolved to + * them. + * @param {Object} solutions - Solutions registry entries for solutions available on the current machine. + * @param {Object} options - Extra options for processing. + * @param {Array} options.solutionsList - If provided, only solutions in this list of `solutionsID`s will + * be captured. Example: + * + * '''json + * ["com.microsoft.windows.cursors", "com.freedomscientific.jaws"] + * ''' + * @return {fluid.promise} Returns a promise resolving with the entire system settings capture. + */ +gpii.flowManager.capture.captureSystemSettings = function (readSettingsFunc, solutions, options) { + var solutionsToFetch = fluid.copy(solutions); + if (options.solutionsList) { + fluid.remove_if(solutionsToFetch, function (solution, solutionID) { + return !options.solutionsList.includes(solutionID); + }); + } + + return readSettingsFunc(solutionsToFetch); +}; + +/** + * The raw return payload from the capture promise sequence looks like: + * '''json + * [ + * { + * "fakemag1": [ + * { + * "settings": { + * "magnification": 2 + * } + * } + * ] + * }, + * { + * "fakemag1": [ + * { + * "settings": { + * "invert": true + * } + * } + * ] + * }, + * { + * "fakemag2": [ + * { + * "settings": { + * "magnification": 2, + * "invert": true + * } + * } + * ] + * } + * ] + * ''' + * + * and we want: + * '''json + * { + * "fakemag1": { + * "magnification": 2, + * "invert": true + * }, + * "fakemag2": { + * "magnification": 2, + * "invert": true + * } + * } + * ''' + * + * @param {Object} data - The raw captured data. + * @return {Object} Returns a new payload with collapsed data, and multiple settings handler + * results for the same solution merged together. + */ +gpii.flowManager.capture.formatRawCapturedSettings = function (data) { + var togo = {}; + fluid.each(data, function (sequenceItem) { + if (sequenceItem.isError) { + fluid.log("Error capturing settings for: ", sequenceItem); + return; + } + fluid.each(sequenceItem, function (item, key) { + if (!togo[key]) { + togo[key] = {}; + } + fluid.each(fluid.get(item, [0, "settings"]), function (value, settingId) { + togo[key][settingId] = value; + }); + }); + }); + return togo; +}; diff --git a/gpii/node_modules/flowManager/src/FlowManager.js b/gpii/node_modules/flowManager/src/FlowManager.js index ea576829e..29a58ec1d 100644 --- a/gpii/node_modules/flowManager/src/FlowManager.js +++ b/gpii/node_modules/flowManager/src/FlowManager.js @@ -28,6 +28,7 @@ require("./DefaultSettingsLoader.js"); require("./PSPChannel.js"); require("./SettingsDataSource.js"); require("./UntrustedFlowManager.js"); +require("./Capture.js"); require("preferencesServer"); require("lifecycleManager"); @@ -179,6 +180,9 @@ fluid.defaults("gpii.flowManager.local", { eventLog: { type: "gpii.eventLog" }, + capture: { + type: "gpii.flowManager.capture" + }, userListeners: { type: "gpii.userListeners" }, diff --git a/gpii/node_modules/flowManager/src/MatchMaking.js b/gpii/node_modules/flowManager/src/MatchMaking.js index c96c9b476..f805484db 100644 --- a/gpii/node_modules/flowManager/src/MatchMaking.js +++ b/gpii/node_modules/flowManager/src/MatchMaking.js @@ -77,28 +77,45 @@ }); }; - /* - * Asynchronous function which makes a get call to the solutions registry (1st parameter) to + /** + * Asynchronous/Promise returning function which makes a get call to the solutions registry (1st parameter) to * retrieve the solutions registry matching what is passed in the `device` parameter. * This is appended to the matchmaker payload (mmpayload) parameter, which in turn is passed * as parameter in the event fired. * - * @solutionsRegistryDataSource (Object) - a solutions registry data source - * @deviceContext (Object) - output from a device reporter. Used to filter solutions registry entries - * @event (Object) - Event to be fired when the solutionsRegistry entry has been retrieved - * @onError (Object) - Event to be fired when an error occurs + * This function can be used with either (or both) asyncronously with an `event` and `onError` handlers + * passed in, or with the returned `fluid.promise`. * - * @return (undefined) - function is asynchronous and doesn't return anything. Instead the event - * is fired with the modified mmpayload. + * @param {Object} solutionsRegistryDataSource - a solutions registry data source + * @param {Object} deviceContext - output from a device reporter. Used to filter solutions registry entries + * @param {Object} onSuccessEvent - Optional: Event to be fired when the solutionsRegistry entry has been retrieved + * @param {Object} onErrorEvent - Optional: Event to be fired when an error occurs + * @return {fluid.promise} - Returns a promise resolving with the mmpayload. Optionally if provided, the events + * are also fired with the modified mmpayload. */ - gpii.flowManager.getSolutions = function (solutionsRegistryDataSource, deviceContext, event, onError) { + gpii.flowManager.getSolutions = function (solutionsRegistryDataSource, deviceContext, onSuccessEvent, onErrorEvent) { + var promiseTogo = fluid.promise(); + var os = fluid.get(deviceContext, "OS.id"); var promise = solutionsRegistryDataSource.get({}); promise.then(function (solutions) { var solutionsRegistryEntries = gpii.matchMakerFramework.filterSolutions(solutions[os], deviceContext); fluid.log("Fetched filtered solutions registry entries: ", gpii.renderMegapayload({solutionsRegistryEntries: solutionsRegistryEntries})); - event.fire(solutionsRegistryEntries, solutions); - }, onError.fire); + promiseTogo.resolve({ + solutionsRegistryEntries: solutionsRegistryEntries, + solutions: solutions + }); + if (onSuccessEvent) { + onSuccessEvent.fire(solutionsRegistryEntries, solutions); + } + }, function (error) { + promiseTogo.reject(error); + if (onErrorEvent) { + onErrorEvent.fire(error); + } + }); + + return promiseTogo; }; // initialPayload contains fields diff --git a/gpii/node_modules/flowManager/test/CaptureTests.js b/gpii/node_modules/flowManager/test/CaptureTests.js new file mode 100644 index 000000000..9d5147617 --- /dev/null +++ b/gpii/node_modules/flowManager/test/CaptureTests.js @@ -0,0 +1,235 @@ +/** + * GPII Capture Tests + * + * Copyright 2019 Raising the Floor - International + * + * Licensed under the New BSD license. You may not use this file except in + * compliance with this License. + * + * You may obtain a copy of the License at + * https://github.com/GPII/universal/blob/master/LICENSE.txt + */ + +"use strict"; + +var fluid = require("infusion"), + gpii = fluid.registerNamespace("gpii"), + kettle = require("kettle"); + +var jqUnit = require("node-jqunit"); + +fluid.require("%gpii-universal"); +gpii.loadTestingSupport(); + +fluid.registerNamespace("gpii.tests.flowManager.capture"); + +kettle.config.createDefaults({ + configName: "gpii.flowManager.tests.capture.fakeData.config", + configPath: "%gpii-universal/gpii/node_modules/flowManager/test/configs" +}); + +gpii.tests.flowManager.capture.checkForFakeMags = function (payload) { + jqUnit.assertDeepEq("FakeMag1 with multiple settings handlers", { + "magnification": 2, + "invert": true + }, payload.fakemag1); + + jqUnit.assertDeepEq("FakeMag2 with single settings handler", { + "invert": 1, + "magnification": 4.5, + "location": "topRight" + }, payload.fakemag2); +}; + +gpii.tests.flowManager.capture.platformReporter = function () { + return { + id: "darwin" + }; +}; + +gpii.tests.flowManager.capture.checkForInstalledMags = function (payload) { + jqUnit.assertEquals("There should be 2 solutions installed", 2, Object.keys(payload).length); + jqUnit.assertEquals("Check for Fake Mag 1", "Fake Magnifier 1", payload.fakemag1.name); + jqUnit.assertEquals("Check for Fake Mag 2", "Fake Magnifier 2 - fully featured", payload.fakemag2.name); +}; + +gpii.tests.flowManager.capture.adjustSolutions = function (solutionsRegistryDataSource) { + var testDataFile = __dirname + "/data/capture_fakemag_settings.json"; + var testDataFile2 = __dirname + "/data/capture_fakemag2_settings.json"; + + // The solutions block is a read only data structure + var adjustedSolutions = fluid.copy(solutionsRegistryDataSource.fullSolutionsRegistry); + adjustedSolutions.darwin.fakemag2.settingsHandlers.configuration.options.filename = testDataFile2; + adjustedSolutions.darwin.fakemag1.settingsHandlers.configuration.options.filename = testDataFile; + adjustedSolutions.darwin.fakemag1.settingsHandlers.configuration1.options.filename = testDataFile; + solutionsRegistryDataSource.fullSolutionsRegistry = adjustedSolutions; +}; + +fluid.defaults("gpii.tests.flowManager.capture.tests", { + gradeNames: ["fluid.test.testEnvironment", "fluid.test.testCaseHolder"], + modules: [ + { + name: "Simple system capture", + tests: [{ + name: "Check for existing FakeMag Settings", + expect: 2, + sequence: [{ + funcName: "gpii.tests.flowManager.capture.adjustSolutions", + args: ["{config}.server.flowManager.solutionsRegistryDataSource"] + }, { + task: "{config}.server.flowManager.capture.getSystemSettingsCapture", + args: [], + resolve: "gpii.tests.flowManager.capture.checkForFakeMags", + resolveArgs: ["{arguments}.0"] + }] + }] + }, + { + name: "Simple installed solutions fetch", + tests: [{ + name: "Testing get installed solutions", + expect: 3, + sequence: [{ + funcName: "gpii.tests.flowManager.capture.adjustSolutions", + args: ["{config}.server.flowManager.solutionsRegistryDataSource"] + }, { + task: "{config}.server.flowManager.capture.getInstalledSolutionsForCurrentDevice", + args: [], + resolve: "gpii.tests.flowManager.capture.checkForInstalledMags", + resolveArgs: ["{arguments}.0"] + }] + }] + } + ], + components: { + "config": { + type: "gpii.flowManager.tests.capture.fakeData.config" + } + } +}); + +fluid.test.runTests([ + "gpii.tests.flowManager.capture.tests" +]); + +/* + * Tests for formatting raw captures. + */ +gpii.tests.flowManager.capture.formatRawCapturedSettingsTestCases = { + emptyInput: { + message: "Empy Input should produce an empty object", + input: [], + expected: {} + }, + allCorrectSettings: { + message: "There should be 2 solutions each with 2 settings from the all correct payload", + input: [ + { + "fakemag1": [ + { + "settings": { + "magnification": 3 + } + } + ] + }, + { + "fakemag1": [ + { + "settings": { + "invert": false + } + } + ] + }, + { + "fakemag2": [ + { + "settings": { + "magnification": 2, + "invert": true + } + } + ] + } + ], + expected: { + "fakemag1": { + "magnification": 3, + "invert": false + }, + "fakemag2": { + "magnification": 2, + "invert": true + } + } + }, + someErrorsSettings: { + message: "There should still be 2 solutions each with 2 settings from the all payload that contained an error in addition to correct entries.", + input: [ + { + "fakemag1": [ + { + "settings": { + "bouncedelay": 2 + } + } + ] + }, + { + "fakemag1": [ + { + "settings": { + "invert": true + } + } + ] + }, + { + isError: true, + msg: "This didn't work properly during capture" + }, + { + "fakemag2": [ + { + "settings": { + "magnification": 5, + "invert": false + } + } + ] + } + ], + expected: { + "fakemag1": { + "bouncedelay": 2, + "invert": true + }, + "fakemag2": { + "magnification": 5, + "invert": false + } + } + }, + allErrorsSettings: { + message: "Settings with just errors should yield an empty object", + input: [ + { + isError: true, + msg: "This didn't work properly during capture" + }, + { + isError: true, + msg: "This is another error apparently" + } + ], + expected: {} + } +}; + +jqUnit.test("Test Raw Settings Formatting", function () { + fluid.each(gpii.tests.flowManager.capture.formatRawCapturedSettingsTestCases, function (nextTest) { + var result = gpii.flowManager.capture.formatRawCapturedSettings(nextTest.input); + jqUnit.assertDeepEq(nextTest.message, nextTest.expected, result); + }); +}); diff --git a/gpii/node_modules/flowManager/test/configs/gpii.flowManager.tests.capture.fakeData.config.json5 b/gpii/node_modules/flowManager/test/configs/gpii.flowManager.tests.capture.fakeData.config.json5 new file mode 100644 index 000000000..cc6b605a5 --- /dev/null +++ b/gpii/node_modules/flowManager/test/configs/gpii.flowManager.tests.capture.fakeData.config.json5 @@ -0,0 +1,29 @@ +// +// This configuration is used for testing the snappingshotting Capture API. Capturing setting will only +// ever happen on a users local machine, so there is only an untrusted test configuration. +// +{ + "type": "gpii.flowManager.tests.capture.fakeData.config", + "options": { + "distributeOptions": { + "capture.solutionsRegistry": { + "record": "%gpii-universal/gpii/node_modules/flowManager/test/data/capture_solutionsRegistry.json", + "target": "{that flowManager solutionsRegistryDataSource}.options.path", + "priority": "after:flowManager.solutions" + }, + "capture.deviceReporter": { + "record": "%gpii-universal/gpii/node_modules/flowManager/test/data/capture_deviceReporter.json", + "target": "{that deviceReporter installedSolutionsDataSource}.options.path", + "priority": "after:development.installedSolutionsPath" + }, + "capture.deviceReporterOS": { + "record": { + "funcName": "gpii.tests.flowManager.capture.platformReporter" + }, + "target": "{that deviceReporter platformReporter}.options.invokers.reportPlatform", + "priority": "after:development.installedSolutionsPath" + } + } + }, + "mergeConfigs": "%gpii-universal/gpii/configs/shared/gpii.config.untrusted.development.json5" +} diff --git a/gpii/node_modules/flowManager/test/data/capture_deviceReporter.json b/gpii/node_modules/flowManager/test/data/capture_deviceReporter.json new file mode 100644 index 000000000..eb53914cb --- /dev/null +++ b/gpii/node_modules/flowManager/test/data/capture_deviceReporter.json @@ -0,0 +1,8 @@ +[ + { + "id": "fakemag1" + }, + { + "id": "fakemag2" + } +] diff --git a/gpii/node_modules/flowManager/test/data/capture_fakemag2_settings.json b/gpii/node_modules/flowManager/test/data/capture_fakemag2_settings.json new file mode 100644 index 000000000..a3c3735d9 --- /dev/null +++ b/gpii/node_modules/flowManager/test/data/capture_fakemag2_settings.json @@ -0,0 +1,5 @@ +{ + "invert": 1, + "magnification": 4.5, + "location": "topRight" +} diff --git a/gpii/node_modules/flowManager/test/data/capture_fakemag_settings.json b/gpii/node_modules/flowManager/test/data/capture_fakemag_settings.json new file mode 100644 index 000000000..5b2a4985b --- /dev/null +++ b/gpii/node_modules/flowManager/test/data/capture_fakemag_settings.json @@ -0,0 +1,4 @@ +{ + "invert": true, + "magnification": 2.0 +} diff --git a/gpii/node_modules/flowManager/test/data/capture_solutionsRegistry.json b/gpii/node_modules/flowManager/test/data/capture_solutionsRegistry.json new file mode 100644 index 000000000..ad190cd29 --- /dev/null +++ b/gpii/node_modules/flowManager/test/data/capture_solutionsRegistry.json @@ -0,0 +1,138 @@ +{ + "darwin": { + "fakemag1": { + "name": "Fake Magnifier 1", + "contexts": { + "OS": [ + { + "id": "darwin" + } + ] + }, + "capabilities": [ + "http://registry\\.gpii\\.net/common/magnification/enabled" + ], + "settingsHandlers": { + "configuration": { + "type": "gpii.settingsHandlers.JSONSettingsHandler", + "liveness": "live", + "options": { + "filename": "/tmp/fakemag2.settings.json" + }, + "capabilitiesTransformations": { + "magnification": "http://registry\\.gpii\\.net/common/magnification" + }, + "supportedSettings": { + "magnification": { + "schema": { + "title": "Magnification Level", + "description": "How many times to magnify content when magnification is enabled.", + "type": "number", + "default": 1.10 + } + } + } + }, + "configuration1": { + "type": "gpii.settingsHandlers.JSONSettingsHandler", + "liveness": "live", + "options": { + "filename": "/tmp/fakemag2.settings.json" + }, + "capabilitiesTransformations": { + "invert": "http://registry\\.gpii\\.net/common/invertColours" + }, + "supportedSettings": { + "invert": { + "schema": { + "title": "Invert Colours", + "description": "Enable colour inversion for Magnifier", + "type": "boolean" + } + } + } + } + }, + "configure": [ + "settings.configuration", + "settings.configuration1" + ], + "restore": [ + "settings.configuration", + "settings.configuration1" + ], + "start": [], + "stop": [], + "isInstalled": [ + { + "type": "gpii.deviceReporter.alwaysInstalled" + } + ] + }, + "fakemag2": { + "name": "Fake Magnifier 2 - fully featured", + "contexts": { + "OS": [ + { + "id": "darwin" + } + ] + }, + "capabilities": [ + "http://registry\\.gpii\\.net/common/magnification/enabled" + ], + "settingsHandlers": { + "configuration": { + "type": "gpii.settingsHandlers.JSONSettingsHandler", + "liveness": "live", + "options": { + "filename": "/tmp/fakemag2.settings.json" + }, + "capabilitiesTransformations": { + "magnification": "http://registry\\.gpii\\.net/common/magnification", + "invert": "http://registry\\.gpii\\.net/common/invertColours", + "location": "http://registry\\.gpii\\.net/common/magnifierLocation" + }, + "supportedSettings": { + "magnification": { + "schema": { + "title": "Magnification Level", + "description": "How many times to magnify content when magnification is enabled.", + "type": "number", + "default": 1.10 + } + }, + "invert": { + "schema": { + "title": "Invert Colours", + "description": "Enable colour inversion for Magnifier", + "type": "integer", + "default": 0 + } + }, + "location": { + "schema": { + "title": "Magnifier Location", + "description": "Magnifier location on screen", + "type": "string" + } + } + } + } + }, + "configure": [ + "settings.configuration" + ], + "restore": [ + "settings.configuration" + ], + "start": [ ], + "stop": [ ], + "isInstalled": [ + { + "type": "gpii.deviceReporter.alwaysInstalled" + } + ] + } + } +} diff --git a/gpii/node_modules/lifecycleManager/src/UserLogonStateChange.js b/gpii/node_modules/lifecycleManager/src/UserLogonStateChange.js index a0156f6c8..3070cca77 100644 --- a/gpii/node_modules/lifecycleManager/src/UserLogonStateChange.js +++ b/gpii/node_modules/lifecycleManager/src/UserLogonStateChange.js @@ -153,22 +153,38 @@ gpii.lifecycleManager.userLogonHandling.loginUser = function (that, lifecycleMan }; gpii.lifecycleManager.getDeviceContext = function (deviceReporter, event, errorEvent) { + gpii.lifecycleManager.getDeviceContextPromise(deviceReporter).then( + event.fire, + errorEvent.fire + ); +}; + +gpii.lifecycleManager.getDeviceContextPromise = function (deviceReporter) { + // GPII-4324 TODO: We have a factoring problem here since properly the LifecycleManager has no business + // reaching out into the environment to interact with the DeviceReporter, as shown by the + // awkward-looking reference {flowManager}.deviceReporter which is out of place with the others. + // However, this ended up being a natural place for the implementation since it is scoped to the + // matchmaking workflow which is tied to lifecycleManager's userLogonRequest via containment. + // When we improve this factoring we will better deliver on our goal of "containment without dependency" + var promiseTogo = fluid.promise(); var promise = deviceReporter.get(); promise.then(function (deviceData) { gpii.logFully("getDeviceContext got deviceData ", deviceData); if (!deviceData) { - errorEvent.fire({message: "Device reporter returned `undefined`." }); + promiseTogo.reject({message: "Device reporter returned `undefined`." }); } else if (deviceData.isError) { - errorEvent.fire({message: "Error in device reporter data: " + deviceData.message}); + promiseTogo.reject({message: "Error in device reporter data: " + deviceData.message}); } else { - event.fire(deviceData); + promiseTogo.resolve(deviceData); } }, function (err) { var error = fluid.extend(err, { message: "Rejected deviceReporter promise: " + err.message }); - errorEvent.fire(error); + promiseTogo.reject(error); }); + + return promiseTogo; }; // A mixin grade for a matchMakingRequest request handler, supporting local user logon diff --git a/testData/solutions/darwin.json5 b/testData/solutions/darwin.json5 index 97aa912c4..3e124df1b 100644 --- a/testData/solutions/darwin.json5 +++ b/testData/solutions/darwin.json5 @@ -20,6 +20,16 @@ }, "capabilitiesTransformations": { "magnification": "http://registry\\.gpii\\.net/common/magnification" + }, + "supportedSettings": { + "magnification": { + schema: { + title: "Magnification Level", + description: "How many times to magnify content when magnification is enabled.", + type: "number", + default: 1.10 + } + } } } }, @@ -60,6 +70,23 @@ "capabilitiesTransformations": { "magnification": "http://registry\\.gpii\\.net/common/magnification", "invert": "http://registry\\.gpii\\.net/common/invertColours" + }, + "supportedSettings": { + "magnification": { + "schema": { + "title": "Magnification Level", + "description": "How many times to magnify content when magnification is enabled.", + "type": "number", + "default": 1.10 + } + }, + "invert": { + "schema": { + "title": "Invert Colours", + "description": "Enable colour inversion for Magnifier", + "type": "boolean" + } + } } } }, @@ -101,6 +128,30 @@ "pitch": "http://registry\\.gpii\\.net/common/pitch", "volumeTTS": "http://registry\\.gpii\\.net/common/volumeTTS", "rate": "http://registry\\.gpii\\.net/common/speechRate" + }, + "supportedSettings": { + "pitch": { + "schema": { + "title": "Speech Pitch", + "description": "The pitch at which text is announced.", + "minimum": 0, + "maximum": 20 + } + }, + "volumeTTS": { + "schema": { + "title": "Volume TTS", + "description": "Volume TTS", + "type": "integer" + } + }, + "rate": { + "schema": { + "title": "Rate", + "description": "Speech rate for all announcements (scale varies by voice).", + "type": "integer" + } + } } } }, diff --git a/tests/all-tests.js b/tests/all-tests.js index 91cda71dd..e8af5a873 100644 --- a/tests/all-tests.js +++ b/tests/all-tests.js @@ -58,6 +58,7 @@ var testIncludes = [ "../gpii/node_modules/eventLog/test/all-tests.js", "../gpii/node_modules/flatMatchMaker/test/FlatMatchMakerTests.js", "../gpii/node_modules/flowManager/test/BrowserChannelTests.js", + "../gpii/node_modules/flowManager/test/CaptureTests.js", "../gpii/node_modules/flowManager/test/DefaultSettingsLoaderTests.js", "../gpii/node_modules/flowManager/test/PrefsServerDataSourceTests.js", "../gpii/node_modules/flowManager/test/PSPChannelTests.js",