зеркало из https://github.com/mozilla/gecko-dev.git
474 строки
14 KiB
JavaScript
474 строки
14 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
const {
|
|
L10nRegistry,
|
|
FileSource,
|
|
IndexedFileSource,
|
|
} = ChromeUtils.import("resource://gre/modules/L10nRegistry.jsm");
|
|
const {setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
|
|
|
|
let fs;
|
|
|
|
L10nRegistry.loadSync = function(url) {
|
|
if (!fs.hasOwnProperty(url)) {
|
|
return false;
|
|
}
|
|
return fs[url];
|
|
};
|
|
|
|
add_task(function test_methods_presence() {
|
|
equal(typeof L10nRegistry.generateBundles, "function");
|
|
equal(typeof L10nRegistry.getAvailableLocales, "function");
|
|
equal(typeof L10nRegistry.registerSources, "function");
|
|
equal(typeof L10nRegistry.removeSources, "function");
|
|
equal(typeof L10nRegistry.updateSources, "function");
|
|
});
|
|
|
|
/**
|
|
* Test that passing empty resourceIds list works.
|
|
*/
|
|
add_task(function test_empty_resourceids() {
|
|
fs = {};
|
|
|
|
const source = new FileSource("test", ["en-US"], "/localization/{locale}");
|
|
L10nRegistry.registerSources([source]);
|
|
|
|
const bundles = L10nRegistry.generateBundlesSync(["en-US"], []);
|
|
|
|
const done = (bundles.next()).done;
|
|
|
|
equal(done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* Test that passing empty sources list works.
|
|
*/
|
|
add_task(function test_empty_sources() {
|
|
fs = {};
|
|
|
|
const bundles = L10nRegistry.generateBundlesSync(["en-US"], []);
|
|
|
|
const done = (bundles.next()).done;
|
|
|
|
equal(done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test tests generation of a proper context for a single
|
|
* source scenario
|
|
*/
|
|
add_task(function test_methods_calling() {
|
|
fs = {
|
|
"/localization/en-US/browser/menu.ftl": "key = Value",
|
|
};
|
|
|
|
const source = new FileSource("test", ["en-US"], "/localization/{locale}");
|
|
L10nRegistry.registerSources([source]);
|
|
|
|
const bundles = L10nRegistry.generateBundlesSync(["en-US"], ["/browser/menu.ftl"]);
|
|
|
|
const bundle = (bundles.next()).value;
|
|
|
|
equal(bundle.hasMessage("key"), true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test verifies that the public methods return expected values
|
|
* for the single source scenario
|
|
*/
|
|
add_task(function test_has_one_source() {
|
|
let oneSource = new FileSource("app", ["en-US"], "./app/data/locales/{locale}/");
|
|
fs = {
|
|
"./app/data/locales/en-US/test.ftl": "key = value en-US",
|
|
};
|
|
L10nRegistry.registerSources([oneSource]);
|
|
|
|
|
|
// has one source
|
|
|
|
equal(L10nRegistry.sources.size, 1);
|
|
equal(L10nRegistry.sources.has("app"), true);
|
|
|
|
|
|
// returns a single context
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["en-US"], ["test.ftl"]);
|
|
let bundle0 = (bundles.next()).value;
|
|
equal(bundle0.hasMessage("key"), true);
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
|
|
// returns no contexts for missing locale
|
|
|
|
bundles = L10nRegistry.generateBundlesSync(["pl"], ["test.ftl"]);
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test verifies that public methods return expected values
|
|
* for the dual source scenario.
|
|
*/
|
|
add_task(function test_has_two_sources() {
|
|
let oneSource = new FileSource("platform", ["en-US"], "./platform/data/locales/{locale}/");
|
|
let secondSource = new FileSource("app", ["pl"], "./app/data/locales/{locale}/");
|
|
L10nRegistry.registerSources([oneSource, secondSource]);
|
|
fs = {
|
|
"./platform/data/locales/en-US/test.ftl": "key = platform value",
|
|
"./app/data/locales/pl/test.ftl": "key = app value",
|
|
};
|
|
|
|
|
|
// has two sources
|
|
|
|
equal(L10nRegistry.sources.size, 2);
|
|
equal(L10nRegistry.sources.has("app"), true);
|
|
equal(L10nRegistry.sources.has("platform"), true);
|
|
|
|
|
|
// returns correct contexts for en-US
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["en-US"], ["test.ftl"]);
|
|
let bundle0 = (bundles.next()).value;
|
|
|
|
equal(bundle0.hasMessage("key"), true);
|
|
let msg = bundle0.getMessage("key");
|
|
equal(bundle0.formatPattern(msg.value), "platform value");
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
|
|
// returns correct contexts for [pl, en-US]
|
|
|
|
bundles = L10nRegistry.generateBundlesSync(["pl", "en-US"], ["test.ftl"]);
|
|
bundle0 = (bundles.next()).value;
|
|
equal(bundle0.locales[0], "pl");
|
|
equal(bundle0.hasMessage("key"), true);
|
|
let msg0 = bundle0.getMessage("key");
|
|
equal(bundle0.formatPattern(msg0.value), "app value");
|
|
|
|
let bundle1 = (bundles.next()).value;
|
|
equal(bundle1.locales[0], "en-US");
|
|
equal(bundle1.hasMessage("key"), true);
|
|
let msg1 = bundle1.getMessage("key");
|
|
equal(bundle1.formatPattern(msg1.value), "platform value");
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test verifies that behavior specific to the IndexedFileSource
|
|
* works correctly.
|
|
*
|
|
* In particular it tests that IndexedFileSource correctly returns
|
|
* missing files as `false` instead of `undefined`.
|
|
*/
|
|
add_task(function test_indexed() {
|
|
let oneSource = new IndexedFileSource("langpack-pl", ["pl"], "/data/locales/{locale}/", [
|
|
"/data/locales/pl/test.ftl",
|
|
]);
|
|
L10nRegistry.registerSources([oneSource]);
|
|
fs = {
|
|
"/data/locales/pl/test.ftl": "key = value",
|
|
};
|
|
|
|
equal(L10nRegistry.sources.size, 1);
|
|
equal(L10nRegistry.sources.has("langpack-pl"), true);
|
|
|
|
equal(oneSource.getPath("pl", "test.ftl"), "/data/locales/pl/test.ftl");
|
|
equal(oneSource.hasFile("pl", "test.ftl"), true);
|
|
equal(oneSource.hasFile("pl", "missing.ftl"), false);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test checks if the correct order of contexts is used for
|
|
* scenarios where a new file source is added on top of the default one.
|
|
*/
|
|
add_task(function test_override() {
|
|
let fileSource = new FileSource("app", ["pl"], "/app/data/locales/{locale}/");
|
|
let oneSource = new IndexedFileSource("langpack-pl", ["pl"], "/data/locales/{locale}/", [
|
|
"/data/locales/pl/test.ftl",
|
|
]);
|
|
L10nRegistry.registerSources([fileSource, oneSource]);
|
|
|
|
fs = {
|
|
"/app/data/locales/pl/test.ftl": "key = value",
|
|
"/data/locales/pl/test.ftl": "key = addon value",
|
|
};
|
|
|
|
equal(L10nRegistry.sources.size, 2);
|
|
equal(L10nRegistry.sources.has("langpack-pl"), true);
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["pl"], ["test.ftl"]);
|
|
let bundle0 = (bundles.next()).value;
|
|
equal(bundle0.locales[0], "pl");
|
|
equal(bundle0.hasMessage("key"), true);
|
|
let msg0 = bundle0.getMessage("key");
|
|
equal(bundle0.formatPattern(msg0.value), "addon value");
|
|
|
|
let bundle1 = (bundles.next()).value;
|
|
equal(bundle1.locales[0], "pl");
|
|
equal(bundle1.hasMessage("key"), true);
|
|
let msg1 = bundle1.getMessage("key");
|
|
equal(bundle1.formatPattern(msg1.value), "value");
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test verifies that new contexts are returned
|
|
* after source update.
|
|
*/
|
|
add_task(function test_updating() {
|
|
let oneSource = new IndexedFileSource("langpack-pl", ["pl"], "/data/locales/{locale}/", [
|
|
"/data/locales/pl/test.ftl",
|
|
]);
|
|
L10nRegistry.registerSources([oneSource]);
|
|
fs = {
|
|
"/data/locales/pl/test.ftl": "key = value",
|
|
};
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["pl"], ["test.ftl"]);
|
|
let bundle0 = (bundles.next()).value;
|
|
equal(bundle0.locales[0], "pl");
|
|
equal(bundle0.hasMessage("key"), true);
|
|
let msg0 = bundle0.getMessage("key");
|
|
equal(bundle0.formatPattern(msg0.value), "value");
|
|
|
|
|
|
const newSource = new IndexedFileSource("langpack-pl", ["pl"], "/data/locales/{locale}/", [
|
|
"/data/locales/pl/test.ftl",
|
|
]);
|
|
fs["/data/locales/pl/test.ftl"] = "key = new value";
|
|
L10nRegistry.updateSources([newSource]);
|
|
|
|
equal(L10nRegistry.sources.size, 1);
|
|
bundles = L10nRegistry.generateBundlesSync(["pl"], ["test.ftl"]);
|
|
bundle0 = (bundles.next()).value;
|
|
msg0 = bundle0.getMessage("key");
|
|
equal(bundle0.formatPattern(msg0.value), "new value");
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test verifies that generated contexts return correct values
|
|
* after sources are being removed.
|
|
*/
|
|
add_task(function test_removing() {
|
|
let fileSource = new FileSource("app", ["pl"], "/app/data/locales/{locale}/");
|
|
let oneSource = new IndexedFileSource("langpack-pl", ["pl"], "/data/locales/{locale}/", [
|
|
"/data/locales/pl/test.ftl",
|
|
]);
|
|
L10nRegistry.registerSources([fileSource, oneSource]);
|
|
|
|
fs = {
|
|
"/app/data/locales/pl/test.ftl": "key = value",
|
|
"/data/locales/pl/test.ftl": "key = addon value",
|
|
};
|
|
|
|
equal(L10nRegistry.sources.size, 2);
|
|
equal(L10nRegistry.sources.has("langpack-pl"), true);
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["pl"], ["test.ftl"]);
|
|
let bundle0 = (bundles.next()).value;
|
|
equal(bundle0.locales[0], "pl");
|
|
equal(bundle0.hasMessage("key"), true);
|
|
let msg0 = bundle0.getMessage("key");
|
|
equal(bundle0.formatPattern(msg0.value), "addon value");
|
|
|
|
let bundle1 = (bundles.next()).value;
|
|
equal(bundle1.locales[0], "pl");
|
|
equal(bundle1.hasMessage("key"), true);
|
|
let msg1 = bundle1.getMessage("key");
|
|
equal(bundle1.formatPattern(msg1.value), "value");
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
// Remove langpack
|
|
|
|
L10nRegistry.removeSources(["langpack-pl"]);
|
|
|
|
equal(L10nRegistry.sources.size, 1);
|
|
equal(L10nRegistry.sources.has("langpack-pl"), false);
|
|
|
|
bundles = L10nRegistry.generateBundlesSync(["pl"], ["test.ftl"]);
|
|
bundle0 = (bundles.next()).value;
|
|
equal(bundle0.locales[0], "pl");
|
|
equal(bundle0.hasMessage("key"), true);
|
|
msg0 = bundle0.getMessage("key");
|
|
equal(bundle0.formatPattern(msg0.value), "value");
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
// Remove app source
|
|
|
|
L10nRegistry.removeSources(["app"]);
|
|
|
|
equal(L10nRegistry.sources.size, 0);
|
|
|
|
bundles = L10nRegistry.generateBundlesSync(["pl"], ["test.ftl"]);
|
|
equal((bundles.next()).done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test verifies that the logic works correctly when there's a missing
|
|
* file in the FileSource scenario.
|
|
*/
|
|
add_task(function test_missing_file() {
|
|
let oneSource = new FileSource("app", ["en-US"], "./app/data/locales/{locale}/");
|
|
let twoSource = new FileSource("platform", ["en-US"], "./platform/data/locales/{locale}/");
|
|
L10nRegistry.registerSources([oneSource, twoSource]);
|
|
|
|
fs = {
|
|
"./app/data/locales/en-US/test.ftl": "key = value en-US",
|
|
"./platform/data/locales/en-US/test.ftl": "key = value en-US",
|
|
"./platform/data/locales/en-US/test2.ftl": "key2 = value2 en-US",
|
|
};
|
|
|
|
|
|
// has two sources
|
|
|
|
equal(L10nRegistry.sources.size, 2);
|
|
equal(L10nRegistry.sources.has("app"), true);
|
|
equal(L10nRegistry.sources.has("platform"), true);
|
|
|
|
|
|
// returns a single context
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["en-US"], ["test.ftl", "test2.ftl"]);
|
|
|
|
// First permutation:
|
|
// [platform, platform] - both present
|
|
let bundle1 = (bundles.next());
|
|
equal(bundle1.value.hasMessage("key"), true);
|
|
|
|
// Second permutation skipped:
|
|
// [platform, app] - second missing
|
|
// Third permutation:
|
|
// [app, platform] - both present
|
|
let bundle2 = (bundles.next());
|
|
equal(bundle2.value.hasMessage("key"), true);
|
|
|
|
// Fourth permutation skipped:
|
|
// [app, app] - second missing
|
|
equal((bundles.next()).done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|
|
|
|
/**
|
|
* This test verifies that each file is that all files requested
|
|
* by a single context are fetched at the same time, even
|
|
* if one I/O is slow.
|
|
*/
|
|
add_task(function test_parallel_io() {
|
|
/* eslint-disable mozilla/no-arbitrary-setTimeout */
|
|
let originalLoad = L10nRegistry.load;
|
|
let fetchIndex = new Map();
|
|
|
|
L10nRegistry.load = function(url) {
|
|
if (!fetchIndex.has(url)) {
|
|
fetchIndex.set(url, 0);
|
|
}
|
|
fetchIndex.set(url, fetchIndex.get(url) + 1);
|
|
|
|
if (url === "/en-US/slow-file.ftl") {
|
|
return new Promise((resolve, reject) => {
|
|
setTimeout(() => {
|
|
// Despite slow-file being the first on the list,
|
|
// by the time the it finishes loading, the other
|
|
// two files are already fetched.
|
|
equal(fetchIndex.get("/en-US/test.ftl"), 1);
|
|
equal(fetchIndex.get("/en-US/test2.ftl"), 1);
|
|
|
|
resolve("");
|
|
}, 10);
|
|
});
|
|
}
|
|
return Promise.resolve("");
|
|
};
|
|
let oneSource = new FileSource("app", ["en-US"], "/{locale}/");
|
|
L10nRegistry.registerSources([oneSource]);
|
|
|
|
fs = {
|
|
"/en-US/test.ftl": "key = value en-US",
|
|
"/en-US/test2.ftl": "key2 = value2 en-US",
|
|
"/en-US/slow-file.ftl": "key-slow = value slow en-US",
|
|
};
|
|
|
|
// returns a single context
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["en-US"], ["slow-file.ftl", "test.ftl", "test2.ftl"]);
|
|
|
|
equal(fetchIndex.size, 0);
|
|
|
|
let bundle0 = bundles.next();
|
|
|
|
equal(bundle0.done, false);
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
// When requested again, the cache should make the load operation not
|
|
// increase the fetchedIndex count
|
|
L10nRegistry.generateBundlesSync(["en-US"], ["test.ftl", "test2.ftl", "slow-file.ftl"]);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
L10nRegistry.load = originalLoad;
|
|
});
|
|
|
|
/**
|
|
* This test verifies that we handle correctly a scenario where a source
|
|
* is being removed while the iterator operates.
|
|
*/
|
|
add_task(function test_remove_source_mid_iter_cycle() {
|
|
let oneSource = new FileSource("platform", ["en-US"], "./platform/data/locales/{locale}/");
|
|
let secondSource = new FileSource("app", ["pl"], "./app/data/locales/{locale}/");
|
|
L10nRegistry.registerSources([oneSource, secondSource]);
|
|
|
|
fs = {
|
|
"./platform/data/locales/en-US/test.ftl": "key = platform value",
|
|
"./app/data/locales/pl/test.ftl": "key = app value",
|
|
};
|
|
|
|
let bundles = L10nRegistry.generateBundlesSync(["en-US", "pl"], ["test.ftl"]);
|
|
|
|
let bundle0 = bundles.next();
|
|
|
|
L10nRegistry.removeSources(["app"]);
|
|
|
|
equal((bundles.next()).done, true);
|
|
|
|
// cleanup
|
|
L10nRegistry.sources.clear();
|
|
});
|