diff --git a/packages/button/src/LionButton.js b/packages/button/src/LionButton.js index ef76bf78a..2795ec766 100644 --- a/packages/button/src/LionButton.js +++ b/packages/button/src/LionButton.js @@ -137,7 +137,7 @@ export class LionButton extends DisabledWithTabIndexMixin(SlotMixin(LitElement)) if (!this.constructor._button) { this.constructor._button = document.createElement('button'); this.constructor._button.setAttribute('tabindex', '-1'); - this.constructor._button.setAttribute('aria-hidden', true); + this.constructor._button.setAttribute('aria-hidden', 'true'); } return this.constructor._button.cloneNode(); }, diff --git a/packages/button/test/lion-button.test.js b/packages/button/test/lion-button.test.js index e75bd35fb..3010579b1 100644 --- a/packages/button/test/lion-button.test.js +++ b/packages/button/test/lion-button.test.js @@ -228,6 +228,16 @@ describe('lion-button', () => { expect(el._nativeButtonNode.getAttribute('aria-hidden')).to.equal('true'); }); + + it('is accessible', async () => { + const el = await fixture(`foo`); + await expect(el).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const el = await fixture(`foo`); + await expect(el).to.be.accessible(); + }); }); describe('form integration', () => { diff --git a/packages/calendar/test/lion-calendar.test.js b/packages/calendar/test/lion-calendar.test.js index dfd711107..0e5018c69 100644 --- a/packages/calendar/test/lion-calendar.test.js +++ b/packages/calendar/test/lion-calendar.test.js @@ -1193,4 +1193,37 @@ describe('', () => { */ }); }); + + describe('Accessibility', () => { + it('is accessible', async () => { + const el = await fixture( + html` + + `, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible with a date selected', async () => { + const today = new Date(); + const selectedDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1); + const el = await fixture( + html` + + `, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible with disabled dates', async () => { + const el = await fixture( + html` + day.getDay() === 6 || day.getDay() === 0} + > + `, + ); + await expect(el).to.be.accessible(); + }); + }); }); diff --git a/packages/checkbox-group/test/lion-checkbox-group.test.js b/packages/checkbox-group/test/lion-checkbox-group.test.js index b1ba75abe..6e9f50cd1 100644 --- a/packages/checkbox-group/test/lion-checkbox-group.test.js +++ b/packages/checkbox-group/test/lion-checkbox-group.test.js @@ -25,4 +25,78 @@ describe('', () => { el.formElements['sports[]'][0].checked = true; expect(el.hasFeedbackFor).to.deep.equal([]); }); + + it('is accessible', async () => { + const el = await fixture(html` + + + + + + `); + await expect(el).to.be.accessible(); + }); + + it('is accessible when pre-selected', async () => { + const el = await fixture(html` + + + + + + `); + await expect(el).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const el = await fixture(html` + + + + + + `); + await expect(el).to.be.accessible(); + }); }); diff --git a/packages/icon/test/lion-icon.test.js b/packages/icon/test/lion-icon.test.js index ffb51c680..00b09ae32 100644 --- a/packages/icon/test/lion-icon.test.js +++ b/packages/icon/test/lion-icon.test.js @@ -71,6 +71,24 @@ describe('lion-icon', () => { expect(el.hasAttribute('aria-label')).to.equal(false); }); + it('is accessible with an aria label', async () => { + const el = await fixture( + html` + + `, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible without an aria label', async () => { + const el = await fixture( + html` + + `, + ); + await expect(el).to.be.accessible(); + }); + it('expects svg-icons to have the attribute `focusable="false"` so the icon doesn\'t appear in tab-order in IE/Edge', async () => { const icon = await fixture( html` diff --git a/packages/input-amount/test/lion-input-amount.test.js b/packages/input-amount/test/lion-input-amount.test.js index 03ea82489..ca7484c3c 100644 --- a/packages/input-amount/test/lion-input-amount.test.js +++ b/packages/input-amount/test/lion-input-amount.test.js @@ -118,4 +118,25 @@ describe('', () => { expect(el._currencyDisplayNode.getAttribute('aria-label')).to.equal('Philippine pisos'); }); }); + + it('is accessible', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible when readonly', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); }); diff --git a/packages/input-date/test/lion-input-date.test.js b/packages/input-date/test/lion-input-date.test.js index 2950239ae..1b511bc9d 100644 --- a/packages/input-date/test/lion-input-date.test.js +++ b/packages/input-date/test/lion-input-date.test.js @@ -96,4 +96,27 @@ describe('', () => { await el.updateComplete; expect(el.formattedValue).to.equal('15/06/2017'); // should stay british }); + + it('is accessible', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible when readonly', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); }); diff --git a/packages/input-datepicker/test/lion-input-datepicker.test.js b/packages/input-datepicker/test/lion-input-datepicker.test.js index 81fc20e05..070a368a7 100644 --- a/packages/input-datepicker/test/lion-input-datepicker.test.js +++ b/packages/input-datepicker/test/lion-input-datepicker.test.js @@ -301,6 +301,50 @@ describe('', () => { await elObj.closeCalendar(); expect(elObj.invokerEl.getAttribute('aria-expanded')).to.equal('false'); }); + + it('is accessible when closed', async () => { + const el = await fixture(html` + + `); + const elObj = new DatepickerInputObject(el); + + await expect(elObj.invokerEl).to.be.accessible(); + await expect(elObj.calendarEl).to.be.accessible(); + }); + + it('is accessible when open', async () => { + const el = await fixture(html` + + `); + const elObj = new DatepickerInputObject(el); + await elObj.openCalendar(); + + await expect(elObj.calendarEl).to.be.accessible(); + elObj.overlayCloseButtonEl.click(); + }); + + it('has accessible invoker when open', async () => { + const el = await fixture(html` + + `); + const elObj = new DatepickerInputObject(el); + await elObj.openCalendar(); + + await expect(elObj.invokerEl).to.be.accessible(); + elObj.overlayCloseButtonEl.click(); + }); + + it('is accessible with a disabled date', async () => { + const no15th = d => d.getDate() !== 15; + const el = await fixture(html` + + `); + const elObj = new DatepickerInputObject(el); + await elObj.openCalendar(); + + await expect(elObj.calendarEl).to.be.accessible(); + elObj.overlayCloseButtonEl.click(); + }); }); describe.skip('Subclassers', () => { diff --git a/packages/input-email/test/lion-input-email.test.js b/packages/input-email/test/lion-input-email.test.js index 0a9d37b59..2b9bdd845 100644 --- a/packages/input-email/test/lion-input-email.test.js +++ b/packages/input-email/test/lion-input-email.test.js @@ -15,4 +15,25 @@ describe('', () => { expect(el.hasFeedbackFor).to.deep.equal(['error']); expect(el.validationStates.error.IsEmail).to.be.true; }); + + it('is accessible', async () => { + const lionInputEmail = await fixture( + ``, + ); + await expect(lionInputEmail).to.be.accessible(); + }); + + it('is accessible when readonly', async () => { + const lionInputEmail = await fixture( + ``, + ); + await expect(lionInputEmail).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const lionInputEmail = await fixture( + ``, + ); + await expect(lionInputEmail).to.be.accessible(); + }); }); diff --git a/packages/input-iban/test/lion-input-iban.test.js b/packages/input-iban/test/lion-input-iban.test.js index 63a2ea492..6268d08e2 100644 --- a/packages/input-iban/test/lion-input-iban.test.js +++ b/packages/input-iban/test/lion-input-iban.test.js @@ -53,4 +53,25 @@ describe('', () => { expect(el.validationStates.error).to.have.a.property('IsIBAN'); expect(el.validationStates.error).to.have.a.property('IsCountryIBAN'); }); + + it('is accessible', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible when readonly', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); }); diff --git a/packages/input/test/lion-input.test.js b/packages/input/test/lion-input.test.js index 9a1f74836..faa0d247f 100644 --- a/packages/input/test/lion-input.test.js +++ b/packages/input/test/lion-input.test.js @@ -41,4 +41,21 @@ describe('', () => { expect(el.getAttribute('placeholder')).to.equal('foo'); expect(el._inputNode.getAttribute('placeholder')).to.equal('foo'); }); + + it('is accessible', async () => { + const el = await fixture(``); + await expect(el).to.be.accessible(); + }); + + it('is accessible when readonly', async () => { + const el = await fixture( + ``, + ); + await expect(el).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const el = await fixture(``); + await expect(el).to.be.accessible(); + }); }); diff --git a/packages/overlays/src/OverlayController.js b/packages/overlays/src/OverlayController.js index 1ba08b842..44059d55a 100644 --- a/packages/overlays/src/OverlayController.js +++ b/packages/overlays/src/OverlayController.js @@ -221,7 +221,7 @@ export class OverlayController { if (this.invokerNode) { this.invokerNode.setAttribute('aria-expanded', this.isShown); } - if (!this.contentNode.hasAttribute('role')) { + if (!this.contentNode.role) { this.contentNode.setAttribute('role', 'dialog'); } } diff --git a/packages/radio-group/test/lion-radio-group.test.js b/packages/radio-group/test/lion-radio-group.test.js index e979edac3..da6d6392d 100644 --- a/packages/radio-group/test/lion-radio-group.test.js +++ b/packages/radio-group/test/lion-radio-group.test.js @@ -265,4 +265,52 @@ describe('', () => { el.children[1].checked = true; expect(el.touched, `focused via a mouse click, group should be touched`).to.be.true; }); + + it('is accessible', async () => { + const el = await fixture(html` + + + + + + + + + + `); + await nextFrame(); + await expect(el).to.be.accessible(); + }); + + it('is accessible when the group is disabled', async () => { + const el = await fixture(html` + + + + + + + + + + `); + await nextFrame(); + await expect(el).to.be.accessible(); + }); + + it('is accessible when an option is disabled', async () => { + const el = await fixture(html` + + + + + + + + + + `); + await nextFrame(); + await expect(el).to.be.accessible(); + }); }); diff --git a/packages/select-rich/test/lion-select-rich.test.js b/packages/select-rich/test/lion-select-rich.test.js index 9485beb16..f680c3e68 100644 --- a/packages/select-rich/test/lion-select-rich.test.js +++ b/packages/select-rich/test/lion-select-rich.test.js @@ -400,6 +400,34 @@ describe('lion-select-rich', () => { expect(el._invokerNode.getAttribute('aria-expanded')).to.equal('true'); }); + + it('is accessible when closed', async () => { + const el = await fixture(html` + + + Item 1 + Item 2 + + + `); + await expect(el).to.be.accessible(); + }); + + it('is accessible when opened', async () => { + const el = await fixture(html` + + + Item 1 + Item 2 + + + `); + el.opened = true; + await el.updateComplete; + await el.updateComplete; // need 2 awaits as overlay.show is an async function + + await expect(el).to.be.accessible(); + }); }); describe('Use cases', () => { diff --git a/packages/select/test/lion-select.test.js b/packages/select/test/lion-select.test.js index aa6379e08..7048fcae9 100644 --- a/packages/select/test/lion-select.test.js +++ b/packages/select/test/lion-select.test.js @@ -15,4 +15,17 @@ describe('lion-select', () => { `); expect(lionSelect.querySelector('select').value).to.equal('nr2'); }); + + it('is accessible', async () => { + const lionSelect = await fixture(html` + + + + + `); + await expect(lionSelect).to.be.accessible(); + }); }); diff --git a/packages/textarea/test/lion-textarea.test.js b/packages/textarea/test/lion-textarea.test.js index 72e244c46..71370f8a2 100644 --- a/packages/textarea/test/lion-textarea.test.js +++ b/packages/textarea/test/lion-textarea.test.js @@ -139,4 +139,14 @@ describe('', () => { .to.be.below(el.clientHeight) .and.to.be.below(el.scrollHeight); }); + + it('is accessible', async () => { + const el = await fixture(``); + await expect(el).to.be.accessible(); + }); + + it('is accessible when disabled', async () => { + const el = await fixture(``); + await expect(el).to.be.accessible(); + }); }); diff --git a/packages/tooltip/test/lion-tooltip.test.js b/packages/tooltip/test/lion-tooltip.test.js index 5d61bd42f..4bb69e256 100644 --- a/packages/tooltip/test/lion-tooltip.test.js +++ b/packages/tooltip/test/lion-tooltip.test.js @@ -117,5 +117,30 @@ describe('lion-tooltip', () => { const content = el.querySelector('[slot=content]'); expect(content.getAttribute('role')).to.be.equal('tooltip'); }); + + it('should be accessible when closed', async () => { + const el = await fixture(html` + +
Hey there
+ Tooltip button +
+ `); + await expect(el).to.be.accessible; + }); + + it('should be accessible when opened', async () => { + const el = await fixture(html` + +
Hey there
+ Tooltip button +
+ `); + const invoker = el.querySelector('[slot="invoker"]'); + const eventFocusIn = new Event('focusin'); + invoker.dispatchEvent(eventFocusIn); + await el.updateComplete; + + await expect(el).to.be.accessible; + }); }); });