diff --git a/src/components/checkbox/checkbox.test.ts b/src/components/checkbox/checkbox.test.ts new file mode 100644 index 000000000..dcc8d0876 --- /dev/null +++ b/src/components/checkbox/checkbox.test.ts @@ -0,0 +1,47 @@ +import { expect, fixture, html, oneEvent } from '@open-wc/testing'; +import { sendKeys } from '@web/test-runner-commands' + +import '../../../dist/shoelace.js'; +import type SlCheckbox from './checkbox'; + +describe('', () => { + it('should be disabled with the disabled attribute', async () => { + const el = await fixture(html` `); + const checkbox = el.shadowRoot?.querySelector('input'); + + expect(checkbox.disabled).to.be.true; + }); + + it('should be valid by default', async () => { + const el = (await fixture(html` `)) + + expect(el.invalid).to.be.false; + }); + + it('should fire sl-change when clicked', async () => { + const el = (await fixture(html` `)) + setTimeout(() => el.shadowRoot?.querySelector('input').click()); + const event = await oneEvent(el, 'sl-change') + expect(event.target).to.equal(el); + expect(el.checked).to.be.true; + }); + + it('should fire sl-change when toggled via keyboard', async () => { + const el = (await fixture(html` `)) + const input = el.shadowRoot?.querySelector('input'); + input.focus(); + setTimeout(() => sendKeys({ press: ' ' })); + const event = await oneEvent(el, 'sl-change') + expect(event.target).to.equal(el); + expect(el.checked).to.be.true; + }); + + it('should not fire sl-change when checked is set by javascript', async () => { + const el = (await fixture(html` `)) + el.addEventListener('sl-change', () => expect.fail('event fired')) + el.checked = true; + await el.updateComplete; + el.checked = false; + await el.updateComplete; + }); +}); diff --git a/src/components/checkbox/checkbox.ts b/src/components/checkbox/checkbox.ts index 70694f6b7..44e5ea711 100644 --- a/src/components/checkbox/checkbox.ts +++ b/src/components/checkbox/checkbox.ts @@ -90,6 +90,7 @@ export default class SlCheckbox extends LitElement { handleClick() { this.checked = !this.checked; this.indeterminate = false; + emit(this, 'sl-change'); } handleBlur() { @@ -121,7 +122,6 @@ export default class SlCheckbox extends LitElement { @watch('indeterminate', { waitUntilFirstUpdate: true }) handleStateChange() { this.invalid = !this.input.checkValidity(); - emit(this, 'sl-change'); } render() { diff --git a/src/components/radio/radio.test.ts b/src/components/radio/radio.test.ts new file mode 100644 index 000000000..dccfe1067 --- /dev/null +++ b/src/components/radio/radio.test.ts @@ -0,0 +1,47 @@ +import { expect, fixture, html, oneEvent } from '@open-wc/testing'; +import { sendKeys } from '@web/test-runner-commands' + +import '../../../dist/shoelace.js'; +import type SlRadio from './radio'; + +describe('', () => { + it('should be disabled with the disabled attribute', async () => { + const el = await fixture(html` `); + const radio = el.shadowRoot?.querySelector('input'); + + expect(radio.disabled).to.be.true; + }); + + it('should be valid by default', async () => { + const el = (await fixture(html` `)) + + expect(el.invalid).to.be.false; + }); + + it('should fire sl-change when clicked', async () => { + const el = (await fixture(html` `)) + setTimeout(() => el.shadowRoot?.querySelector('input').click()); + const event = await oneEvent(el, 'sl-change') + expect(event.target).to.equal(el); + expect(el.checked).to.be.true; + }); + + it('should fire sl-change when toggled via keyboard', async () => { + const el = (await fixture(html` `)) + const input = el.shadowRoot?.querySelector('input'); + input.focus(); + setTimeout(() => sendKeys({ press: ' ' })); + const event = await oneEvent(el, 'sl-change') + expect(event.target).to.equal(el); + expect(el.checked).to.be.true; + }); + + it('should not fire sl-change when checked is set by javascript', async () => { + const el = (await fixture(html` `)) + el.addEventListener('sl-change', () => expect.fail('event fired')) + el.checked = true; + await el.updateComplete; + el.checked = false; + await el.updateComplete; + }); +}); diff --git a/src/components/radio/radio.ts b/src/components/radio/radio.ts index fc3d16ab3..f6b3223fa 100644 --- a/src/components/radio/radio.ts +++ b/src/components/radio/radio.ts @@ -104,11 +104,11 @@ export default class SlRadio extends LitElement { if (this.checked) { this.getSiblingRadios().map(radio => (radio.checked = false)); } - emit(this, 'sl-change'); } handleClick() { this.checked = true; + emit(this, 'sl-change'); } @watch('disabled') diff --git a/src/components/switch/switch.test.ts b/src/components/switch/switch.test.ts new file mode 100644 index 000000000..a097e276b --- /dev/null +++ b/src/components/switch/switch.test.ts @@ -0,0 +1,47 @@ +import { expect, fixture, html, oneEvent } from '@open-wc/testing'; +import { sendKeys } from '@web/test-runner-commands' + +import '../../../dist/shoelace.js'; +import type SlSwitch from './switch'; + +describe('', () => { + it('should be disabled with the disabled attribute', async () => { + const el = await fixture(html` `); + const input = el.shadowRoot?.querySelector('input'); + + expect(input.disabled).to.be.true; + }); + + it('should be valid by default', async () => { + const el = (await fixture(html` `)) + + expect(el.invalid).to.be.false; + }); + + it('should fire sl-change when clicked', async () => { + const el = (await fixture(html` `)) + setTimeout(() => el.shadowRoot?.querySelector('input').click()); + const event = await oneEvent(el, 'sl-change') + expect(event.target).to.equal(el); + expect(el.checked).to.be.true; + }); + + it('should fire sl-change when toggled via keyboard', async () => { + const el = (await fixture(html` `)) + const input = el.shadowRoot?.querySelector('input'); + input.focus(); + setTimeout(() => sendKeys({ press: ' ' })); + const event = await oneEvent(el, 'sl-change') + expect(event.target).to.equal(el); + expect(el.checked).to.be.true; + }); + + it('should not fire sl-change when checked is set by javascript', async () => { + const el = (await fixture(html` `)) + el.addEventListener('sl-change', () => expect.fail('event fired')) + el.checked = true; + await el.updateComplete; + el.checked = false; + await el.updateComplete; + }); +}); diff --git a/src/components/switch/switch.ts b/src/components/switch/switch.ts index 863500412..6ca37c6b5 100644 --- a/src/components/switch/switch.ts +++ b/src/components/switch/switch.ts @@ -97,12 +97,12 @@ export default class SlSwitch extends LitElement { if (this.input) { this.input.checked = this.checked; this.invalid = !this.input.checkValidity(); - emit(this, 'sl-change'); } } handleClick() { this.checked = !this.checked; + emit(this, 'sl-change'); } @watch('disabled') @@ -123,11 +123,13 @@ export default class SlSwitch extends LitElement { if (event.key === 'ArrowLeft') { event.preventDefault(); this.checked = false; + // emit(this, 'sl-change'); } if (event.key === 'ArrowRight') { event.preventDefault(); this.checked = true; + // emit(this, 'sl-change'); } }