Least Power Expressing constraints, relationships and processing instructions in less powerful languages increases the flexibility with which information can be reused: the less powerful the language, the more you can do with the data stored in that language.”
'Example'); await fillIn('textarea[name="body"]', 'This is my issue…'); await fillIn('select[name="assignees"]', 'Alice'); await fillIn('select[name="labels"]', 'Feature'); await fillIn('select[name="project"]', 'Some Project'); await fillIn('select[name="milestone"]', 'v1'); await click('button[type="submit"]'); assert.dom('h1').hasText('Example'); }); Access via accessibility A less powerful language Say more
label.control) { return label.control; } let control = findControl(text); if (control) { return control; } if (label && !label.control) { throw new Error(`Found the label "${label.innerText}" but no associated form control`); } throw new Error(`Could not find a form control labelled "${text}"`); }
selectors = []; for (let tag of ['input', 'textarea', 'select']) { for (let attr of ['title', 'aria-label', 'placeholder']) { selectors.push(`${tag}[${attr}="${text}"]`); } } return find(selectors.join(',')); }
new Error(`The user would have to tab backwards to reach the button containing "${text}"`); } return click(element); } import { calculateTabsTo } from './tabbability'; export default function clickByLabel(text) { let element = findElement(text); if (!element) { throw new Error(`Could not find a button containing "${text}"`); }
new Error(`The user would have to tab backwards to reach the button containing "${text}"`); } return click(element); } import { calculateTabsTo } from './tabbability'; export default function clickByLabel(text) { let element = findElement(text); if (!element) { throw new Error(`Could not find a button containing "${text}"`); }
let { activeElement } = document; // TODO: Make this less naive let tabbables = findAll('*').filter(e => e.tabIndex >= 0); let activeIndex = tabbables.indexOf(activeElement); let targetIndex = tabbables.indexOf(targetElement); if (targetIndex === -1) { throw new Error('The target element is not tabbable, \ try setting tabindex'); } return targetIndex - activeIndex; }
'./find-button'; import { calculateTabsTo } from './tabbability'; const KEY_RETURN = 13; export default async function keyboardClick(text) { let element = findButton(text); if (!element) { throw new Error(`Could not find a button containing "${text}"`); } let tabs = calculateTabsTo(element); if (tabs < 0) { throw new Error(`The user would have to tab backwards to reach the button containing "${text}"`); } await focus(element); await triggerKeyEvent(element, 'keydown', KEY_RETURN); await triggerKeyEvent(element, 'keypress', KEY_RETURN); await triggerKeyEvent(element, 'keyup', KEY_RETURN); }
during "filing an issue": The application made 3 requests after clicking "Submit" ==> POST /issues with { "data": { ... } } ==> GET /issues/1/labels ==> GET /issues/1?include=labels
(!element) { throw new Error(`Could not find a button containing "${text}"`); } let tabs = calculateTabsTo(element); if (tabs < 0) { throw new Error(`The user would have to tab backwards to reach the button containing "${text}"`); } return click(element); }
during "filing an issue": The application made 3 requests after clicking "Submit" ==> POST /issues with { "data": { ... } } ==> GET /issues/1/labels ==> GET /issues/1?include=labels
'Example'); await fillIn('textarea[name="body"]', 'This is my issue…'); await fillIn('select[name="assignees"]', 'Alice'); await fillIn('select[name="labels"]', 'Feature'); await fillIn('select[name="project"]', 'Some Project'); await fillIn('select[name="milestone"]', 'v1'); await click('button[type="submit"]'); assert.dom('h1').hasText('Example'); }); Access via accessibility A less powerful language Say more