Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
71
gaia/apps/sharedtest/test/unit/l10n/lib/context/basic_test.js
Executable file
71
gaia/apps/sharedtest/test/unit/l10n/lib/context/basic_test.js
Executable file
|
|
@ -0,0 +1,71 @@
|
|||
/* global assert:true, it, describe, beforeEach */
|
||||
/* global navigator, __dirname */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var L20n = {
|
||||
getContext: function() {
|
||||
return new L10n.Context();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var L20n = require('../../../src/bindings/node');
|
||||
}
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var path =
|
||||
'app://sharedtest.gaiamobile.org/test/unit/l10n/lib/context';
|
||||
} else {
|
||||
var path = __dirname;
|
||||
}
|
||||
|
||||
describe('A simple context with one resource', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = L20n.getContext();
|
||||
ctx.resLinks.push(path + '/fixtures/basic.properties');
|
||||
ctx.ready(done);
|
||||
ctx.registerLocales('en-US');
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should return the string value of brandName', function() {
|
||||
var value = ctx.get('brandName');
|
||||
assert.strictEqual(value, 'Firefox');
|
||||
});
|
||||
|
||||
it('should return the value of about with the value' +
|
||||
' of brandName in it', function() {
|
||||
var value = ctx.get('about');
|
||||
assert.strictEqual(value, 'About Firefox');
|
||||
});
|
||||
|
||||
it('should return the value of cert with the value of ' +
|
||||
'organization passed directly', function() {
|
||||
var value = ctx.get('cert', {organization: 'Mozilla Foundation'});
|
||||
assert.strictEqual(value, 'Certificate signed by Mozilla Foundation');
|
||||
});
|
||||
|
||||
it('should return the correct plural form for 0', function() {
|
||||
var value = ctx.get('unreadMessages', {unread: 0});
|
||||
assert.strictEqual(value, '0 unread');
|
||||
});
|
||||
|
||||
it('should return the correct plural form for 1', function() {
|
||||
var value = ctx.get('unreadMessages', {unread: 1});
|
||||
assert.strictEqual(value, 'One unread');
|
||||
});
|
||||
|
||||
it('should return the correct plural form for 2', function() {
|
||||
var value = ctx.get('unreadMessages', {unread: 2});
|
||||
assert.strictEqual(value, '2 unread');
|
||||
});
|
||||
|
||||
it('should return the correct plural form for 3', function() {
|
||||
var value = ctx.get('unreadMessages', {unread: 3});
|
||||
assert.strictEqual(value, '3 unread');
|
||||
});
|
||||
});
|
||||
110
gaia/apps/sharedtest/test/unit/l10n/lib/context/fallback_test.js
Executable file
110
gaia/apps/sharedtest/test/unit/l10n/lib/context/fallback_test.js
Executable file
|
|
@ -0,0 +1,110 @@
|
|||
/* global assert:true, it, describe, beforeEach */
|
||||
/* global navigator, __dirname */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var Context = L10n.Context;
|
||||
var path =
|
||||
'app://sharedtest.gaiamobile.org/test/unit/l10n/lib/context';
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Context = require('../../../src/lib/context').Context;
|
||||
var path = __dirname;
|
||||
}
|
||||
|
||||
describe('One fallback locale', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/{locale}.properties');
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US', ['pl']);
|
||||
ctx.requestLocales('pl');
|
||||
});
|
||||
|
||||
describe('Translation in the first locale exists and is OK', function() {
|
||||
it('[e]', function() {
|
||||
assert.strictEqual(ctx.get('e'), 'E pl');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in first locale', function() {
|
||||
describe('Entity exists in second locale:', function() {
|
||||
it('[ve]', function() {
|
||||
assert.strictEqual(ctx.get('ve'), 'VE {{ boo }} pl');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in second locale:', function() {
|
||||
it('[vv]', function() {
|
||||
assert.strictEqual(ctx.get('vv'), 'VV {{ boo }} pl');
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in second locale:', function() {
|
||||
it('[vi]', function() {
|
||||
assert.strictEqual(ctx.get('vi'), 'VI {{ boo }} pl');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity missing in second locale:', function() {
|
||||
it('[vm]', function() {
|
||||
assert.strictEqual(ctx.get('vm'), 'VM {{ boo }} pl');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in first locale', function() {
|
||||
describe('Entity exists in second locale', function() {
|
||||
it('[ie]', function() {
|
||||
assert.strictEqual(ctx.get('ie'), 'ie');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in second locale', function() {
|
||||
it('[iv]', function() {
|
||||
assert.strictEqual(ctx.get('iv'), 'iv');
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in second locale', function() {
|
||||
it('[ii]', function() {
|
||||
assert.strictEqual(ctx.get('ii'), 'ii');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity missing in second locale:', function() {
|
||||
it('[im]', function() {
|
||||
assert.strictEqual(ctx.get('im'), 'im');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity not found in first locale', function() {
|
||||
describe('Entity exists in second locale:', function() {
|
||||
it('[me]', function() {
|
||||
assert.strictEqual(ctx.get('me'), 'ME en-US');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in second locale:', function() {
|
||||
it('[mv]', function() {
|
||||
assert.strictEqual(ctx.get('mv'), 'MV {{ boo }} en-US');
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in second locale:', function() {
|
||||
it('[mi]', function() {
|
||||
assert.strictEqual(ctx.get('mi'), 'mi');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity missing in second locale:', function() {
|
||||
it('[mm]', function() {
|
||||
assert.strictEqual(ctx.get('mm'), '');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
brandName=Firefox
|
||||
about=About {{ brandName }}
|
||||
cert=Certificate signed by {{ organization }}
|
||||
unreadMessages={[plural(unread)]}
|
||||
unreadMessages[one]=One unread
|
||||
unreadMessages[other]={{unread}} unread
|
||||
57
gaia/apps/sharedtest/test/unit/l10n/lib/context/fixtures/en-US.properties
Executable file
57
gaia/apps/sharedtest/test/unit/l10n/lib/context/fixtures/en-US.properties
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
foo=Foo en-US
|
||||
|
||||
# e - existing
|
||||
# v - ValueError
|
||||
# i - IndexError
|
||||
# m - missing
|
||||
|
||||
me=ME en-US
|
||||
mv=MV {{ boo }} en-US
|
||||
mi={[plural(boo)]}
|
||||
mi[key]=MI en-US
|
||||
|
||||
vve=VVE en-US
|
||||
vvv=VVV {{ boo }} en-US
|
||||
<vvi[boo] { key: "VVI en-US" }>
|
||||
|
||||
vie=VIE en-US
|
||||
viv=VIV {{ boo }} en-US
|
||||
vii={[plural(boo)]}
|
||||
vii[key]=VII en-US
|
||||
|
||||
vme=VME en-US
|
||||
vmv=VMV {{ boo }} en-US
|
||||
vmi={[plural(boo)]}
|
||||
vmi[key]=VMI en-US
|
||||
|
||||
|
||||
ive=IVE en-US
|
||||
ivv=IVV {{ boo }} en-US
|
||||
ivi={[plural(boo)]}
|
||||
ivi[key]=IVI en-US
|
||||
|
||||
iie=IIE en-US
|
||||
iiv=IIV {{ boo }} en-US
|
||||
iii={[plural(boo)]}
|
||||
iii[key]=III en-US
|
||||
|
||||
ime=IME en-US
|
||||
imv=IMV {{ boo }} en-US
|
||||
imi={[plural(boo)]}
|
||||
imi[key]=IMI en-US
|
||||
|
||||
|
||||
mve=MVE en-US
|
||||
mvv=MVV {{ boo }} en-US
|
||||
mvi={[plural(boo)]}
|
||||
mvi[key]=MVI en-US
|
||||
|
||||
mie=MIE en-US
|
||||
miv=MIV {{ boo }} en-US
|
||||
mii={[plural(boo)]}
|
||||
mii[key]=MII en-US
|
||||
|
||||
mme=MME en-US
|
||||
mmv=MMV {{ boo }} en-US
|
||||
mmi={[plural(boo)]}
|
||||
mmi[key]=MMI en-US
|
||||
69
gaia/apps/sharedtest/test/unit/l10n/lib/context/fixtures/pl.properties
Executable file
69
gaia/apps/sharedtest/test/unit/l10n/lib/context/fixtures/pl.properties
Executable file
|
|
@ -0,0 +1,69 @@
|
|||
foo=Foo pl
|
||||
|
||||
# e - existing
|
||||
# v - ValueError
|
||||
# i - IndexError
|
||||
# m - missing
|
||||
|
||||
e=E pl
|
||||
v=V {{ boo }} pl
|
||||
i={[plural(boo)]}
|
||||
i[key]=i pl
|
||||
|
||||
|
||||
ve=VE {{ boo }} pl
|
||||
vv=VV {{ boo }} pl
|
||||
vi=VI {{ boo }} pl
|
||||
vm=VM {{ boo }} pl
|
||||
|
||||
ie={[plural(boo)]}
|
||||
ie[key]=IE pl
|
||||
iv={[plural(boo)]}
|
||||
iv[key]=IV pl
|
||||
ii={[plural(boo)]}
|
||||
ii[key]=II pl
|
||||
im={[plural(boo)]}
|
||||
im[key]=IM pl
|
||||
|
||||
|
||||
vve=VVE {{ boo }} pl
|
||||
vvv=VVV {{ boo }} pl
|
||||
vvi=VVI {{ boo }} pl
|
||||
vvm=VVM {{ boo }} pl
|
||||
|
||||
vie=VIE {{ boo }} pl
|
||||
viv=VIV {{ boo }} pl
|
||||
vii=VII {{ boo }} pl
|
||||
vim=VIM {{ boo }} pl
|
||||
|
||||
vme=VME {{ boo }} pl
|
||||
vmv=VMV {{ boo }} pl
|
||||
vmi=VMI {{ boo }} pl
|
||||
vmm=VMM {{ boo }} pl
|
||||
|
||||
ive={[plural(boo)]}
|
||||
ive[key]=IVE pl
|
||||
ivv={[plural(boo)]}
|
||||
ivv[key]=IVV pl
|
||||
ivi={[plural(boo)]}
|
||||
ivi[key]=IVI pl
|
||||
ivm={[plural(boo)]}
|
||||
ivm[key]=IVM pl
|
||||
|
||||
iie={[plural(boo)]}
|
||||
iie[key]=IIE pl
|
||||
iiv={[plural(boo)]}
|
||||
iiv[key]=IIV pl
|
||||
iii={[plural(boo)]}
|
||||
iii[key]=III pl
|
||||
iim={[plural(boo)]}
|
||||
iim[key]=IIM pl
|
||||
|
||||
ime={[plural(boo)]}
|
||||
ime[key]=IME pl
|
||||
imv={[plural(boo)]}
|
||||
imv[key]=IMV pl
|
||||
imi={[plural(boo)]}
|
||||
imi[key]=IMI pl
|
||||
imm={[plural(boo)]}
|
||||
imm[key]=IMM pl
|
||||
116
gaia/apps/sharedtest/test/unit/l10n/lib/context/format_test.js
Executable file
116
gaia/apps/sharedtest/test/unit/l10n/lib/context/format_test.js
Executable file
|
|
@ -0,0 +1,116 @@
|
|||
/* global assert:true, it, describe, beforeEach */
|
||||
/* global navigator, __dirname */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var Context = L10n.Context;
|
||||
var path =
|
||||
'app://sharedtest.gaiamobile.org/test/unit/l10n/lib/context';
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Context = require('../../../src/lib/context').Context;
|
||||
var path = __dirname;
|
||||
}
|
||||
|
||||
function assertPromise(promise, expected, done) {
|
||||
promise.then(function(value) {
|
||||
assert.strictEqual(value, expected);
|
||||
}).then(done, done);
|
||||
}
|
||||
|
||||
describe('One fallback locale', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/{locale}.properties');
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US', ['pl']);
|
||||
ctx.requestLocales('pl');
|
||||
});
|
||||
|
||||
describe('Translation in the first locale exists and is OK', function() {
|
||||
it('[e]', function(done) {
|
||||
assertPromise(ctx.formatValue('e'), 'E pl', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in first locale', function() {
|
||||
describe('Entity exists in second locale:', function() {
|
||||
it('[ve]', function(done) {
|
||||
assertPromise(ctx.formatValue('ve'), 'VE {{ boo }} pl', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in second locale:', function() {
|
||||
it('[vv]', function(done) {
|
||||
assertPromise(ctx.formatValue('vv'), 'VV {{ boo }} pl', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in second locale:', function() {
|
||||
it('[vi]', function(done) {
|
||||
assertPromise(ctx.formatValue('vi'), 'VI {{ boo }} pl', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity missing in second locale:', function() {
|
||||
it('[vm]', function(done) {
|
||||
assertPromise(ctx.formatValue('vm'), 'VM {{ boo }} pl', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in first locale', function() {
|
||||
describe('Entity exists in second locale', function() {
|
||||
it('[ie]', function(done) {
|
||||
assertPromise(ctx.formatValue('ie'), 'ie', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in second locale', function() {
|
||||
it('[iv]', function(done) {
|
||||
assertPromise(ctx.formatValue('iv'), 'iv', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in second locale', function() {
|
||||
it('[ii]', function(done) {
|
||||
assertPromise(ctx.formatValue('ii'), 'ii', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity missing in second locale:', function() {
|
||||
it('[im]', function(done) {
|
||||
assertPromise(ctx.formatValue('im'), 'im', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity not found in first locale', function() {
|
||||
describe('Entity exists in second locale:', function() {
|
||||
it('[me]', function(done) {
|
||||
assertPromise(ctx.formatValue('me'), 'ME en-US', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ValueError in second locale:', function() {
|
||||
it('[mv]', function(done) {
|
||||
assertPromise(ctx.formatValue('mv'), 'MV {{ boo }} en-US', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('IndexError in second locale:', function() {
|
||||
it('[mi]', function(done) {
|
||||
assertPromise(ctx.formatValue('mi'), 'mi', done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entity missing in second locale:', function() {
|
||||
it('[mm]', function(done) {
|
||||
assertPromise(ctx.formatValue('mm'), 'mm', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
59
gaia/apps/sharedtest/test/unit/l10n/lib/context/langnego_test.js
Executable file
59
gaia/apps/sharedtest/test/unit/l10n/lib/context/langnego_test.js
Executable file
|
|
@ -0,0 +1,59 @@
|
|||
/* global assert:true, it, describe, beforeEach */
|
||||
/* global navigator */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var Context = L10n.Context;
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Context = require('../../../src/lib/context').Context;
|
||||
}
|
||||
|
||||
describe('Language negotiation without arguments', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US');
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('used the en-US locale', function() {
|
||||
assert.strictEqual(ctx.supportedLocales.length, 1);
|
||||
assert.strictEqual(ctx.supportedLocales[0], 'en-US');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Language negotiation with arguments', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US', ['pl']);
|
||||
ctx.requestLocales('pl');
|
||||
});
|
||||
|
||||
it('sets the correct fallback chain', function() {
|
||||
assert.strictEqual(ctx.supportedLocales.length, 2);
|
||||
assert.strictEqual(ctx.supportedLocales[0], 'pl');
|
||||
assert.strictEqual(ctx.supportedLocales[1], 'en-US');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Language negotiation with arguments and unsupported', function() {
|
||||
var ctx;
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US', ['pl']);
|
||||
ctx.requestLocales('fr', 'pl');
|
||||
});
|
||||
it('sets the correct fallback chain', function() {
|
||||
assert.strictEqual(ctx.supportedLocales.length, 2);
|
||||
assert.strictEqual(ctx.supportedLocales[0], 'pl');
|
||||
assert.strictEqual(ctx.supportedLocales[1], 'en-US');
|
||||
});
|
||||
});
|
||||
145
gaia/apps/sharedtest/test/unit/l10n/lib/context/loading_test.js
Executable file
145
gaia/apps/sharedtest/test/unit/l10n/lib/context/loading_test.js
Executable file
|
|
@ -0,0 +1,145 @@
|
|||
/* global assert:true, it, describe, beforeEach */
|
||||
/* global navigator, __dirname */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var Context = L10n.Context;
|
||||
var path =
|
||||
'app://sharedtest.gaiamobile.org/test/unit/l10n/lib/context';
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Context = require('../../../src/lib/context').Context;
|
||||
var path = __dirname;
|
||||
}
|
||||
|
||||
describe('A non-loading context', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function() {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/{locale}.properties');
|
||||
});
|
||||
|
||||
it('should throw on get', function() {
|
||||
assert.throws(function(){
|
||||
ctx.get('dummy');
|
||||
}, /Context not ready/);
|
||||
});
|
||||
|
||||
it('should throw on getEntity', function() {
|
||||
assert.throws(function(){
|
||||
ctx.getEntity('dummy');
|
||||
}, /Context not ready/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('A loading, non-ready context', function() {
|
||||
var ctx;
|
||||
beforeEach(function() {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/{locale}.properties');
|
||||
ctx.registerLocales('en-US');
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should throw on requestLocales', function() {
|
||||
assert.throws(function(){
|
||||
ctx.requestLocales('en-US');
|
||||
}, /Context not ready/);
|
||||
});
|
||||
|
||||
it('should throw on get', function() {
|
||||
assert.throws(function(){
|
||||
ctx.get('dummy');
|
||||
}, /Context not ready/);
|
||||
});
|
||||
|
||||
it('should throw on getEntity', function() {
|
||||
assert.throws(function(){
|
||||
ctx.getEntity('dummy');
|
||||
}, /Context not ready/);
|
||||
});
|
||||
|
||||
it('should throw on requestLocales', function() {
|
||||
assert.throws(function(){
|
||||
ctx.requestLocales('en-US');
|
||||
}, /Context not ready/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('A loading, ready context', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/{locale}.properties');
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US');
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should not throw on get of a known entity', function() {
|
||||
assert.doesNotThrow(function(){
|
||||
ctx.get('foo');
|
||||
});
|
||||
assert.strictEqual(ctx.get('foo'), 'Foo en-US');
|
||||
});
|
||||
|
||||
it('should not throw on get of an unknown entity', function() {
|
||||
assert.doesNotThrow(function(){
|
||||
ctx.get('missing');
|
||||
});
|
||||
assert.strictEqual(ctx.get('missing'), '');
|
||||
});
|
||||
|
||||
it('should not throw on getEntity of a known entity', function() {
|
||||
assert.doesNotThrow(function(){
|
||||
ctx.getEntity('foo');
|
||||
});
|
||||
assert.strictEqual(ctx.getEntity('foo').value, 'Foo en-US');
|
||||
});
|
||||
|
||||
it('should not throw on getEntity of an unknown entity', function() {
|
||||
assert.doesNotThrow(function(){
|
||||
ctx.getEntity('missing');
|
||||
});
|
||||
assert.strictEqual(ctx.getEntity('missing'), '');
|
||||
});
|
||||
|
||||
it('should not throw on requestLocales', function(done) {
|
||||
ctx.once(function() {
|
||||
assert.strictEqual(ctx.isReady, true);
|
||||
done();
|
||||
});
|
||||
assert.doesNotThrow(function(){
|
||||
ctx.requestLocales('pl', 'en-US');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('A loading, ready context', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/{locale}.properties');
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US');
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should return translations for the built fallback chain ', function() {
|
||||
// Bug 942183 - Error when localizeNode is done quickly after
|
||||
// requestLocales https://bugzil.la/942183
|
||||
// Changing locales triggers the build process for the 'pl' locale.
|
||||
// However, synchronous methods called right after the change should still
|
||||
// return translations for the previous fallback chain
|
||||
ctx.requestLocales('pl');
|
||||
assert.strictEqual(ctx.get('foo'), 'Foo en-US');
|
||||
});
|
||||
|
||||
});
|
||||
49
gaia/apps/sharedtest/test/unit/l10n/lib/context/resources_test.js
Executable file
49
gaia/apps/sharedtest/test/unit/l10n/lib/context/resources_test.js
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
/* global assert:true, it, describe, beforeEach */
|
||||
/* global navigator, __dirname */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var Context = L10n.Context;
|
||||
var path = 'app://sharedtest.gaiamobile.org/test/unit/l10n/context';
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Context = require('../../../src/lib/context').Context;
|
||||
var path = __dirname;
|
||||
}
|
||||
|
||||
describe('Missing resources', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/en-US.properties');
|
||||
ctx.resLinks.push(path + '/fixtures/missing.properties');
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US');
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should get ready', function() {
|
||||
assert.strictEqual(ctx.isReady, true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('No valid resources', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function(done) {
|
||||
ctx = new Context();
|
||||
ctx.resLinks.push(path + '/fixtures/missing.properties');
|
||||
ctx.resLinks.push(path + '/fixtures/another.properties');
|
||||
ctx.once(done);
|
||||
ctx.registerLocales('en-US');
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should get ready', function() {
|
||||
assert.strictEqual(ctx.isReady, true);
|
||||
});
|
||||
|
||||
});
|
||||
66
gaia/apps/sharedtest/test/unit/l10n/lib/context/retranslation_test.js
Executable file
66
gaia/apps/sharedtest/test/unit/l10n/lib/context/retranslation_test.js
Executable file
|
|
@ -0,0 +1,66 @@
|
|||
/* global it, describe, beforeEach */
|
||||
/* global navigator */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var Context = L10n.Context;
|
||||
} else {
|
||||
var Context = require('../../../src/lib/context').Context;
|
||||
}
|
||||
|
||||
describe('ctx.ready', function() {
|
||||
var ctx;
|
||||
|
||||
beforeEach(function() {
|
||||
ctx = new Context();
|
||||
ctx.registerLocales('en-US', ['pl']);
|
||||
});
|
||||
|
||||
it('should fire asynchronously when context is ready', function(done) {
|
||||
ctx.ready(function() {
|
||||
done();
|
||||
});
|
||||
ctx.requestLocales('pl');
|
||||
});
|
||||
|
||||
it('should fire asynchronously when language changes', function(done) {
|
||||
var now = false;
|
||||
ctx.ready(function() {
|
||||
if (now) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
ctx.once(function() {
|
||||
now = true;
|
||||
ctx.requestLocales('pl');
|
||||
});
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should fire synchronously when context is ready', function(done) {
|
||||
ctx.once(function() {
|
||||
ctx.ready(function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
it('should fire synchronously when language changes', function(done) {
|
||||
var now = false;
|
||||
ctx.once(function() {
|
||||
ctx.ready(function() {
|
||||
if (now) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
setTimeout(function() {
|
||||
now = true;
|
||||
ctx.requestLocales('pl');
|
||||
});
|
||||
});
|
||||
ctx.requestLocales('en-US');
|
||||
});
|
||||
|
||||
});
|
||||
91
gaia/apps/sharedtest/test/unit/l10n/lib/parser/properties/dos_test.js
Executable file
91
gaia/apps/sharedtest/test/unit/l10n/lib/parser/properties/dos_test.js
Executable file
|
|
@ -0,0 +1,91 @@
|
|||
/* global assert:true, it, beforeEach, describe */
|
||||
/* global navigator */
|
||||
/* jshint -W101 */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var L10n = {
|
||||
PropertiesParser: require('../../../../src/lib/format/properties/parser')
|
||||
};
|
||||
}
|
||||
|
||||
describe('Quadratic Blowup', function(){
|
||||
var source;
|
||||
|
||||
beforeEach(function() {
|
||||
source = [
|
||||
'# Project Gutenberg\'s Alice\'s Adventures in Wonderland,',
|
||||
'# by Lewis Carroll',
|
||||
'#',
|
||||
'# This eBook is for the use of anyone anywhere at no cost and with',
|
||||
'# almost no restrictions whatsoever. You may copy it, give it away',
|
||||
'# or re-use it under the terms of the Project Gutenberg License',
|
||||
'# included with this eBook or online at www.gutenberg.org',
|
||||
|
||||
'alice=\\',
|
||||
|
||||
' CHAPTER I. Down the Rabbit-Hole\\',
|
||||
|
||||
' Alice was beginning to get very tired of sitting by her sister on\\',
|
||||
' the bank, and of having nothing to do: once or twice she had peeped\\',
|
||||
' into the book her sister was reading, but it had no pictures or\\',
|
||||
' conversations in it, \'and what is the use of a book,\' thought\\',
|
||||
' Alice \'without pictures or conversation?\'\\',
|
||||
|
||||
' So she was considering in her own mind (as well as she could, for\\',
|
||||
' the hot day made her feel very sleepy and stupid), whether the\\',
|
||||
' pleasure of making a daisy-chain would be worth the trouble of\\',
|
||||
' getting up and picking the daisies, when suddenly a White Rabbit\\',
|
||||
' with pink eyes ran close by her.\\',
|
||||
|
||||
' There was nothing so VERY remarkable in that; nor did Alice think\\',
|
||||
' it so VERY much out of the way to hear the Rabbit say to itself,\\',
|
||||
' \'Oh dear! Oh dear! I shall be late!\' (when she thought it over\\',
|
||||
' afterwards, it occurred to her that she ought to have wondered at\\',
|
||||
' this, but at the time it all seemed quite natural); but when the\\',
|
||||
' Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-POCKET, and\\',
|
||||
' looked at it, and then hurried on, Alice started to her feet, for\\',
|
||||
' it flashed across her mind that she had never before seen a rabbit\\',
|
||||
' with either a waistcoat-pocket, or a watch to take out of it, and\\',
|
||||
' burning with curiosity, she ran across the field after it, and\\',
|
||||
' fortunately was just in time to see it pop down a large rabbit-hole\\',
|
||||
' under the hedge.\\',
|
||||
|
||||
' In another moment down went Alice after it, never once considering\\',
|
||||
' how in the world she was to get out again.\\',
|
||||
|
||||
' The rabbit-hole went straight on like a tunnel for some way, and\\',
|
||||
' then dipped suddenly down, so suddenly that Alice had not a moment\\',
|
||||
' to think about stopping herself before she found herself falling\\',
|
||||
' down a very deep well.',
|
||||
|
||||
'malice=\\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} \\',
|
||||
' {{alice}} {{alice}} {{alice}} {{alice}} {{alice}} {{alice}}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('throws', function() {
|
||||
assert.throws(function() {
|
||||
L10n.PropertiesParser.parse(null, source);
|
||||
}, /too many placeables/i);
|
||||
});
|
||||
});
|
||||
134
gaia/apps/sharedtest/test/unit/l10n/lib/parser/properties/parser_test.js
Executable file
134
gaia/apps/sharedtest/test/unit/l10n/lib/parser/properties/parser_test.js
Executable file
|
|
@ -0,0 +1,134 @@
|
|||
/* global it, assert:true, describe */
|
||||
/* global navigator */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var L10n = {
|
||||
PropertiesParser: require('../../../../src/lib/format/properties/parser')
|
||||
};
|
||||
}
|
||||
|
||||
describe('L10n Parser', function() {
|
||||
|
||||
it('string value', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null, 'id = string');
|
||||
assert.strictEqual(ast[0].$v, 'string');
|
||||
});
|
||||
|
||||
it('empty value', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null, 'id =');
|
||||
assert.equal(ast[0].$v, '');
|
||||
});
|
||||
|
||||
it('empty value with white spaces', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null, 'id = ');
|
||||
assert.equal(ast[0].$v, '');
|
||||
});
|
||||
|
||||
it('basic errors', function() {
|
||||
var strings = [
|
||||
'',
|
||||
'id',
|
||||
'id ',
|
||||
'+id',
|
||||
'=id',
|
||||
];
|
||||
|
||||
for (var i in strings) {
|
||||
if (strings.hasOwnProperty(i)) {
|
||||
var ast = L10n.PropertiesParser.parse(null, strings[i]);
|
||||
assert.equal(Object.keys(ast).length, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('basic attributes', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null, 'id.attr1 = foo');
|
||||
assert.equal(ast[0].attr1, 'foo');
|
||||
});
|
||||
|
||||
it('empty attribute', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null, 'id.attr1 =');
|
||||
assert.equal(ast[0].attr1, '');
|
||||
});
|
||||
|
||||
it('empty attribute with white spaces', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null, 'id.attr1 = ');
|
||||
assert.equal(ast[0].attr1, '');
|
||||
});
|
||||
|
||||
it('attribute errors', function() {
|
||||
var strings = [
|
||||
['key.foo.bar = foo', /Nested attributes are not supported./],
|
||||
['key.$attr = foo', /Attribute can't start/],
|
||||
];
|
||||
|
||||
for (var i in strings) {
|
||||
if (strings.hasOwnProperty(i)) {
|
||||
|
||||
/* jshint -W083 */
|
||||
assert.throws(function() {
|
||||
L10n.PropertiesParser.parse(null, strings[i][0]);
|
||||
}, strings[i][1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('plural macro', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null,
|
||||
'id = {[ plural(m) ]} \nid[one] = foo');
|
||||
assert.ok(ast[0].$v instanceof Object);
|
||||
assert.equal(ast[0].$v.one, 'foo');
|
||||
assert.equal(ast[0].$x.length, 2);
|
||||
assert.equal(ast[0].$x[0].t, 'idOrVar');
|
||||
assert.equal(ast[0].$x[0].v, 'plural');
|
||||
assert.equal(ast[0].$x[1], 'm');
|
||||
});
|
||||
|
||||
it('plural macro errors', function() {
|
||||
var strings = [
|
||||
'id = {[ plural(m) ] \nid[one] = foo',
|
||||
'id = {[ plural(m) \nid[one] = foo',
|
||||
'id = { plural(m) ]} \nid[one] = foo',
|
||||
'id = plural(m) ]} \nid[one] = foo',
|
||||
'id = {[ plural(m ]} \nid[one] = foo',
|
||||
'id = {[ pluralm) ]} \nid[one] = foo',
|
||||
|
||||
];
|
||||
var errorsThrown = 0;
|
||||
|
||||
for (var i in strings) {
|
||||
if (strings.hasOwnProperty(i)) {
|
||||
try {
|
||||
L10n.PropertiesParser.parse(null, strings[i]);
|
||||
} catch (e) {
|
||||
errorsThrown += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.equal(errorsThrown, strings.length);
|
||||
});
|
||||
|
||||
it('comment', function() {
|
||||
var ast = L10n.PropertiesParser.parse(null, '#test');
|
||||
assert.equal(Object.keys(ast).length, 0);
|
||||
});
|
||||
|
||||
it('comment errors', function() {
|
||||
var strings = [
|
||||
' # foo',
|
||||
' ## foo',
|
||||
'f# foo',
|
||||
];
|
||||
for (var i in strings) {
|
||||
if (strings.hasOwnProperty(i)) {
|
||||
var ast = L10n.PropertiesParser.parse(null, strings[i]);
|
||||
assert.equal(Object.keys(ast).length, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
198
gaia/apps/sharedtest/test/unit/l10n/lib/pseudo_test.js
Executable file
198
gaia/apps/sharedtest/test/unit/l10n/lib/pseudo_test.js
Executable file
|
|
@ -0,0 +1,198 @@
|
|||
/* global it, assert:true, describe, before, beforeEach */
|
||||
/* global navigator */
|
||||
'use strict';
|
||||
|
||||
var assert;
|
||||
var PropertiesParser;
|
||||
|
||||
describe('pseudo strategy', function() {
|
||||
var PSEUDO, walkContent, strategy, source, ast, walked;
|
||||
|
||||
before(function(done) {
|
||||
if (typeof navigator !== 'undefined') {
|
||||
require('/shared/js/l10n.js', function() {
|
||||
PSEUDO = navigator.mozL10n.qps;
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
PropertiesParser = L10n.PropertiesParser;
|
||||
walkContent = L10n.walkContent;
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
assert = require('assert');
|
||||
PSEUDO = require('../../src/lib/pseudo').PSEUDO;
|
||||
walkContent = require('../../src/lib/util').walkContent;
|
||||
PropertiesParser =
|
||||
require('../../src/lib/format/properties/parser');
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(function() {
|
||||
ast = PropertiesParser.parse(null, source);
|
||||
walked = pseudolocalize(ast, strategy);
|
||||
});
|
||||
|
||||
function pseudolocalize(arr, strategy) {
|
||||
var obj = {};
|
||||
arr.forEach(function(val) {
|
||||
obj[val.$i] = walkContent(val, strategy);
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
var foo = {t: 'idOrVar', v: 'foo'};
|
||||
var bar = {t: 'idOrVar', v: 'bar'};
|
||||
|
||||
describe('accented English', function(){
|
||||
|
||||
before(function() {
|
||||
strategy = PSEUDO['fr-x-psaccent'].translate;
|
||||
source = [
|
||||
'foo=Foo',
|
||||
|
||||
'bar={[ plural(n) ]}',
|
||||
'bar[one]=One',
|
||||
'bar[two]=Two',
|
||||
'bar[few]=Few',
|
||||
'bar[many]=Many',
|
||||
'bar[other]=Other',
|
||||
|
||||
'baz.attr=An attribute',
|
||||
'baz.attrComplex=An attribute referencing {{ foo }}',
|
||||
|
||||
'templateVar={name} wrote',
|
||||
'dateFormat=%A, %b %Eb',
|
||||
'twoPlaceables1={{ foo }} {{ bar }}',
|
||||
'twoPlaceables2=Foo {{ foo }} and bar {{ bar }}',
|
||||
'parens1=({{ foo }}) {{ bar }}',
|
||||
'parens2=Foo ({{foo}}) [and/or {{bar}}]',
|
||||
'parens3=Foo (and) bar',
|
||||
'unicode=Foo \u0066\u006f\u006f\u0020',
|
||||
'nonascii=Naïve coöperation résumé dæmon phœnix',
|
||||
'html1=visit <a>url</a>',
|
||||
'html2=type <input placeholder="your name"/>',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('walks the value', function(){
|
||||
assert.strictEqual(walked.foo.$v, 'Ƒǿǿǿǿ');
|
||||
|
||||
assert.strictEqual(walked.bar.$v.one, 'Ǿǿƞḗḗ');
|
||||
assert.strictEqual(walked.bar.$v.two, 'Ŧẇǿǿ');
|
||||
assert.strictEqual(walked.bar.$v.few, 'Ƒḗḗẇ');
|
||||
assert.strictEqual(walked.bar.$v.many, 'Ḿȧȧƞẏ');
|
||||
assert.strictEqual(walked.bar.$v.other, 'Ǿǿŧħḗḗř');
|
||||
|
||||
assert.strictEqual(walked.baz.attr, 'Ȧȧƞ ȧȧŧŧřīīƀŭŭŧḗḗ');
|
||||
assert.deepEqual(
|
||||
walked.baz.attrComplex, ['Ȧȧƞ ȧȧŧŧřīīƀŭŭŧḗḗ řḗḗƒḗḗřḗḗƞƈīīƞɠ ', foo]);
|
||||
|
||||
assert.strictEqual(walked.templateVar.$v, '{name} ẇřǿǿŧḗḗ');
|
||||
assert.strictEqual(walked.dateFormat.$v, '%A, %b %Eb');
|
||||
assert.deepEqual(walked.twoPlaceables1.$v, [foo, ' ', bar]);
|
||||
assert.deepEqual(
|
||||
walked.twoPlaceables2.$v, ['Ƒǿǿǿǿ ', foo, ' ȧȧƞḓ ƀȧȧř ', bar]);
|
||||
assert.deepEqual(
|
||||
walked.parens1.$v, ['(', foo, ') ', bar]);
|
||||
assert.deepEqual(
|
||||
walked.parens2.$v, ['Ƒǿǿǿǿ (', foo, ') [ȧȧƞḓ/ǿǿř ', bar, ']']);
|
||||
assert.strictEqual(walked.parens3.$v, 'Ƒǿǿǿǿ (ȧȧƞḓ) ƀȧȧř');
|
||||
assert.strictEqual(walked.unicode.$v, 'Ƒǿǿǿǿ ƒǿǿǿǿ ');
|
||||
assert.strictEqual(
|
||||
walked.nonascii.$v,
|
||||
'Ƞȧȧïṽḗḗ ƈǿǿöƥḗḗřȧȧŧīīǿǿƞ řéşŭŭḿé ḓæḿǿǿƞ ƥħœƞīīẋ');
|
||||
assert.strictEqual(walked.html1.$v, 'ṽīīşīīŧ <a>ŭŭřŀ</a>');
|
||||
assert.strictEqual(
|
||||
walked.html2.$v, 'ŧẏƥḗḗ <input placeholder="your name"/>');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('bidi English', function(){
|
||||
/* jshint -W100 */
|
||||
|
||||
before(function() {
|
||||
strategy = PSEUDO['ar-x-psbidi'].translate;
|
||||
source = [
|
||||
'foo=Foo',
|
||||
|
||||
'bar={[ plural(n) ]}',
|
||||
'bar[one]=One',
|
||||
'bar[two]=Two',
|
||||
'bar[few]=Few',
|
||||
'bar[many]=Many',
|
||||
'bar[other]=Other',
|
||||
|
||||
'baz.attr=An attribute',
|
||||
'baz.attrComplex=An attribute referencing {{ foo }}',
|
||||
|
||||
'templateVar={name} wrote',
|
||||
'dateFormat=%A, %b %Eb',
|
||||
'twoPlaceables1={{ foo }} {{ bar }}',
|
||||
'twoPlaceables2=Foo {{ foo }} and bar {{ bar }}',
|
||||
'parens1=({{ foo }}) {{ bar }}',
|
||||
'parens2=Foo ({{foo}}) [and/or {{bar}}]',
|
||||
'parens3=Foo (and) bar',
|
||||
'unicode=Foo \u0066\u006f\u006f\u0020',
|
||||
'nonascii=Naïve coöperation résumé dæmon phœnix',
|
||||
'html1=visit <a>url</a>',
|
||||
'html2=type <input placeholder="your name"/>',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('walks the value', function(){
|
||||
assert.strictEqual(walked.foo.$v, 'ɟoo');
|
||||
|
||||
assert.strictEqual(walked.bar.$v.one, 'Ouǝ');
|
||||
assert.strictEqual(walked.bar.$v.two, '⊥ʍo');
|
||||
assert.strictEqual(walked.bar.$v.few, 'ɟǝʍ');
|
||||
assert.strictEqual(walked.bar.$v.many, 'Wɐuʎ');
|
||||
assert.strictEqual(walked.bar.$v.other, 'Oʇɥǝɹ');
|
||||
|
||||
assert.strictEqual(
|
||||
walked.baz.attr, '∀u ɐʇʇɹıqnʇǝ');
|
||||
assert.deepEqual(
|
||||
walked.baz.attrComplex,
|
||||
['∀u ɐʇʇɹıqnʇǝ ɹǝɟǝɹǝuɔıuƃ ',
|
||||
foo]);
|
||||
|
||||
assert.strictEqual(walked.templateVar.$v, '{name} ʍɹoʇǝ');
|
||||
assert.strictEqual(walked.dateFormat.$v, '%A, %b %Eb');
|
||||
assert.deepEqual(walked.twoPlaceables1.$v, [foo, ' ', bar]);
|
||||
assert.deepEqual(
|
||||
walked.twoPlaceables2.$v,
|
||||
['ɟoo ', foo, ' ɐup qɐɹ ',
|
||||
bar]);
|
||||
assert.deepEqual(
|
||||
walked.parens1.$v, ['(', foo, ') ', bar]);
|
||||
assert.deepEqual(
|
||||
walked.parens2.$v,
|
||||
['ɟoo (', foo, ') [ɐup/oɹ ',
|
||||
bar, ']']);
|
||||
assert.strictEqual(
|
||||
walked.parens3.$v,
|
||||
'ɟoo (ɐup) qɐɹ');
|
||||
assert.strictEqual(
|
||||
walked.unicode.$v,
|
||||
'ɟoo ɟoo ');
|
||||
assert.strictEqual(
|
||||
walked.html1.$v, 'ʌısıʇ <a>nɹʅ</a>');
|
||||
assert.strictEqual(
|
||||
walked.html2.$v,
|
||||
'ʇʎdǝ <input placeholder="your name"/>');
|
||||
});
|
||||
|
||||
// XXX this requires Unicode support for JavaSript RegExp objects
|
||||
// https://bugzil.la/258974
|
||||
it.skip('walks the value', function(){
|
||||
var walked = walkContent(ast, strategy);
|
||||
assert.strictEqual(
|
||||
walked.nonascii,
|
||||
'Nɐïʌǝ ɔoödǝɹɐʇıou ' +
|
||||
'ɹésnɯé pæɯou ' +
|
||||
'dɥœuıx');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
127
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/attributes_test.js
Executable file
127
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/attributes_test.js
Executable file
|
|
@ -0,0 +1,127 @@
|
|||
/* global assert:true, it, before, beforeEach, describe, requireApp */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
requireApp('sharedtest/test/unit/l10n/lib/resolver/header.js');
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Resolver = require('./header').Resolver;
|
||||
var createEntries = require('./header').createEntries;
|
||||
}
|
||||
|
||||
describe('Attributes', function(){
|
||||
var source, env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
});
|
||||
|
||||
describe('with string values', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo=Foo',
|
||||
'foo.attr=An attribute',
|
||||
'foo.attrComplex=An attribute referencing {{ bar }}',
|
||||
'bar=Bar'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the value', function(){
|
||||
var formatted = Resolver.format(null, env.foo.attrs.attr);
|
||||
assert.strictEqual(formatted[1], 'An attribute');
|
||||
});
|
||||
|
||||
it('returns the value with a placeable', function(){
|
||||
var formatted = Resolver.format(null, env.foo.attrs.attrComplex);
|
||||
assert.strictEqual(formatted[1], 'An attribute referencing Bar');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with hash values', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'update=Update',
|
||||
'update.title={[ plural(n) ]}',
|
||||
'update.title[one]=One update available'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the value of the entity', function(){
|
||||
var formatted = Resolver.format(null, env.update);
|
||||
assert.strictEqual(formatted[1], 'Update');
|
||||
});
|
||||
|
||||
it('returns the value of the attribute\'s member', function(){
|
||||
var formatted = Resolver.format({n: 1}, env.update.attrs.title);
|
||||
assert.strictEqual(formatted[1], 'One update available');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('with hash values, on entities with hash values ', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'update={[ plural(n) ]}',
|
||||
'update[one]=One update',
|
||||
'update[other]={{ n }} updates',
|
||||
'update.title={[ plural(k) ]}',
|
||||
'update.title[one]=One update title',
|
||||
'update.title[other]={{ k }} updates title'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the value of the entity', function(){
|
||||
var formatted = Resolver.format({n: 1, k: 2}, env.update);
|
||||
assert.strictEqual(formatted[1], 'One update');
|
||||
});
|
||||
|
||||
it('returns the value of the attribute', function(){
|
||||
var formatted = Resolver.format({n: 1, k: 2}, env.update.attrs.title);
|
||||
assert.strictEqual(formatted[1], '2 updates title');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with relative self-references', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'brandName=Firefox',
|
||||
'brandName.title=Mozilla {{ brandName }}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the value of the entity', function(){
|
||||
var value = Resolver.format(null, env.brandName)[1];
|
||||
assert.strictEqual(value, 'Firefox');
|
||||
});
|
||||
|
||||
it('returns the value of the attribute', function(){
|
||||
var attr = Resolver.format(null, env.brandName.attrs.title)[1];
|
||||
assert.strictEqual(attr, 'Mozilla Firefox');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with cyclic self-references', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'brandName=Firefox',
|
||||
'brandName.title=Mozilla {{ brandName.title }}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string of the attribute', function(){
|
||||
var attr = Resolver.format(null, env.brandName.attrs.title)[1];
|
||||
assert.strictEqual(attr, 'Mozilla {{ brandName.title }}');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
345
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/ctxdata_test.js
Executable file
345
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/ctxdata_test.js
Executable file
|
|
@ -0,0 +1,345 @@
|
|||
/* global assert:true, it, before, beforeEach, describe, requireApp */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
requireApp('sharedtest/test/unit/l10n/lib/resolver/header.js');
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Resolver = require('./header').Resolver;
|
||||
var createEntries = require('./header').createEntries;
|
||||
}
|
||||
|
||||
describe('Context data', function(){
|
||||
var source, ctxdata, env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
});
|
||||
|
||||
describe('in entities', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
unreadNotifications: 3,
|
||||
foo: 'Foo'
|
||||
};
|
||||
source = [
|
||||
'unread=Unread notifications: {{ unreadNotifications }}',
|
||||
'unreadPlural={[ plural(unreadNotifications) ]}',
|
||||
'unreadPlural[one]=One unread notification',
|
||||
'unreadPlural[other]={{ unreadNotifications}} unread notifications',
|
||||
'foo=Bar',
|
||||
'useFoo={{ foo }}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('can be referenced from strings', function() {
|
||||
var value = Resolver.format(ctxdata, env.unread)[1];
|
||||
assert.strictEqual(value, 'Unread notifications: 3');
|
||||
});
|
||||
|
||||
it('can be passed as argument to a macro', function() {
|
||||
var value = Resolver.format(ctxdata, env.unreadPlural)[1];
|
||||
assert.strictEqual(value, '3 unread notifications');
|
||||
});
|
||||
|
||||
it('takes priority over entities of the same name', function() {
|
||||
var value = Resolver.format(ctxdata, env.useFoo)[1];
|
||||
assert.strictEqual(value, 'Foo');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and simple errors', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
nested: {
|
||||
}
|
||||
};
|
||||
source = [
|
||||
'missingReference={{ missing }}',
|
||||
'nestedReference={{ nested }}',
|
||||
'watchReference={{ watch }}',
|
||||
'hasOwnPropertyReference={{ hasOwnProperty }}',
|
||||
'isPrototypeOfReference={{ isPrototypeOf }}',
|
||||
'toStringReference={{ toString }}',
|
||||
'protoReference={{ __proto__ }}',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string when a missing property of ctxdata is ' +
|
||||
'referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.missingReference)[1];
|
||||
assert.strictEqual(value, '{{ missing }}');
|
||||
});
|
||||
|
||||
it('returns the raw string when an object is referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.nestedReference)[1];
|
||||
assert.strictEqual(value, '{{ nested }}');
|
||||
});
|
||||
|
||||
it('returns the raw string when watch is referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.watchReference)[1];
|
||||
assert.strictEqual(value, '{{ watch }}');
|
||||
});
|
||||
|
||||
it('returns the raw string when hasOwnProperty is referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.hasOwnPropertyReference)[1];
|
||||
assert.strictEqual(value, '{{ hasOwnProperty }}');
|
||||
});
|
||||
|
||||
it('returns the raw string when isPrototypeOf is referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.isPrototypeOfReference)[1];
|
||||
assert.strictEqual(value, '{{ isPrototypeOf }}');
|
||||
});
|
||||
|
||||
it('returns the raw string when toString is referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.toStringReference)[1];
|
||||
assert.strictEqual(value, '{{ toString }}');
|
||||
});
|
||||
|
||||
it('returns the raw string when __proto__ is referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.protoReference)[1];
|
||||
assert.strictEqual(value, '{{ __proto__ }}');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and strings', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
str: 'string',
|
||||
num: '1'
|
||||
};
|
||||
source = [
|
||||
'stringProp={{ str }}',
|
||||
'stringIndex={[ plural(str) ]}',
|
||||
'stringIndex[one]=One',
|
||||
'stringNumProp={{ num }}',
|
||||
'stringNumIndex={[ plural(num) ]}',
|
||||
'stringNumIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns a string value', function(){
|
||||
assert.strictEqual(
|
||||
Resolver.format(ctxdata, env.stringProp)[1], 'string');
|
||||
});
|
||||
|
||||
it('throws when used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.stringIndex);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('digit returns a string value', function(){
|
||||
assert.strictEqual(
|
||||
Resolver.format(ctxdata, env.stringNumProp)[1], '1');
|
||||
});
|
||||
|
||||
it('digit throws when used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.stringNumIndex);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and numbers', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
num: 1,
|
||||
nan: NaN
|
||||
};
|
||||
source = [
|
||||
'numProp={{ num }}',
|
||||
'numIndex={[ plural(num) ]}',
|
||||
'numIndex[one]=One',
|
||||
'nanProp={{ nan }}',
|
||||
'nanIndex={[ plural(nan) ]}',
|
||||
'nanIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns a number value', function(){
|
||||
assert.strictEqual(Resolver.format(ctxdata, env.numProp)[1], '1');
|
||||
});
|
||||
|
||||
it('returns a value when used in macro', function(){
|
||||
assert.strictEqual(Resolver.format(ctxdata, env.numIndex)[1], 'One');
|
||||
});
|
||||
|
||||
it('returns the raw string when NaN is referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.nanProp)[1];
|
||||
assert.strictEqual(value, '{{ nan }}');
|
||||
});
|
||||
|
||||
it('is undefined when NaN is used in macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.nanIndex);
|
||||
}, 'Arg must be a string or a number: nan');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and bools', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
bool: true
|
||||
};
|
||||
source = [
|
||||
'boolProp={{ bool }}',
|
||||
'boolIndex={[ plural(bool) ]}',
|
||||
'boolIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string when referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.boolProp)[1];
|
||||
assert.strictEqual(value, '{{ bool }}');
|
||||
});
|
||||
|
||||
it('is undefined when used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.boolIndex);
|
||||
}, 'Arg must be a string or a number: bool');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and undefined', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
undef: undefined
|
||||
};
|
||||
source = [
|
||||
'undefProp={{ undef }}',
|
||||
'undefIndex={[ plural(undef) ]}',
|
||||
'undefIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string when referenced', function(){
|
||||
var value = Resolver.format(ctxdata, env.undefProp)[1];
|
||||
assert.strictEqual(value, '{{ undef }}');
|
||||
});
|
||||
|
||||
it('is undefined when used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.undefIndex);
|
||||
}, 'Arg must be a string or a number: undef');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and null', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
nullable: null
|
||||
};
|
||||
source = [
|
||||
'nullProp={{ nullable }}',
|
||||
'nullIndex={[ plural(nullable) ]}',
|
||||
'nullIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format(ctxdata, env.nullProp)[1];
|
||||
assert.strictEqual(value, '{{ nullable }}');
|
||||
});
|
||||
|
||||
it('is undefined when used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.nullIndex);
|
||||
}, 'Arg must be a string or a number: nullable');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and arrays where first element is number', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
arr: [1, 2]
|
||||
};
|
||||
source = [
|
||||
'arrProp={{ arr }}',
|
||||
'arrIndex={[ plural(arr) ]}',
|
||||
'arrIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format(ctxdata, env.arrProp)[1];
|
||||
assert.strictEqual(value, '{{ arr }}');
|
||||
});
|
||||
|
||||
it('is undefined when used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.arrIndex);
|
||||
}, 'Arg must be a string or a number: arr');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and arrays where first element is not a number', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
arr: ['a', 'b']
|
||||
};
|
||||
source = [
|
||||
'arrProp={{ arr }}',
|
||||
'arrIndex={[ plural(arr) ]}',
|
||||
'arrIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format(ctxdata, env.arrProp)[1];
|
||||
assert.strictEqual(value, '{{ arr }}');
|
||||
});
|
||||
|
||||
it('is undefined when used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.arrIndex);
|
||||
}, 'Arg must be a string or a number: arr');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('and objects', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
obj: {
|
||||
key: 'value'
|
||||
}
|
||||
};
|
||||
source = [
|
||||
'objProp={{ obj }}',
|
||||
'objIndex={[ plural(obj) ]}',
|
||||
'objIndex[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format(ctxdata, env.objProp)[1];
|
||||
assert.strictEqual(value, '{{ obj }}');
|
||||
});
|
||||
|
||||
it('throws used in a macro', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.objIndex);
|
||||
}, 'Arg must be a string or a number: obj');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
38
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/dos_test.js
Executable file
38
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/dos_test.js
Executable file
|
|
@ -0,0 +1,38 @@
|
|||
/* global assert:true, it, beforeEach, describe, requireApp */
|
||||
/* jshint -W101 */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
requireApp('sharedtest/test/unit/l10n/lib/resolver/header.js');
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Resolver = require('./header.js').Resolver;
|
||||
var createEntries = require('./header.js').createEntries;
|
||||
}
|
||||
|
||||
// Bug 803931 - Compiler is vulnerable to the billion laughs attack
|
||||
|
||||
describe('Billion Laughs', function(){
|
||||
var entries;
|
||||
|
||||
beforeEach(function() {
|
||||
var source = [
|
||||
'lol0=LOL',
|
||||
'lol1={{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}} {{lol0}}',
|
||||
'lol2={{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}} {{lol1}}',
|
||||
'lol3={{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}} {{lol2}}',
|
||||
// normally, we'd continue with lol4 through lol9 in the same manner,
|
||||
// but this would make the test itself dangerous if the guards in the
|
||||
// compiler fail. Given MAX_PLACEABLE_LENGTH of 2500, lol3 is enough
|
||||
// to test this.
|
||||
'lolz={{ lol3 }}'
|
||||
].join('\n');
|
||||
entries = createEntries(source);
|
||||
});
|
||||
|
||||
it('Resolver.format() throws', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(null, entries.lolz);
|
||||
}, /too many characters in placeable/i);
|
||||
});
|
||||
});
|
||||
101
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/errors_test.js
Executable file
101
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/errors_test.js
Executable file
|
|
@ -0,0 +1,101 @@
|
|||
/* global assert:true, it, before, beforeEach, describe, requireApp */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
requireApp('sharedtest/test/unit/l10n/lib/resolver/header.js');
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Resolver = require('./header.js').Resolver;
|
||||
var createEntries = require('./header.js').createEntries;
|
||||
}
|
||||
|
||||
describe('Compiler errors:', function(){
|
||||
var source, env;
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
});
|
||||
|
||||
describe('A complex string referencing an existing entity', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'file=File',
|
||||
'prompt={[ plural(n) ]}',
|
||||
'prompt[one]=One {{ file }}',
|
||||
'prompt[other]=Files'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('works with the default index', function(){
|
||||
assert.strictEqual(
|
||||
Resolver.format({n: 1}, env.prompt)[1], 'One File');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('A complex string referencing a missing entity', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'prompt={[ plural(n) ]}',
|
||||
'prompt[one]=One {{ file }}',
|
||||
'prompt[other]=Files'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format({n: 1}, env.prompt)[1];
|
||||
assert.strictEqual(value, 'One {{ file }}');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('A ctxdata variable in the index, with "other"', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'file=File',
|
||||
'prompt={[ plural(n) ]}',
|
||||
'prompt[one]=One {{ file }}',
|
||||
'prompt[other]=Files'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('is found', function(){
|
||||
assert.strictEqual(
|
||||
Resolver.format({n: 1}, env.prompt)[1], 'One File');
|
||||
});
|
||||
|
||||
it('throws an IndexError if n is not defined', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(null, env.prompt);
|
||||
}, 'Unknown reference: n');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('A ctxdata variable in the index, without "other"', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'file=File',
|
||||
'prompt={[ plural(n) ]}',
|
||||
'prompt[one]=One {{ file }}',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('is found', function(){
|
||||
assert.strictEqual(
|
||||
Resolver.format({n: 1}, env.prompt)[1], 'One File');
|
||||
});
|
||||
|
||||
it('throws an IndexError if n is not defined', function(){
|
||||
assert.throws(function() {
|
||||
Resolver.format(null, env.prompt);
|
||||
}, 'Unknown reference: n');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
33
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/header.js
Executable file
33
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/header.js
Executable file
|
|
@ -0,0 +1,33 @@
|
|||
/* global navigator, exports */
|
||||
/* exported Resolver */
|
||||
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
var L10n = navigator.mozL10n._getInternalAPI();
|
||||
var Resolver = L10n.Resolver;
|
||||
} else {
|
||||
var L10n = {
|
||||
PropertiesParser:
|
||||
require('../../../src/lib/format/properties/parser'),
|
||||
Resolver: require('../../../src/lib/resolver'),
|
||||
getPluralRule: require('../../../src/lib/plurals').getPluralRule
|
||||
};
|
||||
|
||||
exports.createEntries = createEntries;
|
||||
exports.Resolver = L10n.Resolver;
|
||||
}
|
||||
|
||||
|
||||
function createEntries(source) {
|
||||
/* jshint -W089 */
|
||||
var entries = Object.create(null);
|
||||
var ast = L10n.PropertiesParser.parse(null, source);
|
||||
|
||||
for (var i = 0, len = ast.length; i < len; i++) {
|
||||
entries[ast[i].$i] = L10n.Resolver.createEntry(ast[i], entries);
|
||||
}
|
||||
|
||||
entries.__plural = L10n.getPluralRule('en-US');
|
||||
return entries;
|
||||
}
|
||||
86
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/indexes_test.js
Executable file
86
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/indexes_test.js
Executable file
|
|
@ -0,0 +1,86 @@
|
|||
/* global assert:true, it, before, beforeEach, describe, requireApp */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
requireApp('sharedtest/test/unit/l10n/lib/resolver/header.js');
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Resolver = require('./header.js').Resolver;
|
||||
var createEntries = require('./header.js').createEntries;
|
||||
}
|
||||
|
||||
describe('Index', function(){
|
||||
var source, env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
});
|
||||
|
||||
describe('Different values of index', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo=one',
|
||||
'indexEntity={[ foo ]}',
|
||||
'indexEntity[one]=One entity',
|
||||
'indexUncalledMacro={[ plural ]}',
|
||||
'indexUncalledMacro[one]=One uncalled macro',
|
||||
'indexCalledMacro={[ plural(n) ]}',
|
||||
'indexCalledMacro[one]=One called macro',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('works when the index is a regular entity', function() {
|
||||
var value = Resolver.format({n: 1}, env.indexEntity)[1];
|
||||
assert.strictEqual(value, 'One entity');
|
||||
});
|
||||
it('throws when the index is an uncalled macro', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format({n: 1}, env.indexUncalledMacro);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
it('works when the index is a called macro', function() {
|
||||
var value = Resolver.format({n: 1}, env.indexCalledMacro)[1];
|
||||
assert.strictEqual(value, 'One called macro');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Cyclic reference to the same entity', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(foo) ]}',
|
||||
'foo[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('is undefined', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(null, env.foo);
|
||||
}, 'Cyclic reference detected: foo');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Reference from an attribute to the value of the same ' +
|
||||
'entity', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo=Foo',
|
||||
'foo.attr={[ plural(foo) ]}',
|
||||
'foo.attr[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('value of the attribute is undefined', function() {
|
||||
assert.strictEqual(Resolver.format(null, env.foo)[1], 'Foo');
|
||||
assert.throws(function() {
|
||||
Resolver.format(null, env.foo.attrs.attr);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
357
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/macros_test.js
Executable file
357
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/macros_test.js
Executable file
|
|
@ -0,0 +1,357 @@
|
|||
/* global assert:true, it, before, beforeEach, describe, requireApp */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
requireApp('sharedtest/test/unit/l10n/lib/resolver/header.js');
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Resolver = require('./header.js').Resolver;
|
||||
var createEntries = require('./header.js').createEntries;
|
||||
}
|
||||
|
||||
describe('Macros', function(){
|
||||
var source, ctxdata, env;
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
});
|
||||
|
||||
describe('referencing macros', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
n: 1
|
||||
};
|
||||
source = [
|
||||
'placeMacro={{ plural }}',
|
||||
'placeRealMacro={{ __plural }}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('throws when resolving (not calling) a macro in a complex ' +
|
||||
'string', function() {
|
||||
assert.strictEqual(
|
||||
Resolver.format(ctxdata, env.placeMacro)[1], '{{ plural }}');
|
||||
assert.strictEqual(
|
||||
Resolver.format(ctxdata, env.placeRealMacro)[1], '{{ __plural }}');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('passing arguments', function(){
|
||||
|
||||
before(function() {
|
||||
ctxdata = {
|
||||
n: 1
|
||||
};
|
||||
source = [
|
||||
'foo=Foo',
|
||||
'useFoo={{ foo }}',
|
||||
'bar={[ plural(n) ]}',
|
||||
'bar[one]=One',
|
||||
'bar.attr=Attr',
|
||||
|
||||
'passFoo={[ plural(foo) ]}',
|
||||
'passFoo[one]=One',
|
||||
|
||||
'passUseFoo={[ plural(useFoo) ]}',
|
||||
'passUseFoo[one]=One',
|
||||
|
||||
'passBar={[ plural(bar) ]}',
|
||||
'passBar[one]=One',
|
||||
|
||||
'passPlural={[ plural(plural) ]}',
|
||||
'passPlural[one]=One',
|
||||
|
||||
'passMissing={[ plural(missing) ]}',
|
||||
'passMissing[one]=One',
|
||||
|
||||
'passWatch={[ plural(watch) ]}',
|
||||
'passWatch[one]=One',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('throws if an entity is passed', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.passFoo);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('throws if a complex entity is passed', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.passUseFoo);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('throws if a hash entity is passed', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.passBar);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('throws if a macro is passed', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.passPlural);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('throws if a missing entry is passed', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.passMissing);
|
||||
}, 'Unknown reference: missing');
|
||||
});
|
||||
|
||||
it('throws if a native function is passed', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(ctxdata, env.passWatch);
|
||||
}, 'Unknown reference: watch');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('A simple plural macro', function(){
|
||||
var source, env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
env.__plural = function() {
|
||||
return 'other';
|
||||
};
|
||||
});
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[zero]=Zero',
|
||||
'foo[one]=One',
|
||||
'foo[two]=Two',
|
||||
'foo[few]=Few',
|
||||
'foo[many]=Many',
|
||||
'foo[other]=Other'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns zero for 0', function() {
|
||||
var value = Resolver.format({n: 0}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Zero');
|
||||
});
|
||||
|
||||
it('returns one for 1', function() {
|
||||
var value = Resolver.format({n: 1}, env.foo)[1];
|
||||
assert.strictEqual(value, 'One');
|
||||
});
|
||||
|
||||
it('returns two for 2', function() {
|
||||
var value = Resolver.format({n: 2}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Two');
|
||||
});
|
||||
|
||||
it('returns other for 3', function() {
|
||||
var value = Resolver.format({n: 3}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('throws for no arg', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(null, env.foo);
|
||||
}, 'Unknown reference: n');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('A more complex plural macro', function(){
|
||||
var source, env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
env.__plural = function(n) {
|
||||
// a made-up plural rule:
|
||||
// [0, 1) -> other
|
||||
// [1, Inf) -> many
|
||||
return (n >= 0 && n < 1) ? 'other' : 'many';
|
||||
};
|
||||
});
|
||||
|
||||
describe('an entity with all plural forms defined', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[zero]=Zero',
|
||||
'foo[one]=One',
|
||||
'foo[two]=Two',
|
||||
'foo[few]=Few',
|
||||
'foo[many]=Many',
|
||||
'foo[other]=Other'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns zero for 0', function() {
|
||||
var value = Resolver.format({n: 0}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Zero');
|
||||
});
|
||||
|
||||
it('returns one for 1', function() {
|
||||
var value = Resolver.format({n: 1}, env.foo)[1];
|
||||
assert.strictEqual(value, 'One');
|
||||
});
|
||||
|
||||
it('returns two for 2', function() {
|
||||
var value = Resolver.format({n: 2}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Two');
|
||||
});
|
||||
|
||||
it('returns many for 3', function() {
|
||||
var value = Resolver.format({n: 3}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Many');
|
||||
});
|
||||
|
||||
it('returns many for 5', function() {
|
||||
var value = Resolver.format({n: 5}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Many');
|
||||
});
|
||||
|
||||
it('returns other for 0.5', function() {
|
||||
var value = Resolver.format({n: 0.5}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('throws for no arg', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format(null, env.foo);
|
||||
}, 'Unknown reference: n');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('an entity without the zero, one and two forms', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[many]=Many',
|
||||
'foo[other]=Other'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns other for 0', function() {
|
||||
var value = Resolver.format({n: 0}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('returns many for 1', function() {
|
||||
var value = Resolver.format({n: 1}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Many');
|
||||
});
|
||||
|
||||
it('returns many for 2', function() {
|
||||
var value = Resolver.format({n: 2}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Many');
|
||||
});
|
||||
|
||||
it('returns many for 3', function() {
|
||||
var value = Resolver.format({n: 3}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Many');
|
||||
});
|
||||
|
||||
it('returns many for 5', function() {
|
||||
var value = Resolver.format({n: 5}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Many');
|
||||
});
|
||||
|
||||
it('returns other for 0.5', function() {
|
||||
var value = Resolver.format({n: 0.5}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('an entity without the many form', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[other]=Other'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns other for 0', function() {
|
||||
var value = Resolver.format({n: 0}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('returns other for 1', function() {
|
||||
var value = Resolver.format({n: 1}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('returns other for 2', function() {
|
||||
var value = Resolver.format({n: 2}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('returns other for 3', function() {
|
||||
var value = Resolver.format({n: 3}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('returns other for 5', function() {
|
||||
var value = Resolver.format({n: 5}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
it('returns other for 0.5', function() {
|
||||
var value = Resolver.format({n: 0.5}, env.foo)[1];
|
||||
assert.strictEqual(value, 'Other');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('an entity without the other form, but with the one ' +
|
||||
'form', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[one]=One'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('throws for 0', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format({n: 0}, env.foo);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('returns one for 1', function() {
|
||||
var value = Resolver.format({n: 1}, env.foo)[1];
|
||||
assert.strictEqual(value, 'One');
|
||||
});
|
||||
|
||||
it('throws for 2', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format({n: 2}, env.foo);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('throws for 3', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format({n: 3}, env.foo);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('throws for 5', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format({n: 5}, env.foo);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
it('throws for 0.5', function() {
|
||||
assert.throws(function() {
|
||||
Resolver.format({n: 0.5}, env.foo);
|
||||
}, 'Unresolvable value');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
136
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/primitives_test.js
Executable file
136
gaia/apps/sharedtest/test/unit/l10n/lib/resolver/primitives_test.js
Executable file
|
|
@ -0,0 +1,136 @@
|
|||
/* global assert:true, it, before, beforeEach, describe, requireApp */
|
||||
'use strict';
|
||||
|
||||
if (typeof navigator !== 'undefined') {
|
||||
requireApp('sharedtest/test/unit/l10n/lib/resolver/header.js');
|
||||
} else {
|
||||
var assert = require('assert');
|
||||
var Resolver = require('./header.js').Resolver;
|
||||
var createEntries = require('./header.js').createEntries;
|
||||
}
|
||||
|
||||
describe('Primitives:', function(){
|
||||
var source, env;
|
||||
beforeEach(function() {
|
||||
env = createEntries(source);
|
||||
});
|
||||
|
||||
describe('Simple string value', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo=Foo'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the value', function(){
|
||||
assert.strictEqual(Resolver.format(null, env.foo)[1], 'Foo');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Complex string value', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo=Foo',
|
||||
'bar={{ foo }} Bar',
|
||||
'baz={{ missing }}',
|
||||
'qux={{ malformed }'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the value', function(){
|
||||
var value = Resolver.format(null, env.bar)[1];
|
||||
assert.strictEqual(value, 'Foo Bar');
|
||||
});
|
||||
|
||||
it('returns the raw string if the referenced entity is ' +
|
||||
'not found', function(){
|
||||
var value = Resolver.format(null, env.baz)[1];
|
||||
assert.strictEqual(value, '{{ missing }}');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Complex string referencing an entity with null value', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo.attr=Foo',
|
||||
'bar={{ foo }} Bar',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the null value', function(){
|
||||
var value = Resolver.format(null, env.foo)[1];
|
||||
assert.strictEqual(value, null);
|
||||
});
|
||||
|
||||
it('returns the attribute', function(){
|
||||
var attr = Resolver.format(null, env.foo.attrs.attr)[1];
|
||||
assert.strictEqual(attr, 'Foo');
|
||||
});
|
||||
|
||||
it('returns the raw string when the referenced entity has ' +
|
||||
'null value', function(){
|
||||
var value = Resolver.format(null, env.bar)[1];
|
||||
assert.strictEqual(value, '{{ foo }} Bar');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Cyclic reference', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={{ bar }}',
|
||||
'bar={{ foo }}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format(null, env.foo)[1];
|
||||
assert.strictEqual(value, '{{ foo }}');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Cyclic self-reference', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={{ foo }}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format(null, env.foo)[1];
|
||||
assert.strictEqual(value, '{{ foo }}');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Cyclic self-reference in a hash', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[one]={{ foo }}',
|
||||
'foo[two]=Bar',
|
||||
'bar={{ foo }}'
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('returns the raw string', function(){
|
||||
var value = Resolver.format({n: 1}, env.foo)[1];
|
||||
assert.strictEqual(value, '{{ foo }}');
|
||||
});
|
||||
|
||||
it('returns the valid value if requested directly', function(){
|
||||
var value = Resolver.format({n: 2}, env.bar)[1];
|
||||
assert.strictEqual(value, 'Bar');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
157
gaia/apps/sharedtest/test/unit/l10n/lib/util_test.js
Executable file
157
gaia/apps/sharedtest/test/unit/l10n/lib/util_test.js
Executable file
|
|
@ -0,0 +1,157 @@
|
|||
/* global it, assert:true, describe, before, beforeEach */
|
||||
/* global navigator */
|
||||
'use strict';
|
||||
|
||||
var assert, PropertiesParser;
|
||||
|
||||
var reVowels = /[AEIOUaeiou]/;
|
||||
|
||||
function digest(str) {
|
||||
var cur = 0;
|
||||
var i = str.length;
|
||||
while (i) {
|
||||
if (reVowels.test(str[--i])) {
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
describe('walkContent', function() {
|
||||
var L10n, source, ast;
|
||||
|
||||
before(function(done) {
|
||||
if (typeof navigator !== 'undefined') {
|
||||
require('/build/l10n.js', function() {
|
||||
L10n = navigator.mozL10n._getInternalAPI();
|
||||
PropertiesParser = L10n.PropertiesParser;
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
assert = require('assert');
|
||||
L10n = {};
|
||||
L10n.walkContent = require('../../src/lib/util').walkContent;
|
||||
PropertiesParser = require('../../src/lib/format/properties/parser');
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
ast = PropertiesParser.parse(null, source);
|
||||
});
|
||||
|
||||
describe('simple strings and attributes', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo=Foo',
|
||||
'foo.attr=An attribute',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('walks the value', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.strictEqual(walked.$v, 2);
|
||||
});
|
||||
|
||||
it('walks the attribute', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.strictEqual(walked.attr, 5);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('one-level-deep dict', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[one]=One',
|
||||
'foo[two]=Two',
|
||||
'foo[few]=Few',
|
||||
'foo[many]=Many',
|
||||
'foo[other]=Other',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('walks the values', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.strictEqual(walked.$v.one, 2);
|
||||
assert.strictEqual(walked.$v.two, 1);
|
||||
assert.strictEqual(walked.$v.few, 1);
|
||||
assert.strictEqual(walked.$v.many, 1);
|
||||
assert.strictEqual(walked.$v.other, 2);
|
||||
});
|
||||
|
||||
it('does not modify the index', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.deepEqual(walked.$x, [{t: 'idOrVar', v: 'plural'}, 'n']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// XXX parser currently doesn't support nested dicts
|
||||
describe.skip('two-level-deep dict', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo={[ plural(n) ]}',
|
||||
'foo[other]={[ plural(m) ]}',
|
||||
'foo[other][one]=One',
|
||||
'foo[other][two]=Two',
|
||||
'foo[other][few]=Few',
|
||||
'foo[other][many]=Many',
|
||||
'foo[other][other]=Other',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('walks the values', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.strictEqual(walked.$v.other.one, 2);
|
||||
assert.strictEqual(walked.$v.other.two, 1);
|
||||
assert.strictEqual(walked.$v.other.few, 1);
|
||||
assert.strictEqual(walked.$v.other.many, 1);
|
||||
assert.strictEqual(walked.$v.other.other, 2);
|
||||
});
|
||||
|
||||
it('does not modify the indexes', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.deepEqual(
|
||||
walked.$x, [{t: 'idOrVar', v: 'plural'}, 'n']);
|
||||
assert.deepEqual(
|
||||
walked.$v.other.$x, [{t: 'idOrVar', v: 'plural'}, 'n']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('attribute that is a one-level-deep dict', function(){
|
||||
|
||||
before(function() {
|
||||
source = [
|
||||
'foo.attr={[ plural(n) ]}',
|
||||
'foo.attr[one]=One',
|
||||
'foo.attr[two]=Two',
|
||||
'foo.attr[few]=Few',
|
||||
'foo.attr[many]=Many',
|
||||
'foo.attr[other]=Other',
|
||||
].join('\n');
|
||||
});
|
||||
|
||||
it('walks the values', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.strictEqual(walked.attr.$v.one, 2);
|
||||
assert.strictEqual(walked.attr.$v.two, 1);
|
||||
assert.strictEqual(walked.attr.$v.few, 1);
|
||||
assert.strictEqual(walked.attr.$v.many, 1);
|
||||
assert.strictEqual(walked.attr.$v.other, 2);
|
||||
});
|
||||
|
||||
it('does not modify the indexes', function(){
|
||||
var walked = L10n.walkContent(ast[0], digest);
|
||||
assert.deepEqual(walked.attr.$x, [{t: 'idOrVar', v: 'plural'}, 'n']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
Loading…
Reference in a new issue