Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimpliment accessibility based on WAI-ARIA 1.1 #1023

Merged
merged 1 commit into from
Oct 4, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
330 changes: 330 additions & 0 deletions test/accessibility.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
<!doctype html>

<html>

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../web-component-tester/browser.js"></script>
<script src="../../iron-test-helpers/mock-interactions.js"></script>

<link rel="import" href="helpers.html">
<link rel="import" href="../vaadin-grid.html">
<link rel="import" href="../vaadin-grid-column-group.html">
</head>

<body>
<test-fixture id="default">
<template>
<vaadin-grid>
<vaadin-grid-column>
<template class="header">Index</template>
<template>[[index]]</template>
<template class="footer">Index</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">header</template>
<template>[[item]]</template>
<template class="footer">footer</template>
</vaadin-grid-column>
</vaadin-grid>
</template>
</test-fixture>

<test-fixture id="group">
<template>
<vaadin-grid>
<vaadin-grid-column-group>
<template class="header">Group header</template>
<template class="footer">Group footer</template>
<vaadin-grid-column>
<template class="header">Index</template>
<template>[[index]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">header</template>
<template>[[item]]</template>
</vaadin-grid-column>
</vaadin-grid-column-group>
</vaadin-grid>
</template>
</test-fixture>

<test-fixture id="details">
<template>
<vaadin-grid>
<vaadin-grid-column>
<template class="header">Index</template>
<template>[[index]]</template>
<template class="footer">Index</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">header</template>
<template>[[item]]</template>
<template class="footer">footer</template>
</vaadin-grid-column>
<template class="row-details">details</template>
</vaadin-grid>
</template>
</test-fixture>

<script>
describe('accessibility', () => {
let grid;

function initFixture(fixtureName) {
grid = fixture(fixtureName);
grid.items = ['foo', 'bar'];
flushGrid(grid);
}

function uniqueAttrValues(elements, attr) {
const unique = [], valuesSet = new Set();
Array.from(elements).forEach(el => valuesSet.add(el.getAttribute(attr)));
valuesSet.forEach(v => unique.push(v));
return unique;
}

describe('structural roles', () => {
beforeEach(() => initFixture('default'));

it('should have role grid on table', () => {
expect(grid.$.table.getAttribute('role')).to.equal('grid');
});

it('should have role rowgroup on row groups', () => {
expect(grid.$.header.getAttribute('role')).to.equal('rowgroup');
expect(grid.$.items.getAttribute('role')).to.equal('rowgroup');
expect(grid.$.footer.getAttribute('role')).to.equal('rowgroup');
});

it('should have role row on rows', () => {
expect(grid.$.header.children[0].getAttribute('role')).to.equal('row');
expect(grid.$.items.children[0].getAttribute('role')).to.equal('row');
expect(grid.$.items.children[1].getAttribute('role')).to.equal('row');
expect(grid.$.footer.children[0].getAttribute('role')).to.equal('row');
});

it('should have role columnheader on header cells', () => {
expect(grid.$.header.children[0].children[0].getAttribute('role')).to.equal('columnheader');
expect(grid.$.header.children[0].children[1].getAttribute('role')).to.equal('columnheader');
});

it('should have role gridcell on body cells', () => {
expect(grid.$.items.children[0].children[0].getAttribute('role')).to.equal('gridcell');
expect(grid.$.items.children[0].children[1].getAttribute('role')).to.equal('gridcell');
});
});

describe('size', () => {
beforeEach(() => initFixture('default'));

it('should have aria-rowcount on the table', () => {
// 2 item rows + header row + footer row = 4 in total
expect(grid.$.table.getAttribute('aria-rowcount')).to.equal('4');
});

it('should update aria-rowcount on after size change', () => {
grid.size = 10;

// 10 item rows + header row + footer row = 12 in total
expect(grid.$.table.getAttribute('aria-rowcount')).to.equal('12');
});
});

describe('column count', () => {
beforeEach(() => initFixture('details'));

it('should have aria-colcount on the table', () => {
expect(grid.$.table.getAttribute('aria-colcount')).to.equal('2');
});

it('should update aria-colcount when column is added', done => {
const template = document.createElement('template');
template.innerHTML = '[[item]]';
const column = document.createElement('vaadin-grid-column');
column.appendChild(template);
grid.appendChild(column);

setTimeout(() => {
expect(grid.$.table.getAttribute('aria-colcount')).to.equal('3');
done();
});
});
});

describe('row numbers', () => {
beforeEach(() => initFixture('group'));

function setANumberOfItems(grid, number) {
grid.items = Array.apply(null, new Array(number)).map((v, i) => `item ${i}`);
flushGrid(grid);
}

it('should have aria-rowindex on rows', () => {
Array.from(grid.$.table.querySelectorAll('tr')).forEach((row, index) => {
expect(row.getAttribute('aria-rowindex')).to.equal((index + 1).toString());
});
});

it('should update aria-rowindex on size change', () => {
setANumberOfItems(grid, 100);
expect(
Array.from(grid.$.items.children)
.slice(0, 5) // assuming at least five body rows are visible
.map(row => row.getAttribute('aria-rowindex'))
).to.eql(['3', '4', '5', '6', '7']);
expect(grid.$.footer.children[0].getAttribute('aria-rowindex')).to.equal('103');
});

it('should update aria-rowindex on scroll', () => {
setANumberOfItems(grid, 1000);
// scroll to end
grid._accessIronListAPI(() => grid.scrollToIndex(1000));

const ariaRowindexValues = Array.from(grid.$.items.children)
.map(row => row.getAttribute('aria-rowindex'));
expect(ariaRowindexValues).to.include.members(['1000', '1001', '1002']);
expect(ariaRowindexValues).to.not.include.members(['3', '4', '1003']);
});
});

describe('selection', () => {
beforeEach(() => initFixture('default'));

it('should have aria-multiselectable on table', () => {
expect(grid.$.table.getAttribute('aria-multiselectable')).to.equal('true');
});

it('should have aria-selected defined on body rows', () => {
expect(uniqueAttrValues(
grid.$.items.querySelectorAll('tr'),
'aria-selected'
)).to.eql(['false']);
});

it('should have aria-selected defined on body cells', () => {
expect(uniqueAttrValues(
grid.$.items.querySelectorAll('td'),
'aria-selected'
)).to.eql(['false']);
});

it('should set aria-selected true for selected items', () => {
grid.selectedItems = grid.items.slice(1);

expect(grid.$.items.children[0].getAttribute('aria-selected')).to.equal('false');
expect(uniqueAttrValues(
grid.$.items.children[0].children,
'aria-selected'
)).to.eql(['false']);
expect(grid.$.items.children[1].getAttribute('aria-selected')).to.equal('true');
expect(uniqueAttrValues(
grid.$.items.children[1].children,
'aria-selected'
)).to.eql(['true']);
});

it('should set aria-selected false for deselected items', () => {
grid.selectedItems = grid.items.slice(1);
grid.selectedItems = [];

expect(grid.$.items.children[0].getAttribute('aria-selected')).to.equal('false');
expect(uniqueAttrValues(
grid.$.items.children[0].children,
'aria-selected'
)).to.eql(['false']);
expect(grid.$.items.children[1].getAttribute('aria-selected')).to.equal('false');
expect(uniqueAttrValues(
grid.$.items.children[1].children,
'aria-selected'
)).to.eql(['false']);
});
});

describe('column groups', () => {
beforeEach(() => initFixture('group'));

it('should have aria-colspan on group header cell', () => {
expect(grid.$.header.children[0].children[0].getAttribute('aria-colspan')).to.equal('2');
});
});

describe('row details', () => {
describe('not in use', () => {
beforeEach(() => initFixture('default'));

it('should not have aria-expanded on body cells', () => {
expect(uniqueAttrValues(
grid.$.items.querySelectorAll('td'),
'aria-expanded'
)).to.eql([null]);
});

it('should not have aria-controls on body cells', () => {
expect(uniqueAttrValues(
grid.$.items.querySelectorAll('td'),
'aria-controls'
)).to.eql([null]);
});
});

describe('in use', () => {
beforeEach(() => initFixture('details'));

it('should have aria-expanded false on body cells', () => {
expect(uniqueAttrValues(
grid.$.items.querySelectorAll('td'),
'aria-expanded'
)).to.eql(['false']);
});

it('should have aria-controls referencing detail cell id on body cells', () => {
Array.from(grid.$.items.children).forEach(row => {
const detailsCell = row.querySelector('td[part~="details-cell"]');

expect(detailsCell.id).to.be.ok;
expect(detailsCell.getAttribute('aria-controls')).to.equal(null);
expect(uniqueAttrValues(
row.querySelectorAll('td:not([part~="details-cell"])'),
'aria-controls'
)).to.eql([detailsCell.id]);
});
});

it('should set aria-expended true on cells after row expanded', () => {
grid.expandItem(grid.items[0]);

expect(uniqueAttrValues(
grid.$.items.children[0].children,
'aria-expanded'
)).to.eql(['true']);

expect(uniqueAttrValues(
grid.$.items.children[1].children,
'aria-expanded'
)).to.eql(['false']);
});

it('should set aria-expanded false on cells after row collapsed', () => {
grid.expandItem(grid.items[0]);
grid.collapseItem(grid.items[0]);

expect(uniqueAttrValues(
grid.$.items.children[0].children,
'aria-expanded'
)).to.eql(['false']);

expect(uniqueAttrValues(
grid.$.items.children[1].children,
'aria-expanded'
)).to.eql(['false']);
});
});
});
});
</script>
</body>
</html>
1 change: 1 addition & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<body>
<script>
WCT.loadSuites([
'accessibility.html',
'app-localize-behavior.html',
'array-data-provider.html',
'basic.html',
Expand Down
Loading