import { expect, fixture, html, defineCE, unsafeStatic } from '@open-wc/testing'; import { LitElement, SlotMixin } from '@lion/core'; import { FormControlMixin } from '../src/FormControlMixin.js'; describe('FormControlMixin', () => { const inputSlot = ''; let elem; let tag; before(async () => { const FormControlMixinClass = class extends FormControlMixin(SlotMixin(LitElement)) { static get properties() { return { modelValue: { type: String, }, }; } }; elem = defineCE(FormControlMixinClass); tag = unsafeStatic(elem); }); it('has a label', async () => { const elAttr = await fixture(html` <${tag} label="Email address">${inputSlot} `); expect(elAttr.label).to.equal('Email address', 'as an attribute'); const elProp = await fixture(html` <${tag} .label=${'Email address'} >${inputSlot} `); expect(elProp.label).to.equal('Email address', 'as a property'); const elElem = await fixture(html` <${tag}> ${inputSlot} `); expect(elElem.label).to.equal('Email address', 'as an element'); }); it('has a label that supports inner html', async () => { const el = await fixture(html` <${tag}> ${inputSlot} `); expect(el.label).to.equal('Email address'); }); it('only takes label of direct child', async () => { const el = await fixture(html` <${tag}> <${tag} label="Email address"> ${inputSlot} `); expect(el.label).to.equal(''); }); it('can have a help-text', async () => { const elAttr = await fixture(html` <${tag} help-text="We will not send you any spam">${inputSlot} `); expect(elAttr.helpText).to.equal('We will not send you any spam', 'as an attribute'); const elProp = await fixture(html` <${tag} .helpText=${'We will not send you any spam'} >${inputSlot} `); expect(elProp.helpText).to.equal('We will not send you any spam', 'as a property'); const elElem = await fixture(html` <${tag}>
We will not send you any spam
${inputSlot} `); expect(elElem.helpText).to.equal('We will not send you any spam', 'as an element'); }); it('can have a help-text that supports inner html', async () => { const el = await fixture(html` <${tag}>
We will not send you any spam
${inputSlot} `); expect(el.helpText).to.equal('We will not send you any spam'); }); it('only takes help-text of direct child', async () => { const el = await fixture(html` <${tag}> <${tag} help-text="We will not send you any spam"> ${inputSlot} `); expect(el.helpText).to.equal(''); }); it('does not duplicate aria-describedby and aria-labelledby ids', async () => { const lionField = await fixture(` <${elem} help-text="This element will be disconnected/reconnected">${inputSlot} `); const wrapper = await fixture(`
`); lionField.parentElement.appendChild(wrapper); wrapper.appendChild(lionField); await wrapper.updateComplete; ['aria-describedby', 'aria-labelledby'].forEach(ariaAttributeName => { const ariaAttribute = Array.from(lionField.children) .find(child => child.slot === 'input') .getAttribute(ariaAttributeName) .trim() .split(' '); const hasDuplicate = !!ariaAttribute.find((el, i) => ariaAttribute.indexOf(el) !== i); expect(hasDuplicate).to.be.false; }); }); it('internally sorts aria-describedby and aria-labelledby ids', async () => { const wrapper = await fixture(html`
should go after input internals
should go after input internals
<${tag}>
Added to description by default
should go after input internals
should go after input internals
`); const el = wrapper.querySelector(elem); const { _inputNode } = el; // 1. addToAriaLabelledBy() // external inputs should go in order defined by user el.addToAriaLabelledBy(wrapper.querySelector('#additionalLabelB')); el.addToAriaLabelledBy(wrapper.querySelector('#additionalLabelA')); expect( _inputNode.getAttribute('aria-labelledby').indexOf(`label-${el._inputId}`) < _inputNode.getAttribute('aria-labelledby').indexOf('additionalLabelB') < _inputNode.getAttribute('aria-labelledby').indexOf('additionalLabelA'), ); // 2. addToAriaDescribedBy() // Check if the aria attr is filled initially el.addToAriaDescribedBy(wrapper.querySelector('#additionalDescriptionB')); el.addToAriaDescribedBy(wrapper.querySelector('#additionalDescriptionA')); // Should be placed in the end expect( _inputNode.getAttribute('aria-describedby').indexOf(`feedback-${el._inputId}`) < _inputNode.getAttribute('aria-describedby').indexOf('additionalDescriptionB') < _inputNode.getAttribute('aria-describedby').indexOf('additionalDescriptionA'), ); }); it('adds aria-live="polite" to the feedback slot', async () => { const lionField = await fixture(html` <${tag}> ${inputSlot}
Added to see attributes
`); expect( Array.from(lionField.children) .find(child => child.slot === 'feedback') .getAttribute('aria-live'), ).to.equal('polite'); }); });