lion/packages/form-integrations/test/model-value-event.test.js

153 lines
5.6 KiB
JavaScript

import '@lion/fieldset/define';
import '@lion/input/define';
import { expect, html, fixture } from '@open-wc/testing';
// eslint-disable-next-line import/no-extraneous-dependencies
import sinon from 'sinon';
/**
* @typedef {import('@lion/input').LionInput} LionInput
* @typedef {import('@lion/fieldset').LionFieldset} LionFieldset
* @typedef {import('@lion/core').TemplateResult} TemplateResult
*/
const inputFixture = /** @type {(arg: TemplateResult) => Promise<LionInput>} */ (fixture);
const fieldsetFixture = /** @type {(arg: TemplateResult) => Promise<LionFieldset>} */ (fixture);
describe('model value event', () => {
describe('form path', () => {
it('should be property', async () => {
const spy = sinon.spy();
const input = await inputFixture(html`<lion-input></lion-input>`);
input.addEventListener('model-value-changed', spy);
input.modelValue = 'woof';
const e = spy.firstCall.args[0];
expect(e.detail).to.have.property('formPath');
});
it('should contain dispatching field', async () => {
const spy = sinon.spy();
const input = await inputFixture(html`<lion-input></lion-input>`);
input.addEventListener('model-value-changed', spy);
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input]);
});
it('should contain field and group', async () => {
const spy = sinon.spy();
const fieldset = await fieldsetFixture(html`
<lion-fieldset name="fieldset">
<lion-input name="input"></lion-input>
</lion-fieldset>
`);
await fieldset.registrationComplete;
fieldset.addEventListener('model-value-changed', spy);
const input = /** @type {LionInput} */ (fieldset.querySelector('lion-input'));
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input, fieldset]);
});
it('should contain deep elements', async () => {
const spy = sinon.spy();
const grandparent = await fieldsetFixture(html`
<lion-fieldset name="grandparent">
<lion-fieldset name="parent">
<lion-input name="input"></lion-input>
</lion-fieldset>
</lion-fieldset>
`);
const parent = /** @type {LionFieldset} */ (grandparent.querySelector('[name=parent]'));
const input = /** @type {LionInput} */ (grandparent.querySelector('[name=input]'));
await grandparent.registrationComplete;
await parent.registrationComplete;
grandparent.addEventListener('model-value-changed', spy);
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input, parent, grandparent]);
});
it('should ignore elements that are not fields or fieldsets', async () => {
const spy = sinon.spy();
const grandparent = await fieldsetFixture(html`
<lion-fieldset name="grandparent">
<div>
<lion-fieldset name="parent">
<div>
<div>
<lion-input name="input"></lion-input>
</div>
</div>
</lion-fieldset>
</div>
</lion-fieldset>
`);
const parent = /** @type {LionFieldset} */ (grandparent.querySelector('[name=parent]'));
const input = /** @type {LionInput} */ (grandparent.querySelector('[name=input]'));
await grandparent.registrationComplete;
await parent.registrationComplete;
grandparent.addEventListener('model-value-changed', spy);
input.modelValue = 'foo';
const e = spy.firstCall.args[0];
expect(e.detail.formPath).to.eql([input, parent, grandparent]);
});
});
describe('signature', () => {
/** @type {?} */
let e;
beforeEach(async () => {
const spy = sinon.spy();
const el = await inputFixture(html`<lion-input></lion-input>`);
el.addEventListener('model-value-changed', spy);
el.modelValue = 'foo';
// eslint-disable-next-line prefer-destructuring
e = spy.firstCall.args[0];
});
// TODO: Re-enable at some point...
// In my opinion (@CubLion) we should not bubble events.
// Instead each parent should explicitly listen to children events,
// and then re-dispatch on themselves.
it.skip('should not bubble', async () => {
expect(e.bubbles).to.be.false;
});
it('should not leave shadow boundary', async () => {
expect(e.composed).to.be.false;
});
});
describe('propagation', () => {
it('should dispatch different event at each level', async () => {
const grandparent = await fieldsetFixture(html`
<lion-fieldset name="grandparent">
<lion-fieldset name="parent">
<lion-input name="input"></lion-input>
</lion-fieldset>
</lion-fieldset>
`);
const parent = /** @type {LionFieldset} */ (grandparent.querySelector('[name="parent"]'));
const input = /** @type {LionInput} */ (grandparent.querySelector('[name="input"]'));
await grandparent.registrationComplete;
await parent.registrationComplete;
/** @type {sinon.SinonSpy[]} */
const spies = [];
[grandparent, parent, input].forEach(element => {
const spy = sinon.spy();
spies.push(spy);
element.addEventListener('model-value-changed', spy);
});
input.modelValue = 'foo';
spies.forEach((spy, index) => {
const currentEvent = spy.firstCall.args[0];
for (let i = index + 1; i < spies.length; i += 1) {
const nextEvent = spies[i].firstCall.args[0];
expect(currentEvent).not.to.eql(nextEvent);
}
});
});
});
});