import { html, LitElement } from '@lion/core'; import '@lion/fieldset/lion-fieldset.js'; import { LionInput } from '@lion/input'; import { FormGroupMixin, Required } from '@lion/form-core'; import { expect, fixture } from '@open-wc/testing'; import { ChoiceGroupMixin } from '../../src/choice-group/ChoiceGroupMixin.js'; import { ChoiceInputMixin } from '../../src/choice-group/ChoiceInputMixin.js'; describe('ChoiceGroupMixin', () => { before(() => { class ChoiceInput extends ChoiceInputMixin(LionInput) {} customElements.define('choice-group-input', ChoiceInput); class ChoiceGroup extends ChoiceGroupMixin(FormGroupMixin(LitElement)) {} customElements.define('choice-group', ChoiceGroup); class ChoiceGroupMultiple extends ChoiceGroupMixin(FormGroupMixin(LitElement)) { constructor() { super(); this.multipleChoice = true; } } customElements.define('choice-group-multiple', ChoiceGroupMultiple); }); it('has a single modelValue representing the currently checked radio value', async () => { const el = await fixture(html` `); expect(el.modelValue).to.equal('female'); el.formElements[0].checked = true; expect(el.modelValue).to.equal('male'); el.formElements[2].checked = true; expect(el.modelValue).to.equal('other'); }); it('has a single formattedValue representing the currently checked radio value', async () => { const el = await fixture(html` `); expect(el.formattedValue).to.equal('female'); el.formElements[0].checked = true; expect(el.formattedValue).to.equal('male'); el.formElements[2].checked = true; expect(el.formattedValue).to.equal('other'); }); it('throws if a child element without a modelValue like { value: "foo", checked: false } tries to register', async () => { const el = await fixture(html` `); const invalidChild = await fixture(html` `); expect(() => { el.addFormElement(invalidChild); }).to.throw( 'The choice-group name="gender" does not allow to register choice-group-input with .modelValue="Lara" - The modelValue should represent an Object { value: "foo", checked: false }', ); }); it('automatically sets the name property of child radios to its own name', async () => { const el = await fixture(html` `); expect(el.formElements[0].name).to.equal('gender'); expect(el.formElements[1].name).to.equal('gender'); const validChild = await fixture(html` `); el.appendChild(validChild); expect(el.formElements[2].name).to.equal('gender'); }); it('throws if a child element with a different name than the group tries to register', async () => { const el = await fixture(html` `); const invalidChild = await fixture(html` `); expect(() => { el.addFormElement(invalidChild); }).to.throw( 'The choice-group name="gender" does not allow to register choice-group-input with custom names (name="foo" given)', ); }); it('can set initial modelValue on creation', async () => { const el = await fixture(html` `); expect(el.modelValue).to.equal('other'); expect(el.formElements[2].checked).to.be.true; }); it('can set initial serializedValue on creation', async () => { const el = await fixture(html` `); expect(el.serializedValue).to.equal('other'); expect(el.formElements[2].checked).to.be.true; }); it('can set initial formattedValue on creation', async () => { const el = await fixture(html` `); expect(el.formattedValue).to.equal('other'); expect(el.formElements[2].checked).to.be.true; }); it('can handle complex data via choiceValue', async () => { const date = new Date(2018, 11, 24, 10, 33, 30, 0); const el = await fixture(html` `); expect(el.modelValue).to.equal(date); el.formElements[0].checked = true; expect(el.modelValue).to.deep.equal({ some: 'data' }); }); it('can handle 0 and empty string as valid values', async () => { const el = await fixture(html` `); expect(el.modelValue).to.equal(0); el.formElements[1].checked = true; expect(el.modelValue).to.equal(''); }); it('can check a radio by supplying an available modelValue', async () => { const el = await fixture(html` `); expect(el.modelValue).to.equal('female'); el.modelValue = 'other'; expect(el.formElements[2].checked).to.be.true; }); it('expect child nodes to only fire one model-value-changed event per instance', async () => { let counter = 0; const el = await fixture(html` { counter += 1; }} > `); counter = 0; // reset after setup which may result in different results el.formElements[0].checked = true; expect(counter).to.equal(1); // male becomes checked, female becomes unchecked // not changed values trigger no event el.formElements[0].checked = true; expect(counter).to.equal(1); el.formElements[2].checked = true; expect(counter).to.equal(2); // other becomes checked, male becomes unchecked // not found values trigger no event el.modelValue = 'foo'; expect(counter).to.equal(2); el.modelValue = 'male'; expect(counter).to.equal(3); // male becomes checked, other becomes unchecked }); it('can be required', async () => { const el = await fixture(html` `); expect(el.hasFeedbackFor).to.include('error'); expect(el.validationStates).to.have.a.property('error'); expect(el.validationStates.error).to.have.a.property('Required'); el.formElements[0].checked = true; expect(el.hasFeedbackFor).not.to.include('error'); expect(el.validationStates).to.have.a.property('error'); expect(el.validationStates.error).not.to.have.a.property('Required'); el.formElements[1].checked = true; expect(el.hasFeedbackFor).not.to.include('error'); expect(el.validationStates).to.have.a.property('error'); expect(el.validationStates.error).not.to.have.a.property('Required'); }); it('returns serialized value', async () => { const el = await fixture(html` `); el.formElements[0].checked = true; expect(el.serializedValue).to.deep.equal('male'); }); it('returns serialized value on unchecked state', async () => { const el = await fixture(html` `); expect(el.serializedValue).to.deep.equal(''); }); describe('multipleChoice', () => { it('has a single modelValue representing all currently checked values', async () => { const el = await fixture(html` `); expect(el.modelValue).to.eql(['female']); el.formElements[0].checked = true; expect(el.modelValue).to.eql(['male', 'female']); el.formElements[2].checked = true; expect(el.modelValue).to.eql(['male', 'female', 'other']); }); it('has a single serializedValue representing all currently checked values', async () => { const el = await fixture(html` `); expect(el.serializedValue).to.eql(['female']); el.formElements[0].checked = true; expect(el.serializedValue).to.eql(['male', 'female']); el.formElements[2].checked = true; expect(el.serializedValue).to.eql(['male', 'female', 'other']); }); it('has a single formattedValue representing all currently checked values', async () => { const el = await fixture(html` `); expect(el.formattedValue).to.eql(['female']); el.formElements[0].checked = true; expect(el.formattedValue).to.eql(['male', 'female']); el.formElements[2].checked = true; expect(el.formattedValue).to.eql(['male', 'female', 'other']); }); it('can check multiple checkboxes by setting the modelValue', async () => { const el = await fixture(html` `); el.modelValue = ['male', 'other']; expect(el.modelValue).to.eql(['male', 'other']); expect(el.formElements[0].checked).to.be.true; expect(el.formElements[2].checked).to.be.true; }); it('unchecks non-matching checkboxes when setting the modelValue', async () => { const el = await fixture(html` `); expect(el.modelValue).to.eql(['male', 'other']); expect(el.formElements[0].checked).to.be.true; expect(el.formElements[2].checked).to.be.true; el.modelValue = ['female']; expect(el.formElements[0].checked).to.be.false; expect(el.formElements[1].checked).to.be.true; expect(el.formElements[2].checked).to.be.false; }); }); describe('Integration with a parent form/fieldset', () => { it('will serialize all children with their serializedValue', async () => { const el = await fixture(html` `); expect(el.serializedValue).to.eql({ gender: 'female', }); const choiceGroupEl = el.querySelector('[name="gender"]'); choiceGroupEl.multipleChoice = true; expect(el.serializedValue).to.eql({ gender: ['female'], }); }); }); });