lion/packages/core/test/EventMixin.test.js

237 lines
6.6 KiB
JavaScript

import { expect, fixture, html, defineCE } from '@open-wc/testing';
import { LionLitElement } from '../src/LionLitElement.js';
import { EventMixin } from '../src/EventMixin.js';
describe('EventMixin', () => {
before(() => {
class EventMixinSub extends LionLitElement {
static get properties() {
return {
value: {
type: 'String',
asAttribute: 'value',
},
};
}
_requestUpdate(propName) {
super._requestUpdate();
if (propName === 'value') {
this.dispatchEvent(new CustomEvent('value-changed', { bubbles: true, composed: true }));
}
}
}
customElements.define('event-mixin-sub', EventMixinSub);
/* global */
class EventMixinTag extends EventMixin(LionLitElement) {
get events() {
return {
...super.events,
_onSelfClick: [() => this, 'click'],
_onButton1Click: [() => this.$id('button1'), 'click'],
_onSub1Click: [() => this.$id('sub1'), 'click'],
_onSub1Input: [() => this.$id('sub1'), 'value-changed'],
};
}
render() {
return html`
<button id="button1">with click event</button>
<event-mixin-sub type="text" id="sub1"></event-mixin-sub>
<button id="button3">no event</button>
`;
}
constructor() {
super();
this.button1ClickCount = 0;
this.sub1ValueChangeCount = 0;
this.selfClick = 0;
}
_onButton1Click() {
this.button1ClickCount += 1;
}
_onSub1Click() {
this.$id('sub1').value = 'you clicked me';
}
_onSub1Input() {
this.sub1ValueChangeCount += 1;
}
_onSelfClick() {
this.selfClick += 1;
}
}
customElements.define('event-mixin', EventMixinTag);
});
it('can adding an event that gets triggered', async () => {
const element = await fixture(`<event-mixin></event-mixin>`);
element.$id('button1').click();
expect(element.button1ClickCount).to.equal(1);
});
it('can add events to itself', async () => {
const element = await fixture(`<event-mixin></event-mixin>`);
element.click();
expect(element.selfClick).to.equal(1);
});
it('can add events to window', async () => {
const tag = defineCE(
class extends EventMixin(HTMLElement) {
get events() {
return {
_onMyCustomEvent: [() => window, 'my-custom-event'],
};
}
_onMyCustomEvent() {
this.fired = true;
}
},
);
const element = await fixture(`<${tag}></${tag}>`);
expect(element.fired).to.equal(undefined);
window.dispatchEvent(new Event('my-custom-event'));
await element.updateComplete;
expect(element.fired).to.equal(true);
// this will clear it's state on window
delete window.__eventMixinProcessed;
});
it('supports multiple different events for a single node', async () => {
const element = await fixture(`<event-mixin></event-mixin>`);
element.$id('sub1').click();
await element.updateComplete;
expect(element.$id('sub1').value).to.equal('you clicked me');
element.$id('sub1').value = 'new';
await element.updateComplete;
expect(element.$id('sub1').value).to.equal('new');
expect(element.sub1ValueChangeCount).to.equal(2);
});
it('supports multiple different events with a single function', async () => {
class MultiEvents extends EventMixin(HTMLElement) {
get events() {
return {
doIt: [() => this.lightDomInput, ['click', 'change']],
};
}
constructor() {
super();
this.doItCounter = 0;
}
doIt() {
this.doItCounter += 1;
}
connectedCallback() {
this.lightDomInput = this.querySelector('input');
this.__registerEvents();
}
}
customElements.define('multi-events', MultiEvents);
const element = await fixture(`<multi-events><input /></multi-events>`);
expect(element.doItCounter).to.equal(0);
element.lightDomInput.click();
element.lightDomInput.value = 'foo';
element.lightDomInput.dispatchEvent(new Event('change'));
await element.updateComplete;
expect(element.doItCounter).to.equal(2);
});
it('supports multiple functions per event for a single node', async () => {
class MultiFunctions extends EventMixin(HTMLElement) {
get events() {
return {
_onClick: [() => this.lightDomButton, 'click'],
_loggging: [() => this.lightDomButton, 'click'],
};
}
_onClick() {
this.clicked = true;
}
_loggging() {
this.logged = true;
}
connectedCallback() {
this.lightDomButton = this.querySelector('button');
this.__registerEvents();
}
}
customElements.define('multi-functions', MultiFunctions);
const element = await fixture(`<multi-functions><button>click</button></multi-functions>`);
expect(element.clicked).to.equal(undefined);
expect(element.logged).to.equal(undefined);
element.lightDomButton.click();
await element.updateComplete;
expect(element.clicked).to.equal(true);
expect(element.logged).to.equal(true);
});
it('will not add same event/function multiple times to a node', async () => {
const element = await fixture(`<event-mixin></event-mixin>`);
element.__registerEvents();
element.__registerEvents();
expect(element.__eventsCache.length).to.equal(4);
});
it('will cleanup events', async () => {
// we can't test this properly as according to spec there is no way to get
// a list of attached event listeners
// in dev tools you can use getEventListeners but that is not available globally
// so we are at least testing our implementation
const element = await fixture(`<event-mixin></event-mixin>`);
element.__unregisterEvents();
expect(element.__eventsCache.length).to.equal(0);
});
it('reregisters events if dom node is moved', async () => {
const tag = defineCE(
class extends EventMixin(HTMLElement) {
get events() {
return {
_onClick: [() => this.querySelector('button'), 'click'],
};
}
constructor() {
super();
this.myCallCount = 0;
}
_onClick() {
this.myCallCount += 1;
}
},
);
const el = await fixture(`<${tag}><button>click</button></${tag}>`);
el.querySelector('button').click();
expect(el.myCallCount).to.equal(1);
const wrapper = await fixture(`<div></div>`);
wrapper.appendChild(el);
el.querySelector('button').click();
expect(el.myCallCount).to.equal(2);
});
});