Skip to content

Commit 81e6e8c

Browse files
committed
WIP - targetsize unit test.
1 parent 40f09b6 commit 81e6e8c

5 files changed

Lines changed: 205 additions & 23 deletions

File tree

css/showcode.css

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

css/sortable-tables.css

Lines changed: 8 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js/test/targetSize.test.js

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
'use strict';
2+
3+
import config from './test-config.js';
4+
import testHelpers from './test-helpers.js';
5+
6+
const fileList = ['sortable-table.php']; // testHelpers.getPageList();
7+
let mobileBrowser,
8+
desktopBrowser;
9+
10+
describe('Test that all focusable elements have target area greater than 24 x 24 pixels', () => {
11+
beforeAll(async () => { // Put code here that should execute before starting tests.
12+
desktopBrowser = await testHelpers.getDesktopBrowser();
13+
mobileBrowser = await testHelpers.getMobileBrowser();
14+
});
15+
16+
afterAll(async () => {
17+
await mobileBrowser.close();
18+
await desktopBrowser.close();
19+
});
20+
21+
function truncString(s) {
22+
23+
const maxLength = 60;
24+
let r;
25+
if (s.length > maxLength) {
26+
r = s.substring(0, maxLength) + '...';
27+
} else {
28+
r = s;
29+
}
30+
31+
return r;
32+
}
33+
34+
async function testTargets(filename, isDesktop) {
35+
//console.log(`testing ${filename}, Is desktop: ${isDesktop}`);
36+
let domInfo,
37+
page;
38+
39+
if (isDesktop) {
40+
page = await desktopBrowser.newPage();
41+
} else {
42+
page = await mobileBrowser.newPage();
43+
}
44+
45+
// Wait until the DOM is fully loaded.
46+
await page.goto(`${
47+
config.BASE_URL
48+
}/${filename}`, {waitUntil: 'domcontentloaded'});
49+
50+
// Let's loop through all the tabstops on the page.
51+
do { // Let's simulate a tab press
52+
await page.keyboard.press('Tab');
53+
54+
// Now let's see if there is a focus ring around the
55+
// focused element.
56+
domInfo = await page.evaluate(() => {
57+
function getTargetBoxImplicit(el) {
58+
if (!(el instanceof Element))
59+
return null;
60+
61+
62+
const isVisible = (node) => {
63+
const cs = getComputedStyle(node);
64+
if (cs.display === 'none' || cs.visibility === 'hidden' || cs.pointerEvents === 'none')
65+
return false;
66+
67+
const r = node.getBoundingClientRect();
68+
return r.width > 0 && r.height > 0;
69+
};
70+
71+
const rects = [];
72+
if (isVisible(el))
73+
rects.push(el.getBoundingClientRect());
74+
75+
76+
// Only implicit label: <label> ... <input> ... </label>
77+
const wrapLabel = el.closest('label');
78+
if (wrapLabel && isVisible(wrapLabel))
79+
rects.push(wrapLabel.getBoundingClientRect());
80+
81+
82+
if (! rects.length)
83+
return null;
84+
85+
86+
let left = rects[0].left,
87+
top = rects[0].top;
88+
let right = rects[0].right,
89+
bottom = rects[0].bottom;
90+
for (let i = 1; i < rects.length; i++) {
91+
const r = rects[i];
92+
left = Math.min(left, r.left);
93+
top = Math.min(top, r.top);
94+
right = Math.max(right, r.right);
95+
bottom = Math.max(bottom, r.bottom);
96+
}
97+
98+
const width = Math.max(0, right - left);
99+
const height = Math.max(0, bottom - top);
100+
return {
101+
left,
102+
top,
103+
right,
104+
bottom,
105+
width,
106+
height,
107+
x: left,
108+
y: top
109+
};
110+
}
111+
112+
/** Convenience: just the size
113+
function getTargetSizeImplicit(el) {
114+
const box = getTargetBoxImplicit(el);
115+
return box ? {
116+
width: Math.round(box.width),
117+
height: Math.round(box.height)
118+
} : {
119+
width: 0,
120+
height: 0
121+
};
122+
}*/
123+
124+
125+
const {activeElement} = document;
126+
const display = document.defaultView.getComputedStyle(activeElement, null).display;
127+
const {width, height} = getTargetBoxImplicit(activeElement);
128+
const r = {
129+
offsetWidth: width,
130+
offsetHeight: height,
131+
display,
132+
isInline: display === 'inline',
133+
html: activeElement.outerHTML,
134+
isBody: activeElement === document.body
135+
}
136+
137+
return r;
138+
});
139+
if (! domInfo.isInline) {
140+
141+
if (domInfo.offsetWidth < 24) {
142+
console.log(`Bad target width ${
143+
domInfo.offsetWidth
144+
} for:\n\n ${
145+
truncString(domInfo.html)
146+
}\n\n Display is ${
147+
domInfo.display
148+
}`);
149+
}
150+
151+
if (domInfo.offsetHeight < 24) {
152+
console.log(`Bad target height ${
153+
domInfo.offsetHeight
154+
} for:\n\n ${
155+
truncString(domInfo.html)
156+
}\n\n Display is ${
157+
domInfo.display
158+
}`);
159+
}
160+
161+
expect(domInfo.offsetWidth).toBeGreaterThan(24);
162+
expect(domInfo.offsetHeight).toBeGreaterThan(24);
163+
}
164+
165+
} while (! domInfo.isBody);
166+
167+
page.close();
168+
}
169+
// end testFocusStates()
170+
171+
// This goes through all the URLs in the site and
172+
// runs testFocusStates() on it twice, one in the desktop
173+
// browser and one in the mobile.
174+
for (let i = 0; i < fileList.length; i++) {
175+
const file = fileList[i];
176+
it(`Desktop Breakpoint: Test focus states on ${file}`, async () => {
177+
await testTargets(file, true);
178+
});
179+
it(`Mobile Breakpoint: Test focus states on ${file}`, async () => {
180+
await testTargets(file, false);
181+
});
182+
}
183+
});

less/showcode.less

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,12 @@ code {
245245
display: block;
246246
width: calc(100% - 20px);
247247
margin: 0 auto;
248+
min-height: 30px;
248249

249250
@media @tablet-up {
250251
width: calc(100% - 10rem - 10px);
251252
float: right;
252-
margin: 3px 10px 0 0;
253+
margin: 0px 10px 0 0;
253254
}
254255
}
255256
}

less/sortable-tables.less

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
th {
1818
position: relative;
1919
text-align: center;
20+
padding: 0;
21+
22+
&:focus-within {
23+
z-index: 1;
24+
}
2025
}
2126

2227
th:last-child {
@@ -26,8 +31,12 @@
2631
display: inline-block;
2732
height: 100%;
2833
cursor: pointer;
29-
padding: 0 0 0 (25 / @px);
3034
text-align: left;
35+
36+
padding: 12px;
37+
width: 100%;
38+
height: 100%;
39+
text-align: center;
3140
}
3241
th .sortableColumnLabel:hover {
3342
outline: 1px dashed #767676;
@@ -45,16 +54,8 @@
4554
}
4655
}
4756

48-
th button {
49-
margin: -25px 0;
50-
padding: 25px 0;
51-
}
5257

53-
th button:hover {
54-
margin: 0;
55-
}
5658
th button:focus {
57-
margin: 0;
5859
z-index: 1;
5960
}
6061
th button:active {
@@ -100,7 +101,6 @@
100101
}
101102
td,
102103
th {
103-
padding: 12px 11px 12px 0;
104104
text-align: center;
105105
vertical-align: middle;
106106
}

0 commit comments

Comments
 (0)