diff --git a/packages/button/src/LionButton.js b/packages/button/src/LionButton.js
index af4b6ca23..349d4e69d 100644
--- a/packages/button/src/LionButton.js
+++ b/packages/button/src/LionButton.js
@@ -152,9 +152,14 @@ export class LionButton extends DelegateMixin(SlotMixin(LionLitElement)) {
this.__teardownDelegation();
}
- __clickDelegationHandler(e) {
- e.stopPropagation(); // prevent click on the fake element and cause click on the native button
- this.$$slot('_button').click();
+ /**
+ * Prevent click on the fake element and cause click on the native button.
+ */
+ __clickDelegationHandler(oldEvent) {
+ oldEvent.stopPropagation();
+ // replacing `MouseEvent` with `oldEvent.constructor` breaks IE
+ const newEvent = new MouseEvent(oldEvent.type, oldEvent);
+ this.$$slot('_button').dispatchEvent(newEvent);
}
__setupDelegation() {
@@ -180,7 +185,7 @@ export class LionButton extends DelegateMixin(SlotMixin(LionLitElement)) {
if (e.keyCode === 32 /* space */ || e.keyCode === 13 /* enter */) {
e.preventDefault();
this.shadowRoot.querySelector('.btn').removeAttribute('active');
- this.$$slot('_button').click();
+ this.shadowRoot.querySelector('.click-area').click();
}
}
diff --git a/packages/button/test/lion-button.test.js b/packages/button/test/lion-button.test.js
index 76eaca804..44c76af5c 100644
--- a/packages/button/test/lion-button.test.js
+++ b/packages/button/test/lion-button.test.js
@@ -1,9 +1,20 @@
-import { expect, fixture, html, aTimeout } from '@open-wc/testing';
+import { expect, fixture, html, aTimeout, oneEvent } from '@open-wc/testing';
import sinon from 'sinon';
-import { pressEnter, pressSpace } from '@polymer/iron-test-helpers/mock-interactions.js';
+import {
+ makeMouseEvent,
+ pressEnter,
+ pressSpace,
+} from '@polymer/iron-test-helpers/mock-interactions.js';
import '../lion-button.js';
+function getTopElement(el) {
+ const { left, top } = el.getBoundingClientRect();
+ // to support elementFromPoint() in polyfilled browsers we have to use document
+ const crossBrowserRoot = el.shadowRoot.elementFromPoint ? el.shadowRoot : document;
+ return crossBrowserRoot.elementFromPoint(left, top);
+}
+
describe('lion-button', () => {
it('behaves like native `button` in terms of a11y', async () => {
const el = await fixture(`foo`);
@@ -99,11 +110,7 @@ describe('lion-button', () => {
`);
const button = form.querySelector('lion-button');
- const { left, top } = button.getBoundingClientRect();
- // to support elementFromPoint() in polyfilled browsers we have to use document
- const crossBrowserRoot = button.shadowRoot.elementFromPoint ? button.shadowRoot : document;
- const shadowClickAreaElement = crossBrowserRoot.elementFromPoint(left, top);
- shadowClickAreaElement.click();
+ getTopElement(button).click();
expect(formSubmitSpy.called).to.be.true;
});
@@ -138,4 +145,62 @@ describe('lion-button', () => {
expect(formSubmitSpy.called).to.be.true;
});
});
+
+ describe('click event', () => {
+ it('is fired once', async () => {
+ const clickSpy = sinon.spy();
+ const el = await fixture(
+ html`
+
+ `,
+ );
+
+ getTopElement(el).click();
+
+ // trying to wait for other possible redispatched events
+ await aTimeout();
+ await aTimeout();
+
+ expect(clickSpy.callCount).to.equal(1);
+ });
+
+ describe('event after redispatching', async () => {
+ async function prepareClickEvent(el, host) {
+ setTimeout(() => {
+ if (host) {
+ // click on host like in native button
+ makeMouseEvent('click', { x: 11, y: 11 }, el);
+ } else {
+ // click on click-area which is then redispatched
+ makeMouseEvent('click', { x: 11, y: 11 }, getTopElement(el));
+ }
+ });
+ return oneEvent(el, 'click');
+ }
+
+ let hostEvent;
+ let redispatchedEvent;
+
+ before(async () => {
+ const el = await fixture('');
+ hostEvent = await prepareClickEvent(el, true);
+ redispatchedEvent = await prepareClickEvent(el, false);
+ });
+
+ const sameProperties = [
+ 'constructor',
+ 'composed',
+ 'bubbles',
+ 'cancelable',
+ 'clientX',
+ 'clientY',
+ ];
+
+ sameProperties.forEach(property => {
+ it(`has same value of the property "${property}"`, async () => {
+ expect(redispatchedEvent[property]).to.equal(hostEvent[property]);
+ });
+ });
+ });
+ });
});