import { expect, fixture as _fixture, html } from '@open-wc/testing'; import sinon from 'sinon'; import { Validator } from '@lion/form-core'; import { LionSwitch } from '@lion/switch'; import '@lion/switch/define'; /** * @typedef {import('@lion/core').TemplateResult} TemplateResult */ const IsTrue = class extends Validator { static get validatorName() { return 'IsTrue'; } execute() { return true; } }; /** * @param {LionSwitch} lionSwitchEl */ function getProtectedMembers(lionSwitchEl) { return { // @ts-ignore inputNode: lionSwitchEl._inputNode, }; } const fixture = /** @type {(arg: TemplateResult) => Promise} */ (_fixture); describe('lion-switch', () => { it('should have default "input" element', async () => { const el = await fixture(html``); expect(Array.from(el.children).find(child => child.slot === 'input')).not.to.be.false; }); it('clicking the label should toggle the checked state', async () => { const el = await fixture(html``); el._labelNode.click(); expect(el.checked).to.be.true; el._labelNode.click(); expect(el.checked).to.be.false; }); it('clicking the label should not toggle the checked state when disabled', async () => { const el = await fixture(html``); el._labelNode.click(); expect(el.checked).to.be.false; }); it('clicking the label should focus the toggle button', async () => { const el = await fixture(html``); el._labelNode.click(); expect(document.activeElement).to.equal(el._inputNode); }); it('clicking the label should not focus the toggle button when disabled', async () => { const el = await fixture(html``); el._labelNode.click(); expect(document.activeElement).to.not.equal(el._inputNode); }); it('should sync its "disabled" state to child button', async () => { const el = await fixture(html``); const { inputNode } = getProtectedMembers(el); expect(inputNode.disabled).to.be.true; expect(inputNode.hasAttribute('disabled')).to.be.true; el.disabled = false; await el.updateComplete; await el.updateComplete; // safari takes longer expect(inputNode.disabled).to.be.false; expect(inputNode.hasAttribute('disabled')).to.be.false; }); it('is hidden when attribute hidden is true', async () => { const el = await fixture(html``); expect(el).not.to.be.displayed; }); it('should sync its "checked" state to child button', async () => { const uncheckedEl = await fixture(html``); const { inputNode: uncheckeInputNode } = getProtectedMembers(uncheckedEl); const checkedEl = await fixture(html``); const { inputNode: checkeInputNode } = getProtectedMembers(checkedEl); expect(uncheckeInputNode.checked).to.be.false; expect(checkeInputNode.checked).to.be.true; uncheckedEl.checked = true; checkedEl.checked = false; await uncheckedEl.updateComplete; await checkedEl.updateComplete; expect(uncheckeInputNode.checked).to.be.true; expect(checkeInputNode.checked).to.be.false; }); it('should sync "checked" state received from child button', async () => { const el = await fixture(html``); const { inputNode } = getProtectedMembers(el); const button = inputNode; expect(el.checked).to.be.false; button.click(); expect(el.checked).to.be.true; button.click(); expect(el.checked).to.be.false; }); it('synchronizes modelValue to checked state and vice versa', async () => { const el = await fixture(html``); expect(el.checked).to.be.false; expect(el.modelValue).to.deep.equal({ checked: false, value: 'foo', }); el.checked = true; expect(el.checked).to.be.true; expect(el.modelValue).to.deep.equal({ checked: true, value: 'foo', }); }); it('should dispatch "checked-changed" event when toggled via button or label', async () => { const handlerSpy = sinon.spy(); const el = await fixture(html``); const { inputNode } = getProtectedMembers(el); el.addEventListener('checked-changed', handlerSpy); inputNode.click(); el._labelNode.click(); await el.updateComplete; expect(handlerSpy.callCount).to.equal(2); const checkCall = /** @param {import('sinon').SinonSpyCall} call */ call => { expect(call.args).to.have.lengthOf(1); const e = call.args[0]; expect(e).to.be.an.instanceof(Event); expect(e.bubbles).to.be.true; expect(e.composed).to.be.true; }; checkCall(handlerSpy.getCall(0)); checkCall(handlerSpy.getCall(1)); }); it('should dispatch "checked-changed" event when checked changed', async () => { const handlerSpy = sinon.spy(); const el = await fixture(html``); el.addEventListener('checked-changed', handlerSpy); el.checked = true; await el.updateComplete; expect(handlerSpy.callCount).to.equal(1); }); it('can be configured to show feedback messages immediately', async () => { const tagName = 'custom-switch'; if (!customElements.get(tagName)) { customElements.define( tagName, class CustomSwitch extends LionSwitch { static get validationTypes() { return [...super.validationTypes, 'info']; } /** * @param {string} type * @param {object} meta */ _showFeedbackConditionFor(type, meta) { if (type === 'info') { return true; } return super._showFeedbackConditionFor(type, meta); } }, ); } const el = await fixture( html``, ); expect(el.showsFeedbackFor).to.eql(['info']); }); });