feat(@lion/ui): getLocalizeManager method, for side-effect-free localize

This commit is contained in:
Thijs Louisse 2023-02-01 10:17:29 +01:00 committed by Thijs Louisse
parent 0efce8e18b
commit 6712934782
15 changed files with 271 additions and 97 deletions

View file

@ -0,0 +1,74 @@
// @ts-ignore
import { singletonManager } from 'singleton-manager';
import { LocalizeManager } from './LocalizeManager.js';
/**
* Side-effect-free alternative for `localize` (the globally shared instance of LocalizeManager).
* When this function is imported, no side-effect happened yet, i.e. no global instance was registered yet.
* The side effect-free approach generates:
* - smaller, optimized bundles
* - a predictable loading order, that allows for:
* - deduping strategies when multiple instances of the localizeManager are on a page
* - providing a customized extension of LocalizeManager
*
* Use it like this:
*
* ```js
* function myFunction() {
* // note that 'localizeManager' is the same as former 'localize'
* const localize = getLocalizeManger();
* // ...
* }
* ```
*
* In a class, we advise a shared instance:
* ```js
* class MyClass {
* constructor() {
* this._localizeManager = getLocalizeManger();
* }
* // ...
* }
* ```
*
* Make sure to always call this method inside a function or class (otherwise side effects are created)
*
* Do you want to register your own LocalizeManager?
* Make sure it's registered before anyone called `getLocalizeManager()`
*
* ```js
* import { singletonManager } from 'singleton-manager';
* import { getLocalizeManger } from '@lion/ui/localize-no-side-effects.js';
*
* // First register your own LocalizeManager (for deduping or other reasons)
* singletonManager.set('lion/ui::localize::0.x', class MyLocalizeManager extends LocalizeManager {});
*
* // Now, all your code gets the right instance
* function myFuntion() {
* const localizeManager = getLocalizeManager();
* // ...
* }
*
* class myClass() {
* constructor() {
* this._localizeManager = getLocalizeManager();
* // ...
* }
* }
* ```
*
* @returns {LocalizeManager}
*/
export function getLocalizeManager() {
if (singletonManager.has('@lion/ui::localize::0.x')) {
return singletonManager.get('@lion/ui::localize::0.x');
}
const localizeManager = new LocalizeManager({
autoLoadOnLocaleChange: true,
fallbackLocale: 'en-GB',
});
singletonManager.set('@lion/ui::localize::0.x', localizeManager);
return localizeManager;
}

View file

@ -1,11 +1,8 @@
import { singletonManager } from 'singleton-manager';
import { LocalizeManager } from './LocalizeManager.js';
import { getLocalizeManager } from './getLocalizeManager.js';
/** @type {LocalizeManager} */
/**
* Use the side-effect-free `const localizeManager = getLocalizeManager()` instead.
* @deprecated
*/
// eslint-disable-next-line import/no-mutable-exports
export const localize =
/** @type {LocalizeManager} */ (singletonManager.get('@lion/ui::localize::0.x')) ||
new LocalizeManager({
autoLoadOnLocaleChange: true,
fallbackLocale: 'en-GB',
});
export const localize = getLocalizeManager();

View file

@ -4,7 +4,7 @@ import sinon from 'sinon';
import { fetchMock } from '@bundled-es-modules/fetch-mock';
import { setupFakeImport, resetFakeImport, fakeImport } from '@lion/ui/localize-test-helpers.js';
import { LocalizeManager } from '@lion/ui/localize.js';
import { LocalizeManager } from '@lion/ui/localize-no-side-effects.js';
/**
* @param {LocalizeManager} localizeManagerEl

View file

@ -12,7 +12,7 @@ import {
unsafeStatic,
} from '@open-wc/testing';
import sinon from 'sinon';
import { localize, LocalizeMixin } from '@lion/ui/localize.js';
import { LocalizeMixin, getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import {
fakeImport,
localizeTearDown,
@ -26,6 +26,8 @@ import {
*/
describe('LocalizeMixin', () => {
const localizeManager = getLocalizeManager();
afterEach(() => {
resetFakeImport();
localizeTearDown();
@ -48,7 +50,7 @@ describe('LocalizeMixin', () => {
setupEmptyFakeImportsFor(['my-element'], ['en-GB']);
const loadNamespaceSpy = sinon.spy(localize, 'loadNamespace');
const loadNamespaceSpy = sinon.spy(localizeManager, 'loadNamespace');
await fixture(html`<${tag}></${tag}>`);
expect(loadNamespaceSpy.callCount).to.equal(1);
@ -88,7 +90,7 @@ describe('LocalizeMixin', () => {
setupEmptyFakeImportsFor(['default', 'parent-element', 'child-element'], ['en-GB']);
const loadNamespaceSpy = sinon.spy(localize, 'loadNamespace');
const loadNamespaceSpy = sinon.spy(localizeManager, 'loadNamespace');
await fixture(html`<${tag}></${tag}>`);
expect(loadNamespaceSpy.callCount).to.equal(3);
@ -151,7 +153,7 @@ describe('LocalizeMixin', () => {
await el.localizeNamespacesLoaded;
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
await el.localizeNamespacesLoaded;
expect(onLocaleChangedSpy.callCount).to.equal(0);
@ -159,7 +161,7 @@ describe('LocalizeMixin', () => {
wrapper.appendChild(el);
// Changing locale will result in onLocaleChanged to be invoked
localize.locale = 'ru-RU';
localizeManager.locale = 'ru-RU';
await el.localizeNamespacesLoaded;
expect(onLocaleChangedSpy.callCount).to.equal(2);
expect(onLocaleChangedSpy.calledWithExactly('ru-RU', 'nl-NL')).to.be.true;
@ -183,10 +185,10 @@ describe('LocalizeMixin', () => {
onLocaleChanged(newLocale, oldLocale) {
super.onLocaleChanged(newLocale, oldLocale);
// Can call localize.msg immediately, without having to await localize.loadingComplete
// Can call localizeManager.msg immediately, without having to await localizeManager.loadingComplete
// This is because localeChanged event is fired only after awaiting loading
// unless the user disables _autoLoadOnLocaleChange property
this.foo = localize.msg('my-element:foo');
this.foo = localizeManager.msg('my-element:foo');
}
}
@ -198,11 +200,11 @@ describe('LocalizeMixin', () => {
const wrapper = await fixture('<div></div>');
wrapper.appendChild(el);
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
await el.localizeNamespacesLoaded;
expect(el.foo).to.equal('bar-nl-NL');
localize.locale = 'ru-RU';
localizeManager.locale = 'ru-RU';
await el.localizeNamespacesLoaded;
expect(el.foo).to.equal('bar-ru-RU');
});
@ -233,7 +235,7 @@ describe('LocalizeMixin', () => {
await el.localizeNamespacesLoaded;
expect(onLocaleUpdatedSpy.callCount).to.equal(1);
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
await el.localizeNamespacesLoaded;
expect(onLocaleUpdatedSpy.callCount).to.equal(2);
});
@ -261,7 +263,7 @@ describe('LocalizeMixin', () => {
async onLocaleUpdated() {
super.onLocaleUpdated();
this.label = localize.msg('my-element:label');
this.label = localizeManager.msg('my-element:label');
}
}
@ -272,7 +274,7 @@ describe('LocalizeMixin', () => {
await nextFrame(); // needed as both are added to the micro task que
expect(el.label).to.equal('one');
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
await el.localizeNamespacesLoaded;
expect(el.label).to.equal('two');
});
@ -297,7 +299,7 @@ describe('LocalizeMixin', () => {
el.connectedCallback();
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
await el.localizeNamespacesLoaded;
// await next frame for requestUpdate to be fired
@ -325,7 +327,7 @@ describe('LocalizeMixin', () => {
const tagString = defineCE(MyElement);
const el = /** @type {MyElement} */ (document.createElement(tagString));
el.connectedCallback();
const lionLocalizeMessageSpy = sinon.spy(localize, 'msg');
const lionLocalizeMessageSpy = sinon.spy(localizeManager, 'msg');
const messageDirective = el.msgLit('my-element:greeting');
expect(lionLocalizeMessageSpy.callCount).to.equal(0);
@ -442,7 +444,7 @@ describe('LocalizeMixin', () => {
if (el.shadowRoot) {
const p = /** @type {HTMLParagraphElement} */ (el.shadowRoot.querySelector('p'));
expect(p.innerText).to.equal('Hi!');
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(p.innerText).to.equal('Hi!');
await el.localizeNamespacesLoaded;
await nextFrame(); // needed because msgLit relies on until directive to re-render

View file

@ -1,5 +1,5 @@
import { expect } from '@open-wc/testing';
import { localize, formatDate, parseDate } from '@lion/ui/localize.js';
import { getLocalizeManager, formatDate, parseDate } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
const SUPPORTED_LOCALES = {
@ -41,6 +41,7 @@ const SUPPORTED_LOCALES = {
*/
describe('formatDate', () => {
const localizeManager = getLocalizeManager();
beforeEach(() => {
localizeTearDown();
});
@ -50,16 +51,16 @@ describe('formatDate', () => {
expect(formatDate(testDate)).to.equal('21/05/2012');
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(formatDate(testDate)).to.equal('21-05-2012');
localize.locale = 'fr-FR';
localizeManager.locale = 'fr-FR';
expect(formatDate(testDate)).to.equal('21/05/2012');
localize.locale = 'de-DE';
localizeManager.locale = 'de-DE';
expect(formatDate(testDate)).to.equal('21.05.2012');
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(formatDate(testDate)).to.equal('05/21/2012');
});
@ -74,13 +75,13 @@ describe('formatDate', () => {
};
expect(formatDate(testDate, options)).to.equal('Monday, 21 May 2012');
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(formatDate(testDate, options)).to.equal('maandag 21 mei 2012');
localize.locale = 'fr-FR';
localizeManager.locale = 'fr-FR';
expect(formatDate(testDate, options)).to.equal('lundi 21 mai 2012');
localize.locale = 'de-DE';
localizeManager.locale = 'de-DE';
expect(formatDate(testDate, options)).to.equal('Montag, 21. Mai 2012');
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(formatDate(testDate, options)).to.equal('Monday, May 21, 2012');
});
@ -93,7 +94,7 @@ describe('formatDate', () => {
day: '2-digit',
locale: 'en-US',
};
localize.locale = 'hu-HU';
localizeManager.locale = 'hu-HU';
let date = /** @type {Date} */ (parseDate('2018-5-28'));
expect(formatDate(date)).to.equal('2018. 05. 28.');
@ -110,7 +111,7 @@ describe('formatDate', () => {
day: '2-digit',
locale: 'en-US',
};
localize.locale = 'bg-BG';
localizeManager.locale = 'bg-BG';
let date = /** @type {Date} */ (parseDate('29-12-2017'));
expect(formatDate(date)).to.equal('29.12.2017 г.');
@ -130,7 +131,7 @@ describe('formatDate', () => {
day: '2-digit',
locale: 'en-US',
};
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
let date = /** @type {Date} */ (parseDate('12-29-1940'));
expect(formatDate(date)).to.equal('12/29/1940');
@ -276,11 +277,11 @@ describe('formatDate', () => {
// locale is en-GB
expect(formatDate(testDate, options)).to.equal('Monday, 21 May 2012');
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(formatDate(testDate, options)).to.equal('MAANDAG 21 MEI 2012');
localize.locale = 'de-DE';
localizeManager.locale = 'de-DE';
expect(formatDate(testDate, options)).to.equal('montag, 21. mai 2012');
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(formatDate(testDate, options)).to.equal('Monday, May 21, 2012');
});
@ -293,21 +294,21 @@ describe('formatDate', () => {
month: 'long',
day: '2-digit',
};
localize.setDatePostProcessorForLocale({
localizeManager.setDatePostProcessorForLocale({
locale: 'nl-NL',
postProcessor: upperCaseProcessor,
});
localize.setDatePostProcessorForLocale({
localizeManager.setDatePostProcessorForLocale({
locale: 'de-DE',
postProcessor: upperCaseProcessor,
});
expect(formatDate(testDate, options)).to.equal('Monday, 21 May 2012');
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(formatDate(testDate, options)).to.equal('MAANDAG 21 MEI 2012');
localize.locale = 'de-DE';
localizeManager.locale = 'de-DE';
expect(formatDate(testDate, options)).to.equal('MONTAG, 21. MAI 2012');
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(formatDate(testDate, options)).to.equal('Monday, May 21, 2012');
});
@ -326,17 +327,17 @@ describe('formatDate', () => {
postProcessors,
};
localize.setDatePostProcessorForLocale({
localizeManager.setDatePostProcessorForLocale({
locale: 'de-DE',
postProcessor: lowerCaseProcessor,
});
expect(formatDate(testDate, options)).to.equal('Monday, 21 May 2012');
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(formatDate(testDate, options)).to.equal('MAANDAG 21 MEI 2012');
localize.locale = 'de-DE';
localizeManager.locale = 'de-DE';
expect(formatDate(testDate, options)).to.equal('MONTAG, 21. MAI 2012');
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(formatDate(testDate, options)).to.equal('Monday, May 21, 2012');
});
});

View file

@ -1,16 +1,21 @@
import { expect } from '@open-wc/testing';
import { localize, getDateFormatBasedOnLocale } from '@lion/ui/localize.js';
import {
getLocalizeManager,
getDateFormatBasedOnLocale,
} from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
describe('getDateFormatBasedOnLocale()', () => {
const localizeManager = getLocalizeManager();
beforeEach(() => {
localizeTearDown();
});
it('returns the positions of day, month and year', async () => {
localize.locale = 'en-GB';
localizeManager.locale = 'en-GB';
expect(getDateFormatBasedOnLocale()).to.equal('day-month-year');
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(getDateFormatBasedOnLocale()).to.equal('month-day-year');
});
});

View file

@ -1,5 +1,5 @@
import { expect } from '@open-wc/testing';
import { parseDate, localize } from '@lion/ui/localize.js';
import { parseDate, getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
/**
@ -18,6 +18,7 @@ function equalsDate(value, date) {
}
describe('parseDate()', () => {
const localizeManager = getLocalizeManager();
beforeEach(() => {
localizeTearDown();
});
@ -45,9 +46,9 @@ describe('parseDate()', () => {
});
it('handles different locales', () => {
localize.locale = 'en-GB';
localizeManager.locale = 'en-GB';
expect(equalsDate(parseDate('31-12-1976'), new Date('1976/12/31'))).to.equal(true);
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(equalsDate(parseDate('12-31-1976'), new Date('1976/12/31'))).to.equal(true);
});
@ -55,11 +56,11 @@ describe('parseDate()', () => {
expect(parseDate('12.12.1976.,')).to.equal(undefined); // wrong delimiter
expect(parseDate('foo')).to.equal(undefined); // no date
localize.locale = 'en-GB';
localizeManager.locale = 'en-GB';
expect(parseDate('31.02.2020')).to.equal(undefined); // non existing date
expect(parseDate('12.31.2020')).to.equal(undefined); // day & month switched places
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(parseDate('02.31.2020')).to.equal(undefined); // non existing date
expect(parseDate('31.12.2020')).to.equal(undefined); // day & month switched places
});

View file

@ -0,0 +1,30 @@
import { expect } from '@open-wc/testing';
// @ts-ignore
import { singletonManager } from 'singleton-manager';
import { LocalizeManager } from '../src/LocalizeManager.js';
import { getLocalizeManager } from '../src/getLocalizeManager.js';
describe('getLocalizeManager', () => {
beforeEach(() => {
singletonManager._map.clear();
});
it('gets a default instance when nothing registered on singletonManager with "@lion/ui::localize::0.x"', () => {
expect(singletonManager.get('@lion/ui::localize::0.x')).to.be.undefined;
const localizeManager = getLocalizeManager();
expect(localizeManager).to.equal(singletonManager.get('@lion/ui::localize::0.x'));
});
it('gets the same instance when called multiple times', () => {
const localizeManager = getLocalizeManager();
const localizeManagerSecondCall = getLocalizeManager();
expect(localizeManager).to.equal(localizeManagerSecondCall);
});
it('gets the instance that was registered on singletonManager with "@lion/ui::localize::0.x"', () => {
// Set your own for custom behavior or for deduping purposes
class MyLocalizeManager extends LocalizeManager {}
singletonManager.set('@lion/ui::localize::0.x', MyLocalizeManager);
expect(getLocalizeManager()).to.equal(MyLocalizeManager);
});
});

View file

@ -1,6 +1,6 @@
import { expect } from '@open-wc/testing';
import { localize, LocalizeManager } from '@lion/ui/localize.js';
import { getLocalizeManager, LocalizeManager } from '@lion/ui/localize-no-side-effects.js';
/**
* @param {LocalizeManager} localizeManagerEl
@ -16,6 +16,7 @@ function getProtectedMembers(localizeManagerEl) {
}
describe('localize', () => {
const localizeManager = getLocalizeManager();
// this is an important mindset:
// we don't test the singleton
// we check that it is an instance of the right class
@ -23,16 +24,16 @@ describe('localize', () => {
// this allows to avoid any side effects caused by changing singleton state between tests
it('is an instance of LocalizeManager', () => {
expect(localize).to.be.an.instanceOf(LocalizeManager);
expect(localizeManager).to.be.an.instanceOf(LocalizeManager);
});
it('is configured to automatically load namespaces if locale is changed', () => {
const { autoLoadOnLocaleChange } = getProtectedMembers(localize);
const { autoLoadOnLocaleChange } = getProtectedMembers(localizeManager);
expect(autoLoadOnLocaleChange).to.equal(true);
});
it('is configured to fallback to the locale "en-GB"', () => {
const { fallbackLocale } = getProtectedMembers(localize);
const { fallbackLocale } = getProtectedMembers(localizeManager);
expect(fallbackLocale).to.equal('en-GB');
});
});

View file

@ -1,5 +1,5 @@
import { expect } from '@open-wc/testing';
import { localize, formatNumber } from '@lion/ui/localize.js';
import { getLocalizeManager, formatNumber } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
// TODO: This is broken only in Safari 13.1.2 Wait till ci is on 13.1.3 and remove
@ -20,6 +20,8 @@ const currencySymbol = /** @param {string} currency */ currency => ({
});
describe('formatNumber', () => {
const localizeManager = getLocalizeManager();
afterEach(localizeTearDown);
it('displays the appropriate amount of decimal places based on currencies spec http://www.currency-iso.org/en/home/tables/table-a1.html', () => {
@ -74,14 +76,14 @@ describe('formatNumber', () => {
expect(formatNumber(undefined)).to.equal('');
});
it('uses `localize.formatNumberOptions.returnIfNaN`', () => {
const savedReturnIfNaN = localize.formatNumberOptions.returnIfNaN;
it('uses `localizeManager.formatNumberOptions.returnIfNaN`', () => {
const savedReturnIfNaN = localizeManager.formatNumberOptions.returnIfNaN;
localize.formatNumberOptions.returnIfNaN = '-';
localizeManager.formatNumberOptions.returnIfNaN = '-';
// @ts-ignore
expect(formatNumber('foo')).to.equal('-');
localize.formatNumberOptions.returnIfNaN = savedReturnIfNaN;
localizeManager.formatNumberOptions.returnIfNaN = savedReturnIfNaN;
});
it("can set what to returns when NaN via `returnIfNaN: 'foo'`", () => {
@ -89,11 +91,11 @@ describe('formatNumber', () => {
expect(formatNumber('foo', { returnIfNaN: '-' })).to.equal('-');
});
it('uses `localize.locale`', () => {
it('uses `localizeManager.locale`', () => {
expect(formatNumber(123456.789, { style: 'decimal', maximumFractionDigits: 2 })).to.equal(
'123,456.79',
);
localize.locale = 'de-DE';
localizeManager.locale = 'de-DE';
expect(formatNumber(123456.789, { style: 'decimal', maximumFractionDigits: 2 })).to.equal(
'123.456,79',
);
@ -136,7 +138,7 @@ describe('formatNumber', () => {
});
it('formats numbers correctly', () => {
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(formatNumber(0, { style: 'decimal', minimumFractionDigits: 2 })).to.equal('0,00');
expect(formatNumber(0.1, { style: 'decimal', minimumFractionDigits: 2 })).to.equal('0,10');
expect(formatNumber(0.12, { style: 'decimal', minimumFractionDigits: 2 })).to.equal('0,12');
@ -190,7 +192,7 @@ describe('formatNumber', () => {
});
it('throws when decimal and group separator are the same value, only when problematic', () => {
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
const fn = () =>
formatNumber(112345678, {
style: 'decimal',
@ -239,7 +241,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
});
it('formats 2-digit decimals correctly', () => {
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
Array.from(new Array(100), (val, index) => index).forEach(i => {
const iString = `${i}`;
let number = 0.0;
@ -253,7 +255,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
describe('normalization', () => {
describe('en-GB', () => {
it('supports basics', () => {
localize.locale = 'en-GB';
localizeManager.locale = 'en-GB';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('EUR 123,456.79');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('USD 123,456.79');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('JPY 123,457');
@ -265,7 +267,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
describe('en-US', () => {
it('supports basics', () => {
localize.locale = 'en-US';
localizeManager.locale = 'en-US';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('EUR 123,456.79');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('USD 123,456.79');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('JPY 123,457');
@ -282,7 +284,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
}
it('supports basics', () => {
localize.locale = 'en-AU';
localizeManager.locale = 'en-AU';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('EUR 123,456.79');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('USD 123,456.79');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('JPY 123,457');
@ -294,7 +296,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
describe('en-PH', () => {
it('supports basics', () => {
localize.locale = 'en-PH';
localizeManager.locale = 'en-PH';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('EUR 123,456.79');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('USD 123,456.79');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('JPY 123,457');
@ -306,7 +308,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
describe('nl-NL', () => {
it('supports basics', () => {
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123.456,79 USD');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123.457 JPY');
@ -323,7 +325,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
}
it('supports basics', () => {
localize.locale = 'nl-BE';
localizeManager.locale = 'nl-BE';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123.456,79 USD');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123.457 JPY');
@ -335,7 +337,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
describe('fr-FR', () => {
it('supports basics', () => {
localize.locale = 'fr-FR';
localizeManager.locale = 'fr-FR';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123 456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123 456,79 USD');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY');
@ -351,7 +353,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
if (isSafari) {
return;
}
localize.locale = 'fr-BE';
localizeManager.locale = 'fr-BE';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123 456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123 456,79 USD');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY');
@ -363,7 +365,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
describe('bg-BG', () => {
it('supports basics', () => {
localize.locale = 'bg-BG';
localizeManager.locale = 'bg-BG';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123 456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123 456,79 USD');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY');
@ -373,7 +375,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
});
it('normalizes group separator', () => {
localize.locale = 'bg-BG';
localizeManager.locale = 'bg-BG';
expect(formatNumber(1.234, currencyCode('EUR'))).to.equal('1,23 EUR');
expect(formatNumber(1234.567, currencyCode('EUR'))).to.equal('1 234,57 EUR');
expect(formatNumber(-1234.567, currencyCode('EUR'))).to.equal('1 234,57 EUR');
@ -382,7 +384,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
describe('cs-CZ', () => {
it('supports basics', () => {
localize.locale = 'cs-CZ';
localizeManager.locale = 'cs-CZ';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123 456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123 456,79 USD');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY');
@ -401,7 +403,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
}
it('supports basics', () => {
localize.locale = 'tr-TR';
localizeManager.locale = 'tr-TR';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123.456,79 USD');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123.457 JPY');
@ -413,7 +415,7 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
});
it('forces turkish currency code ', () => {
localize.locale = 'tr-TR';
localizeManager.locale = 'tr-TR';
expect(
formatNumber(1234.56, { style: 'currency', currencyDisplay: 'code', currency: 'TRY' }),
).to.equal('1.234,56 TL');
@ -428,10 +430,10 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
/** @type {Map<string, import('../../types/LocalizeMixinTypes.js').NumberPostProcessor>} */
let savedpostProcessors;
beforeEach(() => {
savedpostProcessors = localize.formatNumberOptions.postProcessors;
savedpostProcessors = localizeManager.formatNumberOptions.postProcessors;
});
afterEach(() => {
localize.formatNumberOptions.postProcessors = savedpostProcessors;
localizeManager.formatNumberOptions.postProcessors = savedpostProcessors;
});
/**
@ -460,8 +462,8 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
).to.equal('112 345 678');
});
it('uses `localize.formatNumberOptions.postProcessors`', () => {
localize.setNumberPostProcessorForLocale({
it('uses `localizeManager.formatNumberOptions.postProcessors`', () => {
localizeManager.setNumberPostProcessorForLocale({
locale: 'en-GB',
postProcessor: commaToSpaceProcessor,
});
@ -469,11 +471,11 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
expect(formatNumber(112345678)).to.equal('112 345 678');
});
it('uses `options.postProcessors` and `localize.formatNumberOptions.postProcessors`', () => {
it('uses `options.postProcessors` and `localizeManager.formatNumberOptions.postProcessors`', () => {
const postProcessors = new Map();
postProcessors.set('en-GB', commaToSpaceProcessor);
localize.setNumberPostProcessorForLocale({
localizeManager.setNumberPostProcessorForLocale({
locale: 'en-GB',
postProcessor: firstSpaceToDotProcessor,
});

View file

@ -1,5 +1,5 @@
import { expect } from '@open-wc/testing';
import { localize, formatNumberToParts } from '@lion/ui/localize.js';
import { getLocalizeManager, formatNumberToParts } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
// TODO: This is broken only in Safari 13.1.2 Wait till ci is on 13.1.3 and remove
@ -28,6 +28,8 @@ const stringifyParts =
parts => parts.map(part => part.value).join('');
describe('formatNumberToParts', () => {
const localizeManager = getLocalizeManager();
afterEach(localizeTearDown);
describe("style: 'currency symbol'", () => {
@ -114,7 +116,7 @@ describe('formatNumberToParts', () => {
it(`formats ${locale} ${amount} as "${stringifyParts(
/** @type {FormatNumberPart[]} */ (expectedResult),
)}"`, () => {
localize.locale = locale;
localizeManager.locale = locale;
expect(
formatNumberToParts(Number(amount), {
style: 'decimal',
@ -143,7 +145,7 @@ describe('formatNumberToParts', () => {
it(`formats ${locale} ${amount} as "${stringifyParts(
/** @type {FormatNumberPart[]} */ (expectedResult),
)}"`, () => {
localize.locale = locale;
localizeManager.locale = locale;
expect(
formatNumberToParts(Number(amount), {
style: 'decimal',

View file

@ -1,5 +1,5 @@
import { expect } from '@open-wc/testing';
import { getCurrencyName } from '@lion/ui/localize.js';
import { getCurrencyName } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
describe('getCurrencyName', () => {

View file

@ -1,7 +1,9 @@
import { expect } from '@open-wc/testing';
import { localize, parseNumber } from '@lion/ui/localize.js';
import { getLocalizeManager, parseNumber } from '@lion/ui/localize-no-side-effects.js';
describe('parseNumber()', () => {
const localizeManager = getLocalizeManager();
it('parses integers', () => {
expect(parseNumber('1')).to.equal(1);
expect(parseNumber('12')).to.equal(12);
@ -79,13 +81,13 @@ describe('parseNumber()', () => {
});
it('uses locale to parse amount if there is only one separator e.g. 1.234', () => {
localize.locale = 'en-GB';
localizeManager.locale = 'en-GB';
expect(parseNumber('12.34')).to.equal(12.34);
expect(parseNumber('12,34')).to.equal(1234);
expect(parseNumber('1.234')).to.equal(1.234);
expect(parseNumber('1,234')).to.equal(1234);
localize.locale = 'nl-NL';
localizeManager.locale = 'nl-NL';
expect(parseNumber('12.34')).to.equal(1234);
expect(parseNumber('12,34')).to.equal(12.34);
expect(parseNumber('1.234')).to.equal(1234);

View file

@ -0,0 +1,38 @@
import { expect } from '@open-wc/testing';
import sinon from 'sinon';
// @ts-ignore
import { singletonManager } from 'singleton-manager';
/**
* @typedef {import('../types/LocalizeMixinTypes.js').LocalizeMixin} LocalizeMixinHost
*/
describe('Entrypoints localize', () => {
/** @type {import('sinon').SinonSpy} */
let singletonManagerSetSpy;
beforeEach(() => {
singletonManagerSetSpy = sinon.spy(singletonManager, 'set');
});
afterEach(() => {
singletonManagerSetSpy.restore();
});
it('"@lion/ui/localize-no-side-effects.js" has no side effects (c.q. does not register itself on singletonManager)', async () => {
await import('@lion/ui/localize-no-side-effects.js');
expect(singletonManagerSetSpy).to.not.have.been.called;
});
it('"@lion/ui/localize.js" has side effects (c.q. registers itself on singletonManager)', async () => {
await import('@lion/ui/localize.js');
expect(singletonManagerSetSpy).to.have.been.calledOnce;
const { getLocalizeManager } = await import('@lion/ui/localize-no-side-effects.js');
expect(singletonManagerSetSpy).to.have.been.calledWith(
'@lion/ui::localize::0.x',
getLocalizeManager(),
);
});
});

View file

@ -1 +1,20 @@
export { LocalizeManager } from '../components/localize/src/LocalizeManager.js';
export { formatDate } from '../components/localize/src/date/formatDate.js';
export { getDateFormatBasedOnLocale } from '../components/localize/src/date/getDateFormatBasedOnLocale.js';
export { getMonthNames } from '../components/localize/src/date/getMonthNames.js';
export { getWeekdayNames } from '../components/localize/src/date/getWeekdayNames.js';
export { normalizeDateTime } from '../components/localize/src/date/normalizeDateTime.js';
export { parseDate } from '../components/localize/src/date/parseDate.js';
export { LocalizeMixin } from '../components/localize/src/LocalizeMixin.js';
export { formatNumber } from '../components/localize/src/number/formatNumber.js';
export { formatNumberToParts } from '../components/localize/src/number/formatNumberToParts.js';
export { getCurrencyName } from '../components/localize/src/number/getCurrencyName.js';
export { getDecimalSeparator } from '../components/localize/src/number/getDecimalSeparator.js';
export { getFractionDigits } from '../components/localize/src/number/getFractionDigits.js';
export { getGroupSeparator } from '../components/localize/src/number/getGroupSeparator.js';
export { getSeparatorsFromNumber } from '../components/localize/src/number/getSeparatorsFromNumber.js';
export { normalizeCurrencyLabel } from '../components/localize/src/number/normalizeCurrencyLabel.js';
export { parseNumber } from '../components/localize/src/number/parseNumber.js';
export { getLocale } from '../components/localize/src/utils/getLocale.js';
export { getLocalizeManager } from '../components/localize/src/getLocalizeManager.js';