Skip to content

Commit

Permalink
Merge pull request #182 from springload/chore/context-refactor
Browse files Browse the repository at this point in the history
Retrofit "Legacy Context API"
  • Loading branch information
ryami333 committed Feb 10, 2019
2 parents 1e68a76 + 02748ff commit 5f29a1e
Show file tree
Hide file tree
Showing 29 changed files with 1,173 additions and 1,611 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -81,7 +81,7 @@ jobs:
- checkout
- attach_workspace:
at: ~/repo
- run: yarn test:integration
- run: yarn test:integration --ci

workflows:
version: 2
Expand Down
12 changes: 0 additions & 12 deletions integration/__snapshots__/wai-aria.spec.js.snap
Expand Up @@ -7,26 +7,14 @@ Object {
"name": "Heading One",
"role": "button",
},
Object {
"name": "Sunt in reprehenderit cillum ex proident qui culpa fugiat pariatur aliqua nostrud consequat consequat enim quis sit consectetur ad aute ea ex eiusmod id esse culpa et pariatur ad amet pariatur pariatur dolor quis.",
"role": "text",
},
Object {
"name": "Heading Two",
"role": "button",
},
Object {
"name": "Velit tempor dolore commodo voluptate id do nulla do ut proident cillum ad cillum voluptate deserunt fugiat ut sed cupidatat ut consectetur consequat incididunt sed in culpa do labore ea incididunt ea in eiusmod.",
"role": "text",
},
Object {
"name": "Heading Three",
"role": "button",
},
Object {
"name": "Lorem ipsum esse occaecat voluptate duis incididunt amet eiusmod sunt commodo sunt enim anim ea culpa ut tempor dolore fugiat exercitation aliquip commodo dolore elit esse est ullamco velit et deserunt.",
"role": "text",
},
],
"name": "React Accessible Accordion - Integration Test Sandbox",
"role": "WebArea",
Expand Down
4 changes: 1 addition & 3 deletions integration/jest.config.js
@@ -1,7 +1,5 @@
module.exports = {
globalSetup: 'jest-environment-puppeteer/setup',
globalTeardown: 'jest-environment-puppeteer/teardown',
testEnvironment: 'jest-environment-puppeteer',
testEnvironment: 'jest-environment-node',
transform: {
'^.+\\.(js|ts)x?$': 'babel-jest',
},
Expand Down
3 changes: 3 additions & 0 deletions integration/src/index.tsx
Expand Up @@ -7,6 +7,9 @@ import {
AccordionItemPanel,
} from '../../src';

// tslint:disable-next-line no-import-side-effect
import '../../src/css/minimal-example.css';

ReactDOM.render(
<div id="classic-accordion">
<Accordion>
Expand Down
138 changes: 101 additions & 37 deletions integration/wai-aria.spec.js
@@ -1,46 +1,75 @@
import path from 'path';
import puppeteer from 'puppeteer';

describe('WAI ARIA Spec', () => {
function evaluateHeadings() {
return page.$$('#classic-accordion .accordion__heading');
}
function evaluateItems() {
return page.$$('#classic-accordion .accordion__item');
}
async function setup() {
const browser = await puppeteer.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
],
});

beforeEach(async () => {
await page.goto(`file:${path.resolve(__dirname, 'dist/index.html')}`);
});
const page = await browser.newPage();

await page.goto(`file://${path.resolve(__dirname, 'dist/index.html')}`);

// Seems like the browser is a bit slower on CI, and we're trying to
// select headings before they're registered in the 'store'.
await page.waitForSelector('.accordion__heading');

const headingsHandles = await page.$$(
'#classic-accordion .accordion__heading',
);
const itemsHandles = await page.$$(
'#classic-accordion .accordion__item',
);

return { browser, page, headingsHandles, itemsHandles };
}

describe('Canary tests', () => {
it('Loads the Cypress Testing Sandbox', async () => {
const { browser, page } = await setup();
const title = await page.evaluate(() => document.title);
expect(title).toBe(
'React Accessible Accordion - Integration Test Sandbox',
);

await browser.close();
});
it('has rendered the "classic accordion" example', async () => {
const { browser, page } = await setup();
const qtyClassicAccordion = await page.evaluate(
() => document.querySelectorAll('#classic-accordion').length,
);
expect(qtyClassicAccordion).toEqual(1);

await browser.close();
});
});

describe('Chrome Accessibility Tree', () => {
it('matches snapshots', async () => {
const { browser, page } = await setup();
expect(await page.accessibility.snapshot()).toMatchSnapshot();

await browser.close();
});
});

describe('Keyboard Interaction', () => {
describe('Enter or Space', () => {
it('When focus is on the accordion header for a collapsed panel, expands the associated panel. If the implementation allows only one panel to be expanded, and if another panel is expanded, collapses that panel.', async () => {
const headingHandles = await evaluateHeadings();
expect(headingHandles.length).toEqual(3);
const { browser, page, headingsHandles } = await setup();
expect(headingsHandles.length).toEqual(3);

const firstHeadingHandle = headingHandles[0];
const secondHeadingHandle = headingHandles[1];
const firstHeadingHandle = headingsHandles[0];
const secondHeadingHandle = headingsHandles[1];

function evaluateIsExpanded(headingHandle) {
return page
Expand Down Expand Up @@ -70,35 +99,42 @@ describe('WAI ARIA Spec', () => {
expect(await evaluateIsExpanded(secondHeadingHandle)).toEqual(
true,
);

await browser.close();
});

it('When focus is on the accordion header for an expanded panel, collapses the panel if the implementation supports collapsing. Some implementations require one panel to be expanded at all times and allow only one panel to be expanded; so, they do not support a collapse function.', () => {
xit('When focus is on the accordion header for an expanded panel, collapses the panel if the implementation supports collapsing. Some implementations require one panel to be expanded at all times and allow only one panel to be expanded; so, they do not support a collapse function.', () => {
// todo
});
});

describe('Tab', () => {
it('Moves focus to the next focusable element; all focusable elements in the accordion are included in the page Tab sequence.', async () => {
const { browser, page, headingsHandles } = await setup();

const [
firstHeadingHandle,
secondHeadingHandle,
] = await evaluateHeadings();
] = headingsHandles;
await firstHeadingHandle.focus();
await page.keyboard.press('Tab');
const secondIsFocussed = await page.evaluate(
heading => document.activeElement === heading,
secondHeadingHandle,
);
expect(secondIsFocussed).toEqual(true);

await browser.close();
});
});

describe('Shift + Tab', () => {
it('Moves focus to the previous focusable element; all focusable elements in the accordion are included in the page Tab sequence.', async () => {
const { browser, page, headingsHandles } = await setup();
const [
firstHeadingHandle,
secondHeadingHandle,
] = await evaluateHeadings();
] = headingsHandles;
await secondHeadingHandle.focus();
await page.keyboard.down('Shift');
await page.keyboard.press('Tab');
Expand All @@ -108,22 +144,27 @@ describe('WAI ARIA Spec', () => {
firstHeadingHandle,
);
expect(firstIsFocussed).toEqual(true);

await browser.close();
});
});

describe('Down Arrow (Optional)', () => {
it('If focus is on an accordion header, moves focus to the next accordion header.', async () => {
const { browser, page, headingsHandles } = await setup();
const [
firstHeadingHandle,
secondHeadingHandle,
] = await evaluateHeadings();
] = headingsHandles;
await firstHeadingHandle.focus();
await page.keyboard.press('ArrowDown');
const secondIsFocussed = await page.evaluate(
heading => document.activeElement === heading,
secondHeadingHandle,
);
expect(secondIsFocussed).toEqual(true);

await browser.close();
});

xit('If focus is on the last accordion header, either does nothing or moves focus to the first accordion header.', () => {
Expand All @@ -133,17 +174,20 @@ describe('WAI ARIA Spec', () => {

describe('Up Arrow (Optional)', () => {
it('If focus is on an accordion header, moves focus to the previous accordion header.', async () => {
const { browser, page, headingsHandles } = await setup();
const [
firstHeadingHandle,
secondHeadingHandle,
] = await evaluateHeadings();
] = headingsHandles;
await secondHeadingHandle.focus();
await page.keyboard.press('ArrowUp');
const firstIsFocussed = await page.evaluate(
heading => document.activeElement === heading,
firstHeadingHandle,
);
expect(firstIsFocussed).toEqual(true);

await browser.close();
});

xit('If focus is on the first accordion header, either does nothing or moves focus to the last accordion header.', () => {
Expand All @@ -153,69 +197,78 @@ describe('WAI ARIA Spec', () => {

describe('Home (Optional)', () => {
it('When focus is on an accordion header, moves focus to the first accordion header.', async () => {
const { browser, page, headingsHandles } = await setup();
const [
firstHeadingHandle,
secondHeadingHandle,
thirdHeadingHandle,
] = await evaluateHeadings();
] = headingsHandles;
await thirdHeadingHandle.focus();
await page.keyboard.press('Home');
const firstIsFocussed = await page.evaluate(
heading => document.activeElement === heading,
firstHeadingHandle,
);
expect(firstIsFocussed).toEqual(true);

await browser.close();
});
});

describe('End (Optional)', () => {
it('When focus is on an accordion header, moves focus to the last accordion header.', async () => {
const { browser, page, headingsHandles } = await setup();
const [
firstHeadingHandle,
secondHeadingHandle,
thirdHeadingHandle,
] = await evaluateHeadings();
] = headingsHandles;
await firstHeadingHandle.focus();
await page.keyboard.press('End');
const thirdIsFocussed = await page.evaluate(
heading => document.activeElement === heading,
thirdHeadingHandle,
);
expect(thirdIsFocussed).toEqual(true);

await browser.close();
});
});
});

describe('WAI-ARIA Roles, States, and Properties', () => {
it('The title of each accordion header is contained in an element with role button.', async () => {
const headingHandles = await evaluateHeadings();
expect(headingHandles).toHaveLength(3);
for (const headingHandle of headingHandles) {
const { browser, page, headingsHandles } = await setup();
expect(headingsHandles).toHaveLength(3);
for (const headingHandle of headingsHandles) {
expect(
await page.evaluate(
heading => heading.getAttribute('role'),
headingHandle,
),
).toBe('button');
}

await browser.close();
});

// Not yet supported.
xit('Each accordion header button is wrapped in an element with role heading that has a value set for aria-level that is appropriate for the information architecture of the page.', () => {});
xit('Each accordion header button is wrapped in an element with role heading that has a value set for aria-level that is appropriate for the information architecture of the page.', () => {
// Not yet supported.
});

it('If the native host language has an element with an implicit heading and aria-level, such as an HTML heading tag, a native host language element may be used.', () => {
xit('If the native host language has an element with an implicit heading and aria-level, such as an HTML heading tag, a native host language element may be used.', () => {
// todo
});

it('The button element is the only element inside the heading element. That is, if there are other visually persistent elements, they are not included inside the heading element.', () => {
xit('The button element is the only element inside the heading element. That is, if there are other visually persistent elements, they are not included inside the heading element.', () => {
// todo
});

it('If the accordion panel associated with an accordion header is visible, the header button element has aria-expanded set to true. If the panel is not visible, aria-expanded is set to false.', async () => {
const headings = await evaluateHeadings();
expect(headings.length).toEqual(3);
const { browser, page, headingsHandles } = await setup();
expect(headingsHandles.length).toEqual(3);

for (const handle of headings) {
for (const handle of headingsHandles) {
// Before expanding
expect(
await page.evaluate(
Expand All @@ -235,13 +288,15 @@ describe('WAI ARIA Spec', () => {
),
).toEqual('true');
}

await browser.close();
});

it('The accordion header button element has aria-controls set to the ID of the element containing the accordion panel content.', async () => {
const itemHandles = await evaluateItems();
expect(itemHandles.length).toEqual(3);
const { browser, page, itemsHandles } = await setup();
expect(itemsHandles.length).toEqual(3);

for (const itemHandle of itemHandles) {
for (const itemHandle of itemsHandles) {
const headingHandle = await itemHandle.$('.accordion__heading');
const panelHandle = await itemHandle.$('.accordion__panel');

Expand All @@ -258,10 +313,15 @@ describe('WAI ARIA Spec', () => {
expect(panelId).toBeTruthy();
expect(headingAriaControls).toEqual(panelId);
}

await browser.close();
});

it('If the accordion panel associated with an accordion header is visible, and if the accordion does not permit the panel to be collapsed, the header button element has aria-disabled set to true.', async () => {
const [firstHeadingHandle] = await evaluateHeadings();
const { browser, page, headingsHandles } = await setup();
expect(headingsHandles.length).toEqual(3);

const [firstHeadingHandle] = headingsHandles;
await firstHeadingHandle.click();

const headingAriaDisabled = await page.evaluate(
Expand All @@ -270,13 +330,15 @@ describe('WAI ARIA Spec', () => {
);

expect(headingAriaDisabled).toEqual('true');

await browser.close();
});

it('Optionally, each element that serves as a container for panel content has role region and aria-labelledby with a value that refers to the button that controls display of the panel.', async () => {
const itemHandles = await evaluateItems();
expect(itemHandles.length).toEqual(3);
const { browser, page, itemsHandles } = await setup();
expect(itemsHandles.length).toEqual(3);

for (const itemHandle of itemHandles) {
for (const itemHandle of itemsHandles) {
const headingHandle = await itemHandle.$('.accordion__heading');
const panelHandle = await itemHandle.$('.accordion__panel');

Expand All @@ -299,6 +361,8 @@ describe('WAI ARIA Spec', () => {
expect(panelAriaLabelledBy).toEqual(headingId);
expect(panelRole).toEqual('region');
}

await browser.close();
});
});
});

0 comments on commit 5f29a1e

Please sign in to comment.