Skip to content

Commit

Permalink
Merge branch 'sgithens/GPII-4226' GPII#857
Browse files Browse the repository at this point in the history
* sgithens/GPII-4226: (27 commits)
  GPII-4226 Renaming JAWS settings handler option keys to be more meaningful
  GPII-4226 Adding jsdoc for makeFileGet, Set, Parser, and Fetcher
  GPII-4226 Moving label decl from additionalProperties to properties.
  GPII-1908 Updating description wording on TapEvenDurationMax
  GPII-1908 Renaming file Jaw -> Jaws. Cleaning up more settings.
  GPII-4226 Commenting out settings missing a minimum or maximum value. Removing types from enum settings
  GPII-4226: Added validation for low-quality SR settings.
  GPII-4226 Removing brailleMode from jaws_common tests still that term is not in flat.json
  GPII-4226: Fixed typo
  GPII-4226: Updated test payload and commented transforms until GPII-4336 is addressed
  GPII-4226: Updated JAWS related tests and commented transforms until GPII-4336 is addressed
  GPII-4226: Solved linter issues
  GPII-4226: Fixed invalid settings in JAWS preference set
  GPII-4226: Solved validation issues in JAWS SR entry
  GPII-4226: Uncommented invalid entry from 'jaws.json' preference set
  GPII-4226: Changed the transformation to the correct capabilitiesTransformation block
  GPII-4226: Removed trailing comma fixing linter issue
  GPII-4226: Disabled incomplete transforms and changed life-cycle handler implementation
  GPII-4226: Changed preference sets comment format
  GPII-4226: Added additional settings
  ...
  • Loading branch information
javihernandez committed May 15, 2020
2 parents 7868a22 + 6f3edbc commit 4fbdab6
Show file tree
Hide file tree
Showing 17 changed files with 16,370 additions and 2,541 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gpii/node_modules/settingsHandlers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var fluid = require("infusion");
fluid.module.register("settingsHandlers", __dirname, require);

require("./src/INISettingsHandler.js");
require("./src/JawsSettingsHandler.js");
require("./src/XMLSettingsHandler.js");
require("./src/JSONSettingsHandler.js");
require("./src/WebSocketsSettingsHandler.js");
Expand Down
69 changes: 69 additions & 0 deletions gpii/node_modules/settingsHandlers/src/JawsSettingsHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*!
* JAWS Settings Handler
*
* Copyright 2012 Raising the Floor - International
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
* The research leading to these results has received funding from the European Union's
* Seventh Framework Programme (FP7/2007-2013) under grant agreement no. 289016.
*
* You may obtain a copy of the License at
* https://github.com/GPII/universal/blob/master/LICENSE.txt
*/

"use strict";

var fluid = require("infusion"),
path = require("path"),
gpii = fluid.registerNamespace("gpii");

require("./INISettingsHandler.js");

fluid.registerNamespace("gpii.settingsHandlers.JAWSSettingsHandler.parser");

gpii.settingsHandlers.JAWSSettingsHandler.getVoiceProfileFileName = function (options) {
var iniPayload = {
"com.freedomscientific.jaws": [{
options: {
"defaultSettingsFilePath": options.defaultSettingsFilePath
},
settings: {
"Voice Profiles.ActiveVoiceProfileName": null
}
}]
};
var response = gpii.settingsHandlers.INISettingsHandler.get(iniPayload);
var solutions = response["com.freedomscientific.jaws"];
var voiceProfileFileName = undefined;

if (Array.isArray(solutions) && solutions.length) {
var solution = solutions[0];
var settingValue = fluid.get(solution, ["settings", "Voice Profiles.ActiveVoiceProfileName"]);

if (settingValue) {
voiceProfileFileName = path.join(options.voiceProfilesDirPath, settingValue + ".VPF");
} else {
voiceProfileFileName = path.join(options.voiceProfilesDirPath, "Eloquence.VPF");
}
}

return voiceProfileFileName;
};

gpii.settingsHandlers.JAWSSettingsHandler.parser.parse = function (content, options) {
return gpii.iniFile.read(content, options);
};

gpii.settingsHandlers.JAWSSettingsHandler.parser.stringify = function (content, options) {
return gpii.iniFile.writeFromFile(options.defaultSettingsFilePath, content, options);
};

/* PUBLIC API FUNCTIONS */
gpii.settingsHandlers.JAWSSettingsHandler.get =
gpii.settingsHandlers.makeFileGet(gpii.settingsHandlers.JAWSSettingsHandler.parser,
gpii.settingsHandlers.JAWSSettingsHandler.getProfileFileName);
gpii.settingsHandlers.JAWSSettingsHandler.set =
gpii.settingsHandlers.makeFileSet(gpii.settingsHandlers.JAWSSettingsHandler.parser,
gpii.settingsHandlers.JAWSSettingsHandler.getProfileFileName);
72 changes: 64 additions & 8 deletions gpii/node_modules/settingsHandlers/src/settingsHandlerUtilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,16 +439,56 @@ gpii.settingsHandlers.writeFile = function (content, options) {
fs.writeFileSync(options.filename, content, options.encoding || "utf-8");
};

/**
* A parser for settings handler types that includes `parse` and `stringify` functions to allow reading and
* serialization for each filetype. For example `JSON`, `INI`, and `XML` formats would each have their own parsers for
* this.
*
* @typedef {Object} gpii.settingsHandlers.parser
* @property {gpii.settinghandlers.parser.parse} parse - Parses the data read from a file on disk or other source.
* @property {gpii.settinghandlers.parser.stringify} stringify - Serializes the settings data back to a string to be
* written to disk.
*/

/**
* Parses the data read from a file on disk or other source.
*
* @typedef {Function} gpii.settinghandlers.parser.parse
* @param {Object} parse.content - The file contents.
* @param {Object} parse.options - The `options` block from the settings handler configuration for these settings.
*/

/**
* Serializes the settings data back to a string to be written to disk.
*
* @typedef {Function} gpii.settinghandlers.parser.stringify
* @param {Object} stringify.settings - The solution settings for this configuration.
* @param {Object} stringify.options - The `options` block from the settings handler configuration for these settings.
*/

/**
* `fetcher` is a function that returns a path to the file containing the data for this settings handler. This allows
* dynamic resolution of the file during the life cycle. The original purpose and example for this was the current user
* profile in JAWS, which is stored in another system settings file. This allows the current user profile setting and
* file to be looked up and used to find the settings for the current handler.
*
* @typedef {Function} gpii.settingsHandlers.fetcher
* @param {Object} options - The `options` block from the settings handler configuration for these settings.
*/

/*
* Utility for file-based settings handler. Handle individual solution entry data. The 'modifier' function passed as
* parameter is called to allow editing of the solutionEntry based on the
* current settings (both passed as parameters to the modifier function)
*/
gpii.settingsHandlers.handleFileSolutionEntry = function (solutionEntry, modifier, parser, isWrite) {
var options = solutionEntry.options;
gpii.settingsHandlers.handleFileSolutionEntry = function (solutionEntry, modifier, parser, isWrite, fetcher) {
var options = fluid.copy(solutionEntry.options);

if (options && (options.path || options.filename)) {
// fetch the target file to read
if (fetcher) {
options.filename = fetcher(options);
}
// read file - returns undefined if it doesn't exist
var content = gpii.settingsHandlers.readFile(options);
// if the file is non-existing, current settings are {}, else they're the parsed content of the file
Expand All @@ -472,21 +512,37 @@ gpii.settingsHandlers.handleFileSolutionEntry = function (solutionEntry, modifie
* is done by fluid.transform calls, and at the level of each solution
* entry.
*/
gpii.settingsHandlers.transformFilePayload = function (payload, modifier, parser, isWrite) {
gpii.settingsHandlers.transformFilePayload = function (payload, modifier, parser, isWrite, fetcher) {
return gpii.settingsHandlers.transformPayload(payload, function (solutionEntry) {
return gpii.settingsHandlers.handleFileSolutionEntry(solutionEntry, modifier, parser, isWrite);
return gpii.settingsHandlers.handleFileSolutionEntry(solutionEntry, modifier, parser, isWrite, fetcher);
});
};

gpii.settingsHandlers.makeFileGet = function (parser) {
/**
* Used for defining settings handler `get` functions supporting different file types. The supplied `parser` and
* `fetcher` will be specific to the file format and settings handler.
*
* @param {gpii.settingsHandlers.parser} parser - Parser for the file contents.
* @param {gpii.settingsHandlers.fetcher} fetcher - Optional fetcher to adjust the filename dynamically.
* @return {Object} GPII Settings from the file.
*/
gpii.settingsHandlers.makeFileGet = function (parser, fetcher) {
return function (payload) {
return gpii.settingsHandlers.transformFilePayload(payload, gpii.settingsHandlers.getSettings, parser);
return gpii.settingsHandlers.transformFilePayload(payload, gpii.settingsHandlers.getSettings, parser, false, fetcher);
};
};

gpii.settingsHandlers.makeFileSet = function (parser) {
/**
* Used for defining settings handler `set` functions supporting different file types. The supplied `parser` and
* `fetcher` will be specific to the file format and settings handler.
*
* @param {gpii.settingsHandlers.parser} parser - Parser for the file contents.
* @param {gpii.settingsHandlers.fetcher} fetcher - Optional fetcher to adjust the filename dynamically.
* @return {String} Serialized GPII Settings to write to file.
*/
gpii.settingsHandlers.makeFileSet = function (parser, fetcher) {
return function (payload) {
return gpii.settingsHandlers.transformFilePayload(payload, gpii.settingsHandlers.setSettings, parser, true);
return gpii.settingsHandlers.transformFilePayload(payload, gpii.settingsHandlers.setSettings, parser, true, fetcher);
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use strict";

var fluid = require("infusion"),
gpii = fluid.registerNamespace("gpii");

fluid.registerNamespace("gpii.tests");

fluid.require("%gpii-universal");
gpii.loadTestingSupport();

require("settingsHandlers");

fluid.logObjectRenderChars = 30000;

var test = {
payload: {
"com.freedomscientific.jaws": [{
options: {
"defaultSettingsFilePath": "C:\\Users\\vagrant\\AppData\\Roaming\\Freedom Scientific\\JAWS\\2019\\Settings\\enu\\DEFAULT.JCF",
"voiceProfilesDirPath": "C:\\Users\\vagrant\\AppData\\Roaming\\Freedom Scientific\\JAWS\\2019\\Settings\\VoiceProfiles"
},
settings: {
"ENU-Global.Pitch": 90
}
}]
},
expectedResult: {
"com.freedomscientific.jaws": [{
options: {
"defaultSettingsFilePath": "C:\\Users\\vagrant\\AppData\\Roaming\\Freedom Scientific\\JAWS\\2019\\Settings\\enu\\DEFAULT.JCF",
"voiceProfilesDirPath": "C:\\Users\\vagrant\\AppData\\Roaming\\Freedom Scientific\\JAWS\\2019\\Settings\\VoiceProfiles"
},
settings: {
"ENU-Global.Pitch": {
newValue: 90,
oldValue: 65
}
}
}]
}
};

var output = gpii.settingsHandlers.JAWSSettingsHandler.get(test.payload);
output = gpii.settingsHandlers.JAWSSettingsHandler.set(test.payload);
fluid.log(output);

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ gpii.tests.universal.solutionsRegistry.srFiles.checkSingleSolution = function (g
solutionSchema,
"solution file '" + filename + "' -> solution '" + solutionKey + "'"
);
jqUnit.assertTrue("Solution '" + solutionKey + "' in file '" + filename + "' should have a valid schema.", isSolutionValid);
jqUnit.assertTrue("Solution '" + solutionKey + "' in file '" + filename + "' should be valid according to the schema.", isSolutionValid);

gpii.tests.universal.solutionsRegistry.srFiles.checkDefaults(globalValidator, filename, solutionKey, solutionDef);
gpii.tests.universal.solutionsRegistry.srFiles.checkCapabilities(filename, solutionKey, solutionDef, genericTerms);
Expand Down Expand Up @@ -83,20 +83,43 @@ gpii.tests.universal.solutionsRegistry.srFiles.checkWindowsSettingsHandlers = fu

fluid.each(fluid.get(solutionDef, "settingsHandlers"), function (settingsHandlerDef, settingsHandlerKey) {
var settingsHandlerType = fluid.get(settingsHandlerDef, "type");
if (settingsHandlersDemandingObjects.indexOf(settingsHandlerType) !== -1) {
fluid.each(settingsHandlerDef.supportedSettings, function (settingDef, settingKey) {
fluid.each(settingsHandlerDef.supportedSettings, function (settingDef, settingKey) {
var settingType = fluid.get(settingDef, "schema.type");
var isEnum = fluid.get(settingDef, "schema.enum") !== undefined;

if (isEnum && settingType !== undefined) {
fluid.log("WARNING: enum " + filename + " -> " + solutionKey + " -> " + settingsHandlerKey + " -> " + settingKey + " should not have a type specified.");
}

if (settingsHandlersDemandingObjects.indexOf(settingsHandlerType) !== -1) {
var isObject = settingType === "object";
var hasProperties = fluid.get(settingDef, "schema.properties") !== undefined;
if (!hasProperties) {

if (!isObject || !hasProperties) {
objectivelyAwfulSettingsCount++;
fluid.log(filename + " -> " + solutionKey + " -> " + settingsHandlerKey + " -> " + settingKey + " should have properties defined.");
}

var isObject = fluid.get(settingDef, "schema.type") === "object";
if (!isObject) {
if (!isObject && !hasProperties) {
fluid.log("WARNING: " + filename + " -> " + solutionKey + " -> " + settingsHandlerKey + " -> " + settingKey + " should be an object.");
}
else if (!hasProperties && isObject) {
fluid.log("WARNING: " + filename + " -> " + solutionKey + " -> " + settingsHandlerKey + " -> " + settingKey + " should have properties defined.");
}
else if (!isObject && hasProperties) {
fluid.log("WARNING: " + filename + " -> " + solutionKey + " -> " + settingsHandlerKey + " -> " + settingKey + " does not have the correct 'object' type value.");
}
});
}
}

if (settingType === "number" || settingType === "integer") {
if (fluid.get(settingDef, "schema.minimum") === undefined) {
fluid.log("WARNING: Numeric setting " + filename + " -> " + solutionKey + " -> " + settingsHandlerKey + " -> " + settingKey + " does not specify a minimum value.");
}

if (fluid.get(settingDef, "schema.maximum") === undefined) {
fluid.log("WARNING: Numeric setting " + filename + " -> " + solutionKey + " -> " + settingsHandlerKey + " -> " + settingKey + " does not specify a maximum value.");
}
}
});

if (settingsHandlersDemandingDataTypes.indexOf(settingsHandlerType) !== -1) {
var dataTypeKeys = Object.keys(fluid.get(settingsHandlerDef, "options.dataTypes"));
Expand Down Expand Up @@ -131,7 +154,7 @@ gpii.tests.universal.solutionsRegistry.srFiles.checkCapabilities = function (fil
var termDef = genericTerms[unescapedKey];
if (termDef === undefined) {
missingTermsCount++;
fluid.log("The capability '" + capabilityKey + "' specified in solution '" + solutionKey + "' does not exist.");
fluid.log("ERROR: The capability '" + capabilityKey + "' specified in solution '" + solutionKey + "' does not exist.");
}
});

Expand Down Expand Up @@ -202,7 +225,10 @@ gpii.tests.universal.solutionsRegistry.srFiles.checkDefaults = function (globalV
// Check the specified default against its schema. This only works for simple settings, and not for
// deeply nested objects.
var defaultValue = fluid.get(supportedSetting, "schema.default");
if (defaultValue !== undefined) {
if (defaultValue === undefined) {
fluid.log("WARNING: " + filename + " -> " + solutionKey + " -> " + settingKey + " does not have a default value.");
}
else {
// Check the raw value
var isValid = gpii.tests.universal.solutionsRegistry.validateSinglePayload(
globalValidator,
Expand All @@ -226,11 +252,11 @@ gpii.tests.universal.solutionsRegistry.srFiles.checkDefaults = function (globalV
if (reinvertedDefaultValue !== defaultValue) {
// Warn on "softly equal" things like "truthy" and "falsy" values.
if (reinvertedDefaultValue != defaultValue) { // eslint-disable-line eqeqeq
fluid.log("ERROR: The capabilities transforms for " + solutionKey + " -> " + settingKey + " may result in data corruption.");
fluid.log("ERROR: The capabilities transforms for " + filename + " -> " + solutionKey + " -> " + settingKey + " may result in data corruption.");
fileErrors++;
}
else {
fluid.log("WARNING: The capabilities transforms for " + solutionKey + " -> " + settingKey + " are only safe for truthy and falsy values.");
fluid.log("WARNING: The capabilities transforms for " + filename + " -> " + solutionKey + " -> " + settingKey + " are only safe for truthy and falsy values.");
}
}
}
Expand Down
Loading

0 comments on commit 4fbdab6

Please sign in to comment.