Add lang class

This commit is contained in:
Bartek Fabiszewski 2019-12-19 22:20:55 +01:00
parent ca38094ffd
commit 83c139a035
13 changed files with 357 additions and 47 deletions

View File

@ -17,10 +17,10 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import { lang as $ } from './initializer.js';
import Chartist from 'chartist'
import ViewModel from './viewmodel.js';
import ctAxisTitle from 'chartist-plugin-axistitle';
import { lang } from './initializer.js';
import uUtils from './utils.js';
/**
@ -81,7 +81,7 @@ export default class ChartViewModel extends ViewModel {
plugins: [
ctAxisTitle({
axisY: {
axisTitle: `${lang.strings['altitude']} (${lang.unit('unitDistance')})`,
axisTitle: `${$._('altitude')} (${$.unit('unitDistance')})`,
axisClass: 'ct-axis-title',
offset: {
x: 0,

View File

@ -17,7 +17,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import { config, lang } from './initializer.js';
import { lang as $, config } from './initializer.js';
import ViewModel from './viewmodel.js';
import uUtils from './utils.js';
@ -61,7 +61,7 @@ export default class ConfigViewModel extends ViewModel {
}
setAutoReloadInterval() {
const interval = parseInt(prompt(lang.strings['newinterval']));
const interval = parseInt(prompt($._('newinterval')));
if (!isNaN(interval) && interval !== this.model.interval) {
this.model.interval = interval;
}

128
js/src/lang.js Normal file
View File

@ -0,0 +1,128 @@
/*
* μlogger
*
* Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net)
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
export default class uLang {
constructor() {
this.strings = {};
this.config = null;
}
/**
* @param {uConfig} config
* @param {Object<string, string>} data
*/
init(config, data) {
this.config = config;
if (data) {
/** @type {Object<string, string>} */
this.strings = data;
}
}
_(name) {
if (typeof this.strings[name] === 'undefined') {
throw new Error('Unknown localized string');
}
return this.strings[name];
}
/**
* @param {string} name
* @return {string}
*/
unit(name) {
const unitName = this.config[name];
if (typeof this.config[name] === 'undefined') {
throw new Error('Unknown localized unit');
}
return this._(unitName);
}
/**
* Get speed converted to locale units
* @param {number} ms Speed in meters per second
* @param {boolean} withUnit
* @return {(number|string)} String when with unit
*/
getLocaleSpeed(ms, withUnit) {
const value = Math.round(ms * this.config.factorSpeed * 360) / 100;
if (withUnit) {
return `${value} ${this.unit('unitSpeed')}`;
}
return value;
}
/**
* Get distance converted to locale units
* @param {number} m Distance in meters
* @param {boolean} withUnit
* @return {(number|string)} String when with unit
*/
getLocaleDistanceMajor(m, withUnit) {
const value = Math.round(m * this.config.factorDistanceMajor / 10) / 100;
if (withUnit) {
return `${value} ${this.unit('unitDistanceMajor')}`
}
return value;
}
/**
* @param {number} m Distance in meters
* @param {boolean} withUnit
* @return {(number|string)} String when with unit
*/
getLocaleDistance(m, withUnit) {
const value = Math.round(m * this.config.factorDistance * 100) / 100;
if (withUnit) {
return `${value} ${this.unit('unitDistance')}`;
}
return value;
}
/**
* @param {number} m Distance in meters
* @param {boolean} withUnit
* @return {(number|string)} String when with unit
*/
getLocaleAltitude(m, withUnit) {
return this.getLocaleDistance(m, withUnit);
}
/**
* @param {number} m Distance in meters
* @param {boolean} withUnit
* @return {(number|string)} String when with unit
*/
getLocaleAccuracy(m, withUnit) {
return this.getLocaleDistance(m, withUnit);
}
/**
* @param {number} s Duration in seconds
* @return {string} Formatted to (d) h:m:s
*/
getLocaleDuration(s) {
const d = Math.floor(s / 86400);
const h = Math.floor((s % 86400) / 3600);
const m = Math.floor(((s % 86400) % 3600) / 60);
s = ((s % 86400) % 3600) % 60;
return ((d > 0) ? (`${d} ${this.unit('unitDay')} `) : '') +
((`00${h}`).slice(-2)) + ':' + ((`00${m}`).slice(-2)) + ':' + ((`00${s}`).slice(-2)) + '';
}
}

View File

@ -17,7 +17,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import { config, lang } from '../initializer.js';
import { lang as $, config } from '../initializer.js';
import MapViewModel from '../mapviewmodel.js';
import uTrack from '../track.js';
import uUtils from '../utils.js';
@ -74,9 +74,9 @@ export default class GoogleMapsApi {
};
window.gm_authFailure = () => {
GoogleMapsApi.authError = true;
let message = uUtils.sprintf(lang.strings['apifailure'], 'Google Maps');
message += '<br><br>' + lang.strings['gmauthfailure'];
message += '<br><br>' + lang.strings['gmapilink'];
let message = uUtils.sprintf($._('apifailure'), 'Google Maps');
message += '<br><br>' + $._('gmauthfailure');
message += '<br><br>' + $._('gmapilink');
if (GoogleMapsApi.gmInitialized) {
alert(message);
}

View File

@ -17,7 +17,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import { config, lang } from './initializer.js';
import { lang as $, config } from './initializer.js';
import GoogleMapsApi from './mapapi/api_gmaps.js';
import OpenLayersApi from './mapapi/api_openlayers.js';
import ViewModel from './viewmodel.js';
@ -78,7 +78,7 @@ export default class MapViewModel extends ViewModel {
this.api.init()
.then(() => this.onReady())
.catch((e) => {
let txt = uUtils.sprintf(lang.strings['apifailure'], apiName);
let txt = uUtils.sprintf($._('apifailure'), apiName);
if (e && e.message) {
txt += ` (${e.message})`;
}
@ -134,36 +134,36 @@ export default class MapViewModel extends ViewModel {
}
let provider = '';
if (pos.provider === 'gps') {
provider = ` (<img class="icon" alt="${lang.strings['gps']}" title="${lang.strings['gps']}" src="images/gps_dark.svg">)`;
provider = ` (<img class="icon" alt="${$._('gps')}" title="${$._('gps')}" src="images/gps_dark.svg">)`;
} else if (pos.provider === 'network') {
provider = ` (<img class="icon" alt="${lang.strings['network']}" title="${lang.strings['network']}" src="images/network_dark.svg">)`;
provider = ` (<img class="icon" alt="${$._('network')}" title="${$._('network')}" src="images/network_dark.svg">)`;
}
let stats = '';
if (!this.state.showLatest) {
stats =
`<div id="pright">
<img class="icon" alt="${lang.strings['track']}" src="images/stats_blue.svg" style="padding-left: 3em;"><br>
<img class="icon" alt="${lang.strings['ttime']}" title="${lang.strings['ttime']}" src="images/time_blue.svg"> ${lang.getLocaleDuration(pos.totalSeconds)}<br>
<img class="icon" alt="${lang.strings['aspeed']}" title="${lang.strings['aspeed']}" src="images/speed_blue.svg"> ${lang.getLocaleSpeed(pos.totalSpeed, true)}<br>
<img class="icon" alt="${lang.strings['tdistance']}" title="${lang.strings['tdistance']}" src="images/distance_blue.svg"> ${lang.getLocaleDistanceMajor(pos.totalMeters, true)}<br>
<img class="icon" alt="${$._('track')}" src="images/stats_blue.svg" style="padding-left: 3em;"><br>
<img class="icon" alt="${$._('ttime')}" title="${$._('ttime')}" src="images/time_blue.svg"> ${$.getLocaleDuration(pos.totalSeconds)}<br>
<img class="icon" alt="${$._('aspeed')}" title="${$._('aspeed')}" src="images/speed_blue.svg"> ${$.getLocaleSpeed(pos.totalSpeed, true)}<br>
<img class="icon" alt="${$._('tdistance')}" title="${$._('tdistance')}" src="images/distance_blue.svg"> ${$.getLocaleDistanceMajor(pos.totalMeters, true)}<br>
</div>`;
}
return `<div id="popup">
<div id="pheader">
<div><img alt="${lang.strings['user']}" title="${lang.strings['user']}" src="images/user_dark.svg"> ${uUtils.htmlEncode(pos.username)}</div>
<div><img alt="${lang.strings['track']}" title="${lang.strings['track']}" src="images/route_dark.svg"> ${uUtils.htmlEncode(pos.trackname)}</div>
<div><img alt="${$._('user')}" title="${$._('user')}" src="images/user_dark.svg"> ${uUtils.htmlEncode(pos.username)}</div>
<div><img alt="${$._('track')}" title="${$._('track')}" src="images/route_dark.svg"> ${uUtils.htmlEncode(pos.trackname)}</div>
</div>
<div id="pbody">
${(pos.hasComment()) ? `<div id="pcomments">${uUtils.htmlEncode(pos.comment)}</div>` : ''}
${(pos.hasImage()) ? `<div id="pimage"><img src="uploads/${pos.image}" alt="image"></div>` : ''}
<div id="pleft">
<img class="icon" alt="${lang.strings['time']}" title="${lang.strings['time']}" src="images/calendar_dark.svg"> ${date}<br>
<img class="icon" alt="${lang.strings['time']}" title="${lang.strings['time']}" src="images/clock_dark.svg"> ${time}<br>
${(pos.speed !== null) ? `<img class="icon" alt="${lang.strings['speed']}" title="${lang.strings['speed']}" src="images/speed_dark.svg">${lang.getLocaleSpeed(pos.speed, true)}<br>` : ''}
${(pos.altitude !== null) ? `<img class="icon" alt="${lang.strings['altitude']}" title="${lang.strings['altitude']}" src="images/altitude_dark.svg">${lang.getLocaleAltitude(pos.altitude, true)}<br>` : ''}
${(pos.accuracy !== null) ? `<img class="icon" alt="${lang.strings['accuracy']}" title="${lang.strings['accuracy']}" src="images/accuracy_dark.svg">${lang.getLocaleAccuracy(pos.accuracy, true)}${provider}<br>` : ''}
<img class="icon" alt="${$._('time')}" title="${$._('time')}" src="images/calendar_dark.svg"> ${date}<br>
<img class="icon" alt="${$._('time')}" title="${$._('time')}" src="images/clock_dark.svg"> ${time}<br>
${(pos.speed !== null) ? `<img class="icon" alt="${$._('speed')}" title="${$._('speed')}" src="images/speed_dark.svg">${$.getLocaleSpeed(pos.speed, true)}<br>` : ''}
${(pos.altitude !== null) ? `<img class="icon" alt="${$._('altitude')}" title="${$._('altitude')}" src="images/altitude_dark.svg">${$.getLocaleAltitude(pos.altitude, true)}<br>` : ''}
${(pos.accuracy !== null) ? `<img class="icon" alt="${$._('accuracy')}" title="${$._('accuracy')}" src="images/accuracy_dark.svg">${$.getLocaleAccuracy(pos.accuracy, true)}${provider}<br>` : ''}
</div>${stats}</div>
<div id="pfooter">${uUtils.sprintf(lang.strings['pointof'], id + 1, count)}</div>
<div id="pfooter">${uUtils.sprintf($._('pointof'), id + 1, count)}</div>
</div>`;
}

View File

@ -17,7 +17,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import { config, lang } from './initializer.js';
import { lang as $, config } from './initializer.js';
import ViewModel from './viewmodel.js';
import uObserve from './observe.js';
import uPositionSet from './positionset.js';
@ -154,20 +154,20 @@ export default class TrackViewModel extends ViewModel {
const form = this.importEl.parentElement;
const sizeMax = form.elements['MAX_FILE_SIZE'].value;
if (this.importEl.files && this.importEl.files.length === 1 && this.importEl.files[0].size > sizeMax) {
uUtils.error(uUtils.sprintf(lang.strings['isizefailure'], sizeMax));
uUtils.error(uUtils.sprintf($._('isizefailure'), sizeMax));
return;
}
uTrack.import(form)
.then((trackList) => {
if (trackList.length) {
if (trackList.length > 1) {
alert(uUtils.sprintf(lang.strings['imultiple'], trackList.length));
alert(uUtils.sprintf($._('imultiple'), trackList.length));
}
this.model.trackList = trackList.concat(this.model.trackList);
this.model.currentTrackId = trackList[0].listValue;
}
})
.catch((e) => uUtils.error(e, `${lang.strings['actionfailure']}\n${e.message}`))
.catch((e) => uUtils.error(e, `${$._('actionfailure')}\n${e.message}`))
.finally(() => {
this.model.inputFile = '';
});
@ -190,7 +190,7 @@ export default class TrackViewModel extends ViewModel {
this.model.showLatest = false;
}
})
.catch((e) => { uUtils.error(e, `${lang.strings['actionfailure']}\n${e.message}`); });
.catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); });
}
}
@ -203,7 +203,7 @@ export default class TrackViewModel extends ViewModel {
this.state.currentTrack.clear();
}
this.state.currentTrack.fetchPositions()
.catch((e) => { uUtils.error(e, `${lang.strings['actionfailure']}\n${e.message}`); });
.catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); });
}
/**
@ -220,7 +220,7 @@ export default class TrackViewModel extends ViewModel {
this.model.currentTrackId = _track.listValue;
}
})
.catch((e) => { uUtils.error(e, `${lang.strings['actionfailure']}\n${e.message}`); });
.catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); });
}
/**
@ -235,7 +235,7 @@ export default class TrackViewModel extends ViewModel {
this.state.currentTrack = _track;
}
})
.catch((e) => { uUtils.error(e, `${lang.strings['actionfailure']}\n${e.message}`); });
.catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); });
}
loadTrackList() {
@ -253,7 +253,7 @@ export default class TrackViewModel extends ViewModel {
this.model.currentTrackId = '';
}
})
.catch((e) => { uUtils.error(e, `${lang.strings['actionfailure']}\n${e.message}`); });
.catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); });
}
/**
@ -291,14 +291,14 @@ export default class TrackViewModel extends ViewModel {
const dateString = (date.toDateString() !== today.toDateString()) ? `${dateTime.date}<br>` : '';
const timeString = `${dateTime.time}<span style="font-weight:normal">${dateTime.zone}</span>`;
this.model.summary = `
<div class="menu-title">${lang.strings['latest']}:</div>
<div class="menu-title">${$._('latest')}:</div>
${dateString}
${timeString}`;
} else {
this.model.summary = `
<div class="menu-title">${lang.strings['summary']}</div>
<div><img class="icon" alt="${lang.strings['tdistance']}" title="${lang.strings['tdistance']}" src="images/distance.svg"> ${lang.getLocaleDistanceMajor(last.totalMeters, true)}</div>
<div><img class="icon" alt="${lang.strings['ttime']}" title="${lang.strings['ttime']}" src="images/time.svg"> ${lang.getLocaleDuration(last.totalSeconds)}</div>`;
<div class="menu-title">${$._('summary')}</div>
<div><img class="icon" alt="${$._('tdistance')}" title="${$._('tdistance')}" src="images/distance.svg"> ${$.getLocaleDistanceMajor(last.totalMeters, true)}</div>
<div><img class="icon" alt="${$._('ttime')}" title="${$._('ttime')}" src="images/time.svg"> ${$.getLocaleDuration(last.totalSeconds)}</div>`;
}
}

View File

@ -17,7 +17,7 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import { auth, lang } from './initializer.js';
import { lang as $, auth } from './initializer.js';
import ViewModel from './viewmodel.js';
import uSelect from './select.js';
import uUser from './user.js';
@ -40,7 +40,7 @@ export default class UserViewModel extends ViewModel {
});
/** @type HTMLSelectElement */
const listEl = document.querySelector('#user');
this.select = new uSelect(listEl, lang.strings['suser'], `- ${lang.strings['allusers']} -`);
this.select = new uSelect(listEl, $._('suser'), `- ${$._('allusers')} -`);
this.state = state;
}
@ -61,7 +61,7 @@ export default class UserViewModel extends ViewModel {
this.model.currentUserId = userId;
}
})
.catch((e) => { uUtils.error(e, `${lang.strings['actionfailure']}\n${e.message}`); });
.catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); });
}
/**

View File

@ -21,6 +21,7 @@ import * as gmStub from './googlemaps.stub.js';
import { config, lang } from '../src/initializer.js'
import GoogleMapsApi from '../src/mapapi/api_gmaps.js';
import TrackFactory from './helpers/trackfactory.js';
import uObserve from '../src/observe.js';
import uUtils from '../src/utils.js';
describe('Google Maps map API tests', () => {
@ -45,10 +46,14 @@ describe('Google Maps map API tests', () => {
spyOn(google.maps, 'Polyline').and.callThrough();
spyOnProperty(GoogleMapsApi, 'loadTimeoutMs', 'get').and.returnValue(loadTimeout);
spyOn(window, 'alert');
spyOn(lang, '_').and.returnValue('{placeholder}');
gmStub.applyPrototypes();
});
afterEach(() => gmStub.clear());
afterEach(() => {
gmStub.clear();
uObserve.unobserveAll(lang);
});
it('should timeout initialization of map engine', (done) => {
// given
@ -124,13 +129,13 @@ describe('Google Maps map API tests', () => {
it('should fail with authorization error', (done) => {
// given
spyOn(uUtils, 'loadScript').and.returnValue(Promise.resolve());
lang.strings['apifailure'] = 'authfailure';
lang._.and.returnValue('authfailure');
// when
api.init()
.then(() => done.fail('resolve callback called'))
.catch((e) => {
// then
expect(e.message).toContain(lang.strings['apifailure']);
expect(e.message).toContain('authfailure');
done();
});
window.gm_authFailure();
@ -139,7 +144,7 @@ describe('Google Maps map API tests', () => {
it('should show alert if authorization error occurs after initialization', (done) => {
// given
spyOn(uUtils, 'loadScript').and.returnValue(Promise.resolve());
lang.strings['apifailure'] = 'authfailure';
lang._.and.returnValue('authfailure');
// when
api.init()
.then(() => {
@ -151,7 +156,7 @@ describe('Google Maps map API tests', () => {
window.gm_authFailure();
expect(window.alert).toHaveBeenCalledTimes(1);
expect(window.alert.calls.mostRecent().args[0]).toContain(lang.strings['apifailure']);
expect(window.alert.calls.mostRecent().args[0]).toContain('authfailure');
});
it('should clean up class fields', () => {

View File

@ -86,6 +86,7 @@ describe('ChartViewModel tests', () => {
state = new uState();
vm = new ChartViewModel(state);
spyOn(lang, 'unit');
spyOn(lang, '_').and.returnValue('{placeholder}');
mockChart = jasmine.createSpyObj('mockChart', {
'on': { /* ignored */ },
'update': { /* ignored */ }

View File

@ -17,9 +17,10 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import { config, lang } from '../src/initializer.js';
import ConfigViewModel from '../src/configviewmodel.js';
import ViewModel from '../src/viewmodel.js';
import { config } from '../src/initializer.js';
import uObserve from '../src/observe.js';
import uState from '../src/state.js';
import uUtils from '../src/utils.js';
@ -87,10 +88,12 @@ describe('ConfigViewModel tests', () => {
vm.init();
spyOn(uUtils, 'setCookie').and.returnValue(newInterval);
spyOn(ConfigViewModel, 'reload');
spyOn(lang, '_').and.returnValue('{placeholder}');
});
afterEach(() => {
document.body.removeChild(document.querySelector('#fixture'));
uObserve.unobserveAll(lang);
});
it('should create instance with state as parameter', () => {

167
js/test/lang.test.js Normal file
View File

@ -0,0 +1,167 @@
/*
* μlogger
*
* Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net)
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
import uLang from '../src/lang.js';
describe('Lang tests', () => {
let lang;
let mockConfig;
let mockStrings;
const value = 1000;
beforeEach(() => {
lang = new uLang();
mockConfig = {
factorSpeed: 0.33,
unitSpeed: 'units',
factorDistance: 1.3,
unitDistance: 'unitd',
factorDistanceMajor: 0.55,
unitDistanceMajor: 'unitdm',
unitDay: 'unitday'
};
mockStrings = {
string1: 'łańcuch1',
units: 'jp',
unitd: 'jo',
unitdm: 'jo / 1000',
unitday: 'd'
}
});
it('should create instance', () => {
expect(lang.strings).toEqual({});
expect(lang.config).toBe(null);
});
it('should initialize', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.strings).toBe(mockStrings);
expect(lang.config).toBe(mockConfig);
});
it('should return localized string', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang._('string1')).toBe(mockStrings.string1);
});
it('should throw error on unknown string', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(() => lang._('unknown_string')).toThrowError(/Unknown/);
});
it('should return localized unit', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.unit('unitSpeed')).toBe(mockStrings.units);
});
it('should return localized speed value', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleSpeed(value, false)).toBe(1188);
});
it('should return localized speed value with unit', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleSpeed(value, true)).toBe(`1188 ${mockStrings.units}`);
});
it('should return localized distance major value', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistanceMajor(value, false)).toBe(0.55);
});
it('should return localized distance major value with unit', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistanceMajor(value, true)).toBe(`0.55 ${mockStrings.unitdm}`);
});
it('should return localized distance value', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistance(value, false)).toBe(1300);
});
it('should return localized distance value with unit', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistance(value, true)).toBe(`1300 ${mockStrings.unitd}`);
});
it('should return localized altitude value', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistance(value, false)).toBe(1300);
});
it('should return localized altitude value with unit', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistance(value, true)).toBe(`1300 ${mockStrings.unitd}`);
});
it('should return localized accuracy value', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistance(value, false)).toBe(1300);
});
it('should return localized accuracy value with unit', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDistance(value, true)).toBe(`1300 ${mockStrings.unitd}`);
});
it('should return localized time duration', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDuration(12345)).toBe('03:25:45');
});
it('should return localized time duration with day unit', () => {
// when
lang.init(mockConfig, mockStrings);
// then
expect(lang.getLocaleDuration(123456789)).toBe(`1428 ${mockStrings.unitday} 21:33:09`);
});
});

View File

@ -44,7 +44,6 @@ describe('MapViewModel tests', () => {
config.reinitialize();
config.mapApi = defaultApi;
lang.init(config);
lang.strings['apifailure'] = 'api failure: %s';
mockApi = jasmine.createSpyObj('mockApi', {
'init': Promise.resolve(),
'getBounds': { /* ignored */ },
@ -57,12 +56,17 @@ describe('MapViewModel tests', () => {
state = new uState();
vm = new MapViewModel(state);
spyOn(vm, 'getApi').and.returnValue(mockApi);
spyOn(lang, 'getLocaleSpeed');
spyOn(lang, 'getLocaleDistance');
spyOn(lang, 'getLocaleDistanceMajor');
spyOn(lang, '_').and.returnValue('{placeholder}');
bounds = [ 1, 2, 3, 4 ];
track = TrackFactory.getTrack(0);
});
afterEach(() => {
document.body.removeChild(document.querySelector('#fixture'));
uObserve.unobserveAll(lang);
});
it('should create instance', () => {

View File

@ -83,6 +83,7 @@ describe('TrackViewModel tests', () => {
config.reinitialize();
config.interval = 10;
lang.init(config);
spyOn(lang, '_').and.returnValue('{placeholder}');
trackEl = document.querySelector('#track');
summaryEl = document.querySelector('#summary');
latestEl = document.querySelector('#latest');
@ -106,6 +107,7 @@ describe('TrackViewModel tests', () => {
afterEach(() => {
document.body.removeChild(document.querySelector('#fixture'));
uObserve.unobserveAll(lang);
});
it('should create instance with state as parameter', () => {