Skip to content

Commit

Permalink
Merge remote-tracking branch 'antranig/FLUID-6750' into main
Browse files Browse the repository at this point in the history
* antranig/FLUID-6750:
  FLUID-6750: Comment fix following review
  FLUID-6750: Fix and test case for model-driven localisation on startup
  • Loading branch information
cindyli committed Sep 26, 2022
2 parents 84767d8 + 86bd485 commit 3bb3a81
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 45 deletions.
4 changes: 4 additions & 0 deletions src/components/orator/js/Orator.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ https://github.com/fluid-project/infusion/raw/main/Infusion-LICENSE.txt
fluid.defaults("fluid.orator", {
gradeNames: ["fluid.viewComponent"],
selectors: {
// TODO: AMB 14/9/22 This selector appears unused. The controller instead needs a "parentContainer" literal element supplied -
// The enactor then reaches in and overrides this
controller: ".flc-orator-controller",
content: ".flc-orator-content"
},
Expand Down Expand Up @@ -851,6 +853,8 @@ fluid.defaults("fluid.orator.selectionReader", {
onToggleControl: null
},
components: {
// This parser is only used within fluid.orator.selectionReader.parseElement by direct use of its "parse" function
// and it does not need configuration
parser: {
type: "fluid.textNodeParser"
}
Expand Down
67 changes: 34 additions & 33 deletions src/framework/core/js/ResourceLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ https://github.com/fluid-project/infusion/raw/main/Infusion-LICENSE.txt
* This is similar to the algorithm specified for localised resources in Java, e.g. documented at
* https://docs.oracle.com/javase/6/docs/api/java/util/ResourceBundle.html#getBundle%28java.lang.String,%20java.util.Locale,%20java.lang.ClassLoader%29
* @param {String} fileName - The base filename or URL to be exploded
* @param {String} locale - A locale name with respect to which to perform the explosion
* @param {String} [locale] - A locale name with respect to which to perform the explosion
* @param {String} [defaultLocale] - An optional default locale to fall back on in the case none of the localised
* variants could be located.
* @return {String[]} An array of localised filenames to be fetched, in increasing order of specificity. In
Expand All @@ -36,7 +36,7 @@ fluid.explodeLocalisedName = function (fileName, locale, defaultLocale) {
var baseName = fileName.substring(0, lastDot);
var extension = fileName.substring(lastDot);

var segs = locale.split("_");
var segs = locale ? locale.split("_") : [];

var exploded = fluid.transform(segs, function (seg, index) {
var shortSegs = segs.slice(0, index + 1);
Expand Down Expand Up @@ -127,33 +127,28 @@ fluid.fetchResources = function (resourceSpecs, callback, options) {
*/
fluid.fetchResources.explodeForLocales = function (resourceFetcher) {
fluid.each(resourceFetcher.resourceSpecs, function (resourceSpec) {
if (!resourceSpec.launched) {
// If options.defaultLocale is set, it will replace any
// defaultLocale set on an individual resourceSpec
if (resourceFetcher.options.defaultLocale && resourceSpec.defaultLocale === undefined) {
resourceSpec.defaultLocale = resourceFetcher.options.defaultLocale;
}
if (resourceSpec.locale === undefined) {
resourceSpec.locale = resourceFetcher.options.locale || resourceSpec.defaultLocale;
}
resourceSpec.dataType = resourceSpec.dataType || resourceFetcher.options.dataType;

resourceSpec.loader = fluid.resourceLoader.resolveResourceLoader(resourceSpec);
if (!resourceSpec.loader.loader.noPath) {
var pathKey = resourceSpec.loader.pathKey;
var path = resourceSpec[pathKey];
var resolvedPath = resourceSpec[pathKey] = resourceFetcher.transformResourceURL(path);
if (resourceSpec.locale) {
resourceSpec.localeExploded = fluid.explodeLocalisedName(resolvedPath, resourceSpec.locale, resourceSpec.defaultLocale);
resourceSpec.localeExplodedSpecs = fluid.transform(resourceSpec.localeExploded, function (oneExploded) {
var togo = {
loader: resourceSpec.loader
};
togo[pathKey] = oneExploded;
return togo;
}, fluid.fetchResources.prepareRequestOptions);
}
}
// If options.defaultLocale is set, it will be a default for defaultLocale set on an individual resourceSpec
resourceSpec.resolvedDefaultLocale = resourceSpec.defaultLocale || resourceFetcher.options.defaultLocale;
// A locale from the model takes priority over any locally set locale - should review this
resourceSpec.resolvedLocale = resourceFetcher.options.locale || resourceSpec.locale || resourceSpec.resolvedDefaultLocale;

// Note: An important change from Infusion 4.3 - EVERY resourceSpec with a path now gets upgraded to localeExplodedSpecs,
// since we could never be sure that they wouldn't get localised as a result of a change to model.resourceLoader.locale
// and the "loader" gets established as part of the very first pass in resolveLoaderTask
// Fix for FLUID-6750
if (!resourceSpec.loader.loader.noPath) {
var pathKey = resourceSpec.loader.pathKey;
var path = resourceSpec[pathKey];
var resolvedPath = resourceSpec[pathKey] = resourceFetcher.transformResourceURL(path);
resourceSpec.localeExploded = fluid.explodeLocalisedName(resolvedPath, resourceSpec.resolvedLocale, resourceSpec.resolvedDefaultLocale);
resourceSpec.localeExplodedSpecs = fluid.transform(resourceSpec.localeExploded, function (oneExploded) {
var togo = {
loader: resourceSpec.loader,
options: resourceSpec.options
};
togo[pathKey] = oneExploded;
return togo;
}, fluid.fetchResources.prepareRequestOptions);
}
});
};
Expand Down Expand Up @@ -413,6 +408,7 @@ fluid.initResourceFetcher = function (resourceFetcher) {
*/
resourceFetcher.completionPromise = fluid.promise();
fluid.fetchResources.explodeForLocales(resourceFetcher);

resourceFetcher.onInit.fire(resourceFetcher.completionPromise);
};

Expand Down Expand Up @@ -500,6 +496,11 @@ fluid.makeResourceFetcher = function (sourceResourceSpecs, callback, options, tr
that.onInit.addListener.apply(null, args);
});

fluid.each(that.resourceSpecs, function (resourceSpec) {
resourceSpec.dataType = resourceSpec.dataType || that.options.dataType;
resourceSpec.loader = fluid.resourceLoader.resolveResourceLoader(resourceSpec);
});

fluid.initResourceFetcher(that);

fluid.each(that.resourceSpecs, function (resourceSpec, key) {
Expand Down Expand Up @@ -559,22 +560,21 @@ fluid.fetchResources.refetchOneResource = function (resourceSpec, resourceFetche
fluid.fetchResources.initiateRefetch = function (resourceFetcher) {
resourceFetcher.completionPromise.cancel();
delete resourceFetcher.completionPromise;
fluid.initResourceFetcher(resourceFetcher);
fluid.initResourceFetcher(resourceFetcher, true);
fluid.fetchResources.fetchAll(resourceFetcher);
resourceFetcher.fetchAll();
};

/** Trigger the refetching of all resources managed by this `resourceFetcher`. By default, this will only fetch resources
* which are localisable (that is, they have resource entries with a path field which can be interpolated for a locale)
* @param {resourceFetcher} resourceFetcher - The fetcher for which all resources will be loaded
* @param {Boolean} [withoutLocales] - (Optional) Set to `true` if this should also fetch resources which are not localisable
* @return {Promise} The `completionPromise` for the fetcher which will yield the full state of fetched `resourceSpecs`
* in either success or failure
*/
fluid.fetchResources.refetchAll = function (resourceFetcher, withoutLocales) {
fluid.fetchResources.refetchAll = function (resourceFetcher) {
var anyLaunched = false;
fluid.each(resourceFetcher.resourceSpecs, function (resourceSpec) {
if (resourceSpec.locale || withoutLocales) {
if (resourceSpec.resolvedLocale) {
anyLaunched = true;
fluid.fetchResources.refetchOneResource(resourceSpec, resourceFetcher, true);
}
Expand Down Expand Up @@ -650,6 +650,7 @@ fluid.registerNamespace("fluid.resourceLoader.loaders");
fluid.resourceLoader.modelUpdated = function (resourceFetcher, modelOptions, early) {
resourceFetcher.options = $.extend(true, {}, resourceFetcher.options, modelOptions);
if (early) {
fluid.fetchResources.explodeForLocales(resourceFetcher);
resourceFetcher.optionsReady.resolve();
} else {
resourceFetcher.refetchAll();
Expand Down
2 changes: 1 addition & 1 deletion src/framework/core/js/TextNodeParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ fluid.textNodeParser.getLang = function (elm) {
/**
* Recursively parses a DOM element and it's sub elements and fires the `onParsedTextNode` event for each text node
* found. The event is fired with the text node, language and index of the text node in the list of its parent's
* child nodes..
* child nodes.
*
* Note: elements that return `false` from `that.hasTextToRead` are ignored.
*
Expand Down
1 change: 1 addition & 0 deletions src/framework/preferences/js/LocalizationEnactor.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ fluid.defaults("fluid.prefs.enactor.localization", {
// At the moment, all enactors are copied into the iframe to apply settings to the panel as well.
// However, the strings for the panel will be localized through the prefsEditorLoader and do not
// require the iframe URL to change. When in the panel, we do not run the urlPathLocale changes.
// TODO: This grade is undefined and this check should be removed, especially as we remove the iframe renderer
inPanel: {
contextValue: "{iframeRenderer}.id",
// The following undefined grade is needed to prevent the `urlPath` check from supplying its
Expand Down
46 changes: 37 additions & 9 deletions tests/framework-tests/core/js/DataBindingTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -903,23 +903,51 @@ fluid.tests.fluid6442.checkIt = function (component) {
}
};

fluid.defaults("fluid.tests.fluid6442options", {
listeners: {
"onResourcesLoaded.checkIt": {
func: "fluid.tests.fluid6442.checkIt",
args: "{that}"
},
"onResourceError.failTest": function (err) {
jqUnit.fail("Failure fetching resource: " + err);
}
}
});

jqUnit.asyncTest("FLUID-6442: Modelised relocalisation should be accessible via resources", function () {
jqUnit.expect(2);
var component = fluid.tests.fluid6442({
listeners: {
"onResourcesLoaded.checkIt": {
func: "fluid.tests.fluid6442.checkIt",
args: "{that}"
},
"onResourceError.failTest": function (err) {
jqUnit.fail("Failure fetching resource: " + err);
}
}
gradeNames: "fluid.tests.fluid6442options"
});
// Change the locale before the queued I/O can resolve. In addition this tests promise cancellation propagation.
component.applier.change("resourceLoader.locale", "en_ZA");
});

/** FLUID-6750: Modelised relocalisation should work on startup **/

fluid.defaults("fluid.tests.fluid6750", {
gradeNames: ["fluid.modelComponent", "fluid.resourceLoader"],
resources: {
messages: {
url: "../data/messages1.json",
dataType: "json"
}
},
model: {
resourceLoader: {
locale: "en_ZA"
}
}
});

jqUnit.asyncTest("FLUID-6750: Modelised relocalisation should work on startup", function () {
jqUnit.expect(2);
fluid.tests.fluid6750({
gradeNames: "fluid.tests.fluid6442options"
});
});

/** FLUID-6503: Two side-by-side modelised resources **/

fluid.defaults("fluid.tests.fluid6503", {
Expand Down
5 changes: 3 additions & 2 deletions tests/framework-tests/core/js/ResourceLoaderTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ jqUnit.asyncTest("FLUID-4982: Overlapping creation of asynchronous components",
jqUnit.assertEquals("First component model resolved", "second", first.model);
jqUnit.assertEquals("Second component model resolved", "first", second.model);
jqUnit.assertTrue("Failed component has been destroyed", fluid.isDestroyed(failed));
jqUnit.assertEquals("Status code recoverable from failed component", 404, failed.creationPromise.value.status);
jqUnit.assertTrue("Status code recoverable from failed component", 404, failed.creationPromise.value.message.includes("/notfound"));
jqUnit.assertTrue("onDestroy called for failed component", true, failed.onDestroyCalled);
jqUnit.assertTrue("afterDestroy called for failed component", true, failed.onDestroyCalled);
mocks.destroy();
Expand All @@ -430,7 +430,8 @@ fluid.defaults("fluid.tests.FLUID6460", {

jqUnit.test("FLUID-6460: Transfer options to XHR", function () {
var that = fluid.tests.FLUID6460();
jqUnit.assertEquals("Should have transferred responseType option to XHR property", "arraybuffer", that.resourceFetcher.resourceSpecs.someResource.xhr.responseType);
var spec = that.resourceFetcher.resourceSpecs.someResource;
jqUnit.assertEquals("Should have transferred responseType option to XHR property", "arraybuffer", spec.localeExplodedSpecs[0].xhr.responseType);
});

/** FLUID-4982: Partially filled out resource blocks **/
Expand Down

0 comments on commit 3bb3a81

Please sign in to comment.