lion/packages/ui/components/input-amount-dropdown/test/LionInputAmountDropdown.test.js
Robin Van Roy 57800c4501
chore: adds lion-input-amount-dropdown (#2505)
Co-authored-by: gerjanvangeest <Gerjan.van.Geest@ing.com>
2025-08-13 14:40:57 +02:00

199 lines
7.6 KiB
JavaScript

import { mimicUserChangingDropdown } from '@lion/ui/input-amount-dropdown-test-helpers.js';
import { runInputAmountDropdownSuite } from '@lion/ui/input-amount-dropdown-test-suites.js';
import { LionInputAmountDropdown } from '@lion/ui/input-amount-dropdown.js';
import { aTimeout, expect, fixture } from '@open-wc/testing';
import { LionSelectRich } from '@lion/ui/select-rich.js';
import { repeat } from 'lit/directives/repeat.js';
import { LionOption } from '@lion/ui/listbox.js';
import { ref } from 'lit/directives/ref.js';
import { html } from 'lit';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
import { ScopedElementsMixin } from '../../core/src/ScopedElementsMixin.js';
import '@lion/ui/define/lion-input-amount-dropdown.js';
/**
* @typedef {import('../types/index.js').TemplateDataForDropdownInputAmount} TemplateDataForDropdownInputAmount
* @typedef {HTMLSelectElement|HTMLElement & {modelValue:string}} DropdownElement
* @typedef {import('../types/index.js').RegionMeta} RegionMeta
* @typedef {import('lit').TemplateResult} TemplateResult
*/
class WithFormControlInputAmountDropdown extends ScopedElementsMixin(LionInputAmountDropdown) {
/**
* @configure ScopedElementsMixin
*/
static scopedElements = {
...super.scopedElements,
'lion-select-rich': LionSelectRich,
'lion-option': LionOption,
};
static templates = {
...(super.templates || {}),
/**
* @param {TemplateDataForDropdownInputAmount} templateDataForDropdown
*/
dropdown: templateDataForDropdown => {
const { refs, data } = templateDataForDropdown;
// TODO: once spread directive available, use it per ref (like ref(refs?.dropdown?.ref))
return html`
<lion-select-rich
${ref(refs?.dropdown?.ref)}
label="${refs?.dropdown?.labels?.country}"
label-sr-only
@model-value-changed="${refs?.dropdown?.listeners['model-value-changed']}"
style="${refs?.dropdown?.props?.style}"
>
${repeat(
data.regionMetaList,
regionMeta => regionMeta.currencyCode,
regionMeta => html`
<lion-option .choiceValue="${regionMeta.currencyCode}"> </lion-option>
`,
)}
</lion-select-rich>
`;
},
};
}
runInputAmountDropdownSuite();
describe('WithFormControlInputAmountDropdown', () => {
// @ts-expect-error
// Runs it for LionSelectRich, which uses .modelValue/@model-value-changed instead of .value/@change
runInputAmountDropdownSuite({ klass: WithFormControlInputAmountDropdown });
it('focuses the textbox right after selection if selected via opened dropdown if interaction-mode is mac', async () => {
class InputAmountDropdownMac extends LionInputAmountDropdown {
static templates = {
...(super.templates || {}),
/**
* @param {TemplateDataForDropdownInputAmount} templateDataForDropdown
*/
dropdown: templateDataForDropdown => {
const { refs, data } = templateDataForDropdown;
// TODO: once spread directive available, use it per ref (like ref(refs?.dropdown?.ref))
return html`
<lion-select-rich
${ref(refs?.dropdown?.ref)}
label="${refs?.dropdown?.labels?.country}"
label-sr-only
@model-value-changed="${refs?.dropdown?.listeners['model-value-changed']}"
style="${refs?.dropdown?.props?.style}"
interaction-mode="mac"
>
${repeat(
data.regionMetaList,
regionMeta => regionMeta.currencyCode,
regionMeta => html`
<lion-option .choiceValue="${regionMeta.currencyCode}"> </lion-option>
`,
)}
</lion-select-rich>
`;
},
};
}
customElements.define('input-amount-dropdown-mac', InputAmountDropdownMac);
const el = /** @type {LionInputAmountDropdown} */ (
await fixture(html`
<input-amount-dropdown-mac
.allowedCurrencies="${['GBP', 'EUR']}"
.modelValue="{ currency: 'GBP', amount: '123' }"
></input-amount-dropdown-mac>
`)
);
const dropdownElement = el.refs.dropdown.value;
// @ts-expect-error [allow-protected-in-tests]
if (dropdownElement?._overlayCtrl) {
// @ts-expect-error [allow-protected-in-tests]
dropdownElement._overlayCtrl.show();
mimicUserChangingDropdown(dropdownElement, 'EUR');
await el.updateComplete;
await aTimeout(0);
// @ts-expect-error [allow-protected-in-tests]
expect(isActiveElement(el._inputNode)).to.be.true;
}
});
it('does not focus the textbox right after selection if selected via opened dropdown if interaction-mode is windows/linux', async () => {
class InputAmountDropdownWindows extends LionInputAmountDropdown {
static templates = {
...(super.templates || {}),
/**
* @param {TemplateDataForDropdownInputAmount} templateDataForDropdown
*/
dropdown: templateDataForDropdown => {
const { refs, data } = templateDataForDropdown;
// TODO: once spread directive available, use it per ref (like ref(refs?.dropdown?.ref))
return html`
<lion-select-rich
${ref(refs?.dropdown?.ref)}
label="${refs?.dropdown?.labels?.country}"
label-sr-only
@model-value-changed="${refs?.dropdown?.listeners['model-value-changed']}"
style="${refs?.dropdown?.props?.style}"
interaction-mode="windows/linux"
>
${repeat(
data.regionMetaList,
regionMeta => regionMeta.currencyCode,
regionMeta => html`
<lion-option .choiceValue="${regionMeta.currencyCode}"> </lion-option>
`,
)}
</lion-select-rich>
`;
},
};
}
customElements.define('input-amount-dropdown-windows', InputAmountDropdownWindows);
const el = /** @type {LionInputAmountDropdown} */ (
await fixture(html`
<input-amount-dropdown-windows
.allowedCurrencies="${['GBP', 'EUR']}"
.modelValue="{ currency: 'GBP', amount: '123' }"
></input-amount-dropdown-windows>
`)
);
const dropdownElement = el.refs.dropdown.value;
// @ts-expect-error [allow-protected-in-tests]
if (dropdownElement?._overlayCtrl) {
// @ts-expect-error [allow-protected-in-tests]
dropdownElement._overlayCtrl.show();
mimicUserChangingDropdown(dropdownElement, 'EUR');
await el.updateComplete;
await aTimeout(0);
// @ts-expect-error [allow-protected-in-tests]
expect(isActiveElement(el._inputNode)).to.be.false;
}
});
describe('defaultValidators', () => {
it('without interaction are not called', async () => {
const el = /** @type {LionInputAmountDropdown} */ (
await fixture(html`
<lion-input-amount-dropdown .allowedCurrencies="${['EUR']}"></lion-input-amount-dropdown>
`)
);
await aTimeout(0);
expect(el.hasFeedbackFor).to.deep.equal([]);
});
it('with interaction are called', async () => {
const el = /** @type {LionInputAmountDropdown} */ (
await fixture(html`
<lion-input-amount-dropdown
.allowedCurrencies="${['GBP', 'EUR']}"
></lion-input-amount-dropdown>
`)
);
el.modelValue = { currency: 'EUR' };
await aTimeout(0);
el.modelValue = { currency: 'EUR', amount: '' };
expect(el.hasFeedbackFor).to.deep.equal(['error']);
});
});
});