gpii-universal
Version:
Cross platform, core components of the GPII personalization infrastructure.
201 lines (171 loc) • 10.9 kB
JavaScript
;
var fluid = require("infusion");
var gpii = fluid.registerNamespace("gpii");
var jqUnit = require("node-jqunit");
require("json5/lib/register");
require("gpii-json-schema");
require("./lib/validation");
require("./lib/utils");
require("../../transformer/src/js/Transformer");
jqUnit.module("Sanity checks for Generic Preference Terms data.");
fluid.registerNamespace("gpii.tests.universal.solutionsRegistry.genericTerms");
// Validate the generic preference settings to confirm that they're at least valid GSS schemas.
gpii.tests.universal.solutionsRegistry.genericTerms.validateCommonTerms = function (that, globalValidator) {
var resolvedGenericTermsPath = fluid.module.resolvePath(that.options.genericPreferenceTermsPath);
var genericTerms = require(resolvedGenericTermsPath);
jqUnit.test("Validating generic preference term schemas.", function () {
fluid.each(genericTerms, function (termDef, termKey) {
if (termDef.schema) {
var schemaAsGss = fluid.merge({}, { "$schema": "gss-v7-full#" }, termDef.schema);
// Separate check here as we are only validating the schema itself. In theory, this is already hit for
// any settings in our test data set, but we do it explicitly for all schemas here.
var validationResults = gpii.schema.validator.validateSchema(schemaAsGss);
// We perform these checks a bit flipped so that only a particular value trips it, and not a missing value.
jqUnit.assertFalse("There should be no validation errors in generic preference term '" + termKey + "'.", validationResults.isValid === false);
jqUnit.assertFalse("There should be no low-level errors in generic preference term '" + termKey + "'.", validationResults.isError === true);
if (!validationResults.isError && !validationResults.isValid) {
var localisedErrors = gpii.schema.validator.localiseErrors(validationResults.errors, schemaAsGss);
fluid.each(localisedErrors, function (singleError) {
fluid.log("Validation error is as folows:");
fluid.log(" - " + singleError.dataPath.join(".") + ": " + singleError.message);
});
}
}
else {
jqUnit.fail("Generic Preference Term '" + termKey + "' has no schema.");
}
});
});
jqUnit.test("Validating raw default values for all generic preference terms.", function () {
// We do this so we can report all validation errors rather than failing on the first.
var rawDefaultErrorCount = 0;
fluid.each(genericTerms, function (termDef, termKey) {
var schema = fluid.get(termDef, "schema");
var defaultValue = fluid.get(termDef, "schema.default");
if (defaultValue !== undefined) {
// Check the raw value against the schema
var isValid = gpii.tests.universal.solutionsRegistry.validateSinglePayload(
globalValidator,
defaultValue,
schema,
"Default raw value for generic preference term '" + termKey + "'"
);
if (!isValid) {
rawDefaultErrorCount++;
}
}
});
jqUnit.assertEquals("There should be no validation errors for the raw defaults.", 0, rawDefaultErrorCount);
});
jqUnit.test("Ensure that generic preference term defaults can be transformed to valid application-specific settings.", function () {
var combinedDefaults = {};
var combinedMaximums = {};
var combinedMinimums = {};
fluid.each(genericTerms, function (termDef, termKey) {
var defaultValue = fluid.get(termDef, "schema.default");
if (defaultValue !== undefined) {
combinedDefaults[termKey] = defaultValue;
// If there is no min/max, we add the default so there's at least some value. Otherwise any
// transform that refers to a generic preference term will end up with a value of `undefined`
// and likely fail.
combinedMaximums[termKey] = defaultValue;
combinedMinimums[termKey] = defaultValue;
}
var maxValue = fluid.get(termDef, "schema.maximum");
if (maxValue !== undefined) {
combinedMaximums[termKey] = maxValue;
}
var minValue = fluid.get(termDef, "schema.minimum");
if (minValue !== undefined) {
combinedMinimums[termKey] = minValue;
}
});
// Build a crude rollup of all possible transformations for all solutions.
var solutionsDefs = fluid.require(that.options.srPath);
var combinedCapabilitiesTransform = {};
fluid.each(solutionsDefs, function (solutionDef, solutionKey) {
var escapedSolutionKey = "http://registry\\.gpii\\.net/applications/" + solutionKey.replace(/\./g, "\\.");
fluid.each(solutionDef.settingsHandlers, function (settingsHandlerDef) {
if (settingsHandlerDef.capabilitiesTransformations) {
// Allow for at least a shallow mix of intra-application and common terms transforms.
var filteredTransforms = {};
fluid.each(settingsHandlerDef.capabilitiesTransformations, function (singleTransform, transformKey) {
var hasIntraApplicationTransform = gpii.tests.universal.solutionsRegistry.hasIntraApplicationTransform(singleTransform);
if (!hasIntraApplicationTransform) {
filteredTransforms[transformKey] = singleTransform;
}
});
if (Object.keys(filteredTransforms).length) {
combinedCapabilitiesTransform[escapedSolutionKey] = fluid.extend({}, combinedCapabilitiesTransform[escapedSolutionKey], filteredTransforms);
}
}
});
});
// Transform the defaults into application-specific terms.
var transformedDefaults = fluid.model.transformWithRules(combinedDefaults, combinedCapabilitiesTransform);
var transformedMaximums = fluid.model.transformWithRules(combinedMaximums, combinedCapabilitiesTransform);
var transformedMinimums = fluid.model.transformWithRules(combinedMinimums, combinedCapabilitiesTransform);
// Now validate against each solution individually.
var validationErrorCount = 0;
var codex = fluid.require(that.options.codexPath);
fluid.each(codex, function (solutionSchema, solutionKey) {
var defaultToValidate = transformedDefaults[solutionKey];
if (defaultToValidate) {
var defaultValidationResults = globalValidator.validate(solutionSchema, defaultToValidate);
if (defaultValidationResults.isError || !defaultValidationResults.isValid) {
validationErrorCount += defaultValidationResults.errors.length;
var localisedDefaultErrors = gpii.schema.validator.localiseErrors(defaultValidationResults.errors, defaultToValidate);
// Log the failure details.
fluid.log("Error validating generic preference term default(s) for " + solutionKey + ":");
gpii.tests.universal.solutionsRegistry.genericTerms.logValidationErrors(localisedDefaultErrors, defaultToValidate);
}
}
var maximumToValidate = transformedMaximums[solutionKey];
if (maximumToValidate) {
var maxValidationResults = globalValidator.validate(solutionSchema, maximumToValidate);
if (maxValidationResults.isError || !maxValidationResults.isValid) {
validationErrorCount += maxValidationResults.errors.length;
var localisedMaxErrors = gpii.schema.validator.localiseErrors(maxValidationResults.errors, maximumToValidate);
// Log the failure details.
fluid.log("Error validating generic preference term maximum value(s) for " + solutionKey + ":");
gpii.tests.universal.solutionsRegistry.genericTerms.logValidationErrors(localisedMaxErrors, maximumToValidate);
}
}
var minimumToValidate = transformedMinimums[solutionKey];
if (minimumToValidate) {
var minValidationResults = globalValidator.validate(solutionSchema, minimumToValidate);
if (minValidationResults.isError || !minValidationResults.isValid) {
validationErrorCount += minValidationResults.errors.length;
var localisedMinErrors = gpii.schema.validator.localiseErrors(minValidationResults.errors, minimumToValidate);
// Log the failure details.
fluid.log("Error validating generic preference term minimum value(s) for " + solutionKey + ":");
gpii.tests.universal.solutionsRegistry.genericTerms.logValidationErrors(localisedMinErrors, minimumToValidate);
}
}
});
// Ensure that the tests also fail if there are errors.
jqUnit.assertEquals("There should be no validation errors that result from transforming generic preference terms defaults.", 0, validationErrorCount);
});
};
gpii.tests.universal.solutionsRegistry.genericTerms.logValidationErrors = function (localisedErrors, toValidate) {
fluid.each(localisedErrors, function (singleError) {
// TODO: Track down bogus data paths like `.properties['BounceKeysInterval']`
var dataPath = Array.isArray(singleError.dataPath) ? singleError.dataPath : [];
var problematicValue = fluid.get(toValidate, dataPath);
fluid.log(" - " + dataPath.join(".") + " -> " + JSON.stringify(problematicValue) + " : " + singleError.message);
});
};
fluid.defaults("gpii.tests.universal.solutionsRegistry.genericTerms", {
gradeNames: ["fluid.component"],
genericPreferenceTermsPath: "%gpii-universal/testData/ontologies/flat.json5",
codexPath: "%gpii-universal/build/schemas/solution-schema-codex.json",
// TODO: Replace this with all solutions as part of the LSR refactor.
srPath: "%gpii-universal/testData/solutions/win32.json5",
listeners: {
"onCreate.validateCommonTerms": {
funcName: "gpii.tests.universal.solutionsRegistry.genericTerms.validateCommonTerms",
args: ["{that}", "{gpii.schema.validator}"]
}
}
});
gpii.tests.universal.solutionsRegistry.genericTerms();