chore(@lion/ui): all tests side effect free wrt localize

This commit is contained in:
Thijs Louisse 2023-02-01 10:19:16 +01:00 committed by Thijs Louisse
parent 467ba6bf0b
commit cee40e5588
7 changed files with 89 additions and 20 deletions

View file

@ -0,0 +1,61 @@
---
'@lion/ui': minor
---
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
Also see: https://github.com/ing-bank/lion/discussions/1861
Use it like this:
```js
function myFunction() {
// note that 'localizeManager' is the same as former 'localize'
const localizeManager = 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
export function myFn() {
const localizeManager = getLocalizeManager();
// ...
}
export class myClass() {
constructor() {
this._localizeManager = getLocalizeManager();
// ...
}
}
```

View file

@ -1,5 +1,5 @@
import { html } from 'lit'; import { html } from 'lit';
import { localize } from '@lion/ui/localize.js'; import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
import { expect, fixture as _fixture } from '@open-wc/testing'; import { expect, fixture as _fixture } from '@open-wc/testing';
import sinon from 'sinon'; import sinon from 'sinon';
@ -15,6 +15,8 @@ import { CalendarObject, DayObject } from '@lion/ui/calendar-test-helpers.js';
const fixture = /** @type {(arg: TemplateResult) => Promise<LionCalendar>} */ (_fixture); const fixture = /** @type {(arg: TemplateResult) => Promise<LionCalendar>} */ (_fixture);
describe('<lion-calendar>', () => { describe('<lion-calendar>', () => {
const localizeManager = getLocalizeManager();
beforeEach(() => { beforeEach(() => {
localizeTearDown(); localizeTearDown();
}); });
@ -1348,7 +1350,7 @@ describe('<lion-calendar>', () => {
await el.updateComplete; await el.updateComplete;
expect(elObj.activeMonth).to.equal('décembre'); expect(elObj.activeMonth).to.equal('décembre');
localize.locale = 'cs-CZ'; localizeManager.locale = 'cs-CZ';
await el.updateComplete; await el.updateComplete;
expect(elObj.activeMonth).to.equal('décembre'); expect(elObj.activeMonth).to.equal('décembre');
@ -1391,7 +1393,7 @@ describe('<lion-calendar>', () => {
'Sat', 'Sat',
]); ]);
localize.locale = 'nl-NL'; localizeManager.locale = 'nl-NL';
await el.localizeNamespacesLoaded; await el.localizeNamespacesLoaded;
await el.updateComplete; await el.updateComplete;
expect(elObj.nextMonthButtonEl?.getAttribute('aria-label')).to.equal( expect(elObj.nextMonthButtonEl?.getAttribute('aria-label')).to.equal(

View file

@ -2,7 +2,7 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { Required, Validator } from '@lion/ui/form-core.js'; import { Required, Validator } from '@lion/ui/form-core.js';
import '@lion/ui/define/lion-field.js'; import '@lion/ui/define/lion-field.js';
import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js'; import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js';
import { localize } from '@lion/ui/localize.js'; import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
import { import {
expect, expect,
@ -52,6 +52,8 @@ function getSlot(el, slot) {
} }
describe('<lion-field>', () => { describe('<lion-field>', () => {
const localizeManager = getLocalizeManager();
it(`puts a unique id "${tagString}-[hash]" on the native input`, async () => { it(`puts a unique id "${tagString}-[hash]" on the native input`, async () => {
const el = /** @type {LionField} */ (await fixture(html`<${tag}>${inputSlot}</${tag}>`)); const el = /** @type {LionField} */ (await fixture(html`<${tag}>${inputSlot}</${tag}>`));
// @ts-ignore allow protected accessors in tests // @ts-ignore allow protected accessors in tests
@ -219,7 +221,7 @@ describe('<lion-field>', () => {
beforeEach(() => { beforeEach(() => {
// Reset and preload validation translations // Reset and preload validation translations
localizeTearDown(); localizeTearDown();
localize.addData('en-GB', 'lion-validate', { localizeManager.addData('en-GB', 'lion-validate', {
error: { error: {
hasX: 'This is error message for hasX', hasX: 'This is error message for hasX',
}, },

View file

@ -1,12 +1,13 @@
import { DefaultSuccess, Required, Validator } from '@lion/ui/form-core.js'; import { DefaultSuccess, Required, Validator } from '@lion/ui/form-core.js';
import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js'; import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js';
import { LionInput } from '@lion/ui/input.js'; import { LionInput } from '@lion/ui/input.js';
import { localize } from '@lion/ui/localize.js'; import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { loadDefaultFeedbackMessages } from '@lion/ui/validate-messages.js'; import { loadDefaultFeedbackMessages } from '@lion/ui/validate-messages.js';
import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing'; import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
import sinon from 'sinon'; import sinon from 'sinon';
describe('Form Validation Integrations', () => { describe('Form Validation Integrations', () => {
const localizeManager = getLocalizeManager();
const lightDom = ''; const lightDom = '';
before(() => { before(() => {
loadDefaultFeedbackMessages(); loadDefaultFeedbackMessages();
@ -126,11 +127,11 @@ describe('Form Validation Integrations', () => {
} }
async updateLabel() { async updateLabel() {
this.label = localize.msg('test-default-label:label'); this.label = localizeManager.msg('test-default-label:label');
} }
async setDefaultLabel() { async setDefaultLabel() {
localize.loadNamespace({ localizeManager.loadNamespace({
'test-default-label': /** @param {string} locale */ async locale => { 'test-default-label': /** @param {string} locale */ async locale => {
switch (locale) { switch (locale) {
case 'nl-NL': case 'nl-NL':
@ -143,11 +144,11 @@ describe('Form Validation Integrations', () => {
this.boundUpdateLabel = this.updateLabel.bind(this); this.boundUpdateLabel = this.updateLabel.bind(this);
// localeChanged is fired AFTER localize has finished loading missing translations // localeChanged is fired AFTER localize has finished loading missing translations
// so no need to await localize.loadingComplete // so no need to await localizeManager.loadingComplete
localize.addEventListener('localeChanged', this.boundUpdateLabel); localizeManager.addEventListener('localeChanged', this.boundUpdateLabel);
// Wait for it to complete when updating the label for the first time // Wait for it to complete when updating the label for the first time
await localize.loadingComplete; await localizeManager.loadingComplete;
this.boundUpdateLabel(); this.boundUpdateLabel();
} }
} }
@ -167,15 +168,15 @@ describe('Form Validation Integrations', () => {
const { _feedbackNode } = getFormControlMembers(el); const { _feedbackNode } = getFormControlMembers(el);
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Please enter a(n) Text.'); expect(_feedbackNode.feedbackData?.[0].message).to.equal('Please enter a(n) Text.');
localize.locale = 'nl-NL'; localizeManager.locale = 'nl-NL';
await localize.loadingComplete; await localizeManager.loadingComplete;
await el.updateComplete; await el.updateComplete;
await el.feedbackComplete; await el.feedbackComplete;
expect(el.label).to.equal('Tekst'); expect(el.label).to.equal('Tekst');
expect(_feedbackNode.feedbackData?.[0].message).to.equal('Vul een Tekst in.'); expect(_feedbackNode.feedbackData?.[0].message).to.equal('Vul een Tekst in.');
localize.locale = 'en-GB'; localizeManager.locale = 'en-GB';
await localize.loadingComplete; await localizeManager.loadingComplete;
await el.updateComplete; await el.updateComplete;
await el.feedbackComplete; await el.feedbackComplete;
expect(el.label).to.equal('Text'); expect(el.label).to.equal('Text');

View file

@ -1,5 +1,5 @@
import { html } from 'lit'; import { html } from 'lit';
import { localize } from '@lion/ui/localize.js'; import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
import { MaxDate } from '@lion/ui/form-core.js'; import { MaxDate } from '@lion/ui/form-core.js';
import { expect, fixture as _fixture } from '@open-wc/testing'; import { expect, fixture as _fixture } from '@open-wc/testing';
@ -13,6 +13,8 @@ import '@lion/ui/define/lion-input-date.js';
const fixture = /** @type {(arg: TemplateResult) => Promise<LionInputDate>} */ (_fixture); const fixture = /** @type {(arg: TemplateResult) => Promise<LionInputDate>} */ (_fixture);
describe('<lion-input-date>', () => { describe('<lion-input-date>', () => {
const localizeManager = getLocalizeManager();
beforeEach(() => { beforeEach(() => {
localizeTearDown(); localizeTearDown();
}); });
@ -84,13 +86,13 @@ describe('<lion-input-date>', () => {
}); });
it('uses global locale when formatOptions.locale is not defined', async () => { it('uses global locale when formatOptions.locale is not defined', async () => {
localize.locale = 'fr-FR'; localizeManager.locale = 'fr-FR';
const el = await fixture(html` const el = await fixture(html`
<lion-input-date .modelValue=${new Date('2017/06/15')}></lion-input-date> <lion-input-date .modelValue=${new Date('2017/06/15')}></lion-input-date>
`); `);
expect(el.formattedValue).to.equal('15/06/2017'); expect(el.formattedValue).to.equal('15/06/2017');
localize.locale = 'en-US'; localizeManager.locale = 'en-US';
const el2 = await fixture(html` const el2 = await fixture(html`
<lion-input-date .modelValue=${new Date('2017/06/15')}></lion-input-date> <lion-input-date .modelValue=${new Date('2017/06/15')}></lion-input-date>
`); `);
@ -105,7 +107,7 @@ describe('<lion-input-date>', () => {
></lion-input-date> ></lion-input-date>
`); `);
expect(el.formattedValue).to.equal('15/06/2017'); // british expect(el.formattedValue).to.equal('15/06/2017'); // british
localize.locale = 'en-US'; localizeManager.locale = 'en-US';
await el.updateComplete; await el.updateComplete;
expect(el.formattedValue).to.equal('15/06/2017'); // should stay british expect(el.formattedValue).to.equal('15/06/2017'); // should stay british
}); });

View file

@ -16,7 +16,7 @@ import { LocalizeManager } from './LocalizeManager.js';
* ```js * ```js
* function myFunction() { * function myFunction() {
* // note that 'localizeManager' is the same as former 'localize' * // note that 'localizeManager' is the same as former 'localize'
* const localize = getLocalizeManger(); * const localizeManager = getLocalizeManger();
* // ... * // ...
* } * }
* ``` * ```

View file

@ -6,6 +6,7 @@ import { getLocalizeManager } from '../src/getLocalizeManager.js';
describe('getLocalizeManager', () => { describe('getLocalizeManager', () => {
beforeEach(() => { beforeEach(() => {
// @ts-ignore
singletonManager._map.clear(); singletonManager._map.clear();
}); });